From 5507f618e094554f04f61a950d9c6d2b55865d3e Mon Sep 17 00:00:00 2001 From: randomdan Date: Fri, 5 Jul 2013 00:01:26 +0000 Subject: Massive refactor to remove the appEngine and environment complication and instead have an execution context that's passed around from the original call site --- project2/basics/aggregates/avg.cpp | 2 +- project2/basics/aggregates/count.cpp | 2 +- project2/basics/aggregates/countDistinct.cpp | 2 +- project2/basics/aggregates/distinct.cpp | 2 +- project2/basics/aggregates/join.cpp | 4 +- project2/basics/aggregates/max.cpp | 2 +- project2/basics/aggregates/min.cpp | 2 +- project2/basics/aggregates/sum.cpp | 2 +- project2/basics/functions/dates.cpp | 20 +-- project2/basics/functions/strings.cpp | 4 +- project2/basics/pch.hpp | 1 - project2/basics/tests/compoundTest.cpp | 16 +- project2/basics/tests/equals.cpp | 4 +- project2/basics/tests/isdistinct.cpp | 6 +- project2/basics/tests/isuniq.cpp | 8 +- project2/basics/tests/validDateCheck.cpp | 8 +- project2/cgi/Jamfile.jam | 1 - project2/cgi/cgiAppEngine.cpp | 242 ++++++++++++++++++--------- project2/cgi/cgiAppEngine.h | 92 +++++----- project2/cgi/cgiCommon.cpp | 70 -------- project2/cgi/cgiCommon.h | 6 - project2/cgi/cgiContentNegotiate.cpp | 8 +- project2/cgi/cgiEnvironment.cpp | 207 ----------------------- project2/cgi/cgiEnvironment.h | 78 --------- project2/cgi/cgiProgRouter.cpp | 13 +- project2/cgi/cgiRequestContext.cpp | 161 ++++++++++++++++++ project2/cgi/cgiRequestContext.h | 68 ++++++++ project2/cgi/cgiRequestID.cpp | 11 +- project2/cgi/cgiResultStatic.cpp | 2 +- project2/cgi/cgiResultWritable.cpp | 4 +- project2/cgi/cgiRouter.h | 1 + project2/cgi/cgiSimpleRouter.cpp | 2 +- project2/cgi/cgiStageCacheHit.cpp | 6 +- project2/cgi/cgiStageCustomError.cpp | 18 +- project2/cgi/cgiStageCustomNotFound.cpp | 16 +- project2/cgi/cgiStageDefaultError.cpp | 18 +- project2/cgi/cgiStageDefaultNotFound.cpp | 10 +- project2/cgi/cgiStageFail.cpp | 10 +- project2/cgi/cgiStageInitial.cpp | 13 +- project2/cgi/cgiStagePresent.cpp | 32 ++-- project2/cgi/cgiStageRedirect.cpp | 10 +- project2/cgi/cgiStageRequest.cpp | 18 +- project2/cgi/cgiUriParam.cpp | 9 +- project2/cgi/p2webCgi.cpp | 11 +- project2/cgi/p2webFCgi.cpp | 11 +- project2/cgi/pch.hpp | 8 +- project2/cgi/testCgi.cpp | 22 ++- project2/common/aggregate.cpp | 4 +- project2/common/aggregate.h | 4 +- project2/common/appEngine.cpp | 53 ------ project2/common/appEngine.h | 42 ----- project2/common/cache.cpp | 14 +- project2/common/cache.h | 15 +- project2/common/check.cpp | 4 +- project2/common/check.h | 4 +- project2/common/checkHost.cpp | 8 +- project2/common/checkHost.h | 2 +- project2/common/commonObjects.cpp | 1 - project2/common/environment.cpp | 22 --- project2/common/environment.h | 28 ---- project2/common/exceptions.h | 1 + project2/common/execContext.cpp | 36 ++++ project2/common/execContext.h | 37 ++++ project2/common/iHaveParameters.cpp | 9 +- project2/common/iHaveParameters.h | 4 +- project2/common/iHaveSubTasks.cpp | 4 +- project2/common/iHaveSubTasks.h | 4 +- project2/common/if.cpp | 16 +- project2/common/if.h | 6 +- project2/common/iterate.cpp | 14 +- project2/common/iterate.h | 5 +- project2/common/library.cpp | 2 +- project2/common/memoryCache.cpp | 18 +- project2/common/noOutputExecute.h | 3 +- project2/common/options.cpp | 17 +- project2/common/options.h | 10 +- project2/common/optionsSource.cpp | 8 +- project2/common/optionsSource.h | 6 +- project2/common/presenter.cpp | 1 - project2/common/presenter.h | 4 +- project2/common/presenterCache.cpp | 6 +- project2/common/presenterCache.h | 4 +- project2/common/rowProcessor.cpp | 38 ++--- project2/common/rowProcessor.h | 10 +- project2/common/rowSet.cpp | 13 +- project2/common/rowSet.h | 14 +- project2/common/rowView.cpp | 47 +++--- project2/common/rowView.h | 9 +- project2/common/scriptLoader.cpp | 1 - project2/common/scripts.cpp | 8 +- project2/common/scripts.h | 7 +- project2/common/sessionClearTask.cpp | 8 +- project2/common/sessionClearTask.h | 2 +- project2/common/sessionContainer.cpp | 1 - project2/common/sessionSetTask.cpp | 8 +- project2/common/sessionSetTask.h | 2 +- project2/common/singleton.cpp | 16 +- project2/common/sourceObject.cpp | 2 +- project2/common/stream.h | 4 +- project2/common/structExceptHandling.cpp | 12 +- project2/common/structExceptHandling.h | 2 +- project2/common/task.h | 2 +- project2/common/taskHost.cpp | 4 +- project2/common/taskHost.h | 2 +- project2/common/test.h | 4 +- project2/common/transform.cpp | 18 +- project2/common/transform.h | 18 +- project2/common/variables.cpp | 17 +- project2/common/variables.h | 9 +- project2/common/variables/config.cpp | 13 +- project2/common/variables/fixed.cpp | 2 +- project2/common/variables/fixed.h | 2 +- project2/common/variables/literal.cpp | 22 +-- project2/common/variables/literal.h | 14 +- project2/common/variables/localparam.cpp | 8 +- project2/common/variables/lookup.cpp | 18 +- project2/common/variables/param.cpp | 12 +- project2/common/variables/session.cpp | 10 +- project2/common/view.h | 3 +- project2/common/viewGroup.cpp | 4 +- project2/common/viewHost.cpp | 14 +- project2/common/viewHost.h | 6 +- project2/compression/decompressStream.cpp | 6 +- project2/console/claOptions.cpp | 15 +- project2/console/claOptions.h | 2 +- project2/console/consoleAppEngine.cpp | 119 +++++++++---- project2/console/consoleAppEngine.h | 39 +++-- project2/console/consoleEnvironment.cpp | 100 ----------- project2/console/consoleEnvironment.h | 33 ---- project2/console/consolePresenter.cpp | 2 +- project2/console/consolePresenter.h | 2 +- project2/console/p2consoleMain.cpp | 21 +-- project2/console/pch.hpp | 1 - project2/files/fileStream.cpp | 4 +- project2/files/fsFilterMaxDepth.cpp | 4 +- project2/files/fsFilterName.cpp | 4 +- project2/files/fsFilterType.cpp | 4 +- project2/files/fsRows.cpp | 22 +-- project2/files/fsRows.h | 8 +- project2/files/functions/pwd.cpp | 2 +- project2/files/optionsSource.cpp | 4 +- project2/files/optionsSource.h | 2 +- project2/files/presenterCache.cpp | 27 ++- project2/files/writeStream.cpp | 8 +- project2/json/presenter-p.cpp | 8 +- project2/json/presenter.cpp | 10 +- project2/json/presenter.h | 6 +- project2/mail/sendmailTask.cpp | 39 +++-- project2/mail/sendmailTask.h | 2 +- project2/processes/processStream.cpp | 6 +- project2/regex/regexRows.cpp | 6 +- project2/regex/regexRows.h | 2 +- project2/regex/regexTest.cpp | 6 +- project2/regex/regexTest.h | 2 +- project2/sql/rdbmsDataSource.cpp | 8 +- project2/sql/sqlBulkLoad.cpp | 8 +- project2/sql/sqlCache.cpp | 20 +-- project2/sql/sqlMergeTask.cpp | 87 +++++----- project2/sql/sqlMergeTask.h | 8 +- project2/sql/sqlRows.cpp | 6 +- project2/sql/sqlRows.h | 2 +- project2/sql/sqlTask.cpp | 12 +- project2/sql/sqlTask.h | 2 +- project2/sql/sqlTest.cpp | 10 +- project2/sql/sqlTest.h | 2 +- project2/sql/sqlWriter.cpp | 16 +- project2/sql/sqlWriter.h | 10 +- project2/streams/streamNvpRows.cpp | 22 +-- project2/streams/streamRows.cpp | 22 +-- project2/streams/viewStream.cpp | 14 +- project2/url/curlHelper.cpp | 24 +-- project2/url/curlHelper.h | 8 +- project2/url/downloadToFile.cpp | 6 +- project2/url/urlStream.cpp | 4 +- project2/xml/mutators/copy.cpp | 6 +- project2/xml/mutators/copyToAttr.cpp | 6 +- project2/xml/mutators/create.cpp | 4 +- project2/xml/mutators/delete.cpp | 2 +- project2/xml/mutators/rename.cpp | 4 +- project2/xml/pch.hpp | 2 - project2/xml/rawView.cpp | 18 +- project2/xml/transformHtml.cpp | 4 +- project2/xml/transformHtml.h | 2 +- project2/xml/transformText.cpp | 12 +- project2/xml/transformText.h | 2 +- project2/xml/xmlCache.cpp | 17 +- project2/xml/xmlDocumentCache.cpp | 8 +- project2/xml/xmlDocumentCache.h | 10 +- project2/xml/xmlDocumentPrefetch.cpp | 20 +-- project2/xml/xmlDocumentPrefetch.h | 10 +- project2/xml/xmlPresenter.cpp | 15 +- project2/xml/xmlPresenter.h | 6 +- project2/xml/xmlRawRows.cpp | 13 +- project2/xml/xmlRawRows.h | 6 +- project2/xml/xmlRows.cpp | 10 +- project2/xml/xmlRows.h | 2 +- project2/xml/xmlScriptParser.cpp | 5 +- project2/xml/xmlScriptParser.h | 2 +- project2/xml/xpathRows.cpp | 24 +-- project2/xml/xpathRows.h | 8 +- 200 files changed, 1450 insertions(+), 1660 deletions(-) delete mode 100644 project2/cgi/cgiCommon.cpp delete mode 100644 project2/cgi/cgiCommon.h delete mode 100644 project2/cgi/cgiEnvironment.cpp delete mode 100644 project2/cgi/cgiEnvironment.h create mode 100644 project2/cgi/cgiRequestContext.cpp create mode 100644 project2/cgi/cgiRequestContext.h delete mode 100644 project2/common/appEngine.cpp delete mode 100644 project2/common/appEngine.h delete mode 100644 project2/common/environment.cpp delete mode 100644 project2/common/environment.h create mode 100644 project2/common/execContext.cpp create mode 100644 project2/common/execContext.h delete mode 100644 project2/console/consoleEnvironment.cpp delete mode 100644 project2/console/consoleEnvironment.h diff --git a/project2/basics/aggregates/avg.cpp b/project2/basics/aggregates/avg.cpp index 62239b3..900bc5f 100644 --- a/project2/basics/aggregates/avg.cpp +++ b/project2/basics/aggregates/avg.cpp @@ -12,7 +12,7 @@ class Average : public ValueAggregate { { vals.clear(); } - void pushValue(const VariableType & v) const + void pushValue(const VariableType & v, ExecContext *) const { if (!v.isNull()) { vals.push_back(v); diff --git a/project2/basics/aggregates/count.cpp b/project2/basics/aggregates/count.cpp index 725be72..be22783 100644 --- a/project2/basics/aggregates/count.cpp +++ b/project2/basics/aggregates/count.cpp @@ -11,7 +11,7 @@ class Count : public ValueAggregate { { c = 0; } - void pushValue(const VariableType & v) const + void pushValue(const VariableType & v, ExecContext *) const { if (!v.isNull()) { c += 1; diff --git a/project2/basics/aggregates/countDistinct.cpp b/project2/basics/aggregates/countDistinct.cpp index b471911..205b932 100644 --- a/project2/basics/aggregates/countDistinct.cpp +++ b/project2/basics/aggregates/countDistinct.cpp @@ -10,7 +10,7 @@ class CountDistinct : public ValueAggregate { { result.clear(); } - void pushValue(const VariableType & v) const + void pushValue(const VariableType & v, ExecContext *) const { result.insert(v); } diff --git a/project2/basics/aggregates/distinct.cpp b/project2/basics/aggregates/distinct.cpp index ebac934..6039588 100644 --- a/project2/basics/aggregates/distinct.cpp +++ b/project2/basics/aggregates/distinct.cpp @@ -11,7 +11,7 @@ class Distinct : public SetAggregate { { result.clear(); } - void pushValue(const VariableType & v) const + void pushValue(const VariableType & v, ExecContext *) const { result.insert(v); } diff --git a/project2/basics/aggregates/join.cpp b/project2/basics/aggregates/join.cpp index 841eb9a..405c093 100644 --- a/project2/basics/aggregates/join.cpp +++ b/project2/basics/aggregates/join.cpp @@ -13,10 +13,10 @@ class Join : public ValueAggregate { sum.clear(); first = true; } - void pushValue(const VariableType & v) const + void pushValue(const VariableType & v, ExecContext * ec) const { if (!first) { - sum += sep().as(); + sum += sep(ec).as(); } sum += v.as(); first = false; diff --git a/project2/basics/aggregates/max.cpp b/project2/basics/aggregates/max.cpp index ef904ed..6304647 100644 --- a/project2/basics/aggregates/max.cpp +++ b/project2/basics/aggregates/max.cpp @@ -8,7 +8,7 @@ class Max : public ValueAggregate { { result = VariableType(); } - void pushValue(const VariableType & v) const + void pushValue(const VariableType & v, ExecContext *) const { if (result < v) { result = v; diff --git a/project2/basics/aggregates/min.cpp b/project2/basics/aggregates/min.cpp index ee0bf3d..75b0b87 100644 --- a/project2/basics/aggregates/min.cpp +++ b/project2/basics/aggregates/min.cpp @@ -12,7 +12,7 @@ class Min : public ValueAggregate { result = VariableType(); first = true; } - void pushValue(const VariableType & v) const + void pushValue(const VariableType & v, ExecContext *) const { if (first || v < result) { result = v; diff --git a/project2/basics/aggregates/sum.cpp b/project2/basics/aggregates/sum.cpp index 9bc1120..68a9cd4 100644 --- a/project2/basics/aggregates/sum.cpp +++ b/project2/basics/aggregates/sum.cpp @@ -11,7 +11,7 @@ class Sum : public ValueAggregate { { sum = 0; } - void pushValue(const VariableType & v) const + void pushValue(const VariableType & v, ExecContext *) const { sum += v.as(); } diff --git a/project2/basics/functions/dates.cpp b/project2/basics/functions/dates.cpp index f2dcb20..b19b921 100644 --- a/project2/basics/functions/dates.cpp +++ b/project2/basics/functions/dates.cpp @@ -16,10 +16,10 @@ class ParseDate : public VariableImpl { format(e, "format") { } - VariableType value() const + VariableType value(ExecContext * ec) const { - const char * s = string(); - const char * f = format(); + const char * s = string(ec); + const char * f = format(ec); struct tm tm; memset(&tm, 0, sizeof(struct tm)); mktime(&tm); @@ -27,7 +27,7 @@ class ParseDate : public VariableImpl { if (!e || *e) { Logger()->messagef(LOG_ERR, "%s: check failed (parse) for '%s' against '%s' (remaining chars='%s')", __PRETTY_FUNCTION__, s, f, e); - throw DateParseError(string(), format()); + throw DateParseError(string(ec), format(ec)); } return boost::posix_time::ptime(boost::posix_time::ptime_from_tm(tm)); } @@ -44,13 +44,13 @@ class FormatDate : public VariableImpl { format(e, "format") { } - VariableType value() const + VariableType value(ExecContext * ec) const { std::stringstream ss; boost::date_time::time_facet * ft = new boost::date_time::time_facet(); ss.imbue(std::locale(ss.getloc(), ft)); - ft->format(format()); - ss << boost::get(date()); + ft->format(format(ec)); + ss << boost::get(date(ec)); return ss.str(); } private: @@ -66,9 +66,9 @@ class AdjustDate : public VariableImpl { offset(e, "offset") { } - VariableType value() const + VariableType value(ExecContext * ec) const { - return boost::get(date()) + boost::posix_time::duration_from_string(offset()); + return boost::get(date(ec)) + boost::posix_time::duration_from_string(offset(ec)); } private: Variable date; @@ -81,7 +81,7 @@ class CurrentDate : public VariableImpl { CurrentDate(ScriptNodePtr) { } - VariableType value() const + VariableType value(ExecContext *) const { return boost::posix_time::microsec_clock::universal_time(); } diff --git a/project2/basics/functions/strings.cpp b/project2/basics/functions/strings.cpp index d4ba7b7..735a781 100644 --- a/project2/basics/functions/strings.cpp +++ b/project2/basics/functions/strings.cpp @@ -10,9 +10,9 @@ class Trim : public VariableImpl { string(e, "string") { } - VariableType value() const + VariableType value(ExecContext * ec) const { - Glib::ustring str = string(); + Glib::ustring str = string(ec); Glib::ustring::const_iterator b = str.begin(); while (Glib::Unicode::isspace(*b)) ++b; Glib::ustring::const_iterator e = str.end(); diff --git a/project2/basics/pch.hpp b/project2/basics/pch.hpp index d52b275..0421cfb 100644 --- a/project2/basics/pch.hpp +++ b/project2/basics/pch.hpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include diff --git a/project2/basics/tests/compoundTest.cpp b/project2/basics/tests/compoundTest.cpp index b361db5..119026e 100644 --- a/project2/basics/tests/compoundTest.cpp +++ b/project2/basics/tests/compoundTest.cpp @@ -20,11 +20,11 @@ class All : public CompoundTest { SourceObject(s), CompoundTest(s) { } - bool passes() const { + bool passes(ExecContext * ec) const { if (tests.empty()) { throw NoTestsToPerform(); } - return (std::find_if(tests.begin(), tests.end(), !boost::bind(&Test::passes, _1)) == tests.end()); + return (std::find_if(tests.begin(), tests.end(), !boost::bind(&Test::passes, _1, ec)) == tests.end()); } }; DECLARE_LOADER("all", All); @@ -35,11 +35,11 @@ class Any : public CompoundTest { SourceObject(s), CompoundTest(s) { } - bool passes() const { + bool passes(ExecContext * ec) const { if (tests.empty()) { throw NoTestsToPerform(); } - return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) != tests.end()); + return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1, ec)) != tests.end()); } }; DECLARE_LOADER("any", Any); @@ -50,11 +50,11 @@ class None : public CompoundTest { SourceObject(s), CompoundTest(s) { } - bool passes() const { + bool passes(ExecContext * ec) const { if (tests.empty()) { throw NoTestsToPerform(); } - return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) == tests.end()); + return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1, ec)) == tests.end()); } }; DECLARE_LOADER("none", None); @@ -67,11 +67,11 @@ class Not : public Test { { s->script->loader.addLoadTarget(s, Storer::into(&test)); } - bool passes() const { + bool passes(ExecContext * ec) const { if (!test) { throw NoTestsToPerform(); } - return !test->passes(); + return !test->passes(ec); } private: TestPtr test; diff --git a/project2/basics/tests/equals.cpp b/project2/basics/tests/equals.cpp index ba8c695..6c7a74f 100644 --- a/project2/basics/tests/equals.cpp +++ b/project2/basics/tests/equals.cpp @@ -13,8 +13,8 @@ class Equals : public Test { { } - bool passes() const { - return (a() == b()); + bool passes(ExecContext * ec) const { + return (a(ec) == b(ec)); } private: diff --git a/project2/basics/tests/isdistinct.cpp b/project2/basics/tests/isdistinct.cpp index ab7bf1b..303f88d 100644 --- a/project2/basics/tests/isdistinct.cpp +++ b/project2/basics/tests/isdistinct.cpp @@ -17,13 +17,13 @@ class IsDistinct : public Test, IHaveParameters { void loadComplete(const CommonObjects *) { - findComponent(scope())->registerFor(RowProcessor::Complete, boost::bind(&IsDistinct::reset, this)); + findComponent(scope(NULL))->registerFor(RowProcessor::Complete, boost::bind(&IsDistinct::reset, this)); } - bool passes() const { + bool passes(ExecContext * ec) const { Vars row; BOOST_FOREACH(const Parameters::value_type & p, parameters) { - row.push_back(p.second()); + row.push_back(p.second(ec)); } return previous.insert(row).second; } diff --git a/project2/basics/tests/isuniq.cpp b/project2/basics/tests/isuniq.cpp index c14ea84..e33aba8 100644 --- a/project2/basics/tests/isuniq.cpp +++ b/project2/basics/tests/isuniq.cpp @@ -17,21 +17,21 @@ class IsUniq : public Test, IHaveParameters { void loadComplete(const CommonObjects *) { - findComponent(scope())->registerFor(RowProcessor::Complete, boost::bind(&IsUniq::reset, this)); + findComponent(scope(NULL))->registerFor(RowProcessor::Complete, boost::bind(&IsUniq::reset, this)); } - bool passes() const { + bool passes(ExecContext * ec) const { if (previous.size() > 0) { Vars row; BOOST_FOREACH(const Parameters::value_type & p, parameters) { - row.push_back(p.second()); + row.push_back(p.second(ec)); } std::swap(row, previous); return row != previous; } else { BOOST_FOREACH(const Parameters::value_type & p, parameters) { - previous.push_back(p.second()); + previous.push_back(p.second(ec)); } return true; } diff --git a/project2/basics/tests/validDateCheck.cpp b/project2/basics/tests/validDateCheck.cpp index 8dffd9d..b1ab5a3 100644 --- a/project2/basics/tests/validDateCheck.cpp +++ b/project2/basics/tests/validDateCheck.cpp @@ -13,7 +13,7 @@ class ValidDateTest : public Test { Test(p), applyTo(p, "apply-to"), format(p, "format"), - warnLev(p->value("warn", true).as() ? LOG_WARNING : LOG_INFO) + warnLev(p->value("warn", true, NULL).as() ? LOG_WARNING : LOG_INFO) { } @@ -22,13 +22,13 @@ class ValidDateTest : public Test { } bool - passes() const + passes(ExecContext * ec) const { struct tm tm, ftm; memset(&tm, 0, sizeof(struct tm)); mktime(&tm); - const char * at = applyTo(); - const char * f = format(); + const char * at = applyTo(ec); + const char * f = format(ec); const char * s = strptime(at, f, &tm); if (!s || *s) { Logger()->messagef(warnLev, "%s: check failed (parse) for '%s' against '%s'", diff --git a/project2/cgi/Jamfile.jam b/project2/cgi/Jamfile.jam index cf6e55c..8da2f11 100644 --- a/project2/cgi/Jamfile.jam +++ b/project2/cgi/Jamfile.jam @@ -57,4 +57,3 @@ exe testCgi : p2cgicommon ../../libmisc ; - diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 75bc004..2a82595 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -3,45 +3,83 @@ #include "cgiResult.h" #include #include -#include "cgiEnvironment.h" +#include +#include "cgiRequestContext.h" #include "iterate.h" #include #include #include "ostreamWrapper.h" #include "scopeObject.h" +#include "logger.h" #include #include -#include #include +#include +#include -const std::string SESSIONID = "sessionID"; typedef boost::uuids::uuid SIDKey; typedef std::string SValue; SimpleMessageException(UnknownDomain); -CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) : - _env(e), - sessionsContainer(SessionContainerLoader::getFor(e->sessionModule)->create()), - IO(io), - outputCachingActive(false) -{ - try { - cursession = sessionsContainer->GetSession(boost::uuids::string_generator()(e->getCookieValue(SESSIONID))); - } - catch (const NoSuchCookie &) { - cursession = sessionsContainer->GetSession(boost::uuids::uuid()); - } -} +std::string CgiApplicationEngine::dumpdatadoc; +Glib::ustring CgiApplicationEngine::errorContentType; +Glib::ustring CgiApplicationEngine::errorTransformStyle; +std::string CgiApplicationEngine::defaultPresent; +std::string CgiApplicationEngine::transformContentType; +std::string CgiApplicationEngine::transformTargetType; +std::string CgiApplicationEngine::presentRoot; +std::string CgiApplicationEngine::requestRoot; +std::string CgiApplicationEngine::errorPresentRoot; +std::string CgiApplicationEngine::notFoundPresent; +std::string CgiApplicationEngine::onErrorPresent; +std::string CgiApplicationEngine::defaultPresenter; +SessionContainerPtr CgiApplicationEngine::sessionsContainer; +std::string CgiApplicationEngine::sessionCookie; +boost::shared_ptr CgiApplicationEngine::router; +boost::intrusive_ptr CgiApplicationEngine::hpi; -CgiApplicationEngine::~CgiApplicationEngine() +DECLARE_OPTIONS(CgiApplicationEngine, "Project2 CGI options") +("cgi.defaultPresenter", Options::value(&defaultPresenter, "xml"), + "The default engine for formatting presentations") +("cgi.transformContentType", Options::value(&transformContentType, "text/xml-xslt"), + "The content type specified to enable standard internal transformations") +("cgi.transformTargetType", Options::value(&transformTargetType, "htmldocument"), + "The transform target type used in standard internal transformations") +("cgi.defaultPresent", Options::value(&defaultPresent, "index"), + "The present script to use when no other is specified") +("cgi.presentRoot", Options::value(&presentRoot, "present"), + "The folder in which to find presentation scripts") +("cgi.requestRoot", Options::value(&requestRoot, "request"), + "The folder in which to find request scripts") +("cgi.errorPresentRoot", Options::value(&errorPresentRoot, "error"), + "The folder in which to find presentation scripts for error handling") +("cgi.errorContentType", Options::value(&errorContentType, "application/xml"), + "The Content-Type to use in HTTP headers in event of an error") +("cgi.errorTransformStyle", Options::value(&errorTransformStyle), + "The xml-stylesheet to specify in the data document in event of an error") +("cgi.notFoundPresent", Options::value(¬FoundPresent), + "The present script to use when the requested script does not exist") +("cgi.onErrorPresent", Options::value(&onErrorPresent), + "The present script to use when the requested script (or child) fails") +("cgi.dumpDataDoc", Options::value(&dumpdatadoc), + "Write a copy of the data document before sending it to the web server") +("cgi.sessionModule", Options::function([](const VariableType & m) { sessionsContainer = SessionContainerLoader::createNew(m); }, "xml"), + "The module with which to implement session management") +("cgi.sessionCookie", Options::value(&sessionCookie, "sessionID"), + "The name of the cookie for storing session IDs") +("cgi.hostRegex", (hpi = new HostnamePlatformIdentifier()), + "Regular expression used to define a hostname -> platform association") +("cgi.router", Options::function([](const VariableType & r) { router = RouterLoader::getFor(r); }, "simple"), + "Implemenation of router model to map request paths to scripts") +END_OPTIONS(CgiApplicationEngine); + +CgiApplicationEngine::CgiApplicationEngine() { } -const CgiEnvironment * -CgiApplicationEngine::env() const +CgiApplicationEngine::~CgiApplicationEngine() { - return _env; } TransformSourcePtr @@ -61,51 +99,51 @@ finalTransformSource(TransformSourcePtr ts) } void -CgiApplicationEngine::process() const +CgiApplicationEngine::processRun(std::ostream & IO, CgiRequestContext * crc) const { - bool sessionEmpty = cursession->Empty(); - startTime = boost::date_time::microsec_clock::universal_time(); + bool sessionEmpty = crc->getSession()->Empty(); + crc->startTime = boost::date_time::microsec_clock::universal_time(); bool triedNotFound = false; bool triedOnError = false; NextStage currentStage = NextStage(new InitialStage()); do { try { - currentStage = currentStage.get<0>()->run(); + currentStage = currentStage.get<0>()->run(crc); } catch (const CheckHost::CheckFailure & cf) { - currentStage = NextStage(new PresentStage(ScriptReader::resolveScript(_env->presentRoot, cf.failedCheck->present(), false))); + currentStage = NextStage(new PresentStage(ScriptReader::resolveScript(presentRoot, cf.failedCheck->present(crc), false), crc)); } catch (const ScriptNotFound & nf) { - if (_env->notFoundPresent.empty() || triedNotFound) { + if (notFoundPresent.empty() || triedNotFound) { currentStage = NextStage(new DefaultNotFoundStage(nf)); } else { triedNotFound = true; - currentStage = NextStage(new CustomNotFoundStage(nf, ScriptReader::resolveScript(_env->errorPresentRoot, _env->notFoundPresent, false))); + currentStage = NextStage(new CustomNotFoundStage(nf, ScriptReader::resolveScript(errorPresentRoot, notFoundPresent, false), crc)); } } catch (const std::exception & ex) { - if (_env->onErrorPresent.empty() || triedOnError) { - currentStage = NextStage(new DefaultErrorStage(ex)); + if (onErrorPresent.empty() || triedOnError) { + currentStage = NextStage(new DefaultErrorStage(ex, crc)); } else { triedNotFound = true; - currentStage = NextStage(new CustomErrorStage(ex, ScriptReader::resolveScript(_env->errorPresentRoot, _env->onErrorPresent, false))); + currentStage = NextStage(new CustomErrorStage(ex, ScriptReader::resolveScript(errorPresentRoot, onErrorPresent, false), crc)); } } } while (currentStage.get<0>()); - endTime = boost::date_time::microsec_clock::universal_time(); + crc->endTime = boost::date_time::microsec_clock::universal_time(); ResponseStagePtr rs = currentStage.get<1>(); - outputCachingActive = !rs->caches.empty(); + bool outputCachingActive = !rs->caches.empty(); if (const MultiRowSetPresenter * p = currentStage.get<3>().get()) { - addAppData(p, rs->outputOptions); - addEnvData(p, rs->outputOptions); + addAppData(p, rs->outputOptions, crc, outputCachingActive); + addEnvData(p, rs->outputOptions, crc, outputCachingActive); } - HttpHeaderPtr header = rs->getHeader(); - if (!sessionEmpty || !cursession->Empty()) { - sessionsContainer->SaveSession(cursession); - header->setCookie(cgicc::HTTPCookie(SESSIONID, boost::lexical_cast(cursession->ID()), "Session ID", - _env->getServerName().substr(_env->getServerName().find(".")), SessionContainer::sessionTimeOut, "/", false)); + HttpHeaderPtr header = rs->getHeader(crc); + if (!sessionEmpty || !crc->getSession()->Empty()) { + sessionsContainer->SaveSession(crc->getSession()); + header->setCookie(cgicc::HTTPCookie(sessionCookie, boost::lexical_cast(crc->getSession()->ID()), "Session ID", + crc->getServerName().substr(crc->getServerName().find(".")), SessionContainer::sessionTimeOut, "/", false)); } if (TransformSourcePtr ts = currentStage.get<2>()) { TransformSourcePtr final = finalTransformSource(ts); @@ -113,10 +151,10 @@ CgiApplicationEngine::process() const boost::shared_ptr ddd; ostreamWrapper * osw = NULL; ScopeObject removeDdd([ts, &osw] { if (osw) { ts->removeTarget(osw); } }); - if (!_env->dumpdatadoc.empty()) { - ddd = boost::shared_ptr(new std::fstream(_env->dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out)); + if (!dumpdatadoc.empty()) { + ddd = boost::shared_ptr(new std::fstream(dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out)); if (ddd->good()) { - ts->addTarget(osw = new ostreamWrapper(*ddd)); + ts->addTarget(osw = new ostreamWrapper(*ddd), crc, NULL); } else { ddd.reset(); @@ -124,23 +162,23 @@ CgiApplicationEngine::process() const } if (outputCachingActive) { BOOST_FOREACH(const PresenterCachePtr & p, rs->caches) { - final->addTarget(p, NULL); + final->addTarget(p, crc, NULL); } - ts->doTransforms(); + ts->doTransforms(crc); BOOST_FOREACH(const PresenterCachePtr & p, rs->caches) { p->flushCache(); } - if (rs->caches.front()->check(0)) { + if (rs->caches.front()->check(0, crc)) { ScopeObject emptyFinal([rs] { rs->caches.front()->clearTargets(); }); rs->caches.front()->addTarget(new CgiResult(header, IO, - rs && rs->outputOptions ? rs->outputOptions->Encoding().as() : OutputOptions::encoding), NULL); - rs->caches.front()->doTransforms(); + rs && rs->outputOptions ? rs->outputOptions->Encoding(crc).as() : OutputOptions::encoding), crc, NULL); + rs->caches.front()->doTransforms(crc); return; } } final->addTarget(new CgiResult(header, IO, - rs && rs->outputOptions ? rs->outputOptions->Encoding().as() : OutputOptions::encoding), NULL); - ts->doTransforms(); + rs && rs->outputOptions ? rs->outputOptions->Encoding(crc).as() : OutputOptions::encoding), crc, NULL); + ts->doTransforms(crc); } else { header->render(IO); @@ -151,44 +189,38 @@ CgiApplicationEngine::Stage::~Stage() { } -const CgiEnvironment * -CgiApplicationEngine::Stage::env() const -{ - return dynamic_cast(Environment::getCurrent()); -} - void -CgiApplicationEngine::addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o) const +CgiApplicationEngine::addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext * crc, bool outputCachingActive) const { - if (!o || o->Environment()) { + if (!o || o->Environment(crc)) { // Environment set up by web server p->addNewRowSet("environment", Scripts::scriptNamespacePrefix); // Server stuff - addEnvToPresenter(p, "servername", &cgicc::CgiEnvironment::getServerName); - addEnvToPresenter(p, "serversoftware", &cgicc::CgiEnvironment::getServerSoftware); - addEnvToPresenter(p, "serverprotocol", &cgicc::CgiEnvironment::getServerProtocol); - addEnvToPresenter(p, "serverport", &cgicc::CgiEnvironment::getServerPort); - addEnvToPresenter(p, "serverhttps", &cgicc::CgiEnvironment::usingHTTPS); + addEnvToPresenter(p, "servername", &cgicc::CgiEnvironment::getServerName, crc); + addEnvToPresenter(p, "serversoftware", &cgicc::CgiEnvironment::getServerSoftware, crc); + addEnvToPresenter(p, "serverprotocol", &cgicc::CgiEnvironment::getServerProtocol, crc); + addEnvToPresenter(p, "serverport", &cgicc::CgiEnvironment::getServerPort, crc); + addEnvToPresenter(p, "serverhttps", &cgicc::CgiEnvironment::usingHTTPS, crc); // Request stuff if (!outputCachingActive) { - addEnvToPresenter(p, "referrer", &cgicc::CgiEnvironment::getReferrer); - addEnvToPresenter(p, "querystring", &cgicc::CgiEnvironment::getQueryString); + addEnvToPresenter(p, "referrer", &cgicc::CgiEnvironment::getReferrer, crc); + addEnvToPresenter(p, "querystring", &cgicc::CgiEnvironment::getQueryString, crc); } p->finishRowSet(); } - if (!o || o->URL()) { + if (!o || o->URL(crc)) { // URL elements p->addNewRowSet("uriElems", Scripts::scriptNamespacePrefix); - p->addAttribute("full", _env->getRedirectURL()); - _env->router->present(p); + p->addAttribute("full", crc->getRedirectURL()); + crc->router->present(p); p->finishRowSet(); } - if (!o || o->Parameters()) { + if (!o || o->Parameters(crc)) { // Parameters p->addNewRowSet("params", Scripts::scriptNamespacePrefix); - BOOST_FOREACH(cgicc::FormEntry fe, _env->cgi->getElements()) { + BOOST_FOREACH(cgicc::FormEntry fe, crc->cgi.getElements()) { p->addNamedValue(fe.getName(), fe.getValue()); } p->finishRowSet(); @@ -202,34 +234,78 @@ CgiApplicationEngine::addVarToPresenter(const MultiRowSetPresenter * p, const Gl } void -CgiApplicationEngine::addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o) const +CgiApplicationEngine::addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext * crc, bool outputCachingActive) const { - if (!o || o->Core()) { - addCoreAppData(p); + if (!o || o->Core(crc)) { + crc->addContextData(p); } - if (!outputCachingActive && (!cursession->Empty()) && (!o || o->Session())) { + if (!outputCachingActive && (!crc->getSession()->Empty()) && (!o || o->Session(crc))) { // Sessions variables p->addNewRowSet("session", Scripts::scriptNamespacePrefix); - p->addAttribute("id", boost::lexical_cast(cursession->ID())); - cursession->ForeachValue(boost::bind(&CgiApplicationEngine::addVarToPresenter, this, p, _1, _2)); + p->addAttribute("id", boost::lexical_cast(crc->getSession()->ID())); + crc->getSession()->ForeachValue(boost::bind(&CgiApplicationEngine::addVarToPresenter, this, p, _1, _2)); p->finishRowSet(); } - if (!outputCachingActive && (!o || o->Timing())) { + if (!outputCachingActive && (!o || o->Timing(crc))) { // Timing info p->addNewRowSet("timing", Scripts::scriptNamespacePrefix); - p->addAttribute("start", startTime); - if (!endTime.is_not_a_date_time()) { - p->addAttribute("end", endTime); - p->addAttribute("duration", (endTime - startTime).total_milliseconds()); + p->addAttribute("start", crc->startTime); + if (!crc->endTime.is_not_a_date_time()) { + p->addAttribute("end", crc->endTime); + p->addAttribute("duration", (crc->endTime - crc->startTime).total_milliseconds()); } p->finishRowSet(); } } -SessionPtr -CgiApplicationEngine::session() const +const char * +what(const Glib::Exception & e) +{ + return e.what().c_str(); +} +const char * +what(const std::exception & e) { - return cursession; + return e.what(); +} +template +void +doExceptionReporting(const E & e, std::ostream & IO) +{ + char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL); + Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, what(e)); + cgicc::HTTPStatusHeader header(500, e.what()); + header.render(IO); + IO << "Kaboom!" << std::endl + << std::endl + << buf << std::endl + << "what '" << e.what() << "'" << std::endl; + free(buf); +} + +void +CgiApplicationEngine::process(std::ostream & IO, CgiRequestContext * crc) const +{ + try { + Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__); + processRun(IO, crc); + Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__); + } + catch (const std::exception & e) { + doExceptionReporting(e, IO); + } + catch (const Glib::Exception & e) { + doExceptionReporting(e, IO); + } + catch (...) { + Logger()->messagef(LOG_ERR, "%s: Request errored: Unknown exception", __FUNCTION__); + cgicc::HTTPStatusHeader header(500, "Unknown exception"); + header.render(IO); + IO << "Kaboom!" << std::endl + << std::endl + << "Unknown exception." << std::endl; + throw; + } } diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index f5f0e08..6d3cd0c 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -1,7 +1,6 @@ #ifndef CGIAPPENGINE_H #define CGIAPPENGINE_H -#include "appEngine.h" #include "task.h" #include "commonObjects.h" #include "taskHost.h" @@ -15,7 +14,7 @@ #include #include "cgiOutputOptions.h" #include "cgiHttpHeader.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include class Session; @@ -24,29 +23,26 @@ namespace cgicc { class CgiEnvironment; } -class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink { +class CgiApplicationEngine { public: typedef boost::shared_ptr HttpHeaderPtr; - CgiApplicationEngine(const CgiEnvironment *, std::ostream &); + CgiApplicationEngine(); virtual ~CgiApplicationEngine(); - void process() const; - const CgiEnvironment * env() const; - SessionPtr session() const; - void addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr) const; - void addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr) const; + void process(std::ostream & IO, CgiRequestContext *) const; private: - const CgiEnvironment * _env; - mutable boost::posix_time::ptime startTime; - mutable boost::posix_time::ptime endTime; - SessionContainerPtr sessionsContainer; + void processRun(std::ostream & IO, CgiRequestContext *) const; + void addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext *, bool) const; + void addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext *, bool) const; + // Helpers + // void addVarToPresenter(const MultiRowSetPresenter * p, const Glib::ustring & name, const VariableType &) const; template - void addEnvToPresenter(const MultiRowSetPresenter * p, const char * name, X (Y::*getter)() const) const { - addVarToPresenter(p, name, (_env->cgi->getEnvironment().*getter)()); + void addEnvToPresenter(const MultiRowSetPresenter * p, const char * name, X (Y::*getter)() const, CgiRequestContext * crc) const { + addVarToPresenter(p, name, (crc->cgi.getEnvironment().*getter)()); } public: @@ -59,9 +55,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink class Stage : public virtual IntrusivePtrBase { public: virtual ~Stage() = 0; - virtual NextStage run() = 0; - protected: - const CgiEnvironment * env() const; + virtual NextStage run(CgiRequestContext *) = 0; }; /// Base class for a stage that can be a response to the client @@ -70,7 +64,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink typedef ANONORDEREDSTORAGEOF(PresenterCache) PresenterCaches; ResponseStage(ScriptNodePtr root); - virtual HttpHeaderPtr getHeader() const = 0; + virtual HttpHeaderPtr getHeader(CgiRequestContext *) const = 0; OutputOptionsPtr outputOptions; ScriptNodePtr root; @@ -80,7 +74,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// Stage implementation used to bootstrap the iteration process based on the CGI environment class InitialStage : public Stage { public: - virtual NextStage run(); + virtual NextStage run(CgiRequestContext *); }; /// Stage to process POST requests @@ -88,8 +82,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink public: RequestStage(ScriptReaderPtr); - virtual NextStage run(); - virtual HttpHeaderPtr getHeader() const; + virtual NextStage run(CgiRequestContext *); + virtual HttpHeaderPtr getHeader(CgiRequestContext *) const; protected: Variable present; Variable redirect; @@ -98,11 +92,11 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// Stage to process GET requests and follow up RequestStages class PresentStage : public virtual ResponseStage, ViewHost { public: - PresentStage(ScriptReaderPtr); - MultiRowSetPresenterPtr getPresenter() const; + PresentStage(ScriptReaderPtr, CgiRequestContext *); + MultiRowSetPresenterPtr getPresenter(ExecContext *) const; - virtual NextStage run(); - virtual HttpHeaderPtr getHeader() const; + virtual NextStage run(CgiRequestContext *); + virtual HttpHeaderPtr getHeader(CgiRequestContext *) const; protected: HttpHeaderPtr header; LazyPointer presenter; @@ -113,8 +107,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink public: CacheHitStage(ScriptNodePtr, PresenterCachePtr); - virtual NextStage run(); - virtual HttpHeaderPtr getHeader() const; + virtual NextStage run(CgiRequestContext *); + virtual HttpHeaderPtr getHeader(CgiRequestContext *) const; protected: PresenterCachePtr pc; }; @@ -124,8 +118,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink public: DefaultNotFoundStage(const ScriptNotFound &); - virtual NextStage run(); - virtual HttpHeaderPtr getHeader() const; + virtual NextStage run(CgiRequestContext *); + virtual HttpHeaderPtr getHeader(CgiRequestContext *) const; private: const ScriptNotFound nf; XmlPresenterPtr pres; @@ -134,19 +128,19 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// Custom not found handling stage class CustomNotFoundStage : public DefaultNotFoundStage, public PresentStage { public: - CustomNotFoundStage(const ScriptNotFound &, ScriptReaderPtr); - virtual NextStage run(); - virtual HttpHeaderPtr getHeader() const; + CustomNotFoundStage(const ScriptNotFound &, ScriptReaderPtr, CgiRequestContext *); + virtual NextStage run(CgiRequestContext *); + virtual HttpHeaderPtr getHeader(CgiRequestContext *) const; }; /// The built-in fail-safe unhandled error stage class DefaultErrorStage : public virtual ResponseStage { public: - DefaultErrorStage(const std::exception &); + DefaultErrorStage(const std::exception &, CgiRequestContext *); ~DefaultErrorStage(); - virtual NextStage run(); - virtual HttpHeaderPtr getHeader() const; + virtual NextStage run(CgiRequestContext *); + virtual HttpHeaderPtr getHeader(CgiRequestContext *) const; private: char * buf; std::string what; @@ -156,15 +150,29 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink /// Custom unhandled error handling stage class CustomErrorStage : public DefaultErrorStage, public PresentStage { public: - CustomErrorStage(const std::exception &, ScriptReaderPtr); - virtual NextStage run(); - virtual HttpHeaderPtr getHeader() const; + CustomErrorStage(const std::exception &, ScriptReaderPtr, CgiRequestContext *); + virtual NextStage run(CgiRequestContext *); + virtual HttpHeaderPtr getHeader(CgiRequestContext *) const; }; + INITOPTIONS; + static boost::intrusive_ptr hpi; + static boost::shared_ptr router; + static SessionContainerPtr sessionsContainer; + static std::string sessionCookie; private: - SessionPtr cursession; - std::ostream & IO; - mutable bool outputCachingActive; + static std::string dumpdatadoc; + static Glib::ustring errorContentType; + static Glib::ustring errorTransformStyle; + static std::string defaultPresent; + static std::string transformContentType; + static std::string transformTargetType; + static std::string presentRoot; + static std::string requestRoot; + static std::string errorPresentRoot; + static std::string notFoundPresent; + static std::string onErrorPresent; + static std::string defaultPresenter; }; #endif diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp deleted file mode 100644 index a4ed8c4..0000000 --- a/project2/cgi/cgiCommon.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include "cgiCommon.h" -#include "optionsSource.h" -#include "logger.h" -#include -#include -#include -#include -#include "cgiAppEngine.h" -#include -#include - -// These are templates because some people don't inherit their -// exceptions from std::exception like normal people (Glib) -const char * -what(const Glib::Exception & e) -{ - return e.what().c_str(); -} -const char * -what(const std::exception & e) -{ - return e.what(); -} -template -void -doExceptionReporting(const E & e, std::ostream & IO) -{ - char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL); - Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, what(e)); - cgicc::HTTPStatusHeader header(500, e.what()); - header.render(IO); - IO << "Kaboom!" << std::endl - << std::endl - << buf << std::endl - << "what '" << e.what() << "'" << std::endl; - free(buf); -} - -void -cgiServe(cgicc::CgiInput * i, CgiEnvironment * env, std::ostream & IO, const CgiEnvInput * e) -{ - try { - cgicc::Cgicc cgi(i); - env->setCGICC(&cgi, e); - OptionsSource::loadSources(); - CgiApplicationEngine app(env, IO); - - Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1)); - Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__); - app.process(); - Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__); - } - catch (const std::exception & e) { - doExceptionReporting(e, IO); - } - catch (const Glib::Exception & e) { - doExceptionReporting(e, IO); - } - catch (...) { - Logger()->messagef(LOG_ERR, "%s: Request errored: Unknown exception", __FUNCTION__); - cgicc::HTTPStatusHeader header(500, "Unknown exception"); - header.render(IO); - IO << "Kaboom!" << std::endl - << std::endl - << "Unknown exception." << std::endl; - throw; - } -} - diff --git a/project2/cgi/cgiCommon.h b/project2/cgi/cgiCommon.h deleted file mode 100644 index 42a88e6..0000000 --- a/project2/cgi/cgiCommon.h +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include -#include "cgiEnvironment.h" - -void cgiServe(cgicc::CgiInput * i, CgiEnvironment *, std::ostream & o, const CgiEnvInput * e); - diff --git a/project2/cgi/cgiContentNegotiate.cpp b/project2/cgi/cgiContentNegotiate.cpp index a7f7557..0b6623e 100644 --- a/project2/cgi/cgiContentNegotiate.cpp +++ b/project2/cgi/cgiContentNegotiate.cpp @@ -6,20 +6,20 @@ class ContentNegotiateLoader : public PresenterLoader { public: - MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os) const + MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os, ExecContext * const & ec) const { - auto accept = static_cast(CgiApplicationEngine::getCurrent())->env()->getAccept(); + auto accept = static_cast(ec)->getAccept(); typedef boost::tokenizer> tokenizer; BOOST_FOREACH(auto mimetypeAndWeight, tokenizer(accept, boost::char_separator(","))) { const auto mimetype = mimetypeAndWeight.substr(0, mimetypeAndWeight.find(';')); if (mimetype == "*/*") break; BOOST_FOREACH(const auto & t, mappedTypes) { if (t->Matches(mimetype)) { - return PresenterLoader::getFor(t->present)->create(s, os); + return PresenterLoader::getFor(t->present)->create(s, os, ec); } } } - return PresenterLoader::getFor((*mappedTypes.begin())->present)->create(s, os); + return PresenterLoader::getFor((*mappedTypes.begin())->present)->create(s, os, ec); } INITOPTIONS; diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp deleted file mode 100644 index d2ecf77..0000000 --- a/project2/cgi/cgiEnvironment.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include -#include -#include -#include -#include "cgiEnvironment.h" -#include "appEngine.h" -#include "exceptions.h" -#include -#include -#include -#include - -std::string CgiEnvironment::dumpdatadoc; -Glib::ustring CgiEnvironment::errorContentType; -Glib::ustring CgiEnvironment::errorTransformStyle; -std::string CgiEnvironment::defaultPresent; -std::string CgiEnvironment::transformContentType; -std::string CgiEnvironment::transformTargetType; -std::string CgiEnvironment::presentRoot; -std::string CgiEnvironment::requestRoot; -std::string CgiEnvironment::errorPresentRoot; -std::string CgiEnvironment::notFoundPresent; -std::string CgiEnvironment::onErrorPresent; -std::string CgiEnvironment::defaultPresenter; -std::string CgiEnvironment::sessionModule; -std::string CgiEnvironment::routerType; -boost::intrusive_ptr CgiEnvironment::hpi; - -DECLARE_OPTIONS(CgiEnvironment, "Project2 CGI options") -("cgi.defaultPresenter", Options::value(&defaultPresenter, "xml"), - "The default engine for formatting presentations") -("cgi.transformContentType", Options::value(&transformContentType, "text/xml-xslt"), - "The content type specified to enable standard internal transformations") -("cgi.transformTargetType", Options::value(&transformTargetType, "htmldocument"), - "The transform target type used in standard internal transformations") -("cgi.defaultPresent", Options::value(&defaultPresent, "index"), - "The present script to use when no other is specified") -("cgi.presentRoot", Options::value(&presentRoot, "present"), - "The folder in which to find presentation scripts") -("cgi.requestRoot", Options::value(&requestRoot, "request"), - "The folder in which to find request scripts") -("cgi.errorPresentRoot", Options::value(&errorPresentRoot, "error"), - "The folder in which to find presentation scripts for error handling") -("cgi.errorContentType", Options::value(&errorContentType, "application/xml"), - "The Content-Type to use in HTTP headers in event of an error") -("cgi.errorTransformStyle", Options::value(&errorTransformStyle), - "The xml-stylesheet to specify in the data document in event of an error") -("cgi.notFoundPresent", Options::value(¬FoundPresent), - "The present script to use when the requested script does not exist") -("cgi.onErrorPresent", Options::value(&onErrorPresent), - "The present script to use when the requested script (or child) fails") -("cgi.dumpDataDoc", Options::value(&dumpdatadoc), - "Write a copy of the data document before sending it to the web server") -("cgi.sessionModule", Options::value(&sessionModule, "xml"), - "The module with which to implement session management") -("cgi.hostRegex", (hpi = new HostnamePlatformIdentifier()), - "Regular expression used to define a hostname -> platform association") -("cgi.router", Options::value(&routerType, "simple"), - "Implemenation of router model to map request paths to scripts") -END_OPTIONS(CgiEnvironment); - -CgiEnvironment::CgiEnvironment() : - cgi(NULL), - cgienv(NULL) -{ -} - -CgiEnvironment::~CgiEnvironment() -{ -} - -void -CgiEnvironment::setCGICC(const cgicc::Cgicc * c, const CgiEnvInput * e) -{ - cgi = c; - cgienv = e; - router = boost::bind(&GenLoader::createNew, boost::cref(routerType), getRedirectURL()); -} - -std::string -CgiEnvironment::getCookieValue(const std::string & name) const -{ - BOOST_FOREACH(const cgicc::HTTPCookie & c, cgi->getEnvironment().getCookieList()) { - if (c.getName() == name) { - return c.getValue(); - } - } - throw NoSuchCookie(name); -} - -std::string -CgiEnvironment::getRequestMethod() const -{ - return cgi->getEnvironment().getRequestMethod(); -} - -std::string -CgiEnvironment::getRedirectURL() const -{ - return cgi->getEnvironment().getRedirectURL(); -} - -std::string -CgiEnvironment::getServerName() const -{ - return cgi->getEnvironment().getServerName(); -} - -std::string -CgiEnvironment::getAccept() const -{ - return cgi->getEnvironment().getAccept(); -} - -const Glib::ustring & -CgiEnvironment::platform() const -{ - return hpi->derivedPlatform(); -} - -CgiEnvironment::ETags -CgiEnvironment::getRequestETags() const -{ - const std::string e = cgienv->getenv("HTTP_IF_NONE_MATCH"); - ETags etags; - boost::split(etags, e, boost::is_any_of(" ,"), boost::algorithm::token_compress_on); - return etags; -} - -time_t -CgiEnvironment::getRequestModifiedSince() const -{ - return curl_getdate(cgienv->getenv("HTTP_IF_MODIFIED_SINCE").c_str(), NULL); -} - -Glib::ustring -CgiEnvironment::getParamUri(VariableType p) const -{ - return router->routeParameter(p); -} - -unsigned int -CgiEnvironment::getParamUriCount() const -{ - return router->parameterCount(); -} - -void -CgiEnvironment::applyAllParameters(const boost::function & func) const -{ - BOOST_FOREACH(const auto & f, cgi->getElements()) { - func(f.getName(), f.getValue()); - } -} - -Glib::ustring -CgiEnvironment::getParamQuery(const std::string & p) const -{ - cgicc::const_form_iterator i = cgi->getElement(p); - if (i == cgi->getElements().end()) { - throw ParamNotFound(p); - } - return (*cgi)(p); -} - -HostnamePlatformIdentifier::HostnamePlatformIdentifier() : - platform(NULL) -{ -} - -HostnamePlatformIdentifier::~HostnamePlatformIdentifier() -{ - reset(); -} - -const Glib::ustring & -HostnamePlatformIdentifier::derivedPlatform() const -{ - if (platform) { - return *platform; - } - throw NoSuchPlatform(Environment::getCurrent()->getServerName()); -} - -void -HostnamePlatformIdentifier::reset() const -{ - if (platform) { - delete platform; - platform = NULL; - } -} - -bool -HostnamePlatformIdentifier::paramRequired() const -{ - return true; -} - -void -HostnamePlatformIdentifier::consume(const Glib::ustring & p, const VariableType & r) const -{ - if (!platform && Glib::Regex::create(r, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL)->match(Environment::getCurrent()->getServerName())) { - platform = new Glib::ustring(p); - } -} - diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h deleted file mode 100644 index e9de59d..0000000 --- a/project2/cgi/cgiEnvironment.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef ENVPROC_H -#define ENVPROC_H - -#include -#include -#include "environment.h" -#include "cgiEnvInput.h" -#include "cgiRouter.h" -#include -#include - -SimpleMessageException(NoSuchCookie); - -namespace cgicc { - class Cgicc; -} - -class HostnamePlatformIdentifier : public Options::Target { - public: - HostnamePlatformIdentifier(); - virtual ~HostnamePlatformIdentifier(); - void reset() const; - bool paramRequired() const; - void consume(const Glib::ustring &, const VariableType &) const; - const Glib::ustring & derivedPlatform() const; - private: - mutable Glib::ustring * platform; -}; - -class CgiEnvironment : public Environment { - public: - typedef std::string ETag; - typedef std::vector ETags; - - CgiEnvironment(); - virtual ~CgiEnvironment(); - - Glib::ustring getParamUri(VariableType idx) const; - unsigned int getParamUriCount() const; - Glib::ustring getParamQuery(const std::string & idx) const; - void applyAllParameters(const boost::function &) const; - std::string getServerName() const; - std::string getRedirectURL() const; - std::string getRequestMethod() const; - std::string getAccept() const; - ETags getRequestETags() const; - time_t getRequestModifiedSince() const; - std::string getCookieValue(const std::string & name) const; - - void setCGICC(const cgicc::Cgicc *, const CgiEnvInput * cgienv); - const cgicc::Cgicc * cgi; - const CgiEnvInput * cgienv; - - private: - const Glib::ustring & platform() const; - - public: - INITOPTIONS; - static boost::intrusive_ptr hpi; - static std::string dumpdatadoc; - static Glib::ustring errorContentType; - static Glib::ustring errorTransformStyle; - static std::string defaultPresent; - static std::string transformContentType; - static std::string transformTargetType; - static std::string presentRoot; - static std::string requestRoot; - static std::string errorPresentRoot; - static std::string notFoundPresent; - static std::string onErrorPresent; - static std::string defaultPresenter; - static std::string sessionModule; - static std::string routerType; - typedef LazyPointer RouterPtr; - RouterPtr router; -}; - -#endif diff --git a/project2/cgi/cgiProgRouter.cpp b/project2/cgi/cgiProgRouter.cpp index e8ae15d..8fce50d 100644 --- a/project2/cgi/cgiProgRouter.cpp +++ b/project2/cgi/cgiProgRouter.cpp @@ -1,7 +1,10 @@ #include #include +#include #include -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" +#include "commonObjects.h" +#include "rowProcessor.h" #include "presenter.h" #include "safeMapFind.h" #include "scriptStorage.h" @@ -82,8 +85,8 @@ class RoutingTable { public: Route(ScriptNodePtr s) : SourceObject(s), - present(s->value("present").as()), - path(s->value("path").as()) + present(s->value("present", NULL).as()), + path(s->value("path", NULL).as()) { boost::filesystem::path fspath = path; boost::filesystem::path::iterator p = fspath.begin(); @@ -204,14 +207,14 @@ class Routes : public RowSet { mutable Columns columns; friend class Routes; }; - void execute(const Glib::ustring & filter, const RowProcessor * rp) const + void execute(const Glib::ustring & filter, const RowProcessorCallback & rp, ExecContext *) const { RouteRowState rs; BOOST_FOREACH(const auto & r, ProgRouterLoader::routingTable.routes) { if (boost::algorithm::starts_with(r->path, filter)) { rs.fields[0] = VariableType(r->present); rs.fields[1] = VariableType(r->path); - rs.process(rp); + rp(&rs); } } } diff --git a/project2/cgi/cgiRequestContext.cpp b/project2/cgi/cgiRequestContext.cpp new file mode 100644 index 0000000..5a93243 --- /dev/null +++ b/project2/cgi/cgiRequestContext.cpp @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include "cgiRequestContext.h" +#include "cgiAppEngine.h" +#include "exceptions.h" +#include +#include +#include +#include +#include +#include + +CgiRequestContext::CgiRequestContext(cgicc::CgiInput * i, const CgiEnvInput & e) : + cgi(i), + router(boost::bind(&RouterLoader::create, boost::cref(CgiApplicationEngine::router), getRedirectURL())), + cgienv(e), + session(boost::bind(&CgiRequestContext::getSessionInternal, this)) +{ +} + +CgiRequestContext::~CgiRequestContext() +{ +} + +SessionPtr +CgiRequestContext::getSession() const +{ + return session; +} + +SessionPtr +CgiRequestContext::getSessionInternal() const +{ + try { + return CgiApplicationEngine::sessionsContainer->GetSession(boost::uuids::string_generator()(getCookieValue(CgiApplicationEngine::sessionCookie))); + } + catch (const NoSuchCookie &) { + return CgiApplicationEngine::sessionsContainer->GetSession(boost::uuids::uuid()); + } +} + +std::string +CgiRequestContext::getCookieValue(const std::string & name) const +{ + BOOST_FOREACH(const cgicc::HTTPCookie & c, cgi.getEnvironment().getCookieList()) { + if (c.getName() == name) { + return c.getValue(); + } + } + throw NoSuchCookie(name); +} + +std::string +CgiRequestContext::getRequestMethod() const +{ + return cgi.getEnvironment().getRequestMethod(); +} + +std::string +CgiRequestContext::getRedirectURL() const +{ + return cgi.getEnvironment().getRedirectURL(); +} + +std::string +CgiRequestContext::getServerName() const +{ + return cgi.getEnvironment().getServerName(); +} + +std::string +CgiRequestContext::getAccept() const +{ + return cgi.getEnvironment().getAccept(); +} + +CgiRequestContext::ETags +CgiRequestContext::getRequestETags() const +{ + const std::string e = cgienv.getenv("HTTP_IF_NONE_MATCH"); + ETags etags; + boost::split(etags, e, boost::is_any_of(" ,"), boost::algorithm::token_compress_on); + return etags; +} + +time_t +CgiRequestContext::getRequestModifiedSince() const +{ + return curl_getdate(cgienv.getenv("HTTP_IF_MODIFIED_SINCE").c_str(), NULL); +} + +Glib::ustring +CgiRequestContext::getParamUri(VariableType p) const +{ + return router->routeParameter(p); +} + +unsigned int +CgiRequestContext::getParamUriCount() const +{ + return router->parameterCount(); +} + +void +CgiRequestContext::applyAllParameters(const boost::function & func) const +{ + BOOST_FOREACH(const auto & f, cgi.getElements()) { + func(f.getName(), f.getValue()); + } +} + +VariableType +CgiRequestContext::getParameter(const VariableType & p) const +{ + cgicc::const_form_iterator i = cgi.getElement(p); + if (i == cgi.getElements().end()) { + throw ParamNotFound(p); + } + return cgi(p); +} + +HostnamePlatformIdentifier::HostnamePlatformIdentifier() +{ +} + +HostnamePlatformIdentifier::~HostnamePlatformIdentifier() +{ +} + +const Glib::ustring & +HostnamePlatformIdentifier::derivedPlatform(CgiRequestContext * crc) const +{ + auto pi = std::find_if(platHosts.begin(), platHosts.end(), [crc](const PlatformHostname & r) -> bool { + return r.second->match(crc->getServerName()); + }); + if (pi == platHosts.end()) { + throw NoSuchPlatform(crc->getServerName()); + } + return pi->first; +} + +void +HostnamePlatformIdentifier::reset() const +{ + platHosts.clear(); +} + +bool +HostnamePlatformIdentifier::paramRequired() const +{ + return true; +} + +void +HostnamePlatformIdentifier::consume(const Glib::ustring & p, const VariableType & r, const Options::CurrentPlatform &) const +{ + platHosts.push_back(PlatformHostname(p, Glib::Regex::create(r, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL))); +} + diff --git a/project2/cgi/cgiRequestContext.h b/project2/cgi/cgiRequestContext.h new file mode 100644 index 0000000..1dbc613 --- /dev/null +++ b/project2/cgi/cgiRequestContext.h @@ -0,0 +1,68 @@ +#ifndef ENVPROC_H +#define ENVPROC_H + +#include +#include +#include "cgiEnvInput.h" +#include "cgiRouter.h" +#include "execContext.h" +#include +#include +#include +#include + +SimpleMessageException(NoSuchCookie); + +class CgiRequestContext; +namespace Glib { + class Regex; +} + +class HostnamePlatformIdentifier : public Options::Target { + public: + HostnamePlatformIdentifier(); + virtual ~HostnamePlatformIdentifier(); + void reset() const; + bool paramRequired() const; + void consume(const Glib::ustring &, const VariableType &, const Options::CurrentPlatform &) const; + const Glib::ustring & derivedPlatform(CgiRequestContext *) const; + private: + typedef std::pair> PlatformHostname; + typedef std::vector PlatformHostnameList; + mutable PlatformHostnameList platHosts; +}; + +class CgiRequestContext : public ExecContext { + public: + typedef std::string ETag; + typedef std::vector ETags; + + CgiRequestContext(cgicc::CgiInput *, const CgiEnvInput & cgienv); + virtual ~CgiRequestContext(); + + const cgicc::Cgicc cgi; + + Glib::ustring getParamUri(VariableType idx) const; + unsigned int getParamUriCount() const; + VariableType getParameter(const VariableType & idx) const; + void applyAllParameters(const boost::function &) const; + SessionPtr getSession() const; + std::string getServerName() const; + std::string getRedirectURL() const; + std::string getRequestMethod() const; + std::string getAccept() const; + ETags getRequestETags() const; + time_t getRequestModifiedSince() const; + std::string getCookieValue(const std::string & name) const; + LazyPointer router; + + boost::posix_time::ptime startTime; + boost::posix_time::ptime endTime; + + private: + const CgiEnvInput & cgienv; + LazyPointer session; + SessionPtr getSessionInternal() const; +}; + +#endif diff --git a/project2/cgi/cgiRequestID.cpp b/project2/cgi/cgiRequestID.cpp index da8ad6a..60baa1e 100644 --- a/project2/cgi/cgiRequestID.cpp +++ b/project2/cgi/cgiRequestID.cpp @@ -1,9 +1,8 @@ #include #include -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include #include -#include #include #include #include @@ -16,16 +15,16 @@ class CgiRequestID : public VariableImplDyn { { } - VariableType value() const + VariableType value(ExecContext * ec) const { gcry_md_hd_t state; gcry_md_open(&state, GCRY_MD_SHA1, 0); ScopeObject gcryClose([&state] { gcry_md_close(state); }); - auto _env = static_cast(ApplicationEngine::getCurrent()->env()); - gcryApplyString(state, _env->getRedirectURL()); + auto crc = static_cast(ec); + gcryApplyString(state, crc->getRedirectURL()); - _env->applyAllParameters([&state,this](const std::string & name, const std::string & value) { + crc->applyAllParameters([&state, this](const std::string & name, const std::string & value) { gcryApplyString(state, name); gcryApplyString(state, value); }); diff --git a/project2/cgi/cgiResultStatic.cpp b/project2/cgi/cgiResultStatic.cpp index b5fecd7..ab4ff43 100644 --- a/project2/cgi/cgiResultStatic.cpp +++ b/project2/cgi/cgiResultStatic.cpp @@ -4,7 +4,7 @@ class StaticToCgiResult : public TransformImpl { public: - void transform(const StaticContent * sc, CgiResult * cr) const { + void transform(const StaticContent * sc, CgiResult * cr, ExecContext *) const { cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", sc->getContentType(), sc->getEncoding())); cr->header->addHeader("Content-Length", Glib::ustring::compose("%1", sc->getSizeInBytes())); char buf[100]; diff --git a/project2/cgi/cgiResultWritable.cpp b/project2/cgi/cgiResultWritable.cpp index ea17d3b..357a57c 100644 --- a/project2/cgi/cgiResultWritable.cpp +++ b/project2/cgi/cgiResultWritable.cpp @@ -3,11 +3,11 @@ class WritableToCgiResult : public TransformImpl { public: - void transform(const WritableContent * wc, CgiResult * cr) const { + void transform(const WritableContent * wc, CgiResult * cr, ExecContext * ec) const { cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", wc->getContentType(), cr->encoding)); cr->header->addHeader("Cache-control", "no-cache"); cr->header->render(cr->stream); - wc->writeTo(cr->stream, cr->encoding); + wc->writeTo(cr->stream, cr->encoding, ec); } }; DECLARE_TRANSFORM(WritableToCgiResult); diff --git a/project2/cgi/cgiRouter.h b/project2/cgi/cgiRouter.h index dd9c0e6..4a88b19 100644 --- a/project2/cgi/cgiRouter.h +++ b/project2/cgi/cgiRouter.h @@ -14,6 +14,7 @@ class Router : public IntrusivePtrBase { virtual unsigned int parameterCount() const = 0; virtual void present(const MultiRowSetPresenter * p) const = 0; }; +typedef boost::intrusive_ptr RouterPtr; typedef GenLoader RouterLoader; #endif diff --git a/project2/cgi/cgiSimpleRouter.cpp b/project2/cgi/cgiSimpleRouter.cpp index cd14c53..b67848e 100644 --- a/project2/cgi/cgiSimpleRouter.cpp +++ b/project2/cgi/cgiSimpleRouter.cpp @@ -1,4 +1,4 @@ -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include #include "scriptLoader.h" #include "presenter.h" diff --git a/project2/cgi/cgiStageCacheHit.cpp b/project2/cgi/cgiStageCacheHit.cpp index d398e8f..d74c02f 100644 --- a/project2/cgi/cgiStageCacheHit.cpp +++ b/project2/cgi/cgiStageCacheHit.cpp @@ -1,6 +1,6 @@ #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" #include #include @@ -12,13 +12,13 @@ CgiApplicationEngine::CacheHitStage::CacheHitStage(ScriptNodePtr s, PresenterCac } CgiApplicationEngine::NextStage -CgiApplicationEngine::CacheHitStage::run() +CgiApplicationEngine::CacheHitStage::run(CgiRequestContext *) { return NextStage(NULL, this, pc, NULL); } CgiApplicationEngine::HttpHeaderPtr -CgiApplicationEngine::CacheHitStage::getHeader() const +CgiApplicationEngine::CacheHitStage::getHeader(CgiRequestContext *) const { return HttpHeaderPtr(new Project2HttpHeader("200 OK")); } diff --git a/project2/cgi/cgiStageCustomError.cpp b/project2/cgi/cgiStageCustomError.cpp index 56739fd..e38c7ec 100644 --- a/project2/cgi/cgiStageCustomError.cpp +++ b/project2/cgi/cgiStageCustomError.cpp @@ -1,28 +1,28 @@ #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" #include "logger.h" -CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const std::exception & ex, ScriptReaderPtr s) : +CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const std::exception & ex, ScriptReaderPtr s, CgiRequestContext * crc) : CgiApplicationEngine::ResponseStage(s->root()), ::CommonObjects(s->root()), ::CheckHost(s->root()), - CgiApplicationEngine::DefaultErrorStage(ex), - CgiApplicationEngine::PresentStage(s) + CgiApplicationEngine::DefaultErrorStage(ex, crc), + CgiApplicationEngine::PresentStage(s, crc) { } CgiApplicationEngine::HttpHeaderPtr -CgiApplicationEngine::CustomErrorStage::getHeader() const +CgiApplicationEngine::CustomErrorStage::getHeader(CgiRequestContext * ec) const { - return CgiApplicationEngine::DefaultErrorStage::getHeader(); + return CgiApplicationEngine::DefaultErrorStage::getHeader(ec); } CgiApplicationEngine::NextStage -CgiApplicationEngine::CustomErrorStage::run() +CgiApplicationEngine::CustomErrorStage::run(CgiRequestContext * crc) { - CgiApplicationEngine::DefaultErrorStage::run(); - return CgiApplicationEngine::PresentStage::run(); + CgiApplicationEngine::DefaultErrorStage::run(crc); + return CgiApplicationEngine::PresentStage::run(crc); } diff --git a/project2/cgi/cgiStageCustomNotFound.cpp b/project2/cgi/cgiStageCustomNotFound.cpp index 872da77..48fbf64 100644 --- a/project2/cgi/cgiStageCustomNotFound.cpp +++ b/project2/cgi/cgiStageCustomNotFound.cpp @@ -1,28 +1,28 @@ #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" #include "logger.h" -CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const ScriptNotFound & notfound, ScriptReaderPtr s) : +CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const ScriptNotFound & notfound, ScriptReaderPtr s, CgiRequestContext * crc) : CgiApplicationEngine::ResponseStage(s->root()), ::CommonObjects(s->root()), ::CheckHost(s->root()), CgiApplicationEngine::DefaultNotFoundStage(notfound), - CgiApplicationEngine::PresentStage(s) + CgiApplicationEngine::PresentStage(s, crc) { } CgiApplicationEngine::HttpHeaderPtr -CgiApplicationEngine::CustomNotFoundStage::getHeader() const +CgiApplicationEngine::CustomNotFoundStage::getHeader(CgiRequestContext * crc) const { - return CgiApplicationEngine::DefaultNotFoundStage::getHeader(); + return CgiApplicationEngine::DefaultNotFoundStage::getHeader(crc); } CgiApplicationEngine::NextStage -CgiApplicationEngine::CustomNotFoundStage::run() +CgiApplicationEngine::CustomNotFoundStage::run(CgiRequestContext * crc) { - CgiApplicationEngine::DefaultNotFoundStage::run(); - return CgiApplicationEngine::PresentStage::run(); + CgiApplicationEngine::DefaultNotFoundStage::run(crc); + return CgiApplicationEngine::PresentStage::run(crc); } diff --git a/project2/cgi/cgiStageDefaultError.cpp b/project2/cgi/cgiStageDefaultError.cpp index 4c3eefe..d230a21 100644 --- a/project2/cgi/cgiStageDefaultError.cpp +++ b/project2/cgi/cgiStageDefaultError.cpp @@ -2,22 +2,22 @@ #include "cgiAppEngine.h" #include "cgiHttpHeader.h" #include "logger.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include static const Glib::ustring DefaultErrorStageResp("error"); -CgiApplicationEngine::DefaultErrorStage::DefaultErrorStage(const std::exception & ex) : +CgiApplicationEngine::DefaultErrorStage::DefaultErrorStage(const std::exception & ex, CgiRequestContext * crc) : CgiApplicationEngine::ResponseStage(NULL), buf(__cxxabiv1::__cxa_demangle(typeid(ex).name(), NULL, NULL, NULL)), what(ex.what()), - pres(new XmlPresenter(DefaultErrorStageResp, env()->errorTransformStyle, env()->errorContentType)) + pres(new XmlPresenter(DefaultErrorStageResp, CgiApplicationEngine::errorTransformStyle, CgiApplicationEngine::errorContentType)) { auto xp = dynamic_cast(pres.get()); auto cp = dynamic_cast(pres.get()); - if (xp && cp && cp->contentType == this->env()->transformContentType) { - auto h = TransformTargetLoader::getFor(this->env()->transformTargetType)->create(root, Default); - xp->addTarget(h, root); + if (xp && cp && cp->contentType == CgiApplicationEngine::transformContentType) { + auto h = TransformTargetLoader::getFor(CgiApplicationEngine::transformTargetType)->create(root, Default); + xp->addTarget(h, crc, root); } } @@ -27,15 +27,15 @@ CgiApplicationEngine::DefaultErrorStage::~DefaultErrorStage() } CgiApplicationEngine::HttpHeaderPtr -CgiApplicationEngine::DefaultErrorStage::getHeader() const +CgiApplicationEngine::DefaultErrorStage::getHeader(CgiRequestContext *) const { return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error")); } CgiApplicationEngine::NextStage -CgiApplicationEngine::DefaultErrorStage::run() +CgiApplicationEngine::DefaultErrorStage::run(CgiRequestContext * crc) { - pres->init(); + pres->init(crc); pres->addNamedValue("error-type", Scripts::scriptNamespacePrefix, buf); pres->addNamedValue("error-what", Scripts::scriptNamespacePrefix, what.c_str()); return NextStage(NULL, this, pres.get(), pres.get()); diff --git a/project2/cgi/cgiStageDefaultNotFound.cpp b/project2/cgi/cgiStageDefaultNotFound.cpp index e497058..bfb737f 100644 --- a/project2/cgi/cgiStageDefaultNotFound.cpp +++ b/project2/cgi/cgiStageDefaultNotFound.cpp @@ -1,6 +1,6 @@ #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" #include "logger.h" @@ -9,21 +9,21 @@ static const Glib::ustring DefaultNotFoundStageResp("notfound"); CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const ScriptNotFound & notfound) : CgiApplicationEngine::ResponseStage(NULL), nf(notfound), - pres(new XmlPresenter(DefaultNotFoundStageResp, env()->errorTransformStyle, env()->errorContentType)) + pres(new XmlPresenter(DefaultNotFoundStageResp, CgiApplicationEngine::errorTransformStyle, CgiApplicationEngine::errorContentType)) { Logger()->messagef(LOG_ERR, "%s: Resource not found: %s", __FUNCTION__, nf.what()); } CgiApplicationEngine::HttpHeaderPtr -CgiApplicationEngine::DefaultNotFoundStage::getHeader() const +CgiApplicationEngine::DefaultNotFoundStage::getHeader(CgiRequestContext *) const { return HttpHeaderPtr(new Project2HttpHeader("404 Not found")); } CgiApplicationEngine::NextStage -CgiApplicationEngine::DefaultNotFoundStage::run() +CgiApplicationEngine::DefaultNotFoundStage::run(CgiRequestContext * crc) { - pres->init(); + pres->init(crc); pres->addNamedValue("missing-resource", Scripts::scriptNamespacePrefix, nf.what()); return NextStage(NULL, this, pres.get(), pres.get()); } diff --git a/project2/cgi/cgiStageFail.cpp b/project2/cgi/cgiStageFail.cpp index 019ab8e..461c8a7 100644 --- a/project2/cgi/cgiStageFail.cpp +++ b/project2/cgi/cgiStageFail.cpp @@ -1,7 +1,7 @@ #include #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" #include "logger.h" @@ -14,13 +14,13 @@ namespace CgiApplicationExtras { message(m) { } - CgiApplicationEngine::HttpHeaderPtr getHeader() const + CgiApplicationEngine::HttpHeaderPtr getHeader(CgiRequestContext *) const { Project2HttpHeader * header = new Project2HttpHeader(boost::lexical_cast(code) + " " + message); return CgiApplicationEngine::HttpHeaderPtr(header); } - CgiApplicationEngine::NextStage run() + CgiApplicationEngine::NextStage run(CgiRequestContext *) { return CgiApplicationEngine::NextStage(NULL, this, NULL, NULL); } @@ -37,9 +37,9 @@ namespace CgiApplicationExtras { code(e, "code", 500), message(e, "message", "Application error") { } - void execute(const MultiRowSetPresenter *) const { + void execute(const MultiRowSetPresenter *, ExecContext * ec) const { throw CgiApplicationEngine::ResponseStagePtr( - new FailStage(code(), message())); + new FailStage(code(ec), message(ec))); } private: Variable code, message; diff --git a/project2/cgi/cgiStageInitial.cpp b/project2/cgi/cgiStageInitial.cpp index d5fe424..1326af8 100644 --- a/project2/cgi/cgiStageInitial.cpp +++ b/project2/cgi/cgiStageInitial.cpp @@ -1,17 +1,18 @@ #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "exceptions.h" CgiApplicationEngine::NextStage -CgiApplicationEngine::InitialStage::run() +CgiApplicationEngine::InitialStage::run(CgiRequestContext * crc) { - const CgiEnvironment * e = env(); - if (e->getRequestMethod() == "POST") { - return NextStage(new RequestStage(ScriptReader::resolveScript(e->requestRoot, e->router->route(), false))); + if (crc->getRequestMethod() == "POST") { + return NextStage(new RequestStage(ScriptReader::resolveScript(CgiApplicationEngine::requestRoot, + crc->router->route(), false))); } else { - return NextStage(new PresentStage(ScriptReader::resolveScript(e->presentRoot, e->router->isDefault() ? e->defaultPresent : e->router->route(), false))); + return NextStage(new PresentStage(ScriptReader::resolveScript(CgiApplicationEngine::presentRoot, + crc->router->isDefault() ? CgiApplicationEngine::defaultPresent : crc->router->route(), false), crc)); } } diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp index 90299fe..f077111 100644 --- a/project2/cgi/cgiStagePresent.cpp +++ b/project2/cgi/cgiStagePresent.cpp @@ -1,41 +1,41 @@ #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" #include "safeMapFind.h" #include #include -CgiApplicationEngine::PresentStage::PresentStage(ScriptReaderPtr s) : +CgiApplicationEngine::PresentStage::PresentStage(ScriptReaderPtr s, CgiRequestContext * crc) : CgiApplicationEngine::ResponseStage(s->root()), CommonObjects(s->root()), CheckHost(s->root()), ViewHost(s->root()), - presenter([this] { - auto p = PresenterLoader::getFor(this->env()->defaultPresenter)->create(root, Default); + presenter([this, crc] { + auto p = PresenterLoader::getFor(CgiApplicationEngine::defaultPresenter)->create(root, Default, crc); auto xp = dynamic_cast(p); auto cp = dynamic_cast(p); - if (xp && cp && cp->contentType == this->env()->transformContentType) { - auto h = TransformTargetLoader::getFor(this->env()->transformTargetType)->create(root, Default); - xp->addTarget(h, root); + if (xp && cp && cp->contentType == CgiApplicationEngine::transformContentType) { + auto h = TransformTargetLoader::getFor(CgiApplicationEngine::transformTargetType)->create(root, Default); + xp->addTarget(h, crc, root); } return p; }) { s->loader.addLoadTarget(s->root(), Storer::into(&outputOptions)); - s->loader.addLoadTarget(s->root(), Storer::into(&presenter, Scripted)); + s->loader.addLoadTarget(s->root(), Storer::into(&presenter, Scripted, crc)); s->loader.addLoadTarget(s->root(), Storer::into(&caches)); } CgiApplicationEngine::NextStage -CgiApplicationEngine::PresentStage::run() +CgiApplicationEngine::PresentStage::run(CgiRequestContext * crc) { - runChecks(); + runChecks(crc); PresenterCaches backFill; - time_t reqMS = this->env()->getRequestModifiedSince(); - CgiEnvironment::ETags etags = this->env()->getRequestETags(); + time_t reqMS = crc->getRequestModifiedSince(); + CgiRequestContext::ETags etags = crc->getRequestETags(); BOOST_FOREACH(const PresenterCachePtr & pc, caches) { - if (pc->check(root->script->modifiedTime())) { + if (pc->check(root->script->modifiedTime(), crc)) { if (reqMS >= pc->getModifiedTime() && (etags.empty() || containerContains(etags, pc->getSHA1()))) { header = HttpHeaderPtr(new Project2HttpHeader("304 Not Modified")); return NextStage(NULL, this, NULL, NULL); @@ -49,7 +49,7 @@ CgiApplicationEngine::PresentStage::run() } } try { - executeViews(); + executeViews(crc); header = HttpHeaderPtr(new Project2HttpHeader("200 OK")); return NextStage(NULL, this, boost::dynamic_pointer_cast(presenter), presenter); } @@ -66,7 +66,7 @@ CgiApplicationEngine::PresentStage::run() } MultiRowSetPresenterPtr -CgiApplicationEngine::PresentStage::getPresenter() const +CgiApplicationEngine::PresentStage::getPresenter(ExecContext *) const { return presenter; } @@ -77,7 +77,7 @@ CgiApplicationEngine::ResponseStage::ResponseStage(ScriptNodePtr r) : } CgiApplicationEngine::HttpHeaderPtr -CgiApplicationEngine::PresentStage::getHeader() const +CgiApplicationEngine::PresentStage::getHeader(CgiRequestContext *) const { return header; } diff --git a/project2/cgi/cgiStageRedirect.cpp b/project2/cgi/cgiStageRedirect.cpp index 4a4cd02..d6fee08 100644 --- a/project2/cgi/cgiStageRedirect.cpp +++ b/project2/cgi/cgiStageRedirect.cpp @@ -1,6 +1,6 @@ #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" #include "logger.h" @@ -12,14 +12,14 @@ namespace CgiApplicationExtras { url(u) { } - CgiApplicationEngine::HttpHeaderPtr getHeader() const + CgiApplicationEngine::HttpHeaderPtr getHeader(CgiRequestContext *) const { Project2HttpHeader * header = new Project2HttpHeader("301 Moved Permanently"); header->addHeader("Location", url); return CgiApplicationEngine::HttpHeaderPtr(header); } - CgiApplicationEngine::NextStage run() + CgiApplicationEngine::NextStage run(CgiRequestContext *) { return CgiApplicationEngine::NextStage(NULL, this, NULL, NULL); } @@ -34,8 +34,8 @@ namespace CgiApplicationExtras { View(e), url(e, "url") { } - void execute(const MultiRowSetPresenter *) const { - throw CgiApplicationEngine::ResponseStagePtr(new RedirectStage(url())); + void execute(const MultiRowSetPresenter *, ExecContext * ec) const { + throw CgiApplicationEngine::ResponseStagePtr(new RedirectStage(url(ec))); } private: Variable url; diff --git a/project2/cgi/cgiStageRequest.cpp b/project2/cgi/cgiStageRequest.cpp index 37faaae..78d933b 100644 --- a/project2/cgi/cgiStageRequest.cpp +++ b/project2/cgi/cgiStageRequest.cpp @@ -1,6 +1,6 @@ #include #include "cgiAppEngine.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" #include "scriptLoader.h" #include @@ -17,26 +17,26 @@ CgiApplicationEngine::RequestStage::RequestStage(ScriptReaderPtr s) : } CgiApplicationEngine::NextStage -CgiApplicationEngine::RequestStage::run() +CgiApplicationEngine::RequestStage::run(CgiRequestContext * ec) { - runChecks(); - execute(); - if (!present().isNull()) { - return NextStage(new PresentStage(ScriptReader::resolveScript(env()->presentRoot, present(), false)), this); + runChecks(ec); + execute(ec); + if (!present(ec).isNull()) { + return NextStage(new PresentStage(ScriptReader::resolveScript(CgiApplicationEngine::presentRoot, present(ec), false), ec), this); } return NextStage(NULL, this); } CgiApplicationEngine::HttpHeaderPtr -CgiApplicationEngine::RequestStage::getHeader() const +CgiApplicationEngine::RequestStage::getHeader(CgiRequestContext * ec) const { Project2HttpHeader * header; - if (redirect().isNull()) { + if (redirect(ec).isNull()) { header = new Project2HttpHeader("200 OK"); } else { header = new Project2HttpHeader("301 Moved Permanently"); - header->addHeader("Location", redirect()); + header->addHeader("Location", redirect(ec)); } header->addHeader("Cache-control", "no-cache"); return HttpHeaderPtr(header); diff --git a/project2/cgi/cgiUriParam.cpp b/project2/cgi/cgiUriParam.cpp index c65119e..985048d 100644 --- a/project2/cgi/cgiUriParam.cpp +++ b/project2/cgi/cgiUriParam.cpp @@ -1,9 +1,8 @@ #include -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include #include #include -#include /// Variable implementation to access URI path fragments class VariableUri : public VariableImplDyn { @@ -13,16 +12,16 @@ class VariableUri : public VariableImplDyn { index(e, "index") { } - VariableType value() const + VariableType value(ExecContext * ec) const { try { - return static_cast(ApplicationEngine::getCurrent()->env())->getParamUri(index()); + return static_cast(ec)->getParamUri(index(ec)); } catch (...) { if (!defaultValue) { throw; } - return (*defaultValue)(); + return (*defaultValue)(ec); } } private: diff --git a/project2/cgi/p2webCgi.cpp b/project2/cgi/p2webCgi.cpp index 1b2aa99..4f806b2 100644 --- a/project2/cgi/p2webCgi.cpp +++ b/project2/cgi/p2webCgi.cpp @@ -1,5 +1,5 @@ -#include "cgiCommon.h" -#include "scriptLoader.h" +#include "cgiAppEngine.h" +#include "optionsSource.h" #include class GetEnv : public CgiEnvInput { @@ -16,9 +16,12 @@ int main(void) { Plugable::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1)); - CgiEnvironment env; + CgiApplicationEngine app; GetEnv ge; - cgiServe(NULL, &env, std::cout, &ge); + CgiRequestContext crc(NULL, ge); + OptionsSource::loadSources(boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc)); + Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1)); + app.process(std::cout, &crc); Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1)); Plugable::onAllComponents(boost::bind(&ComponentLoader::onPeriodic, _1)); Plugable::onAllComponents(boost::bind(&ComponentLoader::onIdle, _1)); diff --git a/project2/cgi/p2webFCgi.cpp b/project2/cgi/p2webFCgi.cpp index 7eb631f..4320c48 100644 --- a/project2/cgi/p2webFCgi.cpp +++ b/project2/cgi/p2webFCgi.cpp @@ -1,6 +1,6 @@ -#include "cgiCommon.h" #include "FCgiIO.h" -#include "scriptLoader.h" +#include "cgiAppEngine.h" +#include "optionsSource.h" #include time_t lastPeriodic = 0; @@ -40,12 +40,15 @@ main(void) fprintf(stderr, "Failed to set signal handler\n"); } alarm(60); - CgiEnvironment env; Plugable::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1)); + CgiApplicationEngine app; while (FCGX_Accept_r(&request) == 0) { alarm(0); cgicc::FCgiIO IO(request); - cgiServe(&IO, &env, IO, &IO); + CgiRequestContext crc(&IO, IO); + OptionsSource::loadSources(boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc)); + Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1)); + app.process(IO, &crc); FCGX_Finish_r(&request); Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1)); if (time(NULL) > lastPeriodic + periodicDelay) { diff --git a/project2/cgi/pch.hpp b/project2/cgi/pch.hpp index df744a4..5f68b7c 100644 --- a/project2/cgi/pch.hpp +++ b/project2/cgi/pch.hpp @@ -2,14 +2,8 @@ #ifndef CGI_PCH #define CGI_PCH -#include "appEngine.h" -#include "cgiAppEngine.h" -#include "cgiCommon.h" -#include "cgiEnvironment.h" +#include "cgiRequestContext.h" #include "cgiHttpHeader.h" -#include "exceptions.h" -#include "iterate.h" -#include "logger.h" #include "scriptLoader.h" #include #include diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp index 9ef0079..2025594 100644 --- a/project2/cgi/testCgi.cpp +++ b/project2/cgi/testCgi.cpp @@ -3,8 +3,9 @@ #include #include "options.h" #include "safeMapFind.h" -#include "cgiCommon.h" #include "../files/optionsSource.h" +#include "cgiRequestContext.h" +#include "cgiAppEngine.h" #define TESTOPT(name, def, desc) \ (name, Options::value(optStore().insert(OptStore::value_type(name, StrPtr(new std::string()))).first->second.get(), def), desc) @@ -12,8 +13,8 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput { public: class TestConfigConsumer : public ConfigConsumer { public: - void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const { - Plugable::onAll(boost::bind(&Options::consume, _1, n, p, v)); + void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v, const Options::CurrentPlatform & cp) const { + Plugable::onAll(boost::bind(&Options::consume, _1, n, p, v, cp)); } const Options::Option * get(const Glib::ustring &) const { return NULL; @@ -22,11 +23,13 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput { typedef boost::shared_ptr StrPtr; typedef std::map OptStore; - TestInput(int argc, char ** argv) + TestInput(int argc, char ** argv) : + crc(NULL, *this) { - OptionsSource::loadSources(); + auto cp = boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc); + OptionsSource::loadSources(cp); FileOptions fo(".testCgi.settings"); - fo.loadInto(TestConfigConsumer()); + fo.loadInto(TestConfigConsumer(), cp); if (argc > 1) { const char * qm = strchr(argv[1], '?'); if (qm) { @@ -51,9 +54,10 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput { } void run() { + CgiApplicationEngine app; if (urlListFile.empty()) { for (int run = 0; run < runCount; run += 1) { - cgiServe(this, &env, std::cout, this); + app.process(std::cout, &crc); } } else { @@ -63,7 +67,7 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput { std::string url; urls >> url; optStore()["REDIRECT_URL"] = StrPtr(new std::string(url)); - cgiServe(this, &env, std::cout, this); + app.process(std::cout, &crc); } } } @@ -71,7 +75,7 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput { INITOPTIONS; private: - CgiEnvironment env; + CgiRequestContext crc; static int runCount; static std::string urlListFile; static OptStore & optStore() diff --git a/project2/common/aggregate.cpp b/project2/common/aggregate.cpp index 1bb453b..ee7c871 100644 --- a/project2/common/aggregate.cpp +++ b/project2/common/aggregate.cpp @@ -17,8 +17,8 @@ SetAggregate::SetAggregate(ScriptNodePtr s) : } void -Aggregate::pushValue() const +Aggregate::pushValue(ExecContext * ec) const { - pushValue(value()); + pushValue(value(ec), ec); } diff --git a/project2/common/aggregate.h b/project2/common/aggregate.h index 0641c6e..7f33b6b 100644 --- a/project2/common/aggregate.h +++ b/project2/common/aggregate.h @@ -10,9 +10,9 @@ class Aggregate : public SourceObject { Aggregate(ScriptNodePtr); virtual void reset() const = 0; - void pushValue() const; + void pushValue(ExecContext * ec) const; protected: - virtual void pushValue(const VariableType &) const = 0; + virtual void pushValue(const VariableType &, ExecContext *) const = 0; private: Variable value; }; diff --git a/project2/common/appEngine.cpp b/project2/common/appEngine.cpp deleted file mode 100644 index ce71153..0000000 --- a/project2/common/appEngine.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include "appEngine.h" -#include "logger.h" -#include "presenter.h" -#include -#include - -ApplicationEngine * ApplicationEngine::currentEngine = NULL; - -ApplicationEngine::ApplicationEngine() -{ - if (currentEngine) { - throw std::runtime_error("One application at a time, please"); - } - currentEngine = this; -} - -ApplicationEngine::~ApplicationEngine() -{ - currentEngine = NULL; -} - -void -ApplicationEngine::logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m) -{ - if (writeLog) { - Logger()->messagebf(LOG_NOTICE, "%s: %s: %s", __PRETTY_FUNCTION__, g, m); - } - appMessages.push_back(new Message(g, m)); -} - -void -ApplicationEngine::addCoreAppData(const MultiRowSetPresenter * p) const -{ - // Message log - p->addNewRowSet("messages", Scripts::scriptNamespacePrefix); - p->addNewArray("message", true); - BOOST_FOREACH(const Messages::value_type & m, appMessages) { - p->addNewRow("message"); - p->addAttribute("group", m->group); - p->addAttribute("text", m->message); - p->finishRow(); - } - p->finishArray(true); - p->finishRowSet(); -} - -ApplicationEngine::Message::Message(const Glib::ustring & g, const Glib::ustring & m) : - group(g), - message(m) -{ -} - diff --git a/project2/common/appEngine.h b/project2/common/appEngine.h deleted file mode 100644 index 6de21e1..0000000 --- a/project2/common/appEngine.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef APPENGINE_H -#define APPENGINE_H - -#include "environment.h" -#include "session.h" - -class MultiRowSetPresenter; - -class ApplicationEngine { - public: - class Message : public IntrusivePtrBase { - public: - Message(const Glib::ustring & g, const Glib::ustring & m); - - const Glib::ustring group; - const Glib::ustring message; - }; - typedef boost::intrusive_ptr MessagePtr; - typedef std::list Messages; - - ApplicationEngine(); - virtual ~ApplicationEngine() = 0; - - void logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m); - - virtual void process() const = 0; - virtual const Environment * env() const = 0; - virtual SessionPtr session() const = 0; - - static ApplicationEngine * getCurrent() { return currentEngine; } - - protected: - void addCoreAppData(const MultiRowSetPresenter * p) const; - - Messages appMessages; - - private: - static ApplicationEngine * currentEngine; -}; - -#endif - diff --git a/project2/common/cache.cpp b/project2/common/cache.cpp index 9be5845..2a1d410 100644 --- a/project2/common/cache.cpp +++ b/project2/common/cache.cpp @@ -9,17 +9,17 @@ Cache::Cache(ScriptNodePtr p) : IHaveParameters(p), SourceObject(p), - inherit(p->value("inherit", true).as()) + inherit(p->value("inherit", true, NULL).as()) { } -bool Cache::checkAndExecute(const Glib::ustring & n, const Glib::ustring & f, const RowProcessor * rp) +bool Cache::checkAndExecute(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * p, const RowProcessorCallback & rp) { - RowSetCPtr cached = getCachedRowSet(n, f, rp); + RowSetCPtr cached = getCachedRowSet(ec, n, f, p); if (cached) { try { Logger()->messagebf(LOG_DEBUG, "Executing from cache '%s'", name); - cached->execute(f, rp); + cached->execute(f, rp, ec); return true; } catch (const Glib::Exception & e) { @@ -36,14 +36,14 @@ bool Cache::checkAndExecute(const Glib::ustring & n, const Glib::ustring & f, co } void -Cache::applyKeys(const boost::function2 & f, const IHaveParameters * ps) const +Cache::applyKeys(ExecContext * ec, const KeyApplier & f, const IHaveParameters * ps) const { BOOST_FOREACH(const IHaveParameters::Parameters::value_type & p, allParameters()) { - f(p.first, p.second); + f(p.first, p.second(ec)); } if (inherit) { BOOST_FOREACH(const IHaveParameters::Parameters::value_type & p, ps->allParameters()) { - f(p.first, p.second); + f(p.first, p.second(ec)); } } } diff --git a/project2/common/cache.h b/project2/common/cache.h index 2c438b8..0806c6f 100644 --- a/project2/common/cache.h +++ b/project2/common/cache.h @@ -4,8 +4,8 @@ #include "sourceObject.h" #include "presenter.h" #include "iHaveParameters.h" +#include "rowSet.h" -class RowProcessor; class RowSet; class RowState; typedef boost::intrusive_ptr RowSetCPtr; @@ -14,14 +14,15 @@ class Cache : public IHaveParameters, public SourceObject { public: Cache(ScriptNodePtr p); - bool checkAndExecute(const Glib::ustring &, const Glib::ustring &, const RowProcessor *); - virtual RowSetPresenterPtr openFor(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0; - virtual void save(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0; - virtual void discard(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0; + bool checkAndExecute(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *, const RowProcessorCallback &); + virtual RowSetPresenterPtr openFor(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0; + virtual void save(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0; + virtual void discard(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0; protected: - virtual RowSetCPtr getCachedRowSet(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) const = 0; - void applyKeys(const boost::function2 & f, const IHaveParameters *) const; + virtual RowSetCPtr getCachedRowSet(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) const = 0; + typedef boost::function KeyApplier; + void applyKeys(ExecContext * ec, const KeyApplier & f, const IHaveParameters * ps) const; const bool inherit; }; typedef boost::intrusive_ptr CachePtr; diff --git a/project2/common/check.cpp b/project2/common/check.cpp index 21d17cf..d288e2f 100644 --- a/project2/common/check.cpp +++ b/project2/common/check.cpp @@ -20,11 +20,11 @@ Check::~Check() } bool -Check::performCheck() const +Check::performCheck(ExecContext * ec) const { if (!test) { throw NoTestsToPerform(); } - return test->passes(); + return test->passes(ec); } diff --git a/project2/common/check.h b/project2/common/check.h index e9f44b5..dc97f8f 100644 --- a/project2/common/check.h +++ b/project2/common/check.h @@ -5,13 +5,15 @@ #include "variables.h" #include "test.h" +class ExecContext; + /// Base class for Project2 compoments that perform checks class Check : public SourceObject { public: Check(ScriptNodePtr p); virtual ~Check(); - bool performCheck() const; + bool performCheck(ExecContext *) const; const Variable message; const Variable group; diff --git a/project2/common/checkHost.cpp b/project2/common/checkHost.cpp index 49533a9..dedea85 100644 --- a/project2/common/checkHost.cpp +++ b/project2/common/checkHost.cpp @@ -1,6 +1,6 @@ #include #include "checkHost.h" -#include "appEngine.h" +#include "execContext.h" #include CheckHost::CheckHost(ScriptNodePtr s) : @@ -14,12 +14,12 @@ CheckHost::~CheckHost() } void -CheckHost::runChecks() const +CheckHost::runChecks(ExecContext * ec) const { loadScriptComponents(); BOOST_FOREACH(const Checks::value_type & pc, checks) { - if (!pc->performCheck()) { - ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message()); + if (!pc->performCheck(ec)) { + ec->logMessage(false, pc->group(ec), pc->message(ec)); throw CheckFailure(pc); } } diff --git a/project2/common/checkHost.h b/project2/common/checkHost.h index edc2cd8..f404d9e 100644 --- a/project2/common/checkHost.h +++ b/project2/common/checkHost.h @@ -18,7 +18,7 @@ class CheckHost : virtual public CommonObjects { CheckHost(ScriptNodePtr script); ~CheckHost(); - void runChecks() const; + void runChecks(ExecContext *) const; typedef ANONORDEREDSTORAGEOF(Check) Checks; Checks checks; diff --git a/project2/common/commonObjects.cpp b/project2/common/commonObjects.cpp index 23f2edb..a25bb9f 100644 --- a/project2/common/commonObjects.cpp +++ b/project2/common/commonObjects.cpp @@ -1,7 +1,6 @@ #include #include "commonObjects.h" #include "safeMapFind.h" -#include "appEngine.h" #include "scriptLoader.h" CommonObjects::CommonObjects() : diff --git a/project2/common/environment.cpp b/project2/common/environment.cpp deleted file mode 100644 index 69f853c..0000000 --- a/project2/common/environment.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include "environment.h" -#include "optionsSource.h" - -const Environment * Environment::currentEnv(NULL); - -Environment::Environment() -{ - currentEnv = this; -} - -Environment::~Environment() -{ - currentEnv = NULL; -} - -const Environment * -Environment::getCurrent() -{ - return currentEnv; -} - diff --git a/project2/common/environment.h b/project2/common/environment.h deleted file mode 100644 index a97255f..0000000 --- a/project2/common/environment.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef ENVIRONMENT_H -#define ENVIRONMENT_H - -#include -#include -#include "exceptions.h" -#include "scripts.h" - -SimpleMessageException(NoSuchPlatform); - -class Environment { - public: - Environment(); - virtual ~Environment() = 0; - - static const Environment * getCurrent(); - - virtual Glib::ustring getParamQuery(const std::string & idx) const = 0; - - virtual std::string getServerName() const = 0; - virtual const Glib::ustring & platform() const = 0; - - private: - static const Environment * currentEnv; -}; - -#endif - diff --git a/project2/common/exceptions.h b/project2/common/exceptions.h index 38f0efa..9cdf6f0 100644 --- a/project2/common/exceptions.h +++ b/project2/common/exceptions.h @@ -67,6 +67,7 @@ SimpleMessageException(NotSupported); SimpleMessageException(FileNotReadable); SimpleMessageException(FileNotWritable); SimpleMessageException(FilterNotFound); +SimpleMessageException(NoSuchPlatform); #endif diff --git a/project2/common/execContext.cpp b/project2/common/execContext.cpp new file mode 100644 index 0000000..571b5f0 --- /dev/null +++ b/project2/common/execContext.cpp @@ -0,0 +1,36 @@ +#include "execContext.h" +#include "logger.h" +#include "presenter.h" +#include + +void +ExecContext::logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m) +{ + if (writeLog) { + Logger()->messagebf(LOG_NOTICE, "%s: %s: %s", __PRETTY_FUNCTION__, g, m); + } + messages.push_back(new Message(g, m)); +} + +void +ExecContext::addContextData(const MultiRowSetPresenter * p) const +{ + // Message log + p->addNewRowSet("messages", Scripts::scriptNamespacePrefix); + p->addNewArray("message", true); + BOOST_FOREACH(const Messages::value_type & m, messages) { + p->addNewRow("message"); + p->addAttribute("group", m->group); + p->addAttribute("text", m->message); + p->finishRow(); + } + p->finishArray(true); + p->finishRowSet(); +} + +ExecContext::Message::Message(const Glib::ustring & g, const Glib::ustring & m) : + group(g), + message(m) +{ +} + diff --git a/project2/common/execContext.h b/project2/common/execContext.h new file mode 100644 index 0000000..6018058 --- /dev/null +++ b/project2/common/execContext.h @@ -0,0 +1,37 @@ +#ifndef EXECCONTEXT_H +#define EXECCONTEXT_H + +#include +#include +#include +#include "variableType.h" +#include "session.h" + +class MultiRowSetPresenter; + +class ExecContext { + public: + class Message : public IntrusivePtrBase { + public: + Message(const Glib::ustring & g, const Glib::ustring & m); + + const Glib::ustring group; + const Glib::ustring message; + }; + typedef boost::intrusive_ptr MessagePtr; + typedef std::list Messages; + + virtual VariableType getParameter(const VariableType & key) const = 0; + virtual SessionPtr getSession() const = 0; + + void logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m); + const Messages & getMessages() const; + + void addContextData(const MultiRowSetPresenter * p) const; + + private: + Messages messages; +}; + +#endif + diff --git a/project2/common/iHaveParameters.cpp b/project2/common/iHaveParameters.cpp index f880944..1bf1362 100644 --- a/project2/common/iHaveParameters.cpp +++ b/project2/common/iHaveParameters.cpp @@ -2,7 +2,6 @@ #include "iHaveParameters.h" #include "exceptions.h" #include "safeMapFind.h" -#include "appEngine.h" #include IHaveParameters::Stack IHaveParameters::scope; @@ -19,9 +18,9 @@ IHaveParameters::~IHaveParameters() } VariableType -IHaveParameters::getParameter(const Glib::ustring & name) const +IHaveParameters::getParameter(const Glib::ustring & name, ExecContext * ec) const { - return safeMapLookup(parameters, name); + return safeMapLookup(parameters, name)(ec); } void @@ -37,12 +36,12 @@ IHaveParameters::pop() } VariableType -IHaveParameters::getScopedParameter(const Glib::ustring & name) +IHaveParameters::getScopedParameter(const Glib::ustring & name, ExecContext * ec) { for(Stack::const_reverse_iterator ihp = scope.rbegin(); ihp != scope.rend(); ++ihp) { Parameters::const_iterator i = (*ihp)->parameters.find(name); if (i != (*ihp)->parameters.end()) { - return i->second; + return i->second(ec); } } throw ParamNotFound(name); diff --git a/project2/common/iHaveParameters.h b/project2/common/iHaveParameters.h index 2b7ed2a..7b15289 100644 --- a/project2/common/iHaveParameters.h +++ b/project2/common/iHaveParameters.h @@ -15,8 +15,8 @@ class IHaveParameters { virtual ~IHaveParameters() = 0; const Parameters & allParameters() const; - VariableType getParameter(const Glib::ustring &) const; - static VariableType getScopedParameter(const Glib::ustring &); + VariableType getParameter(const Glib::ustring &, ExecContext *) const; + static VariableType getScopedParameter(const Glib::ustring &, ExecContext *); protected: Parameters parameters; diff --git a/project2/common/iHaveSubTasks.cpp b/project2/common/iHaveSubTasks.cpp index 78868aa..92248fb 100644 --- a/project2/common/iHaveSubTasks.cpp +++ b/project2/common/iHaveSubTasks.cpp @@ -13,10 +13,10 @@ IHaveSubTasks::~IHaveSubTasks() } void -IHaveSubTasks::run(const Tasks & tlist) const +IHaveSubTasks::run(const Tasks & tlist, ExecContext * ec) const { BOOST_FOREACH(const Tasks::value_type & t, tlist) { - t->execute(); + t->execute(ec); } } diff --git a/project2/common/iHaveSubTasks.h b/project2/common/iHaveSubTasks.h index e52a9be..d13a890 100644 --- a/project2/common/iHaveSubTasks.h +++ b/project2/common/iHaveSubTasks.h @@ -12,11 +12,11 @@ class IHaveSubTasks : public NoOutputExecute { IHaveSubTasks(const std::string & n); virtual ~IHaveSubTasks(); - virtual void execute() const = 0; + virtual void execute(ExecContext * ec) const = 0; Tasks normal; protected: - void run(const Tasks &) const; + void run(const Tasks &, ExecContext * ec) const; }; #endif diff --git a/project2/common/if.cpp b/project2/common/if.cpp index c7f790e..ed2abf6 100644 --- a/project2/common/if.cpp +++ b/project2/common/if.cpp @@ -20,31 +20,31 @@ If::If(ScriptNodePtr e) : } bool -If::passes() const +If::passes(ExecContext * ec) const { if (!test) { throw NoTestsToPerform(); } - return test->passes(); + return test->passes(ec); } void -If::execute(const MultiRowSetPresenter * presenter) const +If::execute(const MultiRowSetPresenter * presenter, ExecContext * ec) const { - if (passes()) { + if (passes(ec)) { Logger()->messagef(LOG_DEBUG, "Test passed; showing %zu views", subViews.size()); BOOST_FOREACH(const SubViews::value_type & sq, subViews) { - sq->execute(presenter); + sq->execute(presenter, ec); } } } void -If::execute() const +If::execute(ExecContext * ec) const { - if (passes()) { + if (passes(ec)) { Logger()->messagef(LOG_DEBUG, "Test passed; executing %zu tasks", normal.size()); - run(normal); + run(normal, ec); } } diff --git a/project2/common/if.h b/project2/common/if.h index 2496dc4..64f885b 100644 --- a/project2/common/if.h +++ b/project2/common/if.h @@ -10,11 +10,11 @@ class If : public IHaveSubTasks, public View { public: If(ScriptNodePtr); - virtual void execute(const MultiRowSetPresenter*) const; - virtual void execute() const; + virtual void execute(const MultiRowSetPresenter *, ExecContext *) const; + virtual void execute(ExecContext *) const; private: - bool passes() const; + bool passes(ExecContext *) const; typedef ANONSTORAGEOF(View) SubViews; SubViews subViews; diff --git a/project2/common/iterate.cpp b/project2/common/iterate.cpp index 037261d..4473885 100644 --- a/project2/common/iterate.cpp +++ b/project2/common/iterate.cpp @@ -27,22 +27,16 @@ Iterate::loadComplete(const CommonObjects * co) } void -Iterate::rowReady(const RowState *) const +Iterate::execute(ExecContext * ec) const { - executeChildren(); + RowProcessor::execute(ec, boost::bind(&Iterate::executeChildren, this, ec)); } void -Iterate::execute() const -{ - RowProcessor::execute(); -} - -void -Iterate::executeChildren() const +Iterate::executeChildren(ExecContext * ec) const { BOOST_FOREACH(const Tasks::value_type & sq, normal) { - sq->execute(); + sq->execute(ec); } } diff --git a/project2/common/iterate.h b/project2/common/iterate.h index 540cec6..2afbe98 100644 --- a/project2/common/iterate.h +++ b/project2/common/iterate.h @@ -15,11 +15,10 @@ class Iterate : public IHaveSubTasks, public RowProcessor { virtual ~Iterate(); void loadComplete(const CommonObjects *); - void rowReady(const RowState *) const; - void execute() const; + void execute(ExecContext *) const; protected: - void executeChildren() const; + void executeChildren(ExecContext *) const; }; #endif diff --git a/project2/common/library.cpp b/project2/common/library.cpp index 4762211..738803f 100644 --- a/project2/common/library.cpp +++ b/project2/common/library.cpp @@ -11,7 +11,7 @@ SimpleMessageException(UnloadLibraryFailed); Library::Library(ScriptNodePtr p) : SourceObject(p), - handle(dlopen(Variable(p, "path")(), RTLD_NOW)) + handle(dlopen(Variable(p, "path")(NULL), RTLD_NOW)) { if (!handle) { throw LoadLibraryFailed(dlerror()); diff --git a/project2/common/memoryCache.cpp b/project2/common/memoryCache.cpp index 0a4f53f..7ab271e 100644 --- a/project2/common/memoryCache.cpp +++ b/project2/common/memoryCache.cpp @@ -43,7 +43,7 @@ class MemoryCache : public Cache { { } - void execute(const Glib::ustring&, const RowProcessor * rp) const { + void execute(const Glib::ustring&, const RowProcessorCallback & rp, ExecContext *) const { BOOST_FOREACH(const DataCache::value_type & mcr, dataCache) { mcr->process(rp, false); } @@ -100,8 +100,8 @@ class MemoryCache : public Cache { { } - RowSetCPtr getCachedRowSet(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { - Key key(makeKey(n, f, ps)); + RowSetCPtr getCachedRowSet(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { + Key key(makeKey(ec, n, f, ps)); CacheStore::index::type::const_iterator i = Store.get().find(key); if (i == Store.get().end()) { return NULL; @@ -113,27 +113,27 @@ class MemoryCache : public Cache { return *i; } - RowSetPresenterPtr openFor(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) { - return (cur = new CachedRowSet(makeKey(n, f, ps))); + RowSetPresenterPtr openFor(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) { + return (cur = new CachedRowSet(makeKey(ec, n, f, ps))); } - void save(const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) { + void save(ExecContext *, const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) { if (cur) { Store.insert(cur); cur.reset(); } } - void discard(const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) { + void discard(ExecContext *, const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) { cur.reset(); } private: - Key makeKey(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { + Key makeKey(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { Key key; key.push_back(n); key.push_back(f); - applyKeys([&key](const std::string &, const VariableType & v) { key.push_back(v); }, ps); + applyKeys(ec, [&key](const std::string &, const VariableType & v) { key.push_back(v); }, ps); return key; } diff --git a/project2/common/noOutputExecute.h b/project2/common/noOutputExecute.h index 67f6b00..61d03b5 100644 --- a/project2/common/noOutputExecute.h +++ b/project2/common/noOutputExecute.h @@ -5,6 +5,7 @@ #include "scriptStorage.h" class NoOutputExecute; +class ExecContext; typedef boost::intrusive_ptr NoOutputExecutePtr; /// Base class for Project2 compoments that perform actions, but product no output @@ -15,7 +16,7 @@ class NoOutputExecute : public virtual SourceObject { virtual ~NoOutputExecute(); - virtual void execute() const = 0; + virtual void execute(ExecContext *) const = 0; }; #endif diff --git a/project2/common/options.cpp b/project2/common/options.cpp index 5c79163..fd93576 100644 --- a/project2/common/options.cpp +++ b/project2/common/options.cpp @@ -1,6 +1,5 @@ #include #include "options.h" -#include "environment.h" #include class NamedOption : public Options::Option { @@ -11,9 +10,9 @@ class NamedOption : public Options::Option { desc(d) { } - void consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v) const { + void consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) const { if (n == id) { - target->consume(p, v); + target->consume(p, v, cp); } } void reset() const { @@ -44,9 +43,9 @@ class OptionAlias : public Options::Option { target(t) { } - void consume(const Glib::ustring & a, const Glib::ustring & p, const VariableType & v) const { + void consume(const Glib::ustring & a, const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) const { if (a == alias) { - target->target->consume(p, v); + target->target->consume(p, v, cp); } } void reset() const { @@ -108,10 +107,10 @@ Options::reset() const } void -Options::consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v) const +Options::consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) const { BOOST_FOREACH(const OptionPtr & o, options) { - o->consume(n, p, v); + o->consume(n, p, v, cp); } } @@ -145,13 +144,13 @@ Options::InstanceTarget::paramRequired() const } void -Options::InstanceTarget::consume(const Glib::ustring & p, const VariableType & v) const +Options::InstanceTarget::consume(const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) const { if (ts != Platform && p.empty()) { assign(v); ts = Global; } - else if (!p.empty() && p == Environment::getCurrent()->platform()) { + else if (!p.empty() && p == cp) { assign(v); ts = Platform; } diff --git a/project2/common/options.h b/project2/common/options.h index e92e69b..c2416ef 100644 --- a/project2/common/options.h +++ b/project2/common/options.h @@ -15,11 +15,13 @@ class Options { class Target; enum TargetState { Default = 1, Global = 2, Platform = 3 }; + typedef boost::function CurrentPlatform; + class Target : public IntrusivePtrBase { public: virtual void reset() const = 0; virtual bool paramRequired() const = 0; - virtual void consume(const Glib::ustring & platform, const VariableType & value) const = 0; + virtual void consume(const Glib::ustring & platform, const VariableType & value, const CurrentPlatform & currentPlatform) const = 0; }; typedef boost::intrusive_ptr TargetPtr; typedef boost::function Assigner; @@ -29,7 +31,7 @@ class Options { public: InstanceTarget(const Assigner &, const Resetter &); bool paramRequired() const; - void consume(const Glib::ustring & platform, const VariableType & value) const; + void consume(const Glib::ustring & platform, const VariableType & value, const CurrentPlatform & currentPlatform) const; protected: void reset() const; void assign(const VariableType & value) const; @@ -45,7 +47,7 @@ class Options { virtual Glib::ustring name() const = 0; virtual Glib::ustring description() const = 0; virtual bool accepts(const Glib::ustring & name) const = 0; - virtual void consume(const Glib::ustring & name, const Glib::ustring & platform, const VariableType & value) const = 0; + virtual void consume(const Glib::ustring & name, const Glib::ustring & platform, const VariableType & value, const CurrentPlatform & currentPlatform) const = 0; }; typedef boost::intrusive_ptr