aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerländer2014-04-26 11:21:10 +0200
committerAdrian Kummerländer2014-04-26 11:21:10 +0200
commit0b611b7bd28851fe8096b3d2c121c68e231ada11 (patch)
tree80352794dce96cec2b86659e5a8260fb9a7686c2
parent938ed7622656c3494ae8fdb83bc2ad4b1f31d901 (diff)
downloadInputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar
InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.gz
InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.bz2
InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.lz
InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.xz
InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.tar.zst
InputXSLT-0b611b7bd28851fe8096b3d2c121c68e231ada11.zip
Implemented global DOM document cache
* the plan to return XML-nodes from each external function requires a better way to manage the lifetime of many xerces DOM document instances and their support class instances ** this is why DomDocumentCache and DomDocumentCache::item were implemented ** based on std::map so we can easily access the result of old function calls * changed external read-directory function to return the children of the document node instead of the document node itself ** removes unnecessary cruft in function calls ** will make returning status codes alongside the function result more pleasing to the eye * updated test transformation to reflect new features
-rw-r--r--CMakeLists.txt3
-rw-r--r--dummy/transform.xsl12
-rw-r--r--src/function/read_directory.cc103
-rw-r--r--src/function/read_directory.h12
-rw-r--r--src/support/dom/document_cache.cc26
-rw-r--r--src/support/dom/document_cache.h27
-rw-r--r--src/support/dom/document_cache_item.cc50
-rw-r--r--src/support/dom/document_cache_item.h (renamed from src/support/dom_document_guard.h)24
-rw-r--r--src/support/dom_document_guard.cc45
-rw-r--r--src/support/filesystem_context.cc14
-rw-r--r--src/support/utility.h18
-rw-r--r--src/transformation_facade.cc5
-rw-r--r--src/transformation_facade.h2
13 files changed, 218 insertions, 123 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4d50af0..02a9b79 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,8 @@ add_executable(
src/function/read_xml_file.cc
src/function/read_directory.cc
src/support/filesystem_context.cc
- src/support/dom_document_guard.cc
+ src/support/dom/document_cache.cc
+ src/support/dom/document_cache_item.cc
src/support/xerces_string_guard.cc
)
diff --git a/dummy/transform.xsl b/dummy/transform.xsl
index 95467ca..62d28c2 100644
--- a/dummy/transform.xsl
+++ b/dummy/transform.xsl
@@ -24,7 +24,17 @@
</xsl:for-each>
</ul>
<ul id="filelist">
- <xsl:for-each select="external:read-directory('.')/content/item[@type='file']">
+ <xsl:for-each select="external:read-directory('.')[@type='file']">
+ <li><xsl:value-of select="."/></li>
+ </xsl:for-each>
+ </ul>
+ <ul id="filelist2">
+ <xsl:for-each select="external:read-directory('../')[@type='file']">
+ <li><xsl:value-of select="."/></li>
+ </xsl:for-each>
+ </ul>
+ <ul id="filelist3">
+ <xsl:for-each select="external:read-directory('../')[@type='directory']">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</ul>
diff --git a/src/function/read_directory.cc b/src/function/read_directory.cc
index 9711239..677aa1d 100644
--- a/src/function/read_directory.cc
+++ b/src/function/read_directory.cc
@@ -6,13 +6,15 @@
#include <xercesc/dom/DOMText.hpp>
#include <xercesc/util/XMLString.hpp>
+#include "support/utility.h"
#include "support/xerces_string_guard.h"
namespace InputXSLT {
-FunctionReadDirectory::FunctionReadDirectory(const FilesystemContext& context):
+FunctionReadDirectory::FunctionReadDirectory(const FilesystemContext& context,
+ DomDocumentCache& cache):
fs_context_(context),
- documents_(std::make_shared<std::stack<DomDocumentGuard>>()) { }
+ document_cache_(cache) { }
xalan::XObjectPtr FunctionReadDirectory::execute(
xalan::XPathExecutionContext& executionContext,
@@ -20,53 +22,68 @@ xalan::XObjectPtr FunctionReadDirectory::execute(
const xalan::XObjectPtr argument,
const xalan::Locator*
) const {
- this->documents_->emplace("content");
- DomDocumentGuard& domDocument = this->documents_->top();
-
- xercesc::DOMNode* const rootNode = domDocument->getDocumentElement();
+ DomDocumentCache::item* const cachedDocument(
+ this->document_cache_.get(xalanToString(argument->str()))
+ );
- this->fs_context_.iterate(
- argument->str(),
- [&domDocument, &rootNode](const boost::filesystem::path& p) {
- xercesc::DOMElement* const itemNode(
- domDocument->createElement(*XercesStringGuard("item"))
+ if ( !cachedDocument->isFinalized() ) {
+ xercesc::DOMDocument* const domDocument(
+ cachedDocument->getXercesDocument()
);
- switch ( boost::filesystem::status(p).type() ) {
- case boost::filesystem::regular_file: {
- itemNode->setAttribute(
- *XercesStringGuard("type"),
- *XercesStringGuard("file")
- );
-
- break;
- };
- case boost::filesystem::directory_file: {
- itemNode->setAttribute(
- *XercesStringGuard("type"),
- *XercesStringGuard("directory")
- );
-
- break;
- };
- default: {
- break;
- };
- }
-
- xercesc::DOMText* const textNode(
- domDocument->createTextNode(
- *XercesStringGuard(p.filename().string())
- )
+ xercesc::DOMNode* const rootNode(
+ domDocument->getDocumentElement()
);
- itemNode->appendChild(textNode);
- rootNode->appendChild(itemNode);
- });
+ this->fs_context_.iterate(
+ argument->str(),
+ [&domDocument, &rootNode](const boost::filesystem::path& p) {
+ xercesc::DOMElement* const itemNode(
+ domDocument->createElement(*XercesStringGuard("item"))
+ );
+
+ switch ( boost::filesystem::status(p).type() ) {
+ case boost::filesystem::regular_file: {
+ itemNode->setAttribute(
+ *XercesStringGuard("type"),
+ *XercesStringGuard("file")
+ );
+
+ break;
+ };
+ case boost::filesystem::directory_file: {
+ itemNode->setAttribute(
+ *XercesStringGuard("type"),
+ *XercesStringGuard("directory")
+ );
+
+ break;
+ };
+ default: {
+ break;
+ };
+ }
+
+ xercesc::DOMText* const textNode(
+ domDocument->createTextNode(
+ *XercesStringGuard(p.filename().string())
+ )
+ );
+
+ itemNode->appendChild(textNode);
+ rootNode->appendChild(itemNode);
+ });
+ }
+
+ xalan::XPathExecutionContext::BorrowReturnMutableNodeRefList nodeList(
+ executionContext
+ );
- return executionContext.getXObjectFactory().createNodeSet(
- domDocument.finalize()
+ nodeList->addNodes(
+ *cachedDocument->getXalanDocument()->getDocumentElement()->getChildNodes()
);
+
+ return executionContext.getXObjectFactory().createNodeSet(nodeList);
}
FunctionReadDirectory* FunctionReadDirectory::clone(
@@ -76,7 +93,7 @@ FunctionReadDirectory* FunctionReadDirectory::clone(
const xalan::XalanDOMString& FunctionReadDirectory::getError(
xalan::XalanDOMString& result) const {
- result.assign("The read-directory() function expects one argument.");
+ result.assign("The read-directory() function expects one argument of type string.");
return result;
}
diff --git a/src/function/read_directory.h b/src/function/read_directory.h
index 782ebed..3fcf389 100644
--- a/src/function/read_directory.h
+++ b/src/function/read_directory.h
@@ -6,18 +6,15 @@
#include <xalanc/XPath/Function.hpp>
#include <xalanc/XPath/XObject.hpp>
-#include <memory>
-#include <stack>
-
#include "common.h"
#include "support/filesystem_context.h"
-#include "support/dom_document_guard.h"
+#include "support/dom/document_cache.h"
namespace InputXSLT {
class FunctionReadDirectory : public xalan::Function {
public:
- FunctionReadDirectory(const FilesystemContext&);
+ FunctionReadDirectory(const FilesystemContext&, DomDocumentCache&);
virtual xalan::XObjectPtr execute(
xalan::XPathExecutionContext&,
@@ -33,10 +30,7 @@ class FunctionReadDirectory : public xalan::Function {
private:
const FilesystemContext& fs_context_;
-
- std::shared_ptr<
- std::stack<DomDocumentGuard>
- > documents_;
+ DomDocumentCache& document_cache_;
const xalan::XalanDOMString& getError(xalan::XalanDOMString&) const;
diff --git a/src/support/dom/document_cache.cc b/src/support/dom/document_cache.cc
new file mode 100644
index 0000000..f814559
--- /dev/null
+++ b/src/support/dom/document_cache.cc
@@ -0,0 +1,26 @@
+#include "document_cache.h"
+
+namespace InputXSLT {
+
+DomDocumentCache::DomDocumentCache():
+ map_() { }
+
+DomDocumentCache::item* DomDocumentCache::get(const std::string& key) {
+ auto itemIter = this->map_.find(key);
+
+ if ( itemIter == this->map_.end() ) {
+ auto result = this->map_.emplace(
+ std::make_pair(key, std::unique_ptr<item>(new item("content")))
+ );
+
+ if ( result.second ) {
+ return (*(result.first)).second.get();
+ } else {
+ return nullptr;
+ }
+ } else {
+ return (*itemIter).second.get();
+ }
+}
+
+}
diff --git a/src/support/dom/document_cache.h b/src/support/dom/document_cache.h
new file mode 100644
index 0000000..4447a18
--- /dev/null
+++ b/src/support/dom/document_cache.h
@@ -0,0 +1,27 @@
+#ifndef INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_H_
+#define INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_H_
+
+#include <map>
+#include <string>
+#include <memory>
+
+namespace InputXSLT {
+
+class DomDocumentCache {
+ public:
+ class item;
+
+ DomDocumentCache();
+
+ item* get(const std::string&);
+
+ private:
+ std::map<std::string, std::unique_ptr<item>> map_;
+
+};
+
+}
+
+#include "document_cache_item.h"
+
+#endif // INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_H_
diff --git a/src/support/dom/document_cache_item.cc b/src/support/dom/document_cache_item.cc
new file mode 100644
index 0000000..8cc1c24
--- /dev/null
+++ b/src/support/dom/document_cache_item.cc
@@ -0,0 +1,50 @@
+#include "support/dom/document_cache_item.h"
+
+#include <xercesc/dom/DOMImplementation.hpp>
+#include <xercesc/util/XMLString.hpp>
+
+#include "support/xerces_string_guard.h"
+
+namespace InputXSLT {
+
+DomDocumentCache::item::item(const std::string& rootNode):
+ parser_(),
+ dom_support_(parser_),
+ document_(
+ xercesc::DOMImplementation::getImplementation()->createDocument(
+ nullptr,
+ *XercesStringGuard(rootNode),
+ nullptr
+ )
+ ),
+ parsed_source_() { }
+
+DomDocumentCache::item::~item() {
+ this->document_->release();
+}
+
+bool DomDocumentCache::item::isFinalized() const {
+ return static_cast<bool>(this->parsed_source_);
+}
+
+xercesc::DOMDocument* DomDocumentCache::item::getXercesDocument() const {
+ return this->document_;
+}
+
+xalan::XalanDocument* DomDocumentCache::item::getXalanDocument() {
+ if ( this->parsed_source_ ) {
+ return this->parsed_source_->getDocument();
+ } else {
+ this->parsed_source_.reset(
+ new xalan::XercesDOMWrapperParsedSource(
+ document_,
+ parser_,
+ dom_support_
+ )
+ );
+
+ return this->parsed_source_->getDocument();
+ }
+}
+
+}
diff --git a/src/support/dom_document_guard.h b/src/support/dom/document_cache_item.h
index decca01..1f7152b 100644
--- a/src/support/dom_document_guard.h
+++ b/src/support/dom/document_cache_item.h
@@ -1,5 +1,5 @@
-#ifndef INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_
-#define INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_
+#ifndef INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_ITEM_H_
+#define INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_ITEM_H_
#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>
#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>
@@ -11,21 +11,27 @@
#include <memory>
#include "common.h"
+#include "document_cache.h"
namespace InputXSLT {
-class DomDocumentGuard {
+class DomDocumentCache::item {
public:
- DomDocumentGuard(const std::string&);
- ~DomDocumentGuard();
+ ~item();
- xercesc::DOMDocument* operator->();
- xalan::XalanDocument* finalize();
+ bool isFinalized() const;
+
+ xercesc::DOMDocument* getXercesDocument() const;
+ xalan::XalanDocument* getXalanDocument();
+
+ protected:
+ friend DomDocumentCache;
+
+ item(const std::string&);
private:
xalan::XercesParserLiaison parser_;
xalan::XercesDOMSupport dom_support_;
- XMLCh* root_node_name_;
xercesc::DOMDocument* const document_;
std::unique_ptr<xalan::XercesDOMWrapperParsedSource> parsed_source_;
@@ -33,4 +39,4 @@ class DomDocumentGuard {
}
-#endif // INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_GUARD_H_
+#endif // INPUTXSLT_SRC_SUPPORT_DOM_DOCUMENT_CACHE_ITEM_H_
diff --git a/src/support/dom_document_guard.cc b/src/support/dom_document_guard.cc
deleted file mode 100644
index a83345f..0000000
--- a/src/support/dom_document_guard.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "support/dom_document_guard.h"
-
-#include <xercesc/dom/DOMImplementation.hpp>
-#include <xercesc/util/XMLString.hpp>
-
-namespace InputXSLT {
-
-DomDocumentGuard::DomDocumentGuard(const std::string& rootNode):
- parser_(),
- dom_support_(parser_),
- root_node_name_(
- xercesc::XMLString::transcode(rootNode.data())
- ),
- document_(
- xercesc::DOMImplementation::getImplementation()->createDocument(
- nullptr,
- root_node_name_,
- nullptr
- )
- ),
- parsed_source_() { }
-
-DomDocumentGuard::~DomDocumentGuard() {
- xercesc::XMLString::release(&this->root_node_name_);
-
- this->document_->release();
-}
-
-xercesc::DOMDocument* DomDocumentGuard::operator->() {
- return this->document_;
-}
-
-xalan::XalanDocument* DomDocumentGuard::finalize() {
- this->parsed_source_.reset(
- new xalan::XercesDOMWrapperParsedSource(
- document_,
- parser_,
- dom_support_
- )
- );
-
- return this->parsed_source_->getDocument();
-}
-
-}
diff --git a/src/support/filesystem_context.cc b/src/support/filesystem_context.cc
index baeccf3..9ed9bbf 100644
--- a/src/support/filesystem_context.cc
+++ b/src/support/filesystem_context.cc
@@ -1,18 +1,6 @@
#include "filesystem_context.h"
-namespace {
-
-inline std::string xalanToString(const xalan::XalanDOMString& text) {
- xalan::CharVectorType castHelper;
- text.transcode(castHelper);
-
- return std::string(
- castHelper.begin(),
- castHelper.end() - 1
- );
-}
-
-}
+#include "support/utility.h"
namespace InputXSLT {
diff --git a/src/support/utility.h b/src/support/utility.h
new file mode 100644
index 0000000..4c63c72
--- /dev/null
+++ b/src/support/utility.h
@@ -0,0 +1,18 @@
+#ifndef INPUTXSLT_SRC_SUPPORT_UTILITY_H_
+#define INPUTXSLT_SRC_SUPPORT_UTILITY_H_
+
+namespace {
+
+inline std::string xalanToString(const xalan::XalanDOMString& text) {
+ xalan::CharVectorType castHelper;
+ text.transcode(castHelper);
+
+ return std::string(
+ castHelper.begin(),
+ castHelper.end() - 1
+ );
+}
+
+}
+
+#endif // INPUTXSLT_SRC_SUPPORT_UTILITY_H_
diff --git a/src/transformation_facade.cc b/src/transformation_facade.cc
index 38dfe93..cb89263 100644
--- a/src/transformation_facade.cc
+++ b/src/transformation_facade.cc
@@ -15,7 +15,8 @@ namespace InputXSLT {
TransformationFacade::TransformationFacade(const std::string& transformation):
fs_context_(boost::filesystem::path(transformation).parent_path().string()),
transformation_{},
- transformer_() {
+ transformer_(),
+ document_cache_() {
const xalan::XalanDOMString customNamespace(
"http://ExternalFunction.xalan-c++.xml.apache.org"
);
@@ -35,7 +36,7 @@ TransformationFacade::TransformationFacade(const std::string& transformation):
this->transformer_.installExternalFunction(
customNamespace,
xalan::XalanDOMString("read-directory"),
- InputXSLT::FunctionReadDirectory(this->fs_context_)
+ InputXSLT::FunctionReadDirectory(this->fs_context_, this->document_cache_)
);
this->transformer_.compileStylesheet(
diff --git a/src/transformation_facade.h b/src/transformation_facade.h
index 765a376..3acb364 100644
--- a/src/transformation_facade.h
+++ b/src/transformation_facade.h
@@ -7,6 +7,7 @@
#include "common.h"
#include "support/filesystem_context.h"
+#include "support/dom/document_cache.h"
namespace InputXSLT {
@@ -22,6 +23,7 @@ class TransformationFacade {
const xalan::XalanCompiledStylesheet* transformation_;
xalan::XalanTransformer transformer_;
+ DomDocumentCache document_cache_;
};