summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2012-01-01 04:26:45 +0000
committerrandomdan <randomdan@localhost>2012-01-01 04:26:45 +0000
commitc6f5af306ed3dea3e86c5ad8c7a98ceebd69bb4f (patch)
tree9b938a3d4f289a42b3543ac4327bc9f5ea644aba
parentRemove useless typedef requiring extra template parameter (diff)
downloadproject2-c6f5af306ed3dea3e86c5ad8c7a98ceebd69bb4f.tar.bz2
project2-c6f5af306ed3dea3e86c5ad8c7a98ceebd69bb4f.tar.xz
project2-c6f5af306ed3dea3e86c5ad8c7a98ceebd69bb4f.zip
Regeneralise some code
Fully customisable output chain Minor supporting tweaks here and there
-rw-r--r--project2/cgi/cgiAppEngine.cpp44
-rw-r--r--project2/cgi/cgiAppEngine.h9
-rw-r--r--project2/cgi/cgiHttpHeader.cpp7
-rw-r--r--project2/cgi/cgiHttpHeader.h1
-rw-r--r--project2/cgi/cgiStageCustomError.cpp4
-rw-r--r--project2/cgi/cgiStageCustomNotFound.cpp4
-rw-r--r--project2/cgi/cgiStageDefaultError.cpp2
-rw-r--r--project2/cgi/cgiStageDefaultNotFound.cpp2
-rw-r--r--project2/cgi/cgiStagePresent.cpp22
-rw-r--r--project2/cgi/cgiStageRequest.cpp9
-rw-r--r--project2/common/checkHost.cpp4
-rw-r--r--project2/common/checkHost.h2
-rw-r--r--project2/common/commonObjects.cpp6
-rw-r--r--project2/common/commonObjects.h2
-rw-r--r--project2/common/scriptLoader.cpp2
-rw-r--r--project2/common/scriptStorage.h6
-rw-r--r--project2/common/taskHost.cpp8
-rw-r--r--project2/common/taskHost.h2
-rw-r--r--project2/common/transform.cpp38
-rw-r--r--project2/common/transform.h28
-rw-r--r--project2/common/viewHost.cpp16
-rw-r--r--project2/common/viewHost.h11
-rw-r--r--project2/console/consoleAppEngine.cpp19
-rw-r--r--project2/console/consoleAppEngine.h2
-rw-r--r--project2/console/consolePresenter.cpp4
-rw-r--r--project2/console/consolePresenter.h2
-rw-r--r--project2/json/presenter.cpp20
-rw-r--r--project2/mail/sendmailTask.cpp44
-rw-r--r--project2/xml/transformHtml.cpp39
-rw-r--r--project2/xml/transformHtml.h10
-rw-r--r--project2/xml/transformText.cpp28
-rw-r--r--project2/xml/transformText.h10
-rw-r--r--project2/xml/transformXml.cpp4
-rw-r--r--project2/xml/xmlPresenter.cpp21
-rw-r--r--project2/xml/xmlPresenter.h5
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;