diff options
37 files changed, 910 insertions, 86 deletions
| diff --git a/project2/FCgiIO.cpp b/project2/FCgiIO.cpp new file mode 100644 index 0000000..7a3dd09 --- /dev/null +++ b/project2/FCgiIO.cpp @@ -0,0 +1,63 @@ +/* + *  $Id: FCgiIO.cpp,v 1.6 2007/07/02 18:48:19 sebdiaz Exp $ + * + *  Copyright (C) 2002 Steve McAndrewSmith + *  Copyright (C) 2002 - 2004 Stephen F. Booth + *                       2007 Sebastien DIAZ <sebastien.diaz@gmail.com> + *  Part of the GNU cgicc library, http://www.gnu.org/software/cgicc + * + *  This library is free software; you can redistribute it and/or + *  modify it under the terms of the GNU Lesser General Public + *  License as published by the Free Software Foundation; either + *  version 3 of the License, or (at your option) any later version. + * + *  This library is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + *  Lesser General Public License for more details. + * + *  You should have received a copy of the GNU Lesser General Public + *  License along with this library; if not, write to the Free Software + *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA  + */ + +#ifdef __GNUG__ +#  pragma implementation +#endif + +#include <iostream> +#include <stdexcept> +#include <cstdlib> + +#include "FCgiIO.h" + +cgicc::FCgiIO::FCgiIO(FCGX_Request& request) +  : std::ostream(&fOutBuf), +	 fRequest(request),  +	 fOutBuf(request.out),  +	 fErrBuf(request.err),  +	 fErr(&fErrBuf) +{ +  rdbuf(&fOutBuf); +  fErr.rdbuf(&fErrBuf); + +  // Parse environment +  for(char **e = fRequest.envp; *e != NULL; ++e) { +    std::string s(*e); +    std::string::size_type i = s.find('='); +    if(i == std::string::npos) +      throw std::runtime_error("Illegally formed environment"); +    fEnv[s.substr(0, i)] = s.substr(i + 1); +  } +} + +cgicc::FCgiIO::FCgiIO(const FCgiIO& io) +  : CgiInput(io), +    std::ostream(&fOutBuf), +	 fRequest(io.fRequest),  +	 fErr(&fErrBuf),  +	 fEnv(io.fEnv) +{ +  rdbuf(&fOutBuf); +  fErr.rdbuf(&fErrBuf); +} diff --git a/project2/FCgiIO.h b/project2/FCgiIO.h new file mode 100644 index 0000000..a8b67f3 --- /dev/null +++ b/project2/FCgiIO.h @@ -0,0 +1,153 @@ +/* -*-c++-*- */ +/* + *  $Id: FCgiIO.h,v 1.3 2007/07/02 18:48:19 sebdiaz Exp $ + * + *  Copyright (C) 2002 Steve McAndrewSmith + *  Copyright (C) 2002 Stephen F. Booth + *                2007 Sebastien DIAZ <sebastien.diaz@gmail.com> + *  Part of the GNU cgicc library, http://www.gnu.org/software/cgicc + * + *  This library is free software; you can redistribute it and/or + *  modify it under the terms of the GNU Lesser General Public + *  License as published by the Free Software Foundation; either + *  version 3 of the License, or (at your option) any later version. + * + *  This library is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + *  Lesser General Public License for more details. + * + *  You should have received a copy of the GNU Lesser General Public + *  License along with this library; if not, write to the Free Software + *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA* + */ + +#ifndef _FCGIIO_H_ +#define _FCGIIO_H_ 1 + +#ifdef __GNUG__ +#  pragma interface +#endif + +/*! \file FCgiIO.h + * \brief Class that implements input and output through a FastCGI request. + * + * This class provides access to the input byte-stream and environment + * variable interfaces of a FastCGI request.  It is fully compatible with the + * Cgicc input API. + * + * It also provides access to the request's output and error streams, using a + * similar interface. + */ + +#include <ostream> +#include <string> +#include <map> + +#include "fcgio.h" + +#include "cgicc/CgiInput.h" + +namespace cgicc { + +  // ============================================================ +  // Class FCgiIO +  // ============================================================ +   +  /*! \class FCgiIO FCgiIO.h FCgiIO.h +   * \brief Class that implements input and output through a FastCGI request. +   * +   * This class provides access to the input byte-stream and environment +   * variable interfaces of a FastCGI request.  It is fully compatible with the +   * Cgicc input API. +   * +   * It also provides access to the request's output and error streams, using a +   * similar interface. +   */ +  class CGICC_API FCgiIO : public cgicc::CgiInput, public std::ostream +  { +  public: +     +    // ============================================================ +     +    /*! \name Constructor and Destructor */ +    //@{ +     +    /*! +     * \brief Constructor +     * +     * Create a new FCgiIO object +     */ +    FCgiIO(FCGX_Request& request); +     +    /*! +     * \brief Copy constructor +     * +     */ +    FCgiIO(const FCgiIO& io); +     +    /*! +     * \brief Destructor +     * +     * Delete this FCgiIO object +     */ +    virtual inline +    ~FCgiIO() +    {} +    //@} +     +    // ============================================================ +     +    /*! \name Data Sources */ +    //@{ +     +    /*! +     * \brief Read data from the request's input stream. +     * +     * \param data The target buffer +     * \param length The number of characters to read +     * \return The number of characters read +     */ +    virtual inline size_t read(char *data, size_t length) +    { +      return FCGX_GetStr(data, length, fRequest.in); +    } +     +    /*! +     * \brief Query the value of an environment variable stored in the request. +     * +     * \param varName The name of an environment variable +     * \return The value of the requested environment variable, or an empty +     * string if not found. +     */ +    virtual inline std::string getenv(const char *varName) +    { +      return fEnv[varName]; +    } +    //@} +     +    // ============================================================ +     +    /*! \name Data Target Streams */ +    //@{ +     +    /*! +     * \brief Provides access to the error stream. +   */ +    inline std::ostream& err(void) +    { +      return fErr; +    } +    //@} +     +  protected: +    FCGX_Request& 			fRequest; +    fcgi_streambuf 			fOutBuf; +    fcgi_streambuf 			fErrBuf; +    std::ostream 			fErr; +    std::map<std::string, std::string> 	fEnv; +  }; +   +} // namespace cgicc + +#endif /* ! _FCGIIO_H_ */ diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index a8cf8ae..4fdd54c 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -5,6 +5,7 @@ alias libxmlpp : : : :  	<linkflags>"`pkg-config --libs libxml++-2.6`" ;  lib fcgi : : <name>fcgi ; +lib fcgi++ : : <name>fcgi++ ;  lib odbc : : <name>odbc ;  lib boost_regex : : <name>boost_regex ;  lib cgicc : : <name>cgicc ; @@ -19,4 +20,5 @@ exe p2web :  	<library>boost_regex  	<library>odbc  	<library>cgicc +	<library>fcgi++  	<library>fcgi ; diff --git a/project2/appEngine.h b/project2/appEngine.h index cffd44e..d2cff10 100644 --- a/project2/appEngine.h +++ b/project2/appEngine.h @@ -14,6 +14,8 @@ class ApplicationEngine {  		virtual void process() const = 0;  		virtual const Environment * env() const = 0; +		virtual void SessionSet(const Glib::ustring & name, const Glib::ustring & value) const = 0; +		virtual void SessionClear(const Glib::ustring & name) const = 0;  		template <class DataSourceType>  		const DataSourceType * dataSource(const std::string & name) const diff --git a/project2/cgiAppEngine.cpp b/project2/cgiAppEngine.cpp index 860ce51..f1c38d7 100644 --- a/project2/cgiAppEngine.cpp +++ b/project2/cgiAppEngine.cpp @@ -1,17 +1,36 @@  #include "cgiAppEngine.h"  #include <syslog.h>  #include <cgicc/Cgicc.h> +#include <cgicc/HTTPContentHeader.h> +#include "cgiEnvironment.h"  #include <libxml++/parsers/domparser.h>  #include <libxml/xinclude.h>  #include "xmlObjectLoader.h"  #include "rdbmsDataSource.h" +#include "iterate.h"  #include <boost/bind.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/uuid/uuid_io.hpp> +#include "sessionShm.h" +#include <boost/uuid/uuid_generators.hpp> +const std::string SESSIONID = "sessionID"; +typedef boost::uuids::uuid SIDKey; +typedef std::string SValue; -CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e) : +SessionContainer * sessionsContainer = new SessionContainerShm(); + +CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, cgicc::HTTPContentHeader * h) :  	ApplicationEngine(e), -	_env(e) +	_env(e), +	header(h), +	sessionID(boost::uuids::nil_generator()())  { +	BOOST_FOREACH(const cgicc::HTTPCookie c, e->getCookieList()) { +		if (c.getName() == SESSIONID) { +			sessionID = boost::uuids::string_generator()(c.getValue()); +		} +	}  	if (_env->getRequestMethod() == "POST") {  		currentStage = new RequestStage(this, e->elems[0]);  	} @@ -38,6 +57,10 @@ CgiApplicationEngine::process() const  		currentStage = currentStage->run();  		delete prev;  	} +	if (!sessionID.is_nil()) { +		header->setCookie(cgicc::HTTPCookie(SESSIONID, boost::lexical_cast<std::string>(sessionID), "Session ID", +					_env->getServerName().substr(_env->getServerName().find(".")), 3600, "/", false)); +	}  }  CgiApplicationEngine::Stage::Stage(const CgiApplicationEngine * e) : appEngine(e) @@ -94,6 +117,19 @@ CgiApplicationEngine::PresentStage::run()  		param->add_child_text(fe.getValue());  		param->set_attribute("name", fe.getName());  	} +	// Sessions variables +	if (!appEngine->sessionID.is_nil()) { +		xmlpp::Element * sessionXml = responseRoot->add_child("session", "project2"); +		sessionXml->set_attribute("id", boost::lexical_cast<Glib::ustring>(appEngine->sessionID)); +	syslog(LOG_DEBUG, "> var dump"); +		Session::Values session(sessionsContainer->GetSession(appEngine->sessionID)->GetValuesCopy()); +		//BOOST_FOREACH(SessionShm::Values::value_type sv, session) { +			//xmlpp::Element * param = sessionXml->add_child("var", "project2"); +			//param->add_child_text(sv.second); +			//param->set_attribute("name", sv.first); +		//} +	syslog(LOG_DEBUG, "< var dump"); +	}  	// XSLT Style  	char * buf;  	if (asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", @@ -103,6 +139,7 @@ CgiApplicationEngine::PresentStage::run()  	}  	free(buf);  	appEngine->doc = responseDoc; +	sessionsContainer->CleanUp();  	return NULL;  } @@ -117,6 +154,7 @@ CgiApplicationEngine::RequestStage::RequestStage(const CgiApplicationEngine * e,  	_DataSource::AddLoaders(loaders, appEngine->datasources);  	_ParamChecker::AddLoaders(loaders, parameterChecks);  	_Task::AddLoaders(loaders, tasks); +	_Iterate::AddLoaders(loaders, tasks);  	_LoaderBase::collectAll(loaders, "project2", requestRoot, true, true);  }  CgiApplicationEngine::RequestStage::~RequestStage() @@ -130,9 +168,8 @@ CgiApplicationEngine::RequestStage::run()  			return new PresentStage(appEngine, pc.second->present);  		}  	} -	syslog(LOG_DEBUG, "Checks passed");  	try { -		BOOST_FOREACH(OrderedTasks::value_type t, tasks) { +		BOOST_FOREACH(NoOutputExecutes::value_type t, tasks) {  			t.second->execute(appEngine);  		}  		// Commit data source transactions (without invoking a connection) @@ -150,3 +187,14 @@ CgiApplicationEngine::RequestStage::run()  	return new PresentStage(appEngine, present);  } +void +CgiApplicationEngine::SessionSet(const Glib::ustring & name, const Glib::ustring & value) const +{ +	sessionsContainer->GetSession(sessionID)->SetValue(name, value); +} +void +CgiApplicationEngine::SessionClear(const Glib::ustring & name) const +{ +	sessionsContainer->GetSession(sessionID)->ClearValue(name); +} + diff --git a/project2/cgiAppEngine.h b/project2/cgiAppEngine.h index 80707a0..9532ed4 100644 --- a/project2/cgiAppEngine.h +++ b/project2/cgiAppEngine.h @@ -2,15 +2,20 @@  #define CGIAPPENGINE_H  #include "appEngine.h" -#include "cgiEnvironment.h"  #include "task.h"  #include "paramChecker.h"  #include <boost/shared_ptr.hpp> +#include <boost/uuid/uuid.hpp>  #include <libxml++/document.h> +class CgiEnvironment; +namespace cgicc { +	class HTTPContentHeader; +} +  class CgiApplicationEngine : public ApplicationEngine {  	public: -		CgiApplicationEngine(const CgiEnvironment *); +		CgiApplicationEngine(const CgiEnvironment *, cgicc::HTTPContentHeader *);  		virtual ~CgiApplicationEngine();  		void process() const; @@ -20,7 +25,11 @@ class CgiApplicationEngine : public ApplicationEngine {  			w(doc->cobj());  		}  		const Environment * env() const; +		virtual void SessionSet(const Glib::ustring & name, const Glib::ustring & value) const; +		virtual void SessionClear(const Glib::ustring & name) const;  		const CgiEnvironment * _env; +	protected: +		cgicc::HTTPContentHeader * header;  	private:  		mutable boost::shared_ptr<xmlpp::Document> doc;  		class Stage { @@ -39,7 +48,7 @@ class CgiApplicationEngine : public ApplicationEngine {  				virtual Stage * run();  				std::string present;  			protected: -				OrderedTasks tasks; +				NoOutputExecutes tasks;  		};  		class PresentStage : public Stage {  			public: @@ -52,6 +61,7 @@ class CgiApplicationEngine : public ApplicationEngine {  				Glib::ustring responseStyle;  		};  		mutable Stage * currentStage; +		mutable boost::uuids::uuid sessionID;  };  #endif diff --git a/project2/dataSource.cpp b/project2/dataSource.cpp index 984ea53..9b6bd18 100644 --- a/project2/dataSource.cpp +++ b/project2/dataSource.cpp @@ -4,7 +4,7 @@  #include "rdbmsDataSource.h"  _DataSource::_DataSource(const xmlpp::Element * p) : -	_Project2SourceObject(p) +	_SourceObject(p)  {  } @@ -15,5 +15,5 @@ _DataSource::~_DataSource()  void  _DataSource::AddLoaders(Loaders & l, DataSources & dss)  { -	l.insert(LoadersVT("rdbmsdatasource", _LoaderBase::Make<_RdbmsDataSource, _DataSource, std::string, _Project2SourceObject, &_Project2SourceObject::name>(&dss))); +	l.insert(LoadersVT("rdbmsdatasource", _LoaderBase::Make<_RdbmsDataSource, _DataSource, std::string, _SourceObject, &_SourceObject::name>(&dss)));  } diff --git a/project2/dataSource.h b/project2/dataSource.h index 9d30d07..0cc0124 100644 --- a/project2/dataSource.h +++ b/project2/dataSource.h @@ -11,7 +11,7 @@ class _DataSource;  typedef boost::shared_ptr<_DataSource> DataSource;  typedef std::map<std::string, DataSource> DataSources; -class _DataSource : public _Project2SourceObject { +class _DataSource : public virtual _SourceObject {  	public:  		_DataSource(const xmlpp::Element * p);  		virtual ~_DataSource(); diff --git a/project2/iterate.cpp b/project2/iterate.cpp new file mode 100644 index 0000000..02fc149 --- /dev/null +++ b/project2/iterate.cpp @@ -0,0 +1,41 @@ +#include "iterate.h" +#include <boost/foreach.hpp> +#include <syslog.h> +#include "xmlObjectLoader.h" +#include "sqlIterate.h" +#include "task.h" + +_Iterate::_Iterate(const xmlpp::Element * p) : +	_SourceObject(p), +	_NoOutputExecute(p) +{ +	Loaders loaders; +	_Iterate::AddLoaders(loaders, subIterates); +	_Task::AddLoaders(loaders, subIterates); +	_LoaderBase::collectAll(loaders, "project2", p, true, true); +} + +_Iterate::~_Iterate() +{ +} + +void +_Iterate::AddLoaders(Loaders & l, Iterates & iterates) +{ +	l.insert(LoadersVT("sqliterate", _LoaderBase::Make<_SqlIterate, _Iterate, std::string, _SourceObject, &_SourceObject::name>(&iterates))); +} + +void +_Iterate::AddLoaders(Loaders & l, NoOutputExecutes & iterates) +{ +	l.insert(LoadersVT("sqliterate", _LoaderBase::Make<_SqlIterate, _NoOutputExecute, unsigned int, _SourceObject, &_SourceObject::order>(&iterates))); +} + +void +_Iterate::executeChildren(const ApplicationEngine * ep, const PerRowValues * parent) const +{ +	BOOST_FOREACH(NoOutputExecutes::value_type sq, subIterates) { +		sq.second->execute(ep, this); +	} +} + diff --git a/project2/iterate.h b/project2/iterate.h new file mode 100644 index 0000000..c113585 --- /dev/null +++ b/project2/iterate.h @@ -0,0 +1,33 @@ +#ifndef ITERATE_H +#define ITERATE_H + +#include <libxml++/nodes/element.h> +#include <boost/shared_ptr.hpp> +#include <map> +#include "sourceObject.h" +#include "xmlObjectLoader.h" +#include "perRowValues.h" +#include "noOutputExecute.h" + +class ApplicationEngine; +class _Iterate; +typedef boost::shared_ptr<_Iterate> Iterate; +typedef std::map<std::string, Iterate> Iterates; + +class _Iterate : public virtual _SourceObject, public PerRowValues, public _NoOutputExecute { +	public: +		_Iterate(const xmlpp::Element * p); +		virtual ~_Iterate(); +		virtual void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const = 0; +		virtual Glib::ustring getCurrentValue(const Glib::ustring & id) const = 0; + +		static void AddLoaders(Loaders & l, Iterates & vs); +		static void AddLoaders(Loaders & l, NoOutputExecutes & vs); +	protected: +		void executeChildren(const ApplicationEngine *, const PerRowValues * parent = NULL) const; +		NoOutputExecutes subIterates; +}; + +#endif + + diff --git a/project2/noOutputExecute.h b/project2/noOutputExecute.h new file mode 100644 index 0000000..ad5df92 --- /dev/null +++ b/project2/noOutputExecute.h @@ -0,0 +1,20 @@ +#ifndef NOOUTPUTEXECUTE_H +#define NOOUTPUTEXECUTE_H + +#include "sourceObject.h" + +class ApplicationEngine; +class PerRowValues; + +class _NoOutputExecute; +typedef boost::shared_ptr<_NoOutputExecute> NoOutputExecute; +typedef std::map<unsigned int, NoOutputExecute> NoOutputExecutes; + +class _NoOutputExecute : public virtual _SourceObject { +	public: +		_NoOutputExecute(const xmlpp::Element * p) : _SourceObject(p) { }; +		virtual ~_NoOutputExecute() { } +		virtual void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const = 0; +}; +#endif + diff --git a/project2/p2webMain.cpp b/project2/p2webMain.cpp index 1eafd2d..f424e0a 100644 --- a/project2/p2webMain.cpp +++ b/project2/p2webMain.cpp @@ -1,76 +1,62 @@  #include <libxml/tree.h>  #include <cgicc/Cgicc.h>  #include <cgicc/CgiEnvironment.h> +#include <cgicc/HTTPContentHeader.h> +FILE * realstdout = stdout;  #include <fcgi_stdio.h>  #include "cgiEnvironment.h"  #include "cgiAppEngine.h"  #include <boost/bind.hpp> +#include "FCgiIO.h"  int  xmlWrite(void * _out, const char * buf, int len)  { -	return FCGX_PutStr(buf, len, (FCGX_Stream*)_out); +	cgicc::FCgiIO & IO = *((cgicc::FCgiIO*)_out); +	IO.write(buf, len); +	return len;  } -class CgiReader : public cgicc::CgiInput { -	public: -		CgiReader(FCGX_Stream * i, FCGX_ParamArray & e) : -			in(i), -			envp(e) -		{ -		} -		~CgiReader() { } - -		size_t read(char * data, size_t length) -		{ -			return FCGX_GetStr(data, length, in); -		} -		std::string getenv(const char * env) -		{ -			const char * e = FCGX_GetParam(env, envp); -			return e ? e : ""; -		} -	private: -		FCGX_Stream *in; -		FCGX_ParamArray envp; -};  int main(void)  {  	if (!FCGX_IsCGI()) { -		FCGX_Stream *in, *_out, *err; -		FCGX_ParamArray envp; +		FCGX_Request request; + +		FCGX_Init(); +		FCGX_InitRequest(&request, 0, 0); -		while (FCGX_Accept(&in, &_out, &err, &envp) >= 0)  -		{ -			CgiReader reader(in, envp); -			cgicc::Cgicc cgi(&reader); +		while (FCGX_Accept_r(&request) == 0) { +			cgicc::FCgiIO IO(request);  			try { +				cgicc::Cgicc cgi(&IO);  				CgiEnvironment env(&cgi); -				CgiApplicationEngine app(&env); +				cgicc::HTTPContentHeader header("text/xml-xslt"); +				CgiApplicationEngine app(&env, &header);  				app.process(); -				FCGX_FPrintF(_out, "Content-type: text/xml-xslt\r\n\r\n");       +				header.render(IO);  				xmlOutputBufferPtr out = xmlOutputBufferCreateIO( -						xmlWrite, NULL, _out, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8)); +						xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8));  				app.write(boost::bind(xmlSaveFileTo, out, _1, "utf-8"));  			}  			catch (const std::exception & e) { -				FCGX_FPrintF(_out, "Content-type: text/plain\r\n\r\n");       -				FCGX_FPrintF(_out, "Kaboom!\r\n\r\n");       -				FCGX_FPrintF(_out, "%s\r\n\r\n", e.what());       +				cgicc::HTTPContentHeader header("text/plain"); +				header.render(IO); +				IO << "Kaboom!" << std::endl << std::endl << e.what();  			}  			catch (...) { -				FCGX_FPrintF(_out, "Content-type: text/plain\r\n\r\n");       -				FCGX_FPrintF(_out, "Kaboom!\r\n\r\n");       -				FCGX_FPrintF(_out, "Unknown exception.\r\n\r\n");       +				cgicc::HTTPContentHeader header("text/plain"); +				header.render(IO); +				IO << "Kaboom!" << std::endl << std::endl << "Unknown exception.";        			}  		}  	}  	else {  		cgicc::Cgicc cgi(NULL);  		CgiEnvironment env(&cgi); -		CgiApplicationEngine app(&env); +		cgicc::HTTPContentHeader header("text/xml-xslt"); +		CgiApplicationEngine app(&env, &header);  		app.process(); -		//app.write(boost::bind(xmlDocDump, stdout, _1)); +		app.write(boost::bind(xmlDocDump, realstdout, _1));  	}  	return 0;  } diff --git a/project2/paramChecker.cpp b/project2/paramChecker.cpp index 697728a..627f1be 100644 --- a/project2/paramChecker.cpp +++ b/project2/paramChecker.cpp @@ -4,14 +4,11 @@  #include "regexCheck.h"  #include "sqlCheck.h" -unsigned int _ParamChecker::loadOrder = 1; -  _ParamChecker::_ParamChecker(const xmlpp::Element * p) : -	_Project2SourceObject(p), +	_SourceObject(p),  	message(xmlChildText(p, "message")),  	applyTo(p->get_attribute_value("apply-to")), -	present(p->get_attribute_value("present")), -	order(loadOrder++) +	present(p->get_attribute_value("present"))  {  } @@ -22,7 +19,7 @@ _ParamChecker::~_ParamChecker()  void  _ParamChecker::AddLoaders(Loaders & l, OrderedParamCheckers & checks)  { -	l.insert(LoadersVT("regexcheck", _LoaderBase::Make<_RegexCheck, _ParamChecker, unsigned int, _ParamChecker, &_ParamChecker::order>(&checks))); -	l.insert(LoadersVT("sqlcheck", _LoaderBase::Make<_SqlCheck, _ParamChecker, unsigned int, _ParamChecker, &_ParamChecker::order>(&checks))); +	l.insert(LoadersVT("regexcheck", _LoaderBase::Make<_RegexCheck, _ParamChecker, unsigned int, _SourceObject, &_SourceObject::order>(&checks))); +	l.insert(LoadersVT("sqlcheck", _LoaderBase::Make<_SqlCheck, _ParamChecker, unsigned int, _SourceObject, &_SourceObject::order>(&checks)));  } diff --git a/project2/paramChecker.h b/project2/paramChecker.h index 28c0275..1ffe89f 100644 --- a/project2/paramChecker.h +++ b/project2/paramChecker.h @@ -13,7 +13,7 @@ typedef boost::shared_ptr<_ParamChecker> ParamChecker;  typedef std::map<std::string, ParamChecker> ParamCheckers;  typedef std::map<unsigned int, ParamChecker> OrderedParamCheckers; -class _ParamChecker : public _Project2SourceObject { +class _ParamChecker : public virtual _SourceObject {  	public:  		_ParamChecker(const xmlpp::Element * p);  		virtual ~_ParamChecker(); @@ -23,11 +23,8 @@ class _ParamChecker : public _Project2SourceObject {  		const Glib::ustring message;  		const std::string applyTo;  		const std::string present; -		const unsigned int order;  		static void AddLoaders(Loaders & l, OrderedParamCheckers & vs); -	private: -		static unsigned int loadOrder;  };  #endif diff --git a/project2/perRowValues.h b/project2/perRowValues.h new file mode 100644 index 0000000..2a46763 --- /dev/null +++ b/project2/perRowValues.h @@ -0,0 +1,12 @@ +#ifndef PERROWVALUES_H +#define PERROWVALUES_H + +#include <glibmm/ustring.h> + +class PerRowValues { +	public: +		virtual Glib::ustring getCurrentValue(const Glib::ustring & id) const = 0; +}; + +#endif + diff --git a/project2/rdbmsDataSource.cpp b/project2/rdbmsDataSource.cpp index dad35a3..1a55fb8 100644 --- a/project2/rdbmsDataSource.cpp +++ b/project2/rdbmsDataSource.cpp @@ -3,6 +3,7 @@  #include <libxml++/nodes/textnode.h>  _RdbmsDataSource::_RdbmsDataSource(const xmlpp::Element * p) : +	_SourceObject(p),  	_DataSource(p),  	masterDsn(xmlChildText(p, "masterdsn"))  { diff --git a/project2/regexCheck.cpp b/project2/regexCheck.cpp index abe134c..672194f 100644 --- a/project2/regexCheck.cpp +++ b/project2/regexCheck.cpp @@ -4,6 +4,7 @@  #include <boost/regex.hpp>  _RegexCheck::_RegexCheck(const xmlpp::Element * p) : +	_SourceObject(p),  	_ParamChecker(p),  	regex(xmlChildText(p, "regex").raw())  { diff --git a/project2/session.cpp b/project2/session.cpp new file mode 100644 index 0000000..87bea0c --- /dev/null +++ b/project2/session.cpp @@ -0,0 +1,27 @@ +#include "session.h" +#include <syslog.h> + +Session::Session() +{ +} + +Session::~Session() +{ +} + +SessionContainer::SessionContainer() +{ +} + +SessionContainer::~SessionContainer() +{ +} + +SessionPtr +SessionContainer::GetSession(boost::uuids::uuid & id) +{ +	SessionPtr s = getSession(id); +	s->ExpiryTime(time(NULL) + 3600); +	return s; +} + diff --git a/project2/session.h b/project2/session.h new file mode 100644 index 0000000..de31626 --- /dev/null +++ b/project2/session.h @@ -0,0 +1,42 @@ +#ifndef SESSION_H +#define SESSION_H + +#include <map> +#include <glibmm/ustring.h> +#include <boost/uuid/uuid.hpp> +#include <boost/shared_ptr.hpp> + +class Session { +	public: +		typedef std::map<Glib::ustring, Glib::ustring> Values; + +		Session(); +		virtual ~Session() = 0; + +		virtual Glib::ustring GetValue(const Glib::ustring & name) const = 0; +		virtual Values GetValuesCopy() const = 0; +		virtual void SetValue(const Glib::ustring & name, const Glib::ustring & value) = 0; +		virtual void ClearValue(const Glib::ustring & name) = 0; +		virtual time_t ExpiryTime() const = 0; + +	protected: +		virtual void ExpiryTime(time_t) = 0; +		friend class SessionContainer; +}; +typedef boost::shared_ptr<Session> SessionPtr; + +class SessionContainer { +	public: +		SessionContainer(); +		virtual ~SessionContainer() = 0; + +		SessionPtr GetSession(boost::uuids::uuid & sid); +		virtual void CleanUp() { } + +	protected: +		virtual SessionPtr getSession(boost::uuids::uuid & sid) = 0; +}; + + +#endif + diff --git a/project2/sessionClearTask.cpp b/project2/sessionClearTask.cpp new file mode 100644 index 0000000..c5d6d0d --- /dev/null +++ b/project2/sessionClearTask.cpp @@ -0,0 +1,21 @@ +#include <boost/foreach.hpp> +#include "xmlObjectLoader.h" +#include "sessionClearTask.h" +#include "appEngine.h" + +_SessionClearTask::_SessionClearTask(const xmlpp::Element * p) : +	_SourceObject(p), +	_Task(p) +{ +} + +_SessionClearTask::~_SessionClearTask() +{ +} + +void +_SessionClearTask::execute(const ApplicationEngine * ep, const PerRowValues *) const +{ +	ep->SessionClear(key); +} + diff --git a/project2/sessionClearTask.h b/project2/sessionClearTask.h new file mode 100644 index 0000000..f3b779b --- /dev/null +++ b/project2/sessionClearTask.h @@ -0,0 +1,26 @@ +#ifndef SESSIONCLEARTASK_H +#define SESSIONCLEARTASK_H + +#include <libxml++/nodes/element.h> +#include <boost/shared_ptr.hpp> +#include <map> +#include "sourceObject.h" +#include "xmlObjectLoader.h" +#include "task.h" + +class ApplicationEngine; +class _SessionClearTask; +typedef boost::shared_ptr<_SessionClearTask> SessionClearTask; + +class _SessionClearTask : public virtual _Task { +	public: +		_SessionClearTask(const xmlpp::Element * p); +		virtual ~_SessionClearTask(); +		void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const; + +		const Glib::ustring key; +}; + +#endif + + diff --git a/project2/sessionSetTask.cpp b/project2/sessionSetTask.cpp new file mode 100644 index 0000000..abd02b0 --- /dev/null +++ b/project2/sessionSetTask.cpp @@ -0,0 +1,33 @@ +#include <syslog.h> +#include <boost/foreach.hpp> +#include "xmlObjectLoader.h" +#include "sessionSetTask.h" +#include "appEngine.h" + +_SessionSetTask::_SessionSetTask(const xmlpp::Element * p) : +	_SourceObject(p), +	_Task(p), +	IHaveParameters(p), +	key(p->get_attribute_value("key")) +{ +} + +_SessionSetTask::~_SessionSetTask() +{ +} + +void +_SessionSetTask::execute(const ApplicationEngine * ep, const PerRowValues * parent) const +{ +	Parameter p = parameters.find(0)->second; +	if (p->source == "uri") { +		ep->SessionSet(key, ep->env()->getParamUri(p->id)); +	} +	else if (p->source == "parent") { +		ep->SessionSet(key, parent->getCurrentValue(p->id)); +	} +	else if (p->source == "query") { +		ep->SessionSet(key, ep->env()->getParamQuery(p->id)); +	} +} + diff --git a/project2/sessionSetTask.h b/project2/sessionSetTask.h new file mode 100644 index 0000000..32df37b --- /dev/null +++ b/project2/sessionSetTask.h @@ -0,0 +1,27 @@ +#ifndef SESSIONSETTASK_H +#define SESSIONSETTASK_H + +#include <libxml++/nodes/element.h> +#include <boost/shared_ptr.hpp> +#include <map> +#include "sourceObject.h" +#include "xmlObjectLoader.h" +#include "task.h" +#include "iHaveParameters.h" + +class ApplicationEngine; +class _SessionSetTask; +typedef boost::shared_ptr<_SessionSetTask> SessionSetTask; + +class _SessionSetTask : public virtual _Task, public IHaveParameters { +	public: +		_SessionSetTask(const xmlpp::Element * p); +		virtual ~_SessionSetTask(); +		void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const; + +		const Glib::ustring key; +}; + +#endif + + diff --git a/project2/sessionShm.cpp b/project2/sessionShm.cpp new file mode 100644 index 0000000..c9f748c --- /dev/null +++ b/project2/sessionShm.cpp @@ -0,0 +1,128 @@ +#include "sessionShm.h" +#include <syslog.h> +#include <set> +#include <boost/uuid/uuid.hpp> +#include <boost/foreach.hpp> +#include <boost/uuid/uuid_generators.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/uuid/uuid_io.hpp> + +using namespace boost::interprocess; +using namespace boost::uuids; +class SessionShmData { +	public: +		typedef boost::interprocess::string SKey; +		typedef boost::interprocess::string SValue; + +		typedef std::pair<const SKey, SValue> SValueType; +		typedef boost::interprocess::allocator<SValueType, boost::interprocess::managed_mapped_file::segment_manager> AllocatorValueType; +		typedef boost::interprocess::map<SKey, SValue, std::less<SKey>, AllocatorValueType> SessionValues; + +		SessionShmData(); +		~SessionShmData(); + +		SessionValues svs; +		time_t expiryTime; + +		static boost::interprocess::managed_mapped_file shm; +		friend class SessionContainerShm; +}; + +const char * shmFile = "/tmp/project2.sessions"; + +boost::interprocess::managed_mapped_file SessionShmData::shm(open_or_create, shmFile, 1024 * 1024); + +SessionContainerShm::SessionContainerShm() +{ +} + +SessionContainerShm::~SessionContainerShm() +{ +} + +void +SessionContainerShm::CleanUp() +{ +	std::set<std::string> toDelete; +	for (managed_mapped_file::const_named_iterator i = SessionShmData::shm.named_begin(); +			i != SessionShmData::shm.named_end(); i++) { +		const SessionShmData * s = static_cast<const SessionShmData *>(i->value()); +		if (s) { +			if (s->expiryTime < time(NULL)) { +				toDelete.insert(i->name()); +			} +		} +	} +	for(std::set<std::string>::const_iterator s = toDelete.begin(); s != toDelete.end(); s++) { +		SessionShmData::shm.destroy<const SessionShmData>(s->c_str()); +	} +} + +SessionPtr +SessionContainerShm::getSession(boost::uuids::uuid & sid) +{ +	if (sid.is_nil()) { +		sid = boost::uuids::random_generator()(); +	} +	return SessionPtr(new SessionShm( +			SessionShmData::shm.find_or_construct<SessionShmData>(boost::lexical_cast<std::string>(sid).c_str())())); +} + +SessionShm::SessionShm(SessionShmData * d) : data(d) +{ +} + +SessionShm::~SessionShm() +{ +} + +void +SessionShm::ExpiryTime(time_t t) +{ +	data->expiryTime = t; +} + +time_t +SessionShm::ExpiryTime() const +{ +	return data->expiryTime; +} + +SessionShmData::SessionShmData() : +	svs(std::less<SKey>(), AllocatorValueType(shm.get_segment_manager())) +{ +} + +SessionShmData::~SessionShmData() +{ +} + +Glib::ustring +SessionShm::GetValue(const Glib::ustring & name) const +{ +	return data->svs.find(name.c_str())->second.c_str(); +} + +void +SessionShm::SetValue(const Glib::ustring & name, const Glib::ustring & value) +{ +	data->svs.erase(name.c_str()); +	data->svs.insert(std::pair<SessionShmData::SKey, SessionShmData::SValue>(name.c_str(), value.c_str())); +} + +void +SessionShm::ClearValue(const Glib::ustring & name) +{ +	data->svs.erase(name.c_str()); +} + +Session::Values +SessionShm::GetValuesCopy() const +{ +	Values v; +	BOOST_FOREACH(SessionShmData::SessionValues::value_type kvp, data->svs) { +		v[kvp.first.c_str()] = kvp.second.c_str(); +	} +	return v; +} + diff --git a/project2/sessionShm.h b/project2/sessionShm.h new file mode 100644 index 0000000..2794303 --- /dev/null +++ b/project2/sessionShm.h @@ -0,0 +1,38 @@ +#ifndef SESSIONSHM_H +#define SESSIONSHM_H + +#include "session.h" +#include <boost/interprocess/containers/string.hpp> +#include <boost/interprocess/managed_mapped_file.hpp> +#include <boost/interprocess/allocators/allocator.hpp> +#include <boost/interprocess/containers/map.hpp> + +class SessionShmData; +class SessionShm : public Session { +	public: +		SessionShm(SessionShmData *); +		virtual ~SessionShm(); + +		Glib::ustring GetValue(const Glib::ustring & name) const; +		Values GetValuesCopy() const; +		void SetValue(const Glib::ustring & name, const Glib::ustring & value); +		void ClearValue(const Glib::ustring & name); +		time_t ExpiryTime() const; +		void ExpiryTime(time_t); + +	private: +		SessionShmData * data; +}; + +class SessionContainerShm : public SessionContainer { +	public: +		SessionContainerShm(); +		~SessionContainerShm(); + +		void CleanUp(); + +	protected: +		SessionPtr getSession(boost::uuids::uuid & sid); +}; + +#endif diff --git a/project2/sourceObject.cpp b/project2/sourceObject.cpp index 9d10f52..bb989b5 100644 --- a/project2/sourceObject.cpp +++ b/project2/sourceObject.cpp @@ -1,11 +1,14 @@  #include "sourceObject.h" -_Project2SourceObject::_Project2SourceObject(const xmlpp::Element * p) : -	name(p->get_attribute_value("name")) +unsigned int _SourceObject::loadOrder = 1; + +_SourceObject::_SourceObject(const xmlpp::Element * p) : +	name(p->get_attribute_value("name")), +	order(loadOrder++)  {  } -_Project2SourceObject::~_Project2SourceObject() +_SourceObject::~_SourceObject()  {  } diff --git a/project2/sourceObject.h b/project2/sourceObject.h index 421054d..b4472d4 100644 --- a/project2/sourceObject.h +++ b/project2/sourceObject.h @@ -4,12 +4,15 @@  #include <libxml++/nodes/element.h>  #include <boost/shared_ptr.hpp> -class _Project2SourceObject { +class _SourceObject {  	public: -		_Project2SourceObject(const xmlpp::Element * p); -		virtual ~_Project2SourceObject() = 0; +		_SourceObject(const xmlpp::Element * p); +		virtual ~_SourceObject() = 0;  		const std::string name; +		const unsigned int order; +	private: +		static unsigned int loadOrder;  }; -typedef boost::shared_ptr<_Project2SourceObject> Project2SourceObject; +typedef boost::shared_ptr<_SourceObject> Project2SourceObject;  #endif diff --git a/project2/sqlCheck.cpp b/project2/sqlCheck.cpp index 25094a6..1dab147 100644 --- a/project2/sqlCheck.cpp +++ b/project2/sqlCheck.cpp @@ -7,6 +7,7 @@  #include <boost/regex.hpp>  _SqlCheck::_SqlCheck(const xmlpp::Element * p) : +	_SourceObject(p),  	IHaveParameters(p),  	_ParamChecker(p),  	dataSource(p->get_attribute_value("datasource")), diff --git a/project2/sqlIterate.cpp b/project2/sqlIterate.cpp new file mode 100644 index 0000000..90a8bc1 --- /dev/null +++ b/project2/sqlIterate.cpp @@ -0,0 +1,61 @@ +#include "sqlIterate.h" +#include "xml.h" +#include "selectcommand.h" +#include "column.h" +#include <string.h> +#include <syslog.h> +#include <libxml++/nodes/textnode.h> +#include "xmlObjectLoader.h" +#include "environment.h" +#include "appEngine.h" + +_SqlIterate::_SqlIterate(const xmlpp::Element * p) : +	_SourceObject(p), +	IHaveParameters(p), +	_Iterate(p), +	dataSource(p->get_attribute_value("datasource")), +	sql(xmlChildText(p, "sql")), +	query(NULL) +{ +} + +Glib::ustring +_SqlIterate::getCurrentValue(const Glib::ustring & id) const +{ +	return (*query)[id].compose(); +} + +void +_SqlIterate::rebindCurrentValue(const Glib::ustring & id, ODBC::Command * cmd, unsigned int bind) const +{ +	(*query)[id].rebind(cmd, bind); +} + +void _SqlIterate::execute(const ApplicationEngine * ep, const PerRowValues * parent) const +{ +	typedef std::map<std::string, xmlpp::Element *> Columns; +	query = new ODBC::SelectCommand(ep->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql); +	BOOST_FOREACH(Parameters::value_type p, parameters) { +		if (p.second->source == "uri") { +			query->bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id)); +		} +		else if (p.second->source == "query") { +			query->bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id)); +		} +		else if (parent && p.second->source == "parent") { +			const _SqlIterate * psqlIterate = dynamic_cast<const _SqlIterate *>(parent); +			if (psqlIterate) { +				psqlIterate->rebindCurrentValue(p.second->id, query, p.second->bind); +			} +			else { +				query->bindParamS(p.second->bind, parent->getCurrentValue(p.second->id)); +			} +		} +	} +	while (query->fetch()) { +		executeChildren(ep, this); +	} +	delete query; +	query = NULL; +} + diff --git a/project2/sqlIterate.h b/project2/sqlIterate.h new file mode 100644 index 0000000..c9cef49 --- /dev/null +++ b/project2/sqlIterate.h @@ -0,0 +1,29 @@ +#ifndef SQLITERATE_H +#define SQLITERATE_H + +#include <libxml++/nodes/element.h> +#include <boost/shared_ptr.hpp> +#include <map> +#include "selectcommand.h" +#include "iterate.h" +#include "rdbmsDataSource.h" +#include "iHaveParameters.h" + +class ApplicationEngine; + +class _SqlIterate : public IHaveParameters, public _Iterate { +	public: +		_SqlIterate(const xmlpp::Element * p); +		void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const; +		Glib::ustring getCurrentValue(const Glib::ustring & id) const; +		const std::string dataSource; +		const Glib::ustring sql; +		void rebindCurrentValue(const Glib::ustring & id, ODBC::Command *, unsigned int) const; +	private: +		mutable ODBC::SelectCommand * query; +}; +typedef boost::shared_ptr<_SqlIterate> SqlIterate; +typedef std::map<std::string, SqlIterate> SqlIterates; + +#endif + diff --git a/project2/sqlTask.cpp b/project2/sqlTask.cpp index 2832f73..93e656e 100644 --- a/project2/sqlTask.cpp +++ b/project2/sqlTask.cpp @@ -7,6 +7,7 @@  #include "sqlView.h"  _SqlTask::_SqlTask(const xmlpp::Element * p) : +	_SourceObject(p),  	_Task(p),  	IHaveParameters(p),  	dataSource(p->get_attribute_value("datasource")), @@ -19,7 +20,7 @@ _SqlTask::~_SqlTask()  }  void -_SqlTask::execute(const ApplicationEngine * ep, const _View * parent) const +_SqlTask::execute(const ApplicationEngine * ep, const PerRowValues * parent) const  {  	ODBC::ModifyCommand modify(ep->dataSource<_RdbmsDataSource>(dataSource)->getWritable(), sql);  	BOOST_FOREACH(Parameters::value_type p, parameters) { diff --git a/project2/sqlTask.h b/project2/sqlTask.h index 75333e3..a64b837 100644 --- a/project2/sqlTask.h +++ b/project2/sqlTask.h @@ -14,7 +14,7 @@ class _SqlTask : public _Task, public IHaveParameters {  	public:  		_SqlTask(const xmlpp::Element * p);  		virtual ~_SqlTask(); -		virtual void execute(const ApplicationEngine *, const _View * parent = NULL) const; +		virtual void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const;  		const std::string dataSource;  		const std::string sql; diff --git a/project2/sqlView.cpp b/project2/sqlView.cpp index 1fe0a0d..cab4ca5 100644 --- a/project2/sqlView.cpp +++ b/project2/sqlView.cpp @@ -9,6 +9,7 @@  #include "appEngine.h"  _SqlView::_SqlView(const xmlpp::Element * p) : +	_SourceObject(p),  	IHaveParameters(p),  	_View(p),  	dataSource(p->get_attribute_value("datasource")), @@ -98,9 +99,7 @@ void _SqlView::execute(xmlpp::Element * par, const ApplicationEngine * ep, const  			free(name);  			free(attr);  		} -		BOOST_FOREACH(Views::value_type sq, subViews) { -			sq.second->execute(record, ep, this); -		} +		executeChildren(record, ep, this);  	}  	delete query;  	query = NULL; diff --git a/project2/task.cpp b/project2/task.cpp index 9800b78..a84ad7e 100644 --- a/project2/task.cpp +++ b/project2/task.cpp @@ -2,12 +2,12 @@  #include <boost/foreach.hpp>  #include "xmlObjectLoader.h"  #include "sqlTask.h" - -unsigned int _Task::loadOrder = 1; +#include "sessionClearTask.h" +#include "sessionSetTask.h"  _Task::_Task(const xmlpp::Element * p) : -	_Project2SourceObject(p), -	order(loadOrder++) +	_SourceObject(p), +	_NoOutputExecute(p)  {  } @@ -18,6 +18,16 @@ _Task::~_Task()  void  _Task::AddLoaders(Loaders & l, OrderedTasks & tasks)  { -	l.insert(LoadersVT("sqltask", _LoaderBase::Make<_SqlTask, _Task, unsigned int, _Task, &_Task::order>(&tasks))); +	l.insert(LoadersVT("sqltask", _LoaderBase::Make<_SqlTask, _Task, unsigned int, _SourceObject, &_SourceObject::order>(&tasks))); +	l.insert(LoadersVT("sessionclear", _LoaderBase::Make<_SessionClearTask, _Task, unsigned int, _SourceObject, &_SourceObject::order>(&tasks))); +	l.insert(LoadersVT("sessionset", _LoaderBase::Make<_SessionSetTask, _Task, unsigned int, _SourceObject, &_SourceObject::order>(&tasks))); +} + +void +_Task::AddLoaders(Loaders & l, NoOutputExecutes & tasks) +{ +	l.insert(LoadersVT("sqltask", _LoaderBase::Make<_SqlTask, _NoOutputExecute, unsigned int, _SourceObject, &_SourceObject::order>(&tasks))); +	l.insert(LoadersVT("sessionclear", _LoaderBase::Make<_SessionClearTask, _NoOutputExecute, unsigned int, _SourceObject, &_SourceObject::order>(&tasks))); +	l.insert(LoadersVT("sessionset", _LoaderBase::Make<_SessionSetTask, _NoOutputExecute, unsigned int, _SourceObject, &_SourceObject::order>(&tasks)));  } diff --git a/project2/task.h b/project2/task.h index 00fce4b..b79687b 100644 --- a/project2/task.h +++ b/project2/task.h @@ -7,6 +7,7 @@  #include "sourceObject.h"  #include "xmlObjectLoader.h"  #include "view.h" +#include "noOutputExecute.h"  class ApplicationEngine;  class _Task; @@ -14,16 +15,14 @@ typedef boost::shared_ptr<_Task> Task;  typedef std::map<std::string, Task> Tasks;  typedef std::map<unsigned int, Task> OrderedTasks; -class _Task : public _Project2SourceObject { +class _Task : public virtual _SourceObject, public _NoOutputExecute {  	public:  		_Task(const xmlpp::Element * p);  		virtual ~_Task(); -		virtual void execute(const ApplicationEngine *, const _View * parent = NULL) const = 0; -		const unsigned int order; +		virtual void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const = 0;  		static void AddLoaders(Loaders & l, OrderedTasks & vs); -	private: -		static unsigned int loadOrder; +		static void AddLoaders(Loaders & l, NoOutputExecutes & vs);  };  #endif diff --git a/project2/view.cpp b/project2/view.cpp index 31596d5..799d1ae 100644 --- a/project2/view.cpp +++ b/project2/view.cpp @@ -4,7 +4,7 @@  #include "sqlView.h"  _View::_View(const xmlpp::Element * p) : -	_Project2SourceObject(p), +	_SourceObject(p),  	recordName(p->get_attribute_value("recordname"))  {  } @@ -16,6 +16,14 @@ _View::~_View()  void  _View::AddLoaders(Loaders & l, Views & views)  { -	l.insert(LoadersVT("sqlview", _LoaderBase::Make<_SqlView, _View, std::string, _Project2SourceObject, &_Project2SourceObject::name>(&views))); +	l.insert(LoadersVT("sqlview", _LoaderBase::Make<_SqlView, _View, std::string, _SourceObject, &_SourceObject::name>(&views))); +} + +void +_View::executeChildren(xmlpp::Element * record, const ApplicationEngine * ep, const _View * parent) const +{ +	BOOST_FOREACH(Views::value_type sq, subViews) { +		sq.second->execute(record, ep, this); +	}  } diff --git a/project2/view.h b/project2/view.h index 43f2792..9bd88ed 100644 --- a/project2/view.h +++ b/project2/view.h @@ -6,13 +6,14 @@  #include <map>  #include "sourceObject.h"  #include "xmlObjectLoader.h" +#include "perRowValues.h"  class ApplicationEngine;  class _View;  typedef boost::shared_ptr<_View> View;  typedef std::map<std::string, View> Views; -class _View : public _Project2SourceObject { +class _View : public virtual _SourceObject, public PerRowValues {  	public:  		_View(const xmlpp::Element * p);  		virtual ~_View(); @@ -22,6 +23,7 @@ class _View : public _Project2SourceObject {  		static void AddLoaders(Loaders & l, Views & vs);  	protected: +		void executeChildren(xmlpp::Element *, const ApplicationEngine *, const _View * parent = NULL) const;  		Views subViews;  }; | 
