summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2011-07-14 19:50:11 +0000
committerrandomdan <randomdan@localhost>2011-07-14 19:50:11 +0000
commitd2f60795927647c09acbeceb32efb8a29314c340 (patch)
tree5dc1f6f9b8331a17e67863c847ea63ca97f5d92c
parentFix unused_result warning when compiled with optimization enabled (diff)
downloadproject2-d2f60795927647c09acbeceb32efb8a29314c340.tar.bz2
project2-d2f60795927647c09acbeceb32efb8a29314c340.tar.xz
project2-d2f60795927647c09acbeceb32efb8a29314c340.zip
All new dynamic transformations and processing and tidyup and stuff
-rw-r--r--project2/Jamfile.jam15
-rw-r--r--project2/cgi/cgiAppEngine.cpp99
-rw-r--r--project2/cgi/cgiAppEngine.h84
-rw-r--r--project2/cgi/cgiCommon.cpp4
-rw-r--r--project2/cgi/cgiEnvironment.cpp4
-rw-r--r--project2/cgi/cgiEnvironment.h3
-rw-r--r--project2/cgi/cgiStageCustomError.cpp25
-rw-r--r--project2/cgi/cgiStageCustomNotFound.cpp26
-rw-r--r--project2/cgi/cgiStageDefaultError.cpp35
-rw-r--r--project2/cgi/cgiStageDefaultNotFound.cpp34
-rw-r--r--project2/cgi/cgiStageInitial.cpp6
-rw-r--r--project2/cgi/cgiStagePresent.cpp43
-rw-r--r--project2/cgi/cgiStageRequest.cpp53
-rw-r--r--project2/cgi/testCgi.cpp70
-rw-r--r--project2/checkHost.cpp39
-rw-r--r--project2/checkHost.h30
-rw-r--r--project2/commonObjects.cpp12
-rw-r--r--project2/commonObjects.h12
-rw-r--r--project2/console/consoleAppEngine.cpp100
-rw-r--r--project2/console/consoleAppEngine.h24
-rw-r--r--project2/console/consolePresenter.cpp72
-rw-r--r--project2/console/consolePresenter.h24
-rw-r--r--project2/environment.cpp9
-rw-r--r--project2/environment.h4
-rw-r--r--project2/if.cpp13
-rw-r--r--project2/if.h6
-rw-r--r--project2/iterate.cpp2
-rw-r--r--project2/iterate.h2
-rw-r--r--project2/library.cpp2
-rw-r--r--project2/library.h2
-rw-r--r--project2/noOutputExecute.cpp7
-rw-r--r--project2/noOutputExecute.h4
-rw-r--r--project2/ostreamWrapper.h14
-rw-r--r--project2/paramChecker.h1
-rw-r--r--project2/presenter.cpp16
-rw-r--r--project2/presenter.h30
-rw-r--r--project2/requestHost.cpp61
-rw-r--r--project2/requestHost.h32
-rw-r--r--project2/rowView.h2
-rw-r--r--project2/sendmailTask.cpp150
-rw-r--r--project2/sendmailTask.h15
-rw-r--r--project2/sqlMergeTask.cpp4
-rw-r--r--project2/sqlMergeTask.h2
-rw-r--r--project2/sqlTask.cpp11
-rw-r--r--project2/sqlTask.h2
-rw-r--r--project2/taskHost.cpp76
-rw-r--r--project2/taskHost.h33
-rw-r--r--project2/transform.cpp37
-rw-r--r--project2/transform.h70
-rw-r--r--project2/transformHtml.cpp30
-rw-r--r--project2/transformHtml.h15
-rw-r--r--project2/transformText.cpp38
-rw-r--r--project2/transformText.h15
-rw-r--r--project2/variables.cpp1
-rw-r--r--project2/variables.h1
-rw-r--r--project2/viewHost.cpp107
-rw-r--r--project2/viewHost.h47
-rw-r--r--project2/xmlObjectLoader.cpp2
-rw-r--r--project2/xmlPresenter.cpp78
-rw-r--r--project2/xmlPresenter.h32
-rw-r--r--project2/xmlScriptParser.cpp13
-rw-r--r--project2/xmlScriptParser.h11
-rw-r--r--project2/xmlStorage.h112
63 files changed, 1214 insertions, 709 deletions
diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam
index 5b9799a..6015b7e 100644
--- a/project2/Jamfile.jam
+++ b/project2/Jamfile.jam
@@ -43,7 +43,7 @@ feature pq : yes no : propagated ;
project
: requirements
<variant>debug:<cflags>"-W -Wall -Werror -Wwrite-strings"
- <variant>debug:<linkflags>-Wl,-z,defs
+ <variant>debug:<linkflags>"-Wl,-z,defs --warn-once"
;
lib p2uuid :
@@ -56,10 +56,11 @@ lib p2uuid :
lib p2common :
appEngine.cpp dataSource.cpp environment.cpp fileStarGlibIoChannel.cpp iHaveParameters.cpp library.cpp
- iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp logger.cpp if.cpp xmlScriptParser.cpp
+ iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp logger.cpp if.cpp xmlScriptParser.cpp viewHost.cpp
sourceObject.cpp task.cpp variables.cpp variableConvert.cpp view.cpp xmlObjectLoader.cpp exceptions.cpp
- sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp xmlPresenter.cpp requestHost.cpp
+ sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp xmlPresenter.cpp taskHost.cpp checkHost.cpp
rowView.cpp rowSet.cpp rowUser.cpp rowProcessor.cpp config.cpp fileStrmVarWriter.cpp noOutputExecute.cpp
+ transform.cpp transformHtml.cpp transformText.cpp
../libmisc/buffer.cpp
../libmisc/misc.cpp
:
@@ -70,6 +71,7 @@ lib p2common :
<library>boost_filesystem
<library>boost_date_time
<library>boost_program_options
+ <library>libxslt
: :
<include>.
<include>../libmisc
@@ -217,6 +219,13 @@ exe p2fcgi :
<include>../libmisc
;
+exe testCgi :
+ cgi/testCgi.cpp
+ :
+ <library>p2web
+ <include>../libmisc
+ ;
+
exe p2console :
[ glob console/*.cpp ]
:
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp
index 52e69cf..f4eb134 100644
--- a/project2/cgi/cgiAppEngine.cpp
+++ b/project2/cgi/cgiAppEngine.cpp
@@ -8,6 +8,7 @@
#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#include "../sessionXml.h"
+#include "../ostreamWrapper.h"
#include <boost/date_time/microsec_time_clock.hpp>
const std::string SESSIONID = "sessionID";
@@ -18,29 +19,22 @@ SessionContainer * sessionsContainer = new SessionContainerXml();
SimpleMessageException(UnknownDomain);
-static
-int
-xmlWrite(void * _out, const char * buf, int len)
-{
- std::ostream * IO = static_cast<std::ostream*>(_out);
- IO->write(buf, len);
- return len;
-}
-
-CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e) :
+CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) :
ApplicationEngine("web/host"),
- _env(e)
+ _env(e),
+ IO(io)
{
BOOST_FOREACH(const cgicc::HTTPCookie c, e->getCookieList()) {
if (c.getName() == SESSIONID) {
sessionID = c.getValue();
}
}
- currentStage = new InitialStage(e);
+ currentStage = NextStage(new InitialStage(e));
}
CgiApplicationEngine::~CgiApplicationEngine()
{
+ sessionsContainer->CleanUp();
}
const Environment *
@@ -49,25 +43,14 @@ CgiApplicationEngine::env() const
return _env;
}
-void
-CgiApplicationEngine::write(std::ostream & IO) const
-{
- HttpHeaderPtr header = currentStage->getHeader();
- if (!sessionID.is_nil()) {
- header->setCookie(cgicc::HTTPCookie(SESSIONID, sessionID.str(), "Session ID",
- _env->getServerName().substr(_env->getServerName().find(".")), 3600, "/", false));
- }
- header->render(IO);
- xmlOutputBufferPtr out = xmlOutputBufferCreateIO(
- xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8));
- xmlSaveFileTo(out, currentStage->getDataDocument()->cobj(), "utf-8");
- sessionsContainer->CleanUp();
-#ifndef NDEBUG
- if (!_env->dumpdatadoc.empty()) {
- currentStage->getDataDocument()->write_to_file_formatted(_env->dumpdatadoc);
- }
-#endif
-}
+class TransformXmlToHttpStream : 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);
void
CgiApplicationEngine::process() const
@@ -75,34 +58,56 @@ CgiApplicationEngine::process() const
startTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
bool triedNotFound = false;
bool triedOnError = false;
- StagePtr nextStage;
do {
try {
- nextStage = currentStage->run();
+ currentStage = currentStage.get<0>()->run();
+ }
+ catch (const CheckHost::CheckFailure & cf) {
+ currentStage = NextStage(new PresentStage(_env, cf.failedCheck->present));
}
catch (const XmlScriptParser::NotFound & nf) {
if (_env->notFoundPresent.empty() || triedNotFound) {
- nextStage = new DefaultNotFoundStage(_env, nf);
+ currentStage = NextStage(new DefaultNotFoundStage(_env, nf));
}
else {
triedNotFound = true;
- nextStage = new CustomNotFoundStage(_env, nf);
+ currentStage = NextStage(new CustomNotFoundStage(_env, nf));
}
}
catch (const std::exception & ex) {
if (_env->onErrorPresent.empty() || triedOnError) {
- nextStage = new DefaultErrorStage(_env, ex);
+ currentStage = NextStage(new DefaultErrorStage(_env, ex));
}
else {
triedNotFound = true;
- nextStage = new CustomErrorStage(_env, ex);
+ currentStage = NextStage(new CustomErrorStage(_env, ex));
}
}
- } while (nextStage && (currentStage = nextStage));
+ } while (currentStage.get<0>());
endTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
- PresenterPtr p = boost::dynamic_pointer_cast<Presenter>(currentStage);
- if (p) {
- addAppData(p.get());
+ ResponseStagePtr rs = currentStage.get<1>();
+ if (currentStage.get<3>()) {
+ addAppData(currentStage.get<3>().get());
+ addEnvData(currentStage.get<3>().get());
+ }
+ HttpHeaderPtr header = rs->getHeader();
+ if (!sessionID.is_nil()) {
+ header->setCookie(cgicc::HTTPCookie(SESSIONID, sessionID.str(), "Session ID",
+ _env->getServerName().substr(_env->getServerName().find(".")), 3600, "/", false));
+ }
+ header->render(IO);
+ if (currentStage.get<2>()) {
+ TransformSourcePtr ts = currentStage.get<2>();
+ std::fstream * ddd = NULL;
+ if (!_env->dumpdatadoc.empty()) {
+ ddd = new std::fstream(_env->dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out);
+ ts->addTarget(new ostreamWrapper(*ddd));
+ }
+ ts->addTarget(new ostreamWrapper(IO));
+ ts->doTransforms();
+ if (ddd) {
+ delete ddd;
+ }
}
}
@@ -115,18 +120,6 @@ CgiApplicationEngine::Stage::~Stage()
{
}
-CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::Stage::getHeader() const
-{
- return CgiApplicationEngine::HttpHeaderPtr();
-}
-
-CgiApplicationEngine::XmlDocPtr
-CgiApplicationEngine::Stage::getDataDocument() const
-{
- return XmlDocPtr();
-}
-
void
CgiApplicationEngine::addEnvData(const Presenter * p) const
{
diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h
index 78f796f..e2ad1a2 100644
--- a/project2/cgi/cgiAppEngine.h
+++ b/project2/cgi/cgiAppEngine.h
@@ -4,11 +4,14 @@
#include "../appEngine.h"
#include "../task.h"
#include "../paramChecker.h"
-#include "../xmlPresenter.h"
#include "../commonObjects.h"
#include "../uuid.h"
-#include "../requestHost.h"
+#include "../taskHost.h"
+#include "../viewHost.h"
+#include "../transform.h"
+#include "../xmlPresenter.h"
#include <boost/intrusive_ptr.hpp>
+#include <boost/tuple/tuple.hpp>
class CgiEnvironment;
class Session;
@@ -19,16 +22,15 @@ namespace xmlpp {
class Document;
}
-class CgiApplicationEngine : public ApplicationEngine {
+class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink {
public:
typedef boost::shared_ptr<xmlpp::Document> XmlDocPtr;
typedef boost::shared_ptr<cgicc::HTTPHeader> HttpHeaderPtr;
- CgiApplicationEngine(const CgiEnvironment *);
+ CgiApplicationEngine(const CgiEnvironment *, std::ostream &);
virtual ~CgiApplicationEngine();
void process() const;
- void write(std::ostream &) const;
const Environment * env() const;
SessionPtr session() const;
virtual Glib::ustring resolveCurrentConfig() const;
@@ -45,115 +47,103 @@ class CgiApplicationEngine : public ApplicationEngine {
bool checkDomain(const DomainPlatforms::value_type & i) const;
void loadEngineSection(const xmlpp::Element *) const;
+ public:
class Stage;
+ class ResponseStage;
typedef boost::intrusive_ptr<Stage> StagePtr;
+ typedef boost::intrusive_ptr<ResponseStage> ResponseStagePtr;
+ typedef boost::tuple<StagePtr, ResponseStagePtr, TransformSourcePtr, PresenterPtr> NextStage;
/// Base class for a stage iteration that should eventually produce a response for the client
- class Stage : public virtual CommonObjects {
+ class Stage : public virtual IntrusivePtrBase {
public:
Stage(const CgiEnvironment * e);
virtual ~Stage() = 0;
- virtual StagePtr run() = 0;
- virtual XmlDocPtr getDataDocument() const;
- virtual HttpHeaderPtr getHeader() const;
+ virtual NextStage run() = 0;
protected:
const CgiEnvironment * e;
};
+ /// Base class for a stage that can be a response to the client
+ class ResponseStage : public Stage {
+ public:
+ ResponseStage(const CgiEnvironment * e);
+ virtual HttpHeaderPtr getHeader() const = 0;
+ };
+
/// Stage implementation used to bootstrap the iteration process based on the CGI environment
class InitialStage : public Stage {
public:
InitialStage(const CgiEnvironment * e);
- virtual StagePtr run();
+ virtual NextStage run();
};
/// Stage to process POST requests
- class RequestStage : public Stage, public XmlPresenter, RequestHost {
+ class RequestStage : public ResponseStage, TaskHost {
public:
RequestStage(const CgiEnvironment *, const std::string & id);
- virtual StagePtr run();
- virtual XmlDocPtr getDataDocument() const;
+ virtual NextStage run();
virtual HttpHeaderPtr getHeader() const;
- virtual const Glib::ustring & getResponseRootNodeName() const;
- virtual const Glib::ustring & getResponseStyle() const;
-
protected:
std::string present;
- typedef Storage<ParamChecker>::Objects ParamCheckers;
- ParamCheckers parameterChecks;
-
- private:
- static const Glib::ustring resp;
- static const Glib::ustring style;
};
/// Stage to process GET requests and follow up RequestStages
- class PresentStage : public virtual Stage, public XmlProcessPresenter {
+ class PresentStage : public virtual ResponseStage, ViewHost {
public:
PresentStage(const CgiEnvironment * e, const std::string & id);
PresentStage(const CgiEnvironment * e, const std::string & group, const std::string & id);
- virtual StagePtr run();
- virtual XmlDocPtr getDataDocument() const;
+ virtual NextStage run();
virtual HttpHeaderPtr getHeader() const;
};
/// The built-in fail-safe not found stage
- class DefaultNotFoundStage : public virtual Stage, public XmlPresenter {
+ class DefaultNotFoundStage : public virtual ResponseStage {
public:
DefaultNotFoundStage(const CgiEnvironment *, const XmlScriptParser::NotFound &);
- virtual XmlDocPtr getDataDocument() const;
+ virtual NextStage run();
virtual HttpHeaderPtr getHeader() const;
- virtual StagePtr run();
- virtual const Glib::ustring & getResponseRootNodeName() const;
- virtual const Glib::ustring & getResponseStyle() const;
private:
- static const Glib::ustring resp;
const XmlScriptParser::NotFound nf;
+ XmlPresenterPtr pres;
};
/// Custom not found handling stage
class CustomNotFoundStage : public DefaultNotFoundStage, public PresentStage {
public:
- CustomNotFoundStage(const CgiEnvironment *, const XmlScriptParser::NotFound &);
- virtual StagePtr run();
- virtual XmlDocPtr getDataDocument() const;
+ CustomNotFoundStage(const CgiEnvironment *, const ::XmlScriptParser::NotFound &);
+ virtual NextStage run();
virtual HttpHeaderPtr getHeader() const;
- virtual const Glib::ustring & getResponseRootNodeName() const;
- virtual const Glib::ustring & getResponseStyle() const;
};
/// The built-in fail-safe unhandled error stage
- class DefaultErrorStage : public virtual Stage, public XmlPresenter {
+ class DefaultErrorStage : public virtual ResponseStage {
public:
DefaultErrorStage(const CgiEnvironment *, const std::exception &);
~DefaultErrorStage();
- virtual XmlDocPtr getDataDocument() const;
+ virtual NextStage run();
virtual HttpHeaderPtr getHeader() const;
- virtual StagePtr run();
- virtual const Glib::ustring & getResponseRootNodeName() const;
- virtual const Glib::ustring & getResponseStyle() const;
private:
- static const Glib::ustring resp;
char * buf;
std::string what;
+ XmlPresenterPtr pres;
};
/// Custom unhandled error handling stage
class CustomErrorStage : public DefaultErrorStage, public PresentStage {
public:
CustomErrorStage(const CgiEnvironment *, const std::exception &);
- virtual StagePtr run();
- virtual XmlDocPtr getDataDocument() const;
+ virtual NextStage run();
virtual HttpHeaderPtr getHeader() const;
- virtual const Glib::ustring & getResponseRootNodeName() const;
- virtual const Glib::ustring & getResponseStyle() const;
};
- mutable StagePtr currentStage;
+ private:
+ mutable NextStage currentStage;
mutable UUID sessionID;
+ mutable std::ostream & IO;
};
#endif
diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp
index fa40d2b..b8a2b93 100644
--- a/project2/cgi/cgiCommon.cpp
+++ b/project2/cgi/cgiCommon.cpp
@@ -44,12 +44,10 @@ cgiServe(cgicc::CgiInput * i, std::ostream & IO)
CgiEnvironment env(&cgi);
env.init();
try {
- CgiApplicationEngine app(&env);
+ CgiApplicationEngine app(&env, IO);
Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__);
app.process();
- Logger()->messagef(LOG_DEBUG, "%s: Sending request result", __FUNCTION__);
- app.write(IO);
Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__);
}
catch (const std::exception & e) {
diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp
index e8d5ba3..2bc3b02 100644
--- a/project2/cgi/cgiEnvironment.cpp
+++ b/project2/cgi/cgiEnvironment.cpp
@@ -28,6 +28,8 @@ CgiEnvironment::addOptions(boost::program_options::positional_options_descriptio
{
boost::program_options::options_description cgi("Project2 CGI options");
cgi.add_options()
+ ("defaultpresenter", boost::program_options::value(&defaultPresenter)->default_value("xml"),
+ "The default engine for formatting presentations")
("defaultpresent", boost::program_options::value(&defaultPresent)->default_value("index"),
"The present script to use when no other is specified")
("presentroot", boost::program_options::value(&presentRoot)->default_value("present"),
@@ -44,10 +46,8 @@ CgiEnvironment::addOptions(boost::program_options::positional_options_descriptio
"The present script to use when the requested script does not exist")
("onerrorpresent", boost::program_options::value(&onErrorPresent),
"The present script to use when the requested script (or child) fails")
-#ifndef NDEBUG
("dumpdatadoc", boost::program_options::value(&dumpdatadoc),
"Write a copy of the data document before sending it to the web server")
-#endif
;
return cgi;
}
diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h
index ce765bf..abfe78e 100644
--- a/project2/cgi/cgiEnvironment.h
+++ b/project2/cgi/cgiEnvironment.h
@@ -27,9 +27,7 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {
boost::program_options::options_description addOptions(boost::program_options::positional_options_description &);
void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &);
public:
-#ifndef NDEBUG
std::string dumpdatadoc;
-#endif
Glib::ustring errorContentType;
Glib::ustring errorTransformStyle;
std::string defaultPresent;
@@ -38,6 +36,7 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {
std::string errorPresentRoot;
std::string notFoundPresent;
std::string onErrorPresent;
+ std::string defaultPresenter;
};
#endif
diff --git a/project2/cgi/cgiStageCustomError.cpp b/project2/cgi/cgiStageCustomError.cpp
index a3fbc1f..fb2f0de 100644
--- a/project2/cgi/cgiStageCustomError.cpp
+++ b/project2/cgi/cgiStageCustomError.cpp
@@ -4,7 +4,9 @@
#include "../logger.h"
CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const CgiEnvironment * env, const std::exception & ex) :
- CgiApplicationEngine::Stage(env),
+ CgiApplicationEngine::ResponseStage(env),
+ ::XmlScriptParser(env->errorPresentRoot, env->onErrorPresent, false),
+ ::CheckHost(env->errorPresentRoot, env->onErrorPresent),
CgiApplicationEngine::DefaultErrorStage(env, ex),
CgiApplicationEngine::PresentStage(env, env->errorPresentRoot, env->onErrorPresent)
{
@@ -16,29 +18,10 @@ CgiApplicationEngine::CustomErrorStage::getHeader() const
return CgiApplicationEngine::DefaultErrorStage::getHeader();
}
-CgiApplicationEngine::StagePtr
+CgiApplicationEngine::NextStage
CgiApplicationEngine::CustomErrorStage::run()
{
CgiApplicationEngine::DefaultErrorStage::run();
return CgiApplicationEngine::PresentStage::run();
}
-const Glib::ustring &
-CgiApplicationEngine::CustomErrorStage::getResponseRootNodeName() const
-{
- return CgiApplicationEngine::PresentStage::getResponseRootNodeName();
-}
-
-CgiApplicationEngine::XmlDocPtr
-CgiApplicationEngine::CustomErrorStage::getDataDocument() const
-{
- return CgiApplicationEngine::PresentStage::getDataDocument();
-}
-
-const Glib::ustring &
-CgiApplicationEngine::CustomErrorStage::getResponseStyle() const
-{
- return CgiApplicationEngine::PresentStage::getResponseStyle();
-}
-
-
diff --git a/project2/cgi/cgiStageCustomNotFound.cpp b/project2/cgi/cgiStageCustomNotFound.cpp
index a2d33dc..7c08a9f 100644
--- a/project2/cgi/cgiStageCustomNotFound.cpp
+++ b/project2/cgi/cgiStageCustomNotFound.cpp
@@ -3,8 +3,10 @@
#include "cgiHttpHeader.h"
#include "../logger.h"
-CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const CgiEnvironment * env, const XmlScriptParser::NotFound & notfound) :
- CgiApplicationEngine::Stage(env),
+CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const CgiEnvironment * env, const ::XmlScriptParser::NotFound & notfound) :
+ CgiApplicationEngine::ResponseStage(env),
+ ::XmlScriptParser(env->errorPresentRoot, env->notFoundPresent, false),
+ ::CheckHost(env->errorPresentRoot, env->notFoundPresent),
CgiApplicationEngine::DefaultNotFoundStage(env, notfound),
CgiApplicationEngine::PresentStage(env, env->errorPresentRoot, env->notFoundPresent)
{
@@ -16,28 +18,10 @@ CgiApplicationEngine::CustomNotFoundStage::getHeader() const
return CgiApplicationEngine::DefaultNotFoundStage::getHeader();
}
-CgiApplicationEngine::StagePtr
+CgiApplicationEngine::NextStage
CgiApplicationEngine::CustomNotFoundStage::run()
{
CgiApplicationEngine::DefaultNotFoundStage::run();
return CgiApplicationEngine::PresentStage::run();
}
-const Glib::ustring &
-CgiApplicationEngine::CustomNotFoundStage::getResponseRootNodeName() const
-{
- return CgiApplicationEngine::PresentStage::getResponseRootNodeName();
-}
-
-CgiApplicationEngine::XmlDocPtr
-CgiApplicationEngine::CustomNotFoundStage::getDataDocument() const
-{
- return CgiApplicationEngine::PresentStage::getDataDocument();
-}
-
-const Glib::ustring &
-CgiApplicationEngine::CustomNotFoundStage::getResponseStyle() const
-{
- return CgiApplicationEngine::PresentStage::getResponseStyle();
-}
-
diff --git a/project2/cgi/cgiStageDefaultError.cpp b/project2/cgi/cgiStageDefaultError.cpp
index c881da1..767a634 100644
--- a/project2/cgi/cgiStageDefaultError.cpp
+++ b/project2/cgi/cgiStageDefaultError.cpp
@@ -4,12 +4,13 @@
#include "cgiEnvironment.h"
#include <cxxabi.h>
-const Glib::ustring CgiApplicationEngine::DefaultErrorStage::resp("error");
+static const Glib::ustring DefaultErrorStageResp("error");
CgiApplicationEngine::DefaultErrorStage::DefaultErrorStage(const CgiEnvironment * env, const std::exception & ex) :
- CgiApplicationEngine::Stage(env),
+ CgiApplicationEngine::ResponseStage(env),
buf(__cxxabiv1::__cxa_demangle(typeid(ex).name(), NULL, NULL, NULL)),
- what(ex.what())
+ what(ex.what()),
+ pres(new XmlPresenter(DefaultErrorStageResp, e->errorTransformStyle, e->errorContentType))
{
}
@@ -21,32 +22,14 @@ CgiApplicationEngine::DefaultErrorStage::~DefaultErrorStage()
CgiApplicationEngine::HttpHeaderPtr
CgiApplicationEngine::DefaultErrorStage::getHeader() const
{
- return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error", e->errorContentType));
+ return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error", pres->contentType));
}
-CgiApplicationEngine::StagePtr
+CgiApplicationEngine::NextStage
CgiApplicationEngine::DefaultErrorStage::run()
{
- addField("error-type", e->getXmlPrefix(), buf);
- addField("error-what", e->getXmlPrefix(), what.c_str());
- return NULL;
-}
-
-const Glib::ustring &
-CgiApplicationEngine::DefaultErrorStage::getResponseRootNodeName() const
-{
- return resp;
-}
-
-CgiApplicationEngine::XmlDocPtr
-CgiApplicationEngine::DefaultErrorStage::getDataDocument() const
-{
- return XmlPresenter::getDataDocument();
-}
-
-const Glib::ustring &
-CgiApplicationEngine::DefaultErrorStage::getResponseStyle() const
-{
- return e->errorTransformStyle;
+ pres->addField("error-type", e->getXmlPrefix(), buf);
+ pres->addField("error-what", e->getXmlPrefix(), what.c_str());
+ return NextStage(NULL, this, pres.get(), pres.get());
}
diff --git a/project2/cgi/cgiStageDefaultNotFound.cpp b/project2/cgi/cgiStageDefaultNotFound.cpp
index f32ad1f..2e7acb1 100644
--- a/project2/cgi/cgiStageDefaultNotFound.cpp
+++ b/project2/cgi/cgiStageDefaultNotFound.cpp
@@ -3,9 +3,12 @@
#include "cgiHttpHeader.h"
#include "../logger.h"
+static const Glib::ustring DefaultNotFoundStageResp("notfound");
+
CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const CgiEnvironment * env, const XmlScriptParser::NotFound & notfound) :
- CgiApplicationEngine::Stage(env),
- nf(notfound)
+ CgiApplicationEngine::ResponseStage(env),
+ nf(notfound),
+ pres(new XmlPresenter(DefaultNotFoundStageResp, e->errorTransformStyle, e->errorContentType))
{
Logger()->messagef(LOG_ERR, "%s: Resource not found: %s", __FUNCTION__, nf.what());
}
@@ -13,32 +16,13 @@ CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const CgiEnviro
CgiApplicationEngine::HttpHeaderPtr
CgiApplicationEngine::DefaultNotFoundStage::getHeader() const
{
- return HttpHeaderPtr(new Project2HttpHeader("404 Not found", e->errorContentType));
+ return HttpHeaderPtr(new Project2HttpHeader("404 Not found", pres->contentType));
}
-CgiApplicationEngine::StagePtr
+CgiApplicationEngine::NextStage
CgiApplicationEngine::DefaultNotFoundStage::run()
{
- addField("missing-resource", e->getXmlPrefix(), nf.what());
- return NULL;
-}
-
-const Glib::ustring CgiApplicationEngine::DefaultNotFoundStage::resp("notfound");
-const Glib::ustring &
-CgiApplicationEngine::DefaultNotFoundStage::getResponseRootNodeName() const
-{
- return resp;
-}
-
-CgiApplicationEngine::XmlDocPtr
-CgiApplicationEngine::DefaultNotFoundStage::getDataDocument() const
-{
- return XmlPresenter::getDataDocument();
-}
-
-const Glib::ustring &
-CgiApplicationEngine::DefaultNotFoundStage::getResponseStyle() const
-{
- return e->errorTransformStyle;
+ pres->addField("missing-resource", e->getXmlPrefix(), nf.what());
+ return NextStage(NULL, this, pres.get(), pres.get());
}
diff --git a/project2/cgi/cgiStageInitial.cpp b/project2/cgi/cgiStageInitial.cpp
index d302971..1db8f8f 100644
--- a/project2/cgi/cgiStageInitial.cpp
+++ b/project2/cgi/cgiStageInitial.cpp
@@ -9,17 +9,17 @@ CgiApplicationEngine::InitialStage::InitialStage(const CgiEnvironment * env) :
{
}
-CgiApplicationEngine::StagePtr
+CgiApplicationEngine::NextStage
CgiApplicationEngine::InitialStage::run()
{
if (e->getRequestMethod() == "POST") {
if (e->elems.empty()) {
throw EmptyRequestURL();
}
- return new RequestStage(e, e->elems[0]);
+ return NextStage(new RequestStage(e, e->elems[0]));
}
else {
- return new PresentStage(e, e->elems.empty() ? e->defaultPresent : e->elems[0]);
+ return NextStage(new PresentStage(e, e->elems.empty() ? e->defaultPresent : e->elems[0]));
}
}
diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp
index 47db567..aaa1092 100644
--- a/project2/cgi/cgiStagePresent.cpp
+++ b/project2/cgi/cgiStagePresent.cpp
@@ -2,44 +2,45 @@
#include "cgiEnvironment.h"
#include "cgiHttpHeader.h"
#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
CgiApplicationEngine::PresentStage::PresentStage(const CgiEnvironment * e, const std::string & id) :
- CgiApplicationEngine::Stage(e),
- XmlProcessPresenter(e->presentRoot, id, false)
+ CgiApplicationEngine::ResponseStage(e),
+ XmlScriptParser(e->presentRoot, id, false),
+ CheckHost(e->presentRoot, id),
+ ViewHost(e->presentRoot, id)
{
+ parseDocument();
}
CgiApplicationEngine::PresentStage::PresentStage(const CgiEnvironment * e, const std::string & group, const std::string & id) :
- CgiApplicationEngine::Stage(e),
- XmlProcessPresenter(group, id, false)
+ CgiApplicationEngine::ResponseStage(e),
+ XmlScriptParser(group, id, false),
+ CheckHost(group, id),
+ ViewHost(group, id)
{
+ parseDocument();
}
-CgiApplicationEngine::StagePtr
+CgiApplicationEngine::NextStage
CgiApplicationEngine::PresentStage::run()
{
- BOOST_FOREACH(ParamCheckers::value_type pc, parameterChecks.get<bySOOrder>()) {
- if (!pc->performCheck()) {
- ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message());
- return new PresentStage(e, pc->present);
- }
- }
- execute();
- return NULL;
+ runChecks();
+ executeViews(boost::bind(&PresenterLoader::createFrom, LoaderBase::getLoader<PresenterLoader, NotSupported>(e->defaultPresenter), _1));
+ return NextStage(NULL, this, boost::dynamic_pointer_cast<TransformSource>(headPresenter()), headPresenter());
+}
+
+CgiApplicationEngine::ResponseStage::ResponseStage(const CgiEnvironment * e) :
+ CgiApplicationEngine::Stage(e)
+{
}
CgiApplicationEngine::HttpHeaderPtr
CgiApplicationEngine::PresentStage::getHeader() const
{
- Project2HttpHeader * header = new Project2HttpHeader("200 OK", contentType);
+ ContentPresenter * cp = boost::dynamic_pointer_cast<ContentPresenter>(headPresenter()).get();
+ Project2HttpHeader * header = new Project2HttpHeader("200 OK", cp ? cp->contentType : "text/plain");
header->addHeader("Cache-control", "no-cache");
return HttpHeaderPtr(header);
}
-CgiApplicationEngine::XmlDocPtr
-CgiApplicationEngine::PresentStage::getDataDocument() const
-{
- return XmlProcessPresenter::getDataDocument();
-}
-
-
diff --git a/project2/cgi/cgiStageRequest.cpp b/project2/cgi/cgiStageRequest.cpp
index 22cb2e8..94f3b49 100644
--- a/project2/cgi/cgiStageRequest.cpp
+++ b/project2/cgi/cgiStageRequest.cpp
@@ -5,57 +5,32 @@
#include <boost/foreach.hpp>
CgiApplicationEngine::RequestStage::RequestStage(const CgiEnvironment * e, const std::string & id) :
- CgiApplicationEngine::Stage(e)
+ XmlScriptParser(e->requestRoot, id, false),
+ ::CheckHost(e->requestRoot, id),
+ CgiApplicationEngine::ResponseStage(e),
+ ::TaskHost(e->requestRoot, id)
{
- XmlScriptParser request(e->requestRoot, id, false);
- xmlpp::Element * requestRoot = request.get_document()->get_root_node();
+ xmlpp::Element * requestRoot = get_document()->get_root_node();
present = requestRoot->get_attribute_value("present");
rollbackBeforeHandle = requestRoot->get_attribute_value("rollbackBeforeHandle") == "true";
localErrorHandling = requestRoot->get_attribute_value("errorHandling") == "local";
-
- LoaderBase loader(true);
- loader.supportedStorers.insert(Storer::into(&parameterChecks));
- loader.supportedStorers.insert(Storer::into(&rowSets));
- loader.supportedStorers.insert(new NOEErrorStorer(&normTasks, &errorTasks));
- loader.collectAll(this, requestRoot, true);
+ parseDocument();
}
-CgiApplicationEngine::StagePtr
+CgiApplicationEngine::NextStage
CgiApplicationEngine::RequestStage::run()
{
- BOOST_FOREACH(const ParamCheckers::value_type & pc, parameterChecks.get<bySOOrder>()) {
- if (!pc->performCheck()) {
- ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message());
- return new PresentStage(e, pc->present);
- }
- }
- RequestHost::run();
- return present.empty() ? NULL : new PresentStage(e, present);
+ runChecks();
+ executeTasks();
+ return NextStage(present.empty() ? NULL : new PresentStage(e, present), this);
}
+const std::string contentType = "text/plain";
CgiApplicationEngine::HttpHeaderPtr
CgiApplicationEngine::RequestStage::getHeader() const
{
- return HttpHeaderPtr(new Project2HttpHeader("200 OK", "text/xml"));
-}
-
-CgiApplicationEngine::XmlDocPtr
-CgiApplicationEngine::RequestStage::getDataDocument() const
-{
- return XmlPresenter::getDataDocument();
-}
-
-const Glib::ustring CgiApplicationEngine::RequestStage::resp("request");
-const Glib::ustring CgiApplicationEngine::RequestStage::style;
-const Glib::ustring &
-CgiApplicationEngine::RequestStage::getResponseRootNodeName() const
-{
- return resp;
+ Project2HttpHeader * header = new Project2HttpHeader("200 OK", contentType);
+ header->addHeader("Cache-control", "no-cache");
+ return HttpHeaderPtr(header);
}
-const Glib::ustring &
-CgiApplicationEngine::RequestStage::getResponseStyle() const
-{
- return style;
-}
-
diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp
new file mode 100644
index 0000000..438e1b0
--- /dev/null
+++ b/project2/cgi/testCgi.cpp
@@ -0,0 +1,70 @@
+#include <iostream>
+#include <boost/program_options.hpp>
+#include <boost/filesystem/convenience.hpp>
+#include "cgiCommon.h"
+
+namespace po = boost::program_options;
+
+class TestInput : public cgicc::CgiInput {
+ public:
+ TestInput(int argc, char ** argv)
+ {
+ po::options_description test("Project2 CGI test options");
+ test.add_options()
+ ("help,h", "Print usage and exit")
+ ("SERVER_NAME", "FQDN of web service")
+ ("SERVER_SOFTWARE", po::value<std::string>()->default_value("Apache"), "")
+ ("GATEWAY_INTERFACE", po::value<std::string>()->default_value("CGI/1.1"), "")
+ ("SERVER_PROTOCOL", po::value<std::string>()->default_value("HTTP/1.1"), "")
+ ("SERVER_PORT", po::value<std::string>()->default_value("80"), "")
+ ("REQUEST_METHOD", po::value<std::string>()->default_value("GET"), "")
+ ("PATH_INFO", "")
+ ("PATH_TRANSLATED", "")
+ ("SCRIPT_NAME", po::value<std::string>()->default_value("p2fcgi"), "")
+ ("QUERY_STRING", "")
+ ("REMOTE_HOST", "")
+ ("REMOTE_ADDR", "")
+ ("AUTH_TYPE", "")
+ ("REMOTE_USER", "")
+ ("REMOTE_IDENT", "")
+ ("CONTENT_TYPE", "")
+ ("CONTENT_LENGTH", "")
+ ("HTTP_ACCEPT", po::value<std::string>()->default_value("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"), "")
+ ("HTTP_USER_AGENT", po::value<std::string>()->default_value("Mozilla/5.0"), "")
+ ("REDIRECT_REQUEST", "")
+ ("REDIRECT_URL", "")
+ ("REDIRECT_STATUS", "")
+ ("HTTP_REFERER", "")
+ ("HTTP_COOKIE", "")
+ ("HTTPS", po::value<std::string>()->default_value("No"), "")
+ ;
+ po::parsed_options parsed = po::command_line_parser(argc, argv).options(test).allow_unregistered().run();
+ po::store(parsed, settings);
+ if (boost::filesystem::exists("testCgi.settings")) {
+ std::ifstream f("testCgi.settings");
+ po::store(po::parse_config_file(f, test, true), settings);
+ }
+ po::notify(settings);
+ if (settings.count("help")) {
+ std::cout << test;
+ exit(1);
+ }
+ }
+ virtual std::string getenv(const char *varName)
+ {
+ if (settings.count(varName)) {
+ return settings[varName].as<std::string>();
+ }
+ return "";
+ }
+ private:
+ po::variables_map settings;
+};
+
+int
+main(int argc, char ** argv)
+{
+ TestInput ti(argc, argv);
+ cgiServe(&ti, std::cout);
+}
+
diff --git a/project2/checkHost.cpp b/project2/checkHost.cpp
new file mode 100644
index 0000000..05e7d58
--- /dev/null
+++ b/project2/checkHost.cpp
@@ -0,0 +1,39 @@
+#include "checkHost.h"
+#include "appEngine.h"
+#include <boost/foreach.hpp>
+
+CheckHost::CheckHost(const std::string & group, const std::string & name) :
+ XmlScriptParser(group, name, false)
+{
+ loader.supportedStorers.insert(Storer::into(&parameterChecks));
+}
+
+CheckHost::CheckHost(const std::string & file) :
+ XmlScriptParser(file, false)
+{
+ loader.supportedStorers.insert(Storer::into(&parameterChecks));
+}
+
+CheckHost::~CheckHost()
+{
+}
+
+void
+CheckHost::runChecks() const
+{
+ BOOST_FOREACH(const ParamCheckers::value_type & pc, parameterChecks) {
+ if (!pc->performCheck()) {
+ ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message());
+ throw CheckFailure(pc);
+ }
+ }
+}
+
+CheckHost::CheckFailure::CheckFailure(ParamCheckerCPtr fc) : failedCheck(fc)
+{
+}
+
+CheckHost::CheckFailure::~CheckFailure() throw()
+{
+}
+
diff --git a/project2/checkHost.h b/project2/checkHost.h
new file mode 100644
index 0000000..759c7a0
--- /dev/null
+++ b/project2/checkHost.h
@@ -0,0 +1,30 @@
+#ifndef CHECKHOST_H
+#define CHECKHOST_H
+
+#include "xmlScriptParser.h"
+#include "paramChecker.h"
+#include "xmlStorage.h"
+#include <set>
+#include <boost/function.hpp>
+
+class CheckHost : public virtual XmlScriptParser {
+ public:
+ class CheckFailure : std::exception {
+ public:
+ CheckFailure(ParamCheckerCPtr);
+ ~CheckFailure() throw();
+ const ParamCheckerCPtr failedCheck;
+ };
+ CheckHost(const std::string & group, const std::string & file);
+ CheckHost(const std::string & file);
+ ~CheckHost();
+
+ void runChecks() const;
+
+ typedef ANONORDEREDSTORAGEOF(ParamChecker) ParamCheckers;
+ ParamCheckers parameterChecks;
+};
+
+#endif
+
+
diff --git a/project2/commonObjects.cpp b/project2/commonObjects.cpp
index 039e105..1d0b13e 100644
--- a/project2/commonObjects.cpp
+++ b/project2/commonObjects.cpp
@@ -12,14 +12,14 @@ CommonObjects::~CommonObjects()
RowSetPtr
CommonObjects::getSource(const std::string & name) const
{
- RowSets::index<bySOName>::type::const_iterator i = rowSets.get<bySOName>().find(name);
- if (i != rowSets.get<bySOName>().end()) {
- return *i;
+ RowSets::const_iterator i = rowSets.find(name);
+ if (i != rowSets.end()) {
+ return i->second;
}
throw CommonObjects::DataSourceNotFound(name);
}
-CommonObjects::DataSources::index<bySOName>::type::const_iterator
+CommonObjects::DataSources::const_iterator
CommonObjects::loadDataSource(const std::string & name) const
{
XmlScriptParser xml(ApplicationEngine::getCurrent()->env()->getDatasourceRoot(), name, true);
@@ -28,8 +28,8 @@ CommonObjects::loadDataSource(const std::string & name) const
loader.supportedStorers.insert(Storer::into(&datasources));
loader.collectAll(xml.get_document()->get_root_node(), false);
- DataSources::index<bySOName>::type::const_iterator i = datasources.get<bySOName>().find(name);
- if (i == datasources.get<bySOName>().end()) {
+ DataSources::const_iterator i = datasources.find(name);
+ if (i == datasources.end()) {
throw DataSourceNotFound(name);
}
return i;
diff --git a/project2/commonObjects.h b/project2/commonObjects.h
index dccdb20..dae563a 100644
--- a/project2/commonObjects.h
+++ b/project2/commonObjects.h
@@ -7,8 +7,8 @@
class CommonObjects : public virtual IntrusivePtrBase {
public:
- typedef Storage<RowSet>::Objects RowSets;
- typedef Storage<DataSource>::Objects DataSources;
+ typedef STORAGEOF(RowSet) RowSets;
+ typedef STORAGEOF(DataSource) DataSources;
SimpleMessageException(DataSourceNotFound);
SimpleMessageException(DataSourceNotCompatible);
@@ -19,11 +19,11 @@ class CommonObjects : public virtual IntrusivePtrBase {
template <class DataSourceType>
const DataSourceType * dataSource(const std::string & name) const
{
- Storage<DataSource>::Objects::index<bySOName>::type::const_iterator i = datasources.get<bySOName>().find(name);
- if (i == datasources.get<bySOName>().end()) {
+ DataSources::const_iterator i = datasources.find(name);
+ if (i == datasources.end()) {
i = loadDataSource(name);
}
- const DataSourceType * s = dynamic_cast<const DataSourceType *>(i->get());
+ const DataSourceType * s = boost::dynamic_pointer_cast<const DataSourceType>(i->second).get();
if (!s) {
throw DataSourceNotCompatible(name);
}
@@ -33,7 +33,7 @@ class CommonObjects : public virtual IntrusivePtrBase {
RowSets rowSets;
mutable DataSources datasources;
private:
- DataSources::index<bySOName>::type::const_iterator loadDataSource(const std::string & name) const;
+ DataSources::const_iterator loadDataSource(const std::string & name) const;
};
#endif
diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp
index 1c4f869..8e95b16 100644
--- a/project2/console/consoleAppEngine.cpp
+++ b/project2/console/consoleAppEngine.cpp
@@ -3,6 +3,8 @@
#include "../iterate.h"
#include "../xmlObjectLoader.h"
#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
+#include <iostream>
SimpleMessageException(UnknownPlatformAlias);
@@ -52,23 +54,18 @@ class ConsoleSession : public Session {
};
ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * env, const boost::filesystem::path & f) :
+ XmlScriptParser(f.string(), false),
+ CheckHost(f.string()),
ApplicationEngine("console/environment"),
+ TaskHost(f.string()),
+ ViewHost(f.string()),
_env(env),
- indent(0),
- runtime(new ConsoleSession()),
- out(stdout, true),
- request(f.string(), false)
+ runtime(new ConsoleSession())
{
- xmlpp::Element * requestRoot = request.get_document()->get_root_node();
+ xmlpp::Element * requestRoot = get_document()->get_root_node();
rollbackBeforeHandle = requestRoot->get_attribute_value("rollbackBeforeHandle") == "true";
localErrorHandling = requestRoot->get_attribute_value("errorHandling") == "local";
-
- LoaderBase loader(true);
- loader.supportedStorers.insert(Storer::into(&parameterChecks));
- loader.supportedStorers.insert(new NOEErrorStorer(&normTasks, &errorTasks));
- loader.supportedStorers.insert(Storer::into(&rowSets));
- loader.supportedStorers.insert(Storer::into(&views));
- loader.collectAll(this, request.get_document()->get_root_node(), true);
+ parseDocument();
}
ConsoleApplicationEngine::~ConsoleApplicationEngine()
@@ -76,17 +73,18 @@ ConsoleApplicationEngine::~ConsoleApplicationEngine()
}
void
+onCheckFailureHelper(boost::intrusive_ptr<const ParamChecker> pc)
+{
+ throw std::runtime_error(pc->message());
+}
+
+void
ConsoleApplicationEngine::process() const
{
- BOOST_FOREACH(const ParamCheckers::value_type & pc, parameterChecks.get<bySOOrder>()) {
- if (!pc->performCheck()) {
- ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message());
- throw std::runtime_error("Check failed");
- }
- }
- RequestHost::run();
- Presenter::execute();
- addAppData(this);
+ runChecks();
+ executeTasks();
+ executeViews(boost::bind(&PresenterLoader::createFrom, LoaderBase::getLoader<PresenterLoader, NotSupported>("console"), _1));
+ addAppData(headPresenter().get());
}
const Environment *
@@ -111,66 +109,6 @@ ConsoleApplicationEngine::addAppData(const Presenter *) const
{
}
-void
-ConsoleApplicationEngine::declareNamespace(const Glib::ustring &, const Glib::ustring &) const
-{
-}
-void
-ConsoleApplicationEngine::setNamespace(const Glib::ustring &, const Glib::ustring &) const
-{
-}
-
-void
-ConsoleApplicationEngine::pushSub(const Glib::ustring & name, const Glib::ustring & ns) const
-{
- fprintf(stdout, "%*s", indent, "");
- fprintf(stdout, ">>> ");
- if (!ns.empty()) {
- fprintf(stdout, "%s::", ns.c_str());
- }
- fprintf(stdout, "%s\n", name.c_str());
- indent += 2;
-}
-
-void
-ConsoleApplicationEngine::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const
-{
- fprintf(stdout, "%*s", indent, "");
- if (!ns.empty()) {
- fprintf(stdout, "%s::", ns.c_str());
- }
- fprintf(stdout, "@%s = ", name.c_str());
- boost::apply_visitor(out, value);
- fprintf(stdout, "\n");
-}
-
-void
-ConsoleApplicationEngine::addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const
-{
- fprintf(stdout, "%*s", indent, "");
- if (!ns.empty()) {
- fprintf(stdout, "%s::", ns.c_str());
- }
- fprintf(stdout, "%s = ", name.c_str());
- boost::apply_visitor(out, value);
- fprintf(stdout, "\n");
-}
-
-void
-ConsoleApplicationEngine::addText(const VariableType & value) const
-{
- fprintf(stdout, "%*s<local> = ", indent, "");
- boost::apply_visitor(out, value);
- fprintf(stdout, "\n");
-}
-
-void
-ConsoleApplicationEngine::popSub() const
-{
- indent -= 2;
- fprintf(stdout, "%*s<<<\n", indent, "");
-}
-
Glib::ustring
ConsoleApplicationEngine::resolveCurrentConfig() const
{
diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h
index b08dec3..3d54a18 100644
--- a/project2/console/consoleAppEngine.h
+++ b/project2/console/consoleAppEngine.h
@@ -7,16 +7,14 @@
#include "../presenter.h"
#include "../commonObjects.h"
#include "../view.h"
-#include "../fileStrmVarWriter.h"
-#include "../requestHost.h"
+#include "../taskHost.h"
+#include "../viewHost.h"
#include <boost/intrusive_ptr.hpp>
-#include <boost/filesystem/path.hpp>
#include <libxml++/document.h>
-#include "../xmlScriptParser.h"
class ConsoleEnvironment;
-class ConsoleApplicationEngine : public ApplicationEngine, public Presenter, RequestHost {
+class ConsoleApplicationEngine : public ApplicationEngine, TaskHost, ViewHost {
public:
ConsoleApplicationEngine(const ConsoleEnvironment *, const boost::filesystem::path &);
virtual ~ConsoleApplicationEngine();
@@ -36,24 +34,8 @@ class ConsoleApplicationEngine : public ApplicationEngine, public Presenter, Req
mutable ConsolePlatforms conplat;
void loadEngineSection(const xmlpp::Element *) const;
-
- // Presenter interface
- public:
- void declareNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const;
- void setNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const;
- void pushSub(const Glib::ustring & ns, const Glib::ustring & name) const;
- void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const;
- void addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const;
- void addText(const VariableType & value) const;
- void popSub() const;
private:
- mutable unsigned int indent;
-
- typedef Storage<ParamChecker>::Objects ParamCheckers;
- ParamCheckers parameterChecks;
SessionPtr runtime;
- FileStreamVariableWriter out;
- XmlScriptParser request;
};
#endif
diff --git a/project2/console/consolePresenter.cpp b/project2/console/consolePresenter.cpp
new file mode 100644
index 0000000..d122771
--- /dev/null
+++ b/project2/console/consolePresenter.cpp
@@ -0,0 +1,72 @@
+#include "consolePresenter.h"
+
+DECLARE_COMPONENT_LOADER("console", ConsolePresenter, PresenterLoader)
+
+ConsolePresenter::ConsolePresenter(const xmlpp::Element *) :
+ indent(0),
+ out(stdout, true)
+{
+}
+
+void
+ConsolePresenter::declareNamespace(const Glib::ustring &, const Glib::ustring &) const
+{
+}
+
+void
+ConsolePresenter::setNamespace(const Glib::ustring &, const Glib::ustring &) const
+{
+}
+
+void
+ConsolePresenter::pushSub(const Glib::ustring & name, const Glib::ustring & ns) const
+{
+ fprintf(stdout, "%*s", indent, "");
+ fprintf(stdout, ">>> ");
+ if (!ns.empty()) {
+ fprintf(stdout, "%s::", ns.c_str());
+ }
+ fprintf(stdout, "%s\n", name.c_str());
+ indent += 2;
+}
+
+void
+ConsolePresenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const
+{
+ fprintf(stdout, "%*s", indent, "");
+ if (!ns.empty()) {
+ fprintf(stdout, "%s::", ns.c_str());
+ }
+ fprintf(stdout, "@%s = ", name.c_str());
+ boost::apply_visitor(out, value);
+ fprintf(stdout, "\n");
+}
+
+void
+ConsolePresenter::addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const
+{
+ fprintf(stdout, "%*s", indent, "");
+ if (!ns.empty()) {
+ fprintf(stdout, "%s::", ns.c_str());
+ }
+ fprintf(stdout, "%s = ", name.c_str());
+ boost::apply_visitor(out, value);
+ fprintf(stdout, "\n");
+}
+
+void
+ConsolePresenter::addText(const VariableType & value) const
+{
+ fprintf(stdout, "%*s<local> = ", indent, "");
+ boost::apply_visitor(out, value);
+ fprintf(stdout, "\n");
+}
+
+void
+ConsolePresenter::popSub() const
+{
+ indent -= 2;
+ fprintf(stdout, "%*s<<<\n", indent, "");
+}
+
+
diff --git a/project2/console/consolePresenter.h b/project2/console/consolePresenter.h
new file mode 100644
index 0000000..98cce6d
--- /dev/null
+++ b/project2/console/consolePresenter.h
@@ -0,0 +1,24 @@
+#ifndef CONSOLEPRESENTER_H
+#define CONSOLEPRESENTER_H
+
+#include "../presenter.h"
+#include "../fileStrmVarWriter.h"
+
+class ConsolePresenter : public Presenter {
+ public:
+ ConsolePresenter(const xmlpp::Element *);
+ void declareNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const;
+ void setNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const;
+ void pushSub(const Glib::ustring & ns, const Glib::ustring & name) const;
+ void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const;
+ void addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const;
+ void addText(const VariableType & value) const;
+ void popSub() const;
+ void write(const boost::function1<std::ostream *, const std::string &> &) const;
+ private:
+ mutable unsigned int indent;
+ FileStreamVariableWriter out;
+};
+
+#endif
+
diff --git a/project2/environment.cpp b/project2/environment.cpp
index a3a3d5e..69cdde7 100644
--- a/project2/environment.cpp
+++ b/project2/environment.cpp
@@ -6,6 +6,7 @@
namespace po = boost::program_options;
+const Environment * Environment::currentEnv(NULL);
int Environment::clLevel(-1);
int Environment::slLevel(-1);
bool Environment::optionsBuilt(false);
@@ -16,6 +17,7 @@ Environment::Environment(int c, char ** v) :
argc(c),
argv(v)
{
+ currentEnv = this;
}
void
@@ -61,6 +63,7 @@ Environment::init()
Environment::~Environment()
{
+ currentEnv = NULL;
Logger()->clear();
}
@@ -82,3 +85,9 @@ Environment::getXmlPrefix() const
return xmlPrefix;
}
+const Environment *
+Environment::getCurrent()
+{
+ return currentEnv;
+}
+
diff --git a/project2/environment.h b/project2/environment.h
index 5c66518..e515741 100644
--- a/project2/environment.h
+++ b/project2/environment.h
@@ -13,6 +13,8 @@ class Environment {
void init();
+ static const Environment * getCurrent();
+
const std::string & getDatasourceRoot() const;
const Glib::ustring & getXmlNamespace() const;
const Glib::ustring & getXmlPrefix() const;
@@ -23,6 +25,8 @@ class Environment {
virtual std::string getServerName() const = 0;
virtual std::string getScriptName() const = 0;
private:
+ static const Environment * currentEnv;
+
virtual boost::program_options::options_description addOptions(boost::program_options::positional_options_description &) = 0;
virtual void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &) = 0;
int argc;
diff --git a/project2/if.cpp b/project2/if.cpp
index 5fa7a8c..ed36bad 100644
--- a/project2/if.cpp
+++ b/project2/if.cpp
@@ -2,6 +2,7 @@
#include "logger.h"
#include "xmlObjectLoader.h"
#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
#include <algorithm>
DECLARE_LOADER("if", If);
@@ -19,22 +20,22 @@ IfSet::IfSet(const xmlpp::Element * e) :
template <class Range, class Pred>
bool all(const Range & c, const Pred & p)
{
- return (std::find_if(c.begin(), c.end(), !p) == c.end());
+ return (std::find_if(c.begin(), c.end(), !p) == c.end());
}
template <class Range, class Pred>
bool any(const Range & c, const Pred & p)
{
- return (std::find_if(c.begin(), c.end(), p) != c.end());
+ return (std::find_if(c.begin(), c.end(), p) != c.end());
}
bool
IfSet::passes() const
{
if (mode == And) {
- return all(checks.get<bySOOrder>(), boost::bind(&ParamChecker::performCheck, _1));
+ return all(checks, boost::bind(&ParamChecker::performCheck, _1));
}
else if (mode == Or) {
- return any(checks.get<bySOOrder>(), boost::bind(&ParamChecker::performCheck, _1));
+ return any(checks, boost::bind(&ParamChecker::performCheck, _1));
}
throw IfModeIsNonsense(getName());
}
@@ -74,12 +75,12 @@ If::execute() const
if (passes()) {
Logger()->message(LOG_DEBUG, "IfSet passed");
try {
- BOOST_FOREACH(const SubNOEs::value_type & sq, normNOEs.get<bySOOrder>()) {
+ BOOST_FOREACH(const SubNOEs::value_type & sq, normNOEs) {
sq->execute();
}
}
catch (...) {
- BOOST_FOREACH(const SubNOEs::value_type & sq, errorNOEs.get<bySOOrder>()) {
+ BOOST_FOREACH(const SubNOEs::value_type & sq, errorNOEs) {
sq->execute();
}
if (!localErrorHandling) {
diff --git a/project2/if.h b/project2/if.h
index 6482d7c..9c9acd8 100644
--- a/project2/if.h
+++ b/project2/if.h
@@ -14,7 +14,7 @@ class IfSet : public virtual IntrusivePtrBase {
virtual const std::string & getName() const = 0;
enum Mode { And, Or };
Mode mode;
- typedef Storage<ParamChecker>::Objects ParamCheckers;
+ typedef ANONORDEREDSTORAGEOF(ParamChecker) ParamCheckers;
ParamCheckers checks;
};
@@ -30,9 +30,9 @@ class If : public NoOutputExecute, public View, public IfSet {
const bool localErrorHandling;
private:
- typedef Storage<View>::Objects SubViews;
+ typedef ANONSTORAGEOF(View) SubViews;
SubViews subViews;
- typedef Storage<NoOutputExecute>::Objects SubNOEs;
+ typedef ANONORDEREDSTORAGEOF(NoOutputExecute) SubNOEs;
SubNOEs normNOEs;
SubNOEs errorNOEs;
diff --git a/project2/iterate.cpp b/project2/iterate.cpp
index e7af8f1..55648eb 100644
--- a/project2/iterate.cpp
+++ b/project2/iterate.cpp
@@ -55,7 +55,7 @@ Iterate::execute() const
void
Iterate::executeChildren(bool errs) const
{
- BOOST_FOREACH(const SubNOEs::value_type & sq, (errs ? errorNOEs : normNOEs).get<bySOOrder>()) {
+ BOOST_FOREACH(const SubNOEs::value_type & sq, (errs ? errorNOEs : normNOEs)) {
if (dynamic_cast<const RowProcessor *>(sq.get())) {
sq->execute();
}
diff --git a/project2/iterate.h b/project2/iterate.h
index e4cd3fe..a60a0a4 100644
--- a/project2/iterate.h
+++ b/project2/iterate.h
@@ -19,7 +19,7 @@ class Iterate : public NoOutputExecute, public RowProcessor {
void rowReady() const;
void execute() const;
- typedef Storage<NoOutputExecute>::Objects SubNOEs;
+ typedef ANONORDEREDSTORAGEOF(NoOutputExecute) SubNOEs;
SubNOEs normNOEs;
SubNOEs errorNOEs;
diff --git a/project2/library.cpp b/project2/library.cpp
index 1941254..b1e0b9b 100644
--- a/project2/library.cpp
+++ b/project2/library.cpp
@@ -27,7 +27,7 @@ Library::loadComplete(const CommonObjects*)
{
}
-Storage<Library>::Objects libraries;
+STORAGEOF(Library) libraries;
class LibraryLoader : public ElementLoaderImpl<Library> {
public:
void onIteration()
diff --git a/project2/library.h b/project2/library.h
index 4dfdadd..af8e73f 100644
--- a/project2/library.h
+++ b/project2/library.h
@@ -11,7 +11,7 @@ class Library : public SourceObject {
private:
void * handle;
};
-extern Storage<Library>::Objects libraries;
+extern STORAGEOF(Library) libraries;
#endif
diff --git a/project2/noOutputExecute.cpp b/project2/noOutputExecute.cpp
index 6f599c4..cb12439 100644
--- a/project2/noOutputExecute.cpp
+++ b/project2/noOutputExecute.cpp
@@ -15,7 +15,8 @@ NOEErrorStorer::NOEErrorStorer(Map m, Map em) :
{
}
-NOEErrorStorer::Map
-NOEErrorStorer::getMap(const xmlpp::Element * p) const {
- return ((p->get_attribute_value("onerror") == "true") ? errorMap : map);
+bool
+NOEErrorStorer::insert(const xmlpp::Element * p, NoOutputExecutePtr O) {
+ ((p->get_attribute_value("onerror") == "true") ? errorMap : map)->push_back(O);
+ return true;
}
diff --git a/project2/noOutputExecute.h b/project2/noOutputExecute.h
index fe1c638..78245f2 100644
--- a/project2/noOutputExecute.h
+++ b/project2/noOutputExecute.h
@@ -17,10 +17,10 @@ class NoOutputExecute : public virtual SourceObject {
virtual void execute() const = 0;
};
-class NOEErrorStorer : public StorerBase<NoOutputExecute> {
+class NOEErrorStorer : public StorerBase<NoOutputExecute, ANONORDEREDSTORAGEOF(NoOutputExecute) > {
public:
NOEErrorStorer(Map m, Map em);
- Map getMap(const xmlpp::Element *) const;
+ bool insert(const xmlpp::Element *, NoOutputExecutePtr);
Map map, errorMap;
};
diff --git a/project2/ostreamWrapper.h b/project2/ostreamWrapper.h
new file mode 100644
index 0000000..ef8596c
--- /dev/null
+++ b/project2/ostreamWrapper.h
@@ -0,0 +1,14 @@
+#ifndef OSTREAMWRAPPER_H
+#define OSTREAMWRAPPER_H
+
+#include <ostream>
+#include "transform.h"
+
+class ostreamWrapper : public TransformChainLink {
+ public:
+ ostreamWrapper(std::ostream & s) : strm(s) { }
+ std::ostream & strm;
+};
+
+#endif
+
diff --git a/project2/paramChecker.h b/project2/paramChecker.h
index 57addbc..d013fc4 100644
--- a/project2/paramChecker.h
+++ b/project2/paramChecker.h
@@ -17,6 +17,7 @@ class ParamChecker : public SourceObject {
const Variable group;
const std::string present;
};
+typedef boost::intrusive_ptr<const ParamChecker> ParamCheckerCPtr;
#endif
diff --git a/project2/presenter.cpp b/project2/presenter.cpp
index 005fa2b..9544743 100644
--- a/project2/presenter.cpp
+++ b/project2/presenter.cpp
@@ -12,17 +12,6 @@ Presenter::~Presenter()
}
void
-Presenter::execute() const
-{
- BOOST_FOREACH(const Storage<View>::Objects::value_type & s, views) {
- s->execute(this);
- }
- // These were for debug... but why not pass them on?
- ApplicationEngine * appEngine = ApplicationEngine::getCurrent();
- appEngine->addEnvData(this);
-}
-
-void
Presenter::pushSub(const Glib::ustring & name) const
{
pushSub(name, Glib::ustring());
@@ -54,3 +43,8 @@ Presenter::addField(const Glib::ustring & name, const Glib::ustring & ns, const
popSub();
}
+ContentPresenter::ContentPresenter(const Glib::ustring & ct) :
+ contentType(ct)
+{
+}
+
diff --git a/project2/presenter.h b/project2/presenter.h
index bbfaf82..a4c0a00 100644
--- a/project2/presenter.h
+++ b/project2/presenter.h
@@ -3,12 +3,13 @@
#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
#include <glibmm/ustring.h>
#include "view.h"
#include "paramChecker.h"
-#include "commonObjects.h"
+#include "xmlObjectLoader.h"
-class Presenter : public virtual CommonObjects, public virtual IntrusivePtrBase {
+class Presenter : public virtual IntrusivePtrBase {
public:
Presenter();
virtual ~Presenter() = 0;
@@ -23,15 +24,32 @@ class Presenter : public virtual CommonObjects, public virtual IntrusivePtrBase
virtual void addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const;
virtual void addText(const VariableType & value) const = 0;
virtual void popSub() const = 0;
- void execute() const;
+};
- protected:
- typedef Storage<View>::Objects Views;
- Views views;
+class ContentPresenter : public Presenter {
+ public:
+ ContentPresenter(const Glib::ustring & contentType);
+ const Glib::ustring contentType;
};
typedef boost::intrusive_ptr<const Presenter> PresenterCPtr;
typedef boost::intrusive_ptr<Presenter> PresenterPtr;
+/// Base class to implement presenter modules
+class PresenterLoader : public ComponentLoader {
+ public:
+ virtual PresenterPtr createFrom(const xmlpp::Element * e) const = 0;
+};
+
+/// Helper implemention for specific presenters
+template <class PresenterType>
+class PresenterLoaderImpl : public PresenterLoader {
+ public:
+ virtual PresenterPtr createFrom(const xmlpp::Element * e) const
+ {
+ return new PresenterType(e);
+ }
+};
+
#endif
diff --git a/project2/requestHost.cpp b/project2/requestHost.cpp
deleted file mode 100644
index 7cb3d9c..0000000
--- a/project2/requestHost.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "requestHost.h"
-#include "noOutputExecute.h"
-#include "dataSource.h"
-#include <boost/foreach.hpp>
-
-RequestHost::RequestHost()
-{
-}
-
-RequestHost::~RequestHost()
-{
-}
-
-void
-RequestHost::run() const
-{
- try {
- run(false);
- commitAll();
- }
- catch (...) {
- if (rollbackBeforeHandle) {
- rollbackAll();
- }
- try {
- run(true);
- commitAll();
- }
- catch (...) {
- rollbackAll();
- }
- if (!localErrorHandling) {
- throw;
- }
- }
-}
-
-void
-RequestHost::run(bool errs) const
-{
- BOOST_FOREACH(const Tasks::value_type & t, (errs ? errorTasks : normTasks).get<bySOOrder>()) {
- t->execute();
- }
-}
-
-void
-RequestHost::commitAll() const
-{
- BOOST_FOREACH(const DataSources::value_type & ds, datasources) {
- ds->commit();
- }
-}
-
-void
-RequestHost::rollbackAll() const
-{
- BOOST_FOREACH(const DataSources::value_type & ds, datasources) {
- ds->rollback();
- }
-}
-
diff --git a/project2/requestHost.h b/project2/requestHost.h
deleted file mode 100644
index bf0e9f0..0000000
--- a/project2/requestHost.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef REQUEST_HOST_H
-#define REQUEST_HOST_H
-
-#include "xmlStorage.h"
-#include "commonObjects.h"
-
-class NoOutputExecute;
-class DataSource;
-
-class RequestHost : virtual CommonObjects {
- protected:
- typedef Storage<NoOutputExecute>::Objects Tasks;
- typedef Storage<DataSource>::Objects DataSources;
-
- RequestHost();
- virtual ~RequestHost() = 0;
-
- void run() const;
-
- Tasks normTasks;
- Tasks errorTasks;
- bool rollbackBeforeHandle;
- bool localErrorHandling;
-
- private:
- void commitAll() const;
- void rollbackAll() const;
- void run(bool errs) const;
-};
-
-#endif
-
diff --git a/project2/rowView.h b/project2/rowView.h
index 7cc6fe1..3652e37 100644
--- a/project2/rowView.h
+++ b/project2/rowView.h
@@ -24,7 +24,7 @@ class RowView : public View, public RowProcessor {
Columns viewColumns;
void executeChildren() const;
- typedef Storage<View>::Objects SubViews;
+ typedef ANONSTORAGEOF(View) SubViews;
SubViews subViews;
mutable const Presenter * presenter;
};
diff --git a/project2/sendmailTask.cpp b/project2/sendmailTask.cpp
index e891fea..ba2f3b0 100644
--- a/project2/sendmailTask.cpp
+++ b/project2/sendmailTask.cpp
@@ -1,14 +1,14 @@
#include "sendmailTask.h"
+#include "logger.h"
#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
#include "xmlObjectLoader.h"
-#include "xmlPresenter.h"
-#include <libxslt/transform.h>
-#include <misc.h>
+#include "viewHost.h"
#include <stdexcept>
#include <libesmtp.h>
-#include <libxslt/xsltutils.h>
-#include <libxml/HTMLtree.h>
-#include <sys/wait.h>
+#include "xmlPresenter.h"
+#include "transformHtml.h"
+#include "transformText.h"
DECLARE_LOADER("sendmail", SendMailTask);
@@ -56,6 +56,7 @@ class BoundaryBegin : public SendMailTask::MailPart {
private:
const std::string contentType;
};
+
class BoundaryEnd : public SendMailTask::MailPart {
public:
const char * write(char **, int * len) {
@@ -63,6 +64,7 @@ class BoundaryEnd : public SendMailTask::MailPart {
return "\r\n--<<divider>>--\r\n";
}
};
+
class Header : public SendMailTask::MailPart {
public:
Header(const std::string & h, const VariableType & v) :
@@ -82,90 +84,89 @@ class Header : public SendMailTask::MailPart {
const std::string header;
const VariableType value;
};
-class HtmlContent : public SendMailTask::MailPart {
+
+class MimeContent : public SendMailTask::MailPart {
public:
- HtmlContent(XmlDocumentPtr d) : doc(d) {
+ MimeContent(const char * s, int l) : str(s), length(l) {
}
const char * write(char ** buf, int * len) {
- xmlDocDumpFormatMemoryEnc(doc.get(), (xmlChar**)buf, len, "utf-8", 0);
- return *buf;
+ *buf = NULL;
+ *len = length;
+ return str;
}
private:
- const XmlDocumentPtr doc;
+ const char * str;
+ const int length;
};
-class TextContent : public SendMailTask::MailPart {
+
+class TransformHtmlToEmail : public TransformImpl<HtmlDocument, SendMailTask::Parts> {
public:
- TextContent(XmlDocumentPtr d) : doc(d) {
+ TransformHtmlToEmail() : buf(NULL)
+ {
}
- const char * write(char ** buf, int * pos) {
- int fds[2];
- const char * callLynx[] = {
-#ifdef STRACE_LYNX
- "/usr/bin/strace", "-o", "/tmp/lynx",
-#endif
- "/usr/bin/lynx", "-dump", "-stdin", "-width=105", NULL };
- popenrw(callLynx, fds);
- FILE * lynxIn = fdopen(fds[0], "w");
- FILE * lynxOut = fdopen(fds[1], "r");
- htmlNodeDumpFile(lynxIn, doc.get(), xmlDocGetRootElement(doc.get()));
- fclose(lynxIn);
- close(fds[0]);
- int len = 0;
- *pos = 0;
- for (int ch ; ((ch = fgetc(lynxOut)) >= 0); ) {
- if (*pos >= len) {
- len += BUFSIZ;
- *buf = (char*)realloc(*buf, len);
- }
- (*buf)[(*pos)++] = ch;
+ ~TransformHtmlToEmail()
+ {
+ if (buf) {
+ xmlFree(buf);
}
- fclose(lynxOut);
- close(fds[1]);
- int status;
- wait(&status);
- if (status != 0) {
- throw std::runtime_error("Lynx failed");
+ }
+ void transform(const HtmlDocument * cdoc, SendMailTask::Parts * parts) const
+ {
+ if (buf) {
+ xmlFree(buf);
+ buf = NULL;
}
- return *buf;
+ xmlDoc * doc = const_cast<xmlDoc *>(cdoc->doc);
+ int len = 0;
+ xmlDocDumpFormatMemoryEnc(doc, &buf, &len, "utf-8", 1);
+ parts->parts.push_back(new BoundaryBegin("text/html; utf-8"));
+ parts->parts.push_back(new MimeContent(reinterpret_cast<const char *>(buf), len));
}
private:
- const XmlDocumentPtr doc;
+ mutable xmlChar * buf;
+};
+DECLARE_TRANSFORM(TransformHtmlToEmail)
+
+class TransformTextToEmail : public TransformImpl<TextDocument, SendMailTask::Parts> {
+ public:
+ void transform(const TextDocument * str, SendMailTask::Parts * parts) const
+ {
+ parts->parts.push_back(new BoundaryBegin("text/plain; utf-8"));
+ parts->parts.push_back(new MimeContent(str->doc.c_str(), str->doc.length()));
+ }
};
+DECLARE_TRANSFORM(TransformTextToEmail)
+
+PresenterPtr
+SendMailTask::createDefaultPresenter(const xmlpp::Element * 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;
+}
void
SendMailTask::execute() const
{
- XmlPresenterPtr p = new XmlProcessPresenter("emails", present, true);
- p->execute();
- XmlPresenter::XmlDocumentPtr data = p->getDataDocument();
-#if DEBUG
- data->write_to_file("/tmp/email.xml");
-#endif
- typedef boost::shared_ptr<xsltStylesheet> XsltStyleSheetPtr;
-
- // Do transform
- XsltStyleSheetPtr cur = XsltStyleSheetPtr(xsltParseStylesheetFile(BAD_CAST p->getResponseStyle().c_str()), xsltFreeStylesheet);
- if (!cur) {
- throw xmlpp::exception("Failed to load stylesheet");
- }
- XmlDocumentPtr result = XmlDocumentPtr(xsltApplyStylesheet(cur.get(), data->cobj(), NULL), xmlFreeDoc);
- if (!result) {
- throw xmlpp::exception("Failed to perform transformation");
- }
+ parts = new Parts();
+ parts->parts.push_back(new Header("To", to));
+ parts->parts.push_back(new Header("From", from));
+ parts->parts.push_back(new Header("Subject", subject));
+ parts->parts.push_back(new Header("Content-Type", "multipart/alternative; boundary=\"<<divider>>\""));
+ parts->parts.push_back(new Header("MIME-Version", "1.0"));
+ parts->parts.push_back(new Header("Content-Transfer-Encoding", "binary"));
- parts.clear();
- parts.push_back(new Header("To", to));
- parts.push_back(new Header("From", from));
- parts.push_back(new Header("Subject", subject));
- parts.push_back(new Header("Content-Type", "multipart/alternative; boundary=\"<<divider>>\""));
- parts.push_back(new Header("MIME-Version", "1.0"));
- parts.push_back(new Header("Content-Transfer-Encoding", "binary"));
- parts.push_back(new BoundaryBegin("text/plain; utf-8"));
- parts.push_back(new TextContent(result));
- parts.push_back(new BoundaryBegin("text/html; utf-8"));
- parts.push_back(new HtmlContent(result));
- parts.push_back(new BoundaryEnd());
- part = parts.begin();
+ ViewHostPtr vsp = new ViewHost("emails", present);
+ vsp->executeViews(boost::bind(&SendMailTask::createDefaultPresenter, this, _1));
+ vsp->doTransforms();
+ parts->parts.push_back(new BoundaryEnd());
+ part = parts->parts.begin();
// Write email
smtp_session_t session = smtp_create_session();
@@ -173,18 +174,19 @@ SendMailTask::execute() const
smtp_set_server(session, server());
smtp_set_header(message, "To", NULL, NULL);
smtp_add_recipient(message, to());
- smtp_set_messagecb(message, writeMailWrapper, (SendMailTask*)this);
+ smtp_set_messagecb(message, writeMailWrapper, (SendMailTask*)this);
if (!smtp_start_session(session)) {
char buf[BUFSIZ];
smtp_strerror(smtp_errno(), buf, sizeof buf);
throw SendEmailFailed(buf);
}
+ parts->parts.clear();
}
const char *
SendMailTask::writeMail(void ** buf, int * len) const
{
- if (len == NULL || part == parts.end()) {
+ if (len == NULL || part == parts->parts.end()) {
return NULL;
}
return (*part++)->write((char**)buf, len);
diff --git a/project2/sendmailTask.h b/project2/sendmailTask.h
index 2f3e088..e57a309 100644
--- a/project2/sendmailTask.h
+++ b/project2/sendmailTask.h
@@ -5,7 +5,9 @@
#include <boost/intrusive_ptr.hpp>
#include <map>
#include "task.h"
+#include "transform.h"
#include "variables.h"
+#include "presenter.h"
/// Project2 component to send an email
class SendMailTask : public Task {
@@ -14,6 +16,12 @@ class SendMailTask : public Task {
public:
virtual const char * write(char ** buf, int * len) = 0;
};
+ typedef boost::intrusive_ptr<MailPart> MailPartPtr;
+ typedef std::list<MailPartPtr> PartList;
+ class Parts : public TransformChainLink {
+ public:
+ PartList parts;
+ };
SendMailTask(const xmlpp::Element * p);
virtual ~SendMailTask();
@@ -30,11 +38,10 @@ class SendMailTask : public Task {
private:
static const char * writeMailWrapper(void ** buf, int * len, void * arg);
const char * writeMail(void ** buf, int * len) const;
+ PresenterPtr createDefaultPresenter(const xmlpp::Element * n) const;
- typedef boost::intrusive_ptr<MailPart> MailPartPtr;
- typedef std::list<MailPartPtr> Parts;
- mutable Parts parts;
- mutable Parts::iterator part;
+ mutable boost::intrusive_ptr<Parts> parts;
+ mutable PartList::iterator part;
};
#endif
diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp
index a4c8611..0a9e07d 100644
--- a/project2/sqlMergeTask.cpp
+++ b/project2/sqlMergeTask.cpp
@@ -288,10 +288,10 @@ attach(IteratePtr i, ModifyCommand * insert)
return;
}
if (i->normNOEs.empty()) {
- i->normNOEs.insert(new Populate(insert));
+ i->normNOEs.push_back(new Populate(insert));
}
else {
- BOOST_FOREACH(const Iterate::SubNOEs::value_type & n, i->normNOEs.get<bySOOrder>()) {
+ BOOST_FOREACH(const Iterate::SubNOEs::value_type & n, i->normNOEs) {
attach(boost::dynamic_pointer_cast<Iterate>(n), insert);
attach(boost::dynamic_pointer_cast<SqlMergeInsert>(n), insert);
}
diff --git a/project2/sqlMergeTask.h b/project2/sqlMergeTask.h
index 795e94f..fc72a93 100644
--- a/project2/sqlMergeTask.h
+++ b/project2/sqlMergeTask.h
@@ -58,7 +58,7 @@ class SqlMergeTask : public Task {
void createTempKey() const;
mutable bool tempTableCreated;
- typedef Storage<Iterate>::Objects Sources;
+ typedef ANONSTORAGEOF(Iterate) Sources;
Sources sources;
std::list<std::string> sqls;
protected:
diff --git a/project2/sqlTask.cpp b/project2/sqlTask.cpp
index 0b58423..61bff46 100644
--- a/project2/sqlTask.cpp
+++ b/project2/sqlTask.cpp
@@ -9,19 +9,20 @@
DECLARE_LOADER("sqltask", SqlTask);
StaticMessageException(RunOnNotSpecified, "runon attribute must be specified");
-class SqlIfChangesStorer : public StorerBase<NoOutputExecute> {
+class SqlIfChangesStorer : public StorerBase<NoOutputExecute, ANONORDEREDSTORAGEOF(NoOutputExecute)> {
public:
SqlIfChangesStorer(Map c, Map nc) :
changes(c),
noChanges(nc)
{
}
- Map getMap(const xmlpp::Element * p) const {
+ bool insert(const xmlpp::Element * p, NoOutputExecutePtr O) {
xmlpp::Attribute * runon = p->get_attribute("runon");
if (!runon) {
throw RunOnNotSpecified();
}
- return ((runon->get_value() == "changes") ? changes : noChanges);
+ ((runon->get_value() == "changes") ? changes : noChanges)->push_back(O);
+ return true;
}
Map changes, noChanges;
};
@@ -58,12 +59,12 @@ SqlTask::execute() const
atoi(p.second->name.c_str())), p.second->value);
}
if (modify->execute() == 0) {
- BOOST_FOREACH(const SubNOEs::value_type & sq, noChangesNOEs.get<bySOOrder>()) {
+ BOOST_FOREACH(const SubNOEs::value_type & sq, noChangesNOEs) {
sq->execute();
}
}
else {
- BOOST_FOREACH(const SubNOEs::value_type & sq, changesNOEs.get<bySOOrder>()) {
+ BOOST_FOREACH(const SubNOEs::value_type & sq, changesNOEs) {
sq->execute();
}
}
diff --git a/project2/sqlTask.h b/project2/sqlTask.h
index 83f4062..3815a90 100644
--- a/project2/sqlTask.h
+++ b/project2/sqlTask.h
@@ -20,7 +20,7 @@ class SqlTask : public Task, IHaveParameters {
const Variable dataSource;
const std::string sql;
- typedef Storage<NoOutputExecute>::Objects SubNOEs;
+ typedef ANONORDEREDSTORAGEOF(NoOutputExecute) SubNOEs;
SubNOEs changesNOEs;
SubNOEs noChangesNOEs;
diff --git a/project2/taskHost.cpp b/project2/taskHost.cpp
new file mode 100644
index 0000000..2955dc0
--- /dev/null
+++ b/project2/taskHost.cpp
@@ -0,0 +1,76 @@
+#include "taskHost.h"
+#include "noOutputExecute.h"
+#include "dataSource.h"
+#include <boost/foreach.hpp>
+
+TaskHost::TaskHost(const std::string & group, const std::string & name) :
+ XmlScriptParser(group, name, false),
+ CheckHost(group, name)
+{
+ loader.supportedStorers.insert(new NOEErrorStorer(&normTasks, &errorTasks));
+}
+
+TaskHost::TaskHost(const std::string & file) :
+ XmlScriptParser(file, false),
+ CheckHost(file)
+{
+ loader.supportedStorers.insert(new NOEErrorStorer(&normTasks, &errorTasks));
+}
+
+TaskHost::~TaskHost()
+{
+}
+
+void
+TaskHost::executeTasks() const
+{
+ try {
+ run(normTasks);
+ commitAll();
+ }
+ catch (...) {
+ if (!errorTasks.empty()) {
+ if (rollbackBeforeHandle) {
+ rollbackAll();
+ }
+ try {
+ run(errorTasks);
+ commitAll();
+ }
+ catch (...) {
+ rollbackAll();
+ }
+ }
+ else {
+ rollbackAll();
+ }
+ if (!localErrorHandling) {
+ throw;
+ }
+ }
+}
+
+void
+TaskHost::run(const Tasks & tlist) const
+{
+ BOOST_FOREACH(const Tasks::value_type & t, tlist) {
+ t->execute();
+ }
+}
+
+void
+TaskHost::commitAll() const
+{
+ BOOST_FOREACH(const DataSources::value_type & ds, datasources) {
+ ds.second->commit();
+ }
+}
+
+void
+TaskHost::rollbackAll() const
+{
+ BOOST_FOREACH(const DataSources::value_type & ds, datasources) {
+ ds.second->rollback();
+ }
+}
+
diff --git a/project2/taskHost.h b/project2/taskHost.h
new file mode 100644
index 0000000..812760c
--- /dev/null
+++ b/project2/taskHost.h
@@ -0,0 +1,33 @@
+#ifndef TASKHOST_H
+#define TASKHOST_H
+
+#include "xmlStorage.h"
+#include "xmlScriptParser.h"
+#include "checkHost.h"
+
+class NoOutputExecute;
+class DataSource;
+
+class TaskHost : virtual public XmlScriptParser, virtual public CheckHost {
+ protected:
+ typedef ANONORDEREDSTORAGEOF(NoOutputExecute) Tasks;
+
+ TaskHost(const std::string & group, const std::string & name);
+ TaskHost(const std::string & file);
+ virtual ~TaskHost();
+
+ void executeTasks() const;
+
+ Tasks normTasks;
+ Tasks errorTasks;
+ bool rollbackBeforeHandle;
+ bool localErrorHandling;
+
+ private:
+ void commitAll() const;
+ void rollbackAll() const;
+ void run(const Tasks &) const;
+};
+
+#endif
+
diff --git a/project2/transform.cpp b/project2/transform.cpp
new file mode 100644
index 0000000..37524a0
--- /dev/null
+++ b/project2/transform.cpp
@@ -0,0 +1,37 @@
+#include "transform.h"
+#include "logger.h"
+#include <boost/foreach.hpp>
+
+TransformChainLink::~TransformChainLink()
+{
+}
+
+typedef std::map<std::string, boost::shared_ptr<TransformLoader> > TransformLoaderMap;
+void
+TransformSource::addTarget(TransformChainLinkPtr tcl, const xmlpp::Element * e)
+{
+ BOOST_FOREACH(const TransformLoaderMap::value_type & tl, *LoaderBase::objLoaders<TransformLoader>()) {
+ TransformPtr t = tl.second->create();
+ if (t->canTransform(this, tcl.get())) {
+ if (e) {
+ t->configure(e);
+ }
+ targets[tcl] = t;
+ return;
+ }
+ }
+ throw NotSupported("Couldn't find a suitable transformation");
+}
+
+typedef std::map<TransformChainLinkPtr, TransformPtr> Targets;
+void
+TransformSource::doTransforms() const
+{
+ BOOST_FOREACH(const Targets::value_type & t, targets) {
+ t.second->transform(this, t.first.get());
+ if (const TransformSource * tr = dynamic_cast<const TransformSource *>(t.first.get())) {
+ tr->doTransforms();
+ }
+ }
+}
+
diff --git a/project2/transform.h b/project2/transform.h
new file mode 100644
index 0000000..ded356b
--- /dev/null
+++ b/project2/transform.h
@@ -0,0 +1,70 @@
+#ifndef TRANSFORM_H
+#define TRANSFORM_H
+
+#include <boost/intrusive_ptr.hpp>
+#include "intrusivePtrBase.h"
+#include "xmlObjectLoader.h"
+#include <map>
+
+class TransformChainLink : public virtual IntrusivePtrBase {
+ public:
+ virtual ~TransformChainLink() = 0;
+};
+typedef boost::intrusive_ptr<TransformChainLink> TransformChainLinkPtr;
+
+class Transform;
+typedef boost::intrusive_ptr<Transform> TransformPtr;
+
+class TransformSource : public TransformChainLink {
+ public:
+ void addTarget(TransformChainLinkPtr, const xmlpp::Element * e = NULL);
+ void doTransforms() const;
+ private:
+ virtual const TransformChainLink * object() const { return this; }
+ std::map<TransformChainLinkPtr, TransformPtr> targets;
+};
+typedef boost::intrusive_ptr<TransformSource> TransformSourcePtr;
+
+template <class X>
+class SourceOf : public virtual TransformSource {
+ public:
+ virtual operator const X * () const = 0;
+};
+
+class Transform : public virtual IntrusivePtrBase {
+ public:
+ virtual void transform(const TransformSource * src, TransformChainLink * dest) const = 0;
+ virtual bool canTransform(const TransformSource * src, TransformChainLink * dest) const = 0;
+ virtual void configure(const xmlpp::Element *) { };
+};
+
+class TransformLoader : public ComponentLoader {
+ public:
+ virtual boost::intrusive_ptr<Transform> create() const = 0;
+};
+
+template <class T>
+class TransformLoaderImpl : public TransformLoader {
+ public:
+ boost::intrusive_ptr<Transform> create() const {
+ return new T();
+ }
+};
+#define DECLARE_TRANSFORM(T) DECLARE_COMPONENT_LOADER(#T, T, TransformLoader)
+
+template <class Source, class Destination>
+class TransformImpl : public Transform {
+ public:
+ virtual void transform(const Source *, Destination *) const = 0;
+ void transform(const TransformSource * src, TransformChainLink * dest) const
+ {
+ transform(dynamic_cast<const SourceOf<Source> *>(src)->operator const Source *(), dynamic_cast<Destination *>(dest));
+ }
+ bool canTransform(const TransformSource * src, TransformChainLink * dest) const
+ {
+ return (dynamic_cast<const SourceOf<Source> *>(src) && dynamic_cast<Destination *>(dest));
+ }
+};
+
+#endif
+
diff --git a/project2/transformHtml.cpp b/project2/transformHtml.cpp
new file mode 100644
index 0000000..eae1c27
--- /dev/null
+++ b/project2/transformHtml.cpp
@@ -0,0 +1,30 @@
+#include "transformHtml.h"
+#include "logger.h"
+#include <libxml++/document.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/transform.h>
+
+class TransformXmlToHtml : public TransformImpl<xmlpp::Document, HtmlDocument> {
+ public:
+ void transform(const xmlpp::Document * cdata, HtmlDocument * result) const
+ {
+ xmlpp::Document * data = const_cast<xmlpp::Document *>(cdata);
+ typedef boost::shared_ptr<xsltStylesheet> XsltStyleSheetPtr;
+ XsltStyleSheetPtr cur = XsltStyleSheetPtr(xsltParseStylesheetFile(BAD_CAST stylesheet.c_str()), xsltFreeStylesheet);
+ if (!cur) {
+ throw xmlpp::exception("Failed to load stylesheet");
+ }
+ result->doc = xsltApplyStylesheet(cur.get(), data->cobj(), NULL);
+ if (!result) {
+ throw xmlpp::exception("Failed to perform transformation");
+ }
+ }
+ void configure(const xmlpp::Element * e)
+ {
+ stylesheet = e->get_attribute_value("style");
+ }
+ private:
+ Glib::ustring stylesheet;
+};
+DECLARE_TRANSFORM(TransformXmlToHtml)
+
diff --git a/project2/transformHtml.h b/project2/transformHtml.h
new file mode 100644
index 0000000..25bd0d5
--- /dev/null
+++ b/project2/transformHtml.h
@@ -0,0 +1,15 @@
+#ifndef HTMLDOCUMENT_H
+#define HTMLDOCUMENT_H
+
+#include "transform.h"
+#include <libxml/HTMLtree.h>
+
+class HtmlDocument;
+class HtmlDocument : public SourceOf<HtmlDocument> {
+ public:
+ htmlDocPtr doc;
+ operator const HtmlDocument * () const { return this; }
+};
+
+#endif
+
diff --git a/project2/transformText.cpp b/project2/transformText.cpp
new file mode 100644
index 0000000..5ba03cc
--- /dev/null
+++ b/project2/transformText.cpp
@@ -0,0 +1,38 @@
+#include "transformText.h"
+#include <libxml++/document.h>
+#include "transformHtml.h"
+#include <sys/wait.h>
+#include <misc.h>
+
+class TransformHtmlToText : public TransformImpl<HtmlDocument, TextDocument> {
+ public:
+ void transform(const HtmlDocument * cdoc, TextDocument * str) const
+ {
+ xmlDoc * doc = const_cast<xmlDoc *>(cdoc->doc);
+ str->doc.clear();
+ int fds[2];
+ const char * callLynx[] = {
+#ifdef STRACE_LYNX
+ "/usr/bin/strace", "-o", "/tmp/lynx",
+#endif
+ "/usr/bin/lynx", "-dump", "-stdin", "-width=105", NULL };
+ popenrw(callLynx, fds);
+ FILE * lynxIn = fdopen(fds[0], "w");
+ FILE * lynxOut = fdopen(fds[1], "r");
+ htmlNodeDumpFile(lynxIn, doc, xmlDocGetRootElement(doc));
+ fclose(lynxIn);
+ close(fds[0]);
+ for (int ch ; ((ch = fgetc(lynxOut)) >= 0); ) {
+ str->doc.push_back(ch);
+ }
+ fclose(lynxOut);
+ close(fds[1]);
+ int status;
+ wait(&status);
+ if (status != 0) {
+ throw std::runtime_error("Lynx failed");
+ }
+ }
+};
+DECLARE_TRANSFORM(TransformHtmlToText);
+
diff --git a/project2/transformText.h b/project2/transformText.h
new file mode 100644
index 0000000..9a81c89
--- /dev/null
+++ b/project2/transformText.h
@@ -0,0 +1,15 @@
+#ifndef TEXTDOCUMENT_H
+#define TEXTDOCUMENT_H
+
+#include "transform.h"
+#include <string>
+
+class TextDocument : public SourceOf<TextDocument> {
+ public:
+ std::string doc;
+ operator const TextDocument * () const { return this; }
+};
+
+
+#endif
+
diff --git a/project2/variables.cpp b/project2/variables.cpp
index a5cfa0d..f633ccd 100644
--- a/project2/variables.cpp
+++ b/project2/variables.cpp
@@ -4,6 +4,7 @@
#include "appEngine.h"
#include "session.h"
#include "rowUser.h"
+#include "rowSet.h"
#include <libxml++/nodes/textnode.h>
#include <stdexcept>
#include <boost/tokenizer.hpp>
diff --git a/project2/variables.h b/project2/variables.h
index 5e29547..37aba03 100644
--- a/project2/variables.h
+++ b/project2/variables.h
@@ -53,6 +53,7 @@ class VariableType : public _VT {
operator int32_t() const;
operator double() const;
operator const boost::posix_time::ptime &() const;
+ template <typename T> const T * get() const { return boost::get<T>(this); }
private:
template <typename T> friend const T * set(const VariableType * var, const T * t, Freer);
diff --git a/project2/viewHost.cpp b/project2/viewHost.cpp
new file mode 100644
index 0000000..1fa8d9b
--- /dev/null
+++ b/project2/viewHost.cpp
@@ -0,0 +1,107 @@
+#include "viewHost.h"
+#include "xmlPresenter.h"
+#include <boost/foreach.hpp>
+#include <iostream>
+
+#define FOREACH_PRESENTER BOOST_FOREACH (const PresenterPtr & p, presenters)
+
+ViewHost::ViewHost(const std::string & group, const std::string & name) :
+ XmlScriptParser(group, name, false),
+ CheckHost(group, name)
+{
+ loader.supportedStorers.insert(Storer::into(&views));
+ loader.supportedStorers.insert(Storer::into(&pmp.presenters));
+}
+
+ViewHost::ViewHost(const std::string & file) :
+ XmlScriptParser(file, false),
+ CheckHost(file)
+{
+ loader.supportedStorers.insert(Storer::into(&views));
+ loader.supportedStorers.insert(Storer::into(&pmp.presenters));
+}
+
+ViewHost::~ViewHost()
+{
+}
+
+void
+ViewHost::executeViews(const DefaultPresenterProvider & dpp) const
+{
+ if (pmp.presenters.empty()) {
+ pmp.presenters.insert(dpp(get_document()->get_root_node()));
+ }
+
+ BOOST_FOREACH(const Views::value_type & s, views) {
+ s->execute(&pmp);
+ }
+}
+
+void
+ViewHost::doTransforms() const
+{
+ BOOST_FOREACH (const PresenterPtr & p, pmp.presenters) {
+ TransformSourcePtr ts = boost::dynamic_pointer_cast<TransformSource>(p);
+ if (ts) {
+ ts->doTransforms();
+ }
+ }
+}
+
+PresenterPtr
+ViewHost::headPresenter() const
+{
+ return *pmp.presenters.begin();
+}
+
+void
+ViewHost::PresenterMultiplexer::declareNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const
+{
+ FOREACH_PRESENTER { p->declareNamespace(prefix, ns); }
+}
+void
+ViewHost::PresenterMultiplexer::setNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const
+{
+ FOREACH_PRESENTER { p->setNamespace(prefix, ns); }
+}
+void
+ViewHost::PresenterMultiplexer::pushSub(const Glib::ustring & name) const
+{
+ FOREACH_PRESENTER { p->pushSub(name); }
+}
+void
+ViewHost::PresenterMultiplexer::pushSub(const Glib::ustring & name, const Glib::ustring & ns) const
+{
+ FOREACH_PRESENTER { p->pushSub(name, ns); }
+}
+void
+ViewHost::PresenterMultiplexer::addAttr(const Glib::ustring & name, const VariableType & value) const
+{
+ FOREACH_PRESENTER { p->addAttr(name, value); }
+}
+void
+ViewHost::PresenterMultiplexer::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const
+{
+ FOREACH_PRESENTER { p->addAttr(name, ns, value); }
+}
+void
+ViewHost::PresenterMultiplexer::addField(const Glib::ustring & name, const VariableType & value) const
+{
+ FOREACH_PRESENTER { p->addField(name, value); }
+}
+void
+ViewHost::PresenterMultiplexer::addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const
+{
+ FOREACH_PRESENTER { p->addField(name, ns, value); }
+}
+void
+ViewHost::PresenterMultiplexer::addText(const VariableType & value) const
+{
+ FOREACH_PRESENTER { p->addText(value); }
+}
+void
+ViewHost::PresenterMultiplexer::popSub() const
+{
+ FOREACH_PRESENTER { p->popSub(); }
+}
+
diff --git a/project2/viewHost.h b/project2/viewHost.h
new file mode 100644
index 0000000..19ff65f
--- /dev/null
+++ b/project2/viewHost.h
@@ -0,0 +1,47 @@
+#ifndef VIEWHOST_H
+#define VIEWHOST_H
+
+#include "xmlScriptParser.h"
+#include "paramChecker.h"
+#include "xmlStorage.h"
+#include "presenter.h"
+#include "checkHost.h"
+#include <set>
+#include <boost/filesystem/path.hpp>
+
+class ViewHost : virtual public XmlScriptParser, virtual public CheckHost {
+ public:
+ class PresenterMultiplexer : public Presenter {
+ public:
+ typedef std::set<PresenterPtr> Presenters;
+ void declareNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const;
+ void setNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const;
+ void pushSub(const Glib::ustring & name) const;
+ void pushSub(const Glib::ustring & name, const Glib::ustring & ns) const;
+ void addAttr(const Glib::ustring & name, const VariableType & value) const;
+ void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const;
+ void addField(const Glib::ustring & name, const VariableType & value) const;
+ void addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const;
+ void addText(const VariableType & value) const;
+ void popSub() const;
+ Presenters presenters;
+ };
+ typedef boost::function1<PresenterPtr, const xmlpp::Element *> DefaultPresenterProvider;
+
+ ViewHost(const std::string & group, const std::string & file);
+ ViewHost(const std::string & file);
+ ~ViewHost();
+
+ void executeViews(const DefaultPresenterProvider &) const;
+ void doTransforms() const;
+ PresenterPtr headPresenter() const;
+
+ private:
+ mutable PresenterMultiplexer pmp;
+ typedef ANONSTORAGEOF(View) Views;
+ Views views;
+};
+typedef boost::intrusive_ptr<ViewHost> ViewHostPtr;
+
+#endif
+
diff --git a/project2/xmlObjectLoader.cpp b/project2/xmlObjectLoader.cpp
index d2f25e7..c41b0c0 100644
--- a/project2/xmlObjectLoader.cpp
+++ b/project2/xmlObjectLoader.cpp
@@ -27,7 +27,7 @@ typedef std::set<boost::shared_ptr<ComponentLoader> > ComponentLoaderSet;
LoaderBase::LoaderBase(bool r) :
recursive(r),
- ns(ApplicationEngine::getCurrent()->env()->getXmlNamespace())
+ ns(Environment::getCurrent()->getXmlNamespace())
{
supportedStorers.insert(Storer::into(&libraries));
}
diff --git a/project2/xmlPresenter.cpp b/project2/xmlPresenter.cpp
index adf7860..c6bb04d 100644
--- a/project2/xmlPresenter.cpp
+++ b/project2/xmlPresenter.cpp
@@ -2,67 +2,52 @@
#include "xmlObjectLoader.h"
#include "variables.h"
#include "appEngine.h"
+#include <libxml++/document.h>
-XmlPresenter::XmlPresenter() :
- responseDoc(XmlDocumentPtr(new xmlpp::Document("1.0")))
-{
-}
-
-XmlPresenter::~XmlPresenter()
-{
-}
+DECLARE_COMPONENT_LOADER("xml", XmlPresenter, PresenterLoader)
-void
-XmlPresenter::createDoc() const
+XmlPresenter::XmlPresenter(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle, const Glib::ustring & ct) :
+ ContentPresenter(ct),
+ responseDoc(XmlDocumentPtr(new xmlpp::Document("1.0")))
{
- if (nodeStack.empty()) {
- nodeStack.push_back(responseDoc->create_root_node(getResponseRootNodeName()));
- declareNamespace(ApplicationEngine::getCurrent()->env()->getXmlPrefix(),
- ApplicationEngine::getCurrent()->env()->getXmlNamespace());
- // XSLT Style
- char * buf;
- if (!getResponseStyle().empty() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"",
- getResponseStyle().c_str()) > 0) {
- xmlAddPrevSibling(nodeStack.back()->cobj(),
- xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf));
- free(buf);
- }
- }
+ createDoc(responseRootNodeName, responseStyle);
}
-XmlProcessPresenter::XmlProcessPresenter(const std::string & group, const std::string & file, bool isInclusion) :
- present(group, file, isInclusion),
- responseRootNodeName(present.get_document()->get_root_node()->get_attribute_value("root")),
- responseStyle(present.get_document()->get_root_node()->get_attribute_value("style")),
- contentType(present.get_document()->get_root_node()->get_attribute_value("contenttype"))
+XmlPresenter::XmlPresenter(const xmlpp::Element * e) :
+ ContentPresenter(e->get_attribute_value("contenttype")),
+ responseDoc(XmlDocumentPtr(new xmlpp::Document("1.0")))
{
- LoaderBase loader(true);
- loader.supportedStorers.insert(Storer::into(&rowSets));
- loader.supportedStorers.insert(Storer::into(&views));
- loader.supportedStorers.insert(Storer::into(&parameterChecks));
- loader.collectAll(this, present.get_document()->get_root_node(), true);
+ createDoc(e->get_attribute_value("root"), e->get_attribute_value("style"));
}
-XmlProcessPresenter::~XmlProcessPresenter()
+XmlPresenter::~XmlPresenter()
{
}
-const Glib::ustring &
-XmlProcessPresenter::getResponseRootNodeName() const
+void
+XmlPresenter::createDoc(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle) const
{
- return responseRootNodeName;
+ nodeStack.push_back(responseDoc->create_root_node(responseRootNodeName));
+ declareNamespace(Environment::getCurrent()->getXmlPrefix(),
+ Environment::getCurrent()->getXmlNamespace());
+ // XSLT Style
+ char * buf;
+ if (!responseStyle.empty() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"",
+ responseStyle.c_str()) > 0) {
+ xmlAddPrevSibling(nodeStack.back()->cobj(),
+ xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf));
+ free(buf);
+ }
}
-const Glib::ustring &
-XmlProcessPresenter::getResponseStyle() const
+XmlPresenter::operator const xmlpp::Document * () const
{
- return responseStyle;
+ return responseDoc.get();
}
-XmlPresenter::XmlDocumentPtr
-XmlPresenter::getDataDocument() const
+XmlPresenter::operator const xmlDoc * () const
{
- return responseDoc;
+ return responseDoc->cobj();
}
void
@@ -80,15 +65,13 @@ XmlPresenter::setNamespace(const Glib::ustring & prefix, const Glib::ustring & n
void
XmlPresenter::pushSub(const Glib::ustring & name, const Glib::ustring & ns) const
{
- createDoc();
nodeStack.push_back(nodeStack.back()->add_child(name, ns));
}
void
XmlPresenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const
{
- if (!boost::get<Null>(&value)) {
- createDoc();
+ if (!value.get<Null>()) {
nodeStack.back()->set_attribute(name, value, ns);
}
}
@@ -96,8 +79,7 @@ XmlPresenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, cons
void
XmlPresenter::addText(const VariableType & value) const
{
- if (!boost::get<Null>(&value)) {
- createDoc();
+ if (!value.get<Null>()) {
nodeStack.back()->add_child_text(value);
}
}
diff --git a/project2/xmlPresenter.h b/project2/xmlPresenter.h
index cd63f1e..9b32c31 100644
--- a/project2/xmlPresenter.h
+++ b/project2/xmlPresenter.h
@@ -2,16 +2,17 @@
#define XMLPRESENTER_H
#include "presenter.h"
-#include "xmlScriptParser.h"
+#include "transform.h"
namespace xmlpp {
class Document;
}
-class XmlPresenter : public Presenter {
+class XmlPresenter : public ContentPresenter, public SourceOf<xmlpp::Document>, public SourceOf<xmlDoc> {
public:
typedef boost::shared_ptr<xmlpp::Document> XmlDocumentPtr;
- XmlPresenter();
+ XmlPresenter(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle, const Glib::ustring & contentType);
+ XmlPresenter(const xmlpp::Element * e);
~XmlPresenter();
void declareNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const;
@@ -21,34 +22,15 @@ class XmlPresenter : public Presenter {
void addText(const VariableType & value) const;
void popSub() const;
- virtual XmlDocumentPtr getDataDocument() const;
- virtual const Glib::ustring & getResponseRootNodeName() const = 0;
- virtual const Glib::ustring & getResponseStyle() const = 0;
+ operator const xmlpp::Document * () const;
+ operator const xmlDoc * () const;
private:
- void createDoc() const;
+ void createDoc(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle) const;
XmlDocumentPtr responseDoc;
mutable std::vector<xmlpp::Element *> nodeStack;
};
-class XmlProcessPresenter : public XmlPresenter {
- public:
- XmlProcessPresenter(const std::string & group, const std::string & file, bool isInclusion);
- ~XmlProcessPresenter();
-
- protected:
- const Glib::ustring & getResponseRootNodeName() const;
- const Glib::ustring & getResponseStyle() const;
-
- XmlScriptParser present;
- typedef Storage<ParamChecker>::Objects ParamCheckers;
- ParamCheckers parameterChecks;
-
- const Glib::ustring responseRootNodeName;
- const Glib::ustring responseStyle;
- const Glib::ustring contentType;
-};
-
typedef boost::intrusive_ptr<XmlPresenter> XmlPresenterPtr;
#endif
diff --git a/project2/xmlScriptParser.cpp b/project2/xmlScriptParser.cpp
index 8db4049..fad9542 100644
--- a/project2/xmlScriptParser.cpp
+++ b/project2/xmlScriptParser.cpp
@@ -3,13 +3,15 @@
#include <boost/filesystem/convenience.hpp>
XmlScriptParser::XmlScriptParser(const std::string & group, const std::string & name, bool ii) :
- IsInclusion(ii)
+ IsInclusion(ii),
+ loader(true)
{
loadDocument(group + "/" + name + ".xml");
}
XmlScriptParser::XmlScriptParser(const std::string & file, bool ii) :
- IsInclusion(ii)
+ IsInclusion(ii),
+ loader(true)
{
loadDocument(file);
}
@@ -17,6 +19,7 @@ XmlScriptParser::XmlScriptParser(const std::string & file, bool ii) :
void
XmlScriptParser::loadDocument(const std::string & file)
{
+ loader.supportedStorers.insert(Storer::into(&rowSets));
if (!boost::filesystem::exists(file)) {
if (IsInclusion) {
throw DependencyNotFound(file);
@@ -38,3 +41,9 @@ XmlScriptParser::loadDocument(const std::string & file)
}
}
+void
+XmlScriptParser::parseDocument()
+{
+ loader.collectAll(this, get_document()->get_root_node(), true, ErrorOnUnsupported);
+}
+
diff --git a/project2/xmlScriptParser.h b/project2/xmlScriptParser.h
index 92d1bdb..7b7f644 100644
--- a/project2/xmlScriptParser.h
+++ b/project2/xmlScriptParser.h
@@ -2,9 +2,13 @@
#define XMLSCRIPTPARSER_H
#include <libxml++/parsers/domparser.h>
+#include <boost/function.hpp>
#include "exceptions.h"
+#include "xmlObjectLoader.h"
+#include <intrusivePtrBase.h>
+#include "commonObjects.h"
-class XmlScriptParser : public xmlpp::DomParser {
+class XmlScriptParser : public xmlpp::DomParser, virtual public CommonObjects, virtual public IntrusivePtrBase {
public:
SimpleMessageException(ParseError);
SimpleMessageExceptionBase(NotFound, ParseError);
@@ -15,11 +19,16 @@ class XmlScriptParser : public xmlpp::DomParser {
XmlScriptParser(const std::string & group, const std::string & name, bool isInclusion);
XmlScriptParser(const std::string & file, bool isInclusion);
+ void parseDocument();
const bool IsInclusion;
+ protected:
+ LoaderBase loader;
+
private:
void loadDocument(const std::string & file);
};
+
#endif
diff --git a/project2/xmlStorage.h b/project2/xmlStorage.h
index 9263b48..73fce0a 100644
--- a/project2/xmlStorage.h
+++ b/project2/xmlStorage.h
@@ -3,75 +3,115 @@
#include "sourceObject.h"
#include "exceptions.h"
+#include <set>
+#include <list>
+#include <map>
#include <boost/intrusive_ptr.hpp>
-#include <boost/multi_index_container.hpp>
-#include <boost/multi_index/member.hpp>
-#include <boost/multi_index/ordered_index.hpp>
SimpleMessageException(StoreFailed);
-struct bySOName { };
-struct bySOOrder { };
+#define STORAGEOF(X) \
+ std::map<std::string, boost::intrusive_ptr<X> >
+#define ANONORDEREDSTORAGEOF(X) \
+ std::list<boost::intrusive_ptr<X> >
+#define ANONSTORAGEOF(X) \
+ std::set<boost::intrusive_ptr<X> >
-template <class X>
-class Storage {
- public:
- typedef boost::multi_index::multi_index_container<
- boost::intrusive_ptr<X>,
- boost::multi_index::indexed_by<
- boost::multi_index::ordered_unique<
- boost::multi_index::tag<bySOOrder>, BOOST_MULTI_INDEX_MEMBER(SourceObject, const unsigned int, order)>,
- boost::multi_index::ordered_unique<
- boost::multi_index::tag<bySOName>, BOOST_MULTI_INDEX_MEMBER(SourceObject, const std::string, name)>
- > > Objects;
- typedef Objects * ObjectsPtr;
-};
class Storer;
typedef boost::intrusive_ptr<Storer> StorerPtr;
class Storer : public virtual IntrusivePtrBase {
public:
template <class X>
- static StorerPtr into(X * map);
+ static StorerPtr into(STORAGEOF(X) * map);
+ template <class X>
+ static StorerPtr into(ANONSTORAGEOF(X) * set);
+ template <class X>
+ static StorerPtr into(ANONORDEREDSTORAGEOF(X) * list);
- virtual bool save(SourceObjectPtr o, const xmlpp::Element *) const = 0;
+ virtual bool save(SourceObjectPtr o, const xmlpp::Element *) = 0;
};
-template <class X>
+template <class X, class M = STORAGEOF(X)>
class StorerBase : public Storer {
public:
- typedef typename Storage<X>::ObjectsPtr Map;
- StorerBase()
- {
- }
-
- bool save(SourceObjectPtr obj, const xmlpp::Element * p) const {
+ typedef M * Map;
+ bool save(SourceObjectPtr obj, const xmlpp::Element * p) {
boost::intrusive_ptr<X> O = boost::dynamic_pointer_cast<X>(obj);
if (O) {
- if (getMap(p)->insert(O).second) {
+ if (insert(p, O)) {
return true;
}
throw StoreFailed(obj->name);
}
return false;
}
- virtual Map getMap(const xmlpp::Element *) const = 0;
+ virtual bool insert(const xmlpp::Element *, boost::intrusive_ptr<X>) = 0;
};
+template <class X, class M = STORAGEOF(X)>
+class StorerImpl : public StorerBase<X, M> {
+ public:
+ StorerImpl(M * m);
+ bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O);
+};
template <class X>
-class StorerImpl : public StorerBase<X> {
+class StorerImpl<X, STORAGEOF(X)> : public StorerBase<X, STORAGEOF(X)> {
public:
- StorerImpl(typename StorerBase<X>::Map m) : map(m)
+ typedef STORAGEOF(X) Map;
+ StorerImpl(STORAGEOF(X) * m) : map(m)
{
}
-
- typename StorerBase<X>::Map getMap(const xmlpp::Element *) const { return map; }
- typename StorerBase<X>::Map map;
+ bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O)
+ {
+ return map->insert(typename Map::value_type(O->name, O)).second;
+ }
+ Map * map;
+};
+template <class X>
+class StorerImpl<X, ANONSTORAGEOF(X)> : public StorerBase<X, ANONSTORAGEOF(X)> {
+ public:
+ typedef ANONSTORAGEOF(X) Map;
+ StorerImpl(ANONSTORAGEOF(X) * m) : map(m)
+ {
+ }
+ bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O)
+ {
+ map->insert(O);
+ return true;
+ }
+ Map * map;
+};
+template <class X>
+class StorerImpl<X, ANONORDEREDSTORAGEOF(X)> : public StorerBase<X, ANONORDEREDSTORAGEOF(X)> {
+ public:
+ typedef ANONORDEREDSTORAGEOF(X) Map;
+ StorerImpl(ANONORDEREDSTORAGEOF(X) * m) : map(m)
+ {
+ }
+ bool insert(const xmlpp::Element *, boost::intrusive_ptr<X> O)
+ {
+ map->push_back(O);
+ return true;
+ }
+ Map * map;
};
template <class X>
StorerPtr
-Storer::into(X * map) {
- return new StorerImpl<typename X::value_type::element_type>(map);
+Storer::into(STORAGEOF(X) * map) {
+ return new StorerImpl<X, STORAGEOF(X)>(map);
+}
+
+template <class X>
+StorerPtr
+Storer::into(ANONSTORAGEOF(X) * set) {
+ return new StorerImpl<X, ANONSTORAGEOF(X)>(set);
+}
+
+template <class X>
+StorerPtr
+Storer::into(ANONORDEREDSTORAGEOF(X) * list) {
+ return new StorerImpl<X, ANONORDEREDSTORAGEOF(X)>(list);
}
#endif