From 79d3e2bdfd441d6eba2f22af78d5bea5e488daf1 Mon Sep 17 00:00:00 2001 From: Adrian Kummerländer Date: Fri, 30 May 2014 22:19:32 +0200 Subject: Rewrote error handling based on exceptions * ErrorHandler is replaced by ErrorCapacitor ** temporarily registers itself as both the ProblemListener and ErrorHandler of a given XalanTransformer instance ** deregisters itself on destruction ** collects all problems and errors during its lifetime inside a internal std::vector instance ** if this instance is not empty it is thrown contained within a ErrorCapacitor::exception by the member method ErrorCapacitor::discharge * this enables using the same code for handling transformation compilation and generation errors and problems * updated test frontend accordingly --- CMakeLists.txt | 2 +- src/function/transform.cc | 19 ++++---- src/support/error_capacitor.cc | 107 +++++++++++++++++++++++++++++++++++++++++ src/support/error_capacitor.h | 81 +++++++++++++++++++++++++++++++ src/support/error_handler.cc | 107 ----------------------------------------- src/support/error_handler.h | 67 -------------------------- src/transformation_facade.cc | 49 ++++++++++--------- src/transformation_facade.h | 33 ++++++------- test.cc | 33 +++++++------ 9 files changed, 256 insertions(+), 242 deletions(-) create mode 100644 src/support/error_capacitor.cc create mode 100644 src/support/error_capacitor.h delete mode 100644 src/support/error_handler.cc delete mode 100644 src/support/error_handler.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d83c0a..2ca7990 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ set( src/support/stylesheet_parameter_guard.cc src/support/xalan_string.cc src/support/include_entity_resolver.cc - src/support/error_handler.cc + src/support/error_capacitor.cc src/support/tuple/xobject_value.cc src/support/dom/document_cache.cc src/support/dom/document_cache_item.cc diff --git a/src/function/transform.cc b/src/function/transform.cc index 7e8a844..e952018 100644 --- a/src/function/transform.cc +++ b/src/function/transform.cc @@ -41,17 +41,16 @@ xercesc::DOMDocument* FunctionTransform::constructDocument( ResultNodeFacade result(domDocument, rootNode, "result"); result.setAttribute("name", targetPath); - InputXSLT::TransformationFacade transformation( - transformationPath, - this->include_resolver_ - ); - - InputXSLT::TransformationFacade::return_type errors( - transformation.generate(targetPath, parameterObject) - ); + try { + InputXSLT::TransformationFacade transformation( + transformationPath, + this->include_resolver_ + ); - if ( errors ) { - for ( auto&& error : *errors ) { + transformation.generate(targetPath, parameterObject); + } + catch (const ErrorCapacitor::exception& exception) { + for ( auto&& error : *(exception.getCachedErrors()) ) { result.setValueNode("error", error); } } diff --git a/src/support/error_capacitor.cc b/src/support/error_capacitor.cc new file mode 100644 index 0000000..e83ba9a --- /dev/null +++ b/src/support/error_capacitor.cc @@ -0,0 +1,107 @@ +#include "error_capacitor.h" + +#include + +#include + +#include "support/xalan_string.h" +#include "support/xerces_string_guard.h" + +namespace { + +inline std::string getMessage(const xercesc::SAXParseException& exception) { + return std::string( + *InputXSLT::XercesStringGuard(exception.getMessage()) + ); +} + +} + +namespace InputXSLT { + +ErrorCapacitor::ErrorCapacitor(xalan::XalanTransformer* transformer): + transformer_(transformer), + error_cache_(new error_cache()) { + this->transformer_->setErrorHandler(this); + this->transformer_->setProblemListener(this); +} + +ErrorCapacitor::~ErrorCapacitor() { + this->transformer_->setErrorHandler(nullptr); + this->transformer_->setProblemListener(nullptr); +} + +void ErrorCapacitor::discharge() { + if ( !this->error_cache_->empty() ) { + throw exception(std::move(this->error_cache_)); + } +} + +void ErrorCapacitor::warning(const xercesc::SAXParseException& exception) { + this->error_cache_->emplace_back( + "Warning: " + getMessage(exception) + ); +} + +void ErrorCapacitor::error(const xercesc::SAXParseException& exception) { + this->error_cache_->emplace_back( + "Error: " + getMessage(exception) + ); +} + +void ErrorCapacitor::fatalError(const xercesc::SAXParseException& exception) { + this->error_cache_->emplace_back( + "Fatal error: " + getMessage(exception) + ); +} + +void ErrorCapacitor::resetErrors() { } + +void ErrorCapacitor::problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanDOMString& message, + const xalan::Locator*, + const xalan::XalanNode* +) { + this->error_cache_->emplace_back( + "XSLT problem: " + toString(message) + ); +} + +void ErrorCapacitor::problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanNode*, + const xalan::ElemTemplateElement*, + const xalan::XalanDOMString& message, + const xalan::XalanDOMChar*, + xalan::XalanFileLoc, + xalan::XalanFileLoc +) { + this->error_cache_->emplace_back( + "XSLT problem: " + toString(message) + ); +} + +void ErrorCapacitor::problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanDOMString& message, + const xalan::XalanNode* +) { + this->error_cache_->emplace_back( + "XSLT problem: " + toString(message) + ); +} + +void ErrorCapacitor::setPrintWriter(xalan::PrintWriter*) { } + +ErrorCapacitor::exception::exception(error_cache_ptr ptr): + error_cache_(std::move(ptr)) { } + +auto ErrorCapacitor::exception::getCachedErrors() const -> const error_cache* { + return this->error_cache_.get(); +} + +} diff --git a/src/support/error_capacitor.h b/src/support/error_capacitor.h new file mode 100644 index 0000000..d89b5ae --- /dev/null +++ b/src/support/error_capacitor.h @@ -0,0 +1,81 @@ +#ifndef INPUTXSLT_SRC_SUPPORT_ERROR_CAPACITOR_H_ +#define INPUTXSLT_SRC_SUPPORT_ERROR_CAPACITOR_H_ + +#include +#include +#include + +#include +#include +#include + +#include "common.h" + +namespace InputXSLT { + +class ErrorCapacitor : public xercesc::ErrorHandler, + public xalan::ProblemListener { + public: + class exception; + + typedef std::vector error_cache; + typedef std::unique_ptr error_cache_ptr; + + ErrorCapacitor(xalan::XalanTransformer*); + ~ErrorCapacitor(); + + void discharge(); + + virtual void warning(const xercesc::SAXParseException&); + virtual void error(const xercesc::SAXParseException&); + virtual void fatalError(const xercesc::SAXParseException&); + virtual void resetErrors(); + + virtual void problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanDOMString&, + const xalan::Locator*, + const xalan::XalanNode* + ); + + virtual void problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanNode*, + const xalan::ElemTemplateElement*, + const xalan::XalanDOMString&, + const xalan::XalanDOMChar*, + xalan::XalanFileLoc, + xalan::XalanFileLoc + ); + + virtual void problem( + xalan::ProblemListenerBase::eSource, + xalan::ProblemListenerBase::eClassification, + const xalan::XalanDOMString&, + const xalan::XalanNode* + ); + + virtual void setPrintWriter(xalan::PrintWriter*); + + private: + xalan::XalanTransformer* const transformer_; + error_cache_ptr error_cache_; + +}; + +class ErrorCapacitor::exception { + public: + exception(error_cache_ptr); + + const error_cache* getCachedErrors() const; + + private: + error_cache_ptr error_cache_; + +}; + +} + +#endif // INPUTXSLT_SRC_SUPPORT_ERROR_CAPACITOR_H_ diff --git a/src/support/error_handler.cc b/src/support/error_handler.cc deleted file mode 100644 index 2ca721d..0000000 --- a/src/support/error_handler.cc +++ /dev/null @@ -1,107 +0,0 @@ -#include "error_handler.h" - -#include - -#include - -#include "support/xalan_string.h" -#include "support/xerces_string_guard.h" - -namespace { - -inline std::string getMessage(const xercesc::SAXParseException& exception) { - return std::string( - *InputXSLT::XercesStringGuard(exception.getMessage()) - ); -} - -} - -namespace InputXSLT { - -ErrorHandler::ErrorHandler(): - error_cache_{} { } - -void ErrorHandler::warning(const xercesc::SAXParseException& exception) { - this->constructErrorCache(); - - this->error_cache_->emplace_back( - "Warning: " + getMessage(exception) - ); -} - -void ErrorHandler::error(const xercesc::SAXParseException& exception) { - this->constructErrorCache(); - - this->error_cache_->emplace_back( - "Error: " + getMessage(exception) - ); -} - -void ErrorHandler::fatalError(const xercesc::SAXParseException& exception) { - this->constructErrorCache(); - - this->error_cache_->emplace_back( - "Fatal error: " + getMessage(exception) - ); -} - -void ErrorHandler::resetErrors() { } - -void ErrorHandler::problem( - xalan::ProblemListenerBase::eSource, - xalan::ProblemListenerBase::eClassification, - const xalan::XalanDOMString& message, - const xalan::Locator*, - const xalan::XalanNode* -) { - this->constructErrorCache(); - - this->error_cache_->emplace_back( - "XSLT problem: " + toString(message) - ); -} - -void ErrorHandler::problem( - xalan::ProblemListenerBase::eSource, - xalan::ProblemListenerBase::eClassification, - const xalan::XalanNode*, - const xalan::ElemTemplateElement*, - const xalan::XalanDOMString& message, - const xalan::XalanDOMChar*, - xalan::XalanFileLoc, - xalan::XalanFileLoc -) { - this->constructErrorCache(); - - this->error_cache_->emplace_back( - "XSLT problem: " + toString(message) - ); -} - -void ErrorHandler::problem( - xalan::ProblemListenerBase::eSource, - xalan::ProblemListenerBase::eClassification, - const xalan::XalanDOMString& message, - const xalan::XalanNode* -) { - this->constructErrorCache(); - - this->error_cache_->emplace_back( - "XSLT problem: " + toString(message) - ); -} - -void ErrorHandler::setPrintWriter(xalan::PrintWriter*) { } - -auto ErrorHandler::getCachedErrors() -> error_cache_ptr { - return error_cache_ptr(this->error_cache_.release()); -} - -void ErrorHandler::constructErrorCache() { - if ( !this->error_cache_ ) { - this->error_cache_.reset(new error_cache()); - } -} - -} diff --git a/src/support/error_handler.h b/src/support/error_handler.h deleted file mode 100644 index 02d741e..0000000 --- a/src/support/error_handler.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef INPUTXSLT_SRC_SUPPORT_ERROR_HANDLER_H_ -#define INPUTXSLT_SRC_SUPPORT_ERROR_HANDLER_H_ - -#include -#include - -#include -#include -#include - -#include "common.h" - -namespace InputXSLT { - -class ErrorHandler : public xercesc::ErrorHandler, - public xalan::ProblemListener { - public: - typedef std::vector error_cache; - typedef std::unique_ptr error_cache_ptr; - - ErrorHandler(); - - virtual void warning(const xercesc::SAXParseException&); - virtual void error(const xercesc::SAXParseException&); - virtual void fatalError(const xercesc::SAXParseException&); - virtual void resetErrors(); - - virtual void problem( - xalan::ProblemListenerBase::eSource, - xalan::ProblemListenerBase::eClassification, - const xalan::XalanDOMString&, - const xalan::Locator*, - const xalan::XalanNode* - ); - - virtual void problem( - xalan::ProblemListenerBase::eSource, - xalan::ProblemListenerBase::eClassification, - const xalan::XalanNode*, - const xalan::ElemTemplateElement*, - const xalan::XalanDOMString&, - const xalan::XalanDOMChar*, - xalan::XalanFileLoc, - xalan::XalanFileLoc - ); - - virtual void problem( - xalan::ProblemListenerBase::eSource, - xalan::ProblemListenerBase::eClassification, - const xalan::XalanDOMString&, - const xalan::XalanNode* - ); - - virtual void setPrintWriter(xalan::PrintWriter*); - - error_cache_ptr getCachedErrors(); - - private: - error_cache_ptr error_cache_; - - void constructErrorCache(); - -}; - -} - -#endif // INPUTXSLT_SRC_SUPPORT_ERROR_HANDLER_H_ diff --git a/src/transformation_facade.cc b/src/transformation_facade.cc index 8b9e1a2..f415cd8 100644 --- a/src/transformation_facade.cc +++ b/src/transformation_facade.cc @@ -14,16 +14,17 @@ TransformationFacade::TransformationFacade( IncludeEntityResolver* resolver ): transformation_{}, - transformer_(), - error_handler_() { + transformer_() { this->transformer_.setEntityResolver(resolver); - this->transformer_.setErrorHandler(&this->error_handler_); - this->transformer_.setProblemListener(&this->error_handler_); + + ErrorCapacitor errorCapacitor(&this->transformer_); this->transformer_.compileStylesheet( xalan::XSLTInputSource(transformation.data()), this->transformation_ ); + + errorCapacitor.discharge(); } TransformationFacade::~TransformationFacade() { @@ -32,10 +33,10 @@ TransformationFacade::~TransformationFacade() { ); } -auto TransformationFacade::generate( +void TransformationFacade::generate( const std::string& targetPath, StylesheetParameterGuard& parameters -) -> return_type { +) { const boost::filesystem::path targetPathHelper( boost::filesystem::absolute(targetPath) ); @@ -47,38 +48,38 @@ auto TransformationFacade::generate( "parent-directory", targetPathHelper.parent_path().filename().string() ); - return this->generate( + this->generate( xalan::XSLTResultTarget(targetPath.data()), parameters ); } -auto TransformationFacade::generate( +void TransformationFacade::generate( std::basic_ostream& targetStream, StylesheetParameterGuard& parameters -) -> return_type { - return this->generate( +) { + this->generate( xalan::XSLTResultTarget(targetStream), parameters ); } -auto TransformationFacade::generate( +void TransformationFacade::generate( xalan::XSLTResultTarget&& outputTarget, StylesheetParameterGuard& -) -> return_type { - if ( this->transformation_ != nullptr ) { - std::stringstream emptyStream(""); - xalan::XSLTInputSource inputSource(emptyStream); - - this->transformer_.transform( - inputSource, - this->transformation_, - outputTarget - ); - } - - return this->error_handler_.getCachedErrors(); +) { + ErrorCapacitor errorCapacitor(&this->transformer_); + + std::stringstream emptyStream(""); + xalan::XSLTInputSource inputSource(emptyStream); + + this->transformer_.transform( + inputSource, + this->transformation_, + outputTarget + ); + + errorCapacitor.discharge(); } } diff --git a/src/transformation_facade.h b/src/transformation_facade.h index 28d1895..4fb997b 100644 --- a/src/transformation_facade.h +++ b/src/transformation_facade.h @@ -6,7 +6,7 @@ #include #include "common.h" -#include "support/error_handler.h" +#include "support/error_capacitor.h" #include "support/include_entity_resolver.h" #include "support/stylesheet_parameter_guard.h" @@ -14,58 +14,55 @@ namespace InputXSLT { class TransformationFacade { public: - typedef ErrorHandler::error_cache_ptr return_type; - TransformationFacade(const std::string&, IncludeEntityResolver*); ~TransformationFacade(); template - return_type generate(Target&); + void generate(Target&); template - return_type generate(Target&, const StylesheetParameterGuard::map&); + void generate(Target&, const StylesheetParameterGuard::map&); template - return_type generate(Target&, const xalan::XObjectPtr&); + void generate(Target&, const xalan::XObjectPtr&); private: const xalan::XalanCompiledStylesheet* transformation_; xalan::XalanTransformer transformer_; - ErrorHandler error_handler_; - return_type generate(const std::string&, StylesheetParameterGuard&); - return_type generate(std::basic_ostream&, StylesheetParameterGuard&); - return_type generate(xalan::XSLTResultTarget&&, StylesheetParameterGuard&); + void generate(const std::string&, StylesheetParameterGuard&); + void generate(std::basic_ostream&, StylesheetParameterGuard&); + void generate(xalan::XSLTResultTarget&&, StylesheetParameterGuard&); }; template -auto TransformationFacade::generate(Target& target) -> return_type { +void TransformationFacade::generate(Target& target) { StylesheetParameterGuard guard(this->transformer_); - return this->generate(target, guard); + this->generate(target, guard); } template -auto TransformationFacade::generate( +void TransformationFacade::generate( Target& target, const StylesheetParameterGuard::map& parameters -) -> return_type { +) { StylesheetParameterGuard guard(this->transformer_, parameters); - return this->generate(target, guard); + this->generate(target, guard); } template -auto TransformationFacade::generate( +void TransformationFacade::generate( Target& target, const xalan::XObjectPtr& parameter -) -> return_type { +) { StylesheetParameterGuard guard(this->transformer_); guard.set("parameters", parameter); - return this->generate(target, guard); + this->generate(target, guard); } } diff --git a/test.cc b/test.cc index 0c5e4b2..6874fd5 100644 --- a/test.cc +++ b/test.cc @@ -43,25 +43,28 @@ int main(int ac, char** av) { InputXSLT::PlattformGuard plattform(includePath); - InputXSLT::TransformationFacade transformation( - variables["transformation"].as(), - plattform.getEntityResolver() - ); - - InputXSLT::TransformationFacade::return_type errors{}; - - if ( variables.count("target") ) { - errors = transformation.generate( - variables["target"].as() + try { + InputXSLT::TransformationFacade transformation( + variables["transformation"].as(), + plattform.getEntityResolver() ); - } else { - errors = transformation.generate(std::cout); - } - if ( errors ) { - for ( auto&& error : *errors ) { + if ( variables.count("target") ) { + transformation.generate( + variables["target"].as() + ); + } else { + transformation.generate(std::cout); + } + + return 0; + } + catch (const InputXSLT::ErrorCapacitor::exception& exception) { + for ( auto&& error : *(exception.getCachedErrors()) ) { std::cerr << error << std::endl; } + + return 1; } } else { std::cout << optionDescription << std::endl; -- cgit v1.2.3