diff options
35 files changed, 333 insertions, 104 deletions
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 8d079f9..8093ef3 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -4,7 +4,6 @@  #include <cgicc/HTTPHeader.h>  #include "cgiEnvironment.h"  #include "iterate.h" -#include "logger.h"  #include <boost/bind.hpp>  #include <boost/foreach.hpp>  #include "ostreamWrapper.h" @@ -44,6 +43,43 @@ CgiApplicationEngine::env() const  	return _env;  } +class CgiResult : public TransformChainLink { +	public: +		CgiResult(CgiApplicationEngine::HttpHeaderPtr & h, std::ostream & s) : +			header(h), +			stream(s) { +		} +		CgiApplicationEngine::HttpHeaderPtr header; +		std::ostream & stream; +}; + +class WriteToCgiResult : public TransformImpl<WritableContent, CgiResult> { +	public: +		void transform(const WritableContent * wc, CgiResult * cr) const { +			cr->header->addHeader("Content-Type", wc->getContentType()); +			cr->header->render(cr->stream); +			wc->writeTo(cr->stream); +		} +}; +DECLARE_TRANSFORM(WriteToCgiResult); + +bool +addFinalTransformTarget(TransformSourcePtr ts, TransformChainLink * tcl) +{ +	if (ts->getTargets().empty()) { +		ts->addTarget(tcl, NULL); +		return true; +	} +	BOOST_FOREACH(const Targets::value_type & t, ts->getTargets()) { +		if (TransformSource * tr = dynamic_cast<TransformSource *>(t.first.get())) { +			if (addFinalTransformTarget(tr, tcl)) { +				return true; +			} +		} +	} +	return false; +} +  void  CgiApplicationEngine::process() const  { @@ -89,9 +125,9 @@ CgiApplicationEngine::process() const  		header->setCookie(cgicc::HTTPCookie(SESSIONID, cursession->ID.str(), "Session ID",  					_env->getServerName().substr(_env->getServerName().find(".")), env()->sessionTimeOut, "/", false));  	} -	header->render(IO);  	if (currentStage.get<2>()) {  		TransformSourcePtr ts = currentStage.get<2>(); +		addFinalTransformTarget(ts, new CgiResult(header, IO));  		std::fstream * ddd = NULL;  		if (!_env->dumpdatadoc.empty()) {  			ddd = new std::fstream(_env->dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out); @@ -99,12 +135,14 @@ CgiApplicationEngine::process() const  				ts->addTarget(new ostreamWrapper(*ddd));  			}  		} -		ts->addTarget(new ostreamWrapper(IO));  		ts->doTransforms();  		if (ddd) {  			delete ddd;  		}  	} +	else { +		header->render(IO); +	}  }  CgiApplicationEngine::Stage::Stage(const CgiEnvironment * env) : diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index e339576..80dad6e 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -13,6 +13,7 @@  #include <boost/intrusive_ptr.hpp>  #include <boost/tuple/tuple.hpp>  #include "cgiOutputOptions.h" +#include "cgiHttpHeader.h"  class CgiEnvironment;  class Session; @@ -23,7 +24,7 @@ namespace cgicc {  class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink {  	public: -		typedef boost::shared_ptr<cgicc::HTTPHeader> HttpHeaderPtr; +		typedef boost::shared_ptr<Project2HttpHeader> HttpHeaderPtr;  		CgiApplicationEngine(const CgiEnvironment *, std::ostream &);  		virtual ~CgiApplicationEngine(); @@ -94,9 +95,13 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink  		class PresentStage : public virtual ResponseStage, ViewHost {  			public:  				PresentStage(const CgiEnvironment * e, ScriptReaderPtr); -		 +				MultiRowSetPresenterPtr getPresenter() const; +  				virtual NextStage run();  				virtual HttpHeaderPtr getHeader() const; +			protected: +				mutable MultiRowSetPresenterPtr presenter; +				ScriptNodePtr root;  		};  		/// The built-in fail-safe not found stage diff --git a/project2/cgi/cgiHttpHeader.cpp b/project2/cgi/cgiHttpHeader.cpp index 20b20ea..b71a647 100644 --- a/project2/cgi/cgiHttpHeader.cpp +++ b/project2/cgi/cgiHttpHeader.cpp @@ -8,13 +8,6 @@ Project2HttpHeader::Project2HttpHeader(const std::string & s) :  	addHeader("Status", s);  } -Project2HttpHeader::Project2HttpHeader(const std::string & s, const std::string & t) : -	cgicc::HTTPHeader("") -{ -	addHeader("Status", s); -	addHeader("Content-Type", t); -} -  void  Project2HttpHeader::addHeader(const std::string & name, const Glib::ustring & value)  { diff --git a/project2/cgi/cgiHttpHeader.h b/project2/cgi/cgiHttpHeader.h index 87edde5..ffa5e70 100644 --- a/project2/cgi/cgiHttpHeader.h +++ b/project2/cgi/cgiHttpHeader.h @@ -10,7 +10,6 @@ class Project2HttpHeader : public cgicc::HTTPHeader {  	public:  		typedef std::map<std::string, const Glib::ustring> Headers;  		Project2HttpHeader(const std::string & s); -		Project2HttpHeader(const std::string & s, const std::string & t);  		void addHeader(const std::string & name, const Glib::ustring & value);  		void render(std::ostream & out) const;  	private: diff --git a/project2/cgi/cgiStageCustomError.cpp b/project2/cgi/cgiStageCustomError.cpp index 82fc6a1..eb66ff0 100644 --- a/project2/cgi/cgiStageCustomError.cpp +++ b/project2/cgi/cgiStageCustomError.cpp @@ -6,8 +6,8 @@  CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const CgiEnvironment * env, const std::exception & ex, ScriptReaderPtr s) :  	CgiApplicationEngine::ResponseStage(env), -	::CommonObjects(s), -	::CheckHost(s), +	::CommonObjects(s->root()), +	::CheckHost(s->root()),  	CgiApplicationEngine::DefaultErrorStage(env, ex),  	CgiApplicationEngine::PresentStage(env, s)  { diff --git a/project2/cgi/cgiStageCustomNotFound.cpp b/project2/cgi/cgiStageCustomNotFound.cpp index 8a224fa..e6520dd 100644 --- a/project2/cgi/cgiStageCustomNotFound.cpp +++ b/project2/cgi/cgiStageCustomNotFound.cpp @@ -6,8 +6,8 @@  CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const CgiEnvironment * env, const ScriptNotFound & notfound, ScriptReaderPtr s) :  	CgiApplicationEngine::ResponseStage(env), -	::CommonObjects(s), -	::CheckHost(s), +	::CommonObjects(s->root()), +	::CheckHost(s->root()),  	CgiApplicationEngine::DefaultNotFoundStage(env, notfound),  	CgiApplicationEngine::PresentStage(env, s)  { diff --git a/project2/cgi/cgiStageDefaultError.cpp b/project2/cgi/cgiStageDefaultError.cpp index ad27d2d..e464981 100644 --- a/project2/cgi/cgiStageDefaultError.cpp +++ b/project2/cgi/cgiStageDefaultError.cpp @@ -23,7 +23,7 @@ CgiApplicationEngine::DefaultErrorStage::~DefaultErrorStage()  CgiApplicationEngine::HttpHeaderPtr  CgiApplicationEngine::DefaultErrorStage::getHeader() const  { -	return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error", pres->contentType)); +	return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error"));  }  CgiApplicationEngine::NextStage diff --git a/project2/cgi/cgiStageDefaultNotFound.cpp b/project2/cgi/cgiStageDefaultNotFound.cpp index be32658..2cf0475 100644 --- a/project2/cgi/cgiStageDefaultNotFound.cpp +++ b/project2/cgi/cgiStageDefaultNotFound.cpp @@ -17,7 +17,7 @@ CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const CgiEnviro  CgiApplicationEngine::HttpHeaderPtr  CgiApplicationEngine::DefaultNotFoundStage::getHeader() const  { -	return HttpHeaderPtr(new Project2HttpHeader("404 Not found", pres->contentType)); +	return HttpHeaderPtr(new Project2HttpHeader("404 Not found"));  }  CgiApplicationEngine::NextStage diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp index 8eb0487..1330cdc 100644 --- a/project2/cgi/cgiStagePresent.cpp +++ b/project2/cgi/cgiStagePresent.cpp @@ -7,11 +7,13 @@  CgiApplicationEngine::PresentStage::PresentStage(const CgiEnvironment * e, ScriptReaderPtr s) :  	CgiApplicationEngine::ResponseStage(e), -	CommonObjects(s), -	CheckHost(s), -	ViewHost(s) +	CommonObjects(s->root()), +	CheckHost(s->root()), +	ViewHost(s->root()), +	root(s->root())  {  	s->loader.addLoadTarget(s->root(), Storer::into<OutputOptionsLoader>(&outputOptions)); +	s->loader.addLoadTarget(s->root(), Storer::into<PresenterLoader>(&presenter));  }  CgiApplicationEngine::NextStage @@ -19,7 +21,7 @@ CgiApplicationEngine::PresentStage::run()  {  	runChecks();  	try { -		executeViews(boost::bind(&PresenterLoader::createFrom, LoaderBase::getLoader<PresenterLoader, NotSupported>(e->defaultPresenter), _1)); +		executeViews();  		return NextStage(NULL, this, boost::dynamic_pointer_cast<TransformSource>(presenter), presenter);  	}  	catch (ResponseStagePtr p) { @@ -30,6 +32,15 @@ CgiApplicationEngine::PresentStage::run()  	}  } +MultiRowSetPresenterPtr +CgiApplicationEngine::PresentStage::getPresenter() const +{ +	if (!presenter) { +		presenter = LoaderBase::getLoader<PresenterLoader, NotSupported>(e->defaultPresenter)->createFrom(root); +	} +	return presenter; +} +  CgiApplicationEngine::ResponseStage::ResponseStage(const CgiEnvironment * e) :  	CgiApplicationEngine::Stage(e)  { @@ -38,8 +49,7 @@ CgiApplicationEngine::ResponseStage::ResponseStage(const CgiEnvironment * e) :  CgiApplicationEngine::HttpHeaderPtr  CgiApplicationEngine::PresentStage::getHeader() const  { -	const ContentPresenter * cp = dynamic_cast<const ContentPresenter *>(presenter.get()); -	Project2HttpHeader * header = new Project2HttpHeader("200 OK", cp ? cp->contentType : "text/plain; charset=UTF-8"); +	Project2HttpHeader * header = new Project2HttpHeader("200 OK");  	header->addHeader("Cache-control", "no-cache");  	return HttpHeaderPtr(header);  } diff --git a/project2/cgi/cgiStageRequest.cpp b/project2/cgi/cgiStageRequest.cpp index ac8516b..d505f3c 100644 --- a/project2/cgi/cgiStageRequest.cpp +++ b/project2/cgi/cgiStageRequest.cpp @@ -7,10 +7,10 @@  CgiApplicationEngine::RequestStage::RequestStage(const CgiEnvironment * e, ScriptReaderPtr s) :  	SourceObject(s->root()), -	CommonObjects(s), -	::CheckHost(s), +	CommonObjects(s->root()), +	::CheckHost(s->root()),  	CgiApplicationEngine::ResponseStage(e), -	::TaskHost(s), +	::TaskHost(s->root()),  	present(s->root()->value("present","").as<std::string>())  {  } @@ -23,11 +23,10 @@ CgiApplicationEngine::RequestStage::run()  	return NextStage(present.empty() ? NULL : new PresentStage(e, e->resolveScript(e->presentRoot, present, false)), this);  } -const std::string contentType = "text/plain";  CgiApplicationEngine::HttpHeaderPtr  CgiApplicationEngine::RequestStage::getHeader() const  { -	Project2HttpHeader * header = new Project2HttpHeader("200 OK", contentType); +	Project2HttpHeader * header = new Project2HttpHeader("200 OK");  	header->addHeader("Cache-control", "no-cache");  	return HttpHeaderPtr(header);  } diff --git a/project2/common/checkHost.cpp b/project2/common/checkHost.cpp index be7b572..49533a9 100644 --- a/project2/common/checkHost.cpp +++ b/project2/common/checkHost.cpp @@ -3,10 +3,10 @@  #include "appEngine.h"  #include <boost/foreach.hpp> -CheckHost::CheckHost(ScriptReaderPtr s) : +CheckHost::CheckHost(ScriptNodePtr s) :  	CommonObjects(s)  { -	s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(&checks)); +	s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&checks));  }  CheckHost::~CheckHost() diff --git a/project2/common/checkHost.h b/project2/common/checkHost.h index 0721ac5..edc2cd8 100644 --- a/project2/common/checkHost.h +++ b/project2/common/checkHost.h @@ -15,7 +15,7 @@ class CheckHost : virtual public CommonObjects {  				~CheckFailure() throw();  				const CheckCPtr failedCheck;  		}; -		CheckHost(ScriptReaderPtr script);  +		CheckHost(ScriptNodePtr script);   		~CheckHost();  		void runChecks() const; diff --git a/project2/common/commonObjects.cpp b/project2/common/commonObjects.cpp index 041b4ef..b615b62 100644 --- a/project2/common/commonObjects.cpp +++ b/project2/common/commonObjects.cpp @@ -8,10 +8,10 @@ CommonObjects::CommonObjects()  {  } -CommonObjects::CommonObjects(ScriptReaderPtr s) : -	script(s) +CommonObjects::CommonObjects(ScriptNodePtr s) : +	script(s->script)  { -	s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(&rowSets)); +	s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&rowSets));  }  CommonObjects::~CommonObjects() diff --git a/project2/common/commonObjects.h b/project2/common/commonObjects.h index 6c587c4..5c4b574 100644 --- a/project2/common/commonObjects.h +++ b/project2/common/commonObjects.h @@ -14,7 +14,7 @@ class CommonObjects : public virtual IntrusivePtrBase {  		SimpleMessageException(DataSourceNotCompatible);  		CommonObjects(); -		CommonObjects(ScriptReaderPtr script); +		CommonObjects(ScriptNodePtr script);  		~CommonObjects();  		RowSetPtr getSource(const std::string &) const; diff --git a/project2/common/scriptLoader.cpp b/project2/common/scriptLoader.cpp index 6a0f0b3..3d34d55 100644 --- a/project2/common/scriptLoader.cpp +++ b/project2/common/scriptLoader.cpp @@ -98,7 +98,7 @@ LoaderBase::collectAll(ScriptNodePtr node, bool childrenOnly, const StorerPtrs &  			throw NotSupported(name);  		}  		BOOST_FOREACH(const StorerPtr & s, sts) { -			if (s->save(o, name)) { +			if (s->save(o, node)) {  				stored += 1;  				break;  			} diff --git a/project2/common/scriptStorage.h b/project2/common/scriptStorage.h index 1c5ed1e..14ebe6e 100644 --- a/project2/common/scriptStorage.h +++ b/project2/common/scriptStorage.h @@ -35,7 +35,7 @@ class Storer : public virtual IntrusivePtrBase {  		static StorerPtr into(ANONORDEREDSTORAGEOF(X) * list);  		virtual boost::intrusive_ptr<IntrusivePtrBase> create(ScriptNodePtr) const = 0; -		virtual bool save(boost::intrusive_ptr<IntrusivePtrBase>, const Glib::ustring &) = 0; +		virtual bool save(boost::intrusive_ptr<IntrusivePtrBase>, ScriptNodePtr) = 0;  };  template <class X, class L> @@ -44,11 +44,11 @@ class StorerBase : public Storer {  		boost::intrusive_ptr<IntrusivePtrBase> create(ScriptNodePtr p) const {  			return LoaderBase::getLoader<L, NotSupported>(p->get_name())->createFrom(p);  		} -		bool save(boost::intrusive_ptr<IntrusivePtrBase> o, const Glib::ustring & name) { +		bool save(boost::intrusive_ptr<IntrusivePtrBase> o, ScriptNodePtr name) {  			boost::intrusive_ptr<X> O = boost::dynamic_pointer_cast<X>(o);  			if (O) {  				if (!insert(O)) { -					throw StoreFailed(name); +					throw StoreFailed(name->get_name());  				}  			}  			return O; diff --git a/project2/common/taskHost.cpp b/project2/common/taskHost.cpp index 1b4e929..72fedad 100644 --- a/project2/common/taskHost.cpp +++ b/project2/common/taskHost.cpp @@ -7,13 +7,13 @@  #include "commonObjects.h"  #include <boost/foreach.hpp> -TaskHost::TaskHost(ScriptReaderPtr s) : -	SourceObject(s->root()), +TaskHost::TaskHost(ScriptNodePtr s) : +	SourceObject(s),  	CommonObjects(s),  	CheckHost(s), -	IHaveSubTasks(s->root()) +	IHaveSubTasks(s)  { -	s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(&tasks)); +	s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&tasks));  }  TaskHost::~TaskHost() diff --git a/project2/common/taskHost.h b/project2/common/taskHost.h index e4cc443..edecda6 100644 --- a/project2/common/taskHost.h +++ b/project2/common/taskHost.h @@ -11,7 +11,7 @@ class DataSource;  class TaskHost : public IHaveSubTasks, virtual public CheckHost, virtual public CommonObjects {  	protected: -		TaskHost(ScriptReaderPtr script); +		TaskHost(ScriptNodePtr script);  		virtual ~TaskHost();  		void loadComplete(const CommonObjects *); diff --git a/project2/common/transform.cpp b/project2/common/transform.cpp index 0dafcd5..202da6a 100644 --- a/project2/common/transform.cpp +++ b/project2/common/transform.cpp @@ -3,6 +3,37 @@  #include "logger.h"  #include <boost/foreach.hpp> +class TransformTargetStorer : public Storer { +	public: +		TransformTargetStorer(TransformSource * ts) : +			transformSource(ts) +		{ +		} +		boost::intrusive_ptr<IntrusivePtrBase> create(ScriptNodePtr p) const +		{ +			return LoaderBase::getLoader<TransformTargetLoader, NotSupported>(p->get_name())->createFrom(p); +		} +		bool save(boost::intrusive_ptr<IntrusivePtrBase> o, ScriptNodePtr s) +		{ +			TransformChainLinkPtr O = boost::dynamic_pointer_cast<TransformChainLink>(o); +			if (O) { +				transformSource->addTarget(O, s); +			} +			return O; +		} +	private: +		TransformSource * transformSource; +}; + +TransformSource::TransformSource() +{ +} + +TransformSource::TransformSource(ScriptNodePtr s) +{ +	s->script->loader.addLoadTarget(s, new TransformTargetStorer(this)); +} +  TransformChainLink::~TransformChainLink()  {  } @@ -24,7 +55,6 @@ TransformSource::addTarget(TransformChainLinkPtr tcl, ScriptNodePtr e)  	throw NotSupported("Couldn't find a suitable transformation");  } -typedef std::map<TransformChainLinkPtr, TransformPtr> Targets;  void  TransformSource::doTransforms() const  { @@ -36,3 +66,9 @@ TransformSource::doTransforms() const  	}  } +const Targets & +TransformSource::getTargets() const +{ +	return targets; +} + diff --git a/project2/common/transform.h b/project2/common/transform.h index 42f4d4d..175bf42 100644 --- a/project2/common/transform.h +++ b/project2/common/transform.h @@ -15,19 +15,25 @@ typedef boost::intrusive_ptr<TransformChainLink> TransformChainLinkPtr;  class Transform;  typedef boost::intrusive_ptr<Transform> TransformPtr; +typedef std::map<TransformChainLinkPtr, TransformPtr> Targets;  class TransformSource : public TransformChainLink {  	public: +		TransformSource(); +		TransformSource(ScriptNodePtr);  		void addTarget(TransformChainLinkPtr, ScriptNodePtr e = NULL);  		void doTransforms() const; +		const Targets & getTargets() const;  	private:  		virtual const TransformChainLink * object() const { return this; } -		std::map<TransformChainLinkPtr, TransformPtr> targets; +		Targets targets;  };  typedef boost::intrusive_ptr<TransformSource> TransformSourcePtr;  template <class X>  class SourceOf : public virtual TransformSource {  	public: +		SourceOf() { } +		SourceOf(ScriptNodePtr s) : TransformSource(s) { }  		virtual operator const X * () const = 0;  }; @@ -52,6 +58,20 @@ class TransformLoaderImpl : public TransformLoader {  };  #define DECLARE_TRANSFORM(T) DECLARE_COMPONENT_LOADER(#T, T, TransformLoader) +class TransformTargetLoader : public ComponentLoader { +	public: +		virtual boost::intrusive_ptr<TransformChainLink> createFrom(ScriptNodePtr) const = 0; +}; + +template <class T> +class TransformTargetLoaderImpl : public TransformTargetLoader { +	public: +		boost::intrusive_ptr<TransformChainLink> createFrom(ScriptNodePtr s) const { +			return new T(s); +		} +}; +#define DECLARE_TRANSFORMTARGET(N, T) DECLARE_COMPONENT_LOADER(N, T, TransformTargetLoader) +  template <class Source, class Destination>  class TransformImpl : public Transform {  	public: @@ -66,5 +86,11 @@ class TransformImpl : public Transform {  		}  }; +class WritableContent { +	public: +		virtual Glib::ustring getContentType() const = 0; +		virtual void writeTo(std::ostream &) const = 0; +}; +  #endif diff --git a/project2/common/viewHost.cpp b/project2/common/viewHost.cpp index 4c19370..64a8c8b 100644 --- a/project2/common/viewHost.cpp +++ b/project2/common/viewHost.cpp @@ -5,13 +5,11 @@  #include <boost/foreach.hpp>  #include <iostream> -ViewHost::ViewHost(ScriptReaderPtr s) : +ViewHost::ViewHost(ScriptNodePtr s) :  	CommonObjects(s), -	CheckHost(s), -	root(s->root()) +	CheckHost(s)  { -	s->loader.addLoadTarget(root, Storer::into<ElementLoader>(&views)); -	s->loader.addLoadTarget(root, Storer::into<PresenterLoader>(&presenter)); +	s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&views));  }  ViewHost::~ViewHost() @@ -19,14 +17,11 @@ ViewHost::~ViewHost()  }  void -ViewHost::executeViews(const DefaultPresenterProvider & dpp) const +ViewHost::executeViews() const  {  	loadScriptComponents(); -	if (!presenter) { -		presenter = dpp(root); -		root.reset(); -	} +	MultiRowSetPresenterPtr presenter = getPresenter();  	BOOST_FOREACH(const Views::value_type & s, views) {  		s->execute(presenter.get());  	} @@ -39,6 +34,7 @@ ViewHost::executeViews(const DefaultPresenterProvider & dpp) const  void  ViewHost::doTransforms() const  { +	MultiRowSetPresenterPtr presenter = getPresenter();  	TransformSourcePtr ts = boost::dynamic_pointer_cast<TransformSource>(presenter);  	if (ts) {  		ts->doTransforms(); diff --git a/project2/common/viewHost.h b/project2/common/viewHost.h index a1468ed..d09f1af 100644 --- a/project2/common/viewHost.h +++ b/project2/common/viewHost.h @@ -10,19 +10,18 @@  class ViewHost : virtual public CheckHost, virtual public CommonObjects {  	public: -		typedef boost::function1<MultiRowSetPresenterPtr, ScriptNodePtr> DefaultPresenterProvider; - -		ViewHost(ScriptReaderPtr script);  +		ViewHost(ScriptNodePtr script);   		~ViewHost(); -		void executeViews(const DefaultPresenterProvider &) const; +		void executeViews() const;  		void doTransforms() const; -		mutable MultiRowSetPresenterPtr presenter; + +	protected: +		virtual MultiRowSetPresenterPtr getPresenter() const = 0;  	private:  		typedef ANONORDEREDSTORAGEOF(View) Views;  		Views views; -		mutable ScriptNodePtr root;  };  typedef boost::intrusive_ptr<ViewHost> ViewHostPtr; diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index 7643cad..a546aca 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -14,12 +14,13 @@ SimpleMessageException(UnknownPlatformAlias);  ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * env, ScriptReaderPtr script) :  	SourceObject(script->root()), -	CommonObjects(script), -	CheckHost(script), -	TaskHost(script), -	ViewHost(script), +	CommonObjects(script->root()), +	CheckHost(script->root()), +	TaskHost(script->root()), +	ViewHost(script->root()),  	_env(env), -	runtime(new Session(UUID::generate_random())) +	runtime(new Session(UUID::generate_random())), +	presenter(new ConsolePresenter())  {  } @@ -33,7 +34,7 @@ ConsoleApplicationEngine::process() const  	try {  		runChecks();  		execute(); -		executeViews(boost::bind(&PresenterLoader::createFrom, LoaderBase::getLoader<PresenterLoader, NotSupported>("console"), _1)); +		executeViews();  		addAppData(presenter.get());  	}  	catch (const std::exception & e) { @@ -48,6 +49,12 @@ ConsoleApplicationEngine::process() const  	}  } +MultiRowSetPresenterPtr +ConsoleApplicationEngine::getPresenter() const +{ +	return presenter; +} +  const Environment *  ConsoleApplicationEngine::env() const  { diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h index a0f72e5..4368c6b 100644 --- a/project2/console/consoleAppEngine.h +++ b/project2/console/consoleAppEngine.h @@ -25,6 +25,7 @@ class ConsoleApplicationEngine : public ApplicationEngine, TaskHost, ViewHost {  	protected:  		const ConsoleEnvironment * _env; +		MultiRowSetPresenterPtr getPresenter() const;  	private:  		typedef std::map<Glib::ustring, const Glib::ustring> ConsolePlatforms; @@ -32,6 +33,7 @@ class ConsoleApplicationEngine : public ApplicationEngine, TaskHost, ViewHost {  	private:  		SessionPtr runtime; +		MultiRowSetPresenterPtr presenter;  };  #endif diff --git a/project2/console/consolePresenter.cpp b/project2/console/consolePresenter.cpp index 33a7af9..3a8bf11 100644 --- a/project2/console/consolePresenter.cpp +++ b/project2/console/consolePresenter.cpp @@ -2,9 +2,7 @@  #include <stdio.h>  #include "consolePresenter.h" -DECLARE_COMPONENT_LOADER("console", ConsolePresenter, PresenterLoader) - -ConsolePresenter::ConsolePresenter(ScriptNodePtr) : +ConsolePresenter::ConsolePresenter() :  	indent(0),  	out(stdout, true)  { diff --git a/project2/console/consolePresenter.h b/project2/console/consolePresenter.h index 6122f7f..2a67727 100644 --- a/project2/console/consolePresenter.h +++ b/project2/console/consolePresenter.h @@ -6,7 +6,7 @@  class ConsolePresenter : public Presenter {  	public: -		ConsolePresenter(ScriptNodePtr); +		ConsolePresenter();  		void pushSub(const Glib::ustring & ns, const Glib::ustring & name) const;  		void addAttribute(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const;  		void addNamedValue(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const; diff --git a/project2/json/presenter.cpp b/project2/json/presenter.cpp index 3b069a4..aaa72bf 100644 --- a/project2/json/presenter.cpp +++ b/project2/json/presenter.cpp @@ -5,10 +5,13 @@  #include "transform.h"  #include <stack> -class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, public SourceOf<json::Object> { +class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, public SourceOf<json::Object>, public WritableContent, public SourceOf<WritableContent> {  	public: -		JsonPresenter(ScriptNodePtr) : -			ContentPresenter("application/json; charset=UTF-8") { +		JsonPresenter(ScriptNodePtr s) : +			TransformSource(s), +			ContentPresenter("application/json; charset=UTF-8"), +			SourceOf<json::Object>(s), +			SourceOf<WritableContent>(s) {  			curRowSet.push(&object);  		}  		void addNamedValue(const Glib::ustring & name, const VariableType & value) const { @@ -43,6 +46,17 @@ class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, publ  		operator const json::Object *() const {  			return &object;  		} +		operator const WritableContent * () const +		{ +			return this; +		} +		Glib::ustring getContentType() const { +			return contentType; +		} +		void writeTo(std::ostream & o) const { +			serializeObject(object, o); +		} +  	private:  		mutable json::Object object;  		mutable std::stack<json::Object *> curRowSet; diff --git a/project2/mail/sendmailTask.cpp b/project2/mail/sendmailTask.cpp index 447b8f9..2fc77fa 100644 --- a/project2/mail/sendmailTask.cpp +++ b/project2/mail/sendmailTask.cpp @@ -188,19 +188,33 @@ class TransformTextToEmail : public TransformImpl<TextDocument, SendMailTask::Pa  };  DECLARE_TRANSFORM(TransformTextToEmail); -PresenterPtr -SendMailTask::createDefaultPresenter(ScriptNodePtr n) const -{ -	Logger()->message(LOG_DEBUG, "Building default email transform chain"); -	XmlPresenterPtr xpp = new XmlPresenter(n); -	HtmlDocument * hd = new HtmlDocument(); -	TextDocument * td = new TextDocument(); -	xpp->addTarget(hd, n); -	hd->addTarget(parts); -	hd->addTarget(td, n); -	td->addTarget(parts); -	return xpp; -} +class EmailViewHost : public ViewHost { +	public: +		EmailViewHost(boost::intrusive_ptr<SendMailTask::Parts> & ps, ScriptNodePtr node) : +			CheckHost(node), +			ViewHost(node), +			parts(ps), +			n(node) { +		} +		MultiRowSetPresenterPtr getPresenter() const { +			if (!presenter) { +				Logger()->message(LOG_DEBUG, "Building default email transform chain"); +				XmlPresenterPtr xpp = new XmlPresenter(n); +				HtmlDocument * hd = new HtmlDocument(n); +				TextDocument * td = new TextDocument(n); +				xpp->addTarget(hd, n); +				hd->addTarget(parts); +				hd->addTarget(td, n); +				td->addTarget(parts); +				presenter = xpp; +			} +			return presenter; +		} +	private: +		boost::intrusive_ptr<SendMailTask::Parts> & parts; +		ScriptNodePtr n; +		mutable MultiRowSetPresenterPtr presenter; +};  void  SendMailTask::execute() const @@ -215,8 +229,8 @@ SendMailTask::execute() const  	parts->parts.insert(new Header("Content-Transfer-Encoding", "binary"));  	parts->parts.insert(new BoundaryEnd()); -	ViewHostPtr vsp = new ViewHost(Environment::getCurrent()->resolveScript("emails", present(), false)); -	vsp->executeViews(boost::bind(&SendMailTask::createDefaultPresenter, this, _1)); +	ViewHostPtr vsp = new EmailViewHost(parts, Environment::getCurrent()->resolveScript("emails", present(), false)->root()); +	vsp->executeViews();  	vsp->doTransforms();  	part = parts->parts.begin(); diff --git a/project2/xml/transformHtml.cpp b/project2/xml/transformHtml.cpp index ebde94b..54919ef 100644 --- a/project2/xml/transformHtml.cpp +++ b/project2/xml/transformHtml.cpp @@ -1,10 +1,45 @@  #include <pch.hpp>  #include "transformHtml.h" -#include "logger.h"  #include <libxml++/document.h>  #include <libxslt/xsltutils.h>  #include <libxslt/transform.h> +HtmlDocument::HtmlDocument(ScriptNodePtr s) : +	TransformSource(s), +	SourceOf<HtmlDocument>(s), +	SourceOf<WritableContent>(s), +	contentType(s, "contenttype", "text/html; charset=utf-8") +{ +} + +HtmlDocument::operator const HtmlDocument * () const { return this; } +HtmlDocument::operator const WritableContent * () const { return this; } + +int	xmlstrmclosecallback(void * context) +{ +	((std::ostream*)context)->flush(); +	return 0; +} +int	xmlstrmwritecallback(void * context, const char * buffer, int len) +{ +	((std::ostream*)context)->write(buffer, len); +	return len; +} + +void +HtmlDocument::writeTo(std::ostream & o) const +{ +	xmlOutputBufferPtr buf = xmlOutputBufferCreateIO(xmlstrmwritecallback, xmlstrmclosecallback, &o, NULL); +	htmlDocContentDumpFormatOutput(buf, doc, "utf-8", 0); +	xmlOutputBufferClose(buf); +} + +Glib::ustring +HtmlDocument::getContentType() const +{ +	return contentType(); +} +  class TransformXmlToHtml : public TransformImpl<xmlpp::Document, HtmlDocument> {  	public:  		void transform(const xmlpp::Document * cdata, HtmlDocument * result) const @@ -27,5 +62,7 @@ class TransformXmlToHtml : public TransformImpl<xmlpp::Document, HtmlDocument> {  	private:  		Glib::ustring stylesheet;  }; +  DECLARE_TRANSFORM(TransformXmlToHtml) +DECLARE_TRANSFORMTARGET("htmldocument", HtmlDocument) diff --git a/project2/xml/transformHtml.h b/project2/xml/transformHtml.h index 25bd0d5..8a34f2f 100644 --- a/project2/xml/transformHtml.h +++ b/project2/xml/transformHtml.h @@ -4,11 +4,15 @@  #include "transform.h"  #include <libxml/HTMLtree.h> -class HtmlDocument; -class HtmlDocument : public SourceOf<HtmlDocument> { +class HtmlDocument : public SourceOf<HtmlDocument>, public WritableContent, public SourceOf<WritableContent> {  	public: +		HtmlDocument(ScriptNodePtr);  		htmlDocPtr doc; -		operator const HtmlDocument * () const { return this; } +		operator const HtmlDocument * () const; +		operator const WritableContent * () const; +		Glib::ustring getContentType() const; +		void writeTo(std::ostream &) const; +		Variable contentType;  };  #endif diff --git a/project2/xml/transformText.cpp b/project2/xml/transformText.cpp index bec1a95..6bc43a7 100644 --- a/project2/xml/transformText.cpp +++ b/project2/xml/transformText.cpp @@ -5,6 +5,30 @@  #include <sys/wait.h>  #include <misc.h> +TextDocument::TextDocument(ScriptNodePtr s) : +	TransformSource(s), +	SourceOf<TextDocument>(s), +	SourceOf<WritableContent>(s), +	contentType(s, "contenttype", "text/plain; charset=utf-8") +{ +} + +TextDocument::operator const TextDocument * () const { return this; } +TextDocument::operator const WritableContent * () const { return this; } + +void +TextDocument::writeTo(std::ostream & o) const +{ +	o << doc; +} + +Glib::ustring +TextDocument::getContentType() const +{ +	return contentType(); +} + +  class TransformHtmlToText : public TransformImpl<HtmlDocument, TextDocument> {  	public:  		void transform(const HtmlDocument * cdoc, TextDocument * str) const @@ -16,7 +40,7 @@ class TransformHtmlToText : public TransformImpl<HtmlDocument, TextDocument> {  #ifdef STRACE_LYNX  				"/usr/bin/strace", "-o", "/tmp/lynx",  #endif -				"/usr/bin/lynx", "-dump", "-stdin", "-width=105", NULL }; +				"/usr/bin/lynx", "-dump", "-stdin", "-width=105", "-nonumbers", "-nolist", NULL };  			popenrw(callLynx, fds);  			FILE * lynxIn = fdopen(fds[0], "w");  			FILE * lynxOut = fdopen(fds[1], "r"); @@ -35,5 +59,7 @@ class TransformHtmlToText : public TransformImpl<HtmlDocument, TextDocument> {  			}  		}  }; +  DECLARE_TRANSFORM(TransformHtmlToText); +DECLARE_TRANSFORMTARGET("textdocument", TextDocument) diff --git a/project2/xml/transformText.h b/project2/xml/transformText.h index 9a81c89..07eb583 100644 --- a/project2/xml/transformText.h +++ b/project2/xml/transformText.h @@ -4,12 +4,16 @@  #include "transform.h"  #include <string> -class TextDocument : public SourceOf<TextDocument> { +class TextDocument : public SourceOf<TextDocument>, public WritableContent, public SourceOf<WritableContent> {  	public: +		TextDocument(ScriptNodePtr);  		std::string doc; -		operator const TextDocument * () const { return this; } +		operator const TextDocument * () const; +		operator const WritableContent * () const; +		Glib::ustring getContentType() const; +		void writeTo(std::ostream &) const; +		Variable contentType;  }; -  #endif diff --git a/project2/xml/transformXml.cpp b/project2/xml/transformXml.cpp index d1e58b5..fb115f1 100644 --- a/project2/xml/transformXml.cpp +++ b/project2/xml/transformXml.cpp @@ -3,12 +3,12 @@  #include <libxml++/document.h>  #include "ostreamWrapper.h" -class TransformXmlToHttpStream : public TransformImpl<xmlpp::Document, ostreamWrapper> { +class TransformXmlToStdStream : public TransformImpl<xmlpp::Document, ostreamWrapper> {  	public:  		void transform(const xmlpp::Document * doc, ostreamWrapper * o) const  		{  			const_cast<xmlpp::Document *>(doc)->write_to_stream_formatted(o->strm, "UTF-8");  		}  }; -DECLARE_TRANSFORM(TransformXmlToHttpStream); +DECLARE_TRANSFORM(TransformXmlToStdStream); diff --git a/project2/xml/xmlPresenter.cpp b/project2/xml/xmlPresenter.cpp index 70cb743..e9d9a18 100644 --- a/project2/xml/xmlPresenter.cpp +++ b/project2/xml/xmlPresenter.cpp @@ -17,10 +17,15 @@ XmlPresenter::XmlPresenter(const Glib::ustring & responseRootNodeName, const Gli  }  XmlPresenter::XmlPresenter(ScriptNodePtr e) : +	TransformSource(e),  	ContentPresenter(e->value("contenttype", "")), +	SourceOf<xmlpp::Document>(e), +	SourceOf<_xmlDoc>(e), +	SourceOf<boost::shared_ptr<xmlpp::Document> >(e), +	SourceOf<WritableContent>(e),  	responseDoc(XmlDocumentPtr(new xmlpp::Document("1.0")))  { -	createDoc(e->value("root", ""), e->value("style", "")); +	createDoc(e->value("root"), e->value("style", ""));  }  XmlPresenter::~XmlPresenter() @@ -58,6 +63,11 @@ XmlPresenter::operator const xmlDoc * () const  	return responseDoc->cobj();  } +XmlPresenter::operator const WritableContent * () const +{ +	return this; +} +  void  XmlPresenter::declareNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const  { @@ -136,3 +146,12 @@ XmlPresenter::popSub() const  	nodeStack.pop_back();  } +Glib::ustring +XmlPresenter::getContentType() const { +	return contentType; +} + +void +XmlPresenter::writeTo(std::ostream & o) const { +	responseDoc->write_to_stream_formatted(o, "UTF-8"); +} diff --git a/project2/xml/xmlPresenter.h b/project2/xml/xmlPresenter.h index 38244be..0671548 100644 --- a/project2/xml/xmlPresenter.h +++ b/project2/xml/xmlPresenter.h @@ -10,7 +10,7 @@ namespace xmlpp {  	class Element;  } -class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf<xmlpp::Document>, public SourceOf<xmlDoc>, public SourceOf<boost::shared_ptr<xmlpp::Document> > { +class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf<xmlpp::Document>, public SourceOf<xmlDoc>, public SourceOf<boost::shared_ptr<xmlpp::Document> >, public WritableContent, public SourceOf<WritableContent> {  	public:  		typedef boost::shared_ptr<xmlpp::Document> XmlDocumentPtr;  		XmlPresenter(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle, const Glib::ustring & contentType); @@ -27,6 +27,9 @@ class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf<  		operator const xmlpp::Document * () const;  		operator const xmlDoc * () const;  		operator const boost::shared_ptr<xmlpp::Document> * () const; +		operator const WritableContent * () const; +		Glib::ustring getContentType() const; +		void writeTo(std::ostream &) const;  	private:  		void createDoc(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle) const;  | 
