diff options
42 files changed, 740 insertions, 427 deletions
| diff --git a/project2/cgi/Jamfile.jam b/project2/cgi/Jamfile.jam index 261e992..48225cb 100644 --- a/project2/cgi/Jamfile.jam +++ b/project2/cgi/Jamfile.jam @@ -2,7 +2,6 @@ alias libxmlpp : : : :  	<cflags>"`pkg-config --cflags libxml++-2.6`"  	<linkflags>"`pkg-config --libs libxml++-2.6`" ;  lib boost_filesystem : : <name>boost_filesystem ; -lib boost_program_options : : <name>boost_program_options ;  lib cgicc : : <name>cgicc ;  lib fcgi : : <name>fcgi ;  lib fcgi++ : : <name>fcgi++ ; @@ -12,7 +11,6 @@ cpp-pch pch : pch.hpp :  	<library>cgicc  	<library>libxmlpp  	<library>../common//p2common -	<library>boost_program_options  	<library>boost_filesystem  	<library>../xml//p2xml  	; @@ -24,7 +22,6 @@ lib p2web :  	<library>cgicc  	<library>libxmlpp  	<library>../common//p2common -	<library>boost_program_options  	<library>boost_filesystem  	<library>../xml//p2xml  	: : diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 779b25a..7fd7c33 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -9,7 +9,6 @@  #include <boost/foreach.hpp>  #include "ostreamWrapper.h"  #include <boost/date_time/microsec_time_clock.hpp> -#include <glibmm/regex.h>  const std::string SESSIONID = "sessionID";  typedef UUID SIDKey; @@ -27,7 +26,6 @@ getSessionID(const std::vector<cgicc::HTTPCookie> & cookies) {  	return UUID();  }  CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) : -	ApplicationEngine("web/host"),  	_env(e),  	sessionsContainer(LoaderBase::getLoader<SessionContainerLoader, NotSupported>(e->sessionModule)->open()),  	IO(io) @@ -200,27 +198,3 @@ CgiApplicationEngine::session() const  	return cursession;  } -bool -CgiApplicationEngine::checkDomain(const DomainPlatforms::value_type & i) const -{ -	Glib::RefPtr<Glib::Regex> reg = Glib::Regex::create(i.first, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL); -	return reg->match(_env->getServerName()); -} - -Glib::ustring -CgiApplicationEngine::resolveCurrentConfig() const -{ -	DomainPlatforms::const_iterator i = std::find_if(domplat.begin(), domplat.end(), boost::bind(&CgiApplicationEngine::checkDomain, this, _1)); -	if (i != domplat.end()) { -		return i->second; -	} -	throw UnknownDomain(_env->getServerName()); -} - -void -CgiApplicationEngine::loadEngineSection(const xmlpp::Element * e) const -{ -	domplat.push_back(DomainPlatforms::value_type(e->get_attribute_value("name"), e->get_attribute_value("platform"))); -} - - diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index e837b9d..25d3b93 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -36,7 +36,6 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink  		void process() const;  		const Environment * env() const;  		SessionPtr session() const; -		virtual Glib::ustring resolveCurrentConfig() const;  		void addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr) const;  		void addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr) const;  		const CgiEnvironment * _env; @@ -44,10 +43,6 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink  	private:  		mutable boost::posix_time::ptime startTime;  		mutable boost::posix_time::ptime endTime; -		typedef std::pair<Glib::ustring, Glib::ustring> DomainPlatform; -		typedef std::list<DomainPlatform> DomainPlatforms; -		mutable DomainPlatforms domplat; -		bool checkDomain(const DomainPlatforms::value_type & i) const;  		void loadEngineSection(const xmlpp::Element *) const;  		SessionContainerPtr sessionsContainer;  		// Helpers diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp index 579e3f4..3664e9f 100644 --- a/project2/cgi/cgiCommon.cpp +++ b/project2/cgi/cgiCommon.cpp @@ -34,7 +34,7 @@ doExceptionReporting(const E & e, std::ostream & IO)  	IO << "Kaboom!" << std::endl  		<< std::endl  		<< buf << std::endl -		<< e.what() << std::endl; +		<< "what '" << e.what() << "'" << std::endl;  	free(buf);  } diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp index 541e7ae..ae7ad52 100644 --- a/project2/cgi/cgiEnvironment.cpp +++ b/project2/cgi/cgiEnvironment.cpp @@ -1,9 +1,11 @@  #include <pch.hpp> +#include <boost/version.hpp>  #include "cgiEnvironment.h"  #include "appEngine.h"  #include "exceptions.h"  #include <map>  #include <cgicc/Cgicc.h> +#include <glibmm/regex.h>  std::vector<std::string>  makeVector(const boost::filesystem::path & y) @@ -22,53 +24,56 @@ makeVector(const boost::filesystem::path & y)  }  CgiEnvironment::CgiEnvironment(cgicc::Cgicc * c) : -	Environment(0, NULL),  	cgicc::CgiEnvironment(c->getEnvironment()),  	elems(makeVector(boost::filesystem::path(getRedirectURL()))), -	cgi(c) +	cgi(c), +	cgiOptions("Project2 CGI options"), +	hpi(new HostnamePlatformIdentifier())  { -} - -CgiEnvironment::~CgiEnvironment() -{ -} - -boost::program_options::options_description -CgiEnvironment::addOptions(boost::program_options::positional_options_description &) -{ -	boost::program_options::options_description cgi("Project2 CGI options"); -	cgi.add_options() -		("defaultpresenter", boost::program_options::value(&defaultPresenter)->default_value("xml"), +	cgiOptions +		("cgi.defaultPresenter", Options::value(&defaultPresenter, "xml"),  		 "The default engine for formatting presentations") -		("defaultpresent", boost::program_options::value(&defaultPresent)->default_value("index"), +		("cgi.defaultPresent", Options::value(&defaultPresent, "index"),  		 "The present script to use when no other is specified") -		("presentroot", boost::program_options::value(&presentRoot)->default_value("present"), +		("cgi.presentRoot", Options::value(&presentRoot, "present"),  		 "The folder in which to find presentation scripts") -		("requestroot", boost::program_options::value(&requestRoot)->default_value("request"), +		("cgi.requestRoot", Options::value(&requestRoot, "request"),  		 "The folder in which to find request scripts") -		("errorpresentroot", boost::program_options::value(&errorPresentRoot)->default_value("error"), +		("cgi.errorPresentRoot", Options::value(&errorPresentRoot, "error"),  		 "The folder in which to find presentation scripts for error handling") -		("errorcontenttype", boost::program_options::value(&errorContentType)->default_value("text/xml"), +		("cgi.errorContentType", Options::value(&errorContentType, "text/xml"),  		 "The Content-Type to use in HTTP headers in event of an error") -		("errortransformstyle", boost::program_options::value(&errorTransformStyle), +		("cgi.errorTransformStyle", Options::value(&errorTransformStyle),  		 "The xml-stylesheet to specify in the data document in event of an error") -		("notfoundpresent", boost::program_options::value(¬FoundPresent), +		("cgi.notFoundPresent", Options::value(¬FoundPresent),  		 "The present script to use when the requested script does not exist") -		("onerrorpresent", boost::program_options::value(&onErrorPresent), +		("cgi.onErrorPresent", Options::value(&onErrorPresent),  		 "The present script to use when the requested script (or child) fails") -		("dumpdatadoc", boost::program_options::value(&dumpdatadoc), +		("cgi.dumpDataDoc", Options::value(&dumpdatadoc),  		 "Write a copy of the data document before sending it to the web server") -		("sessionModule", boost::program_options::value(&sessionModule)->default_value("xml"), +		("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")  		; -	return cgi;  } -void -CgiEnvironment::postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &) +const Options & +CgiEnvironment::engineOptions() const { +	return cgiOptions; +} + +CgiEnvironment::~CgiEnvironment() +{ +} + +const Glib::ustring & +CgiEnvironment::platform() const  { +	return hpi->derivedPlatform();  } +  Glib::ustring  CgiEnvironment::getParamUri(unsigned int p) const  { @@ -88,3 +93,38 @@ CgiEnvironment::getParamQuery(const std::string & p) const  	return (*cgi)(p);  } +HostnamePlatformIdentifier::HostnamePlatformIdentifier() : +	platform(NULL) +{ +} + +HostnamePlatformIdentifier::~HostnamePlatformIdentifier() +{ +	reset(); +} + +const Glib::ustring & +HostnamePlatformIdentifier::derivedPlatform() const +{ +	if (platform) { +		return *platform; +	} +	throw NoSuchPlatform(Environment::getCurrent()->getServerName()); +} + +void +HostnamePlatformIdentifier::reset() const +{ +	if (platform) { +		delete platform; +	} +} + +void +HostnamePlatformIdentifier::consume(const Glib::ustring & p, const Glib::ustring & r) const +{ +	if (!platform && Glib::Regex::create(r, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL)->match(Environment::getCurrent()->getServerName())) { +		platform = new Glib::ustring(p); +	} +} + diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h index fe99f5e..654f772 100644 --- a/project2/cgi/cgiEnvironment.h +++ b/project2/cgi/cgiEnvironment.h @@ -10,6 +10,17 @@ namespace cgicc {  	class Cgicc;  } +class HostnamePlatformIdentifier : public Options::Target { +	public: +		HostnamePlatformIdentifier(); +		virtual ~HostnamePlatformIdentifier(); +		void reset() const; +		void consume(const Glib::ustring &, const Glib::ustring &) const; +		const Glib::ustring & derivedPlatform() const; +	private: +		mutable Glib::ustring * platform; +}; +  class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {  	public:  		CgiEnvironment(cgicc::Cgicc *); @@ -24,8 +35,11 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment {  		const cgicc::Cgicc * const cgi;  	private: -		boost::program_options::options_description addOptions(boost::program_options::positional_options_description &); -		void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &); +		const Options & engineOptions() const; +		const Glib::ustring & platform() const; +		Options cgiOptions; +		boost::intrusive_ptr<HostnamePlatformIdentifier> hpi; +  	public:  		std::string dumpdatadoc;  		Glib::ustring errorContentType; diff --git a/project2/cgi/cgiOutputOptions.cpp b/project2/cgi/cgiOutputOptions.cpp index eb07b25..add1671 100644 --- a/project2/cgi/cgiOutputOptions.cpp +++ b/project2/cgi/cgiOutputOptions.cpp @@ -20,13 +20,13 @@ OutputOptions::OutputOptions(const xmlpp::Element * p) :  OutputOptionsLoader::OutputOptionsLoader() :  	opts("CGI default output options")  { -	opts.add_options() -		("cgi.output.core", po::value(&OutputOptions::core)->default_value(true), "Core messages") -		("cgi.output.session", po::value(&OutputOptions::core)->default_value(true), "Session values") -		("cgi.output.timing", po::value(&OutputOptions::core)->default_value(true), "Timing") -		("cgi.output.environment", po::value(&OutputOptions::core)->default_value(true), "Environment") -		("cgi.output.url", po::value(&OutputOptions::core)->default_value(true), "URL breakdown") -		("cgi.output.parameters", po::value(&OutputOptions::core)->default_value(true), "Parameters") +	opts +		("cgi.output.core", Options::value(&OutputOptions::core, true), "Core messages") +		("cgi.output.session", Options::value(&OutputOptions::core, true), "Session values") +		("cgi.output.timing", Options::value(&OutputOptions::core, true), "Timing") +		("cgi.output.environment", Options::value(&OutputOptions::core, true), "Environment") +		("cgi.output.url", Options::value(&OutputOptions::core, true), "URL breakdown") +		("cgi.output.parameters", Options::value(&OutputOptions::core, true), "Parameters")  		;  } @@ -35,8 +35,8 @@ OutputOptionsLoader::createFrom(const xmlpp::Element * e) const {  	return new OutputOptions(e);  } -po::options_description * -OutputOptionsLoader::options() +const Options * +OutputOptionsLoader::options() const  {  	return &opts;  } diff --git a/project2/cgi/cgiOutputOptions.h b/project2/cgi/cgiOutputOptions.h index 540764e..a1ff62d 100644 --- a/project2/cgi/cgiOutputOptions.h +++ b/project2/cgi/cgiOutputOptions.h @@ -2,7 +2,7 @@  #define OUTPUTOPTIONS_H  #include "intrusivePtrBase.h" -#include <boost/program_options.hpp> +#include "options.h"  #include "variables.h"  namespace xmlpp { @@ -32,15 +32,14 @@ class OutputOptions : public IntrusivePtrBase {  };  typedef boost::intrusive_ptr<OutputOptions> OutputOptionsPtr; -namespace po = boost::program_options;  class OutputOptionsLoader : public ComponentLoader {  	public:  		OutputOptionsLoader();  		OutputOptionsPtr createFrom(const xmlpp::Element * e) const; -		po::options_description * options(); +		const Options * options() const;  	private: -		po::options_description opts; +		Options opts;  };  #endif diff --git a/project2/cgi/cgiStageFail.cpp b/project2/cgi/cgiStageFail.cpp index 97ac22a..87aba66 100644 --- a/project2/cgi/cgiStageFail.cpp +++ b/project2/cgi/cgiStageFail.cpp @@ -1,4 +1,5 @@  #include <pch.hpp> +#include <boost/lexical_cast.hpp>  #include "cgiAppEngine.h"  #include "cgiEnvironment.h"  #include "cgiHttpHeader.h" diff --git a/project2/cgi/pch.hpp b/project2/cgi/pch.hpp index b3c7108..ff0b175 100644 --- a/project2/cgi/pch.hpp +++ b/project2/cgi/pch.hpp @@ -13,7 +13,7 @@  #include "xmlObjectLoader.h"  #include <boost/bind.hpp>  #include <boost/foreach.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include <cgicc/CgiEnvironment.h>  #include <cgicc/Cgicc.h>  #include <cgicc/HTTPContentHeader.h> diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp index 438e1b0..c2e8d4e 100644 --- a/project2/cgi/testCgi.cpp +++ b/project2/cgi/testCgi.cpp @@ -1,70 +1,71 @@  #include <iostream> -#include <boost/program_options.hpp> -#include <boost/filesystem/convenience.hpp> +#include <boost/bind.hpp> +#include <map> +#include "options.h" +#include "safeMapFind.h"  #include "cgiCommon.h" +#include "../files/optionsSource.h" -namespace po = boost::program_options; - +#define TESTOPT(name, def, desc) \ +				(name, Options::value(optStore.insert(OptStore::value_type(name, new std::string())).first->second, def), desc)  class TestInput : public cgicc::CgiInput {  	public: -		TestInput(int argc, char ** argv) +		typedef std::string * StrPtr; +		typedef std::map<std::string, StrPtr> OptStore; +		OptStore optStore; +		TestInput() : +			opts("Project2 CGI test options")  		{ -			po::options_description test("Project2 CGI test options"); -			test.add_options() -				("help,h", "Print usage and exit") -				("SERVER_NAME", "FQDN of web service") -				("SERVER_SOFTWARE", po::value<std::string>()->default_value("Apache"), "") -				("GATEWAY_INTERFACE", po::value<std::string>()->default_value("CGI/1.1"), "") -				("SERVER_PROTOCOL", po::value<std::string>()->default_value("HTTP/1.1"), "") -				("SERVER_PORT", po::value<std::string>()->default_value("80"), "") -				("REQUEST_METHOD", po::value<std::string>()->default_value("GET"), "") -				("PATH_INFO", "") -				("PATH_TRANSLATED", "") -				("SCRIPT_NAME", po::value<std::string>()->default_value("p2fcgi"), "") -				("QUERY_STRING", "") -				("REMOTE_HOST", "") -				("REMOTE_ADDR", "") -				("AUTH_TYPE", "") -				("REMOTE_USER", "") -				("REMOTE_IDENT", "") -				("CONTENT_TYPE", "") -				("CONTENT_LENGTH", "") -				("HTTP_ACCEPT", po::value<std::string>()->default_value("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"), "") -				("HTTP_USER_AGENT", po::value<std::string>()->default_value("Mozilla/5.0"), "") -				("REDIRECT_REQUEST", "") -				("REDIRECT_URL", "") -				("REDIRECT_STATUS", "") -				("HTTP_REFERER", "") -				("HTTP_COOKIE", "") -				("HTTPS", po::value<std::string>()->default_value("No"), "") +			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?")  				; -			po::parsed_options parsed = po::command_line_parser(argc, argv).options(test).allow_unregistered().run(); -			po::store(parsed, settings); -			if (boost::filesystem::exists("testCgi.settings")) { -				std::ifstream f("testCgi.settings"); -				po::store(po::parse_config_file(f, test, true), settings); -			} -			po::notify(settings); -			if (settings.count("help")) { -				std::cout << test; -				exit(1); -			} +			FileOptions fo(".testCgi.settings"); +			opts.reset(); +			fo.loadInto(boost::bind(&Options::consume, &opts, _1, _2, _3)); +		} + +		const Options * options() const { +			return &opts;  		} -		virtual std::string getenv(const char *varName) + +		virtual std::string getenv(const char * varName)  		{ -			if (settings.count(varName)) { -				return settings[varName].as<std::string>(); -			} -			return ""; +			StrPtr def(new std::string()); +			return *defaultMapFind(optStore, varName, def);  		} +  	private: -		po::variables_map settings; +		Options opts;  };  int -main(int argc, char ** argv) +main(int, char **)  { -	TestInput ti(argc, argv); +	TestInput ti;  	cgiServe(&ti, std::cout);  } diff --git a/project2/common/Jamfile.jam b/project2/common/Jamfile.jam index f08a2ff..4964ea1 100644 --- a/project2/common/Jamfile.jam +++ b/project2/common/Jamfile.jam @@ -5,7 +5,6 @@ lib dl : : <name>dl ;  lib boost_system : : <name>boost_system ;  lib boost_filesystem : : <name>boost_filesystem ;  lib boost_date_time : : <name>boost_date_time ; -lib boost_program_options : : <name>boost_program_options ;  cpp-pch pch : pch.hpp :  	<include>../../libmisc @@ -24,12 +23,10 @@ lib p2common :  	<library>boost_system  	<library>boost_filesystem  	<library>boost_date_time -	<library>boost_program_options  	<library>../uuid//p2uuid  	: :  	<include>.  	<include>../../libmisc  	<library>boost_system -	<library>boost_program_options  	; diff --git a/project2/common/appEngine.cpp b/project2/common/appEngine.cpp index 245f4e5..db44a94 100644 --- a/project2/common/appEngine.cpp +++ b/project2/common/appEngine.cpp @@ -7,8 +7,7 @@  ApplicationEngine * ApplicationEngine::currentEngine = NULL; -ApplicationEngine::ApplicationEngine(const Glib::ustring & engineKeys) : -	Configuration(engineKeys) +ApplicationEngine::ApplicationEngine()  {  	if (currentEngine) {  		throw std::runtime_error("One application at a time, please"); diff --git a/project2/common/appEngine.h b/project2/common/appEngine.h index 85e7229..6de21e1 100644 --- a/project2/common/appEngine.h +++ b/project2/common/appEngine.h @@ -3,11 +3,10 @@  #include "environment.h"  #include "session.h" -#include "config.h"  class MultiRowSetPresenter; -class ApplicationEngine : public Configuration { +class ApplicationEngine {  	public:  		class Message : public IntrusivePtrBase {  			public: @@ -19,7 +18,7 @@ class ApplicationEngine : public Configuration {  		typedef boost::intrusive_ptr<Message> MessagePtr;  		typedef std::list<MessagePtr> Messages; -		ApplicationEngine(const Glib::ustring & engineKeys); +		ApplicationEngine();  		virtual ~ApplicationEngine() = 0;  		void logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m); diff --git a/project2/common/config.cpp b/project2/common/config.cpp deleted file mode 100644 index cb316e5..0000000 --- a/project2/common/config.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include <pch.hpp> -#include "config.h" -#include "safeMapFind.h" -#include "exceptions.h" -#include <boost/filesystem/operations.hpp> -#include <boost/foreach.hpp> -#include "xmlScriptParser.h" - -SimpleMessageException(NoSuchPlatform); -SimpleMessageException(NoSuchConfigurationValue); - -Configuration::Configuration(const Glib::ustring & ek) : -	loaded(false), -	engineKeys(ek) -{ -} - -void -Configuration::load() const -{ -	if (loaded) { -		return; -	} -	loaded = true; -	if (!boost::filesystem::exists("config.xml")) { -		return; -	} -	XmlScriptParser configxml("config.xml", true); -	xmlpp::NodeSet ps(configxml.get_document()->get_root_node()->find("platform")); -	BOOST_FOREACH(const xmlpp::Node * p, ps) { -		const xmlpp::Element * pe = dynamic_cast<const xmlpp::Element *>(p); -		if (pe) { -			platforms[pe->get_attribute_value("name")] = new Platform(pe); -		} -	} -	xmlpp::NodeSet eks(configxml.get_document()->get_root_node()->find(engineKeys)); -	BOOST_FOREACH(const xmlpp::Node * ek, eks) { -		const xmlpp::Element * eke = dynamic_cast<const xmlpp::Element *>(ek); -		if (eke) { -			loadEngineSection(eke); -		} -	} -} - -Configuration::~Configuration() -{ -} - -Configuration::PlatformPtr -Configuration::getCurrentConfig() const -{ -	load(); -	Glib::ustring platformName(resolveCurrentConfig()); -	return safeMapLookup<NoSuchPlatform>(platforms, platformName); -} - -const Glib::ustring & -Configuration::Platform::getValue(const Glib::ustring & key) const -{ -	return safeMapLookup<NoSuchConfigurationValue>(values, key); -} - -Configuration::Platform::Platform(const xmlpp::Element * e) -{ -	xmlpp::NodeSet vs(e->find("variable")); -	BOOST_FOREACH(const xmlpp::Node * v, vs) { -		const xmlpp::Element * ve = dynamic_cast<const xmlpp::Element *>(v); -		if (ve) { -			values.insert(Values::value_type(ve->get_attribute_value("name"), ve->get_attribute_value("value"))); -		} -	} -} - diff --git a/project2/common/config.h b/project2/common/config.h deleted file mode 100644 index 9f6cd5d..0000000 --- a/project2/common/config.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#include <string> -#include <libxml++/nodes/element.h> -#include "intrusivePtrBase.h" -#include <boost/function.hpp> - -class Configuration { -	public: -		class Platform : public virtual IntrusivePtrBase { -			public: -				typedef std::map<Glib::ustring, const Glib::ustring> Values; - -				Platform(const xmlpp::Element * instanceRoot); -				const Glib::ustring & getValue(const Glib::ustring & key) const; - -			private: -				Values values; -		}; -		typedef boost::intrusive_ptr<const Platform> PlatformPtr; - -		typedef std::map<Glib::ustring, PlatformPtr> Platforms; - -		Configuration(const Glib::ustring & engineKeys); -		virtual ~Configuration() = 0; - -		PlatformPtr getCurrentConfig() const; - -	protected: -		virtual Glib::ustring resolveCurrentConfig() const = 0; -		void load() const; - -	private: -		virtual void loadEngineSection(const xmlpp::Element *) const = 0; - -		mutable bool loaded; -		mutable Platforms platforms; -		const Glib::ustring engineKeys; -}; - -#endif -		 diff --git a/project2/common/environment.cpp b/project2/common/environment.cpp index 3106e9a..18d60a0 100644 --- a/project2/common/environment.cpp +++ b/project2/common/environment.cpp @@ -1,5 +1,6 @@  #include <pch.hpp>  #include "environment.h" +#include "optionsSource.h"  #include "loggers.h"  #include "xmlObjectLoader.h"  #include <stdio.h> @@ -8,73 +9,66 @@  #include <boost/foreach.hpp>  #include <boost/bind.hpp> -namespace po = boost::program_options; -  const Environment * Environment::currentEnv(NULL);  int Environment::clLevel(-1);  int Environment::slLevel(-1); -bool Environment::optionsBuilt(false); -po::options_description Environment::allOptions("Project2 options"); -po::positional_options_description Environment::posOptions; -Environment::Environment(int c, char ** v) : -	argc(c), -	argv(v) +Environment::Environment() : +	commonOptions("Project2 Common options")  {  	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(&xmlNamespace, "http://project2.randomdan.homeip.net"), +		 "The namespace to use for Project2 components and responses") +		("common.namespacePrefix", Options::value(&xmlPrefix, "project2"), +		 "The namespace prefix to use for the Project2 namespace") +		("common.sessionTimeOut", Options::value(&sessionTimeOut, 3600), +		 "The time after which idle sessions are forgetten") +		;  } +typedef std::vector<const Options *> AllOptions; +  static -po::variables_map -injectSettingsHelper(int argc, char ** argv, const po::options_description * opts, po::positional_options_description * posOpts) +void +optionsHelper(AllOptions * ao, const Options * options)  { -	po::variables_map settings; -	if (!opts) { -		return settings; -	} -	if (argc > 0 && argv != NULL) { -		if (posOpts) { -			po::store(po::command_line_parser(argc, argv).options(*opts).positional(*posOpts).allow_unregistered().run(), settings); -		} -		else { -			po::store(po::command_line_parser(argc, argv).options(*opts).allow_unregistered().run(), settings); -		} +	if (options) { +		ao->push_back(options);  	} -	po::store(po::parse_environment(*opts, "P2_"), settings); -	if (boost::filesystem::exists(".p2config")) { -		std::ifstream f(".p2config"); -		po::store(po::parse_config_file(f, *opts, true), settings); +} + +static +void +consumeIntoAll(const AllOptions * ao, const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) +{ +	BOOST_FOREACH(const Options * o, *ao) { +		o->consume(n, p, v);  	} -	po::notify(settings); -	return settings;  }  void  Environment::init()  { -	if (!optionsBuilt) { -		po::options_description common("Project2 Common options"); -		common.add_options() -			("sysloglevel,s", po::value(&slLevel)->default_value(-1), -			 "Log to syslog with level <arg> (default OFF)") -			("consoleloglevel,c", po::value(&clLevel)->default_value(LOG_WARNING), -			 "Log to console with level <arg> (default WARNING)") -			("datasourceroot", boost::program_options::value(&datasourceRoot)->default_value("datasources"), -			 "The folder in which to find datasource definitions") -			("xmlnamespace", boost::program_options::value(&xmlNamespace)->default_value("http://project2.randomdan.homeip.net"), -			 "The XML namespace to use for Project2 components and responses") -			("xmlprefix", boost::program_options::value(&xmlPrefix)->default_value("project2"), -			 "The XML namespace prefix to use for the Project2 XML namespace") -			("sessionTimeOut", boost::program_options::value(&sessionTimeOut)->default_value(3600), -			 "The time after which idle sessions are forgetten") -			; -		allOptions.add(common).add(addOptions(posOptions)); -		optionsBuilt = true; +	AllOptions allOptions; +	allOptions.push_back(&commonOptions); +	allOptions.push_back(&engineOptions()); +	LoaderBase::onAllComponents(boost::bind(optionsHelper, &allOptions, boost::bind(&ComponentLoader::options, _1))); + +	BOOST_FOREACH(const AllOptions::value_type & v, allOptions) { +		v->reset(); +	} + +	typedef std::map<std::string, boost::shared_ptr<OptionsSourceLoader> > ConfigParsersMap; +	BOOST_FOREACH(const ConfigParsersMap::value_type & cp, *LoaderBase::objLoaders<OptionsSourceLoader>()) { +		cp.second->create()->loadInto(boost::bind(&consumeIntoAll, &allOptions, _1, _2, _3));  	} -	po::variables_map settings(injectSettingsHelper(argc, argv, &allOptions, &posOptions)); -	postinit(allOptions, settings); -	LoaderBase::onAllComponents(boost::bind( -				injectSettingsHelper, argc, argv, boost::bind(&ComponentLoader::options, _1), (po::positional_options_description*)NULL));  	Logger()->clear();  	if (clLevel >= 0) { diff --git a/project2/common/environment.h b/project2/common/environment.h index 367d800..6185178 100644 --- a/project2/common/environment.h +++ b/project2/common/environment.h @@ -3,13 +3,16 @@  #include <string>  #include <glibmm/ustring.h> -#include <boost/program_options.hpp>  #include <boost/function.hpp>  #include <boost/filesystem/path.hpp> +#include "options.h" +#include "exceptions.h" + +SimpleMessageException(NoSuchPlatform);  class Environment {  	public: -		Environment(int argc, char ** argv); +		Environment();  		virtual ~Environment() = 0;  		void init(); @@ -21,20 +24,15 @@ class Environment {  		virtual std::string getServerName() const = 0;  		virtual std::string getScriptName() const = 0; +		virtual const Glib::ustring & platform() const = 0;  		boost::filesystem::path resolveScript(const std::string & group, const std::string & name) const;  	private: -		static const Environment * currentEnv; +		Options commonOptions; +		virtual const Options & engineOptions() const = 0; -		virtual boost::program_options::options_description addOptions(boost::program_options::positional_options_description &) = 0; -		virtual void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &) = 0; -		int argc; -		char ** argv; - -		static bool optionsBuilt; -		static boost::program_options::options_description allOptions; -		static boost::program_options::positional_options_description posOptions; +		static const Environment * currentEnv;  		static int clLevel;  		static int slLevel; diff --git a/project2/common/memoryCache.cpp b/project2/common/memoryCache.cpp index 34d2cf9..5942cb8 100644 --- a/project2/common/memoryCache.cpp +++ b/project2/common/memoryCache.cpp @@ -2,7 +2,7 @@  #include "logger.h"  #include "cache.h"  #include <boost/foreach.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include "rowSet.h"  #include "presenter.h"  #include "safeMapFind.h" @@ -145,19 +145,18 @@ class MemoryCache : public Cache {  time_t MemoryCache::CacheLife;  MemoryCache::CacheStore MemoryCache::Store; -namespace po = boost::program_options;  class CustomMemoryCacheLoader : public ElementLoaderImpl<MemoryCache> {  	public:  		CustomMemoryCacheLoader() :  			opts("Memory Cache options")  		{ -			opts.add_options() -				("cache.memory.life", po::value(&MemoryCache::CacheLife)->default_value(3600), +			opts +				("cache.memory.life", Options::value(&MemoryCache::CacheLife, 3600),  				 "The age of cache entries after which they are removed (seconds)")  				;  		} -		po::options_description * options() { +		const Options * options() const {  			return &opts;  		} @@ -169,7 +168,7 @@ class CustomMemoryCacheLoader : public ElementLoaderImpl<MemoryCache> {  		}  	private: -		po::options_description opts; +		Options opts;  };  DECLARE_CUSTOM_LOADER("memorycache", CustomMemoryCacheLoader); diff --git a/project2/common/options.cpp b/project2/common/options.cpp new file mode 100644 index 0000000..a99c78e --- /dev/null +++ b/project2/common/options.cpp @@ -0,0 +1,110 @@ +#include <pch.hpp> +#include "options.h" +#include "environment.h" +#include <boost/foreach.hpp> + +class NamedOption : public Options::Option { +	public: +		NamedOption(Glib::ustring const & n, Options::TargetPtr t, Glib::ustring const & d) : +			name(n), +			target(t), +			desc(d) +		{ +		} +		void consume(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const { +			if (n == name) { +				target->consume(p, v); +			} +		} +		void reset() const { +			target->reset(); +		} + +		const Glib::ustring name; +		const Options::TargetPtr target; +		const Glib::ustring desc; +}; + +class OptionAlias : public Options::Option { +	public: +		OptionAlias(const Glib::ustring & a, Options::TargetPtr t) : +			alias(a), +			target(t) +		{ +		} +		void consume(const Glib::ustring & a, const Glib::ustring & p, const Glib::ustring & v) const { +			if (a == alias) { +				target->consume(p, v); +			} +		} +		void reset() const { +			target->reset(); +		} +		const Glib::ustring alias; +		const Options::TargetPtr target; +}; + +Options::Options(Glib::ustring const&) +{ +} + +Options & +Options::operator()(const Glib::ustring & n, TargetPtr t, const Glib::ustring & d) +{ +	options.push_back(new NamedOption(n, t, d)); +	return *this; +} + +Options & +Options::operator()(const Glib::ustring & a) +{ +	for (OptionList::const_reverse_iterator i = options.rbegin(); i != options.rend(); i++) { +		if (const NamedOption * no = dynamic_cast<const NamedOption *>(i->get())) { +			options.push_back(new OptionAlias(a, no->target)); +			break; +		} +	} +	return *this; +} + +Options & +Options::operator()(OptionPtr o) +{ +	options.push_back(o); +	return *this; +} + +void +Options::reset() const +{ +	BOOST_FOREACH(const OptionPtr & o, options) { +		o->reset(); +	} +} + +void +Options::consume(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const +{ +	BOOST_FOREACH(const OptionPtr & o, options) { +		o->consume(n, p, v); +	} +} + +Options::InstanceTarget::InstanceTarget() : +	ts(Default) +{ +} + +void +Options::InstanceTarget::consume(const Glib::ustring & p, const Glib::ustring & v) const +{ +	if (ts != Platform && p.empty()) { +		assign(v); +		ts = Global; +	} +	else if (!p.empty() && p == Environment::getCurrent()->platform()) { +		assign(v); +		ts = Platform; +	} +} + diff --git a/project2/common/options.h b/project2/common/options.h new file mode 100644 index 0000000..77c71b5 --- /dev/null +++ b/project2/common/options.h @@ -0,0 +1,110 @@ +#ifndef OPTIONS_H +#define OPTIONS_H + +#include <glibmm/ustring.h> +#include <intrusivePtrBase.h> +#include <vector> +#include <list> +#include <boost/lexical_cast.hpp> + +class Options { +	public: +		class Target; +		template <typename T> class TypedTarget; + +		enum TargetState { Default = 1, Global = 2, Platform = 3 }; +		class Target : public IntrusivePtrBase { +			public: +				virtual void reset() const = 0; +				virtual void consume(const Glib::ustring & platform, const Glib::ustring & value) const = 0; +		}; +		typedef boost::intrusive_ptr<Target> TargetPtr; + +		class InstanceTarget : public Target { +			public: +				InstanceTarget(); +				void consume(const Glib::ustring & platform, const Glib::ustring & value) const; +			protected: +				virtual void assign(const Glib::ustring & value) const = 0; +				mutable TargetState ts; +		}; + +		template <typename T> class TypedTarget : public InstanceTarget { +			public: +				TypedTarget(T * t) : +					target(t) { +				} +				void reset() const { +					ts = Default; +					*target = T(); +				} +				void assign(const Glib::ustring & value) const { +					*target = boost::lexical_cast<T>(value); +				} +			protected: +				T * target; +		}; + +		template <typename T> class TypedTarget<std::vector<T> > : public InstanceTarget { +			public: +				typedef std::vector<T> VofT; +				TypedTarget(VofT * t) : +					target(t) { +				} +				void reset() const { +					ts = Default; +					target->clear(); +				} +				void assign(const Glib::ustring & value) const { +					target->push_back(boost::lexical_cast<T>(value)); +				} +			protected: +				VofT * target; +		}; + +		template <typename T> class DefaultTypedTarget : public TypedTarget<T> { +			public: +				DefaultTypedTarget(T * t, const T & d) : +					TypedTarget<T>(t), +					defValue(d) { +				} +				void reset() const { +					InstanceTarget::ts = Default; +					*TypedTarget<T>::target = defValue; +				} +			private: +				T defValue; +		}; + +		class Option : public IntrusivePtrBase { +			public: +				virtual void reset() const = 0; +				virtual void consume(const Glib::ustring & name, const Glib::ustring & platform, const Glib::ustring & value) const = 0; +		}; +		typedef boost::intrusive_ptr<Option> OptionPtr; + +		Options(const Glib::ustring & name); + +		Options & operator()(const Glib::ustring & optionName, TargetPtr target, const Glib::ustring & description); +		Options & operator()(const Glib::ustring & optionName); +		Options & operator()(OptionPtr); +		template <typename T> +		static +		TargetPtr value(T * t) { +			return new TypedTarget<T>(t); +		} +		template <typename T, typename D> +		static +		TargetPtr value(T * t, const D & d) { +			return new DefaultTypedTarget<T>(t, d); +		} + +		void reset() const; +		void consume(const Glib::ustring & name, const Glib::ustring & platform, const Glib::ustring & value) const; +	private: +		typedef std::list<OptionPtr> OptionList; +		OptionList options; +}; + +#endif + diff --git a/project2/common/optionsSource.h b/project2/common/optionsSource.h new file mode 100644 index 0000000..73335d8 --- /dev/null +++ b/project2/common/optionsSource.h @@ -0,0 +1,35 @@ +#ifndef OPTIONSSOURCE_H +#define OPTIONSSOURCE_H + +#include <boost/function.hpp> +#include <glibmm/ustring.h> +#include <intrusivePtrBase.h> +#include "xmlObjectLoader.h" + +typedef boost::function3<void, const Glib::ustring &, const Glib::ustring &, const Glib::ustring &> ConfigConsumer; + +/// Base class of things that load options +class OptionsSource : public IntrusivePtrBase { +	public: +		virtual void loadInto(const ConfigConsumer &) const = 0; +}; +typedef boost::intrusive_ptr<OptionsSource> OptionsSourcePtr; + +/// Base class to implement presenter modules +class OptionsSourceLoader : public ComponentLoader { +	public: +		virtual OptionsSourcePtr create() const = 0; +}; + +/// Helper implemention for specific presenters +template <class OptionsSourceType> +class OptionsSourceLoaderImpl : public OptionsSourceLoader { +	public: +		virtual OptionsSourcePtr create() const +		{ +			return new OptionsSourceType(); +		} +}; + +#endif + diff --git a/project2/common/pch.hpp b/project2/common/pch.hpp index 708b437..536dc5a 100644 --- a/project2/common/pch.hpp +++ b/project2/common/pch.hpp @@ -8,7 +8,7 @@  #include <boost/foreach.hpp>  #include <boost/function.hpp>  #include <boost/intrusive_ptr.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include <boost/shared_ptr.hpp>  #include <boost/variant.hpp>  #include <glibmm/ustring.h> diff --git a/project2/common/variables-modconfig.cpp b/project2/common/variables-modconfig.cpp index c9a6b2c..c44daf2 100644 --- a/project2/common/variables-modconfig.cpp +++ b/project2/common/variables-modconfig.cpp @@ -2,8 +2,14 @@  #include "variables.h"  #include "xmlObjectLoader.h"  #include "xmlStorage.h" +#include <boost/algorithm/string/predicate.hpp>  #include "appEngine.h" +typedef std::map<Glib::ustring, Glib::ustring> ConfigOptions; +static ConfigOptions cfgOpts; + +SimpleMessageException(NoSuchConfigurationValue); +  /// Variable implementation to access platform configuration values  class VariableConfig : public VariableImplDyn {  	public: @@ -14,10 +20,56 @@ class VariableConfig : public VariableImplDyn {  		}  		VariableType value() const  		{ -			return ApplicationEngine::getCurrent()->getCurrentConfig()->getValue(name); +			const ConfigOptions::const_iterator i = cfgOpts.find(name); +			if (i != cfgOpts.end()) { +				return i->second; +			} +			if (defaultValue) { +				return defaultValue.get()(); +			} +			throw NoSuchConfigurationValue(name);  		}  	private:  		const Glib::ustring name;  }; -DECLARE_COMPONENT_LOADER("config", VariableConfig, VariableLoader); + +class VariableConfigLoader : public VariableLoaderImpl<VariableConfig> { +	public: +		class AppSettings : public Options::Option { +			public: +				void reset() const { +					cfgOpts.clear(); +				} +				void consume(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const { +					if (boost::algorithm::starts_with(n, "application.")) { +						Glib::ustring k(n.substr(12)); +						const ConfigOptions::iterator i = cfgOpts.find(k); +						if (i == cfgOpts.end()) { +							if (p.empty() || p == Environment::getCurrent()->platform()) { +								cfgOpts.insert(ConfigOptions::value_type(k, v)); +							} +						} +						else { +							if (p == Environment::getCurrent()->platform()) { +								i->second = v; +							} +						} +					} +				} +		}; +		VariableConfigLoader() : +			opts("Variables - ModConfig options") +		{ +			opts(new AppSettings()); +		} + +		const Options * options() const { +			return &opts; +		} + +	private: +		Options opts; +}; + +DECLARE_CUSTOM_COMPONENT_LOADER("config", VariableConfigLoader, VariableConfigLoader, VariableLoader); diff --git a/project2/common/xmlObjectLoader.cpp b/project2/common/xmlObjectLoader.cpp index 81cab9e..d430194 100644 --- a/project2/common/xmlObjectLoader.cpp +++ b/project2/common/xmlObjectLoader.cpp @@ -158,8 +158,8 @@ ComponentLoader::onPeriodic()  {  } -boost::program_options::options_description * -ComponentLoader::options() +const Options * +ComponentLoader::options() const  {  	return NULL;  } diff --git a/project2/common/xmlObjectLoader.h b/project2/common/xmlObjectLoader.h index 0552a9e..3c6fa34 100644 --- a/project2/common/xmlObjectLoader.h +++ b/project2/common/xmlObjectLoader.h @@ -108,7 +108,7 @@ class LoaderBase {  	DECLARE_COMPONENT_LOADER(N, T, ElementLoader)  /// Helper for loading and maintaining Project2 components -namespace boost { namespace program_options { class options_description; } } +class Options;  class ComponentLoader {  	public:  		virtual void onBegin();		// App engine start up (before settings are processed) @@ -116,8 +116,7 @@ class ComponentLoader {  		virtual void onIdle();		// When the app engine goes idle  		virtual void onIteration();	// When the app engine has completed an iteration  		virtual void onPeriodic();	// When the app engine feels like it -		virtual boost::program_options::options_description * -			options();	// Options to be populated from the common config file/env/etc +		virtual const Options * options() const;	// Options to be populated from the common config file/env/etc  };  /// Helper for loading and maintaining Project2 script components  class ElementLoader : public ComponentLoader { diff --git a/project2/console/claOptions.cpp b/project2/console/claOptions.cpp new file mode 100644 index 0000000..135eebc --- /dev/null +++ b/project2/console/claOptions.cpp @@ -0,0 +1,61 @@ +#include <pch.hpp> +#include <boost/foreach.hpp> +#include "../common/optionsSource.h" +#include "consoleEnvironment.h" + +class CommandLineArguments : public OptionsSource { +	public: +		typedef std::list<Glib::ustring> optionList; +		void loadInto(const ConfigConsumer & consume) const { +			int argc = ConsoleEnvironment::argc; +			char ** argv = ConsoleEnvironment::argv; +			bool moreopts = true; +			optionList opts, values; + +			for (int x = 1; x < argc; x += 1) { +				if (moreopts && strcmp(argv[x], "--") == 0) { +					moreopts = false; +				} +				else if (moreopts && strncmp(argv[x], "--", 2) == 0) { +					opts.push_back(argv[x] + 2); +				} +				else if (moreopts && *(argv[x]) == '-') { +					const char * o = argv[x] + 1; +					while (*o) { +						opts.push_back(Glib::ustring(1, *o)); +						o += 1; +					} +				} +				else { +					values.push_back(argv[x]); +				} +			} + +			BOOST_FOREACH (const optionList::value_type & i, opts) { +				Glib::ustring name, plat; +				Glib::ustring::size_type sl = i.find('/'); +				if (sl != (Glib::ustring::size_type)-1) { +					name = i.substr(0, sl); +					plat = i.substr(sl + 1); +				} +				else { +					name = i; +				} +				if (values.size()) { +					consume(name, plat, values.front()); +					values.pop_front(); +				} +				else { +					consume(name, plat, Glib::ustring()); +				} +			} + +			BOOST_FOREACH (const optionList::value_type & i, values) { +				ConsoleEnvironment::todolist.push_back(i.raw()); +			} +		} +}; + +// A... process first :) +DECLARE_COMPONENT_LOADER("A_commandLineArguments", CommandLineArguments, OptionsSourceLoader) + diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index 83ab311..40d369e 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -16,7 +16,6 @@ ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * en  	XmlScriptParser(f, false),  	SourceObject(get_document()->get_root_node()),  	CheckHost(f), -	ApplicationEngine("console/environment"),  	TaskHost(f),  	ViewHost(f),  	_env(env), @@ -77,12 +76,6 @@ ConsoleApplicationEngine::addAppData(const MultiRowSetPresenter *) const  {  } -Glib::ustring -ConsoleApplicationEngine::resolveCurrentConfig() const -{ -	return safeMapLookup<UnknownPlatformAlias>(conplat, _env->getPlatform()); -} -  void  ConsoleApplicationEngine::loadEngineSection(const xmlpp::Element * e) const  { diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h index 681f4a9..f2a0519 100644 --- a/project2/console/consoleAppEngine.h +++ b/project2/console/consoleAppEngine.h @@ -22,7 +22,6 @@ class ConsoleApplicationEngine : public ApplicationEngine, TaskHost, ViewHost {  		void process() const;  		const Environment * env() const;  		SessionPtr session() const; -		virtual Glib::ustring resolveCurrentConfig() const;  		virtual void addAppData(const MultiRowSetPresenter * p) const;  		virtual void addEnvData(const MultiRowSetPresenter * p) const; diff --git a/project2/console/consoleEnvironment.cpp b/project2/console/consoleEnvironment.cpp index fa2748e..6c407b3 100644 --- a/project2/console/consoleEnvironment.cpp +++ b/project2/console/consoleEnvironment.cpp @@ -10,10 +10,12 @@  #include <iostream>  #include <string>  #include <boost/algorithm/string/predicate.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include <boost/bind.hpp> -namespace po = boost::program_options; +int ConsoleEnvironment::argc; +char ** ConsoleEnvironment::argv; +ConsoleEnvironment::ToDoList ConsoleEnvironment::todolist;  template<typename _CharT, typename _Traits>  std::basic_istream<_CharT, _Traits> & @@ -24,53 +26,37 @@ operator>>(std::basic_istream<_CharT, _Traits> & s, ConsoleEnvironment::QueryPar  	return s;  } -ConsoleEnvironment::ConsoleEnvironment(int argc, char ** argv) : -	Environment(argc, argv) -{ -} - -ConsoleEnvironment::~ConsoleEnvironment() -{ -} +class ShowHelpTrigger : public Options::Target { +	public: +		void reset() const { } +		void consume(const Glib::ustring &, const Glib::ustring &) const { +			fprintf(stdout, "Help\n"); +			exit(1); +		} +}; -boost::program_options::options_description -ConsoleEnvironment::addOptions(boost::program_options::positional_options_description & poptions) +ConsoleEnvironment::ConsoleEnvironment(int c, char ** v) : +	consoleOptions("Project2 Console options"), +	help(false)  { -	boost::program_options::options_description console("Project2 Console options"); -	console.add_options() -		//("version,v", "Print version and exit") -		("help,h", "Print usage and exit") -		("syslogident,i", po::value(&scriptname)->default_value(scriptname), "Log to syslog with ident <arg>") -		("platform,p", po::value(&platform), "Platform") -		("queryparam,q", po::value(&queryParams), "Query parameter") -		("uriparam,u", po::value(&uriParams), "URL paramater") -		("file,f", po::value(&todolist), "File to process") +	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::value(&queryParams), "Query parameter")("q") +		("console.uriParam", Options::value(&uriParams), "URL paramater")("u")  		; -	poptions.add("file", -1); -	return console;  } -static -void -showHelpHelper(const boost::program_options::options_description * options) -{ -	if (options) { -		std::cout << *options << std::endl; -	} +const Options & +ConsoleEnvironment::engineOptions() const { +	return consoleOptions;  } -void -ConsoleEnvironment::postinit(const boost::program_options::options_description & options, const boost::program_options::variables_map & settings) +ConsoleEnvironment::~ConsoleEnvironment()  { -	if (settings.count("version")) { -		//show_version(version); -		exit(1); -	} -	if (settings.count("help")) { -		showHelpHelper(&options); -		LoaderBase::onAllComponents(boost::bind(showHelpHelper, boost::bind(&ComponentLoader::options, _1))); -		exit(1); -	}  }  Glib::ustring @@ -94,10 +80,10 @@ ConsoleEnvironment::getParamQuery(const std::string & p) const  	throw ParamNotFound(p);  } -const std::string & -ConsoleEnvironment::getPlatform() const +const Glib::ustring & +ConsoleEnvironment::platform() const  { -	return platform; +	return reqPlatform;  }  std::string diff --git a/project2/console/consoleEnvironment.h b/project2/console/consoleEnvironment.h index 363090d..5f4545c 100644 --- a/project2/console/consoleEnvironment.h +++ b/project2/console/consoleEnvironment.h @@ -20,17 +20,22 @@ class ConsoleEnvironment : public Environment {  		Glib::ustring getParamQuery(const std::string & idx) const;  		std::string getServerName() const;  		std::string getScriptName() const; -		const std::string & getPlatform() const;  		const ToDoList & todoList() const;  	private: -		boost::program_options::options_description addOptions(boost::program_options::positional_options_description &); -		void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &); +		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; -		std::string platform; +		Glib::ustring reqPlatform;  		QueryParams queryParams;  		UriParams uriParams; -		ToDoList todolist; +		static ToDoList todolist;  };  #endif diff --git a/project2/console/pch.hpp b/project2/console/pch.hpp index 39cc465..6e6ee96 100644 --- a/project2/console/pch.hpp +++ b/project2/console/pch.hpp @@ -11,7 +11,7 @@  #include "xmlObjectLoader.h"  #include <boost/bind.hpp>  #include <boost/foreach.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include <iostream>  #include <string> diff --git a/project2/files/Jamfile.jam b/project2/files/Jamfile.jam index ec1e19e..1b34e3c 100644 --- a/project2/files/Jamfile.jam +++ b/project2/files/Jamfile.jam @@ -5,9 +5,7 @@ lib boost_system : : <name>boost_system ;  lib boost_filesystem : : <name>boost_filesystem ;  lib p2files : -	fsRows.cpp -	fileRows.cpp -	streamRows.cpp +	[ glob *.cpp ]  	:  	<include>../libmisc  	<library>libxmlpp diff --git a/project2/files/optionsSource.cpp b/project2/files/optionsSource.cpp new file mode 100644 index 0000000..95c2a57 --- /dev/null +++ b/project2/files/optionsSource.cpp @@ -0,0 +1,62 @@ +#include "optionsSource.h" +#include <glibmm/iochannel.h> +#include <glibmm/fileutils.h> +#include <boost/algorithm/string/trim.hpp> + +FileOptions::FileOptions() : +	file(".p2config") +{ +} + +FileOptions::FileOptions(const Glib::ustring & f) : +	file(f) +{ +} + +void +FileOptions::loadInto(const ConfigConsumer & consume) const { +	try { +		Glib::RefPtr<Glib::IOChannel> cfg = Glib::IOChannel::create_from_file(file, "r"); +		Glib::ustring line; +		Glib::ustring prefix; +		while (cfg->read_line(line) != Glib::IO_STATUS_EOF) { +			switch (line[0]) { +				case '#': +					continue; +				case '[': +					prefix = line.substr(1, line.find(']', 2) - 1); +					boost::algorithm::trim_if(prefix, Glib::Unicode::isspace); +					if (!prefix.empty()) { +						prefix += '.'; +					} +					break; +				default: +					Glib::ustring name, plat; +					Glib::ustring::size_type eq = line.find('='); +					Glib::ustring::size_type sl = line.find('/'); +					if (sl < eq && sl != (Glib::ustring::size_type)-1) { +						name = line.substr(0, sl); +						plat = line.substr(sl + 1, eq - sl - 1); +					} +					else { +						name = line.substr(0, eq); +					} +					boost::algorithm::trim_if(name, Glib::Unicode::isspace); +					if (name.empty()) { +						continue; +					} +					Glib::ustring val = line.substr(eq + 1); +					boost::algorithm::trim_if(plat, Glib::Unicode::isspace); +					boost::algorithm::trim_if(val, Glib::Unicode::isspace); +					consume(prefix + name, plat, val); +					break; +			} +		} +	} +	catch (const Glib::FileError &) { +	} +} + +// Z... process last :) +DECLARE_COMPONENT_LOADER("Z_configfile", FileOptions, OptionsSourceLoader) + diff --git a/project2/files/optionsSource.h b/project2/files/optionsSource.h new file mode 100644 index 0000000..722d7b9 --- /dev/null +++ b/project2/files/optionsSource.h @@ -0,0 +1,17 @@ +#ifndef FILES_OPTIONSSOURCE_H +#define FILES_OPTIONSSOURCE_H + +#include "../common/optionsSource.h" + +class FileOptions : public OptionsSource { +	public: +		FileOptions(); +		FileOptions(const Glib::ustring & file); + +		void loadInto(const ConfigConsumer & consume) const; +	private: +		const Glib::ustring file; +}; + +#endif + diff --git a/project2/json/couchSession.cpp b/project2/json/couchSession.cpp index 1f6c444..8a4436b 100644 --- a/project2/json/couchSession.cpp +++ b/project2/json/couchSession.cpp @@ -11,7 +11,7 @@  #include "json.h"  #include "safeMapFind.h"  #include "conversion.h" -#include <boost/program_options.hpp> +#include "options.h"  class CouchDBFailure : public std::exception { }; @@ -105,19 +105,18 @@ class CouchSessionContainer : public SessionContainer {  std::vector<std::string> CouchSessionContainer::baseUrls;  const Glib::ustring CouchSessionContainer::ExpiryKey("project2:expires"); -namespace po = boost::program_options;  class CustomCouchSessionLoader : public SessionContainerLoaderImpl<CouchSessionContainer> {  	public:  		CustomCouchSessionLoader() :  			opts("Session CouchDB options")  		{ -			opts.add_options() -				("session.couchdb.baseurl", po::value(&CouchSessionContainer::baseUrls)->composing(), +			opts +				("session.couchdb.baseUrl", Options::value(&CouchSessionContainer::baseUrls),  				 "Base URL to store sessions in")  				;  		} -		po::options_description * -		options() +		const Options * +		options() const  		{  			return &opts;  		} @@ -184,7 +183,7 @@ class CustomCouchSessionLoader : public SessionContainerLoaderImpl<CouchSessionC  				return;  			}  		} -		po::options_description opts; +		Options opts;  };  DECLARE_CUSTOM_COMPONENT_LOADER("couchsession", CouchSessionContainer, CustomCouchSessionLoader, SessionContainerLoader); diff --git a/project2/mail/sendmailTask.cpp b/project2/mail/sendmailTask.cpp index 18be222..e2ca703 100644 --- a/project2/mail/sendmailTask.cpp +++ b/project2/mail/sendmailTask.cpp @@ -13,25 +13,24 @@  std::string SendMailTask::defaultMailServer; -namespace po = boost::program_options;  class CustomSendMailTaskLoader : public ElementLoaderImpl<SendMailTask> {  	public:  		CustomSendMailTaskLoader() :  			opts("Send Email Task options")  		{ -			opts.add_options() -				("sendmail.defaultserver", po::value(&SendMailTask::defaultMailServer), +			opts +				("sendmail.defaultServer", Options::value(&SendMailTask::defaultMailServer),  				 "The address of the default mail relay server")  				;  		} -		po::options_description * -		options() +		const Options * +		options() const  		{  			return &opts;  		}  	private: -		po::options_description opts; +		Options opts;  };  DECLARE_CUSTOM_LOADER("sendmail", CustomSendMailTaskLoader); diff --git a/project2/sql/pch.hpp b/project2/sql/pch.hpp index f009f1c..a212245 100644 --- a/project2/sql/pch.hpp +++ b/project2/sql/pch.hpp @@ -23,7 +23,7 @@  #include "xmlObjectLoader.h"  #include <boost/bind.hpp>  #include <boost/foreach.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include <buffer.h>  #include <column.h>  #include <errno.h> diff --git a/project2/sql/sqlCache.cpp b/project2/sql/sqlCache.cpp index 5435dc4..d1ae930 100644 --- a/project2/sql/sqlCache.cpp +++ b/project2/sql/sqlCache.cpp @@ -13,7 +13,7 @@  #include "iHaveParameters.h"  #include "rowSet.h"  #include <boost/foreach.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include <boost/algorithm/string/predicate.hpp>  typedef boost::shared_ptr<DB::SelectCommand> SelectPtr; @@ -257,23 +257,22 @@ std::string SqlCache::DataSource;  std::string SqlCache::HeaderTable;  time_t SqlCache::CacheLife; -namespace po = boost::program_options;  class CustomSqlCacheLoader : public ElementLoaderImpl<SqlCache> {  	public:  		CustomSqlCacheLoader() :  			opts("SQL Cache options")  		{ -			opts.add_options() -				("cache.sql.datasource", po::value(&SqlCache::DataSource), +			opts +				("cache.sql.dataSource", Options::value(&SqlCache::DataSource),  				 "The default datasource to connect to") -				("cache.sql.headertable", po::value(&SqlCache::HeaderTable)->default_value("p2cache"), +				("cache.sql.headerTable", Options::value(&SqlCache::HeaderTable, "p2cache"),  				 "The filename to store the data in") -				("cache.sql.life", po::value(&SqlCache::CacheLife)->default_value(3600), +				("cache.sql.life", Options::value(&SqlCache::CacheLife, 3600),  				 "The age of cache entries after which they are removed (seconds)")  				;  		} -		po::options_description * options() +		const Options * options() const  		{  			return &opts;  		} @@ -293,7 +292,7 @@ class CustomSqlCacheLoader : public ElementLoaderImpl<SqlCache> {  		}  	private: -		po::options_description opts; +		Options opts;  };  DECLARE_CUSTOM_LOADER("sqlcache", CustomSqlCacheLoader); diff --git a/project2/xml/pch.hpp b/project2/xml/pch.hpp index 911d45c..329d949 100644 --- a/project2/xml/pch.hpp +++ b/project2/xml/pch.hpp @@ -15,7 +15,7 @@  #include "variables.h"  #include <boost/filesystem/path.hpp>  #include <boost/foreach.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include <libxml++/document.h>  #include <libxml++/nodes/element.h>  #include <libxml++/nodes/textnode.h> diff --git a/project2/xml/sessionXml.cpp b/project2/xml/sessionXml.cpp index 12235b1..b66a812 100644 --- a/project2/xml/sessionXml.cpp +++ b/project2/xml/sessionXml.cpp @@ -6,16 +6,15 @@  #include <boost/foreach.hpp>  #include <boost/filesystem/convenience.hpp>  #include <boost/lexical_cast.hpp> -#include <boost/program_options.hpp> +#include "options.h" -namespace po = boost::program_options;  class CustomSessionContainerLoaderXml : public SessionContainerLoaderImpl<SessionContainerXml> {  	public:  		CustomSessionContainerLoaderXml() :  			opts("SessionXML options")  		{ -			opts.add_options() -				("session.xml.path", po::value(&SessionContainerXml::xmlDir)->default_value("/tmp/project2.sessions"), +			opts +				("session.xml.path", Options::value(&SessionContainerXml::xmlDir, "/tmp/project2.sessions"),  				 "Path of the folder in which to store XML files for session information")  				;  		} @@ -35,14 +34,14 @@ class CustomSessionContainerLoaderXml : public SessionContainerLoaderImpl<Sessio  				}  			}  		} -		po::options_description * -		options() +		const Options * +		options() const  		{  			return &opts;  		}  	private: -		po::options_description opts; +		Options opts;  };  boost::filesystem::path SessionContainerXml::xmlDir; diff --git a/project2/xml/xmlCache.cpp b/project2/xml/xmlCache.cpp index 64e5f86..8c0dd00 100644 --- a/project2/xml/xmlCache.cpp +++ b/project2/xml/xmlCache.cpp @@ -7,7 +7,7 @@  #include "xmlPresenter.h"  #include <sys/stat.h>  #include <boost/foreach.hpp> -#include <boost/program_options.hpp> +#include "options.h"  #include <boost/filesystem/path.hpp>  #include <boost/filesystem/convenience.hpp>  #include <libxml++/document.h> @@ -84,23 +84,22 @@ boost::filesystem::path XmlCache::Store;  std::string XmlCache::FileName;  time_t XmlCache::CacheLife; -namespace po = boost::program_options;  class CustomXmlCacheLoader : public ElementLoaderImpl<XmlCache> {  	public:  		CustomXmlCacheLoader() :  			opts("XML Cache options")  		{ -			opts.add_options() -				("cache.xml.store", po::value(&XmlCache::Store)->default_value("/tmp/project2.cache"), +			opts +				("cache.xml.store", Options::value(&XmlCache::Store, "/tmp/project2.cache"),  				 "The root folder of the cache storage area") -				("cache.xml.filename", po::value(&XmlCache::FileName)->default_value("cache.xml"), +				("cache.xml.filename", Options::value(&XmlCache::FileName, "cache.xml"),  				 "The filename to store the data in") -				("cache.xml.life", po::value(&XmlCache::CacheLife)->default_value(3600), +				("cache.xml.life", Options::value(&XmlCache::CacheLife, 3600),  				 "The age of cache entries after which they are removed (seconds)")  				;  		} -		po::options_description * options() +		const Options * options() const  		{  			return &opts;  		} @@ -138,7 +137,7 @@ class CustomXmlCacheLoader : public ElementLoaderImpl<XmlCache> {  		}  	private: -		po::options_description opts; +		Options opts;  };  DECLARE_CUSTOM_LOADER("xmlcache", CustomXmlCacheLoader); | 
