From c6f5af306ed3dea3e86c5ad8c7a98ceebd69bb4f Mon Sep 17 00:00:00 2001 From: randomdan Date: Sun, 1 Jan 2012 04:26:45 +0000 Subject: Regeneralise some code Fully customisable output chain Minor supporting tweaks here and there --- project2/cgi/cgiAppEngine.cpp | 44 +++++++++++++++++++++++++++++--- project2/cgi/cgiAppEngine.h | 9 +++++-- project2/cgi/cgiHttpHeader.cpp | 7 ----- project2/cgi/cgiHttpHeader.h | 1 - project2/cgi/cgiStageCustomError.cpp | 4 +-- project2/cgi/cgiStageCustomNotFound.cpp | 4 +-- project2/cgi/cgiStageDefaultError.cpp | 2 +- project2/cgi/cgiStageDefaultNotFound.cpp | 2 +- project2/cgi/cgiStagePresent.cpp | 22 +++++++++++----- project2/cgi/cgiStageRequest.cpp | 9 +++---- project2/common/checkHost.cpp | 4 +-- project2/common/checkHost.h | 2 +- project2/common/commonObjects.cpp | 6 ++--- project2/common/commonObjects.h | 2 +- project2/common/scriptLoader.cpp | 2 +- project2/common/scriptStorage.h | 6 ++--- project2/common/taskHost.cpp | 8 +++--- project2/common/taskHost.h | 2 +- project2/common/transform.cpp | 38 ++++++++++++++++++++++++++- project2/common/transform.h | 28 +++++++++++++++++++- project2/common/viewHost.cpp | 16 +++++------- project2/common/viewHost.h | 11 ++++---- project2/console/consoleAppEngine.cpp | 19 +++++++++----- project2/console/consoleAppEngine.h | 2 ++ project2/console/consolePresenter.cpp | 4 +-- project2/console/consolePresenter.h | 2 +- project2/json/presenter.cpp | 20 ++++++++++++--- project2/mail/sendmailTask.cpp | 44 +++++++++++++++++++++----------- project2/xml/transformHtml.cpp | 39 +++++++++++++++++++++++++++- project2/xml/transformHtml.h | 10 +++++--- project2/xml/transformText.cpp | 28 +++++++++++++++++++- project2/xml/transformText.h | 10 +++++--- project2/xml/transformXml.cpp | 4 +-- project2/xml/xmlPresenter.cpp | 21 ++++++++++++++- project2/xml/xmlPresenter.h | 5 +++- 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 #include "cgiEnvironment.h" #include "iterate.h" -#include "logger.h" #include #include #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 { + 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(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 #include #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 HttpHeaderPtr; + typedef boost::shared_ptr 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 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(&outputOptions)); + s->loader.addLoadTarget(s->root(), Storer::into(&presenter)); } CgiApplicationEngine::NextStage @@ -19,7 +21,7 @@ CgiApplicationEngine::PresentStage::run() { runChecks(); try { - executeViews(boost::bind(&PresenterLoader::createFrom, LoaderBase::getLoader(e->defaultPresenter), _1)); + executeViews(); return NextStage(NULL, this, boost::dynamic_pointer_cast(presenter), presenter); } catch (ResponseStagePtr p) { @@ -30,6 +32,15 @@ CgiApplicationEngine::PresentStage::run() } } +MultiRowSetPresenterPtr +CgiApplicationEngine::PresentStage::getPresenter() const +{ + if (!presenter) { + presenter = LoaderBase::getLoader(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(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()) { } @@ -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 -CheckHost::CheckHost(ScriptReaderPtr s) : +CheckHost::CheckHost(ScriptNodePtr s) : CommonObjects(s) { - s->loader.addLoadTarget(s->root(), Storer::into(&checks)); + s->script->loader.addLoadTarget(s, Storer::into(&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(&rowSets)); + s->script->loader.addLoadTarget(s, Storer::into(&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 create(ScriptNodePtr) const = 0; - virtual bool save(boost::intrusive_ptr, const Glib::ustring &) = 0; + virtual bool save(boost::intrusive_ptr, ScriptNodePtr) = 0; }; template @@ -44,11 +44,11 @@ class StorerBase : public Storer { boost::intrusive_ptr create(ScriptNodePtr p) const { return LoaderBase::getLoader(p->get_name())->createFrom(p); } - bool save(boost::intrusive_ptr o, const Glib::ustring & name) { + bool save(boost::intrusive_ptr o, ScriptNodePtr name) { boost::intrusive_ptr O = boost::dynamic_pointer_cast(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 -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(&tasks)); + s->script->loader.addLoadTarget(s, Storer::into(&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 +class TransformTargetStorer : public Storer { + public: + TransformTargetStorer(TransformSource * ts) : + transformSource(ts) + { + } + boost::intrusive_ptr create(ScriptNodePtr p) const + { + return LoaderBase::getLoader(p->get_name())->createFrom(p); + } + bool save(boost::intrusive_ptr o, ScriptNodePtr s) + { + TransformChainLinkPtr O = boost::dynamic_pointer_cast(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 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 TransformChainLinkPtr; class Transform; typedef boost::intrusive_ptr TransformPtr; +typedef std::map 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 targets; + Targets targets; }; typedef boost::intrusive_ptr TransformSourcePtr; template 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 createFrom(ScriptNodePtr) const = 0; +}; + +template +class TransformTargetLoaderImpl : public TransformTargetLoader { + public: + boost::intrusive_ptr createFrom(ScriptNodePtr s) const { + return new T(s); + } +}; +#define DECLARE_TRANSFORMTARGET(N, T) DECLARE_COMPONENT_LOADER(N, T, TransformTargetLoader) + template 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 #include -ViewHost::ViewHost(ScriptReaderPtr s) : +ViewHost::ViewHost(ScriptNodePtr s) : CommonObjects(s), - CheckHost(s), - root(s->root()) + CheckHost(s) { - s->loader.addLoadTarget(root, Storer::into(&views)); - s->loader.addLoadTarget(root, Storer::into(&presenter)); + s->script->loader.addLoadTarget(s, Storer::into(&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(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 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 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("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 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 #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 -class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, public SourceOf { +class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, public SourceOf, public WritableContent, public SourceOf { public: - JsonPresenter(ScriptNodePtr) : - ContentPresenter("application/json; charset=UTF-8") { + JsonPresenter(ScriptNodePtr s) : + TransformSource(s), + ContentPresenter("application/json; charset=UTF-8"), + SourceOf(s), + SourceOf(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 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 TransformImplmessage(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 & 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 & 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 #include "transformHtml.h" -#include "logger.h" #include #include #include +HtmlDocument::HtmlDocument(ScriptNodePtr s) : + TransformSource(s), + SourceOf(s), + SourceOf(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 { public: void transform(const xmlpp::Document * cdata, HtmlDocument * result) const @@ -27,5 +62,7 @@ class TransformXmlToHtml : public TransformImpl { 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 -class HtmlDocument; -class HtmlDocument : public SourceOf { +class HtmlDocument : public SourceOf, public WritableContent, public SourceOf { 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 #include +TextDocument::TextDocument(ScriptNodePtr s) : + TransformSource(s), + SourceOf(s), + SourceOf(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 { public: void transform(const HtmlDocument * cdoc, TextDocument * str) const @@ -16,7 +40,7 @@ class TransformHtmlToText : public TransformImpl { #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 { } } }; + 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 -class TextDocument : public SourceOf { +class TextDocument : public SourceOf, public WritableContent, public SourceOf { 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 #include "ostreamWrapper.h" -class TransformXmlToHttpStream : public TransformImpl { +class TransformXmlToStdStream : public TransformImpl { public: void transform(const xmlpp::Document * doc, ostreamWrapper * o) const { const_cast(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(e), + SourceOf<_xmlDoc>(e), + SourceOf >(e), + SourceOf(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, public SourceOf, public SourceOf > { +class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf, public SourceOf, public SourceOf >, public WritableContent, public SourceOf { public: typedef boost::shared_ptr 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 * () 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; -- cgit v1.2.3