summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2011-12-08 16:46:11 +0000
committerrandomdan <randomdan@localhost>2011-12-08 16:46:11 +0000
commit7a558e7a82db05e7768eb61bc77da690b06c6a71 (patch)
tree15b804e78d42233d736351569ec893280d1d7a5f
parentSend the expiry time to CouchDB when deleting old sessions (it's time seems o... (diff)
downloadproject2-7a558e7a82db05e7768eb61bc77da690b06c6a71.tar.bz2
project2-7a558e7a82db05e7768eb61bc77da690b06c6a71.tar.xz
project2-7a558e7a82db05e7768eb61bc77da690b06c6a71.zip
Drop Boost::program_options in favour of our own, pluggable system which integrates application platforms properly
-rw-r--r--project2/cgi/Jamfile.jam3
-rw-r--r--project2/cgi/cgiAppEngine.cpp26
-rw-r--r--project2/cgi/cgiAppEngine.h5
-rw-r--r--project2/cgi/cgiCommon.cpp2
-rw-r--r--project2/cgi/cgiEnvironment.cpp94
-rw-r--r--project2/cgi/cgiEnvironment.h18
-rw-r--r--project2/cgi/cgiOutputOptions.cpp18
-rw-r--r--project2/cgi/cgiOutputOptions.h7
-rw-r--r--project2/cgi/cgiStageFail.cpp1
-rw-r--r--project2/cgi/pch.hpp2
-rw-r--r--project2/cgi/testCgi.cpp105
-rw-r--r--project2/common/Jamfile.jam3
-rw-r--r--project2/common/appEngine.cpp3
-rw-r--r--project2/common/appEngine.h5
-rw-r--r--project2/common/config.cpp73
-rw-r--r--project2/common/config.h43
-rw-r--r--project2/common/environment.cpp92
-rw-r--r--project2/common/environment.h20
-rw-r--r--project2/common/memoryCache.cpp11
-rw-r--r--project2/common/options.cpp110
-rw-r--r--project2/common/options.h110
-rw-r--r--project2/common/optionsSource.h35
-rw-r--r--project2/common/pch.hpp2
-rw-r--r--project2/common/variables-modconfig.cpp56
-rw-r--r--project2/common/xmlObjectLoader.cpp4
-rw-r--r--project2/common/xmlObjectLoader.h5
-rw-r--r--project2/console/claOptions.cpp61
-rw-r--r--project2/console/consoleAppEngine.cpp7
-rw-r--r--project2/console/consoleAppEngine.h1
-rw-r--r--project2/console/consoleEnvironment.cpp74
-rw-r--r--project2/console/consoleEnvironment.h15
-rw-r--r--project2/console/pch.hpp2
-rw-r--r--project2/files/Jamfile.jam4
-rw-r--r--project2/files/optionsSource.cpp62
-rw-r--r--project2/files/optionsSource.h17
-rw-r--r--project2/json/couchSession.cpp13
-rw-r--r--project2/mail/sendmailTask.cpp11
-rw-r--r--project2/sql/pch.hpp2
-rw-r--r--project2/sql/sqlCache.cpp15
-rw-r--r--project2/xml/pch.hpp2
-rw-r--r--project2/xml/sessionXml.cpp13
-rw-r--r--project2/xml/xmlCache.cpp15
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(&notFoundPresent),
+ ("cgi.notFoundPresent", Options::value(&notFoundPresent),
"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);