diff options
| -rw-r--r-- | project2/Jamfile.jam | 2 | ||||
| -rw-r--r-- | project2/cgi/cgiAppEngine.cpp | 238 | ||||
| -rw-r--r-- | project2/cgi/cgiAppEngine.h | 83 | ||||
| -rw-r--r-- | project2/cgi/cgiCommon.cpp | 17 | ||||
| -rw-r--r-- | project2/cgi/cgiEnvironment.cpp | 8 | ||||
| -rw-r--r-- | project2/cgi/cgiEnvironment.h | 4 | ||||
| -rw-r--r-- | project2/commonObjects.cpp | 6 | ||||
| -rw-r--r-- | project2/config.cpp | 6 | ||||
| -rw-r--r-- | project2/console/consoleAppEngine.cpp | 6 | ||||
| -rw-r--r-- | project2/exceptions.h | 5 | ||||
| -rw-r--r-- | project2/presenter.h | 1 | ||||
| -rw-r--r-- | project2/sendmailTask.cpp | 4 | ||||
| -rw-r--r-- | project2/xmlPresenter.cpp | 56 | ||||
| -rw-r--r-- | project2/xmlPresenter.h | 32 | ||||
| -rw-r--r-- | project2/xmlScriptParser.cpp | 40 | ||||
| -rw-r--r-- | project2/xmlScriptParser.h | 25 | 
16 files changed, 415 insertions, 118 deletions
| diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index d4e72e8..f591344 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -49,7 +49,7 @@ lib p2uuid :  lib p2common :  	appEngine.cpp dataSource.cpp environment.cpp fileStarGlibIoChannel.cpp iHaveParameters.cpp -	iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp logger.cpp if.cpp +	iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp logger.cpp if.cpp xmlScriptParser.cpp  	sourceObject.cpp task.cpp variables.cpp variableConvert.cpp view.cpp xmlObjectLoader.cpp exceptions.cpp  	sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp xmlPresenter.cpp  	rowView.cpp rowSet.cpp rowUser.cpp rowProcessor.cpp config.cpp fileStrmVarWriter.cpp diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 40d1431..043da76 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -1,14 +1,15 @@  #include "cgiAppEngine.h"  #include <cgicc/Cgicc.h> -#include <cgicc/HTTPContentHeader.h> +#include <cgicc/HTTPStatusHeader.h>  #include "cgiEnvironment.h" -#include <libxml/xinclude.h>  #include "../xmlObjectLoader.h"  #include "../iterate.h" +#include "../logger.h"  #include <boost/bind.hpp>  #include <boost/regex.hpp>  #include <boost/foreach.hpp>  #include "../sessionXml.h" +#include <cxxabi.h>  const std::string SESSIONID = "sessionID";  typedef UUID SIDKey; @@ -18,27 +19,64 @@ SessionContainer * sessionsContainer = new SessionContainerXml();  SimpleMessageException(UnknownDomain); +class Project2HttpHeader : public cgicc::HTTPStatusHeader { +	public: +		typedef std::map<std::string, const Glib::ustring> Headers; +		Project2HttpHeader(int c, const std::string & m, const std::string & t) : +			cgicc::HTTPStatusHeader(c, m) +		{ +			addHeader("Content-Type", t); +		} +		void addHeader(const std::string & name, const Glib::ustring & value) { +			headers.erase(name); +			headers.insert(Headers::value_type(name, value)); +		} +		void render(std::ostream & out) const { +			BOOST_FOREACH(const Headers::value_type & h, headers) { +				out << h.first << ": " << h.second << std::endl; +			} +			cgicc::HTTPStatusHeader::render(out); +		} +	private: +		Headers headers; +}; + +static +int +xmlWrite(void * _out, const char * buf, int len) +{ +	std::ostream * IO = static_cast<std::ostream*>(_out); +	IO->write(buf, len); +	return len; +} +  CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e) :  	ApplicationEngine("web/host"), -	_env(e), -	header(NULL) +	_env(e)  {  	BOOST_FOREACH(const cgicc::HTTPCookie c, e->getCookieList()) {  		if (c.getName() == SESSIONID) {  			sessionID = c.getValue();  		}  	} -	if (_env->getRequestMethod() == "POST") { -		currentStage = new RequestStage(this, e->elems[0]); +	try { +		if (_env->getRequestMethod() == "POST") { +			currentStage = new RequestStage(e->elems[0]); +		} +		else { +			currentStage = new PresentStage(e->elems.size() > 0 ? e->elems[0] : "index"); +		} +	} +	catch (const XmlScriptParser::NotFound & nf) { +		currentStage = new NotFoundStage(_env, nf);  	} -	else { -		currentStage = new PresentStage(this, e->elems.size() > 0 ? e->elems[0] : "index"); +	catch (const std::exception & ex) { +		currentStage = new ErrorStage(_env, ex);  	}  }  CgiApplicationEngine::~CgiApplicationEngine()  { -	delete header;  }  const Environment * @@ -48,45 +86,50 @@ CgiApplicationEngine::env() const  }  void -CgiApplicationEngine::write(const XmlWriter & w) const +CgiApplicationEngine::write(std::ostream & IO) const  { -	w(doc->cobj()); -} - -void -CgiApplicationEngine::process() const -{ -	while (!doc && currentStage) { -		currentStage = currentStage->run(); -	} +	HttpHeaderPtr header = currentStage->getHeader();  	if (!sessionID.is_nil()) {  		header->setCookie(cgicc::HTTPCookie(SESSIONID, sessionID.str(), "Session ID",  					_env->getServerName().substr(_env->getServerName().find(".")), 3600, "/", false));  	} +	header->render(IO); +	xmlOutputBufferPtr out = xmlOutputBufferCreateIO( +			xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8)); +	xmlSaveFileTo(out, currentStage->getDataDocument()->cobj(), "utf-8");  #ifndef NDEBUG  	if (!_env->dumpdatadoc.empty()) { -		doc->write_to_file_formatted(_env->dumpdatadoc); +		currentStage->getDataDocument()->write_to_file_formatted(_env->dumpdatadoc);  	}  #endif  } -CgiApplicationEngine::Stage::Stage(const CgiApplicationEngine * e) : appEngine(e) +void +CgiApplicationEngine::process() const  { +	try { +		for (StagePtr nextStage; (nextStage = currentStage->run()); ) { +			currentStage = nextStage; +		} +	} +	catch (const XmlScriptParser::NotFound & nf) { +		currentStage = new NotFoundStage(_env, nf); +	} +	catch (const std::exception & ex) { +		currentStage = new ErrorStage(_env, ex); +	}  } -CgiApplicationEngine::Stage::~Stage() +CgiApplicationEngine::Stage::Stage()  {  } -CgiApplicationEngine::PresentStage::PresentStage(const CgiApplicationEngine * e, const std::string & id) : -	CgiApplicationEngine::Stage(e), -	XmlPresenter("present", id) +CgiApplicationEngine::Stage::~Stage()  {  } -CgiApplicationEngine::PresentStage::PresentStage(const CgiApplicationEngine * e, const std::string & group, const std::string & id) : -	CgiApplicationEngine::Stage(e), -	XmlPresenter(group, id) +CgiApplicationEngine::PresentStage::PresentStage(const std::string & id) : +	XmlProcessPresenter("present", id, false)  {  } @@ -99,16 +142,28 @@ CgiApplicationEngine::PresentStage::run()  {  	BOOST_FOREACH(ParamCheckers::value_type pc, parameterChecks.get<bySOOrder>()) {  		if (!pc->performCheck()) { -			return new PresentStage(appEngine, pc->present); +			return new PresentStage(pc->present);  		}  	}  	execute(); -	appEngine->doc = getDataDocument(); -	appEngine->header = new cgicc::HTTPContentHeader(contentType);  	sessionsContainer->CleanUp();  	return NULL;  } +CgiApplicationEngine::HttpHeaderPtr +CgiApplicationEngine::PresentStage::getHeader() const +{ +	Project2HttpHeader * header = new Project2HttpHeader(200, "OK", contentType); +	header->addHeader("Cache-control", "no-cache"); +	return HttpHeaderPtr(header); +} + +CgiApplicationEngine::XmlDocPtr +CgiApplicationEngine::PresentStage::getDataDocument() const +{ +	return XmlProcessPresenter::getDataDocument(); +} +  void  CgiApplicationEngine::addAppData(const Presenter * p) const  { @@ -144,11 +199,9 @@ CgiApplicationEngine::addAppData(const Presenter * p) const  	}  } -CgiApplicationEngine::RequestStage::RequestStage(const CgiApplicationEngine * e, const std::string & id) : -	CgiApplicationEngine::Stage(e) +CgiApplicationEngine::RequestStage::RequestStage(const std::string & id)  { -	xmlpp::DomParser request("request/" + id + ".xml"); -	while (xmlXIncludeProcessFlags(request.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); +	XmlScriptParser request("request", id, false);  	xmlpp::Element * requestRoot = request.get_document()->get_root_node();  	present = requestRoot->get_attribute_value("present"); @@ -166,7 +219,7 @@ CgiApplicationEngine::RequestStage::run()  {  	BOOST_FOREACH(const ParamCheckers::value_type & pc, parameterChecks.get<bySOOrder>()) {  		if (!pc->performCheck()) { -			return new PresentStage(appEngine, pc->present); +			return new PresentStage(pc->present);  		}  	}  	try { @@ -177,7 +230,7 @@ CgiApplicationEngine::RequestStage::run()  		BOOST_FOREACH(const DataSources::value_type & ds, datasources) {  			ds->commit();  		} -		return new PresentStage(appEngine, present); +		return present.empty() ? NULL : new PresentStage(present);  	}  	catch (...) {  		// Do something about the error @@ -188,6 +241,31 @@ CgiApplicationEngine::RequestStage::run()  	}  } +CgiApplicationEngine::HttpHeaderPtr +CgiApplicationEngine::RequestStage::getHeader() const +{ +	return HttpHeaderPtr(new Project2HttpHeader(200, "OK", "text/xml")); +} + +CgiApplicationEngine::XmlDocPtr +CgiApplicationEngine::RequestStage::getDataDocument() const +{ +	return XmlPresenter::getDataDocument(); +} + +const Glib::ustring CgiApplicationEngine::RequestStage::resp("request"); +const Glib::ustring CgiApplicationEngine::RequestStage::style; +const Glib::ustring & +CgiApplicationEngine::RequestStage::getResponseRootNodeName() const +{ +	return resp; +} +const Glib::ustring & +CgiApplicationEngine::RequestStage::getResponseStyle() const +{ +	return style; +} +  SessionPtr  CgiApplicationEngine::session() const  { @@ -217,3 +295,89 @@ CgiApplicationEngine::loadEngineSection(const xmlpp::Element * e) const  	domplat.push_back(DomainPlatforms::value_type(e->get_attribute_value("name"), e->get_attribute_value("platform")));  } +CgiApplicationEngine::FailStage::FailStage(const CgiEnvironment * e) : +	env(e) +{ +} + +CgiApplicationEngine::FailStage::~FailStage() +{ +} + +const Glib::ustring & +CgiApplicationEngine::FailStage::getResponseStyle() const +{ +	return env->errorTransformStyle; +} + +CgiApplicationEngine::StagePtr +CgiApplicationEngine::FailStage::run() +{ +	return NULL; +} + +CgiApplicationEngine::NotFoundStage::NotFoundStage(const CgiEnvironment * e, const XmlScriptParser::NotFound & nf) : +	CgiApplicationEngine::FailStage(e) +{ +	initDoc(); +	responseDoc->get_root_node()->add_child("resource")->set_child_text(nf.what()); +} + +CgiApplicationEngine::NotFoundStage::~NotFoundStage() +{ +} + +CgiApplicationEngine::HttpHeaderPtr +CgiApplicationEngine::NotFoundStage::getHeader() const +{ +	return HttpHeaderPtr(new Project2HttpHeader(404, "Not found", env->errorContentType)); +} + +const Glib::ustring CgiApplicationEngine::NotFoundStage::resp("notfound"); +const Glib::ustring & +CgiApplicationEngine::NotFoundStage::getResponseRootNodeName() const +{ +	return resp; +} + +CgiApplicationEngine::XmlDocPtr +CgiApplicationEngine::NotFoundStage::getDataDocument() const +{ +	return XmlPresenter::getDataDocument(); +} + +CgiApplicationEngine::ErrorStage::ErrorStage(const CgiEnvironment * e, const std::exception & ex) : +	CgiApplicationEngine::FailStage(e) +{ +	initDoc(); +	char * buf = __cxxabiv1::__cxa_demangle(typeid(ex).name(), NULL, NULL, NULL); +	Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, ex.what()); +	responseDoc->get_root_node()->add_child("type")->set_child_text(buf); +	responseDoc->get_root_node()->add_child("what")->set_child_text(ex.what()); +	free(buf); +} + +CgiApplicationEngine::ErrorStage::~ErrorStage() +{ +} + +CgiApplicationEngine::HttpHeaderPtr +CgiApplicationEngine::ErrorStage::getHeader() const +{ +	return HttpHeaderPtr(new Project2HttpHeader(500, "Internal Server Error", env->errorContentType)); +} + +const Glib::ustring CgiApplicationEngine::ErrorStage::resp("error"); +const Glib::ustring & +CgiApplicationEngine::ErrorStage::getResponseRootNodeName() const +{ +	return resp; +} + +CgiApplicationEngine::XmlDocPtr +CgiApplicationEngine::ErrorStage::getDataDocument() const +{ +	return XmlPresenter::getDataDocument(); +} + + diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index 1425207..79638f4 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -8,36 +8,32 @@  #include "../commonObjects.h"  #include "../uuid.h"  #include <boost/intrusive_ptr.hpp> -#include <boost/function.hpp> -#include <libxml++/document.h> -#include <libxml++/parsers/domparser.h>  class CgiEnvironment;  class Session;  namespace cgicc { -	class HTTPContentHeader; +	class HTTPHeader; +} +namespace xmlpp { +	class Document;  }  class CgiApplicationEngine : public ApplicationEngine {  	public:  		typedef boost::shared_ptr<xmlpp::Document> XmlDocPtr; -		typedef boost::function1<void, xmlDocPtr> XmlWriter; +		typedef boost::shared_ptr<cgicc::HTTPHeader> HttpHeaderPtr;  		CgiApplicationEngine(const CgiEnvironment *);  		virtual ~CgiApplicationEngine();  		void process() const; -		const cgicc::HTTPContentHeader * getHeader() const { return header; } -		void write(const XmlWriter & w) const; +		void write(std::ostream &) const;  		const Environment * env() const;  		SessionPtr session() const;  		virtual Glib::ustring resolveCurrentConfig() const;  		void addAppData(const Presenter * p) const;  		const CgiEnvironment * _env; -	protected: -		mutable cgicc::HTTPContentHeader * header; -  	private:  		typedef std::pair<Glib::ustring, Glib::ustring> DomainPlatform;  		typedef std::list<DomainPlatform> DomainPlatforms; @@ -45,39 +41,84 @@ class CgiApplicationEngine : public ApplicationEngine {  		bool checkDomain(const DomainPlatforms::value_type & i) const;  		void loadEngineSection(const xmlpp::Element *) const; -		mutable XmlDocPtr doc; -  		class Stage;  		typedef boost::intrusive_ptr<Stage> StagePtr;  		class Stage : public virtual CommonObjects {  			public: -				Stage(const CgiApplicationEngine *); +				Stage();  				virtual ~Stage() = 0;  				virtual StagePtr run() = 0; -			protected: -				const CgiApplicationEngine * appEngine; +				virtual XmlDocPtr getDataDocument() const = 0; +				virtual HttpHeaderPtr getHeader() const = 0;  		}; -		class RequestStage : public Stage { +		class RequestStage : public Stage, public XmlPresenter {  			public: -				RequestStage(const CgiApplicationEngine *, const std::string & id); +				RequestStage(const std::string & id);  				virtual ~RequestStage(); +  				virtual StagePtr run(); -				std::string present; +				virtual XmlDocPtr getDataDocument() const; +				virtual HttpHeaderPtr getHeader() const; +				virtual const Glib::ustring & getResponseRootNodeName() const; +				virtual const Glib::ustring & getResponseStyle() const; +  			protected: +				std::string present;  				typedef Storage<ParamChecker>::Objects ParamCheckers;  				ParamCheckers parameterChecks;  				typedef Storage<NoOutputExecute>::Objects Tasks;  				Tasks tasks; + +			private: +				static const Glib::ustring resp; +				static const Glib::ustring style;  		}; -		class PresentStage : public Stage, public XmlPresenter { +		class PresentStage : public Stage, public XmlProcessPresenter {  			public: -				PresentStage(const CgiApplicationEngine *, const std::string & id); -				PresentStage(const CgiApplicationEngine *, const std::string & group, const std::string & id); +				PresentStage(const std::string & id);  				virtual ~PresentStage(); +		 +				virtual StagePtr run(); +				virtual XmlDocPtr getDataDocument() const; +				virtual HttpHeaderPtr getHeader() const; +		}; + +		class FailStage : public Stage, public XmlPresenter { +			public: +				FailStage(const CgiEnvironment *); +				virtual ~FailStage(); +		 +				virtual const Glib::ustring & getResponseStyle() const;  				virtual StagePtr run(); + +			protected: +				const CgiEnvironment * env; +		}; + +		class NotFoundStage : public FailStage { +			public: +				NotFoundStage(const CgiEnvironment *, const XmlScriptParser::NotFound &); +				virtual ~NotFoundStage(); +		 +				virtual XmlDocPtr getDataDocument() const; +				virtual HttpHeaderPtr getHeader() const; +				virtual const Glib::ustring & getResponseRootNodeName() const; +			private: +				static const Glib::ustring resp; +		}; + +		class ErrorStage : public FailStage { +			public: +				ErrorStage(const CgiEnvironment *, const std::exception &); +				virtual ~ErrorStage(); +				virtual XmlDocPtr getDataDocument() const; +				virtual HttpHeaderPtr getHeader() const; +				virtual const Glib::ustring & getResponseRootNodeName() const; +			private: +				static const Glib::ustring resp;  		};  		mutable StagePtr currentStage;  		mutable UUID sessionID; diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp index 322bdf7..fa40d2b 100644 --- a/project2/cgi/cgiCommon.cpp +++ b/project2/cgi/cgiCommon.cpp @@ -10,15 +10,6 @@  #include <boost/bind.hpp>  #include <cxxabi.h> -static -int -xmlWrite(void * _out, const char * buf, int len) -{ -	std::ostream * IO = static_cast<std::ostream*>(_out); -	IO->write(buf, len); -	return len; -} -  // These are templates because some people don't inherit their  // exceptions from std::exception like normal people (Glib)  const char * @@ -57,14 +48,8 @@ cgiServe(cgicc::CgiInput * i, std::ostream & IO)  		Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__);  		app.process(); -  		Logger()->messagef(LOG_DEBUG, "%s: Sending request result", __FUNCTION__); -		IO << "Cache-control: no-cache" << std::endl; -		app.getHeader()->render(IO); -		xmlOutputBufferPtr out = xmlOutputBufferCreateIO( -				xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8)); -		app.write(boost::bind(xmlSaveFileTo, out, _1, "utf-8")); - +		app.write(IO);  		Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__);  	}  	catch (const std::exception & e) { diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp index f858262..3fdb158 100644 --- a/project2/cgi/cgiEnvironment.cpp +++ b/project2/cgi/cgiEnvironment.cpp @@ -27,12 +27,16 @@ boost::program_options::options_description  CgiEnvironment::addOptions(boost::program_options::positional_options_description &)  {  	boost::program_options::options_description cgi("Project2 CGI options"); -#ifndef NDEBUG  	cgi.add_options() +		("errorcontenttype", boost::program_options::value<Glib::ustring>(&errorContentType)->default_value("text/xml"), +		 "The Content-Type to use in HTTP headers in event of an error") +		("errortransformstyle", boost::program_options::value<Glib::ustring>(&errorTransformStyle), +		 "The xml-stylesheet to specify in the data document in event of an error") +#ifndef NDEBUG  		("dumpdatadoc", boost::program_options::value<std::string>(&dumpdatadoc),  		 "Write a copy of the data document before sending it to the web server") -		;  #endif +		;  	return cgi;  } diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h index 1774417..c9b33fa 100644 --- a/project2/cgi/cgiEnvironment.h +++ b/project2/cgi/cgiEnvironment.h @@ -26,10 +26,12 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {  	private:  		boost::program_options::options_description addOptions(boost::program_options::positional_options_description &);  		void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &); -#ifndef NDEBUG  	public: +#ifndef NDEBUG  		std::string dumpdatadoc;  #endif +		Glib::ustring errorContentType; +		Glib::ustring errorTransformStyle;  };  #endif diff --git a/project2/commonObjects.cpp b/project2/commonObjects.cpp index fcf479c..b6a3b7d 100644 --- a/project2/commonObjects.cpp +++ b/project2/commonObjects.cpp @@ -1,7 +1,6 @@  #include "commonObjects.h"  #include "xmlObjectLoader.h" -#include <libxml++/parsers/domparser.h> -#include <libxml/xinclude.h> +#include "xmlScriptParser.h"  CommonObjects::~CommonObjects()  { @@ -22,8 +21,7 @@ CommonObjects::getSource(const std::string & name) const  CommonObjects::DataSources::index<bySOName>::type::const_iterator  CommonObjects::loadDataSource(const std::string & name) const  { -	xmlpp::DomParser xml("datasources/" + name + ".xml"); -	while (xmlXIncludeProcessFlags(xml.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); +	XmlScriptParser xml("datasources", name, true);  	LoaderBase loader("http://project2.randomdan.homeip.net", true);  	loader.supportedStorers.insert(Storer::into(&datasources)); diff --git a/project2/config.cpp b/project2/config.cpp index c3823ff..a3b9afe 100644 --- a/project2/config.cpp +++ b/project2/config.cpp @@ -2,8 +2,7 @@  #include "exceptions.h"  #include <boost/filesystem/operations.hpp>  #include <boost/foreach.hpp> -#include <libxml/xinclude.h> -#include <libxml++/parsers/domparser.h> +#include "xmlScriptParser.h"  SimpleMessageException(NoSuchPlatform);  SimpleMessageException(NoSuchConfigurationValue); @@ -24,8 +23,7 @@ Configuration::load() const  	if (!boost::filesystem::exists("config.xml")) {  		return;  	} -	xmlpp::DomParser configxml("config.xml"); -	while (xmlXIncludeProcessFlags(configxml.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); +	XmlScriptParser configxml("config.xml", true);  	xmlpp::NodeSet ps(configxml.get_document()->get_root_node()->find("platform"));  	BOOST_FOREACH(const xmlpp::Node * p, ps) {  		const xmlpp::Element * pe = dynamic_cast<const xmlpp::Element *>(p); diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index 7ef1ad0..e126793 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -2,8 +2,7 @@  #include "consoleEnvironment.h"  #include "../iterate.h"  #include "../xmlObjectLoader.h" -#include <libxml/xinclude.h> -#include <libxml++/parsers/domparser.h> +#include "../xmlScriptParser.h"  #include <boost/foreach.hpp>  SimpleMessageException(UnknownPlatformAlias); @@ -59,8 +58,7 @@ ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * en  	runtime(new ConsoleSession()),  	out(stdout, true)  { -	xmlpp::DomParser request(f.string()); -	while (xmlXIncludeProcessFlags(request.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); +	XmlScriptParser request(f.string(), false);  	LoaderBase loader("http://project2.randomdan.homeip.net", true);  	loader.supportedStorers.insert(Storer::into(¶meterChecks)); diff --git a/project2/exceptions.h b/project2/exceptions.h index b6c64ae..23faafc 100644 --- a/project2/exceptions.h +++ b/project2/exceptions.h @@ -17,6 +17,11 @@ class Name : public std::runtime_error { \  	public: \  		Name(const std::string & what) : std::runtime_error(what) { } \  } +#define SimpleMessageExceptionBase(Name, Base) \ +class Name : public Base { \ +	public: \ +		Name(const std::string & what) : Base(what) { } \ +}  #define SimpleNumericException(Name) \  class Name : public numeric_error { \  	public: \ diff --git a/project2/presenter.h b/project2/presenter.h index 6b75c5a..2391a29 100644 --- a/project2/presenter.h +++ b/project2/presenter.h @@ -4,7 +4,6 @@  #include <boost/intrusive_ptr.hpp>  #include <boost/shared_ptr.hpp>  #include <glibmm/ustring.h> -#include <libxml++/parsers/domparser.h>  #include "view.h"  #include "paramChecker.h"  #include "commonObjects.h" diff --git a/project2/sendmailTask.cpp b/project2/sendmailTask.cpp index b1e3bb6..e891fea 100644 --- a/project2/sendmailTask.cpp +++ b/project2/sendmailTask.cpp @@ -135,7 +135,7 @@ class TextContent : public SendMailTask::MailPart {  void  SendMailTask::execute() const  { -	XmlPresenterPtr p = new XmlPresenter("emails", present); +	XmlPresenterPtr p = new XmlProcessPresenter("emails", present, true);  	p->execute();  	XmlPresenter::XmlDocumentPtr data = p->getDataDocument();  #if DEBUG @@ -144,7 +144,7 @@ SendMailTask::execute() const  	typedef boost::shared_ptr<xsltStylesheet> XsltStyleSheetPtr;  	// Do transform -	XsltStyleSheetPtr cur = XsltStyleSheetPtr(xsltParseStylesheetFile(BAD_CAST p->responseStyle.c_str()), xsltFreeStylesheet); +	XsltStyleSheetPtr cur = XsltStyleSheetPtr(xsltParseStylesheetFile(BAD_CAST p->getResponseStyle().c_str()), xsltFreeStylesheet);  	if (!cur) {  		throw xmlpp::exception("Failed to load stylesheet");  	} diff --git a/project2/xmlPresenter.cpp b/project2/xmlPresenter.cpp index 906d2c9..244c96c 100644 --- a/project2/xmlPresenter.cpp +++ b/project2/xmlPresenter.cpp @@ -1,37 +1,59 @@  #include "xmlPresenter.h"  #include "xmlObjectLoader.h" -#include <libxml/xinclude.h>  #include "variables.h" +XmlPresenter::XmlPresenter() : +	responseDoc(XmlDocumentPtr(new xmlpp::Document("1.0"))) +{ +} +  XmlPresenter::~XmlPresenter()  {  } -XmlPresenter::XmlPresenter(const std::string & group, const std::string & file) : -	present(group + "/" + file + ".xml"), +void +XmlPresenter::initDoc() +{ +	nodeStack.push_back(responseDoc->create_root_node(getResponseRootNodeName())); +	xmlNewNs(nodeStack.back()->cobj(), BAD_CAST "http://project2.randomdan.homeip.net", BAD_CAST "project2"); +	// XSLT Style +	char * buf; +	if (!getResponseStyle().empty() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", +			getResponseStyle().c_str()) > 0) { +		xmlAddPrevSibling(nodeStack.back()->cobj(), +				xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf)); +		free(buf); +	} +} + +XmlProcessPresenter::XmlProcessPresenter(const std::string & group, const std::string & file, bool isInclusion) : +	present(group, file, isInclusion),  	responseRootNodeName(present.get_document()->get_root_node()->get_attribute_value("root")),  	responseStyle(present.get_document()->get_root_node()->get_attribute_value("style")), -	contentType(present.get_document()->get_root_node()->get_attribute_value("contenttype")), -	responseDoc(XmlDocumentPtr(new xmlpp::Document("1.0"))) +	contentType(present.get_document()->get_root_node()->get_attribute_value("contenttype"))  { -	while (xmlXIncludeProcessFlags(present.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); -  	LoaderBase loader("http://project2.randomdan.homeip.net", true);  	loader.supportedStorers.insert(Storer::into(&rowSets));  	loader.supportedStorers.insert(Storer::into(&views));  	loader.supportedStorers.insert(Storer::into(¶meterChecks));  	loader.collectAll(this, present.get_document()->get_root_node(), true); +	initDoc(); +} -	nodeStack.push_back(responseDoc->create_root_node(responseRootNodeName)); -	xmlNewNs(nodeStack.back()->cobj(), BAD_CAST "http://project2.randomdan.homeip.net", BAD_CAST "project2"); -	// XSLT Style -	char * buf; -	if (responseStyle.length() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", -			responseStyle.c_str()) > 0) { -		xmlAddPrevSibling(nodeStack.back()->cobj(), -				xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf)); -		free(buf); -	} +XmlProcessPresenter::~XmlProcessPresenter() +{ +} + +const Glib::ustring & +XmlProcessPresenter::getResponseRootNodeName() const +{ +	return responseRootNodeName; +} + +const Glib::ustring & +XmlProcessPresenter::getResponseStyle() const +{ +	return responseStyle;  }  XmlPresenter::XmlDocumentPtr diff --git a/project2/xmlPresenter.h b/project2/xmlPresenter.h index effa713..8ced38f 100644 --- a/project2/xmlPresenter.h +++ b/project2/xmlPresenter.h @@ -2,11 +2,16 @@  #define XMLPRESENTER_H  #include "presenter.h" +#include "xmlScriptParser.h" + +namespace xmlpp { +	class Document; +}  class XmlPresenter : public Presenter {  	public:  		typedef boost::shared_ptr<xmlpp::Document> XmlDocumentPtr; -		XmlPresenter(const std::string & group, const std::string & file); +		XmlPresenter();  		~XmlPresenter();  		void pushSub(const Glib::ustring & name, const Glib::ustring & ns) const; @@ -15,22 +20,33 @@ class XmlPresenter : public Presenter {  		void popSub() const;  		virtual XmlDocumentPtr getDataDocument() const; +		virtual const Glib::ustring & getResponseRootNodeName() const = 0; +		virtual const Glib::ustring & getResponseStyle() const = 0;  	protected: -		xmlpp::DomParser present; +		void initDoc(); +		XmlDocumentPtr responseDoc; + +	private: +		mutable std::vector<xmlpp::Element *> nodeStack; +}; +class XmlProcessPresenter : public XmlPresenter {  	public: -		const Glib::ustring responseRootNodeName; -		const Glib::ustring responseStyle; -		const Glib::ustring contentType; +		XmlProcessPresenter(const std::string & group, const std::string & file, bool isInclusion); +		~XmlProcessPresenter();  	protected: +		const Glib::ustring & getResponseRootNodeName() const; +		const Glib::ustring & getResponseStyle() const; + +		XmlScriptParser present;  		typedef Storage<ParamChecker>::Objects ParamCheckers;  		ParamCheckers parameterChecks; -	private: -		XmlDocumentPtr responseDoc; -		mutable std::vector<xmlpp::Element *> nodeStack; +		const Glib::ustring responseRootNodeName; +		const Glib::ustring responseStyle; +		const Glib::ustring contentType;  };  typedef boost::intrusive_ptr<XmlPresenter> XmlPresenterPtr; diff --git a/project2/xmlScriptParser.cpp b/project2/xmlScriptParser.cpp new file mode 100644 index 0000000..8db4049 --- /dev/null +++ b/project2/xmlScriptParser.cpp @@ -0,0 +1,40 @@ +#include "xmlScriptParser.h" +#include <libxml/xinclude.h> +#include <boost/filesystem/convenience.hpp> + +XmlScriptParser::XmlScriptParser(const std::string & group, const std::string & name, bool ii) : +	IsInclusion(ii) +{ +	loadDocument(group + "/" + name + ".xml"); +} + +XmlScriptParser::XmlScriptParser(const std::string & file, bool ii) : +	IsInclusion(ii) +{ +	loadDocument(file); +} + +void +XmlScriptParser::loadDocument(const std::string & file) +{ +	if (!boost::filesystem::exists(file)) { +		if (IsInclusion) { +			throw DependencyNotFound(file); +		} +		else { +			throw NotFound(file); +		} +	} +	try { +		parse_file(file); +	} +	catch (const xmlpp::internal_error &) { +		throw NotReadable(file); +	} +	for (int x; (x = xmlXIncludeProcessFlags(get_document()->cobj(), XML_PARSE_NOXINCNODE)); ) { +		if (x < 0) { +			throw IncludesError(file); +		} +	} +} + diff --git a/project2/xmlScriptParser.h b/project2/xmlScriptParser.h new file mode 100644 index 0000000..92d1bdb --- /dev/null +++ b/project2/xmlScriptParser.h @@ -0,0 +1,25 @@ +#ifndef XMLSCRIPTPARSER_H +#define XMLSCRIPTPARSER_H + +#include <libxml++/parsers/domparser.h> +#include "exceptions.h" + +class XmlScriptParser : public xmlpp::DomParser { +	public: +		SimpleMessageException(ParseError); +		SimpleMessageExceptionBase(NotFound, ParseError); +		SimpleMessageExceptionBase(DependencyNotFound, ParseError); +		SimpleMessageExceptionBase(NotReadable, ParseError); +		SimpleMessageExceptionBase(IncludesError, ParseError); + +		XmlScriptParser(const std::string & group, const std::string & name, bool isInclusion); +		XmlScriptParser(const std::string & file, bool isInclusion); + +		const bool IsInclusion; + +	private: +		void loadDocument(const std::string & file); +}; + +#endif + | 
