summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--project2/envproc.cpp71
-rw-r--r--project2/envproc.h4
-rw-r--r--project2/p2webMain.cpp14
-rw-r--r--project2/rdbmsDataSource.cpp4
-rw-r--r--project2/rdbmsDataSource.h2
-rw-r--r--project2/sqlView.cpp33
-rw-r--r--project2/sqlView.h15
-rw-r--r--project2/xmlObjectLoader.h44
8 files changed, 142 insertions, 45 deletions
diff --git a/project2/envproc.cpp b/project2/envproc.cpp
index f280aa0..e5c2a52 100644
--- a/project2/envproc.cpp
+++ b/project2/envproc.cpp
@@ -1,3 +1,4 @@
+#include "xmlObjectLoader.h"
#include "envproc.h"
#include "rdbmsDataSource.h"
#include "sqlView.h"
@@ -16,37 +17,9 @@ EnvironmentProcessor::init()
page = elems.size() > 0 ? elems[0] : "index";
}
-template <class X, class Y>
-void
-collectAll(std::map<std::string, Y> & objs, const xmlpp::Element * node, const Glib::ustring & name)
-{
- if (!node) {
- return;
- }
- if (name == node->get_name()) {
- fprintf(stderr, "Found a %s\n", name.c_str());
- try {
- objs[node->get_attribute_value("name").raw()] = Y(new X(node));
- fprintf(stderr, "Load succeeded\n");
- }
- catch (const std::exception & e) {
- // Assume the XML node is what we thought it was
- fprintf(stderr, "Load failed (%s)\n", e.what());
- }
- catch (...) {
- // Assume the XML node is what we thought it was
- fprintf(stderr, "Load failed\n");
- }
- }
- else {
- BOOST_FOREACH(xmlpp::Node * child, node->get_children()) {
- collectAll<X, Y>(objs, dynamic_cast<const xmlpp::Element *>(child), name);
- }
- }
-}
boost::shared_ptr<xmlpp::Document>
-EnvironmentProcessor::process()
+EnvironmentProcessor::process() const
{
fprintf(stderr, "parsing present .xml\n");
xmlpp::DomParser present("present/" + page + ".xml");
@@ -57,22 +30,39 @@ EnvironmentProcessor::process()
// Collect datasources
fprintf(stderr, "collecting datasources\n");
RdbmsDataSources rdbmsDataSources;
- collectAll<_RdbmsDataSource>(rdbmsDataSources, presentRoot, "rdbmsdatasource");
+ collectAll<_RdbmsDataSource>(rdbmsDataSources, presentRoot, "rdbmsdatasource", &_Project2SourceObject::name);
// Collect views
fprintf(stderr, "collecting sqlviews\n");
SqlViews sqlViews;
- collectAll<_SqlView>(sqlViews, presentRoot, "sqlview");
+ collectAll<_SqlView>(sqlViews, presentRoot, "sqlview", &_SqlView::name);
//
boost::shared_ptr<xmlpp::Document> responseDoc = boost::shared_ptr<xmlpp::Document>(new xmlpp::Document("1.0"));
xmlpp::Element * responseRoot = responseDoc->create_root_node(presentRoot->get_attribute_value("root"));
try {
BOOST_FOREACH(SqlViews::value_type s, sqlViews) {
- s.second->execute(rdbmsDataSources, responseRoot);
+ s.second->execute(rdbmsDataSources, responseRoot, this);
}
}
catch (...) {
}
fprintf(stderr, "done views\n");
+ // These were for debug... but why not pass them on?
+ xmlNewNs(responseRoot->cobj(), BAD_CAST "http://project2.randomdan.homeip.net/", BAD_CAST "project2");
+ responseRoot->add_child("fqdn", "project2")->set_child_text(http_host);
+ responseRoot->add_child("requesturi", "project2")->set_child_text(request_uri);
+ // URL elements
+ xmlpp::Element * uriElems = responseRoot->add_child("uriElems", "project2");
+ BOOST_FOREACH(std::string s, elems) {
+ uriElems->add_child("uriElem", "project2")->set_child_text(s);
+ }
+ // Parameters
+ xmlpp::Element * paramsXml = responseRoot->add_child("params", "project2");
+ BOOST_FOREACH(RegMultiMatch::value_type u, params) {
+ xmlpp::Element * param = paramsXml->add_child("param", "project2");
+ param->add_child_text(u[1]);
+ param->set_attribute("name", u[0]);
+ }
+ // XSLT Style
char * buf;
if (asprintf(&buf, "type=\"text/xsl\" href=\"%s\"",
presentRoot->get_attribute_value("style").c_str()) > 0) {
@@ -84,3 +74,20 @@ EnvironmentProcessor::process()
return responseDoc;
}
+Glib::ustring
+EnvironmentProcessor::getParamUri(const std::string & p) const
+{
+ return elems[atoi(p.c_str())];
+}
+
+Glib::ustring
+EnvironmentProcessor::getParamQuery(const std::string & p) const
+{
+ BOOST_FOREACH(RegMultiMatch::value_type u, params) {
+ if (u[0] == p) {
+ return u[1];
+ }
+ }
+ return Glib::ustring();
+}
+
diff --git a/project2/envproc.h b/project2/envproc.h
index 8d434df..998899a 100644
--- a/project2/envproc.h
+++ b/project2/envproc.h
@@ -17,7 +17,9 @@ class EnvironmentProcessor {
{
init();
}
- virtual boost::shared_ptr<xmlpp::Document> process();
+ virtual boost::shared_ptr<xmlpp::Document> process() const;
+ Glib::ustring getParamUri(const std::string & idx) const;
+ Glib::ustring getParamQuery(const std::string & idx) const;
private:
void init();
diff --git a/project2/p2webMain.cpp b/project2/p2webMain.cpp
index e8cef2c..896af0b 100644
--- a/project2/p2webMain.cpp
+++ b/project2/p2webMain.cpp
@@ -1,16 +1,24 @@
+// Undefine me to run from console for debugging
+//#define FCGI
+
#include <libxml/tree.h>
+#ifdef FCGI
#include <fcgi_stdio.h>
+#endif
#include "envproc.h"
#include <boost/bind.hpp>
+#ifdef FCGI
int
xmlWrite(void * _out, const char * buf, int len)
{
return FCGX_PutStr(buf, len, (FCGX_Stream*)_out);
}
+#endif
int main(void)
{
+#ifdef FCGI
FCGX_Stream *in, *_out, *err;
FCGX_ParamArray envp;
@@ -37,5 +45,11 @@ int main(void)
FCGX_FPrintF(_out, "Unknown exception.\r\n\r\n");
}
}
+#else
+ EnvironmentProcessor ep(getenv);
+
+ boost::shared_ptr<xmlpp::Document> doc = ep.process();
+ xmlDocDump(stdout, doc->cobj());
+#endif
return 0;
}
diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp
index 53a769c..10f6e75 100644
--- a/project2/rdbmsDataSource.cpp
+++ b/project2/rdbmsDataSource.cpp
@@ -1,10 +1,10 @@
#include "rdbmsDataSource.h"
-#include "xml.h"
+#include "xmlObjectLoader.h"
#include <libxml++/nodes/textnode.h>
_RdbmsDataSource::_RdbmsDataSource(const xmlpp::Element * p) :
_Project2SourceObject(p),
- masterDsn(dynamic_cast<const xmlpp::Element&>(*p->get_children("masterdsn").front()).get_child_text()->get_content())
+ masterDsn(xmlChildText(p, "masterdsn"))
{
fprintf(stderr, "Created RDBMS Datasource %s (%s)\n", name.c_str(), masterDsn.c_str());
}
diff --git a/project2/rdbmsDataSource.h b/project2/rdbmsDataSource.h
index 49266e1..1fd9fac 100644
--- a/project2/rdbmsDataSource.h
+++ b/project2/rdbmsDataSource.h
@@ -12,7 +12,7 @@ class _RdbmsDataSource : public _Project2SourceObject {
_RdbmsDataSource(const xmlpp::Element * p);
ODBC::Connection & getReadonly();
ODBC::Connection & getWritable();
- const Glib::ustring masterDsn;
+ const std::string masterDsn;
private:
boost::shared_ptr<ODBC::Connection> database;
};
diff --git a/project2/sqlView.cpp b/project2/sqlView.cpp
index ad88514..7b75a81 100644
--- a/project2/sqlView.cpp
+++ b/project2/sqlView.cpp
@@ -4,31 +4,49 @@
#include "column.h"
#include <string.h>
#include <libxml++/nodes/textnode.h>
+#include "xmlObjectLoader.h"
+#include "envproc.h"
_SqlView::_SqlView(const xmlpp::Element * p) :
_Project2SourceObject(p),
- sql(dynamic_cast<const xmlpp::Element&>(*p->get_children("sql").front()).get_child_text()->get_content()),
+ sql(xmlChildText(p, "sql")),
dataSource(p->get_attribute_value("datasource")),
recordName(p->get_attribute_value("recordname"))
{
+ collectAll<_Parameter>(parameters, p, "param", &_Parameter::bind);
}
-void _SqlView::execute(RdbmsDataSources s, xmlpp::Element * par) const
+_SqlView::_Parameter::_Parameter(const xmlpp::Element * p) :
+ source(p->get_attribute_value("source")),
+ id(p->get_attribute_value("id")),
+ bind(atoi(p->get_attribute_value("bind").c_str()))
{
- typedef std::map<ODBC::String, xmlpp::Element *> Columns;
- fprintf(stderr, "executing\n");
- ODBC::SelectCommand query(s[dataSource]->getReadonly(), sql.c_str());
+}
+
+void _SqlView::execute(RdbmsDataSources s, xmlpp::Element * par, const EnvironmentProcessor * ep) const
+{
+ typedef std::map<std::string, xmlpp::Element *> Columns;
+ ODBC::SelectCommand query(s[dataSource]->getReadonly(), sql);
+ BOOST_FOREACH(Parameters::value_type p, parameters) {
+ if (p.second->source == "uri") {
+ query.bindParamS(p.second->bind, ep->getParamUri(p.second->id));
+ }
+ else if (p.second->source == "query") {
+ query.bindParamS(p.second->bind, ep->getParamQuery(p.second->id));
+ }
+ }
xmlpp::Element * set = par->add_child(name);
while (query.fetch()) {
Columns columns;
unsigned int cols = query.columnCount();
xmlpp::Element * record = set->add_child(recordName);
for (unsigned int col = 0; col < cols; col += 1) {
- const unsigned char * nameattr = query[col].name.c_str();
+ const Glib::ustring & nameattr = query[col].name;
char * name, * attr = NULL;
- switch (sscanf((const char *)nameattr, "%a[^_]_%as", &name, &attr))
+ switch (sscanf(nameattr.c_str(), "%a[^_]_%as", &name, &attr))
{
case 0:
+ fprintf(stderr, "non-sense column name\n");
return; // Make me an exception
break;
case 1:
@@ -76,6 +94,5 @@ void _SqlView::execute(RdbmsDataSources s, xmlpp::Element * par) const
}
*/
}
- fprintf(stderr, "finished\n");
}
diff --git a/project2/sqlView.h b/project2/sqlView.h
index b2e7d86..81f759b 100644
--- a/project2/sqlView.h
+++ b/project2/sqlView.h
@@ -7,13 +7,26 @@
#include "sourceObject.h"
#include "rdbmsDataSource.h"
+class EnvironmentProcessor;
class _SqlView : public _Project2SourceObject {
public:
+ class _Parameter {
+ public:
+ _Parameter(const xmlpp::Element * p);
+ const std::string source;
+ const std::string id;
+ const unsigned int bind;
+ };
+ typedef boost::shared_ptr<_Parameter> Parameter;
+ typedef std::map<unsigned int, Parameter> Parameters;
+
_SqlView(const xmlpp::Element * p);
- void execute(RdbmsDataSources s, xmlpp::Element *) const;
+ void execute(RdbmsDataSources s, xmlpp::Element *, const EnvironmentProcessor *) const;
const Glib::ustring sql;
const Glib::ustring dataSource;
const Glib::ustring recordName;
+ private:
+ Parameters parameters;
};
typedef boost::shared_ptr<_SqlView> SqlView;
typedef std::map<std::string, SqlView> SqlViews;
diff --git a/project2/xmlObjectLoader.h b/project2/xmlObjectLoader.h
new file mode 100644
index 0000000..ecc97fa
--- /dev/null
+++ b/project2/xmlObjectLoader.h
@@ -0,0 +1,44 @@
+#ifndef XMLOBJECTLOADER_H
+#define XMLOBJECTLOADER_H
+
+#include <map>
+#include <string>
+#include <stdio.h>
+#include <libxml++/nodes/element.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/foreach.hpp>
+
+#define xmlChildText(p, t) dynamic_cast<const xmlpp::Element&>(*p->get_children(t).front()).get_child_text()->get_content()
+template <class ObjectType, class ContainerType, class IDType, class ObjectBase>
+void
+collectAll(std::map<IDType, ContainerType> & objs, const xmlpp::Element * node, const Glib::ustring & name,
+ const IDType ObjectBase::*id)
+{
+ if (!node) {
+ return;
+ }
+ if (name == node->get_name()) {
+ fprintf(stderr, "Found a %s\n", name.c_str());
+ try {
+ ContainerType c = ContainerType(new ObjectType(node));
+ objs[(*c).*id] = c;
+ fprintf(stderr, "Load succeeded\n");
+ }
+ catch (const std::exception & e) {
+ // Assume the XML node is what we thought it was
+ fprintf(stderr, "Load failed (%s)\n", e.what());
+ }
+ catch (...) {
+ // Assume the XML node is what we thought it was
+ fprintf(stderr, "Load failed\n");
+ }
+ }
+ else {
+ BOOST_FOREACH(xmlpp::Node * child, node->get_children()) {
+ collectAll<ObjectType, ContainerType>(objs, dynamic_cast<const xmlpp::Element *>(child), name, id);
+ }
+ }
+}
+
+#endif
+