summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project2/Jamfile.jam31
-rw-r--r--project2/rdbmsDataSource.cpp42
-rw-r--r--project2/rdbmsDataSource.h19
-rw-r--r--project2/sql-modODBC.cpp4
-rw-r--r--project2/sql-modPQ.cpp4
-rw-r--r--project2/xmlObjectLoader.cpp78
-rw-r--r--project2/xmlObjectLoader.h68
7 files changed, 127 insertions, 119 deletions
diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam
index caf94fd..5b9799a 100644
--- a/project2/Jamfile.jam
+++ b/project2/Jamfile.jam
@@ -126,28 +126,35 @@ lib p2xmlSession :
<library>p2common
;
-obj rdbmsDataSource :
- rdbmsDataSource.cpp :
- <odbc>yes:<define>WITH_ODBC
- <pq>yes:<define>WITH_PQ
- <odbc>yes:<library>../libodbcpp//odbcpp
- <pq>yes:<library>../libpqpp//pqpp
+explicit object sql-modODBC ;
+obj sql-modODBC :
+ sql-modODBC.cpp :
+ <library>../libodbcpp//odbcpp
<library>libxmlpp
<include>../libmisc
+ : :
+ <library>../libodbcpp//odbcpp
+ ;
+
+explicit object sql-modPQ ;
+obj sql-modPQ :
+ sql-modPQ.cpp :
+ <library>../libpqpp//pqpp
+ <library>libxmlpp
+ <include>../libmisc
+ : :
+ <library>../libpqpp//pqpp
;
lib p2sql :
- [ glob sql*.cpp ] tablepatch.cpp rdbmsDataSource
+ sqlCheck.cpp sqlTask.cpp sqlMergeTask.cpp sqlRows.cpp sqlVariableBinder.cpp tablepatch.cpp rdbmsDataSource.cpp
../libdbpp//dbpp
:
- <odbc>yes:<library>../libodbcpp//odbcpp
- <pq>yes:<library>../libpqpp//pqpp
+ <odbc>yes:<library>sql-modODBC
+ <pq>yes:<library>sql-modPQ
<library>libxmlpp
<library>p2common
<include>../libmisc
- : :
- <odbc>yes:<library>../libodbcpp//odbcpp
- <pq>yes:<library>../libpqpp//pqpp
;
lib p2url :
diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp
index 1b0ab3c..f21c737 100644
--- a/project2/rdbmsDataSource.cpp
+++ b/project2/rdbmsDataSource.cpp
@@ -1,5 +1,4 @@
#include "rdbmsDataSource.h"
-#include "xmlObjectLoader.h"
#include <libxml++/nodes/textnode.h>
#include <sys/utsname.h>
#include "logger.h"
@@ -7,16 +6,6 @@
#include <sqlext.h>
#include <boost/foreach.hpp>
-static const int NOTSET = 0;
-#ifdef WITH_PQ
-#include "../libpqpp/connection.h"
-static const int PQ_TYPEID = 1;
-#endif
-#ifdef WITH_ODBC
-#include "../libodbcpp/connection.h"
-static const int ODBC_TYPEID = 2;
-#endif
-
SimpleMessageException(UnknownConnectionProvider);
/// Specialized ElementLoader for instances of RdbmsDataSource; handles persistent DB connections
@@ -209,41 +198,18 @@ RdbmsDataSource::RdbmsConnection::isExpired() const
return (time(NULL) > lastUsedTime + keepAliveTime);
}
-RdbmsDataSource::ConnectionInfo::ConnectionInfo(const xmlpp::Element * n) :
- typeId(NOTSET)
+RdbmsDataSource::ConnectionInfo::ConnectionInfo(const xmlpp::Element * n)
{
-#if WITH_ODBC
- BOOST_FOREACH(const xmlpp::Node * node, n->find("odbc")) {
- typeId = ODBC_TYPEID;
- dsn = dynamic_cast<const xmlpp::Element *>(node)->get_child_text()->get_content();
- }
-#endif
-#if WITH_PQ
- BOOST_FOREACH(const xmlpp::Node * node, n->find("postgresql")) {
- typeId = PQ_TYPEID;
+ BOOST_FOREACH(const xmlpp::Node * node, n->get_children()) {
+ typeId = LoaderBase::getLoader<ConnectionLoader, UnknownConnectionProvider>(node->get_name());
dsn = dynamic_cast<const xmlpp::Element *>(node)->get_child_text()->get_content();
}
-#endif
- if (typeId == NOTSET || dsn.empty()) {
- throw UnknownConnectionProvider(n->get_path());
- }
}
DB::Connection *
RdbmsDataSource::ConnectionInfo::connect() const
{
-#if WITH_ODBC
- if (typeId == ODBC_TYPEID) {
- return new ODBC::Connection(dsn);
- }
-#endif
-#if WITH_PQ
- if (typeId == PQ_TYPEID) {
- return new PQ::Connection(dsn);
- }
-#endif
- // This should never happen if the object was constructed correctly
- throw UnknownConnectionProvider(__PRETTY_FUNCTION__);
+ return typeId->connect(dsn);
}
bool
diff --git a/project2/rdbmsDataSource.h b/project2/rdbmsDataSource.h
index 857173b..0e175e7 100644
--- a/project2/rdbmsDataSource.h
+++ b/project2/rdbmsDataSource.h
@@ -8,6 +8,23 @@
#include "dataSource.h"
#include "../libdbpp/connection.h"
#include "../libdbpp/error.h"
+#include "xmlObjectLoader.h"
+
+/// Base class to implement DB connection type modules
+class ConnectionLoader : public ComponentLoader {
+ public:
+ virtual DB::Connection * connect(const std::string & dsn) const = 0;
+};
+
+/// Helper implemention for specific DB types
+template <class DBType>
+class ConnectionLoaderImpl : public ConnectionLoader {
+ public:
+ virtual DB::Connection * connect(const std::string & dsn) const
+ {
+ return new DBType(dsn);
+ }
+};
/// Project2 component to provide access to transactional RDBMS data sources
class RdbmsDataSource : public DataSource {
@@ -37,7 +54,7 @@ class RdbmsDataSource : public DataSource {
private:
std::string dsn;
- int typeId;
+ boost::shared_ptr<ConnectionLoader> typeId;
};
typedef boost::shared_ptr<RdbmsConnection> ConnectionPtr;
diff --git a/project2/sql-modODBC.cpp b/project2/sql-modODBC.cpp
new file mode 100644
index 0000000..ca57731
--- /dev/null
+++ b/project2/sql-modODBC.cpp
@@ -0,0 +1,4 @@
+#include "rdbmsDataSource.h"
+#include "../libodbcpp/connection.h"
+typedef ODBC::Connection ODBCConnection;
+DECLARE_COMPONENT_LOADER("odbc", ODBCConnection, ConnectionLoader)
diff --git a/project2/sql-modPQ.cpp b/project2/sql-modPQ.cpp
new file mode 100644
index 0000000..499d8e7
--- /dev/null
+++ b/project2/sql-modPQ.cpp
@@ -0,0 +1,4 @@
+#include "rdbmsDataSource.h"
+#include "../libpqpp/connection.h"
+typedef PQ::Connection PQConnection;
+DECLARE_COMPONENT_LOADER("postgresql", PQConnection, ConnectionLoader)
diff --git a/project2/xmlObjectLoader.cpp b/project2/xmlObjectLoader.cpp
index 9187c82..372081b 100644
--- a/project2/xmlObjectLoader.cpp
+++ b/project2/xmlObjectLoader.cpp
@@ -11,15 +11,6 @@ unsigned int LoaderBase::depth = 0;
std::set<SourceObjectPtr> LoaderBase::loadedObjects;
typedef std::map<std::string, boost::shared_ptr<ElementLoader> > ElementLoaderMap;
-ElementLoaderMap * &
-objLoaders()
-{
- static ElementLoaderMap * _objLoaders = NULL;
- if (!_objLoaders) {
- _objLoaders = new ElementLoaderMap();
- }
- return _objLoaders;
-}
LoaderBase::LoaderBase(bool r) :
recursive(r),
@@ -50,27 +41,21 @@ LoaderBase::collectAll(const xmlpp::Element * node, bool childrenOnly, Unsupport
if (!childrenOnly && node->get_namespace_uri() == ns) {
Glib::ustring name = node->get_name();
unsigned int stored = 0;
- ElementLoaderMap::const_iterator i = objLoaders()->find(name);
- if (i != objLoaders()->end()) {
- SourceObjectPtr o = i->second->go(node);
- created += 1;
- loadedObjects.insert(o);
- BOOST_FOREACH(std::set<boost::intrusive_ptr<Storer> >::value_type s, supportedStorers) {
- if (s->save(o, node)) {
- stored += 1;
- }
- }
- if (stored < 1) {
- if (uh == ErrorOnUnsupported) {
- throw NotSupported(name);
- }
- else if (uh == WarnOnUnsupported) {
- Logger()->messagef(LOG_WARNING, "'%s' unsupported in this location", name.c_str());
- }
+ SourceObjectPtr o = getLoader<ElementLoader, NotSupported>(name)->go(node);
+ created += 1;
+ loadedObjects.insert(o);
+ BOOST_FOREACH(std::set<boost::intrusive_ptr<Storer> >::value_type s, supportedStorers) {
+ if (s->save(o, node)) {
+ stored += 1;
}
}
- else {
- throw NotSupported(name);
+ if (stored < 1) {
+ if (uh == ErrorOnUnsupported) {
+ throw NotSupported(name);
+ }
+ else if (uh == WarnOnUnsupported) {
+ Logger()->messagef(LOG_WARNING, "'%s' unsupported in this location", name.c_str());
+ }
}
}
if (created == 0 && (recursive || childrenOnly)) {
@@ -95,26 +80,9 @@ LoaderBase::collectAll(const CommonObjects * co, const xmlpp::Element * node, bo
}
void
-LoaderBase::newLoader(const std::string & n, ElementLoader * l)
-{
- objLoaders()->insert(ElementLoaderMap::value_type(n, boost::shared_ptr<ElementLoader>(l)));
-}
-
-void
-LoaderBase::removeLoader(const std::string & n)
-{
- ElementLoaderMap * & o = objLoaders();
- o->erase(n);
- if (o->empty()) {
- delete o;
- o = NULL;
- }
-}
-
-void
LoaderBase::onIdle()
{
- BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) {
+ BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders<ElementLoader>()) {
l.second->onIdle();
}
}
@@ -126,7 +94,7 @@ LoaderBase::onIteration()
depth = 0;
loadedObjects.clear();
- BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) {
+ BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders<ElementLoader>()) {
l.second->onIteration();
}
}
@@ -134,16 +102,11 @@ LoaderBase::onIteration()
void
LoaderBase::onPeriodic()
{
- BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders()) {
+ BOOST_FOREACH(ElementLoaderMap::value_type l, *objLoaders<ElementLoader>()) {
l.second->onPeriodic();
}
}
-void
-ElementLoader::onIdle()
-{
-}
-
Glib::ustring
xmlChildText(const xmlpp::Node * p, const Glib::ustring & t)
{
@@ -161,12 +124,17 @@ xmlChildText(const xmlpp::Node * p, const Glib::ustring & t)
}
void
-ElementLoader::onIteration()
+ComponentLoader::onIdle()
+{
+}
+
+void
+ComponentLoader::onIteration()
{
}
void
-ElementLoader::onPeriodic()
+ComponentLoader::onPeriodic()
{
}
diff --git a/project2/xmlObjectLoader.h b/project2/xmlObjectLoader.h
index fb0ac16..e68a390 100644
--- a/project2/xmlObjectLoader.h
+++ b/project2/xmlObjectLoader.h
@@ -4,6 +4,7 @@
#include <set>
#include <string>
#include <boost/intrusive_ptr.hpp>
+#include <boost/shared_ptr.hpp>
#include "intrusivePtrBase.h"
#include "sourceObject.h"
#include "exceptions.h"
@@ -34,8 +35,44 @@ class LoaderBase {
static void onIteration();
static void onPeriodic();
- static void newLoader(const std::string & N, ElementLoader * L);
- static void removeLoader(const std::string & N);
+ template <class T>
+ static std::map<std::string, boost::shared_ptr<T> > * & objLoaders()
+ {
+ static std::map<std::string, boost::shared_ptr<T> > * _objLoaders = NULL;
+ if (!_objLoaders) {
+ _objLoaders = new std::map<std::string, boost::shared_ptr<T> >();
+ }
+ return _objLoaders;
+ }
+
+ template <class T>
+ static void newLoader(const std::string & n, T * l)
+ {
+ objLoaders<T>()->insert(std::pair<std::string, boost::shared_ptr<T> >(n, boost::shared_ptr<T>(l)));
+ }
+
+ template <class T>
+ static void removeLoader(const std::string & n)
+ {
+ std::map<std::string, boost::shared_ptr<T> > * & o = objLoaders<T>();
+ o->erase(n);
+ if (o->empty()) {
+ delete o;
+ o = NULL;
+ }
+ }
+
+ template <class L, class E>
+ static boost::shared_ptr<L> getLoader(const std::string & n)
+ {
+ typename std::map<std::string, boost::shared_ptr<L> >::const_iterator i = objLoaders<L>()->find(n);
+ if (i != objLoaders<L>()->end()) {
+ return i->second;
+ }
+ else {
+ throw E(n);
+ }
+ }
private:
static unsigned int depth;
@@ -47,25 +84,30 @@ class LoaderBase {
const Glib::ustring ns;
};
+#define DECLARE_CUSTOM_COMPONENT_LOADER(N, I, T, B) \
+ static void init_loader_##I() __attribute__ ((constructor(201))); \
+ static void init_loader_##I() { LoaderBase::newLoader<B>(N, new T()); } \
+ static void kill_loader_##I() __attribute__ ((destructor(201))); \
+ static void kill_loader_##I() { LoaderBase::removeLoader<B>(N); }
#define DECLARE_CUSTOM_LOADER(N, T) \
- static void init_loader_##T() __attribute__ ((constructor(201))); \
- static void init_loader_##T() { LoaderBase::newLoader(N, new T()); } \
- static void kill_loader_##T() __attribute__ ((destructor(201))); \
- static void kill_loader_##T() { LoaderBase::removeLoader(N); }
+ DECLARE_CUSTOM_COMPONENT_LOADER(N, T, T, ElementLoader)
+#define DECLARE_COMPONENT_LOADER(N, T, B) \
+ DECLARE_CUSTOM_COMPONENT_LOADER(N, T, B##Impl<T>, B)
#define DECLARE_LOADER(N, T) \
- static void init_loader_##T() __attribute__ ((constructor(201))); \
- static void init_loader_##T() { LoaderBase::newLoader(N, new ElementLoaderImpl<T>()); } \
- static void kill_loader_##T() __attribute__ ((destructor(201))); \
- static void kill_loader_##T() { LoaderBase::removeLoader(N); }
+ DECLARE_COMPONENT_LOADER(N, T, ElementLoader)
-/// Helper for loading and maintaining Project2 script components
-class ElementLoader {
+/// Helper for loading and maintaining Project2 components
+class ComponentLoader {
public:
- virtual SourceObjectPtr go(const xmlpp::Element * xml) const = 0;
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
};
+/// Helper for loading and maintaining Project2 script components
+class ElementLoader : public ComponentLoader {
+ public:
+ virtual SourceObjectPtr go(const xmlpp::Element * xml) const = 0;
+};
/// Helper for loading and maintaining Project2 script components (typed implementation)
template <class X>