summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project2/cgi/cgiContentNegotiate.cpp25
-rw-r--r--project2/cgi/cgiEnvironment.cpp92
-rw-r--r--project2/cgi/cgiEnvironment.h33
-rw-r--r--project2/cgi/cgiOutputOptions.cpp28
-rw-r--r--project2/cgi/cgiOutputOptions.h6
-rw-r--r--project2/cgi/cgiProgRouter.cpp26
-rw-r--r--project2/cgi/testCgi.cpp115
-rw-r--r--project2/common/environment.cpp73
-rw-r--r--project2/common/environment.h17
-rw-r--r--project2/common/memoryCache.cpp21
-rw-r--r--project2/common/options.h19
-rw-r--r--project2/common/scriptLoader.cpp25
-rw-r--r--project2/common/scriptLoader.h38
-rw-r--r--project2/console/consoleEnvironment.cpp46
-rw-r--r--project2/console/consoleEnvironment.h11
-rw-r--r--project2/files/presenterCache.cpp35
-rw-r--r--project2/json/couchSession.cpp23
-rw-r--r--project2/mail/sendmailTask.cpp30
-rw-r--r--project2/mail/sendmailTask.h2
-rw-r--r--project2/sql/sqlCache.cpp31
-rw-r--r--project2/xml/sessionXml.cpp20
-rw-r--r--project2/xml/sessionXml.h1
-rw-r--r--project2/xml/transformText.cpp45
-rw-r--r--project2/xml/xmlCache.cpp30
-rw-r--r--project2/xml/xmlPresenter.cpp104
-rw-r--r--project2/xml/xmlPresenter.h13
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<const CgiApplicationEngine *>(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<MappedType> MappedTypePtr;
typedef std::vector<MappedTypePtr> 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 <glibmm/regex.h>
#include <curl/curl.h>
+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<HostnamePlatformIdentifier> 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(&notFoundPresent),
+ "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(&notFoundPresent),
- "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<HostnamePlatformIdentifier> 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<HostnamePlatformIdentifier> 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<const Router> 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<OutputOptions> 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<ProgRouter> {
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<ProgRouter> {
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<Options>(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<std::string> StrPtr;
typedef std::map<std::string, StrPtr> 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 <boost/bind.hpp>
const Environment * Environment::currentEnv(NULL);
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/facilities/expand.hpp>
-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 <arg> (default OFF)")("s")
+("common.consolelogLevel", Options::value(&clLevel, LOG_WARNING),
+ "Log to console with level <arg> (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 <arg> (default OFF)")("s")
- ("common.consolelogLevel", Options::value(&clLevel, LOG_WARNING),
- "Log to console with level <arg> (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<std::string, boost::shared_ptr<OptionsSourceLoader> > ConfigParsersMap;
BOOST_FOREACH(const ConfigParsersMap::value_type & cp, *LoaderBase::objLoaders<OptionsSourceLoader>()) {
configs.push_back(cp.second->create());
@@ -40,32 +47,21 @@ Environment::Environment() :
typedef std::vector<const Options *> 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<Options>(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<Options>([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<Options>(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 <boost/tuple/tuple.hpp>
#include <boost/filesystem/path.hpp>
#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<OptionsSourcePtr> ConfigsMap;
ConfigsMap configs;
typedef boost::tuple<const std::string, const std::string> 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<MemoryCache> {
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<MemoryCache::IndexByTime>::type::iterator iter;
iter x = MemoryCache::Store.get<MemoryCache::IndexByTime>().begin();
@@ -168,8 +155,12 @@ class CustomMemoryCacheLoader : public ElementLoader::For<MemoryCache> {
MemoryCache::Store.get<MemoryCache::IndexByTime>().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<Options, Options>(#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<Options, Options>(#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<boost::shared_ptr<ComponentLoader> > * &
-LoaderBase::componentLoaders()
-{
- static std::set<boost::shared_ptr<ComponentLoader> > * _compLoaders = NULL;
- if (!_compLoaders) {
- _compLoaders = new std::set<boost::shared_ptr<ComponentLoader> >();
- }
- 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<void, ComponentLoader *> & func)
{
- BOOST_FOREACH(ComponentLoaderSet::value_type l, *componentLoaders()) {
- try {
- func(l.get());
- }
- catch (...) {
- }
- }
+ onAll<ComponentLoader>(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 <boost/intrusive_ptr.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/foreach.hpp>
#include "intrusivePtrBase.h"
#include "sourceObject.h"
#include "scripts_fwd.h"
@@ -36,8 +37,29 @@ class LoaderBase {
void discardLoadTargets();
static void onAllComponents(const boost::function1<void, ComponentLoader *> &);
+ template <class CT>
+ static void onAll(const boost::function<void(CT *)> & func) {
+ BOOST_FOREACH(const auto & l, *ComponentType<CT>::components()) {
+ try {
+ func(l.get());
+ }
+ catch (...) {
+ }
+ }
+ }
- static std::set<boost::shared_ptr<ComponentLoader> > * & componentLoaders();
+ template <class CT>
+ class ComponentType {
+ public:
+ static std::set<boost::shared_ptr<CT>> * & components()
+ {
+ static std::set<boost::shared_ptr<CT>> * _comp = NULL;
+ if (!_comp) {
+ _comp = new std::set<boost::shared_ptr<CT>>();
+ }
+ return _comp;
+ }
+ };
template <class T>
static std::map<std::string, boost::shared_ptr<T> > * & objLoaders()
@@ -49,19 +71,19 @@ class LoaderBase {
return _objLoaders;
}
- template <class T>
+ template <class T, class BT>
static void newLoader(const std::string & n, T * l)
{
boost::shared_ptr<T> p = boost::shared_ptr<T>(l);
objLoaders<T>()->insert(std::pair<std::string, boost::shared_ptr<T> >(n, p));
- componentLoaders()->insert(boost::shared_ptr<T>(p));
+ ComponentType<BT>::components()->insert(boost::shared_ptr<T>(p));
}
- template <class T>
+ template <class T, class BT>
static void removeLoader(const std::string & n)
{
std::map<std::string, boost::shared_ptr<T> > * & o = objLoaders<T>();
- std::set<boost::shared_ptr<ComponentLoader> > * & c = componentLoaders();
+ std::set<boost::shared_ptr<BT> > * & c = ComponentType<BT>::components();
typename std::map<std::string, boost::shared_ptr<T> >::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<B>(N, new T()); } \
+ static void init_loader_##I() { LoaderBase::newLoader<B, ComponentLoader>(N, new T()); } \
static void kill_loader_##I() __attribute__ ((destructor(201))); \
- static void kill_loader_##I() { LoaderBase::removeLoader<B>(N); } \
+ static void kill_loader_##I() { LoaderBase::removeLoader<B, ComponentLoader>(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<T>, 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<Options>(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 <arg>")
+("console.platform", Options::value(&reqPlatform),
+ "Platform")("p")
+("console.queryParam", Options::functions(
+ [](const VariableType & v) {
+ Glib::ustring vs(v.as<Glib::ustring>());
+ 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 <arg>")
- ("console.platform", Options::value(&reqPlatform), "Platform")("p")
- ("console.queryParam", Options::functions(
- [this](const VariableType & v) {
- Glib::ustring vs(v.as<Glib::ustring>());
- 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<FilePresenterCache> {
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<FilePresenterCache> {
}
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<CouchSessionContainer> {
public:
- CustomCouchSessionLoader() :
- opts("Session CouchDB options")
- {
- opts
- ("session.couchdb.baseUrl", Options::functions(
- [](const VariableType & v) { CouchSessionContainer::baseUrls.push_back(v); },
- boost::bind(&std::vector<std::string>::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<CouchSession
return;
}
}
- Options opts;
};
DECLARE_CUSTOM_COMPONENT_LOADER("couchsession", CouchSessionContainer, CustomCouchSessionLoader, SessionContainerLoader);
+DECLARE_OPTIONS(CustomCouchSessionLoader, "Session CouchDB options")
+("session.couchdb.baseUrl", Options::functions([](const VariableType & v) { CouchSessionContainer::baseUrls.push_back(v); }, boost::bind(&std::vector<std::string>::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<SendMailTask> {
- 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 <options.h>
/// 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<SqlCache> {
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<SqlCache> {
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<SessionContainerXml> {
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<Sessi
}
}
}
- const Options *
- options() const
- {
- return &opts;
- }
-
- private:
- Options opts;
};
+DECLARE_OPTIONS(SessionContainerXml, "Session XML options")
+("session.xml.path", Options::value(&xmlDir, "/tmp/project2.sessions"),
+ "Path of the folder in which to store XML files for session information")
+END_OPTIONS(SessionContainerXml)
boost::filesystem::path SessionContainerXml::xmlDir;
DECLARE_CUSTOM_COMPONENT_LOADER("xml", SessionContainerXml, CustomSessionContainerLoaderXml, SessionContainerLoader);
diff --git a/project2/xml/sessionXml.h b/project2/xml/sessionXml.h
index 98123f6..e79e507 100644
--- a/project2/xml/sessionXml.h
+++ b/project2/xml/sessionXml.h
@@ -10,6 +10,7 @@ class SessionContainerXml : public SessionContainer {
~SessionContainerXml();
void SaveSession(SessionPtr) const;
+ INITOPTIONS;
protected:
SessionPtr getSession(const boost::uuids::uuid & sid) const;
diff --git a/project2/xml/transformText.cpp b/project2/xml/transformText.cpp
index 2ea755f..dc69b17 100644
--- a/project2/xml/transformText.cpp
+++ b/project2/xml/transformText.cpp
@@ -36,35 +36,11 @@ TextDocument::getContentClass() const {
return ClassPlain;
}
-class TransformHtmlToText;
-class TransformHtmlToTextLoader : public TransformLoader::For<TransformHtmlToText> {
- 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<HtmlDocument, TextDocument> {
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<HtmlDocument, TextDocument> {
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<XmlCache> {
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<XmlCache> {
}
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 <boost/date_time/gregorian/formatters.hpp>
#include <boost/foreach.hpp>
-class XmlPresenterLoader : public PresenterLoader::For<XmlPresenter> {
- 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<std::string> 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<std::string> 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<std::string> 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<bool> {
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<boost::posix_time::ptime, char> * ft = new boost::date_time::time_facet<boost::posix_time::ptime, char>();
ss.imbue(std::locale(ss.getloc(), ft));
- ft->format(XmlPresenterLoader::customFormat->c_str());
+ ft->format(XmlPresenter::customFormat->c_str());
ss << boost::get<boost::posix_time::ptime>(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<std::string> customFormat;
};
typedef boost::intrusive_ptr<XmlPresenter> XmlPresenterPtr;