From 525aa8c4dc3e23f0369c7edb1fb507ecad5f43bf Mon Sep 17 00:00:00 2001
From: Adrian Kummerländer
Date: Wed, 23 Apr 2014 21:26:58 +0200
Subject: Fixed xerces DOM construction related memory leaks * Wrapped xerces
 DOM and support class instances in now DomDocumentGuard scope-guard class *
 FunctionReadDirectory class contains interal std::stack instance to store
 DomDocumentGuard instances ** wrapped in std::shared_ptr as
 FunctionReadDirectory is internally cloned by xalan... ** this is needed as
 the DOM has to preserved longer than the external function execution scope *
 Sadly XMLCh xerces strings have to be manually released ** added appropriate
 xercesc::XMLString::release calls * xalan::XercesDOMWrapperParsedSource does
 not mirror a given xerces DOM but convert it on instantiation ** this is why
 there is a dedicated finalize member method in InputXSLT::DomDocumentGuard *
 In short: I do not like the amount of trickery needed to simply prevent
 memory leaks in this context ** there sadly doesn't seem to be a
 substantially easier way to return arbitrary DOM trees from a external
 function

---
 src/function/read_directory.cc | 48 +++++++++++-------------------------------
 src/function/read_directory.h  | 10 ++++-----
 2 files changed, 17 insertions(+), 41 deletions(-)

(limited to 'src/function')

diff --git a/src/function/read_directory.cc b/src/function/read_directory.cc
index a4284c0..6d643da 100644
--- a/src/function/read_directory.cc
+++ b/src/function/read_directory.cc
@@ -1,25 +1,16 @@
 #include "read_directory.h"
 
-#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>
-#include <xalanc/XalanTransformer/XercesDOMWrapperParsedSource.hpp>
-
 #include <xercesc/dom/DOMDocument.hpp>
 #include <xercesc/dom/DOMImplementation.hpp>
 #include <xercesc/dom/DOMElement.hpp>
 #include <xercesc/dom/DOMText.hpp>
 #include <xercesc/util/XMLString.hpp>
 
-#include <sstream>
-
 namespace InputXSLT {
 
 FunctionReadDirectory::FunctionReadDirectory(const FilesystemContext& context):
 	fs_context_(context),
-	parser_() { }
-
-FunctionReadDirectory::FunctionReadDirectory(const FunctionReadDirectory& src):
-	fs_context_(src.fs_context_),
-	parser_() { }
+	documents_(new std::stack<DomDocumentGuard>()) { }
 
 xalan::XObjectPtr FunctionReadDirectory::execute(
 	xalan::XPathExecutionContext&                executionContext,
@@ -35,44 +26,29 @@ xalan::XObjectPtr FunctionReadDirectory::execute(
 		this->generalError(executionContext, context, locator);
 	}
 
-	xercesc::DOMDocument* const inputDom(
-		xercesc::DOMImplementation::getImplementation()->createDocument(
-			nullptr, xercesc::XMLString::transcode("content"), nullptr
-		)
-	);
+	this->documents_->emplace("content");
+	DomDocumentGuard& domDocument = this->documents_->top();
 
-	xercesc::DOMNode* const rootNode = inputDom->getDocumentElement();
+	xercesc::DOMNode* const rootNode = domDocument->getDocumentElement();
 
 	this->fs_context_.iterate(
 		arguments[0]->str(),
-		[&inputDom, &rootNode](const boost::filesystem::path& p) {
-		xercesc::DOMNode* const fileNode = inputDom->createElement(
-			xercesc::XMLString::transcode("file")
-		);
+		[&domDocument, &rootNode](const boost::filesystem::path& p) {
+		XMLCh* buffer = xercesc::XMLString::transcode("file");
+		xercesc::DOMNode* const fileNode = domDocument->createElement(buffer);
+		xercesc::XMLString::release(&buffer);
 
-		xercesc::DOMText* const textNode = inputDom->createTextNode(
-			xercesc::XMLString::transcode(p.filename().string().data())
-		);
+		buffer = xercesc::XMLString::transcode(p.filename().string().data());
+		xercesc::DOMText* const textNode = domDocument->createTextNode(buffer);
+		xercesc::XMLString::release(&buffer);
 
 		fileNode->appendChild(textNode);
 		rootNode->appendChild(fileNode);
 	});
 
-
-	xalan::XercesDOMSupport domSupport(this->parser_);
-
-	xalan::XercesDOMWrapperParsedSource* const parsedSource(
-		new xalan::XercesDOMWrapperParsedSource(
-			inputDom,
-			this->parser_,
-			domSupport
-		)
-	);
-
 	return executionContext.getXObjectFactory().createNodeSet(
-		parsedSource->getDocument()
+		domDocument.finalize()
 	);
-
 }
 
 FunctionReadDirectory* FunctionReadDirectory::clone(
diff --git a/src/function/read_directory.h b/src/function/read_directory.h
index e7ee0c4..3c55591 100644
--- a/src/function/read_directory.h
+++ b/src/function/read_directory.h
@@ -6,19 +6,18 @@
 #include <xalanc/XPath/Function.hpp>
 #include <xalanc/XPath/XObject.hpp>
 
-#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>
-
-#include <string>
+#include <memory>
+#include <stack>
 
 #include "common.h"
 #include "support/filesystem_context.h"
+#include "support/dom_document_guard.h"
 
 namespace InputXSLT {
 
 class FunctionReadDirectory : public xalan::Function {
 	public:
 		FunctionReadDirectory(const FilesystemContext&);
-		FunctionReadDirectory(const FunctionReadDirectory&);
 
 		virtual xalan::XObjectPtr execute(
 			xalan::XPathExecutionContext&,
@@ -34,7 +33,8 @@ class FunctionReadDirectory : public xalan::Function {
 
 	private:
 		const FilesystemContext& fs_context_;
-		mutable xalan::XercesParserLiaison parser_;
+
+		std::shared_ptr<std::stack<DomDocumentGuard>> documents_;
 
 		const xalan::XalanDOMString& getError(xalan::XalanDOMString&) const;
 
-- 
cgit v1.2.3