diff options
| author | randomdan <randomdan@localhost> | 2013-06-20 18:08:17 +0000 | 
|---|---|---|
| committer | randomdan <randomdan@localhost> | 2013-06-20 18:08:17 +0000 | 
| commit | 4d2de57f7ae974347767785dbb2062986d30df27 (patch) | |
| tree | c6ccd43f1524adb06850795efa33d822691e30ca | |
| parent | Add back some basic help output (diff) | |
| download | project2-4d2de57f7ae974347767785dbb2062986d30df27.tar.bz2 project2-4d2de57f7ae974347767785dbb2062986d30df27.tar.xz project2-4d2de57f7ae974347767785dbb2062986d30df27.zip  | |
Move options into the global scope
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(¬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<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;  | 
