From 4d2de57f7ae974347767785dbb2062986d30df27 Mon Sep 17 00:00:00 2001 From: randomdan Date: Thu, 20 Jun 2013 18:08:17 +0000 Subject: Move options into the global scope --- project2/cgi/cgiContentNegotiate.cpp | 25 +++---- project2/cgi/cgiEnvironment.cpp | 92 +++++++++++++------------ project2/cgi/cgiEnvironment.h | 33 +++++---- project2/cgi/cgiOutputOptions.cpp | 28 +++----- project2/cgi/cgiOutputOptions.h | 6 +- project2/cgi/cgiProgRouter.cpp | 26 +++----- project2/cgi/testCgi.cpp | 115 +++++++++++++++++--------------- project2/common/environment.cpp | 73 +++++++++----------- project2/common/environment.h | 17 +++-- project2/common/memoryCache.cpp | 21 ++---- project2/common/options.h | 19 ++++++ project2/common/scriptLoader.cpp | 25 +------ project2/common/scriptLoader.h | 38 ++++++++--- project2/console/consoleEnvironment.cpp | 46 ++++++------- project2/console/consoleEnvironment.h | 11 ++- project2/files/presenterCache.cpp | 35 ++++------ project2/json/couchSession.cpp | 23 ++----- project2/mail/sendmailTask.cpp | 30 +++------ project2/mail/sendmailTask.h | 2 + project2/sql/sqlCache.cpp | 31 +++------ project2/xml/sessionXml.cpp | 20 ++---- project2/xml/sessionXml.h | 1 + project2/xml/transformText.cpp | 45 +++++-------- project2/xml/xmlCache.cpp | 30 +++------ project2/xml/xmlPresenter.cpp | 104 +++++++++++------------------ project2/xml/xmlPresenter.h | 13 ++++ 26 files changed, 400 insertions(+), 509 deletions(-) diff --git a/project2/cgi/cgiContentNegotiate.cpp b/project2/cgi/cgiContentNegotiate.cpp index 2ed54c9..916dfc1 100644 --- a/project2/cgi/cgiContentNegotiate.cpp +++ b/project2/cgi/cgiContentNegotiate.cpp @@ -6,19 +6,6 @@ class ContentNegotiateLoader : public PresenterLoader { public: - ContentNegotiateLoader() : - opts("Content negotiation options") - { - opts - ("cgi.contentnegotiation.mappedtype", Options::functions( - [this](const VariableType & v) { mappedTypes.push_back(new MappedType(v)); }, - boost::bind(&MappedTypes::clear, &mappedTypes)), - "mimetype=presenter list of types to negotiate") - ; - } - - const Options * options() const { return &opts; } - MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os) const { auto accept = static_cast(CgiApplicationEngine::getCurrent())->env()->getAccept(); @@ -35,7 +22,7 @@ class ContentNegotiateLoader : public PresenterLoader { return PresenterLoader::getFor((*mappedTypes.begin())->present)->create(s, os); } - Options opts; + INITOPTIONS; class MappedType : public IntrusivePtrBase { public: MappedType(const std::string & val) : @@ -54,10 +41,18 @@ class ContentNegotiateLoader : public PresenterLoader { }; typedef boost::intrusive_ptr MappedTypePtr; typedef std::vector MappedTypes; - MappedTypes mappedTypes; + static MappedTypes mappedTypes; bool cacheable() const { return false; } }; +ContentNegotiateLoader::MappedTypes ContentNegotiateLoader::mappedTypes; DECLARE_CUSTOM_COMPONENT_LOADER("contentnegotiate", ContentNegotiateLoader, ContentNegotiateLoader, PresenterLoader); +DECLARE_OPTIONS(ContentNegotiateLoader, "Content negotiation options") +("cgi.contentnegotiation.mappedtype", Options::functions( + [](const VariableType & v) { mappedTypes.push_back(new MappedType(v)); }, + boost::bind(&MappedTypes::clear, &mappedTypes)), + "mimetype=presenter list of types to negotiate") +END_OPTIONS(ContentNegotiateLoader) + diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp index 618548c..7cd7cd5 100644 --- a/project2/cgi/cgiEnvironment.cpp +++ b/project2/cgi/cgiEnvironment.cpp @@ -10,49 +10,59 @@ #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), - cgiOptions("Project2 CGI options"), - hpi(new HostnamePlatformIdentifier()) -{ - cgiOptions - ("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, - "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") - ; -} - -const Options & -CgiEnvironment::engineOptions() const { - return cgiOptions; + cgienv(NULL) +{ } CgiEnvironment::~CgiEnvironment() diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h index c09f5a9..d1d51c0 100644 --- a/project2/cgi/cgiEnvironment.h +++ b/project2/cgi/cgiEnvironment.h @@ -53,26 +53,25 @@ class CgiEnvironment : public Environment { const CgiEnvInput * cgienv; private: - const Options & engineOptions() const; const Glib::ustring & platform() const; - Options cgiOptions; - boost::intrusive_ptr hpi; public: - std::string dumpdatadoc; - Glib::ustring errorContentType; - Glib::ustring errorTransformStyle; - std::string defaultPresent; - std::string transformContentType; - std::string transformTargetType; - std::string presentRoot; - std::string requestRoot; - std::string errorPresentRoot; - std::string notFoundPresent; - std::string onErrorPresent; - std::string defaultPresenter; - std::string sessionModule; - std::string routerType; + 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; }; diff --git a/project2/cgi/cgiOutputOptions.cpp b/project2/cgi/cgiOutputOptions.cpp index 59b034d..55e1de4 100644 --- a/project2/cgi/cgiOutputOptions.cpp +++ b/project2/cgi/cgiOutputOptions.cpp @@ -20,30 +20,20 @@ OutputOptions::OutputOptions(ScriptNodePtr p) : { } -OutputOptionsLoader::OutputOptionsLoader() : - opts("CGI default output options") -{ - opts - ("cgi.output.encoding", Options::value(&OutputOptions::encoding, "utf-8"), "Default out encoding") - ("cgi.output.core", Options::value(&OutputOptions::core, true), "Core messages") - ("cgi.output.session", Options::value(&OutputOptions::session, true), "Session values") - ("cgi.output.timing", Options::value(&OutputOptions::timing, true), "Timing") - ("cgi.output.environment", Options::value(&OutputOptions::environment, true), "Environment") - ("cgi.output.url", Options::value(&OutputOptions::url, true), "URL breakdown") - ("cgi.output.parameters", Options::value(&OutputOptions::parameters, true), "Parameters") - ; -} +DECLARE_OPTIONS(OutputOptionsLoader, "CGI default output options") +("cgi.output.encoding", Options::value(&OutputOptions::encoding, "utf-8"), "Default out encoding") +("cgi.output.core", Options::value(&OutputOptions::core, true), "Core messages") +("cgi.output.session", Options::value(&OutputOptions::session, true), "Session values") +("cgi.output.timing", Options::value(&OutputOptions::timing, true), "Timing") +("cgi.output.environment", Options::value(&OutputOptions::environment, true), "Environment") +("cgi.output.url", Options::value(&OutputOptions::url, true), "URL breakdown") +("cgi.output.parameters", Options::value(&OutputOptions::parameters, true), "Parameters") +END_OPTIONS(OutputOptionsLoader) OutputOptionsPtr OutputOptionsLoader::create(ScriptNodePtr e) const { return new OutputOptions(e); } -const Options * -OutputOptionsLoader::options() const -{ - return &opts; -} - DECLARE_CUSTOM_COMPONENT_LOADER("outputoptions", OutputOptions, OutputOptionsLoader, OutputOptionsLoader) diff --git a/project2/cgi/cgiOutputOptions.h b/project2/cgi/cgiOutputOptions.h index a975fa0..bb214ea 100644 --- a/project2/cgi/cgiOutputOptions.h +++ b/project2/cgi/cgiOutputOptions.h @@ -32,12 +32,8 @@ typedef boost::intrusive_ptr OutputOptionsPtr; class OutputOptionsLoader : public ComponentLoader { public: - OutputOptionsLoader(); OutputOptionsPtr create(ScriptNodePtr e) const; - const Options * options() const; - - private: - Options opts; + INITOPTIONS; }; #endif diff --git a/project2/cgi/cgiProgRouter.cpp b/project2/cgi/cgiProgRouter.cpp index 932242e..742924c 100644 --- a/project2/cgi/cgiProgRouter.cpp +++ b/project2/cgi/cgiProgRouter.cpp @@ -127,22 +127,6 @@ DECLARE_LOADER("route", Route); class ProgRouter; class ProgRouterLoader : public RouterLoader::For { public: - ProgRouterLoader() : - opts("CGI Prog Router options") - { - opts - ("cgi.progRouter.routes", Options::functions( - boost::bind(&RoutingTable::loadRoutesFromFile, &routingTable, _1), - boost::bind(&RoutingTable::clearRoutes, &routingTable)), - "Script file defining web service routes") - ; - } - - const Options * options() const - { - return &opts; - } - void onBefore() { routingTable.onBefore(); @@ -150,12 +134,18 @@ class ProgRouterLoader : public RouterLoader::For { static RoutingTable routingTable; - private: - Options opts; + INITOPTIONS; }; RoutingTable ProgRouterLoader::routingTable; +DECLARE_OPTIONS(ProgRouterLoader, "CGI Programmable Router options") +("cgi.progRouter.routes", Options::functions( + boost::bind(&RoutingTable::loadRoutesFromFile, &routingTable, _1), + boost::bind(&RoutingTable::clearRoutes, &routingTable)), + "Script file defining web service routes") +END_OPTIONS(ProgRouterLoader); + SimpleMessageException(UriElementNotFound); class ProgRouter : public Router { diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp index 6dc2193..cff947d 100644 --- a/project2/cgi/testCgi.cpp +++ b/project2/cgi/testCgi.cpp @@ -7,78 +7,47 @@ #include "../files/optionsSource.h" #define TESTOPT(name, def, desc) \ - (name, Options::value(optStore.insert(OptStore::value_type(name, StrPtr(new std::string()))).first->second.get(), def), desc) + (name, Options::value(optStore().insert(OptStore::value_type(name, StrPtr(new std::string()))).first->second.get(), def), desc) class TestInput : public cgicc::CgiInput, public CgiEnvInput { public: class TestConfigConsumer : public ConfigConsumer { public: - TestConfigConsumer(const Options * os) : o(os) { - } void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const { - o->consume(n, p, v); + LoaderBase::onAll(boost::bind(&Options::consume, _1, n, p, v)); } const Options::Option * get(const Glib::ustring &) const { return NULL; } - private: - const Options * o; }; typedef boost::shared_ptr StrPtr; typedef std::map OptStore; - OptStore optStore; - TestInput() : - opts("Project2 CGI test options"), - runCount(0) + TestInput(int argc, char ** argv) { - opts - TESTOPT("SERVER_NAME", "localhost", "FQDN of web service") - TESTOPT("SERVER_SOFTWARE", "Apache", "Web server version string") - TESTOPT("GATEWAY_INTERFACE", "CGI/1.1", "Web server/script interface version") - TESTOPT("SERVER_PROTOCOL", "HTTP/1.1", "Web server/client interface version") - TESTOPT("SERVER_PORT", "80", "Server Port") - TESTOPT("REQUEST_METHOD", "GET", "Request method") - TESTOPT("PATH_INFO", "", "Path info") - TESTOPT("PATH_TRANSLATED", "", "Path translated") - TESTOPT("SCRIPT_NAME", "p2fcgi", "Script name") - TESTOPT("QUERY_STRING", "", "Query string") - TESTOPT("REMOTE_HOST", "", "Remote host") - TESTOPT("REMOTE_ADDR", "", "Remote address") - TESTOPT("AUTH_TYPE", "", "Authentication type") - TESTOPT("REMOTE_USER", "", "Remote user") - TESTOPT("REMOTE_IDENT", "", "Remote ident") - TESTOPT("CONTENT_TYPE", "", "Content type") - TESTOPT("CONTENT_LENGTH", "", "Content length") - TESTOPT("HTTP_ACCEPT", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accepted MIME types") - TESTOPT("HTTP_USER_AGENT", "Mozilla/5.0", "User agent") - TESTOPT("REDIRECT_REQUEST", "", "Redirect request") - TESTOPT("REDIRECT_URL", "", "Redirect URL") - TESTOPT("REDIRECT_STATUS", "", "Redirect status") - TESTOPT("HTTP_REFERER", "", "Referrer") - TESTOPT("HTTP_COOKIE", "", "Cookie") - TESTOPT("HTTPS", "No", "HTTPS?") - TESTOPT("HTTP_IF_MODIFIED_SINCE", "", "Client cached copy timestamp") - ("urlListFile", Options::value(&urlListFile, ""), "Load URL list from this file") - ("runCount", Options::value(&runCount, 1), "Repeat run this many times") - ; + env.init(); FileOptions fo(".testCgi.settings"); - opts.reset(); - fo.loadInto(TestConfigConsumer(&opts)); - } - - const Options * options() const { - return &opts; + fo.loadInto(TestConfigConsumer()); + if (argc > 1) { + const char * qm = strchr(argv[1], '?'); + if (qm) { + optStore()["REDIRECT_URL"] = StrPtr(new std::string(argv[1], qm - argv[1])); + optStore()["QUERY_STRING"] = StrPtr(new std::string(qm + 1)); + } + else { + optStore()["REDIRECT_URL"] = StrPtr(new std::string(argv[1])); + } + } } std::string getenv(const std::string & varName) const { StrPtr def(new std::string()); - return *defaultMapFind(optStore, varName, def); + return *defaultMapFind(optStore(), varName, def); } virtual std::string getenv(const char * varName) { StrPtr def(new std::string()); - return *defaultMapFind(optStore, varName, def); + return *defaultMapFind(optStore(), varName, def); } void run() { @@ -93,24 +62,62 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput { while (!urls.eof()) { std::string url; urls >> url; - optStore["REDIRECT_URL"] = StrPtr(new std::string(url)); + optStore()["REDIRECT_URL"] = StrPtr(new std::string(url)); cgiServe(this, &env, std::cout, this); } } } } + INITOPTIONS; private: CgiEnvironment env; - Options opts; - int runCount; - std::string urlListFile; + static int runCount; + static std::string urlListFile; + static OptStore & optStore() + { + static OptStore _optStore; + return _optStore; + } }; +int TestInput::runCount; +std::string TestInput::urlListFile; + +DECLARE_OPTIONS(TestInput, "Project2 CGI test options") +TESTOPT("SERVER_NAME", "localhost", "FQDN of web service") +TESTOPT("SERVER_SOFTWARE", "Apache", "Web server version string") +TESTOPT("GATEWAY_INTERFACE", "CGI/1.1", "Web server/script interface version") +TESTOPT("SERVER_PROTOCOL", "HTTP/1.1", "Web server/client interface version") +TESTOPT("SERVER_PORT", "80", "Server Port") +TESTOPT("REQUEST_METHOD", "GET", "Request method") +TESTOPT("PATH_INFO", "", "Path info") +TESTOPT("PATH_TRANSLATED", "", "Path translated") +TESTOPT("SCRIPT_NAME", "p2fcgi", "Script name") +TESTOPT("QUERY_STRING", "", "Query string") +TESTOPT("REMOTE_HOST", "", "Remote host") +TESTOPT("REMOTE_ADDR", "", "Remote address") +TESTOPT("AUTH_TYPE", "", "Authentication type") +TESTOPT("REMOTE_USER", "", "Remote user") +TESTOPT("REMOTE_IDENT", "", "Remote ident") +TESTOPT("CONTENT_TYPE", "", "Content type") +TESTOPT("CONTENT_LENGTH", "", "Content length") +TESTOPT("HTTP_ACCEPT", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accepted MIME types") +TESTOPT("HTTP_USER_AGENT", "Mozilla/5.0", "User agent") +TESTOPT("REDIRECT_REQUEST", "", "Redirect request") +TESTOPT("REDIRECT_URL", "", "Redirect URL") +TESTOPT("REDIRECT_STATUS", "", "Redirect status") +TESTOPT("HTTP_REFERER", "", "Referrer") +TESTOPT("HTTP_COOKIE", "", "Cookie") +TESTOPT("HTTPS", "No", "HTTPS?") +TESTOPT("HTTP_IF_MODIFIED_SINCE", "", "Client cached copy timestamp") +("urlListFile", Options::value(&urlListFile, ""), "Load URL list from this file") +("runCount", Options::value(&runCount, 1), "Repeat run this many times") +END_OPTIONS(TestInput); int -main(int, char **) +main(int argc, char ** argv) { - TestInput ti; + TestInput ti(argc, argv); ti.run(); } diff --git a/project2/common/environment.cpp b/project2/common/environment.cpp index 57665f0..7d24c5c 100644 --- a/project2/common/environment.cpp +++ b/project2/common/environment.cpp @@ -11,27 +11,34 @@ #include const Environment * Environment::currentEnv(NULL); +#include +#include -Environment::Environment() : - commonOptions("Project2 Common options"), - clLevel(-1), - slLevel(-1) +DECLARE_OPTIONS(Environment, "Project2 Common options") +("common.syslogLevel", Options::value(&slLevel, -1), + "Log to syslog with level (default OFF)")("s") +("common.consolelogLevel", Options::value(&clLevel, LOG_WARNING), + "Log to console with level (default WARNING)")("c") +("common.datasourceRoot", Options::value(&datasourceRoot, "datasources"), + "The folder in which to find datasource definitions") +("common.namespace", Options::value(&scriptNamespace, "http://project2.randomdan.homeip.net"), + "The namespace to use for Project2 components and responses") +("common.namespacePrefix", Options::value(&scriptNamespacePrefix, "project2"), + "The namespace prefix to use for the Project2 namespace") +("common.sessionTimeOut", Options::value(&sessionTimeOut, 3600), + "The time after which idle sessions are forgotten") +END_OPTIONS(Environment); + +time_t Environment::sessionTimeOut; +std::string Environment::scriptNamespacePrefix; +std::string Environment::scriptNamespace; +std::string Environment::datasourceRoot; +int Environment::clLevel; +int Environment::slLevel; + +Environment::Environment() { currentEnv = this; - commonOptions - ("common.syslogLevel", Options::value(&slLevel, -1), - "Log to syslog with level (default OFF)")("s") - ("common.consolelogLevel", Options::value(&clLevel, LOG_WARNING), - "Log to console with level (default WARNING)")("c") - ("common.datasourceRoot", Options::value(&datasourceRoot, "datasources"), - "The folder in which to find datasource definitions") - ("common.namespace", Options::value(&scriptNamespace, "http://project2.randomdan.homeip.net"), - "The namespace to use for Project2 components and responses") - ("common.namespacePrefix", Options::value(&scriptNamespacePrefix, "project2"), - "The namespace prefix to use for the Project2 namespace") - ("common.sessionTimeOut", Options::value(&sessionTimeOut, 3600), - "The time after which idle sessions are forgotten") - ; typedef std::map > ConfigParsersMap; BOOST_FOREACH(const ConfigParsersMap::value_type & cp, *LoaderBase::objLoaders()) { configs.push_back(cp.second->create()); @@ -40,32 +47,21 @@ Environment::Environment() : typedef std::vector AllOptions; -static -void -optionsHelper(AllOptions * ao, const Options * options) -{ - if (options) { - ao->push_back(options); - } -} - class DefaultConfigConsumer : public ConfigConsumer { public: void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const { - BOOST_FOREACH(const Options * o, allOptions) { - o->consume(n, p, v); - } + LoaderBase::onAll(boost::bind(&Options::consume, _1, n, p, v)); } const Options::Option * get(const Glib::ustring & n) const { - BOOST_FOREACH(const Options * os, allOptions) { + const Options::Option * rtn = NULL; + LoaderBase::onAll([n,&rtn](const Options * os) { const Options::Option * o = os->find(n); if (o) { - return o; + rtn = o; } - } - return NULL; + }); + return rtn; } - AllOptions allOptions; }; void @@ -73,13 +69,8 @@ Environment::init() { if (std::find_if(configs.begin(), configs.end(), boost::bind(&OptionsSource::needReload, _1)) != configs.end()) { DefaultConfigConsumer dcc; - dcc.allOptions.push_back(&commonOptions); - dcc.allOptions.push_back(&engineOptions()); - LoaderBase::onAllComponents(boost::bind(optionsHelper, &dcc.allOptions, boost::bind(&ComponentLoader::options, _1))); - BOOST_FOREACH(const AllOptions::value_type & v, dcc.allOptions) { - v->reset(); - } + LoaderBase::onAll(boost::bind(&Options::reset, _1)); BOOST_FOREACH(const ConfigsMap::value_type & c, configs) { c->loadInto(dcc); diff --git a/project2/common/environment.h b/project2/common/environment.h index af9f5dd..a7f8f4b 100644 --- a/project2/common/environment.h +++ b/project2/common/environment.h @@ -7,6 +7,7 @@ #include #include #include "optionsSource.h" +#include "options.h" #include "exceptions.h" #include "scripts.h" @@ -29,14 +30,10 @@ class Environment { ScriptReaderPtr resolveScript(const std::string & group, const std::string & name, bool ii) const; + INITOPTIONS; private: - Options commonOptions; - virtual const Options & engineOptions() const = 0; - static const Environment * currentEnv; - int clLevel; - int slLevel; typedef std::vector ConfigsMap; ConfigsMap configs; typedef boost::tuple ScriptKey; @@ -44,10 +41,12 @@ class Environment { mutable ScriptCache scriptCache; public: - std::string datasourceRoot; - std::string scriptNamespace; - std::string scriptNamespacePrefix; - time_t sessionTimeOut; + static int clLevel; + static int slLevel; + static std::string datasourceRoot; + static std::string scriptNamespace; + static std::string scriptNamespacePrefix; + static time_t sessionTimeOut; }; #endif diff --git a/project2/common/memoryCache.cpp b/project2/common/memoryCache.cpp index 4e5f276..0ddd018 100644 --- a/project2/common/memoryCache.cpp +++ b/project2/common/memoryCache.cpp @@ -148,19 +148,6 @@ MemoryCache::CacheStore MemoryCache::Store; class CustomMemoryCacheLoader : public ElementLoader::For { public: - CustomMemoryCacheLoader() : - opts("Memory Cache options") - { - opts - ("cache.memory.life", Options::value(&MemoryCache::CacheLife, 3600), - "The age of cache entries after which they are removed (seconds)") - ; - } - - const Options * options() const { - return &opts; - } - void onPeriodic() { typedef MemoryCache::CacheStore::index::type::iterator iter; iter x = MemoryCache::Store.get().begin(); @@ -168,8 +155,12 @@ class CustomMemoryCacheLoader : public ElementLoader::For { MemoryCache::Store.get().erase(x, y); } - private: - Options opts; + INITOPTIONS; }; DECLARE_CUSTOM_LOADER("memorycache", CustomMemoryCacheLoader); +DECLARE_OPTIONS(CustomMemoryCacheLoader, "Memory Cache options") +("cache.memory.life", Options::value(&MemoryCache::CacheLife, 3600), + "The age of cache entries after which they are removed (seconds)") +END_OPTIONS(CustomMemoryCacheLoader); + diff --git a/project2/common/options.h b/project2/common/options.h index 8a2584c..34a22f6 100644 --- a/project2/common/options.h +++ b/project2/common/options.h @@ -96,5 +96,24 @@ class Options { OptionList options; }; +// Registration helpers +// These work pluggable component style + +#define DECLARE_OPTIONS(Type, Label) \ + static void init_options_##Type() __attribute__ ((constructor(200))); \ + static void init_options_##Type() { \ + Options * o = new Options(Label); \ + Type::InitOptions(*o); \ + LoaderBase::newLoader(#Type, o); } \ + void Type::InitOptions(Options & o) { o + +#define END_OPTIONS(Type) \ + ;} \ + static void kill_options_##Type() __attribute__ ((destructor(200))); \ + static void kill_options_##Type() { LoaderBase::removeLoader(#Type); } + +#define INITOPTIONS \ + static void InitOptions(Options &) + #endif diff --git a/project2/common/scriptLoader.cpp b/project2/common/scriptLoader.cpp index e4f31da..f622856 100644 --- a/project2/common/scriptLoader.cpp +++ b/project2/common/scriptLoader.cpp @@ -71,17 +71,6 @@ LoaderBase::getSub(ScriptNodePtr root, const Glib::ustring & name, bool required } } - -std::set > * & -LoaderBase::componentLoaders() -{ - static std::set > * _compLoaders = NULL; - if (!_compLoaders) { - _compLoaders = new std::set >(); - } - return _compLoaders; -} - void LoaderBase::collectAll(ScriptNodePtr node, bool childrenOnly, const StorerPtrs & sts) const { @@ -152,13 +141,7 @@ LoaderBase::collectAll(const CommonObjects * co, bool childrenOnly, ScriptNodePt void LoaderBase::onAllComponents(const boost::function1 & func) { - BOOST_FOREACH(ComponentLoaderSet::value_type l, *componentLoaders()) { - try { - func(l.get()); - } - catch (...) { - } - } + onAll(func); } ComponentLoader::~ComponentLoader() @@ -195,9 +178,3 @@ ComponentLoader::onConfigLoad() { } -const Options * -ComponentLoader::options() const -{ - return NULL; -} - diff --git a/project2/common/scriptLoader.h b/project2/common/scriptLoader.h index 2b1057b..6e0bfe5 100644 --- a/project2/common/scriptLoader.h +++ b/project2/common/scriptLoader.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "intrusivePtrBase.h" #include "sourceObject.h" #include "scripts_fwd.h" @@ -36,8 +37,29 @@ class LoaderBase { void discardLoadTargets(); static void onAllComponents(const boost::function1 &); + template + static void onAll(const boost::function & func) { + BOOST_FOREACH(const auto & l, *ComponentType::components()) { + try { + func(l.get()); + } + catch (...) { + } + } + } - static std::set > * & componentLoaders(); + template + class ComponentType { + public: + static std::set> * & components() + { + static std::set> * _comp = NULL; + if (!_comp) { + _comp = new std::set>(); + } + return _comp; + } + }; template static std::map > * & objLoaders() @@ -49,19 +71,19 @@ class LoaderBase { return _objLoaders; } - template + template static void newLoader(const std::string & n, T * l) { boost::shared_ptr p = boost::shared_ptr(l); objLoaders()->insert(std::pair >(n, p)); - componentLoaders()->insert(boost::shared_ptr(p)); + ComponentType::components()->insert(boost::shared_ptr(p)); } - template + template static void removeLoader(const std::string & n) { std::map > * & o = objLoaders(); - std::set > * & c = componentLoaders(); + std::set > * & c = ComponentType::components(); typename std::map >::iterator i = o->find(n); c->erase(i->second); o->erase(i); @@ -106,9 +128,9 @@ class LoaderBase { #define DECLARE_CUSTOM_COMPONENT_LOADER(N, I, T, B) \ namespace TOKENPASTE2(I, __LINE__) { \ static void init_loader_##I() __attribute__ ((constructor(201))); \ - static void init_loader_##I() { LoaderBase::newLoader(N, new T()); } \ + static void init_loader_##I() { LoaderBase::newLoader(N, new T()); } \ static void kill_loader_##I() __attribute__ ((destructor(201))); \ - static void kill_loader_##I() { LoaderBase::removeLoader(N); } \ + static void kill_loader_##I() { LoaderBase::removeLoader(N); } \ } #define DECLARE_CUSTOM_LOADER(N, T) \ DECLARE_CUSTOM_COMPONENT_LOADER(N, T, T, ElementLoader) @@ -120,7 +142,6 @@ namespace TOKENPASTE2(I, __LINE__) { \ DECLARE_CUSTOM_COMPONENT_LOADER(N, T, B::For, B); /// Helper for loading and maintaining Project2 components -class Options; class ComponentLoader { public: virtual ~ComponentLoader() = 0; @@ -130,7 +151,6 @@ class ComponentLoader { virtual void onIteration(); // When the app engine has completed an iteration virtual void onPeriodic(); // When the app engine feels like it virtual void onConfigLoad(); // When the environment reloads the configuration - virtual const Options * options() const; // Options to be populated from the common config file/env/etc virtual bool cacheable() const { return true; } // The component can be cached for next run }; diff --git a/project2/console/consoleEnvironment.cpp b/project2/console/consoleEnvironment.cpp index 6bbeeed..2cb64bd 100644 --- a/project2/console/consoleEnvironment.cpp +++ b/project2/console/consoleEnvironment.cpp @@ -25,13 +25,11 @@ class ShowHelpTrigger : public Options::Target { } void consume(const Glib::ustring &, const VariableType &) const { fprintf(stdout, "Help\n"); - LoaderBase::onAllComponents(boost::bind(&ShowHelpTrigger::outputOptions, this, _1)); + LoaderBase::onAll(boost::bind(&ShowHelpTrigger::outputOptions, this, _1)); exit(1); } private: - void outputOptions(ComponentLoader * cl) const { - const Options * options = cl->options(); - if (!options) return; + void outputOptions(const Options * options) const { fprintf(stdout, " * %s\n", options->name.c_str()); BOOST_FOREACH(const auto & option, options->allOptions()) { fprintf(stdout, " * %s - %s\n", option->name().c_str(), option->description().c_str()); @@ -39,28 +37,30 @@ class ShowHelpTrigger : public Options::Target { } }; -ConsoleEnvironment::ConsoleEnvironment(int c, char ** v) : - consoleOptions("Project2 Console options"), - help(false) +DECLARE_OPTIONS(ConsoleEnvironment, "Console options") +("help", new ShowHelpTrigger(), + "Print usage and exit")("h") +("console.syslogIdent", Options::value(&scriptname, "p2console"), + "Log to syslog with ident ") +("console.platform", Options::value(&reqPlatform), + "Platform")("p") +("console.queryParam", Options::functions( + [](const VariableType & v) { + Glib::ustring vs(v.as()); + queryParams.push_back(QueryParams::value_type(vs.substr(0, vs.find('=')), vs.substr(vs.find('=') + 1))); + }, + boost::bind(&QueryParams::clear, &queryParams)), +"Query parameter")("q") +END_OPTIONS(ConsoleEnvironment); + +std::string ConsoleEnvironment::scriptname; +Glib::ustring ConsoleEnvironment::reqPlatform; +ConsoleEnvironment::QueryParams ConsoleEnvironment::queryParams; + +ConsoleEnvironment::ConsoleEnvironment(int c, char ** v) { argc = c; argv = v; - consoleOptions - ("help", new ShowHelpTrigger(), "Print usage and exit")("h") - ("console.syslogIdent", Options::value(&scriptname, scriptname), "Log to syslog with ident ") - ("console.platform", Options::value(&reqPlatform), "Platform")("p") - ("console.queryParam", Options::functions( - [this](const VariableType & v) { - Glib::ustring vs(v.as()); - queryParams.push_back(QueryParams::value_type(vs.substr(0, vs.find('=')), vs.substr(vs.find('=') + 1))); - }, - boost::bind(&QueryParams::clear, &queryParams)), "Query parameter")("q") - ; -} - -const Options & -ConsoleEnvironment::engineOptions() const { - return consoleOptions; } ConsoleEnvironment::~ConsoleEnvironment() diff --git a/project2/console/consoleEnvironment.h b/project2/console/consoleEnvironment.h index fd54dd3..1379584 100644 --- a/project2/console/consoleEnvironment.h +++ b/project2/console/consoleEnvironment.h @@ -21,18 +21,17 @@ class ConsoleEnvironment : public Environment { std::string getScriptName() const; const ToDoList & todoList() const; + INITOPTIONS; private: - const Options & engineOptions() const; const Glib::ustring & platform() const; friend class CommandLineArguments; static int argc; static char ** argv; - Options consoleOptions; - bool help; - std::string scriptname; - Glib::ustring reqPlatform; - QueryParams queryParams; + static bool help; + static std::string scriptname; + static Glib::ustring reqPlatform; + static QueryParams queryParams; static ToDoList todolist; }; diff --git a/project2/files/presenterCache.cpp b/project2/files/presenterCache.cpp index 439028a..f3c3ea9 100644 --- a/project2/files/presenterCache.cpp +++ b/project2/files/presenterCache.cpp @@ -184,6 +184,7 @@ class FilePresenterCache : public PresenterCache { } WriteCacheStrmPtr writecache; + INITOPTIONS; private: Key getCacheKey() const { @@ -235,28 +236,19 @@ std::string FilePresenterCache::FileName; std::string FilePresenterCache::Provider; time_t FilePresenterCache::CacheLife; +DECLARE_OPTIONS(FilePresenterCache, "File Presenter Cache options") +("pcache.file.store", Options::value(&FilePresenterCache::Store, "/tmp/project2.pcache"), + "The root folder of the cache storage area") +("pcache.file.filename", Options::value(&FilePresenterCache::FileName, "cache"), + "The filename to store the data in") +("pcache.file.life", Options::value(&FilePresenterCache::CacheLife, 3600), + "The age of cache entries after which they are removed (seconds)") +("pcache.file.idprovider", Options::value(&FilePresenterCache::Provider, "requestid"), + "The name of the component used to provide a unique request ID") +END_OPTIONS(FilePresenterCache) + class FilePresenterCacheLoader : public ElementLoader::For { public: - FilePresenterCacheLoader() : - opts("File Presenter Cache options") - { - opts - ("pcache.file.store", Options::value(&FilePresenterCache::Store, "/tmp/project2.pcache"), - "The root folder of the cache storage area") - ("pcache.file.filename", Options::value(&FilePresenterCache::FileName, "cache"), - "The filename to store the data in") - ("pcache.file.life", Options::value(&FilePresenterCache::CacheLife, 3600), - "The age of cache entries after which they are removed (seconds)") - ("pcache.file.idprovider", Options::value(&FilePresenterCache::Provider, "requestid"), - "The name of the component used to provide a unique request ID") - ; - } - - const Options * options() const - { - return &opts; - } - void onIdle() { emptyDir(FilePresenterCache::Store); @@ -293,8 +285,5 @@ class FilePresenterCacheLoader : public ElementLoader::For { } return files; } - - private: - Options opts; }; DECLARE_CUSTOM_LOADER("filecache", FilePresenterCacheLoader); diff --git a/project2/json/couchSession.cpp b/project2/json/couchSession.cpp index ab7a7be..b4b3f6b 100644 --- a/project2/json/couchSession.cpp +++ b/project2/json/couchSession.cpp @@ -110,27 +110,12 @@ const Glib::ustring CouchSessionContainer::ExpiryKey("project2:expires"); class CustomCouchSessionLoader : public SessionContainerLoader::For { public: - CustomCouchSessionLoader() : - opts("Session CouchDB options") - { - opts - ("session.couchdb.baseUrl", Options::functions( - [](const VariableType & v) { CouchSessionContainer::baseUrls.push_back(v); }, - boost::bind(&std::vector::clear, &CouchSessionContainer::baseUrls)), - "Base URL to store sessions in") - ; - } - const Options * - options() const - { - return &opts; - } - void onPeriodic() { deleteSessions(); compactDB(); } + INITOPTIONS; private: static size_t discard(size_t l) { return l; @@ -188,7 +173,11 @@ class CustomCouchSessionLoader : public SessionContainerLoader::For::clear, &CouchSessionContainer::baseUrls)), + "Base URL to store sessions in") +END_OPTIONS(CustomCouchSessionLoader); + diff --git a/project2/mail/sendmailTask.cpp b/project2/mail/sendmailTask.cpp index f798e45..836b61a 100644 --- a/project2/mail/sendmailTask.cpp +++ b/project2/mail/sendmailTask.cpp @@ -14,28 +14,14 @@ std::string SendMailTask::defaultMailServer; std::string SendMailTask::defaultMailEncoding; -class CustomSendMailTaskLoader : public ElementLoader::For { - public: - CustomSendMailTaskLoader() : - opts("Send Email Task options") - { - opts - ("sendmail.defaultServer", Options::value(&SendMailTask::defaultMailServer), - "The address of the default mail relay server") - ("sendmail.defaultEncoding", Options::value(&SendMailTask::defaultMailEncoding, "utf-8"), - "The default encoding to use in email content") - ; - } - const Options * - options() const - { - return &opts; - } - - private: - Options opts; -}; -DECLARE_CUSTOM_LOADER("sendmail", CustomSendMailTaskLoader); +DECLARE_OPTIONS(SendMailTask, "Send Email Task options") +("sendmail.defaultServer", Options::value(&SendMailTask::defaultMailServer), + "The address of the default mail relay server") +("sendmail.defaultEncoding", Options::value(&SendMailTask::defaultMailEncoding, "utf-8"), + "The default encoding to use in email content") +END_OPTIONS(SendMailTask); + +DECLARE_LOADER("sendmail", SendMailTask); uint8_t SendMailTask::MailPart::mimeIdx; diff --git a/project2/mail/sendmailTask.h b/project2/mail/sendmailTask.h index 75d98f6..20435e8 100644 --- a/project2/mail/sendmailTask.h +++ b/project2/mail/sendmailTask.h @@ -7,6 +7,7 @@ #include "transform.h" #include "variables.h" #include "presenter.h" +#include /// Project2 component to send an email class SendMailTask : public Task { @@ -34,6 +35,7 @@ class SendMailTask : public Task { SendMailTask(ScriptNodePtr p); virtual ~SendMailTask(); virtual void execute() const; + INITOPTIONS; protected: const Variable to; diff --git a/project2/sql/sqlCache.cpp b/project2/sql/sqlCache.cpp index bb8adb1..bb61969 100644 --- a/project2/sql/sqlCache.cpp +++ b/project2/sql/sqlCache.cpp @@ -246,6 +246,7 @@ class SqlCache : public Cache { s->execute(); } + INITOPTIONS; private: friend class CustomSqlCacheLoader; const RdbmsDataSource * db; @@ -260,24 +261,6 @@ time_t SqlCache::CacheLife; class CustomSqlCacheLoader : public ElementLoader::For { public: - CustomSqlCacheLoader() : - opts("SQL Cache options") - { - opts - ("cache.sql.dataSource", Options::value(&SqlCache::DataSource), - "The default datasource to connect to") - ("cache.sql.headerTable", Options::value(&SqlCache::HeaderTable, "p2cache"), - "The filename to store the data in") - ("cache.sql.life", Options::value(&SqlCache::CacheLife, 3600), - "The age of cache entries after which they are removed (seconds)") - ; - } - - const Options * options() const - { - return &opts; - } - void onIdle() { if (!SqlCache::DataSource.empty()) { @@ -291,9 +274,15 @@ class CustomSqlCacheLoader : public ElementLoader::For { db->commit(); } } - - private: - Options opts; }; DECLARE_CUSTOM_LOADER("sqlcache", CustomSqlCacheLoader); +DECLARE_OPTIONS(SqlCache, "SQL Cache options") +("cache.sql.dataSource", Options::value(&DataSource), + "The default datasource to connect to") +("cache.sql.headerTable", Options::value(&HeaderTable, "p2cache"), + "The filename to store the data in") +("cache.sql.life", Options::value(&CacheLife, 3600), + "The age of cache entries after which they are removed (seconds)") +END_OPTIONS(SqlCache) + diff --git a/project2/xml/sessionXml.cpp b/project2/xml/sessionXml.cpp index 85ad6bd..7194246 100644 --- a/project2/xml/sessionXml.cpp +++ b/project2/xml/sessionXml.cpp @@ -12,14 +12,6 @@ class CustomSessionContainerLoaderXml : public SessionContainerLoader::For { public: - CustomSessionContainerLoaderXml() : - opts("SessionXML options") - { - opts - ("session.xml.path", Options::value(&SessionContainerXml::xmlDir, "/tmp/project2.sessions"), - "Path of the folder in which to store XML files for session information") - ; - } void onBefore() { boost::filesystem::create_directories(SessionContainerXml::xmlDir); @@ -36,15 +28,11 @@ class CustomSessionContainerLoaderXml : public SessionContainerLoader::For { - public: - TransformHtmlToTextLoader() : - opts("Transform HTML to text options") - { - opts - ("tx.html2txt.width", Options::value(&defaultWidth, 105), - "Default width in the resulting text document") - ("tx.html2txt.links", Options::value(&defaultLinks, false), - "Default flag for whether the document should contain link references"); - } - const Options * options() const - { - return &opts; - } - - static int defaultWidth; - static bool defaultLinks; - - private: - Options opts; -}; - class TransformHtmlToText : public TransformImpl { public: TransformHtmlToText() : - width(TransformHtmlToTextLoader::defaultWidth), - links(TransformHtmlToTextLoader::defaultLinks) { + width(defaultWidth), + links(defaultLinks) { } void transform(const HtmlDocument * cdoc, TextDocument * str) const { @@ -105,14 +81,25 @@ class TransformHtmlToText : public TransformImpl { s->applyValue("width", width); s->applyValue("links", links); } + + INITOPTIONS; private: + static int defaultWidth; + static bool defaultLinks; VariableType width; VariableType links; }; -int TransformHtmlToTextLoader::defaultWidth; -bool TransformHtmlToTextLoader::defaultLinks; +DECLARE_OPTIONS(TransformHtmlToText, "Transform HTML to text options") +("tx.html2txt.width", Options::value(&defaultWidth, 105), + "Default width in the resulting text document") +("tx.html2txt.links", Options::value(&defaultLinks, false), + "Default flag for whether the document should contain link references"); +END_OPTIONS(TransformHtmlToText) + +int TransformHtmlToText::defaultWidth; +bool TransformHtmlToText::defaultLinks; -DECLARE_CUSTOM_COMPONENT_LOADER("TransformHtmlToText", TransformHtmlToText, TransformHtmlToTextLoader, TransformLoader); +DECLARE_COMPONENT_LOADER("TransformHtmlToText", TransformHtmlToText, TransformLoader); DECLARE_TRANSFORMTARGET("textdocument", TextDocument) diff --git a/project2/xml/xmlCache.cpp b/project2/xml/xmlCache.cpp index 7224cba..7f3b5be 100644 --- a/project2/xml/xmlCache.cpp +++ b/project2/xml/xmlCache.cpp @@ -58,6 +58,7 @@ class XmlCache : public Cache { { } + INITOPTIONS; private: boost::filesystem::path getCacheFile(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const { @@ -87,24 +88,6 @@ time_t XmlCache::CacheLife; class CustomXmlCacheLoader : public ElementLoader::For { public: - CustomXmlCacheLoader() : - opts("XML Cache options") - { - opts - ("cache.xml.store", Options::value(&XmlCache::Store, "/tmp/project2.cache"), - "The root folder of the cache storage area") - ("cache.xml.filename", Options::value(&XmlCache::FileName, "cache.xml"), - "The filename to store the data in") - ("cache.xml.life", Options::value(&XmlCache::CacheLife, 3600), - "The age of cache entries after which they are removed (seconds)") - ; - } - - const Options * options() const - { - return &opts; - } - void onIdle() { emptyDir(XmlCache::Store); @@ -136,9 +119,14 @@ class CustomXmlCacheLoader : public ElementLoader::For { } return files; } - - private: - Options opts; }; DECLARE_CUSTOM_LOADER("xmlcache", CustomXmlCacheLoader); +DECLARE_OPTIONS(XmlCache, "XML Cache options") +("cache.xml.store", Options::value(&XmlCache::Store, "/tmp/project2.cache"), + "The root folder of the cache storage area") +("cache.xml.filename", Options::value(&XmlCache::FileName, "cache.xml"), + "The filename to store the data in") +("cache.xml.life", Options::value(&XmlCache::CacheLife, 3600), + "The age of cache entries after which they are removed (seconds)") +END_OPTIONS(XmlCache) diff --git a/project2/xml/xmlPresenter.cpp b/project2/xml/xmlPresenter.cpp index 48f5752..5f7c3dd 100644 --- a/project2/xml/xmlPresenter.cpp +++ b/project2/xml/xmlPresenter.cpp @@ -10,62 +10,38 @@ #include #include -class XmlPresenterLoader : public PresenterLoader::For { - public: - XmlPresenterLoader() : - opts("XML Presenter options") - { - opts - ("presenter.xml.typeid.null", Options::value(&typeidNull, false), - "Indicate the type of nulls on output") - ("presenter.xml.typeid.boolean", Options::value(&typeidBoolean, true), - "Indicate the type of booleans on output") - ("presenter.xml.typeid.string", Options::value(&typeidString, false), - "Indicate the type of strings on output") - ("presenter.xml.typeid.int", Options::value(&typeidInt, true), - "Indicate the type of integers on output") - ("presenter.xml.typeid.float", Options::value(&typeidFloat, true), - "Indicate the type of floating point numbers on output") - ("presenter.xml.typeid.datetime", Options::value(&typeidDateTime, true), - "Indicate the type of datetimes on output") - ("presenter.xml.datetime.dateattr", Options::value(&dateAttr, true), - "Output a date attribute in standard format") - ("presenter.xml.datetime.timeattr", Options::value(&timeAttr, true), - "Output a time attribute in standard format") - ("presenter.xml.datetime.customformat", Options::value(&customFormat), - "Output a time attribute in this custom format") - ; - } - - const Options * options() const - { - return &opts; - } - - static bool typeidNull; - static bool typeidBoolean; - static bool typeidString; - static bool typeidInt; - static bool typeidFloat; - static bool typeidDateTime; - static bool dateAttr; - static bool timeAttr; - static boost::optional customFormat; - private: - Options opts; -}; +DECLARE_OPTIONS(XmlPresenter, "XML Presenter options") +("presenter.xml.typeid.null", Options::value(&typeidNull, false), + "Indicate the type of nulls on output") +("presenter.xml.typeid.boolean", Options::value(&typeidBoolean, true), + "Indicate the type of booleans on output") +("presenter.xml.typeid.string", Options::value(&typeidString, false), + "Indicate the type of strings on output") +("presenter.xml.typeid.int", Options::value(&typeidInt, true), + "Indicate the type of integers on output") +("presenter.xml.typeid.float", Options::value(&typeidFloat, true), + "Indicate the type of floating point numbers on output") +("presenter.xml.typeid.datetime", Options::value(&typeidDateTime, true), + "Indicate the type of datetimes on output") +("presenter.xml.datetime.dateattr", Options::value(&dateAttr, true), + "Output a date attribute in standard format") +("presenter.xml.datetime.timeattr", Options::value(&timeAttr, true), + "Output a time attribute in standard format") +("presenter.xml.datetime.customformat", Options::value(&customFormat), + "Output a time attribute in this custom format") +END_OPTIONS(XmlPresenter) -bool XmlPresenterLoader::typeidNull; -bool XmlPresenterLoader::typeidBoolean; -bool XmlPresenterLoader::typeidString; -bool XmlPresenterLoader::typeidInt; -bool XmlPresenterLoader::typeidFloat; -bool XmlPresenterLoader::typeidDateTime; -bool XmlPresenterLoader::dateAttr; -bool XmlPresenterLoader::timeAttr; -boost::optional XmlPresenterLoader::customFormat; +bool XmlPresenter::typeidNull; +bool XmlPresenter::typeidBoolean; +bool XmlPresenter::typeidString; +bool XmlPresenter::typeidInt; +bool XmlPresenter::typeidFloat; +bool XmlPresenter::typeidDateTime; +bool XmlPresenter::dateAttr; +bool XmlPresenter::timeAttr; +boost::optional XmlPresenter::customFormat; -DECLARE_CUSTOM_COMPONENT_LOADER("xml", XmlPresenter, XmlPresenterLoader, PresenterLoader) +DECLARE_GENERIC_LOADER("xml", PresenterLoader, XmlPresenter) XmlPresenter::XmlPresenter(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle, const Glib::ustring & ct) : Presenter(Default), @@ -183,38 +159,38 @@ class XmlNodeWriter : public boost::static_visitor { public: XmlNodeWriter(xmlpp::Element * n) : node(n) { } bool operator()(const Null &) const { - addType(XmlPresenterLoader::typeidNull, "null"); + addType(XmlPresenter::typeidNull, "null"); return false; } bool operator()(const Boolean &) const { - addType(XmlPresenterLoader::typeidBoolean, "bool"); + addType(XmlPresenter::typeidBoolean, "bool"); return true; } bool operator()(const Glib::ustring &) const { - addType(XmlPresenterLoader::typeidString, "string"); + addType(XmlPresenter::typeidString, "string"); return true; } bool operator()(const int64_t &) const { - addType(XmlPresenterLoader::typeidInt, "int"); + addType(XmlPresenter::typeidInt, "int"); return true; } bool operator()(const double &) const { - addType(XmlPresenterLoader::typeidFloat, "float"); + addType(XmlPresenter::typeidFloat, "float"); return true; } bool operator()(const boost::posix_time::ptime & i) const { - addType(XmlPresenterLoader::typeidDateTime, "datetime"); - if (XmlPresenterLoader::timeAttr) { + addType(XmlPresenter::typeidDateTime, "datetime"); + if (XmlPresenter::timeAttr) { node->set_attribute("time", boost::posix_time::to_simple_string(i.time_of_day())); } - if (XmlPresenterLoader::dateAttr) { + if (XmlPresenter::dateAttr) { node->set_attribute("date", boost::gregorian::to_iso_extended_string(i.date())); } - if (!!XmlPresenterLoader::customFormat) { + if (!!XmlPresenter::customFormat) { std::stringstream ss; boost::date_time::time_facet * ft = new boost::date_time::time_facet(); ss.imbue(std::locale(ss.getloc(), ft)); - ft->format(XmlPresenterLoader::customFormat->c_str()); + ft->format(XmlPresenter::customFormat->c_str()); ss << boost::get(i); node->set_attribute("custom", ss.str()); } diff --git a/project2/xml/xmlPresenter.h b/project2/xml/xmlPresenter.h index 79d9634..fd586a5 100644 --- a/project2/xml/xmlPresenter.h +++ b/project2/xml/xmlPresenter.h @@ -46,6 +46,7 @@ class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf< void finalizeContent() const; void init(); + INITOPTIONS; private: void createDoc(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle) const; XmlDocumentPtr responseDoc; @@ -55,6 +56,18 @@ class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf< typedef ANONORDEREDSTORAGEOF(XmlDocMutator) Mutators; Mutators mutators; + + friend class XmlNodeWriter; + + static bool typeidNull; + static bool typeidBoolean; + static bool typeidString; + static bool typeidInt; + static bool typeidFloat; + static bool typeidDateTime; + static bool dateAttr; + static bool timeAttr; + static boost::optional customFormat; }; typedef boost::intrusive_ptr XmlPresenterPtr; -- cgit v1.2.3