From 530d921225b019130585667d91bad25194179310 Mon Sep 17 00:00:00 2001
From: randomdan <randomdan@localhost>
Date: Fri, 5 Jul 2013 00:01:26 +0000
Subject: Massive refactor to remove the appEngine and environment complication
 and instead have an execution context that's passed around from the original
 call site

---
 project2/basics/aggregates/avg.cpp           |   2 +-
 project2/basics/aggregates/count.cpp         |   2 +-
 project2/basics/aggregates/countDistinct.cpp |   2 +-
 project2/basics/aggregates/distinct.cpp      |   2 +-
 project2/basics/aggregates/join.cpp          |   4 +-
 project2/basics/aggregates/max.cpp           |   2 +-
 project2/basics/aggregates/min.cpp           |   2 +-
 project2/basics/aggregates/sum.cpp           |   2 +-
 project2/basics/functions/dates.cpp          |  20 +--
 project2/basics/functions/strings.cpp        |   4 +-
 project2/basics/pch.hpp                      |   1 -
 project2/basics/tests/compoundTest.cpp       |  16 +-
 project2/basics/tests/equals.cpp             |   4 +-
 project2/basics/tests/isdistinct.cpp         |   6 +-
 project2/basics/tests/isuniq.cpp             |   8 +-
 project2/basics/tests/validDateCheck.cpp     |   8 +-
 project2/cgi/Jamfile.jam                     |   1 -
 project2/cgi/cgiAppEngine.cpp                | 242 ++++++++++++++++++---------
 project2/cgi/cgiAppEngine.h                  |  92 +++++-----
 project2/cgi/cgiCommon.cpp                   |  70 --------
 project2/cgi/cgiCommon.h                     |   6 -
 project2/cgi/cgiContentNegotiate.cpp         |   8 +-
 project2/cgi/cgiEnvironment.cpp              | 207 -----------------------
 project2/cgi/cgiEnvironment.h                |  78 ---------
 project2/cgi/cgiProgRouter.cpp               |  13 +-
 project2/cgi/cgiRequestContext.cpp           | 161 ++++++++++++++++++
 project2/cgi/cgiRequestContext.h             |  68 ++++++++
 project2/cgi/cgiRequestID.cpp                |  11 +-
 project2/cgi/cgiResultStatic.cpp             |   2 +-
 project2/cgi/cgiResultWritable.cpp           |   4 +-
 project2/cgi/cgiRouter.h                     |   1 +
 project2/cgi/cgiSimpleRouter.cpp             |   2 +-
 project2/cgi/cgiStageCacheHit.cpp            |   6 +-
 project2/cgi/cgiStageCustomError.cpp         |  18 +-
 project2/cgi/cgiStageCustomNotFound.cpp      |  16 +-
 project2/cgi/cgiStageDefaultError.cpp        |  18 +-
 project2/cgi/cgiStageDefaultNotFound.cpp     |  10 +-
 project2/cgi/cgiStageFail.cpp                |  10 +-
 project2/cgi/cgiStageInitial.cpp             |  13 +-
 project2/cgi/cgiStagePresent.cpp             |  32 ++--
 project2/cgi/cgiStageRedirect.cpp            |  10 +-
 project2/cgi/cgiStageRequest.cpp             |  18 +-
 project2/cgi/cgiUriParam.cpp                 |   9 +-
 project2/cgi/p2webCgi.cpp                    |  11 +-
 project2/cgi/p2webFCgi.cpp                   |  11 +-
 project2/cgi/pch.hpp                         |   8 +-
 project2/cgi/testCgi.cpp                     |  22 ++-
 project2/common/aggregate.cpp                |   4 +-
 project2/common/aggregate.h                  |   4 +-
 project2/common/appEngine.cpp                |  53 ------
 project2/common/appEngine.h                  |  42 -----
 project2/common/cache.cpp                    |  14 +-
 project2/common/cache.h                      |  15 +-
 project2/common/check.cpp                    |   4 +-
 project2/common/check.h                      |   4 +-
 project2/common/checkHost.cpp                |   8 +-
 project2/common/checkHost.h                  |   2 +-
 project2/common/commonObjects.cpp            |   1 -
 project2/common/environment.cpp              |  22 ---
 project2/common/environment.h                |  28 ----
 project2/common/exceptions.h                 |   1 +
 project2/common/execContext.cpp              |  36 ++++
 project2/common/execContext.h                |  37 ++++
 project2/common/iHaveParameters.cpp          |   9 +-
 project2/common/iHaveParameters.h            |   4 +-
 project2/common/iHaveSubTasks.cpp            |   4 +-
 project2/common/iHaveSubTasks.h              |   4 +-
 project2/common/if.cpp                       |  16 +-
 project2/common/if.h                         |   6 +-
 project2/common/iterate.cpp                  |  14 +-
 project2/common/iterate.h                    |   5 +-
 project2/common/library.cpp                  |   2 +-
 project2/common/memoryCache.cpp              |  18 +-
 project2/common/noOutputExecute.h            |   3 +-
 project2/common/options.cpp                  |  17 +-
 project2/common/options.h                    |  10 +-
 project2/common/optionsSource.cpp            |   8 +-
 project2/common/optionsSource.h              |   6 +-
 project2/common/presenter.cpp                |   1 -
 project2/common/presenter.h                  |   4 +-
 project2/common/presenterCache.cpp           |   6 +-
 project2/common/presenterCache.h             |   4 +-
 project2/common/rowProcessor.cpp             |  38 ++---
 project2/common/rowProcessor.h               |  10 +-
 project2/common/rowSet.cpp                   |  13 +-
 project2/common/rowSet.h                     |  14 +-
 project2/common/rowView.cpp                  |  47 +++---
 project2/common/rowView.h                    |   9 +-
 project2/common/scriptLoader.cpp             |   1 -
 project2/common/scripts.cpp                  |   8 +-
 project2/common/scripts.h                    |   7 +-
 project2/common/sessionClearTask.cpp         |   8 +-
 project2/common/sessionClearTask.h           |   2 +-
 project2/common/sessionContainer.cpp         |   1 -
 project2/common/sessionSetTask.cpp           |   8 +-
 project2/common/sessionSetTask.h             |   2 +-
 project2/common/singleton.cpp                |  16 +-
 project2/common/sourceObject.cpp             |   2 +-
 project2/common/stream.h                     |   4 +-
 project2/common/structExceptHandling.cpp     |  12 +-
 project2/common/structExceptHandling.h       |   2 +-
 project2/common/task.h                       |   2 +-
 project2/common/taskHost.cpp                 |   4 +-
 project2/common/taskHost.h                   |   2 +-
 project2/common/test.h                       |   4 +-
 project2/common/transform.cpp                |  18 +-
 project2/common/transform.h                  |  18 +-
 project2/common/variables.cpp                |  17 +-
 project2/common/variables.h                  |   9 +-
 project2/common/variables/config.cpp         |  13 +-
 project2/common/variables/fixed.cpp          |   2 +-
 project2/common/variables/fixed.h            |   2 +-
 project2/common/variables/literal.cpp        |  22 +--
 project2/common/variables/literal.h          |  14 +-
 project2/common/variables/localparam.cpp     |   8 +-
 project2/common/variables/lookup.cpp         |  18 +-
 project2/common/variables/param.cpp          |  12 +-
 project2/common/variables/session.cpp        |  10 +-
 project2/common/view.h                       |   3 +-
 project2/common/viewGroup.cpp                |   4 +-
 project2/common/viewHost.cpp                 |  14 +-
 project2/common/viewHost.h                   |   6 +-
 project2/compression/decompressStream.cpp    |   6 +-
 project2/console/claOptions.cpp              |  15 +-
 project2/console/claOptions.h                |   2 +-
 project2/console/consoleAppEngine.cpp        | 119 +++++++++----
 project2/console/consoleAppEngine.h          |  39 +++--
 project2/console/consoleEnvironment.cpp      | 100 -----------
 project2/console/consoleEnvironment.h        |  33 ----
 project2/console/consolePresenter.cpp        |   2 +-
 project2/console/consolePresenter.h          |   2 +-
 project2/console/p2consoleMain.cpp           |  21 +--
 project2/console/pch.hpp                     |   1 -
 project2/files/fileStream.cpp                |   4 +-
 project2/files/fsFilterMaxDepth.cpp          |   4 +-
 project2/files/fsFilterName.cpp              |   4 +-
 project2/files/fsFilterType.cpp              |   4 +-
 project2/files/fsRows.cpp                    |  22 +--
 project2/files/fsRows.h                      |   8 +-
 project2/files/functions/pwd.cpp             |   2 +-
 project2/files/optionsSource.cpp             |   4 +-
 project2/files/optionsSource.h               |   2 +-
 project2/files/presenterCache.cpp            |  27 ++-
 project2/files/writeStream.cpp               |   8 +-
 project2/json/presenter-p.cpp                |   8 +-
 project2/json/presenter.cpp                  |  10 +-
 project2/json/presenter.h                    |   6 +-
 project2/mail/sendmailTask.cpp               |  39 +++--
 project2/mail/sendmailTask.h                 |   2 +-
 project2/processes/processStream.cpp         |   6 +-
 project2/regex/regexRows.cpp                 |   6 +-
 project2/regex/regexRows.h                   |   2 +-
 project2/regex/regexTest.cpp                 |   6 +-
 project2/regex/regexTest.h                   |   2 +-
 project2/sql/rdbmsDataSource.cpp             |   8 +-
 project2/sql/sqlBulkLoad.cpp                 |   8 +-
 project2/sql/sqlCache.cpp                    |  20 +--
 project2/sql/sqlMergeTask.cpp                |  87 +++++-----
 project2/sql/sqlMergeTask.h                  |   8 +-
 project2/sql/sqlRows.cpp                     |   6 +-
 project2/sql/sqlRows.h                       |   2 +-
 project2/sql/sqlTask.cpp                     |  12 +-
 project2/sql/sqlTask.h                       |   2 +-
 project2/sql/sqlTest.cpp                     |  10 +-
 project2/sql/sqlTest.h                       |   2 +-
 project2/sql/sqlWriter.cpp                   |  16 +-
 project2/sql/sqlWriter.h                     |  10 +-
 project2/streams/streamNvpRows.cpp           |  22 +--
 project2/streams/streamRows.cpp              |  22 +--
 project2/streams/viewStream.cpp              |  14 +-
 project2/url/curlHelper.cpp                  |  24 +--
 project2/url/curlHelper.h                    |   8 +-
 project2/url/downloadToFile.cpp              |   6 +-
 project2/url/urlStream.cpp                   |   4 +-
 project2/xml/mutators/copy.cpp               |   6 +-
 project2/xml/mutators/copyToAttr.cpp         |   6 +-
 project2/xml/mutators/create.cpp             |   4 +-
 project2/xml/mutators/delete.cpp             |   2 +-
 project2/xml/mutators/rename.cpp             |   4 +-
 project2/xml/pch.hpp                         |   2 -
 project2/xml/rawView.cpp                     |  18 +-
 project2/xml/transformHtml.cpp               |   4 +-
 project2/xml/transformHtml.h                 |   2 +-
 project2/xml/transformText.cpp               |  12 +-
 project2/xml/transformText.h                 |   2 +-
 project2/xml/xmlCache.cpp                    |  17 +-
 project2/xml/xmlDocumentCache.cpp            |   8 +-
 project2/xml/xmlDocumentCache.h              |  10 +-
 project2/xml/xmlDocumentPrefetch.cpp         |  20 +--
 project2/xml/xmlDocumentPrefetch.h           |  10 +-
 project2/xml/xmlPresenter.cpp                |  15 +-
 project2/xml/xmlPresenter.h                  |   6 +-
 project2/xml/xmlRawRows.cpp                  |  13 +-
 project2/xml/xmlRawRows.h                    |   6 +-
 project2/xml/xmlRows.cpp                     |  10 +-
 project2/xml/xmlRows.h                       |   2 +-
 project2/xml/xmlScriptParser.cpp             |   5 +-
 project2/xml/xmlScriptParser.h               |   2 +-
 project2/xml/xpathRows.cpp                   |  24 +--
 project2/xml/xpathRows.h                     |   8 +-
 200 files changed, 1450 insertions(+), 1660 deletions(-)
 delete mode 100644 project2/cgi/cgiCommon.cpp
 delete mode 100644 project2/cgi/cgiCommon.h
 delete mode 100644 project2/cgi/cgiEnvironment.cpp
 delete mode 100644 project2/cgi/cgiEnvironment.h
 create mode 100644 project2/cgi/cgiRequestContext.cpp
 create mode 100644 project2/cgi/cgiRequestContext.h
 delete mode 100644 project2/common/appEngine.cpp
 delete mode 100644 project2/common/appEngine.h
 delete mode 100644 project2/common/environment.cpp
 delete mode 100644 project2/common/environment.h
 create mode 100644 project2/common/execContext.cpp
 create mode 100644 project2/common/execContext.h
 delete mode 100644 project2/console/consoleEnvironment.cpp
 delete mode 100644 project2/console/consoleEnvironment.h

diff --git a/project2/basics/aggregates/avg.cpp b/project2/basics/aggregates/avg.cpp
index 62239b3..900bc5f 100644
--- a/project2/basics/aggregates/avg.cpp
+++ b/project2/basics/aggregates/avg.cpp
@@ -12,7 +12,7 @@ class Average : public ValueAggregate {
 		{
 			vals.clear();
 		}
-		void pushValue(const VariableType & v) const
+		void pushValue(const VariableType & v, ExecContext *) const
 		{
 			if (!v.isNull()) {
 				vals.push_back(v);
diff --git a/project2/basics/aggregates/count.cpp b/project2/basics/aggregates/count.cpp
index 725be72..be22783 100644
--- a/project2/basics/aggregates/count.cpp
+++ b/project2/basics/aggregates/count.cpp
@@ -11,7 +11,7 @@ class Count : public ValueAggregate {
 		{
 			c = 0;
 		}
-		void pushValue(const VariableType & v) const
+		void pushValue(const VariableType & v, ExecContext *) const
 		{
 			if (!v.isNull()) {
 				c += 1;
diff --git a/project2/basics/aggregates/countDistinct.cpp b/project2/basics/aggregates/countDistinct.cpp
index b471911..205b932 100644
--- a/project2/basics/aggregates/countDistinct.cpp
+++ b/project2/basics/aggregates/countDistinct.cpp
@@ -10,7 +10,7 @@ class CountDistinct : public ValueAggregate {
 		{
 			result.clear();
 		}
-		void pushValue(const VariableType & v) const
+		void pushValue(const VariableType & v, ExecContext *) const
 		{
 			result.insert(v);
 		}
diff --git a/project2/basics/aggregates/distinct.cpp b/project2/basics/aggregates/distinct.cpp
index ebac934..6039588 100644
--- a/project2/basics/aggregates/distinct.cpp
+++ b/project2/basics/aggregates/distinct.cpp
@@ -11,7 +11,7 @@ class Distinct : public SetAggregate {
 		{
 			result.clear();
 		}
-		void pushValue(const VariableType & v) const
+		void pushValue(const VariableType & v, ExecContext *) const
 		{
 			result.insert(v);
 		}
diff --git a/project2/basics/aggregates/join.cpp b/project2/basics/aggregates/join.cpp
index 841eb9a..405c093 100644
--- a/project2/basics/aggregates/join.cpp
+++ b/project2/basics/aggregates/join.cpp
@@ -13,10 +13,10 @@ class Join : public ValueAggregate {
 			sum.clear();
 			first = true;
 		}
-		void pushValue(const VariableType & v) const
+		void pushValue(const VariableType & v, ExecContext * ec) const
 		{
 			if (!first) {
-				sum += sep().as<Glib::ustring>();
+				sum += sep(ec).as<Glib::ustring>();
 			}
 			sum += v.as<Glib::ustring>();
 			first = false;
diff --git a/project2/basics/aggregates/max.cpp b/project2/basics/aggregates/max.cpp
index ef904ed..6304647 100644
--- a/project2/basics/aggregates/max.cpp
+++ b/project2/basics/aggregates/max.cpp
@@ -8,7 +8,7 @@ class Max : public ValueAggregate {
 		{
 			result = VariableType();
 		}
-		void pushValue(const VariableType & v) const
+		void pushValue(const VariableType & v, ExecContext *) const
 		{
 			if (result < v) {
 				result = v;
diff --git a/project2/basics/aggregates/min.cpp b/project2/basics/aggregates/min.cpp
index ee0bf3d..75b0b87 100644
--- a/project2/basics/aggregates/min.cpp
+++ b/project2/basics/aggregates/min.cpp
@@ -12,7 +12,7 @@ class Min : public ValueAggregate {
 			result = VariableType();
 			first = true;
 		}
-		void pushValue(const VariableType & v) const
+		void pushValue(const VariableType & v, ExecContext *) const
 		{
 			if (first || v < result) {
 				result = v;
diff --git a/project2/basics/aggregates/sum.cpp b/project2/basics/aggregates/sum.cpp
index 9bc1120..68a9cd4 100644
--- a/project2/basics/aggregates/sum.cpp
+++ b/project2/basics/aggregates/sum.cpp
@@ -11,7 +11,7 @@ class Sum : public ValueAggregate {
 		{
 			sum = 0;
 		}
-		void pushValue(const VariableType & v) const
+		void pushValue(const VariableType & v, ExecContext *) const
 		{
 			sum += v.as<double>();
 		}
diff --git a/project2/basics/functions/dates.cpp b/project2/basics/functions/dates.cpp
index f2dcb20..b19b921 100644
--- a/project2/basics/functions/dates.cpp
+++ b/project2/basics/functions/dates.cpp
@@ -16,10 +16,10 @@ class ParseDate : public VariableImpl {
 			format(e, "format")
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
-			const char * s = string();
-			const char * f = format();
+			const char * s = string(ec);
+			const char * f = format(ec);
 			struct tm tm;
 			memset(&tm, 0, sizeof(struct tm));
 			mktime(&tm);
@@ -27,7 +27,7 @@ class ParseDate : public VariableImpl {
 			if (!e || *e) {
 				Logger()->messagef(LOG_ERR, "%s: check failed (parse) for '%s' against '%s' (remaining chars='%s')",
 						__PRETTY_FUNCTION__, s, f, e);
-				throw DateParseError(string(), format());
+				throw DateParseError(string(ec), format(ec));
 			}
 			return boost::posix_time::ptime(boost::posix_time::ptime_from_tm(tm));
 		}
@@ -44,13 +44,13 @@ class FormatDate : public VariableImpl {
 			format(e, "format")
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			std::stringstream ss;
 			boost::date_time::time_facet<boost::posix_time::ptime, char> * ft = new boost::date_time::time_facet<boost::posix_time::ptime, char>();
 			ss.imbue(std::locale(ss.getloc(), ft));
-			ft->format(format());
-			ss << boost::get<boost::posix_time::ptime>(date());
+			ft->format(format(ec));
+			ss << boost::get<boost::posix_time::ptime>(date(ec));
 			return ss.str();
 		}
 	private:
@@ -66,9 +66,9 @@ class AdjustDate : public VariableImpl {
 			offset(e, "offset")
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
-			return boost::get<boost::posix_time::ptime>(date()) + boost::posix_time::duration_from_string(offset());
+			return boost::get<boost::posix_time::ptime>(date(ec)) + boost::posix_time::duration_from_string(offset(ec));
 		}
 	private:
 		Variable date;
@@ -81,7 +81,7 @@ class CurrentDate : public VariableImpl {
 		CurrentDate(ScriptNodePtr)
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext *) const
 		{
 			return boost::posix_time::microsec_clock::universal_time();
 		}
diff --git a/project2/basics/functions/strings.cpp b/project2/basics/functions/strings.cpp
index d4ba7b7..735a781 100644
--- a/project2/basics/functions/strings.cpp
+++ b/project2/basics/functions/strings.cpp
@@ -10,9 +10,9 @@ class Trim : public VariableImpl {
 			string(e, "string")
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
-			Glib::ustring str = string();
+			Glib::ustring str = string(ec);
 			Glib::ustring::const_iterator b = str.begin();
 			while (Glib::Unicode::isspace(*b)) ++b;
 			Glib::ustring::const_iterator e = str.end();
diff --git a/project2/basics/pch.hpp b/project2/basics/pch.hpp
index d52b275..0421cfb 100644
--- a/project2/basics/pch.hpp
+++ b/project2/basics/pch.hpp
@@ -4,7 +4,6 @@
 
 #include <aggregate.h>
 #include <algorithm>
-#include <appEngine.h>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/bind.hpp>
 #include <boost/date_time.hpp>
diff --git a/project2/basics/tests/compoundTest.cpp b/project2/basics/tests/compoundTest.cpp
index b361db5..119026e 100644
--- a/project2/basics/tests/compoundTest.cpp
+++ b/project2/basics/tests/compoundTest.cpp
@@ -20,11 +20,11 @@ class All : public CompoundTest {
 			SourceObject(s),
 			CompoundTest(s) {
 		}
-		bool passes() const {
+		bool passes(ExecContext * ec) const {
 			if (tests.empty()) {
 				throw NoTestsToPerform();
 			}
-			return (std::find_if(tests.begin(), tests.end(), !boost::bind(&Test::passes, _1)) == tests.end());
+			return (std::find_if(tests.begin(), tests.end(), !boost::bind(&Test::passes, _1, ec)) == tests.end());
 		}
 };
 DECLARE_LOADER("all", All);
@@ -35,11 +35,11 @@ class Any : public CompoundTest {
 			SourceObject(s),
 			CompoundTest(s) {
 		}
-		bool passes() const {
+		bool passes(ExecContext * ec) const {
 			if (tests.empty()) {
 				throw NoTestsToPerform();
 			}
-			return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) != tests.end());
+			return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1, ec)) != tests.end());
 		}
 };
 DECLARE_LOADER("any", Any);
@@ -50,11 +50,11 @@ class None : public CompoundTest {
 			SourceObject(s),
 			CompoundTest(s) {
 		}
-		bool passes() const {
+		bool passes(ExecContext * ec) const {
 			if (tests.empty()) {
 				throw NoTestsToPerform();
 			}
-			return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) == tests.end());
+			return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1, ec)) == tests.end());
 		}
 };
 DECLARE_LOADER("none", None);
@@ -67,11 +67,11 @@ class Not : public Test {
 		{
 			s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&test));
 		}
-		bool passes() const {
+		bool passes(ExecContext * ec) const {
 			if (!test) {
 				throw NoTestsToPerform();
 			}
-			return !test->passes();
+			return !test->passes(ec);
 		}
 	private:
 		TestPtr test;
diff --git a/project2/basics/tests/equals.cpp b/project2/basics/tests/equals.cpp
index ba8c695..6c7a74f 100644
--- a/project2/basics/tests/equals.cpp
+++ b/project2/basics/tests/equals.cpp
@@ -13,8 +13,8 @@ class Equals : public Test {
 		{
 		}
 
-		bool passes() const {
-			return (a() == b());
+		bool passes(ExecContext * ec) const {
+			return (a(ec) == b(ec));
 		}
 		
 	private:
diff --git a/project2/basics/tests/isdistinct.cpp b/project2/basics/tests/isdistinct.cpp
index ab7bf1b..303f88d 100644
--- a/project2/basics/tests/isdistinct.cpp
+++ b/project2/basics/tests/isdistinct.cpp
@@ -17,13 +17,13 @@ class IsDistinct : public Test, IHaveParameters {
 		
 		void loadComplete(const CommonObjects *)
 		{
-			findComponent(scope())->registerFor(RowProcessor::Complete, boost::bind(&IsDistinct::reset, this));
+			findComponent(scope(NULL))->registerFor(RowProcessor::Complete, boost::bind(&IsDistinct::reset, this));
 		}
 
-		bool passes() const {
+		bool passes(ExecContext * ec) const {
 			Vars row;
 			BOOST_FOREACH(const Parameters::value_type & p, parameters) {
-				row.push_back(p.second());
+				row.push_back(p.second(ec));
 			}
 			return previous.insert(row).second;
 		}
diff --git a/project2/basics/tests/isuniq.cpp b/project2/basics/tests/isuniq.cpp
index c14ea84..e33aba8 100644
--- a/project2/basics/tests/isuniq.cpp
+++ b/project2/basics/tests/isuniq.cpp
@@ -17,21 +17,21 @@ class IsUniq : public Test, IHaveParameters {
 
 		void loadComplete(const CommonObjects *)
 		{
-			findComponent(scope())->registerFor(RowProcessor::Complete, boost::bind(&IsUniq::reset, this));
+			findComponent(scope(NULL))->registerFor(RowProcessor::Complete, boost::bind(&IsUniq::reset, this));
 		}
 
-		bool passes() const {
+		bool passes(ExecContext * ec) const {
 			if (previous.size() > 0) {
 				Vars row;
 				BOOST_FOREACH(const Parameters::value_type & p, parameters) {
-					row.push_back(p.second());
+					row.push_back(p.second(ec));
 				}
 				std::swap(row, previous);
 				return row != previous;
 			}
 			else {
 				BOOST_FOREACH(const Parameters::value_type & p, parameters) {
-					previous.push_back(p.second());
+					previous.push_back(p.second(ec));
 				}
 				return true;
 			}
diff --git a/project2/basics/tests/validDateCheck.cpp b/project2/basics/tests/validDateCheck.cpp
index 8dffd9d..b1ab5a3 100644
--- a/project2/basics/tests/validDateCheck.cpp
+++ b/project2/basics/tests/validDateCheck.cpp
@@ -13,7 +13,7 @@ class ValidDateTest : public Test {
 			Test(p),
 			applyTo(p, "apply-to"),
 			format(p, "format"),
-			warnLev(p->value("warn", true).as<bool>() ? LOG_WARNING : LOG_INFO)
+			warnLev(p->value("warn", true, NULL).as<bool>() ? LOG_WARNING : LOG_INFO)
 		{
 		}
 
@@ -22,13 +22,13 @@ class ValidDateTest : public Test {
 		}
 
 		bool
-		passes() const
+		passes(ExecContext * ec) const
 		{
 			struct tm tm, ftm;
 			memset(&tm, 0, sizeof(struct tm));
 			mktime(&tm);
-			const char * at = applyTo();
-			const char * f = format();
+			const char * at = applyTo(ec);
+			const char * f = format(ec);
 			const char * s = strptime(at, f, &tm);
 			if (!s || *s) {
 				Logger()->messagef(warnLev, "%s: check failed (parse) for '%s' against '%s'",
diff --git a/project2/cgi/Jamfile.jam b/project2/cgi/Jamfile.jam
index cf6e55c..8da2f11 100644
--- a/project2/cgi/Jamfile.jam
+++ b/project2/cgi/Jamfile.jam
@@ -57,4 +57,3 @@ exe testCgi :
 	<library>p2cgicommon
 	<include>../../libmisc
 	;
-
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp
index 75bc004..2a82595 100644
--- a/project2/cgi/cgiAppEngine.cpp
+++ b/project2/cgi/cgiAppEngine.cpp
@@ -3,45 +3,83 @@
 #include "cgiResult.h"
 #include <cgicc/Cgicc.h>
 #include <cgicc/HTTPHeader.h>
-#include "cgiEnvironment.h"
+#include <cgicc/HTTPStatusHeader.h>
+#include "cgiRequestContext.h"
 #include "iterate.h"
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
 #include "ostreamWrapper.h"
 #include "scopeObject.h"
+#include "logger.h"
 #include <boost/date_time/microsec_time_clock.hpp>
 #include <boost/uuid/uuid_io.hpp>
-#include <boost/uuid/uuid_generators.hpp>
 #include <boost/lexical_cast.hpp>
+#include <glibmm/exception.h>
+#include <cxxabi.h>
 
-const std::string SESSIONID = "sessionID";
 typedef boost::uuids::uuid SIDKey;
 typedef std::string SValue;
 
 SimpleMessageException(UnknownDomain);
 
-CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) :
-	_env(e),
-	sessionsContainer(SessionContainerLoader::getFor(e->sessionModule)->create()),
-	IO(io),
-	outputCachingActive(false)
-{
-	try {
-		cursession = sessionsContainer->GetSession(boost::uuids::string_generator()(e->getCookieValue(SESSIONID)));
-	}
-	catch (const NoSuchCookie &) {
-		cursession = sessionsContainer->GetSession(boost::uuids::uuid());
-	}
-}
+std::string CgiApplicationEngine::dumpdatadoc;
+Glib::ustring CgiApplicationEngine::errorContentType;
+Glib::ustring CgiApplicationEngine::errorTransformStyle;
+std::string CgiApplicationEngine::defaultPresent;
+std::string CgiApplicationEngine::transformContentType;
+std::string CgiApplicationEngine::transformTargetType;
+std::string CgiApplicationEngine::presentRoot;
+std::string CgiApplicationEngine::requestRoot;
+std::string CgiApplicationEngine::errorPresentRoot;
+std::string CgiApplicationEngine::notFoundPresent;
+std::string CgiApplicationEngine::onErrorPresent;
+std::string CgiApplicationEngine::defaultPresenter;
+SessionContainerPtr CgiApplicationEngine::sessionsContainer;
+std::string CgiApplicationEngine::sessionCookie;
+boost::shared_ptr<RouterLoader> CgiApplicationEngine::router;
+boost::intrusive_ptr<HostnamePlatformIdentifier> CgiApplicationEngine::hpi;
 
-CgiApplicationEngine::~CgiApplicationEngine()
+DECLARE_OPTIONS(CgiApplicationEngine, "Project2 CGI options")
+("cgi.defaultPresenter", Options::value(&defaultPresenter, "xml"),
+ "The default engine for formatting presentations")
+("cgi.transformContentType", Options::value(&transformContentType, "text/xml-xslt"),
+ "The content type specified to enable standard internal transformations")
+("cgi.transformTargetType", Options::value(&transformTargetType, "htmldocument"),
+ "The transform target type used in standard internal transformations")
+("cgi.defaultPresent", Options::value(&defaultPresent, "index"),
+ "The present script to use when no other is specified")
+("cgi.presentRoot", Options::value(&presentRoot, "present"),
+ "The folder in which to find presentation scripts")
+("cgi.requestRoot", Options::value(&requestRoot, "request"),
+ "The folder in which to find request scripts")
+("cgi.errorPresentRoot", Options::value(&errorPresentRoot, "error"),
+ "The folder in which to find presentation scripts for error handling")
+("cgi.errorContentType", Options::value(&errorContentType, "application/xml"),
+ "The Content-Type to use in HTTP headers in event of an error")
+("cgi.errorTransformStyle", Options::value(&errorTransformStyle),
+ "The xml-stylesheet to specify in the data document in event of an error")
+("cgi.notFoundPresent", Options::value(&notFoundPresent),
+ "The present script to use when the requested script does not exist")
+("cgi.onErrorPresent", Options::value(&onErrorPresent),
+ "The present script to use when the requested script (or child) fails")
+("cgi.dumpDataDoc", Options::value(&dumpdatadoc),
+ "Write a copy of the data document before sending it to the web server")
+("cgi.sessionModule", Options::function([](const VariableType & m) { sessionsContainer = SessionContainerLoader::createNew(m); }, "xml"),
+ "The module with which to implement session management")
+("cgi.sessionCookie", Options::value(&sessionCookie, "sessionID"),
+ "The name of the cookie for storing session IDs")
+("cgi.hostRegex", (hpi = new HostnamePlatformIdentifier()),
+ "Regular expression used to define a hostname -> platform association")
+("cgi.router", Options::function([](const VariableType & r) { router = RouterLoader::getFor(r); }, "simple"),
+ "Implemenation of router model to map request paths to scripts")
+END_OPTIONS(CgiApplicationEngine);
+
+CgiApplicationEngine::CgiApplicationEngine()
 {
 }
 
-const CgiEnvironment *
-CgiApplicationEngine::env() const
+CgiApplicationEngine::~CgiApplicationEngine()
 {
-	return _env;
 }
 
 TransformSourcePtr
@@ -61,51 +99,51 @@ finalTransformSource(TransformSourcePtr ts)
 }
 
 void
-CgiApplicationEngine::process() const
+CgiApplicationEngine::processRun(std::ostream & IO, CgiRequestContext * crc) const
 {
-	bool sessionEmpty = cursession->Empty();
-	startTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
+	bool sessionEmpty = crc->getSession()->Empty();
+	crc->startTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
 	bool triedNotFound = false;
 	bool triedOnError = false;
 	NextStage currentStage = NextStage(new InitialStage());
 	do {
 		try {
- 			currentStage = currentStage.get<0>()->run();
+ 			currentStage = currentStage.get<0>()->run(crc);
 		}
 		catch (const CheckHost::CheckFailure & cf) {
-			currentStage = NextStage(new PresentStage(ScriptReader::resolveScript(_env->presentRoot, cf.failedCheck->present(), false)));
+			currentStage = NextStage(new PresentStage(ScriptReader::resolveScript(presentRoot, cf.failedCheck->present(crc), false), crc));
 		}
 		catch (const ScriptNotFound & nf) {
-			if (_env->notFoundPresent.empty() || triedNotFound) {
+			if (notFoundPresent.empty() || triedNotFound) {
 				currentStage = NextStage(new DefaultNotFoundStage(nf));
 			}
 			else {
 				triedNotFound = true;
-				currentStage = NextStage(new CustomNotFoundStage(nf, ScriptReader::resolveScript(_env->errorPresentRoot, _env->notFoundPresent, false)));
+				currentStage = NextStage(new CustomNotFoundStage(nf, ScriptReader::resolveScript(errorPresentRoot, notFoundPresent, false), crc));
 			}
 		}
 		catch (const std::exception & ex) {
-			if (_env->onErrorPresent.empty() || triedOnError) {
-				currentStage = NextStage(new DefaultErrorStage(ex));
+			if (onErrorPresent.empty() || triedOnError) {
+				currentStage = NextStage(new DefaultErrorStage(ex, crc));
 			}
 			else {
 				triedNotFound = true;
-				currentStage = NextStage(new CustomErrorStage(ex, ScriptReader::resolveScript(_env->errorPresentRoot, _env->onErrorPresent, false)));
+				currentStage = NextStage(new CustomErrorStage(ex, ScriptReader::resolveScript(errorPresentRoot, onErrorPresent, false), crc));
 			}
 		}
 	} while (currentStage.get<0>());
-	endTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
+	crc->endTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time();
 	ResponseStagePtr rs = currentStage.get<1>();
-	outputCachingActive = !rs->caches.empty();
+	bool outputCachingActive = !rs->caches.empty();
 	if (const MultiRowSetPresenter * p = currentStage.get<3>().get()) {
-		addAppData(p, rs->outputOptions);
-		addEnvData(p, rs->outputOptions);
+		addAppData(p, rs->outputOptions, crc, outputCachingActive);
+		addEnvData(p, rs->outputOptions, crc, outputCachingActive);
 	}
-	HttpHeaderPtr header = rs->getHeader();
-	if (!sessionEmpty || !cursession->Empty()) {
-		sessionsContainer->SaveSession(cursession);
-		header->setCookie(cgicc::HTTPCookie(SESSIONID, boost::lexical_cast<std::string>(cursession->ID()), "Session ID",
-					_env->getServerName().substr(_env->getServerName().find(".")), SessionContainer::sessionTimeOut, "/", false));
+	HttpHeaderPtr header = rs->getHeader(crc);
+	if (!sessionEmpty || !crc->getSession()->Empty()) {
+		sessionsContainer->SaveSession(crc->getSession());
+		header->setCookie(cgicc::HTTPCookie(sessionCookie, boost::lexical_cast<std::string>(crc->getSession()->ID()), "Session ID",
+					crc->getServerName().substr(crc->getServerName().find(".")), SessionContainer::sessionTimeOut, "/", false));
 	}
 	if (TransformSourcePtr ts = currentStage.get<2>()) {
 		TransformSourcePtr final = finalTransformSource(ts);
@@ -113,10 +151,10 @@ CgiApplicationEngine::process() const
 		boost::shared_ptr<std::fstream> ddd;
 		ostreamWrapper * osw = NULL;
 		ScopeObject removeDdd([ts, &osw] { if (osw) { ts->removeTarget(osw); } });
-		if (!_env->dumpdatadoc.empty()) {
-			ddd = boost::shared_ptr<std::fstream>(new std::fstream(_env->dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out));
+		if (!dumpdatadoc.empty()) {
+			ddd = boost::shared_ptr<std::fstream>(new std::fstream(dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out));
 			if (ddd->good()) {
-				ts->addTarget(osw = new ostreamWrapper(*ddd));
+				ts->addTarget(osw = new ostreamWrapper(*ddd), crc, NULL);
 			}
 			else {
 				ddd.reset();
@@ -124,23 +162,23 @@ CgiApplicationEngine::process() const
 		}
 		if (outputCachingActive) {
 			BOOST_FOREACH(const PresenterCachePtr & p, rs->caches) {
-				final->addTarget(p, NULL);
+				final->addTarget(p, crc, NULL);
 			}
-			ts->doTransforms();
+			ts->doTransforms(crc);
 			BOOST_FOREACH(const PresenterCachePtr & p, rs->caches) {
 				p->flushCache();
 			}
-			if (rs->caches.front()->check(0)) {
+			if (rs->caches.front()->check(0, crc)) {
 				ScopeObject emptyFinal([rs] { rs->caches.front()->clearTargets(); });
 				rs->caches.front()->addTarget(new CgiResult(header, IO,
-							rs && rs->outputOptions ? rs->outputOptions->Encoding().as<std::string>() : OutputOptions::encoding), NULL);
-				rs->caches.front()->doTransforms();
+							rs && rs->outputOptions ? rs->outputOptions->Encoding(crc).as<std::string>() : OutputOptions::encoding), crc, NULL);
+				rs->caches.front()->doTransforms(crc);
 				return;
 			}
 		}
 		final->addTarget(new CgiResult(header, IO,
-					rs && rs->outputOptions ? rs->outputOptions->Encoding().as<std::string>() : OutputOptions::encoding), NULL);
-		ts->doTransforms();
+					rs && rs->outputOptions ? rs->outputOptions->Encoding(crc).as<std::string>() : OutputOptions::encoding), crc, NULL);
+		ts->doTransforms(crc);
 	}
 	else {
 		header->render(IO);
@@ -151,44 +189,38 @@ CgiApplicationEngine::Stage::~Stage()
 {
 }
 
-const CgiEnvironment *
-CgiApplicationEngine::Stage::env() const
-{
-	return dynamic_cast<const CgiEnvironment *>(Environment::getCurrent());
-}
-
 void
-CgiApplicationEngine::addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o) const
+CgiApplicationEngine::addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext * crc, bool outputCachingActive) const
 {
-	if (!o || o->Environment()) {
+	if (!o || o->Environment(crc)) {
 		// Environment set up by web server
 		p->addNewRowSet("environment", Scripts::scriptNamespacePrefix);
 		// Server stuff
-		addEnvToPresenter(p, "servername", &cgicc::CgiEnvironment::getServerName);
-		addEnvToPresenter(p, "serversoftware", &cgicc::CgiEnvironment::getServerSoftware);
-		addEnvToPresenter(p, "serverprotocol", &cgicc::CgiEnvironment::getServerProtocol);
-		addEnvToPresenter(p, "serverport", &cgicc::CgiEnvironment::getServerPort);
-		addEnvToPresenter(p, "serverhttps", &cgicc::CgiEnvironment::usingHTTPS);
+		addEnvToPresenter(p, "servername", &cgicc::CgiEnvironment::getServerName, crc);
+		addEnvToPresenter(p, "serversoftware", &cgicc::CgiEnvironment::getServerSoftware, crc);
+		addEnvToPresenter(p, "serverprotocol", &cgicc::CgiEnvironment::getServerProtocol, crc);
+		addEnvToPresenter(p, "serverport", &cgicc::CgiEnvironment::getServerPort, crc);
+		addEnvToPresenter(p, "serverhttps", &cgicc::CgiEnvironment::usingHTTPS, crc);
 		// Request stuff
 		if (!outputCachingActive) {
-			addEnvToPresenter(p, "referrer", &cgicc::CgiEnvironment::getReferrer);
-			addEnvToPresenter(p, "querystring", &cgicc::CgiEnvironment::getQueryString);
+			addEnvToPresenter(p, "referrer", &cgicc::CgiEnvironment::getReferrer, crc);
+			addEnvToPresenter(p, "querystring", &cgicc::CgiEnvironment::getQueryString, crc);
 		}
 		p->finishRowSet();
 	}
 	
-	if (!o || o->URL()) {
+	if (!o || o->URL(crc)) {
 		// URL elements
 		p->addNewRowSet("uriElems", Scripts::scriptNamespacePrefix);
-		p->addAttribute("full", _env->getRedirectURL());
-		_env->router->present(p);
+		p->addAttribute("full", crc->getRedirectURL());
+		crc->router->present(p);
 		p->finishRowSet();
 	}
 
-	if (!o || o->Parameters()) {
+	if (!o || o->Parameters(crc)) {
 		// Parameters
 		p->addNewRowSet("params", Scripts::scriptNamespacePrefix);
-		BOOST_FOREACH(cgicc::FormEntry fe, _env->cgi->getElements()) {
+		BOOST_FOREACH(cgicc::FormEntry fe, crc->cgi.getElements()) {
 			p->addNamedValue(fe.getName(), fe.getValue());
 		}
 		p->finishRowSet();
@@ -202,34 +234,78 @@ CgiApplicationEngine::addVarToPresenter(const MultiRowSetPresenter * p, const Gl
 }
 
 void
-CgiApplicationEngine::addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o) const
+CgiApplicationEngine::addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext * crc, bool outputCachingActive) const
 {
-	if (!o || o->Core()) {
-		addCoreAppData(p);
+	if (!o || o->Core(crc)) {
+		crc->addContextData(p);
 	}
-	if (!outputCachingActive && (!cursession->Empty()) && (!o || o->Session())) {
+	if (!outputCachingActive && (!crc->getSession()->Empty()) && (!o || o->Session(crc))) {
 		// Sessions variables
 		p->addNewRowSet("session", Scripts::scriptNamespacePrefix);
-		p->addAttribute("id", boost::lexical_cast<Glib::ustring>(cursession->ID()));
-		cursession->ForeachValue(boost::bind(&CgiApplicationEngine::addVarToPresenter, this, p, _1, _2));
+		p->addAttribute("id", boost::lexical_cast<Glib::ustring>(crc->getSession()->ID()));
+		crc->getSession()->ForeachValue(boost::bind(&CgiApplicationEngine::addVarToPresenter, this, p, _1, _2));
 		p->finishRowSet();
 	}
 
-	if (!outputCachingActive && (!o || o->Timing())) {
+	if (!outputCachingActive && (!o || o->Timing(crc))) {
 		// Timing info
 		p->addNewRowSet("timing", Scripts::scriptNamespacePrefix);
-		p->addAttribute("start", startTime);
-		if (!endTime.is_not_a_date_time()) {
-			p->addAttribute("end", endTime);
-			p->addAttribute("duration", (endTime - startTime).total_milliseconds());
+		p->addAttribute("start", crc->startTime);
+		if (!crc->endTime.is_not_a_date_time()) {
+			p->addAttribute("end", crc->endTime);
+			p->addAttribute("duration", (crc->endTime - crc->startTime).total_milliseconds());
 		}
 		p->finishRowSet();
 	}
 }
 
-SessionPtr
-CgiApplicationEngine::session() const
+const char *
+what(const Glib::Exception & e)
+{
+	return e.what().c_str();
+}
+const char *
+what(const std::exception & e)
 {
-	return cursession;
+	return e.what();
+}
+template <typename E>
+void
+doExceptionReporting(const E & e, std::ostream & IO)
+{
+	char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL);
+	Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, what(e));
+	cgicc::HTTPStatusHeader header(500, e.what());
+	header.render(IO);
+	IO << "Kaboom!" << std::endl
+		<< std::endl
+		<< buf << std::endl
+		<< "what '" << e.what() << "'" << std::endl;
+	free(buf);
+}
+
+void
+CgiApplicationEngine::process(std::ostream & IO, CgiRequestContext * crc) const
+{
+	try {
+		Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__);
+		processRun(IO, crc);
+		Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__);
+	}
+	catch (const std::exception & e) {
+		doExceptionReporting(e, IO);
+	}
+	catch (const Glib::Exception & e) {
+		doExceptionReporting(e, IO);
+	}
+	catch (...) {
+		Logger()->messagef(LOG_ERR, "%s: Request errored: Unknown exception", __FUNCTION__);
+		cgicc::HTTPStatusHeader header(500, "Unknown exception");
+		header.render(IO);
+		IO << "Kaboom!" << std::endl
+			<< std::endl
+			<< "Unknown exception." << std::endl;
+		throw;
+	}
 }
 
diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h
index f5f0e08..6d3cd0c 100644
--- a/project2/cgi/cgiAppEngine.h
+++ b/project2/cgi/cgiAppEngine.h
@@ -1,7 +1,6 @@
 #ifndef CGIAPPENGINE_H
 #define CGIAPPENGINE_H
 
-#include "appEngine.h"
 #include "task.h"
 #include "commonObjects.h"
 #include "taskHost.h"
@@ -15,7 +14,7 @@
 #include <boost/tuple/tuple.hpp>
 #include "cgiOutputOptions.h"
 #include "cgiHttpHeader.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include <cgicc/Cgicc.h>
 
 class Session;
@@ -24,29 +23,26 @@ namespace cgicc {
 	class CgiEnvironment;
 }
 
-class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink {
+class CgiApplicationEngine {
 	public:
 		typedef boost::shared_ptr<Project2HttpHeader> HttpHeaderPtr;
 
-		CgiApplicationEngine(const CgiEnvironment *, std::ostream &);
+		CgiApplicationEngine();
 		virtual ~CgiApplicationEngine();
 
-		void process() const;
-		const CgiEnvironment * env() const;
-		SessionPtr session() const;
-		void addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr) const;
-		void addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr) const;
+		void process(std::ostream & IO, CgiRequestContext *) const;
 
 	private:
-		const CgiEnvironment * _env;
-		mutable boost::posix_time::ptime startTime;
-		mutable boost::posix_time::ptime endTime;
-		SessionContainerPtr sessionsContainer;
+		void processRun(std::ostream & IO, CgiRequestContext *) const;
+		void addAppData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext *, bool) const;
+		void addEnvData(const MultiRowSetPresenter * p, OutputOptionsPtr o, CgiRequestContext *, bool) const;
+
 		// Helpers
+		//
 		void addVarToPresenter(const MultiRowSetPresenter * p, const Glib::ustring & name, const VariableType &) const;
 		template <class X, class Y>
-		void addEnvToPresenter(const MultiRowSetPresenter * p, const char * name, X (Y::*getter)() const) const {
-			addVarToPresenter(p, name, (_env->cgi->getEnvironment().*getter)());
+		void addEnvToPresenter(const MultiRowSetPresenter * p, const char * name, X (Y::*getter)() const, CgiRequestContext * crc) const {
+			addVarToPresenter(p, name, (crc->cgi.getEnvironment().*getter)());
 		}
 
 	public:
@@ -59,9 +55,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 		class Stage : public virtual IntrusivePtrBase {
 			public:
 				virtual ~Stage() = 0;
-				virtual NextStage run() = 0;
-			protected:
-				const CgiEnvironment * env() const;
+				virtual NextStage run(CgiRequestContext *) = 0;
 		};
 
 		/// Base class for a stage that can be a response to the client
@@ -70,7 +64,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 				typedef ANONORDEREDSTORAGEOF(PresenterCache) PresenterCaches;
 
 				ResponseStage(ScriptNodePtr root);
-				virtual HttpHeaderPtr getHeader() const = 0;
+				virtual HttpHeaderPtr getHeader(CgiRequestContext *) const = 0;
 
 				OutputOptionsPtr outputOptions;
 				ScriptNodePtr root;
@@ -80,7 +74,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 		/// Stage implementation used to bootstrap the iteration process based on the CGI environment
 		class InitialStage : public Stage {
 			public:
-				virtual NextStage run();
+				virtual NextStage run(CgiRequestContext *);
 		};
 		
 		/// Stage to process POST requests
@@ -88,8 +82,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 			public:
 				RequestStage(ScriptReaderPtr);
 
-				virtual NextStage run();
-				virtual HttpHeaderPtr getHeader() const;
+				virtual NextStage run(CgiRequestContext *);
+				virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
 			protected:
 				Variable present;
 				Variable redirect;
@@ -98,11 +92,11 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 		/// Stage to process GET requests and follow up RequestStages
 		class PresentStage : public virtual ResponseStage, ViewHost {
 			public:
-				PresentStage(ScriptReaderPtr);
-				MultiRowSetPresenterPtr getPresenter() const;
+				PresentStage(ScriptReaderPtr, CgiRequestContext *);
+				MultiRowSetPresenterPtr getPresenter(ExecContext *) const;
 
-				virtual NextStage run();
-				virtual HttpHeaderPtr getHeader() const;
+				virtual NextStage run(CgiRequestContext *);
+				virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
 			protected:
 				HttpHeaderPtr header;
 				LazyPointer<MultiRowSetPresenter> presenter;
@@ -113,8 +107,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 			public:
 				CacheHitStage(ScriptNodePtr, PresenterCachePtr);
 
-				virtual NextStage run();
-				virtual HttpHeaderPtr getHeader() const;
+				virtual NextStage run(CgiRequestContext *);
+				virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
 			protected:
 				PresenterCachePtr pc;
 		};
@@ -124,8 +118,8 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 			public:
 				DefaultNotFoundStage(const ScriptNotFound &);
 		
-				virtual NextStage run();
-				virtual HttpHeaderPtr getHeader() const;
+				virtual NextStage run(CgiRequestContext *);
+				virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
 			private:
 				const ScriptNotFound nf;
 				XmlPresenterPtr pres;
@@ -134,19 +128,19 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 		/// Custom not found handling stage
 		class CustomNotFoundStage : public DefaultNotFoundStage, public PresentStage {
 			public:
-				CustomNotFoundStage(const ScriptNotFound &, ScriptReaderPtr);
-				virtual NextStage run();
-				virtual HttpHeaderPtr getHeader() const;
+				CustomNotFoundStage(const ScriptNotFound &, ScriptReaderPtr, CgiRequestContext *);
+				virtual NextStage run(CgiRequestContext *);
+				virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
 		};
 
 		/// The built-in fail-safe unhandled error stage
 		class DefaultErrorStage : public virtual ResponseStage {
 			public:
-				DefaultErrorStage(const std::exception &);
+				DefaultErrorStage(const std::exception &, CgiRequestContext *);
 				~DefaultErrorStage();
 		
-				virtual NextStage run();
-				virtual HttpHeaderPtr getHeader() const;
+				virtual NextStage run(CgiRequestContext *);
+				virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
 			private:
 				char * buf;
 				std::string what;
@@ -156,15 +150,29 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink
 		/// Custom unhandled error handling stage
 		class CustomErrorStage : public DefaultErrorStage, public PresentStage {
 			public:
-				CustomErrorStage(const std::exception &, ScriptReaderPtr);
-				virtual NextStage run();
-				virtual HttpHeaderPtr getHeader() const;
+				CustomErrorStage(const std::exception &, ScriptReaderPtr, CgiRequestContext *);
+				virtual NextStage run(CgiRequestContext *);
+				virtual HttpHeaderPtr getHeader(CgiRequestContext *) const;
 		};
 
+		INITOPTIONS;
+		static boost::intrusive_ptr<HostnamePlatformIdentifier> hpi;
+		static boost::shared_ptr<RouterLoader> router;
+		static SessionContainerPtr sessionsContainer;
+		static std::string sessionCookie;
 	private:
-		SessionPtr cursession;
-		std::ostream & IO;
-		mutable bool outputCachingActive;
+		static std::string dumpdatadoc;
+		static Glib::ustring errorContentType;
+		static Glib::ustring errorTransformStyle;
+		static std::string defaultPresent;
+		static std::string transformContentType;
+		static std::string transformTargetType;
+		static std::string presentRoot;
+		static std::string requestRoot;
+		static std::string errorPresentRoot;
+		static std::string notFoundPresent;
+		static std::string onErrorPresent;
+		static std::string defaultPresenter;
 };
 
 #endif
diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp
deleted file mode 100644
index a4ed8c4..0000000
--- a/project2/cgi/cgiCommon.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <pch.hpp>
-#include "cgiCommon.h"
-#include "optionsSource.h"
-#include "logger.h"
-#include <glibmm/exception.h>
-#include <cgicc/CgiEnvironment.h>
-#include <cgicc/HTTPContentHeader.h>
-#include <cgicc/HTTPStatusHeader.h>
-#include "cgiAppEngine.h"
-#include <boost/bind.hpp>
-#include <cxxabi.h>
-
-// These are templates because some people don't inherit their
-// exceptions from std::exception like normal people (Glib)
-const char *
-what(const Glib::Exception & e)
-{
-	return e.what().c_str();
-}
-const char *
-what(const std::exception & e)
-{
-	return e.what();
-}
-template <typename E>
-void
-doExceptionReporting(const E & e, std::ostream & IO)
-{
-	char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL);
-	Logger()->messagef(LOG_ERR, "%s: Request errored: %s: %s", __FUNCTION__, buf, what(e));
-	cgicc::HTTPStatusHeader header(500, e.what());
-	header.render(IO);
-	IO << "Kaboom!" << std::endl
-		<< std::endl
-		<< buf << std::endl
-		<< "what '" << e.what() << "'" << std::endl;
-	free(buf);
-}
-
-void
-cgiServe(cgicc::CgiInput * i, CgiEnvironment * env, std::ostream & IO, const CgiEnvInput * e)
-{
-	try {
-		cgicc::Cgicc cgi(i);
-		env->setCGICC(&cgi, e);
-		OptionsSource::loadSources();
-		CgiApplicationEngine app(env, IO);
-
-		Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
-		Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__);
-		app.process();
-		Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__);
-	}
-	catch (const std::exception & e) {
-		doExceptionReporting(e, IO);
-	}
-	catch (const Glib::Exception & e) {
-		doExceptionReporting(e, IO);
-	}
-	catch (...) {
-		Logger()->messagef(LOG_ERR, "%s: Request errored: Unknown exception", __FUNCTION__);
-		cgicc::HTTPStatusHeader header(500, "Unknown exception");
-		header.render(IO);
-		IO << "Kaboom!" << std::endl
-			<< std::endl
-			<< "Unknown exception." << std::endl;
-		throw;
-	}
-}
-
diff --git a/project2/cgi/cgiCommon.h b/project2/cgi/cgiCommon.h
deleted file mode 100644
index 42a88e6..0000000
--- a/project2/cgi/cgiCommon.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <ostream>
-#include <cgicc/Cgicc.h>
-#include "cgiEnvironment.h"
-
-void cgiServe(cgicc::CgiInput * i, CgiEnvironment *, std::ostream & o, const CgiEnvInput * e);
-
diff --git a/project2/cgi/cgiContentNegotiate.cpp b/project2/cgi/cgiContentNegotiate.cpp
index a7f7557..0b6623e 100644
--- a/project2/cgi/cgiContentNegotiate.cpp
+++ b/project2/cgi/cgiContentNegotiate.cpp
@@ -6,20 +6,20 @@
 
 class ContentNegotiateLoader : public PresenterLoader {
 	public:
-		MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os) const
+		MultiRowSetPresenter * create(const ScriptNodePtr & s, const ObjectSource & os, ExecContext * const & ec) const
 		{
-			auto accept = static_cast<const CgiApplicationEngine *>(CgiApplicationEngine::getCurrent())->env()->getAccept();
+			auto accept = static_cast<const CgiRequestContext *>(ec)->getAccept();
 			typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
 			BOOST_FOREACH(auto mimetypeAndWeight, tokenizer(accept, boost::char_separator<char>(","))) {
 				const auto mimetype = mimetypeAndWeight.substr(0, mimetypeAndWeight.find(';'));
 				if (mimetype == "*/*") break;
 				BOOST_FOREACH(const auto & t, mappedTypes) {
 					if (t->Matches(mimetype)) {
-						return PresenterLoader::getFor(t->present)->create(s, os);
+						return PresenterLoader::getFor(t->present)->create(s, os, ec);
 					}
 				}
 			}
-			return PresenterLoader::getFor((*mappedTypes.begin())->present)->create(s, os);
+			return PresenterLoader::getFor((*mappedTypes.begin())->present)->create(s, os, ec);
 		}
 
 		INITOPTIONS;
diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp
deleted file mode 100644
index d2ecf77..0000000
--- a/project2/cgi/cgiEnvironment.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-#include <pch.hpp>
-#include <boost/bind.hpp>
-#include <boost/foreach.hpp>
-#include <boost/algorithm/string.hpp>
-#include "cgiEnvironment.h"
-#include "appEngine.h"
-#include "exceptions.h"
-#include <map>
-#include <cgicc/Cgicc.h>
-#include <glibmm/regex.h>
-#include <curl/curl.h>
-
-std::string CgiEnvironment::dumpdatadoc;
-Glib::ustring CgiEnvironment::errorContentType;
-Glib::ustring CgiEnvironment::errorTransformStyle;
-std::string CgiEnvironment::defaultPresent;
-std::string CgiEnvironment::transformContentType;
-std::string CgiEnvironment::transformTargetType;
-std::string CgiEnvironment::presentRoot;
-std::string CgiEnvironment::requestRoot;
-std::string CgiEnvironment::errorPresentRoot;
-std::string CgiEnvironment::notFoundPresent;
-std::string CgiEnvironment::onErrorPresent;
-std::string CgiEnvironment::defaultPresenter;
-std::string CgiEnvironment::sessionModule;
-std::string CgiEnvironment::routerType;
-boost::intrusive_ptr<HostnamePlatformIdentifier> CgiEnvironment::hpi;
-
-DECLARE_OPTIONS(CgiEnvironment, "Project2 CGI options")
-("cgi.defaultPresenter", Options::value(&defaultPresenter, "xml"),
- "The default engine for formatting presentations")
-("cgi.transformContentType", Options::value(&transformContentType, "text/xml-xslt"),
- "The content type specified to enable standard internal transformations")
-("cgi.transformTargetType", Options::value(&transformTargetType, "htmldocument"),
- "The transform target type used in standard internal transformations")
-("cgi.defaultPresent", Options::value(&defaultPresent, "index"),
- "The present script to use when no other is specified")
-("cgi.presentRoot", Options::value(&presentRoot, "present"),
- "The folder in which to find presentation scripts")
-("cgi.requestRoot", Options::value(&requestRoot, "request"),
- "The folder in which to find request scripts")
-("cgi.errorPresentRoot", Options::value(&errorPresentRoot, "error"),
- "The folder in which to find presentation scripts for error handling")
-("cgi.errorContentType", Options::value(&errorContentType, "application/xml"),
- "The Content-Type to use in HTTP headers in event of an error")
-("cgi.errorTransformStyle", Options::value(&errorTransformStyle),
- "The xml-stylesheet to specify in the data document in event of an error")
-("cgi.notFoundPresent", Options::value(&notFoundPresent),
- "The present script to use when the requested script does not exist")
-("cgi.onErrorPresent", Options::value(&onErrorPresent),
- "The present script to use when the requested script (or child) fails")
-("cgi.dumpDataDoc", Options::value(&dumpdatadoc),
- "Write a copy of the data document before sending it to the web server")
-("cgi.sessionModule", Options::value(&sessionModule, "xml"),
- "The module with which to implement session management")
-("cgi.hostRegex", (hpi = new HostnamePlatformIdentifier()),
- "Regular expression used to define a hostname -> platform association")
-("cgi.router", Options::value(&routerType, "simple"),
- "Implemenation of router model to map request paths to scripts")
-END_OPTIONS(CgiEnvironment);
-
-CgiEnvironment::CgiEnvironment() :
-	cgi(NULL),
-	cgienv(NULL)
-{
-}
-
-CgiEnvironment::~CgiEnvironment()
-{
-}
-
-void
-CgiEnvironment::setCGICC(const cgicc::Cgicc * c, const CgiEnvInput * e)
-{
-	cgi = c;
-	cgienv = e;
-	router = boost::bind(&GenLoader<Router, const std::string &>::createNew, boost::cref(routerType), getRedirectURL());
-}
-
-std::string
-CgiEnvironment::getCookieValue(const std::string & name) const
-{
-	BOOST_FOREACH(const cgicc::HTTPCookie & c, cgi->getEnvironment().getCookieList()) {
-		if (c.getName() == name) {
-			return c.getValue();
-		}
-	}
-	throw NoSuchCookie(name);
-}
-
-std::string
-CgiEnvironment::getRequestMethod() const
-{
-	return cgi->getEnvironment().getRequestMethod();
-}
-
-std::string
-CgiEnvironment::getRedirectURL() const
-{
-	return cgi->getEnvironment().getRedirectURL();
-}
-
-std::string
-CgiEnvironment::getServerName() const
-{
-	return cgi->getEnvironment().getServerName();
-}
-
-std::string
-CgiEnvironment::getAccept() const
-{
-	return cgi->getEnvironment().getAccept();
-}
-
-const Glib::ustring &
-CgiEnvironment::platform() const
-{
-	return hpi->derivedPlatform();
-}
-
-CgiEnvironment::ETags
-CgiEnvironment::getRequestETags() const
-{
-	const std::string e = cgienv->getenv("HTTP_IF_NONE_MATCH");
-	ETags etags;
-	boost::split(etags, e, boost::is_any_of(" ,"), boost::algorithm::token_compress_on);
-	return etags;
-}
-
-time_t
-CgiEnvironment::getRequestModifiedSince() const
-{
-	return curl_getdate(cgienv->getenv("HTTP_IF_MODIFIED_SINCE").c_str(), NULL);
-}
-
-Glib::ustring
-CgiEnvironment::getParamUri(VariableType p) const
-{
-	return router->routeParameter(p);
-}
-
-unsigned int
-CgiEnvironment::getParamUriCount() const
-{
-	return router->parameterCount();
-}
-
-void
-CgiEnvironment::applyAllParameters(const boost::function<void (const std::string &, const std::string &)> & func) const
-{
-	BOOST_FOREACH(const auto & f, cgi->getElements()) {
-		func(f.getName(), f.getValue());
-	}
-}
-
-Glib::ustring
-CgiEnvironment::getParamQuery(const std::string & p) const
-{
-	cgicc::const_form_iterator i = cgi->getElement(p);
-	if (i == cgi->getElements().end()) {
-		throw ParamNotFound(p);
-	}
-	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;
-		platform = NULL;
-	}
-}
-
-bool
-HostnamePlatformIdentifier::paramRequired() const
-{
-	return true;
-}
-
-void
-HostnamePlatformIdentifier::consume(const Glib::ustring & p, const VariableType & 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
deleted file mode 100644
index e9de59d..0000000
--- a/project2/cgi/cgiEnvironment.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef ENVPROC_H
-#define ENVPROC_H
-
-#include <string>
-#include <vector>
-#include "environment.h"
-#include "cgiEnvInput.h"
-#include "cgiRouter.h"
-#include <cgicc/CgiEnvironment.h>
-#include <lazyPointer.h>
-
-SimpleMessageException(NoSuchCookie);
-
-namespace cgicc {
-	class Cgicc;
-}
-
-class HostnamePlatformIdentifier : public Options::Target {
-	public:
-		HostnamePlatformIdentifier();
-		virtual ~HostnamePlatformIdentifier();
-		void reset() const;
-		bool paramRequired() const;
-		void consume(const Glib::ustring &, const VariableType &) const;
-		const Glib::ustring & derivedPlatform() const;
-	private:
-		mutable Glib::ustring * platform;
-};
-
-class CgiEnvironment : public Environment {
-	public:
-		typedef std::string ETag;
-		typedef std::vector<ETag> ETags;
-
-		CgiEnvironment();
-		virtual ~CgiEnvironment();
-
-		Glib::ustring getParamUri(VariableType idx) const;
-		unsigned int getParamUriCount() const;
-		Glib::ustring getParamQuery(const std::string & idx) const;
-		void applyAllParameters(const boost::function<void (const std::string &, const std::string &)> &) const;
-		std::string getServerName() const;
-		std::string getRedirectURL() const;
-		std::string getRequestMethod() const;
-		std::string getAccept() const;
-		ETags getRequestETags() const;
-		time_t getRequestModifiedSince() const;
-		std::string getCookieValue(const std::string & name) const;
-
-		void setCGICC(const cgicc::Cgicc *, const CgiEnvInput * cgienv);
-		const cgicc::Cgicc * cgi;
-		const CgiEnvInput * cgienv;
-
-	private:
-		const Glib::ustring & platform() const;
-
-	public:
-		INITOPTIONS;
-		static boost::intrusive_ptr<HostnamePlatformIdentifier> hpi;
-		static std::string dumpdatadoc;
-		static Glib::ustring errorContentType;
-		static Glib::ustring errorTransformStyle;
-		static std::string defaultPresent;
-		static std::string transformContentType;
-		static std::string transformTargetType;
-		static std::string presentRoot;
-		static std::string requestRoot;
-		static std::string errorPresentRoot;
-		static std::string notFoundPresent;
-		static std::string onErrorPresent;
-		static std::string defaultPresenter;
-		static std::string sessionModule;
-		static std::string routerType;
-		typedef LazyPointer<const Router> RouterPtr;
-		RouterPtr router;
-};
-
-#endif
diff --git a/project2/cgi/cgiProgRouter.cpp b/project2/cgi/cgiProgRouter.cpp
index e8ae15d..8fce50d 100644
--- a/project2/cgi/cgiProgRouter.cpp
+++ b/project2/cgi/cgiProgRouter.cpp
@@ -1,7 +1,10 @@
 #include <pch.hpp>
 #include <boost/foreach.hpp>
+#include <boost/filesystem/path.hpp>
 #include <boost/algorithm/string/predicate.hpp>
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
+#include "commonObjects.h"
+#include "rowProcessor.h"
 #include "presenter.h"
 #include "safeMapFind.h"
 #include "scriptStorage.h"
@@ -82,8 +85,8 @@ class RoutingTable {
 			public:
 				Route(ScriptNodePtr s) :
 					SourceObject(s),
-					present(s->value("present").as<std::string>()),
-					path(s->value("path").as<std::string>())
+					present(s->value("present", NULL).as<std::string>()),
+					path(s->value("path", NULL).as<std::string>())
 				{
 					boost::filesystem::path fspath = path;
 					boost::filesystem::path::iterator p = fspath.begin();
@@ -204,14 +207,14 @@ class Routes : public RowSet {
 				mutable Columns columns;
 				friend class Routes;
 		};
-		void execute(const Glib::ustring & filter, const RowProcessor * rp) const
+		void execute(const Glib::ustring & filter, const RowProcessorCallback & rp, ExecContext *) const
 		{
 			RouteRowState rs;
 			BOOST_FOREACH(const auto & r, ProgRouterLoader::routingTable.routes) {
 				if (boost::algorithm::starts_with(r->path, filter)) {
 					rs.fields[0] = VariableType(r->present);
 					rs.fields[1] = VariableType(r->path);
-					rs.process(rp);
+					rp(&rs);
 				}
 			}
 		}
diff --git a/project2/cgi/cgiRequestContext.cpp b/project2/cgi/cgiRequestContext.cpp
new file mode 100644
index 0000000..5a93243
--- /dev/null
+++ b/project2/cgi/cgiRequestContext.cpp
@@ -0,0 +1,161 @@
+#include <pch.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+#include "cgiRequestContext.h"
+#include "cgiAppEngine.h"
+#include "exceptions.h"
+#include <map>
+#include <cgicc/Cgicc.h>
+#include <glibmm/regex.h>
+#include <curl/curl.h>
+#include <boost/uuid/uuid_io.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+CgiRequestContext::CgiRequestContext(cgicc::CgiInput * i, const CgiEnvInput & e) :
+	cgi(i),
+	router(boost::bind(&RouterLoader::create, boost::cref(CgiApplicationEngine::router), getRedirectURL())),
+	cgienv(e),
+	session(boost::bind(&CgiRequestContext::getSessionInternal, this))
+{
+}
+
+CgiRequestContext::~CgiRequestContext()
+{
+}
+
+SessionPtr
+CgiRequestContext::getSession() const
+{
+	return session;
+}
+
+SessionPtr
+CgiRequestContext::getSessionInternal() const
+{
+	try {
+		return CgiApplicationEngine::sessionsContainer->GetSession(boost::uuids::string_generator()(getCookieValue(CgiApplicationEngine::sessionCookie)));
+	}
+	catch (const NoSuchCookie &) {
+		return CgiApplicationEngine::sessionsContainer->GetSession(boost::uuids::uuid());
+	}
+}
+
+std::string
+CgiRequestContext::getCookieValue(const std::string & name) const
+{
+	BOOST_FOREACH(const cgicc::HTTPCookie & c, cgi.getEnvironment().getCookieList()) {
+		if (c.getName() == name) {
+			return c.getValue();
+		}
+	}
+	throw NoSuchCookie(name);
+}
+
+std::string
+CgiRequestContext::getRequestMethod() const
+{
+	return cgi.getEnvironment().getRequestMethod();
+}
+
+std::string
+CgiRequestContext::getRedirectURL() const
+{
+	return cgi.getEnvironment().getRedirectURL();
+}
+
+std::string
+CgiRequestContext::getServerName() const
+{
+	return cgi.getEnvironment().getServerName();
+}
+
+std::string
+CgiRequestContext::getAccept() const
+{
+	return cgi.getEnvironment().getAccept();
+}
+
+CgiRequestContext::ETags
+CgiRequestContext::getRequestETags() const
+{
+	const std::string e = cgienv.getenv("HTTP_IF_NONE_MATCH");
+	ETags etags;
+	boost::split(etags, e, boost::is_any_of(" ,"), boost::algorithm::token_compress_on);
+	return etags;
+}
+
+time_t
+CgiRequestContext::getRequestModifiedSince() const
+{
+	return curl_getdate(cgienv.getenv("HTTP_IF_MODIFIED_SINCE").c_str(), NULL);
+}
+
+Glib::ustring
+CgiRequestContext::getParamUri(VariableType p) const
+{
+	return router->routeParameter(p);
+}
+
+unsigned int
+CgiRequestContext::getParamUriCount() const
+{
+	return router->parameterCount();
+}
+
+void
+CgiRequestContext::applyAllParameters(const boost::function<void (const std::string &, const std::string &)> & func) const
+{
+	BOOST_FOREACH(const auto & f, cgi.getElements()) {
+		func(f.getName(), f.getValue());
+	}
+}
+
+VariableType
+CgiRequestContext::getParameter(const VariableType & p) const
+{
+	cgicc::const_form_iterator i = cgi.getElement(p);
+	if (i == cgi.getElements().end()) {
+		throw ParamNotFound(p);
+	}
+	return cgi(p);
+}
+
+HostnamePlatformIdentifier::HostnamePlatformIdentifier()
+{
+}
+
+HostnamePlatformIdentifier::~HostnamePlatformIdentifier()
+{
+}
+
+const Glib::ustring &
+HostnamePlatformIdentifier::derivedPlatform(CgiRequestContext * crc) const
+{
+	auto pi = std::find_if(platHosts.begin(), platHosts.end(), [crc](const PlatformHostname & r) -> bool {
+			return r.second->match(crc->getServerName());
+		});
+	if (pi == platHosts.end()) {
+		throw NoSuchPlatform(crc->getServerName());
+	}
+	return pi->first;
+}
+
+void
+HostnamePlatformIdentifier::reset() const
+{
+	platHosts.clear();
+}
+
+bool
+HostnamePlatformIdentifier::paramRequired() const
+{
+	return true;
+}
+
+void
+HostnamePlatformIdentifier::consume(const Glib::ustring & p, const VariableType & r, const Options::CurrentPlatform &) const
+{
+	platHosts.push_back(PlatformHostname(p, Glib::Regex::create(r, Glib::REGEX_CASELESS | Glib::REGEX_DOTALL)));
+}
+
diff --git a/project2/cgi/cgiRequestContext.h b/project2/cgi/cgiRequestContext.h
new file mode 100644
index 0000000..1dbc613
--- /dev/null
+++ b/project2/cgi/cgiRequestContext.h
@@ -0,0 +1,68 @@
+#ifndef ENVPROC_H
+#define ENVPROC_H
+
+#include <string>
+#include <vector>
+#include "cgiEnvInput.h"
+#include "cgiRouter.h"
+#include "execContext.h"
+#include <cgicc/CgiEnvironment.h>
+#include <cgicc/Cgicc.h>
+#include <lazyPointer.h>
+#include <glibmm/refptr.h>
+
+SimpleMessageException(NoSuchCookie);
+
+class CgiRequestContext;
+namespace Glib {
+	class Regex;
+}
+
+class HostnamePlatformIdentifier : public Options::Target {
+	public:
+		HostnamePlatformIdentifier();
+		virtual ~HostnamePlatformIdentifier();
+		void reset() const;
+		bool paramRequired() const;
+		void consume(const Glib::ustring &, const VariableType &, const Options::CurrentPlatform &) const;
+		const Glib::ustring & derivedPlatform(CgiRequestContext *) const;
+	private:
+		typedef std::pair<Glib::ustring, Glib::RefPtr<Glib::Regex>> PlatformHostname;
+		typedef std::vector<PlatformHostname>  PlatformHostnameList;
+		mutable PlatformHostnameList platHosts;
+};
+
+class CgiRequestContext : public ExecContext {
+	public:
+		typedef std::string ETag;
+		typedef std::vector<ETag> ETags;
+
+		CgiRequestContext(cgicc::CgiInput *, const CgiEnvInput & cgienv);
+		virtual ~CgiRequestContext();
+
+		const cgicc::Cgicc cgi;
+
+		Glib::ustring getParamUri(VariableType idx) const;
+		unsigned int getParamUriCount() const;
+		VariableType getParameter(const VariableType & idx) const;
+		void applyAllParameters(const boost::function<void (const std::string &, const std::string &)> &) const;
+		SessionPtr getSession() const;
+		std::string getServerName() const;
+		std::string getRedirectURL() const;
+		std::string getRequestMethod() const;
+		std::string getAccept() const;
+		ETags getRequestETags() const;
+		time_t getRequestModifiedSince() const;
+		std::string getCookieValue(const std::string & name) const;
+		LazyPointer<Router> router;
+
+		boost::posix_time::ptime startTime;
+		boost::posix_time::ptime endTime;
+
+	private:
+		const CgiEnvInput & cgienv;
+		LazyPointer<Session> session;
+		SessionPtr getSessionInternal() const;
+};
+
+#endif
diff --git a/project2/cgi/cgiRequestID.cpp b/project2/cgi/cgiRequestID.cpp
index da8ad6a..60baa1e 100644
--- a/project2/cgi/cgiRequestID.cpp
+++ b/project2/cgi/cgiRequestID.cpp
@@ -1,9 +1,8 @@
 #include <pch.hpp>
 #include <variables.h>
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include <scriptLoader.h>
 #include <scriptStorage.h>
-#include <appEngine.h>
 #include <gcrypt.h>
 #include <scopeObject.h>
 #include <iomanip>
@@ -16,16 +15,16 @@ class CgiRequestID : public VariableImplDyn {
 		{
 		}
 
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			gcry_md_hd_t state;
 			gcry_md_open(&state, GCRY_MD_SHA1, 0);
 			ScopeObject gcryClose([&state] { gcry_md_close(state); });
 
-			auto _env = static_cast<const CgiEnvironment *>(ApplicationEngine::getCurrent()->env());
-			gcryApplyString(state, _env->getRedirectURL());
+			auto crc = static_cast<const CgiRequestContext *>(ec);
+			gcryApplyString(state, crc->getRedirectURL());
 
-			_env->applyAllParameters([&state,this](const std::string & name, const std::string & value) {
+			crc->applyAllParameters([&state, this](const std::string & name, const std::string & value) {
 				gcryApplyString(state, name);
 				gcryApplyString(state, value);
 			});
diff --git a/project2/cgi/cgiResultStatic.cpp b/project2/cgi/cgiResultStatic.cpp
index b5fecd7..ab4ff43 100644
--- a/project2/cgi/cgiResultStatic.cpp
+++ b/project2/cgi/cgiResultStatic.cpp
@@ -4,7 +4,7 @@
 
 class StaticToCgiResult : public TransformImpl<StaticContent, CgiResult> {
 	public:
-		void transform(const StaticContent * sc, CgiResult * cr) const {
+		void transform(const StaticContent * sc, CgiResult * cr, ExecContext *) const {
 			cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", sc->getContentType(), sc->getEncoding()));
 			cr->header->addHeader("Content-Length", Glib::ustring::compose("%1", sc->getSizeInBytes()));
 			char buf[100];
diff --git a/project2/cgi/cgiResultWritable.cpp b/project2/cgi/cgiResultWritable.cpp
index ea17d3b..357a57c 100644
--- a/project2/cgi/cgiResultWritable.cpp
+++ b/project2/cgi/cgiResultWritable.cpp
@@ -3,11 +3,11 @@
 
 class WritableToCgiResult : public TransformImpl<WritableContent, CgiResult> {
 	public:
-		void transform(const WritableContent * wc, CgiResult * cr) const {
+		void transform(const WritableContent * wc, CgiResult * cr, ExecContext * ec) const {
 			cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", wc->getContentType(), cr->encoding));
 			cr->header->addHeader("Cache-control", "no-cache");
 			cr->header->render(cr->stream);
-			wc->writeTo(cr->stream, cr->encoding);
+			wc->writeTo(cr->stream, cr->encoding, ec);
 		}
 };
 DECLARE_TRANSFORM(WritableToCgiResult);
diff --git a/project2/cgi/cgiRouter.h b/project2/cgi/cgiRouter.h
index dd9c0e6..4a88b19 100644
--- a/project2/cgi/cgiRouter.h
+++ b/project2/cgi/cgiRouter.h
@@ -14,6 +14,7 @@ class Router : public IntrusivePtrBase {
 		virtual unsigned int parameterCount() const = 0;
 		virtual void present(const MultiRowSetPresenter * p) const = 0;
 };
+typedef boost::intrusive_ptr<Router> RouterPtr;
 typedef GenLoader<Router, const std::string &> RouterLoader;
 
 #endif
diff --git a/project2/cgi/cgiSimpleRouter.cpp b/project2/cgi/cgiSimpleRouter.cpp
index cd14c53..b67848e 100644
--- a/project2/cgi/cgiSimpleRouter.cpp
+++ b/project2/cgi/cgiSimpleRouter.cpp
@@ -1,4 +1,4 @@
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include <boost/filesystem/path.hpp>
 #include "scriptLoader.h"
 #include "presenter.h"
diff --git a/project2/cgi/cgiStageCacheHit.cpp b/project2/cgi/cgiStageCacheHit.cpp
index d398e8f..d74c02f 100644
--- a/project2/cgi/cgiStageCacheHit.cpp
+++ b/project2/cgi/cgiStageCacheHit.cpp
@@ -1,6 +1,6 @@
 #include <pch.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
 #include <boost/foreach.hpp>
 #include <boost/bind.hpp>
@@ -12,13 +12,13 @@ CgiApplicationEngine::CacheHitStage::CacheHitStage(ScriptNodePtr s, PresenterCac
 }
 
 CgiApplicationEngine::NextStage
-CgiApplicationEngine::CacheHitStage::run()
+CgiApplicationEngine::CacheHitStage::run(CgiRequestContext *)
 {
 	return NextStage(NULL, this, pc, NULL);
 }
 
 CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::CacheHitStage::getHeader() const
+CgiApplicationEngine::CacheHitStage::getHeader(CgiRequestContext *) const
 {
 	return HttpHeaderPtr(new Project2HttpHeader("200 OK"));
 }
diff --git a/project2/cgi/cgiStageCustomError.cpp b/project2/cgi/cgiStageCustomError.cpp
index 56739fd..e38c7ec 100644
--- a/project2/cgi/cgiStageCustomError.cpp
+++ b/project2/cgi/cgiStageCustomError.cpp
@@ -1,28 +1,28 @@
 #include <pch.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
 #include "logger.h"
 
-CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const std::exception & ex, ScriptReaderPtr s) :
+CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const std::exception & ex, ScriptReaderPtr s, CgiRequestContext * crc) :
 	CgiApplicationEngine::ResponseStage(s->root()),
 	::CommonObjects(s->root()),
 	::CheckHost(s->root()),
-	CgiApplicationEngine::DefaultErrorStage(ex),
-	CgiApplicationEngine::PresentStage(s)
+	CgiApplicationEngine::DefaultErrorStage(ex, crc),
+	CgiApplicationEngine::PresentStage(s, crc)
 {
 }
 
 CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::CustomErrorStage::getHeader() const
+CgiApplicationEngine::CustomErrorStage::getHeader(CgiRequestContext * ec) const
 {
-	return CgiApplicationEngine::DefaultErrorStage::getHeader();
+	return CgiApplicationEngine::DefaultErrorStage::getHeader(ec);
 }
 
 CgiApplicationEngine::NextStage
-CgiApplicationEngine::CustomErrorStage::run()
+CgiApplicationEngine::CustomErrorStage::run(CgiRequestContext * crc)
 {
-	CgiApplicationEngine::DefaultErrorStage::run();
-	return CgiApplicationEngine::PresentStage::run();
+	CgiApplicationEngine::DefaultErrorStage::run(crc);
+	return CgiApplicationEngine::PresentStage::run(crc);
 }
 
diff --git a/project2/cgi/cgiStageCustomNotFound.cpp b/project2/cgi/cgiStageCustomNotFound.cpp
index 872da77..48fbf64 100644
--- a/project2/cgi/cgiStageCustomNotFound.cpp
+++ b/project2/cgi/cgiStageCustomNotFound.cpp
@@ -1,28 +1,28 @@
 #include <pch.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
 #include "logger.h"
 
-CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const ScriptNotFound & notfound, ScriptReaderPtr s) :
+CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const ScriptNotFound & notfound, ScriptReaderPtr s, CgiRequestContext * crc) :
 	CgiApplicationEngine::ResponseStage(s->root()),
 	::CommonObjects(s->root()),
 	::CheckHost(s->root()),
 	CgiApplicationEngine::DefaultNotFoundStage(notfound),
-	CgiApplicationEngine::PresentStage(s)
+	CgiApplicationEngine::PresentStage(s, crc)
 {
 }
 
 CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::CustomNotFoundStage::getHeader() const
+CgiApplicationEngine::CustomNotFoundStage::getHeader(CgiRequestContext * crc) const
 {
-	return CgiApplicationEngine::DefaultNotFoundStage::getHeader();
+	return CgiApplicationEngine::DefaultNotFoundStage::getHeader(crc);
 }
 
 CgiApplicationEngine::NextStage
-CgiApplicationEngine::CustomNotFoundStage::run()
+CgiApplicationEngine::CustomNotFoundStage::run(CgiRequestContext * crc)
 {
-	CgiApplicationEngine::DefaultNotFoundStage::run();
-	return CgiApplicationEngine::PresentStage::run();
+	CgiApplicationEngine::DefaultNotFoundStage::run(crc);
+	return CgiApplicationEngine::PresentStage::run(crc);
 }
 
diff --git a/project2/cgi/cgiStageDefaultError.cpp b/project2/cgi/cgiStageDefaultError.cpp
index 4c3eefe..d230a21 100644
--- a/project2/cgi/cgiStageDefaultError.cpp
+++ b/project2/cgi/cgiStageDefaultError.cpp
@@ -2,22 +2,22 @@
 #include "cgiAppEngine.h"
 #include "cgiHttpHeader.h"
 #include "logger.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include <cxxabi.h>
 
 static const Glib::ustring DefaultErrorStageResp("error");
 
-CgiApplicationEngine::DefaultErrorStage::DefaultErrorStage(const std::exception & ex) :
+CgiApplicationEngine::DefaultErrorStage::DefaultErrorStage(const std::exception & ex, CgiRequestContext * crc) :
 	CgiApplicationEngine::ResponseStage(NULL),
 	buf(__cxxabiv1::__cxa_demangle(typeid(ex).name(), NULL, NULL, NULL)),
 	what(ex.what()),
-	pres(new XmlPresenter(DefaultErrorStageResp, env()->errorTransformStyle, env()->errorContentType))
+	pres(new XmlPresenter(DefaultErrorStageResp, CgiApplicationEngine::errorTransformStyle, CgiApplicationEngine::errorContentType))
 {
 	auto xp = dynamic_cast<TransformSource *>(pres.get());
 	auto cp = dynamic_cast<ContentPresenter *>(pres.get());
-	if (xp && cp && cp->contentType == this->env()->transformContentType) {
-		auto h = TransformTargetLoader::getFor(this->env()->transformTargetType)->create(root, Default);
-		xp->addTarget(h, root);
+	if (xp && cp && cp->contentType == CgiApplicationEngine::transformContentType) {
+		auto h = TransformTargetLoader::getFor(CgiApplicationEngine::transformTargetType)->create(root, Default);
+		xp->addTarget(h, crc, root);
 	}
 }
 
@@ -27,15 +27,15 @@ CgiApplicationEngine::DefaultErrorStage::~DefaultErrorStage()
 }
 
 CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::DefaultErrorStage::getHeader() const
+CgiApplicationEngine::DefaultErrorStage::getHeader(CgiRequestContext *) const
 {
 	return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error"));
 }
 
 CgiApplicationEngine::NextStage
-CgiApplicationEngine::DefaultErrorStage::run()
+CgiApplicationEngine::DefaultErrorStage::run(CgiRequestContext * crc)
 {
-	pres->init();
+	pres->init(crc);
 	pres->addNamedValue("error-type", Scripts::scriptNamespacePrefix, buf);
 	pres->addNamedValue("error-what", Scripts::scriptNamespacePrefix, what.c_str());
 	return NextStage(NULL, this, pres.get(), pres.get());
diff --git a/project2/cgi/cgiStageDefaultNotFound.cpp b/project2/cgi/cgiStageDefaultNotFound.cpp
index e497058..bfb737f 100644
--- a/project2/cgi/cgiStageDefaultNotFound.cpp
+++ b/project2/cgi/cgiStageDefaultNotFound.cpp
@@ -1,6 +1,6 @@
 #include <pch.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
 #include "logger.h"
 
@@ -9,21 +9,21 @@ static const Glib::ustring DefaultNotFoundStageResp("notfound");
 CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const ScriptNotFound & notfound) :
 	CgiApplicationEngine::ResponseStage(NULL),
 	nf(notfound),
-	pres(new XmlPresenter(DefaultNotFoundStageResp, env()->errorTransformStyle, env()->errorContentType))
+	pres(new XmlPresenter(DefaultNotFoundStageResp, CgiApplicationEngine::errorTransformStyle, CgiApplicationEngine::errorContentType))
 {
 	Logger()->messagef(LOG_ERR, "%s: Resource not found: %s", __FUNCTION__, nf.what());
 }
 
 CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::DefaultNotFoundStage::getHeader() const
+CgiApplicationEngine::DefaultNotFoundStage::getHeader(CgiRequestContext *) const
 {
 	return HttpHeaderPtr(new Project2HttpHeader("404 Not found"));
 }
 
 CgiApplicationEngine::NextStage
-CgiApplicationEngine::DefaultNotFoundStage::run()
+CgiApplicationEngine::DefaultNotFoundStage::run(CgiRequestContext * crc)
 {
-	pres->init();
+	pres->init(crc);
 	pres->addNamedValue("missing-resource", Scripts::scriptNamespacePrefix, nf.what());
 	return NextStage(NULL, this, pres.get(), pres.get());
 }
diff --git a/project2/cgi/cgiStageFail.cpp b/project2/cgi/cgiStageFail.cpp
index 019ab8e..461c8a7 100644
--- a/project2/cgi/cgiStageFail.cpp
+++ b/project2/cgi/cgiStageFail.cpp
@@ -1,7 +1,7 @@
 #include <pch.hpp>
 #include <boost/lexical_cast.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
 #include "logger.h"
 
@@ -14,13 +14,13 @@ namespace CgiApplicationExtras {
 				message(m) {
 			}
 
-			CgiApplicationEngine::HttpHeaderPtr getHeader() const
+			CgiApplicationEngine::HttpHeaderPtr getHeader(CgiRequestContext *) const
 			{
 				Project2HttpHeader * header = new Project2HttpHeader(boost::lexical_cast<std::string>(code) + " " + message);
 				return CgiApplicationEngine::HttpHeaderPtr(header);
 			}
 
-			CgiApplicationEngine::NextStage run()
+			CgiApplicationEngine::NextStage run(CgiRequestContext *)
 			{
 				return CgiApplicationEngine::NextStage(NULL, this, NULL, NULL);
 			}
@@ -37,9 +37,9 @@ namespace CgiApplicationExtras {
 				code(e, "code", 500),
 				message(e, "message", "Application error") {
 			}
-			void execute(const MultiRowSetPresenter *) const {
+			void execute(const MultiRowSetPresenter *, ExecContext * ec) const {
 				throw CgiApplicationEngine::ResponseStagePtr(
-						new FailStage(code(), message()));
+						new FailStage(code(ec), message(ec)));
 			}
 		private:
 			Variable code, message;
diff --git a/project2/cgi/cgiStageInitial.cpp b/project2/cgi/cgiStageInitial.cpp
index d5fe424..1326af8 100644
--- a/project2/cgi/cgiStageInitial.cpp
+++ b/project2/cgi/cgiStageInitial.cpp
@@ -1,17 +1,18 @@
 #include <pch.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "exceptions.h"
 
 CgiApplicationEngine::NextStage
-CgiApplicationEngine::InitialStage::run()
+CgiApplicationEngine::InitialStage::run(CgiRequestContext * crc)
 {
-	const CgiEnvironment * e = env();
-	if (e->getRequestMethod() == "POST") {
-		return NextStage(new RequestStage(ScriptReader::resolveScript(e->requestRoot, e->router->route(), false)));
+	if (crc->getRequestMethod() == "POST") {
+		return NextStage(new RequestStage(ScriptReader::resolveScript(CgiApplicationEngine::requestRoot,
+						crc->router->route(), false)));
 	}
 	else {
-		return NextStage(new PresentStage(ScriptReader::resolveScript(e->presentRoot, e->router->isDefault() ? e->defaultPresent : e->router->route(), false)));
+		return NextStage(new PresentStage(ScriptReader::resolveScript(CgiApplicationEngine::presentRoot,
+						crc->router->isDefault() ? CgiApplicationEngine::defaultPresent : crc->router->route(), false), crc));
 	}
 }
 
diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp
index 90299fe..f077111 100644
--- a/project2/cgi/cgiStagePresent.cpp
+++ b/project2/cgi/cgiStagePresent.cpp
@@ -1,41 +1,41 @@
 #include <pch.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
 #include "safeMapFind.h"
 #include <boost/foreach.hpp>
 #include <boost/bind.hpp>
 
-CgiApplicationEngine::PresentStage::PresentStage(ScriptReaderPtr s) :
+CgiApplicationEngine::PresentStage::PresentStage(ScriptReaderPtr s, CgiRequestContext * crc) :
 	CgiApplicationEngine::ResponseStage(s->root()),
 	CommonObjects(s->root()),
 	CheckHost(s->root()),
 	ViewHost(s->root()),
-	presenter([this] {
-			auto p = PresenterLoader::getFor(this->env()->defaultPresenter)->create(root, Default);
+	presenter([this, crc] {
+			auto p = PresenterLoader::getFor(CgiApplicationEngine::defaultPresenter)->create(root, Default, crc);
 			auto xp = dynamic_cast<TransformSource *>(p);
 			auto cp = dynamic_cast<ContentPresenter *>(p);
-			if (xp && cp && cp->contentType == this->env()->transformContentType) {
-				auto h = TransformTargetLoader::getFor(this->env()->transformTargetType)->create(root, Default);
-				xp->addTarget(h, root);
+			if (xp && cp && cp->contentType == CgiApplicationEngine::transformContentType) {
+				auto h = TransformTargetLoader::getFor(CgiApplicationEngine::transformTargetType)->create(root, Default);
+				xp->addTarget(h, crc, root);
 			}
 			return p;
 		})
 {
 	s->loader.addLoadTarget(s->root(), Storer::into<OutputOptionsLoader>(&outputOptions));
-	s->loader.addLoadTarget(s->root(), Storer::into<PresenterLoader>(&presenter, Scripted));
+	s->loader.addLoadTarget(s->root(), Storer::into<PresenterLoader>(&presenter, Scripted, crc));
 	s->loader.addLoadTarget(s->root(), Storer::into<ElementLoader>(&caches));
 }
 
 CgiApplicationEngine::NextStage
-CgiApplicationEngine::PresentStage::run()
+CgiApplicationEngine::PresentStage::run(CgiRequestContext * crc)
 {
-	runChecks();
+	runChecks(crc);
 	PresenterCaches backFill;
-	time_t reqMS = this->env()->getRequestModifiedSince();
-	CgiEnvironment::ETags etags = this->env()->getRequestETags();
+	time_t reqMS = crc->getRequestModifiedSince();
+	CgiRequestContext::ETags etags = crc->getRequestETags();
 	BOOST_FOREACH(const PresenterCachePtr & pc, caches) {
-		if (pc->check(root->script->modifiedTime())) {
+		if (pc->check(root->script->modifiedTime(), crc)) {
 			if (reqMS >= pc->getModifiedTime() && (etags.empty() || containerContains(etags, pc->getSHA1()))) {
 				header = HttpHeaderPtr(new Project2HttpHeader("304 Not Modified"));
 				return NextStage(NULL, this, NULL, NULL);
@@ -49,7 +49,7 @@ CgiApplicationEngine::PresentStage::run()
 		}
 	}
 	try {
-		executeViews();
+		executeViews(crc);
 		header = HttpHeaderPtr(new Project2HttpHeader("200 OK"));
 		return NextStage(NULL, this, boost::dynamic_pointer_cast<TransformSource>(presenter), presenter);
 	}
@@ -66,7 +66,7 @@ CgiApplicationEngine::PresentStage::run()
 }
 
 MultiRowSetPresenterPtr
-CgiApplicationEngine::PresentStage::getPresenter() const
+CgiApplicationEngine::PresentStage::getPresenter(ExecContext *) const
 {
 	return presenter;
 }
@@ -77,7 +77,7 @@ CgiApplicationEngine::ResponseStage::ResponseStage(ScriptNodePtr r) :
 }
 
 CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::PresentStage::getHeader() const
+CgiApplicationEngine::PresentStage::getHeader(CgiRequestContext *) const
 {
 	return header;
 }
diff --git a/project2/cgi/cgiStageRedirect.cpp b/project2/cgi/cgiStageRedirect.cpp
index 4a4cd02..d6fee08 100644
--- a/project2/cgi/cgiStageRedirect.cpp
+++ b/project2/cgi/cgiStageRedirect.cpp
@@ -1,6 +1,6 @@
 #include <pch.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
 #include "logger.h"
 
@@ -12,14 +12,14 @@ namespace CgiApplicationExtras {
 				url(u) {
 			}
 
-			CgiApplicationEngine::HttpHeaderPtr getHeader() const
+			CgiApplicationEngine::HttpHeaderPtr getHeader(CgiRequestContext *) const
 			{
 				Project2HttpHeader * header = new Project2HttpHeader("301 Moved Permanently");
 				header->addHeader("Location", url);
 				return CgiApplicationEngine::HttpHeaderPtr(header);
 			}
 
-			CgiApplicationEngine::NextStage run()
+			CgiApplicationEngine::NextStage run(CgiRequestContext *)
 			{
 				return CgiApplicationEngine::NextStage(NULL, this, NULL, NULL);
 			}
@@ -34,8 +34,8 @@ namespace CgiApplicationExtras {
 				View(e),
 				url(e, "url") {
 			}
-			void execute(const MultiRowSetPresenter *) const {
-				throw CgiApplicationEngine::ResponseStagePtr(new RedirectStage(url()));
+			void execute(const MultiRowSetPresenter *, ExecContext * ec) const {
+				throw CgiApplicationEngine::ResponseStagePtr(new RedirectStage(url(ec)));
 			}
 		private:
 			Variable url;
diff --git a/project2/cgi/cgiStageRequest.cpp b/project2/cgi/cgiStageRequest.cpp
index 37faaae..78d933b 100644
--- a/project2/cgi/cgiStageRequest.cpp
+++ b/project2/cgi/cgiStageRequest.cpp
@@ -1,6 +1,6 @@
 #include <pch.hpp>
 #include "cgiAppEngine.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
 #include "scriptLoader.h"
 #include <boost/foreach.hpp>
@@ -17,26 +17,26 @@ CgiApplicationEngine::RequestStage::RequestStage(ScriptReaderPtr s) :
 }
 
 CgiApplicationEngine::NextStage
-CgiApplicationEngine::RequestStage::run()
+CgiApplicationEngine::RequestStage::run(CgiRequestContext * ec)
 {
-	runChecks();
-	execute();
-	if (!present().isNull()) {
-		return NextStage(new PresentStage(ScriptReader::resolveScript(env()->presentRoot, present(), false)), this);
+	runChecks(ec);
+	execute(ec);
+	if (!present(ec).isNull()) {
+		return NextStage(new PresentStage(ScriptReader::resolveScript(CgiApplicationEngine::presentRoot, present(ec), false), ec), this);
 	}
 	return NextStage(NULL, this);
 }
 
 CgiApplicationEngine::HttpHeaderPtr
-CgiApplicationEngine::RequestStage::getHeader() const
+CgiApplicationEngine::RequestStage::getHeader(CgiRequestContext * ec) const
 {
 	Project2HttpHeader * header;
-	if (redirect().isNull()) {
+	if (redirect(ec).isNull()) {
 		header = new Project2HttpHeader("200 OK");
 	}
 	else {
 		header = new Project2HttpHeader("301 Moved Permanently");
-		header->addHeader("Location", redirect());
+		header->addHeader("Location", redirect(ec));
 	}
 	header->addHeader("Cache-control", "no-cache");
 	return HttpHeaderPtr(header);
diff --git a/project2/cgi/cgiUriParam.cpp b/project2/cgi/cgiUriParam.cpp
index c65119e..985048d 100644
--- a/project2/cgi/cgiUriParam.cpp
+++ b/project2/cgi/cgiUriParam.cpp
@@ -1,9 +1,8 @@
 #include <pch.hpp>
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include <variables.h>
 #include <scriptLoader.h>
 #include <scriptStorage.h>
-#include <appEngine.h>
 
 /// Variable implementation to access URI path fragments
 class VariableUri : public VariableImplDyn {
@@ -13,16 +12,16 @@ class VariableUri : public VariableImplDyn {
 			index(e, "index")
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			try {
-				return static_cast<const CgiEnvironment *>(ApplicationEngine::getCurrent()->env())->getParamUri(index());
+				return static_cast<const CgiRequestContext *>(ec)->getParamUri(index(ec));
 			}
 			catch (...) {
 				if (!defaultValue) {
 					throw;
 				}
-				return (*defaultValue)();
+				return (*defaultValue)(ec);
 			}
 		}
 	private:
diff --git a/project2/cgi/p2webCgi.cpp b/project2/cgi/p2webCgi.cpp
index 1b2aa99..4f806b2 100644
--- a/project2/cgi/p2webCgi.cpp
+++ b/project2/cgi/p2webCgi.cpp
@@ -1,5 +1,5 @@
-#include "cgiCommon.h"
-#include "scriptLoader.h"
+#include "cgiAppEngine.h"
+#include "optionsSource.h"
 #include <boost/bind.hpp>
 
 class GetEnv : public CgiEnvInput {
@@ -16,9 +16,12 @@ int
 main(void)
 {
 	Plugable::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1));
-	CgiEnvironment env;
+	CgiApplicationEngine app;
 	GetEnv ge;
-	cgiServe(NULL, &env, std::cout, &ge);
+	CgiRequestContext crc(NULL, ge);
+	OptionsSource::loadSources(boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc));
+	Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
+	app.process(std::cout, &crc);
 	Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1));
 	Plugable::onAllComponents(boost::bind(&ComponentLoader::onPeriodic, _1));
 	Plugable::onAllComponents(boost::bind(&ComponentLoader::onIdle, _1));
diff --git a/project2/cgi/p2webFCgi.cpp b/project2/cgi/p2webFCgi.cpp
index 7eb631f..4320c48 100644
--- a/project2/cgi/p2webFCgi.cpp
+++ b/project2/cgi/p2webFCgi.cpp
@@ -1,6 +1,6 @@
-#include "cgiCommon.h"
 #include "FCgiIO.h"
-#include "scriptLoader.h"
+#include "cgiAppEngine.h"
+#include "optionsSource.h"
 #include <boost/bind.hpp>
 
 time_t lastPeriodic = 0;
@@ -40,12 +40,15 @@ main(void)
 			fprintf(stderr, "Failed to set signal handler\n");
 		}
 		alarm(60);
-		CgiEnvironment env;
 		Plugable::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1));
+		CgiApplicationEngine app;
 		while (FCGX_Accept_r(&request) == 0) {
 			alarm(0);
 			cgicc::FCgiIO IO(request);
-			cgiServe(&IO, &env, IO, &IO);
+			CgiRequestContext crc(&IO, IO);
+			OptionsSource::loadSources(boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc));
+			Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
+			app.process(IO, &crc);
 			FCGX_Finish_r(&request);
 			Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1));
 			if (time(NULL) > lastPeriodic + periodicDelay) {
diff --git a/project2/cgi/pch.hpp b/project2/cgi/pch.hpp
index df744a4..5f68b7c 100644
--- a/project2/cgi/pch.hpp
+++ b/project2/cgi/pch.hpp
@@ -2,14 +2,8 @@
 #ifndef CGI_PCH
 #define CGI_PCH
 
-#include "appEngine.h"
-#include "cgiAppEngine.h"
-#include "cgiCommon.h"
-#include "cgiEnvironment.h"
+#include "cgiRequestContext.h"
 #include "cgiHttpHeader.h"
-#include "exceptions.h"
-#include "iterate.h"
-#include "logger.h"
 #include "scriptLoader.h"
 #include <boost/bind.hpp>
 #include <boost/foreach.hpp>
diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp
index 9ef0079..2025594 100644
--- a/project2/cgi/testCgi.cpp
+++ b/project2/cgi/testCgi.cpp
@@ -3,8 +3,9 @@
 #include <map>
 #include "options.h"
 #include "safeMapFind.h"
-#include "cgiCommon.h"
 #include "../files/optionsSource.h"
+#include "cgiRequestContext.h"
+#include "cgiAppEngine.h"
 
 #define TESTOPT(name, def, desc) \
 				(name, Options::value(optStore().insert(OptStore::value_type(name, StrPtr(new std::string()))).first->second.get(), def), desc)
@@ -12,8 +13,8 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
 	public:
 		class TestConfigConsumer : public ConfigConsumer {
 			public:
-				void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const {
-					Plugable::onAll<Options>(boost::bind(&Options::consume, _1, n, p, v));
+				void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v, const Options::CurrentPlatform & cp) const {
+					Plugable::onAll<Options>(boost::bind(&Options::consume, _1, n, p, v, cp));
 				}
 				const Options::Option * get(const Glib::ustring &) const {
 					return NULL;
@@ -22,11 +23,13 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
 
 		typedef boost::shared_ptr<std::string> StrPtr;
 		typedef std::map<std::string, StrPtr> OptStore;
-		TestInput(int argc, char ** argv)
+		TestInput(int argc, char ** argv) :
+			crc(NULL, *this)
 		{
-			OptionsSource::loadSources();
+			auto cp = boost::bind(&HostnamePlatformIdentifier::derivedPlatform, boost::cref(CgiApplicationEngine::hpi), &crc);
+			OptionsSource::loadSources(cp);
 			FileOptions fo(".testCgi.settings");
-			fo.loadInto(TestConfigConsumer());
+			fo.loadInto(TestConfigConsumer(), cp);
 			if (argc > 1) {
 				const char * qm = strchr(argv[1], '?');
 				if (qm) {
@@ -51,9 +54,10 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
 		}
 		void run()
 		{
+			CgiApplicationEngine app;
 			if (urlListFile.empty()) {
 				for (int run = 0; run < runCount; run += 1) {
-					cgiServe(this, &env, std::cout, this);
+					app.process(std::cout, &crc);
 				}
 			}
 			else {
@@ -63,7 +67,7 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
 						std::string url;
 						urls >> url;
 						optStore()["REDIRECT_URL"] = StrPtr(new std::string(url));
-						cgiServe(this, &env, std::cout, this);
+						app.process(std::cout, &crc);
 					}
 				}
 			}
@@ -71,7 +75,7 @@ class TestInput : public cgicc::CgiInput, public CgiEnvInput {
 		INITOPTIONS;
 
 	private:
-		CgiEnvironment env;
+		CgiRequestContext crc;
 		static int runCount;
 		static std::string urlListFile;
 		static OptStore & optStore()
diff --git a/project2/common/aggregate.cpp b/project2/common/aggregate.cpp
index 1bb453b..ee7c871 100644
--- a/project2/common/aggregate.cpp
+++ b/project2/common/aggregate.cpp
@@ -17,8 +17,8 @@ SetAggregate::SetAggregate(ScriptNodePtr s) :
 }
 
 void
-Aggregate::pushValue() const
+Aggregate::pushValue(ExecContext * ec) const
 {
-	pushValue(value());
+	pushValue(value(ec), ec);
 }
 
diff --git a/project2/common/aggregate.h b/project2/common/aggregate.h
index 0641c6e..7f33b6b 100644
--- a/project2/common/aggregate.h
+++ b/project2/common/aggregate.h
@@ -10,9 +10,9 @@ class Aggregate : public SourceObject {
 		Aggregate(ScriptNodePtr);
 
 		virtual void reset() const = 0;
-		void pushValue() const;
+		void pushValue(ExecContext * ec) const;
 	protected:
-		virtual void pushValue(const VariableType &) const = 0;
+		virtual void pushValue(const VariableType &, ExecContext *) const = 0;
 	private:
 		Variable value;
 };
diff --git a/project2/common/appEngine.cpp b/project2/common/appEngine.cpp
deleted file mode 100644
index ce71153..0000000
--- a/project2/common/appEngine.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <pch.hpp>
-#include "appEngine.h"
-#include "logger.h"
-#include "presenter.h"
-#include <stdexcept>
-#include <boost/foreach.hpp>
-
-ApplicationEngine * ApplicationEngine::currentEngine = NULL;
-
-ApplicationEngine::ApplicationEngine()
-{
-	if (currentEngine) {
-		throw std::runtime_error("One application at a time, please");
-	}
-	currentEngine = this;
-}
-
-ApplicationEngine::~ApplicationEngine()
-{
-	currentEngine = NULL;
-}
-
-void
-ApplicationEngine::logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m)
-{
-	if (writeLog) {
-		Logger()->messagebf(LOG_NOTICE, "%s: %s: %s", __PRETTY_FUNCTION__, g, m);
-	}
-	appMessages.push_back(new Message(g, m));
-}
-
-void
-ApplicationEngine::addCoreAppData(const MultiRowSetPresenter * p) const
-{
-	// Message log
-	p->addNewRowSet("messages", Scripts::scriptNamespacePrefix);
-	p->addNewArray("message", true);
-	BOOST_FOREACH(const Messages::value_type & m, appMessages) {
-		p->addNewRow("message");
-		p->addAttribute("group", m->group);
-		p->addAttribute("text", m->message);
-		p->finishRow();
-	}
-	p->finishArray(true);
-	p->finishRowSet();
-}
-
-ApplicationEngine::Message::Message(const Glib::ustring & g, const Glib::ustring & m) :
-	group(g),
-	message(m)
-{
-}
-
diff --git a/project2/common/appEngine.h b/project2/common/appEngine.h
deleted file mode 100644
index 6de21e1..0000000
--- a/project2/common/appEngine.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef APPENGINE_H
-#define APPENGINE_H
-
-#include "environment.h"
-#include "session.h"
-
-class MultiRowSetPresenter;
-
-class ApplicationEngine {
-	public:
-		class Message : public IntrusivePtrBase {
-			public:
-				Message(const Glib::ustring & g, const Glib::ustring & m);
-
-				const Glib::ustring group;
-				const Glib::ustring message;
-		};
-		typedef boost::intrusive_ptr<Message> MessagePtr;
-		typedef std::list<MessagePtr> Messages;
-
-		ApplicationEngine();
-		virtual ~ApplicationEngine() = 0;
-
-		void logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m);
-
-		virtual void process() const = 0;
-		virtual const Environment * env() const = 0;
-		virtual SessionPtr session() const = 0;
-
-		static ApplicationEngine * getCurrent() { return currentEngine; }
-
-	protected:
-		void addCoreAppData(const MultiRowSetPresenter * p) const;
-
-		Messages appMessages;
-
-	private:
-		static ApplicationEngine * currentEngine;
-};
-
-#endif
-
diff --git a/project2/common/cache.cpp b/project2/common/cache.cpp
index 9be5845..2a1d410 100644
--- a/project2/common/cache.cpp
+++ b/project2/common/cache.cpp
@@ -9,17 +9,17 @@
 Cache::Cache(ScriptNodePtr p) :
 	IHaveParameters(p),
 	SourceObject(p),
-	inherit(p->value("inherit", true).as<bool>())
+	inherit(p->value("inherit", true, NULL).as<bool>())
 {
 }
 
-bool Cache::checkAndExecute(const Glib::ustring & n, const Glib::ustring & f, const RowProcessor * rp)
+bool Cache::checkAndExecute(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * p, const RowProcessorCallback & rp)
 {
-	RowSetCPtr cached = getCachedRowSet(n, f, rp);
+	RowSetCPtr cached = getCachedRowSet(ec, n, f, p);
 	if (cached) {
 		try {
 			Logger()->messagebf(LOG_DEBUG, "Executing from cache '%s'", name);
-			cached->execute(f, rp);
+			cached->execute(f, rp, ec);
 			return true;
 		}
 		catch (const Glib::Exception & e) {
@@ -36,14 +36,14 @@ bool Cache::checkAndExecute(const Glib::ustring & n, const Glib::ustring & f, co
 }
 
 void
-Cache::applyKeys(const boost::function2<void, const std::string &, const VariableType &> & f, const IHaveParameters * ps) const
+Cache::applyKeys(ExecContext * ec, const KeyApplier & f, const IHaveParameters * ps) const
 {
 	BOOST_FOREACH(const IHaveParameters::Parameters::value_type & p, allParameters()) {
-		f(p.first, p.second);
+		f(p.first, p.second(ec));
 	}
 	if (inherit) {
 		BOOST_FOREACH(const IHaveParameters::Parameters::value_type & p, ps->allParameters()) {
-			f(p.first, p.second);
+			f(p.first, p.second(ec));
 		}
 	}
 }
diff --git a/project2/common/cache.h b/project2/common/cache.h
index 2c438b8..0806c6f 100644
--- a/project2/common/cache.h
+++ b/project2/common/cache.h
@@ -4,8 +4,8 @@
 #include "sourceObject.h"
 #include "presenter.h"
 #include "iHaveParameters.h"
+#include "rowSet.h"
 
-class RowProcessor;
 class RowSet;
 class RowState;
 typedef boost::intrusive_ptr<const RowSet> RowSetCPtr;
@@ -14,14 +14,15 @@ class Cache : public IHaveParameters, public SourceObject {
 	public:
 		Cache(ScriptNodePtr p);
 
-		bool checkAndExecute(const Glib::ustring &, const Glib::ustring &, const RowProcessor *);
-		virtual RowSetPresenterPtr openFor(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0;
-		virtual void save(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0;
-		virtual void discard(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0;
+		bool checkAndExecute(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *, const RowProcessorCallback &);
+		virtual RowSetPresenterPtr openFor(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0;
+		virtual void save(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0;
+		virtual void discard(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) = 0;
 
 	protected:
-		virtual RowSetCPtr getCachedRowSet(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) const = 0;
-		void applyKeys(const boost::function2<void, const std::string &, const VariableType &> & f, const IHaveParameters *) const;
+		virtual RowSetCPtr getCachedRowSet(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *) const = 0;
+		typedef boost::function<void (const std::string &, const VariableType &)> KeyApplier;
+		void applyKeys(ExecContext * ec, const KeyApplier & f, const IHaveParameters * ps) const;
 		const bool inherit;
 };
 typedef boost::intrusive_ptr<Cache> CachePtr;
diff --git a/project2/common/check.cpp b/project2/common/check.cpp
index 21d17cf..d288e2f 100644
--- a/project2/common/check.cpp
+++ b/project2/common/check.cpp
@@ -20,11 +20,11 @@ Check::~Check()
 }
 
 bool
-Check::performCheck() const
+Check::performCheck(ExecContext * ec) const
 {
 	if (!test) {
 		throw NoTestsToPerform();
 	}
-	return test->passes();
+	return test->passes(ec);
 }
 
diff --git a/project2/common/check.h b/project2/common/check.h
index e9f44b5..dc97f8f 100644
--- a/project2/common/check.h
+++ b/project2/common/check.h
@@ -5,13 +5,15 @@
 #include "variables.h"
 #include "test.h"
 
+class ExecContext;
+
 /// Base class for Project2 compoments that perform checks
 class Check : public SourceObject {
 	public:
 		Check(ScriptNodePtr p);
 		virtual ~Check();
 
-		bool performCheck() const;
+		bool performCheck(ExecContext *) const;
 
 		const Variable message;
 		const Variable group;
diff --git a/project2/common/checkHost.cpp b/project2/common/checkHost.cpp
index 49533a9..dedea85 100644
--- a/project2/common/checkHost.cpp
+++ b/project2/common/checkHost.cpp
@@ -1,6 +1,6 @@
 #include <pch.hpp>
 #include "checkHost.h"
-#include "appEngine.h"
+#include "execContext.h"
 #include <boost/foreach.hpp>
 
 CheckHost::CheckHost(ScriptNodePtr s) :
@@ -14,12 +14,12 @@ CheckHost::~CheckHost()
 }
 
 void
-CheckHost::runChecks() const
+CheckHost::runChecks(ExecContext * ec) const
 {
 	loadScriptComponents();
 	BOOST_FOREACH(const Checks::value_type & pc, checks) {
-		if (!pc->performCheck()) {
-			ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message());
+		if (!pc->performCheck(ec)) {
+			ec->logMessage(false, pc->group(ec), pc->message(ec));
 			throw CheckFailure(pc);
 		}
 	}
diff --git a/project2/common/checkHost.h b/project2/common/checkHost.h
index edc2cd8..f404d9e 100644
--- a/project2/common/checkHost.h
+++ b/project2/common/checkHost.h
@@ -18,7 +18,7 @@ class CheckHost : virtual public CommonObjects {
 		CheckHost(ScriptNodePtr script); 
 		~CheckHost();
 
-		void runChecks() const;
+		void runChecks(ExecContext *) const;
 
 		typedef ANONORDEREDSTORAGEOF(Check) Checks;
 		Checks checks;
diff --git a/project2/common/commonObjects.cpp b/project2/common/commonObjects.cpp
index 23f2edb..a25bb9f 100644
--- a/project2/common/commonObjects.cpp
+++ b/project2/common/commonObjects.cpp
@@ -1,7 +1,6 @@
 #include <pch.hpp>
 #include "commonObjects.h"
 #include "safeMapFind.h"
-#include "appEngine.h"
 #include "scriptLoader.h"
 
 CommonObjects::CommonObjects() :
diff --git a/project2/common/environment.cpp b/project2/common/environment.cpp
deleted file mode 100644
index 69f853c..0000000
--- a/project2/common/environment.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <pch.hpp>
-#include "environment.h"
-#include "optionsSource.h"
-
-const Environment * Environment::currentEnv(NULL);
-
-Environment::Environment()
-{
-	currentEnv = this;
-}
-
-Environment::~Environment()
-{
-	currentEnv = NULL;
-}
-
-const Environment *
-Environment::getCurrent()
-{
-	return currentEnv;
-}
-
diff --git a/project2/common/environment.h b/project2/common/environment.h
deleted file mode 100644
index a97255f..0000000
--- a/project2/common/environment.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef ENVIRONMENT_H
-#define ENVIRONMENT_H
-
-#include <string>
-#include <glibmm/ustring.h>
-#include "exceptions.h"
-#include "scripts.h"
-
-SimpleMessageException(NoSuchPlatform);
-
-class Environment {
-	public:
-		Environment();
-		virtual ~Environment() = 0;
-
-		static const Environment * getCurrent();
-
-		virtual Glib::ustring getParamQuery(const std::string & idx) const = 0;
-
-		virtual std::string getServerName() const = 0;
-		virtual const Glib::ustring & platform() const = 0;
-
-	private:
-		static const Environment * currentEnv;
-};
-
-#endif
-
diff --git a/project2/common/exceptions.h b/project2/common/exceptions.h
index 38f0efa..9cdf6f0 100644
--- a/project2/common/exceptions.h
+++ b/project2/common/exceptions.h
@@ -67,6 +67,7 @@ SimpleMessageException(NotSupported);
 SimpleMessageException(FileNotReadable);
 SimpleMessageException(FileNotWritable);
 SimpleMessageException(FilterNotFound);
+SimpleMessageException(NoSuchPlatform);
 
 #endif
 
diff --git a/project2/common/execContext.cpp b/project2/common/execContext.cpp
new file mode 100644
index 0000000..571b5f0
--- /dev/null
+++ b/project2/common/execContext.cpp
@@ -0,0 +1,36 @@
+#include "execContext.h"
+#include "logger.h"
+#include "presenter.h"
+#include <boost/foreach.hpp>
+
+void
+ExecContext::logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m)
+{
+	if (writeLog) {
+		Logger()->messagebf(LOG_NOTICE, "%s: %s: %s", __PRETTY_FUNCTION__, g, m);
+	}
+	messages.push_back(new Message(g, m));
+}
+
+void
+ExecContext::addContextData(const MultiRowSetPresenter * p) const
+{
+	// Message log
+	p->addNewRowSet("messages", Scripts::scriptNamespacePrefix);
+	p->addNewArray("message", true);
+	BOOST_FOREACH(const Messages::value_type & m, messages) {
+		p->addNewRow("message");
+		p->addAttribute("group", m->group);
+		p->addAttribute("text", m->message);
+		p->finishRow();
+	}
+	p->finishArray(true);
+	p->finishRowSet();
+}
+
+ExecContext::Message::Message(const Glib::ustring & g, const Glib::ustring & m) :
+	group(g),
+	message(m)
+{
+}
+
diff --git a/project2/common/execContext.h b/project2/common/execContext.h
new file mode 100644
index 0000000..6018058
--- /dev/null
+++ b/project2/common/execContext.h
@@ -0,0 +1,37 @@
+#ifndef EXECCONTEXT_H
+#define EXECCONTEXT_H
+
+#include <glibmm/ustring.h>
+#include <boost/intrusive_ptr.hpp>
+#include <list>
+#include "variableType.h"
+#include "session.h"
+
+class MultiRowSetPresenter;
+
+class ExecContext {
+	public:
+		class Message : public IntrusivePtrBase {
+			public:
+				Message(const Glib::ustring & g, const Glib::ustring & m);
+
+				const Glib::ustring group;
+				const Glib::ustring message;
+		};
+		typedef boost::intrusive_ptr<Message> MessagePtr;
+		typedef std::list<MessagePtr> Messages;
+
+		virtual VariableType getParameter(const VariableType & key) const = 0;
+		virtual SessionPtr getSession() const = 0;
+
+		void logMessage(bool writeLog, const Glib::ustring & g, const Glib::ustring & m);
+		const Messages & getMessages() const;
+
+		void addContextData(const MultiRowSetPresenter * p) const;
+
+	private:
+		Messages messages;
+};
+
+#endif
+
diff --git a/project2/common/iHaveParameters.cpp b/project2/common/iHaveParameters.cpp
index f880944..1bf1362 100644
--- a/project2/common/iHaveParameters.cpp
+++ b/project2/common/iHaveParameters.cpp
@@ -2,7 +2,6 @@
 #include "iHaveParameters.h"
 #include "exceptions.h"
 #include "safeMapFind.h"
-#include "appEngine.h"
 #include <boost/foreach.hpp>
 
 IHaveParameters::Stack IHaveParameters::scope;
@@ -19,9 +18,9 @@ IHaveParameters::~IHaveParameters()
 }
 
 VariableType
-IHaveParameters::getParameter(const Glib::ustring & name) const
+IHaveParameters::getParameter(const Glib::ustring & name, ExecContext * ec) const
 {
-	return safeMapLookup<ParamNotFound>(parameters, name);
+	return safeMapLookup<ParamNotFound>(parameters, name)(ec);
 }
 
 void
@@ -37,12 +36,12 @@ IHaveParameters::pop()
 }
 
 VariableType
-IHaveParameters::getScopedParameter(const Glib::ustring & name)
+IHaveParameters::getScopedParameter(const Glib::ustring & name, ExecContext * ec)
 {
 	for(Stack::const_reverse_iterator ihp = scope.rbegin(); ihp != scope.rend(); ++ihp) {
 		Parameters::const_iterator i = (*ihp)->parameters.find(name);
 		if (i != (*ihp)->parameters.end()) {
-			return i->second;
+			return i->second(ec);
 		}
 	}
 	throw ParamNotFound(name);
diff --git a/project2/common/iHaveParameters.h b/project2/common/iHaveParameters.h
index 2b7ed2a..7b15289 100644
--- a/project2/common/iHaveParameters.h
+++ b/project2/common/iHaveParameters.h
@@ -15,8 +15,8 @@ class IHaveParameters {
 		virtual ~IHaveParameters() = 0;
 
 		const Parameters & allParameters() const;
-		VariableType getParameter(const Glib::ustring &) const;
-		static VariableType getScopedParameter(const Glib::ustring &);
+		VariableType getParameter(const Glib::ustring &, ExecContext *) const;
+		static VariableType getScopedParameter(const Glib::ustring &, ExecContext *);
 
 	protected:
 		Parameters parameters;
diff --git a/project2/common/iHaveSubTasks.cpp b/project2/common/iHaveSubTasks.cpp
index 78868aa..92248fb 100644
--- a/project2/common/iHaveSubTasks.cpp
+++ b/project2/common/iHaveSubTasks.cpp
@@ -13,10 +13,10 @@ IHaveSubTasks::~IHaveSubTasks()
 }
 
 void
-IHaveSubTasks::run(const Tasks & tlist) const
+IHaveSubTasks::run(const Tasks & tlist, ExecContext * ec) const
 {
 	BOOST_FOREACH(const Tasks::value_type & t, tlist) {
-		t->execute();
+		t->execute(ec);
 	}
 }
 
diff --git a/project2/common/iHaveSubTasks.h b/project2/common/iHaveSubTasks.h
index e52a9be..d13a890 100644
--- a/project2/common/iHaveSubTasks.h
+++ b/project2/common/iHaveSubTasks.h
@@ -12,11 +12,11 @@ class IHaveSubTasks : public NoOutputExecute {
 		IHaveSubTasks(const std::string & n);
 		virtual ~IHaveSubTasks();
 
-		virtual void execute() const = 0;
+		virtual void execute(ExecContext * ec) const = 0;
 		Tasks normal;
 
 	protected:
-		void run(const Tasks &) const;
+		void run(const Tasks &, ExecContext * ec) const;
 };
 
 #endif
diff --git a/project2/common/if.cpp b/project2/common/if.cpp
index c7f790e..ed2abf6 100644
--- a/project2/common/if.cpp
+++ b/project2/common/if.cpp
@@ -20,31 +20,31 @@ If::If(ScriptNodePtr e) :
 }
 
 bool
-If::passes() const
+If::passes(ExecContext * ec) const
 {
 	if (!test) {
 		throw NoTestsToPerform();
 	}
-	return test->passes();
+	return test->passes(ec);
 }
 
 void
-If::execute(const MultiRowSetPresenter * presenter) const
+If::execute(const MultiRowSetPresenter * presenter, ExecContext * ec) const
 {
-	if (passes()) {
+	if (passes(ec)) {
 		Logger()->messagef(LOG_DEBUG, "Test passed; showing %zu views", subViews.size());
 		BOOST_FOREACH(const SubViews::value_type & sq, subViews) {
-			sq->execute(presenter);
+			sq->execute(presenter, ec);
 		}
 	}
 }
 
 void
-If::execute() const
+If::execute(ExecContext * ec) const
 {
-	if (passes()) {
+	if (passes(ec)) {
 		Logger()->messagef(LOG_DEBUG, "Test passed; executing %zu tasks", normal.size());
-		run(normal);
+		run(normal, ec);
 	}
 }
 
diff --git a/project2/common/if.h b/project2/common/if.h
index 2496dc4..64f885b 100644
--- a/project2/common/if.h
+++ b/project2/common/if.h
@@ -10,11 +10,11 @@ class If : public IHaveSubTasks, public View {
 	public:
 		If(ScriptNodePtr);
 
-		virtual void execute(const MultiRowSetPresenter*) const;
-		virtual void execute() const;
+		virtual void execute(const MultiRowSetPresenter *, ExecContext *) const;
+		virtual void execute(ExecContext *) const;
 
 	private:
-		bool passes() const;
+		bool passes(ExecContext *) const;
 
 		typedef ANONSTORAGEOF(View) SubViews;
 		SubViews subViews;
diff --git a/project2/common/iterate.cpp b/project2/common/iterate.cpp
index 037261d..4473885 100644
--- a/project2/common/iterate.cpp
+++ b/project2/common/iterate.cpp
@@ -27,22 +27,16 @@ Iterate::loadComplete(const CommonObjects * co)
 }
 
 void
-Iterate::rowReady(const RowState *) const
+Iterate::execute(ExecContext * ec) const
 {
-	executeChildren();
+	RowProcessor::execute(ec, boost::bind(&Iterate::executeChildren, this, ec));
 }
 
 void
-Iterate::execute() const
-{
-	RowProcessor::execute();
-}
-
-void
-Iterate::executeChildren() const
+Iterate::executeChildren(ExecContext * ec) const
 {
 	BOOST_FOREACH(const Tasks::value_type & sq, normal) {
-		sq->execute();
+		sq->execute(ec);
 	}
 }
 
diff --git a/project2/common/iterate.h b/project2/common/iterate.h
index 540cec6..2afbe98 100644
--- a/project2/common/iterate.h
+++ b/project2/common/iterate.h
@@ -15,11 +15,10 @@ class Iterate : public IHaveSubTasks, public RowProcessor {
 		virtual ~Iterate();
 
 		void loadComplete(const CommonObjects *);
-		void rowReady(const RowState *) const;
-		void execute() const;
+		void execute(ExecContext *) const;
 
 	protected:
-		void executeChildren() const;
+		void executeChildren(ExecContext *) const;
 };
 
 #endif
diff --git a/project2/common/library.cpp b/project2/common/library.cpp
index 4762211..738803f 100644
--- a/project2/common/library.cpp
+++ b/project2/common/library.cpp
@@ -11,7 +11,7 @@ SimpleMessageException(UnloadLibraryFailed);
 
 Library::Library(ScriptNodePtr p) :
 	SourceObject(p),
-	handle(dlopen(Variable(p, "path")(), RTLD_NOW))
+	handle(dlopen(Variable(p, "path")(NULL), RTLD_NOW))
 {
 	if (!handle) {
 		throw LoadLibraryFailed(dlerror());
diff --git a/project2/common/memoryCache.cpp b/project2/common/memoryCache.cpp
index 0a4f53f..7ab271e 100644
--- a/project2/common/memoryCache.cpp
+++ b/project2/common/memoryCache.cpp
@@ -43,7 +43,7 @@ class MemoryCache : public Cache {
 				{
 				}
 
-				void execute(const Glib::ustring&, const RowProcessor * rp) const {
+				void execute(const Glib::ustring&, const RowProcessorCallback & rp, ExecContext *) const {
 					BOOST_FOREACH(const DataCache::value_type & mcr, dataCache) {
 						mcr->process(rp, false);
 					}
@@ -100,8 +100,8 @@ class MemoryCache : public Cache {
 		{
 		}
 
-		RowSetCPtr getCachedRowSet(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const {
-			Key key(makeKey(n, f, ps));
+		RowSetCPtr getCachedRowSet(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const {
+			Key key(makeKey(ec, n, f, ps));
 			CacheStore::index<IndexByKey>::type::const_iterator i = Store.get<IndexByKey>().find(key);
 			if (i == Store.get<IndexByKey>().end()) {
 				return NULL;
@@ -113,27 +113,27 @@ class MemoryCache : public Cache {
 			return *i;
 		}
 
-		RowSetPresenterPtr openFor(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) {
-			return (cur = new CachedRowSet(makeKey(n, f, ps)));
+		RowSetPresenterPtr openFor(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) {
+			return (cur = new CachedRowSet(makeKey(ec, n, f, ps)));
 		}
 
-		void save(const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) {
+		void save(ExecContext *, const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) {
 			if (cur) {
 				Store.insert(cur);
 				cur.reset();
 			}
 		}
 
-		void discard(const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) {
+		void discard(ExecContext *, const Glib::ustring & , const Glib::ustring & , const IHaveParameters * ) {
 			cur.reset();
 		}
 
 	private:
-		Key makeKey(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const {
+		Key makeKey(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const {
 			Key key;
 			key.push_back(n);
 			key.push_back(f);
-			applyKeys([&key](const std::string &, const VariableType & v) { key.push_back(v); }, ps);
+			applyKeys(ec, [&key](const std::string &, const VariableType & v) { key.push_back(v); }, ps);
 			return key;
 		}
 
diff --git a/project2/common/noOutputExecute.h b/project2/common/noOutputExecute.h
index 67f6b00..61d03b5 100644
--- a/project2/common/noOutputExecute.h
+++ b/project2/common/noOutputExecute.h
@@ -5,6 +5,7 @@
 #include "scriptStorage.h"
 
 class NoOutputExecute;
+class ExecContext;
 typedef boost::intrusive_ptr<NoOutputExecute> NoOutputExecutePtr;
 
 /// Base class for Project2 compoments that perform actions, but product no output
@@ -15,7 +16,7 @@ class NoOutputExecute : public virtual SourceObject {
 
 		virtual ~NoOutputExecute();
 
-		virtual void execute() const = 0;
+		virtual void execute(ExecContext *) const = 0;
 };
 
 #endif
diff --git a/project2/common/options.cpp b/project2/common/options.cpp
index 5c79163..fd93576 100644
--- a/project2/common/options.cpp
+++ b/project2/common/options.cpp
@@ -1,6 +1,5 @@
 #include <pch.hpp>
 #include "options.h"
-#include "environment.h"
 #include <boost/foreach.hpp>
 
 class NamedOption : public Options::Option {
@@ -11,9 +10,9 @@ class NamedOption : public Options::Option {
 			desc(d)
 		{
 		}
-		void consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v) const {
+		void consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) const {
 			if (n == id) {
-				target->consume(p, v);
+				target->consume(p, v, cp);
 			}
 		}
 		void reset() const {
@@ -44,9 +43,9 @@ class OptionAlias : public Options::Option {
 			target(t)
 		{
 		}
-		void consume(const Glib::ustring & a, const Glib::ustring & p, const VariableType & v) const {
+		void consume(const Glib::ustring & a, const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) const {
 			if (a == alias) {
-				target->target->consume(p, v);
+				target->target->consume(p, v, cp);
 			}
 		}
 		void reset() const {
@@ -108,10 +107,10 @@ Options::reset() const
 }
 
 void
-Options::consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v) const
+Options::consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) const
 {
 	BOOST_FOREACH(const OptionPtr & o, options) {
-		o->consume(n, p, v);
+		o->consume(n, p, v, cp);
 	}
 }
 
@@ -145,13 +144,13 @@ Options::InstanceTarget::paramRequired() const
 }
 
 void
-Options::InstanceTarget::consume(const Glib::ustring & p, const VariableType & v) const
+Options::InstanceTarget::consume(const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) const
 {
 	if (ts != Platform && p.empty()) {
 		assign(v);
 		ts = Global;
 	}
-	else if (!p.empty() && p == Environment::getCurrent()->platform()) {
+	else if (!p.empty() && p == cp) {
 		assign(v);
 		ts = Platform;
 	}
diff --git a/project2/common/options.h b/project2/common/options.h
index e92e69b..c2416ef 100644
--- a/project2/common/options.h
+++ b/project2/common/options.h
@@ -15,11 +15,13 @@ class Options {
 		class Target;
 
 		enum TargetState { Default = 1, Global = 2, Platform = 3 };
+		typedef boost::function<const Glib::ustring &()> CurrentPlatform;
+
 		class Target : public IntrusivePtrBase {
 			public:
 				virtual void reset() const = 0;
 				virtual bool paramRequired() const = 0;
-				virtual void consume(const Glib::ustring & platform, const VariableType & value) const = 0;
+				virtual void consume(const Glib::ustring & platform, const VariableType & value, const CurrentPlatform & currentPlatform) const = 0;
 		};
 		typedef boost::intrusive_ptr<Target> TargetPtr;
 		typedef boost::function<void(const VariableType &)> Assigner;
@@ -29,7 +31,7 @@ class Options {
 			public:
 				InstanceTarget(const Assigner &, const Resetter &);
 				bool paramRequired() const;
-				void consume(const Glib::ustring & platform, const VariableType & value) const;
+				void consume(const Glib::ustring & platform, const VariableType & value, const CurrentPlatform & currentPlatform) const;
 			protected:
 				void reset() const;
 				void assign(const VariableType & value) const;
@@ -45,7 +47,7 @@ class Options {
 				virtual Glib::ustring name() const = 0;
 				virtual Glib::ustring description() const = 0;
 				virtual bool accepts(const Glib::ustring & name) const = 0;
-				virtual void consume(const Glib::ustring & name, const Glib::ustring & platform, const VariableType & value) const = 0;
+				virtual void consume(const Glib::ustring & name, const Glib::ustring & platform, const VariableType & value, const CurrentPlatform & currentPlatform) const = 0;
 		};
 		typedef boost::intrusive_ptr<Option> OptionPtr;
 		typedef std::list<OptionPtr> OptionList;
@@ -86,7 +88,7 @@ class Options {
 		}
 
 		void reset() const;
-		void consume(const Glib::ustring & name, const Glib::ustring & platform, const VariableType & value) const;
+		void consume(const Glib::ustring & name, const Glib::ustring & platform, const VariableType & value, const CurrentPlatform & currentPlatform) const;
 		const Option * find(const Glib::ustring & name) const;
 
 		const Glib::ustring name;
diff --git a/project2/common/optionsSource.cpp b/project2/common/optionsSource.cpp
index ed40df9..702b852 100644
--- a/project2/common/optionsSource.cpp
+++ b/project2/common/optionsSource.cpp
@@ -3,8 +3,8 @@
 
 class DefaultConfigConsumer : public ConfigConsumer {
 	public:
-		void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v) const {
-			Plugable::onAll<Options>(boost::bind(&Options::consume, _1, n, p, v));
+		void operator()(const Glib::ustring & n, const Glib::ustring & p, const Glib::ustring & v, const Options::CurrentPlatform & cp) const {
+			Plugable::onAll<Options>(boost::bind(&Options::consume, _1, n, p, v, cp));
 		}
 		const Options::Option * get(const Glib::ustring & n) const {
 			const Options::Option * rtn = NULL;
@@ -19,7 +19,7 @@ class DefaultConfigConsumer : public ConfigConsumer {
 };
 
 void
-OptionsSource::loadSources()
+OptionsSource::loadSources(const Options::CurrentPlatform & platform)
 {
 	const auto & configs = Plugable::ComponentType<OptionsSource>::components();
 	if (std::find_if(configs->begin(), configs->end(), boost::bind(&OptionsSource::needReload, _1)) != configs->end()) {
@@ -27,7 +27,7 @@ OptionsSource::loadSources()
 
 		DefaultConfigConsumer dcc;
 		BOOST_FOREACH(const auto & c, *configs) {
-			c->loadInto(dcc);
+			c->loadInto(dcc, platform);
 		}
 		Plugable::onAllComponents(boost::bind(&ComponentLoader::onConfigLoad, _1));
 		
diff --git a/project2/common/optionsSource.h b/project2/common/optionsSource.h
index 49bb876..d6f41ab 100644
--- a/project2/common/optionsSource.h
+++ b/project2/common/optionsSource.h
@@ -9,17 +9,17 @@
 
 class ConfigConsumer {
 	public:
-		virtual void operator()(const Glib::ustring &, const Glib::ustring &, const Glib::ustring &) const = 0;
+		virtual void operator()(const Glib::ustring &, const Glib::ustring &, const Glib::ustring &, const Options::CurrentPlatform &) const = 0;
 		virtual const Options::Option * get(const Glib::ustring & name) const = 0;
 };
 
 /// Base class of things that load options
 class OptionsSource {
 	public:
-		virtual void loadInto(const ConfigConsumer &) const = 0;
+		virtual void loadInto(const ConfigConsumer &, const Options::CurrentPlatform & platform) const = 0;
 		virtual bool needReload() const = 0;
 
-		static void loadSources();
+		static void loadSources(const Options::CurrentPlatform & platform);
 };
 typedef boost::intrusive_ptr<OptionsSource> OptionsSourcePtr;
 
diff --git a/project2/common/presenter.cpp b/project2/common/presenter.cpp
index 1e5bbf2..4e12307 100644
--- a/project2/common/presenter.cpp
+++ b/project2/common/presenter.cpp
@@ -1,7 +1,6 @@
 #include <pch.hpp>
 #include "presenter.h"
 #include "dataSource.h"
-#include "appEngine.h"
 #include <boost/foreach.hpp>
 
 NameValuePairPresenter::NameValuePairPresenter()
diff --git a/project2/common/presenter.h b/project2/common/presenter.h
index f9069de..3ea56e7 100644
--- a/project2/common/presenter.h
+++ b/project2/common/presenter.h
@@ -39,7 +39,7 @@ class MultiRowSetPresenter : public RowSetPresenter {
 		virtual void finishRowSet() const = 0;
 		virtual void addNewArray(const Glib::ustring & name, bool objects) const = 0;
 		virtual void finishArray(bool objects) const = 0;
-		virtual void init() = 0;
+		virtual void init(ExecContext *) = 0;
 		virtual void finalizeContent() const;
 };
 
@@ -77,7 +77,7 @@ typedef boost::intrusive_ptr<RowSetPresenter> RowSetPresenterPtr;
 typedef boost::intrusive_ptr<MultiRowSetPresenter> MultiRowSetPresenterPtr;
 typedef boost::intrusive_ptr<NameValuePairPresenter> NameValuePairPresenterPtr;
 
-typedef GenLoader<MultiRowSetPresenter, ScriptNodePtr, ObjectSource> PresenterLoader;
+typedef GenLoader<MultiRowSetPresenter, ScriptNodePtr, ObjectSource, ExecContext *> PresenterLoader;
 
 #endif
 
diff --git a/project2/common/presenterCache.cpp b/project2/common/presenterCache.cpp
index 6ca3661..31fdc8f 100644
--- a/project2/common/presenterCache.cpp
+++ b/project2/common/presenterCache.cpp
@@ -4,7 +4,7 @@
 PresenterCache::PresenterCache(ScriptNodePtr s) :
 	SourceObject(s),
 	IHaveParameters(s),
-	encoding(s->value("encoding", "utf-8").as<std::string>())
+	encoding(s->value("encoding", "utf-8", NULL).as<std::string>())
 {
 }
 
@@ -15,8 +15,8 @@ PresenterCache::flushCache()
 
 class WriteToCache : public TransformImpl<WritableContent, PresenterCache> {
 	public:
-		void transform(const WritableContent * wc, PresenterCache * pc) const {
-			wc->writeTo(pc->writeCache(wc->getContentType(), pc->encoding), pc->encoding);
+		void transform(const WritableContent * wc, PresenterCache * pc, ExecContext * ec) const {
+			wc->writeTo(pc->writeCache(wc->getContentType(), pc->encoding, ec), pc->encoding, ec);
 		}
 };
 DECLARE_TRANSFORM(WriteToCache);
diff --git a/project2/common/presenterCache.h b/project2/common/presenterCache.h
index 799181b..b0adab8 100644
--- a/project2/common/presenterCache.h
+++ b/project2/common/presenterCache.h
@@ -8,9 +8,9 @@
 class PresenterCache : public SourceObject, public virtual TransformSource, public StaticContent, public SourceOf<StaticContent>, public IHaveParameters {
 	public:
 		PresenterCache(ScriptNodePtr);
-		virtual bool check(time_t scriptMtime) const = 0;
+		virtual bool check(time_t scriptMtime, ExecContext *) const = 0;
 
-		virtual std::ostream & writeCache(const std::string & ct, const std::string & encoding) = 0;
+		virtual std::ostream & writeCache(const std::string & ct, const std::string & encoding, ExecContext *) = 0;
 		virtual void flushCache();
 		const std::string encoding;
 };
diff --git a/project2/common/rowProcessor.cpp b/project2/common/rowProcessor.cpp
index 4e3bf1d..26ca433 100644
--- a/project2/common/rowProcessor.cpp
+++ b/project2/common/rowProcessor.cpp
@@ -8,10 +8,10 @@
 
 RowProcessor::RowProcessor(ScriptNodePtr p) :
 	IHaveParameters(p),
-	recordSource(p->value("source").as<std::string>()),
-	filter(p->value("filter", "").as<Glib::ustring>()),
-	CROE(p->value("cacheRowsOnError", false)),
-	IRSE(p->value("ignoreRowSourceError", false))
+	recordSource(p->value("source", NULL).as<std::string>()),
+	filter(p->value("filter", "", NULL).as<Glib::ustring>()),
+	CROE(p->value("cacheRowsOnError", false, NULL)),
+	IRSE(p->value("ignoreRowSourceError", false, NULL))
 {
 	p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&caches));
 	p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&tests));
@@ -24,19 +24,19 @@ RowProcessor::loadComplete(const CommonObjects * co)
 }
 
 void
-RowProcessor::execute() const
+RowProcessor::execute(ExecContext * ec, const RowProcessorCallback & cb) const
 {
 	IHaveParameters::push(this);
 	ScopeObject _ihp(
 			boost::bind(&IHaveParameters::pop),
-			boost::bind(&RowProcessor::saveCaches, this),
-			boost::bind((CROE ? &RowProcessor::saveCaches : &RowProcessor::discardCaches), this),
+			boost::bind(&RowProcessor::saveCaches, this, ec),
+			boost::bind((CROE ? &RowProcessor::saveCaches : &RowProcessor::discardCaches), this, ec),
 			boost::bind(&TargetCaches::clear, &tc));
 	BOOST_FOREACH(const CachePtr & c, caches) {
-		if (c->checkAndExecute(source->name, filter, this)) {
+		if (c->checkAndExecute(ec, source->name, filter, this, cb)) {
 			return;
 		}
-		RowSetPresenterPtr p = c->openFor(source->name, filter, this);
+		RowSetPresenterPtr p = c->openFor(ec, source->name, filter, this);
 		if (p) {
 			tc.insert(TargetCachePtr(new TargetCache(p, c)));
 		}
@@ -47,44 +47,44 @@ RowProcessor::execute() const
 	}
 	if (IRSE) {
 		try {
-			source->execute(filter, this);
+			source->execute(filter, cb, ec);
 		}
 		catch (const std::exception & e) {
 			Logger()->messagebf(LOG_WARNING, "Source '%s' failed with '%s'", source->name, e.what());
 		}
 	}
 	else {
-		source->execute(filter, this);
+		source->execute(filter, cb, ec);
 	}
 }
 
 void
-RowProcessor::saveCaches() const
+RowProcessor::saveCaches(ExecContext * ec) const
 {
 	BOOST_FOREACH(const TargetCaches::value_type & c, tc) {
-		c->get<1>()->save(source->name, filter, this);
+		c->get<1>()->save(ec, source->name, filter, this);
 	}
 }
 
 void
-RowProcessor::discardCaches() const
+RowProcessor::discardCaches(ExecContext * ec) const
 {
 	BOOST_FOREACH(const TargetCaches::value_type & c, tc) {
-		c->get<1>()->discard(source->name, filter, this);
+		c->get<1>()->discard(ec, source->name, filter, this);
 	}
 }
 
 void
-RowProcessor::rowReadyInternal(const RowState * rs) const
+RowProcessor::rowReadyInternal(const RowState * rs, const RowProcessorCallback & cb, ExecContext * ec) const
 {
 	BOOST_FOREACH(const TargetCaches::value_type & c, tc) {
 		c->get<0>()->addNewRow(filter.empty() ? "row" : filter);
-		rs->foreachColumn(boost::bind(&RowSetPresenter::addNamedValue, c->get<0>(), _2, _3));
+		rs->foreachColumn(ec, boost::bind(&RowSetPresenter::addNamedValue, c->get<0>(), _2, _3));
 		rs->foreachAttr(boost::bind(&RowSetPresenter::addAttribute, c->get<0>(), _1, _2));
 		c->get<0>()->finishRow();
 	}
-	if (boost::algorithm::all(tests, boost::bind(&Test::passes, _1))) {
-		rowReady(rs);
+	if (boost::algorithm::all(tests, boost::bind(&Test::passes, _1, ec))) {
+		cb(rs);
 	}
 }
 
diff --git a/project2/common/rowProcessor.h b/project2/common/rowProcessor.h
index 04a61bf..70f453c 100644
--- a/project2/common/rowProcessor.h
+++ b/project2/common/rowProcessor.h
@@ -10,6 +10,7 @@
 #include "scriptStorage.h"
 
 class Presenter;
+class ExecContext;
 
 /// Base class for Project2 components that work with row sets
 class RowProcessor : public IHaveParameters {
@@ -25,12 +26,11 @@ class RowProcessor : public IHaveParameters {
 
 	protected:
 		boost::intrusive_ptr<RowSet> source;
-		void execute() const;
+		void execute(ExecContext *, const RowProcessorCallback &) const;
 
 	private:
 		friend class RowState;
-		void rowReadyInternal(const RowState *) const;
-		virtual void rowReady(const RowState *) const = 0;
+		void rowReadyInternal(const RowState *, const RowProcessorCallback &, ExecContext *) const;
 		typedef ANONSTORAGEOF(Test) Tests;
 		Tests tests;
 		typedef ANONORDEREDSTORAGEOF(Cache) Caches;
@@ -40,8 +40,8 @@ class RowProcessor : public IHaveParameters {
 		typedef std::set<TargetCachePtr> TargetCaches;
 		mutable TargetCaches tc;
 
-		void saveCaches() const;
-		void discardCaches() const;
+		void saveCaches(ExecContext *) const;
+		void discardCaches(ExecContext *) const;
 };
 
 #endif
diff --git a/project2/common/rowSet.cpp b/project2/common/rowSet.cpp
index 0378b51..daa81b3 100644
--- a/project2/common/rowSet.cpp
+++ b/project2/common/rowSet.cpp
@@ -4,7 +4,6 @@
 #include "scopeObject.h"
 #include "logger.h"
 #include "variables.h"
-#include "rowProcessor.h"
 #include <boost/foreach.hpp>
 #include <boost/bind.hpp>
 
@@ -29,12 +28,12 @@ RowState::~RowState()
 }
 
 void
-RowState::process(const RowProcessor * rp, bool r)
+RowState::process(const RowProcessorCallback & rp, bool r)
 {
 	rowNum += 1;
 	stack.push_back(this);
 	ScopeObject s(boost::bind(&RowState::RowValuesStack::pop_back, &stack));
-	rp->rowReadyInternal(this);
+	rp(this);
 	if (r) {
 		reset();
 	}
@@ -70,13 +69,13 @@ RowState::resolveAttr(const Glib::ustring & attrName) const
 }
 
 VariableType
-RowState::getCurrentValue(const Glib::ustring & col) const
+RowState::getCurrentValue(ExecContext * ec, const Glib::ustring & col) const
 {
 	const Columns & columns = getColumns();
 	Columns::index<byColName>::type::iterator di = columns.get<byColName>().find(col);
 	if (di != columns.get<byColName>().end()) {
 		if (fields[(*di)->idx].isNull()) {
-			return (*di)->defValue;
+			return (*di)->defValue(ec);
 		}
 		return fields[(*di)->idx];
 	}
@@ -84,11 +83,11 @@ RowState::getCurrentValue(const Glib::ustring & col) const
 }
 
 void
-RowState::foreachColumn(const ColumnAction & action) const
+RowState::foreachColumn(ExecContext * ec, const ColumnAction & action) const
 {
 	const Columns & columns = getColumns();
 	BOOST_FOREACH(const Columns::value_type & col, columns.get<byColName>()) {
-		action(col->idx, col->name, (!boost::get<Null>(&fields[col->idx])) ? fields[col->idx] : col->defValue());
+		action(col->idx, col->name, (!boost::get<Null>(&fields[col->idx])) ? fields[col->idx] : col->defValue(ec));
 	}
 }
 
diff --git a/project2/common/rowSet.h b/project2/common/rowSet.h
index 2845983..50dd3fd 100644
--- a/project2/common/rowSet.h
+++ b/project2/common/rowSet.h
@@ -8,13 +8,13 @@
 #include "columns.h"
 #include <boost/function.hpp>
 
-class RowProcessor;
 class RowSet;
 class VariableType;
+class RowState;
+
 typedef boost::intrusive_ptr<RowSet> RowSetPtr;
 typedef boost::intrusive_ptr<const RowSet> ConstRowSetPtr;
-
-class RowState;
+typedef boost::function<void(const RowState *)> RowProcessorCallback;
 
 /// Base class for Project2 components that provide a row set representation of data
 class RowSet : public SourceObject {
@@ -26,7 +26,7 @@ class RowSet : public SourceObject {
 		RowSet(ScriptNodePtr);
 		virtual ~RowSet() = 0;
 
-		virtual void execute(const Glib::ustring &, const RowProcessor *) const = 0;
+		virtual void execute(const Glib::ustring &, const RowProcessorCallback &, ExecContext *) const = 0;
 };
 
 class RowState {
@@ -40,12 +40,12 @@ class RowState {
 		SimpleMessageException(AttributeDoesNotExist);
 
 		VariableType getRowNum() const;
-		void process(const RowProcessor *, bool reset = true);
+		void process(const RowProcessorCallback &, bool reset = true);
 		void blankRow();
 		void reset();
-		virtual VariableType getCurrentValue(const Glib::ustring & id) const;
+		virtual VariableType getCurrentValue(ExecContext *, const Glib::ustring & id) const;
 		virtual RowAttribute resolveAttr(const Glib::ustring & attrName) const;
-		void foreachColumn(const ColumnAction & action) const;
+		void foreachColumn(ExecContext * ec, const ColumnAction & action) const;
 		virtual void foreachAttr(const AttrAction & action) const;
 		virtual const Columns & getColumns() const = 0;
 
diff --git a/project2/common/rowView.cpp b/project2/common/rowView.cpp
index c0e5cae..b9508bd 100644
--- a/project2/common/rowView.cpp
+++ b/project2/common/rowView.cpp
@@ -16,9 +16,7 @@ RowView::RowView(ScriptNodePtr p) :
 	rootName(p, "rootname", Null()),
 	recordName(p, "recordname"),
 	required(p, "required", false),
-	isObject(p, "isobject", true),
-	presenter(NULL),
-	rowsFound(false)
+	isObject(p, "isobject", true)
 {
 	BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("columns")) {
 		viewColumns.insert(Columns::value_type(node->get_name(), Variable(node)));
@@ -39,67 +37,66 @@ RowView::loadComplete(const CommonObjects * co)
 }
 
 void
-RowView::rowReady(const RowState * rs) const
+RowView::rowReady(const RowState * rs, const MultiRowSetPresenter * presenter, ExecContext * ec, bool & rowsFound) const
 {
 	rowsFound = true;
-	if (isObject()) {
-		presenter->addNewRow(recordName());
+	if (isObject(ec)) {
+		presenter->addNewRow(recordName(ec));
 	}
 	if (viewColumns.empty()) {
-		rs->foreachColumn(boost::bind(&RowSetPresenter::addNamedValue, presenter, _2, _3));
+		rs->foreachColumn(ec, boost::bind(&RowSetPresenter::addNamedValue, presenter, _2, _3));
 	}
 	else {
 		BOOST_FOREACH(const Columns::value_type & col, viewColumns) {
-			presenter->addNamedValue(col.first, col.second);
+			presenter->addNamedValue(col.first, col.second(ec));
 		}
 	}
-	if (isObject()) {
-		executeChildren();
+	if (isObject(ec)) {
+		executeChildren(presenter, ec);
 		presenter->finishRow();
 	}
 	BOOST_FOREACH(SetAggregateCPtr s, setAggregates) {
-		s->pushValue();
+		s->pushValue(ec);
 	}
 	BOOST_FOREACH(ValueAggregateCPtr a, valueAggregates) {
-		a->pushValue();
+		a->pushValue(ec);
 	}
 }
 
 void
-RowView::execute(const MultiRowSetPresenter * p) const
+RowView::execute(const MultiRowSetPresenter * p, ExecContext * ec) const
 {
-	rowsFound = false;
-	presenter = p;
-	if (!rootName().isNull()) {
-		presenter->addNewRowSet(rootName());
+	if (!rootName(ec).isNull()) {
+		p->addNewRowSet(rootName(ec));
 	}
-	ScopeObject pres(rootName().isNull() ? ScopeObject::Event() : boost::bind(&MultiRowSetPresenter::finishRowSet, p));
+	bool rowsFound = false;
+	ScopeObject pres(rootName(ec).isNull() ? ScopeObject::Event() : boost::bind(&MultiRowSetPresenter::finishRowSet, p));
 	{
-		presenter->addNewArray(recordName(), true);
+		p->addNewArray(recordName(ec), true);
 		ScopeObject pres(boost::bind(&MultiRowSetPresenter::finishArray, p, true));
-		RowProcessor::execute();
+		RowProcessor::execute(ec, boost::bind(&RowView::rowReady, this, _1, p, ec, boost::ref(rowsFound)));
 	}
-	if (required() && !rowsFound) {
+	if (required(ec) && !rowsFound) {
 		throw EmptyRequiredRows(name);
 	}
 
 	BOOST_FOREACH(SetAggregateCPtr s, setAggregates) {
-		presenter->addNewArray(s->name, false);
+		p->addNewArray(s->name, false);
 		ScopeObject pres(boost::bind(&MultiRowSetPresenter::finishArray, p, false));
 		s->onResultValues(boost::bind(&MultiRowSetPresenter::addNamedValue, p, "value", _1));
 		s->reset();
 	}
 	BOOST_FOREACH(ValueAggregateCPtr a, valueAggregates) {
-		presenter->addNamedValue(a->name, a->resultValue());
+		p->addNamedValue(a->name, a->resultValue());
 		a->reset();
 	}
 }
 
 void
-RowView::executeChildren() const
+RowView::executeChildren(const MultiRowSetPresenter * presenter, ExecContext * ec) const
 {
 	BOOST_FOREACH(const SubViews::value_type & sq, subViews) {
-		sq->execute(presenter);
+		sq->execute(presenter, ec);
 	}
 }
 
diff --git a/project2/common/rowView.h b/project2/common/rowView.h
index 534a06f..d2745db 100644
--- a/project2/common/rowView.h
+++ b/project2/common/rowView.h
@@ -13,8 +13,8 @@ class RowView : public View, public RowProcessor {
 		virtual ~RowView();
 
 		void loadComplete(const CommonObjects *);
-		void execute(const MultiRowSetPresenter *) const;
-		void rowReady(const RowState *) const;
+		void execute(const MultiRowSetPresenter *, ExecContext *) const;
+		void rowReady(const RowState *, const MultiRowSetPresenter *, ExecContext *, bool & found) const;
 
 		const Variable rootName;
 		const Variable recordName;
@@ -25,16 +25,13 @@ class RowView : public View, public RowProcessor {
 		typedef std::map<Glib::ustring, Variable> Columns;
 		Columns viewColumns;
 
-		void executeChildren() const;
+		void executeChildren(const MultiRowSetPresenter * presenter, ExecContext *) const;
 		typedef ANONORDEREDSTORAGEOF(View) SubViews;
 		SubViews subViews;
 		typedef ANONSTORAGEOF(ValueAggregate) ValueAggregates;
 		ValueAggregates valueAggregates;
 		typedef ANONSTORAGEOF(SetAggregate) SetAggregates;
 		SetAggregates setAggregates;
-		mutable const MultiRowSetPresenter * presenter;
-
-		mutable bool rowsFound;
 };
 
 #endif
diff --git a/project2/common/scriptLoader.cpp b/project2/common/scriptLoader.cpp
index ab02f02..fe8799b 100644
--- a/project2/common/scriptLoader.cpp
+++ b/project2/common/scriptLoader.cpp
@@ -3,7 +3,6 @@
 #include "scriptLoader.h"
 #include "scriptStorage.h"
 #include "library.h"
-#include "appEngine.h"
 #include <boost/shared_ptr.hpp>
 #include <boost/foreach.hpp>
 #include <boost/function.hpp>
diff --git a/project2/common/scripts.cpp b/project2/common/scripts.cpp
index 767ff0d..f065e4b 100644
--- a/project2/common/scripts.cpp
+++ b/project2/common/scripts.cpp
@@ -32,20 +32,20 @@ ScriptNode::variable(const Glib::ustring & n, const VariableType & def) const
 }
 
 VariableType
-ScriptNode::value(const Glib::ustring & n, const VariableType & def) const
+ScriptNode::value(const Glib::ustring & n, const VariableType & def, ExecContext * ec) const
 {
 	VariableType r;
-	if (applyValue(n, r)) {
+	if (applyValue(n, r, ec)) {
 		return r;
 	}
 	return def;
 }
 
 VariableType
-ScriptNode::value(const Glib::ustring & n) const
+ScriptNode::value(const Glib::ustring & n, ExecContext * ec) const
 {
 	VariableType r;
-	if (applyValue(n, r)) {
+	if (applyValue(n, r, ec)) {
 		return r;
 	}
 	throw ValueNotFound(n);
diff --git a/project2/common/scripts.h b/project2/common/scripts.h
index 0cb478c..7bf6326 100644
--- a/project2/common/scripts.h
+++ b/project2/common/scripts.h
@@ -18,6 +18,7 @@ SimpleMessage2Exception(ScriptNotFound);
 SimpleMessage2Exception(DependencyNotFound);
 
 class VariableImpl;
+class ExecContext;
 
 class Scripts {
 	public:
@@ -45,12 +46,12 @@ class ScriptNode : public IntrusivePtrBase {
 		virtual ScriptNodes childrenIn(const Glib::ustring & sub) const = 0;
 		
 		virtual bool valueExists(const Glib::ustring & name) const = 0;
-		virtual bool applyValue(const Glib::ustring & name, VariableType & target) const = 0;
+		virtual bool applyValue(const Glib::ustring & name, VariableType & target, ExecContext *) const = 0;
 		virtual VariableImpl * variable(const boost::optional<Glib::ustring> & defaultSource = boost::optional<Glib::ustring>()) const = 0;
 		virtual VariableImpl * variable(const Glib::ustring & name) const = 0;
 		VariableImpl * variable(const Glib::ustring & name, const VariableType & def) const;
-		VariableType value(const Glib::ustring & name) const;
-		VariableType value(const Glib::ustring & name, const VariableType & def) const;
+		VariableType value(const Glib::ustring & name, ExecContext *) const;
+		VariableType value(const Glib::ustring & name, const VariableType & def, ExecContext *) const;
 		virtual void composeWithCallbacks(const LiteralCallback &, const NodeCallback &) const = 0;
 
 		const ScriptReaderPtr script;
diff --git a/project2/common/sessionClearTask.cpp b/project2/common/sessionClearTask.cpp
index b3b1000..265bb1c 100644
--- a/project2/common/sessionClearTask.cpp
+++ b/project2/common/sessionClearTask.cpp
@@ -2,15 +2,15 @@
 #include <boost/foreach.hpp>
 #include "scriptLoader.h"
 #include "sessionClearTask.h"
-#include "appEngine.h"
 #include "session.h"
+#include "execContext.h"
 
 DECLARE_LOADER("sessionclear", SessionClearTask);
 
 SessionClearTask::SessionClearTask(ScriptNodePtr p) :
 	SourceObject(p),
 	Task(p),
-	key(p->value("key").as<Glib::ustring>())
+	key(p->value("key", NULL).as<Glib::ustring>())
 {
 }
 
@@ -19,8 +19,8 @@ SessionClearTask::~SessionClearTask()
 }
 
 void
-SessionClearTask::execute() const
+SessionClearTask::execute(ExecContext * ec) const
 {
-	ApplicationEngine::getCurrent()->session()->ClearValue(key);
+	ec->getSession()->ClearValue(key);
 }
 
diff --git a/project2/common/sessionClearTask.h b/project2/common/sessionClearTask.h
index c7def60..ead88bf 100644
--- a/project2/common/sessionClearTask.h
+++ b/project2/common/sessionClearTask.h
@@ -15,7 +15,7 @@ class SessionClearTask : public Task {
 		SessionClearTask(ScriptNodePtr p);
 		virtual ~SessionClearTask();
 
-		void execute() const;
+		void execute(ExecContext *) const;
 
 		const Glib::ustring key;
 };
diff --git a/project2/common/sessionContainer.cpp b/project2/common/sessionContainer.cpp
index e9c76c9..41c3f98 100644
--- a/project2/common/sessionContainer.cpp
+++ b/project2/common/sessionContainer.cpp
@@ -1,6 +1,5 @@
 #include <pch.hpp>
 #include "sessionContainer.h"
-#include "environment.h"
 
 SessionContainer::SessionContainer()
 {
diff --git a/project2/common/sessionSetTask.cpp b/project2/common/sessionSetTask.cpp
index aca5b26..f46571b 100644
--- a/project2/common/sessionSetTask.cpp
+++ b/project2/common/sessionSetTask.cpp
@@ -2,15 +2,15 @@
 #include <boost/foreach.hpp>
 #include "scriptLoader.h"
 #include "sessionSetTask.h"
-#include "appEngine.h"
 #include "session.h"
+#include "execContext.h"
 
 DECLARE_LOADER("sessionset", SessionSetTask);
 
 SessionSetTask::SessionSetTask(ScriptNodePtr p) :
 	SourceObject(p),
 	Task(p),
-	key(p->value("key").as<Glib::ustring>()),
+	key(p->value("key", NULL).as<Glib::ustring>()),
 	value(p, "value")
 {
 }
@@ -20,8 +20,8 @@ SessionSetTask::~SessionSetTask()
 }
 
 void
-SessionSetTask::execute() const
+SessionSetTask::execute(ExecContext * ec) const
 {
-	ApplicationEngine::getCurrent()->session()->SetValue(key, value);
+	ec->getSession()->SetValue(key, value(ec));
 }
 
diff --git a/project2/common/sessionSetTask.h b/project2/common/sessionSetTask.h
index 8e88837..d38c216 100644
--- a/project2/common/sessionSetTask.h
+++ b/project2/common/sessionSetTask.h
@@ -16,7 +16,7 @@ class SessionSetTask : public Task {
 		SessionSetTask(ScriptNodePtr p);
 		virtual ~SessionSetTask();
 
-		void execute() const;
+		void execute(ExecContext *) const;
 
 		const Glib::ustring key;
 		const Variable value;
diff --git a/project2/common/singleton.cpp b/project2/common/singleton.cpp
index 0aaf5f7..eff3f94 100644
--- a/project2/common/singleton.cpp
+++ b/project2/common/singleton.cpp
@@ -10,29 +10,28 @@ class Singleton : public View {
 		Singleton(ScriptNodePtr p) :
 			SourceObject(p),
 			View(p),
-			rootName(p, "rootname"),
-			presenter(NULL) {
+			rootName(p, "rootname")
+		{
 			BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("columns")) {
 				viewColumns.insert(Columns::value_type(node->get_name(), Variable(node)));
 			}
 			p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&subViews));
 		}
-		void execute(const MultiRowSetPresenter * p) const
+		void execute(const MultiRowSetPresenter * p, ExecContext * ec) const
 		{
-			presenter = p;
-			presenter->addNewRowSet(rootName());
+			p->addNewRowSet(rootName(ec));
 			ScopeObject pres(boost::bind(&MultiRowSetPresenter::finishRowSet, p));
 			BOOST_FOREACH(const Columns::value_type & col, viewColumns) {
-				p->addNamedValue(col.first, col.second);
+				p->addNamedValue(col.first, col.second(ec));
 			}
 		}
 
 		const Variable rootName;
 	private:
-		void executeChildren() const
+		void executeChildren(const MultiRowSetPresenter * p, ExecContext * ec) const
 		{
 			BOOST_FOREACH(const SubViews::value_type & sq, subViews) {
-				sq->execute(presenter);
+				sq->execute(p, ec);
 			}
 		}
 
@@ -41,7 +40,6 @@ class Singleton : public View {
 
 		typedef ANONSTORAGEOF(View) SubViews;
 		SubViews subViews;
-		mutable const MultiRowSetPresenter * presenter;
 };
 DECLARE_LOADER("singleton", Singleton);
 
diff --git a/project2/common/sourceObject.cpp b/project2/common/sourceObject.cpp
index 03f06b5..b451919 100644
--- a/project2/common/sourceObject.cpp
+++ b/project2/common/sourceObject.cpp
@@ -8,7 +8,7 @@ unsigned int SourceObject::loadOrder = 1;
 SimpleMessageException(ComponentNotFound);
 
 SourceObject::SourceObject(ScriptNodePtr p) :
-	name(p ? p->value("name", "anon").as<std::string>() : "anon"),
+	name(p ? p->value("name", "anon", NULL).as<std::string>() : "anon"),
 	order(loadOrder++),
 	script(p->script.get())
 {
diff --git a/project2/common/stream.h b/project2/common/stream.h
index eebefab..ad3ee79 100644
--- a/project2/common/stream.h
+++ b/project2/common/stream.h
@@ -4,12 +4,14 @@
 #include "sourceObject.h"
 #include <boost/function.hpp>
 
+class ExecContext;
+
 class Stream : public SourceObject {
 	public:
 		template<typename... X> Stream(const X &... x) : SourceObject(x...) { }
 
 		typedef boost::function<size_t(const char *, size_t)> Sink;
-		virtual void runStream(const Sink &) const = 0;
+		virtual void runStream(const Sink &, ExecContext *) const = 0;
 };
 typedef boost::intrusive_ptr<Stream> StreamPtr;
 
diff --git a/project2/common/structExceptHandling.cpp b/project2/common/structExceptHandling.cpp
index 0881d6d..917f030 100644
--- a/project2/common/structExceptHandling.cpp
+++ b/project2/common/structExceptHandling.cpp
@@ -23,22 +23,22 @@ StructuredExceptionHandler::loadComplete(const CommonObjects * co)
 }
 
 void
-StructuredExceptionHandler::execute() const
+StructuredExceptionHandler::execute(ExecContext * ec) const
 {
 	try {
-		run(normal);
+		run(normal, ec);
 	}
 	catch (...) {
 		try {
-			run(catches);
-			run(finallies);
+			run(catches, ec);
+			run(finallies, ec);
 			return;
 		}
 		catch (...) {
 		}
-		run(finallies);
+		run(finallies, ec);
 		throw;
 	}
-	run(finallies);
+	run(finallies, ec);
 }
 
diff --git a/project2/common/structExceptHandling.h b/project2/common/structExceptHandling.h
index 067c389..b6702f1 100644
--- a/project2/common/structExceptHandling.h
+++ b/project2/common/structExceptHandling.h
@@ -8,7 +8,7 @@ class StructuredExceptionHandler : public IHaveSubTasks {
 		StructuredExceptionHandler(ScriptNodePtr);
 
 		void loadComplete(const CommonObjects*);
-		void execute() const;
+		void execute(ExecContext * ec) const;
 
 	private:
 		Tasks catches, finallies;
diff --git a/project2/common/task.h b/project2/common/task.h
index 5303f15..15ccfbd 100644
--- a/project2/common/task.h
+++ b/project2/common/task.h
@@ -9,7 +9,7 @@ class Task : public NoOutputExecute {
 	public:
 		Task(ScriptNodePtr p);
 		virtual ~Task();
-		virtual void execute() const = 0;
+		virtual void execute(ExecContext *) const = 0;
 };
 
 #endif
diff --git a/project2/common/taskHost.cpp b/project2/common/taskHost.cpp
index cbfe7c3..07f7601 100644
--- a/project2/common/taskHost.cpp
+++ b/project2/common/taskHost.cpp
@@ -27,11 +27,11 @@ TaskHost::loadComplete(const CommonObjects * co)
 }
 
 void
-TaskHost::execute() const
+TaskHost::execute(ExecContext * ec) const
 {
 	loadScriptComponents();
 	ScopeObject txHandler(ScopeObject::Event(), boost::bind(&TaskHost::commitAll, this), boost::bind(&TaskHost::rollbackAll, this));
-	run(tasks);
+	run(tasks, ec);
 }
 
 void
diff --git a/project2/common/taskHost.h b/project2/common/taskHost.h
index edecda6..e4b8b3a 100644
--- a/project2/common/taskHost.h
+++ b/project2/common/taskHost.h
@@ -15,7 +15,7 @@ class TaskHost : public IHaveSubTasks, virtual public CheckHost, virtual public
 		virtual ~TaskHost();
 
 		void loadComplete(const CommonObjects *);
-		void execute() const;
+		void execute(ExecContext *) const;
 
 		Tasks tasks;
 
diff --git a/project2/common/test.h b/project2/common/test.h
index 4f87c10..7cf563c 100644
--- a/project2/common/test.h
+++ b/project2/common/test.h
@@ -4,10 +4,12 @@
 #include "sourceObject.h"
 #include "scripts.h"
 
+class ExecContext;
+
 class Test : public virtual SourceObject {
 	public:
 		Test(ScriptNodePtr);
-		virtual bool passes() const = 0;
+		virtual bool passes(ExecContext *) const = 0;
 		virtual void reset() const;
 };
 typedef boost::intrusive_ptr<const Test> TestPtr;
diff --git a/project2/common/transform.cpp b/project2/common/transform.cpp
index fb92486..efe9bf6 100644
--- a/project2/common/transform.cpp
+++ b/project2/common/transform.cpp
@@ -19,7 +19,7 @@ class TransformTargetStorer : public Storer {
 		{
 			TransformChainLinkPtr O = boost::dynamic_pointer_cast<TransformChainLink>(o);
 			if (O) {
-				transformSource->addTarget(O, s);
+				transformSource->addTarget(O, NULL, s);
 			}
 			return O;
 		}
@@ -44,13 +44,13 @@ TransformChainLink::~TransformChainLink()
 
 typedef std::map<std::string, boost::shared_ptr<TransformLoader> > TransformLoaderMap;
 void
-TransformSource::addTarget(TransformChainLinkPtr tcl, ScriptNodePtr e)
+TransformSource::addTarget(TransformChainLinkPtr tcl, ExecContext * ec, ScriptNodePtr e)
 {
 	BOOST_FOREACH(const TransformLoaderMap::value_type & tl, *Plugable::objLoaders<TransformLoader>()) {
 		TransformPtr t = tl.second->create();
 		if (t->canTransform(this, tcl.get())) {
 			if (e) {
-				t->configure(e);
+				t->configure(e, ec);
 			}
 			targets[tcl] = t;
 			return;
@@ -72,12 +72,12 @@ TransformSource::removeTarget(TransformChainLinkPtr tcl)
 }
 
 void
-TransformSource::doTransforms() const
+TransformSource::doTransforms(ExecContext * ec) const
 {
 	BOOST_FOREACH(const Targets::value_type & t, targets) {
-		t.second->transform(this, t.first.get());
+		t.second->transform(this, t.first.get(), ec);
 		if (const TransformSource * tr = dynamic_cast<const TransformSource *>(t.first.get())) {
-			tr->doTransforms();
+			tr->doTransforms(ec);
 		}
 	}
 }
@@ -90,16 +90,16 @@ TransformSource::getTargets() const
 
 class TransformWritableContentToStdStream : public TransformImpl<WritableContent, ostreamWrapper> {
 	public:
-		void transform(const WritableContent * wc, ostreamWrapper * o) const
+		void transform(const WritableContent * wc, ostreamWrapper * o, ExecContext * ec) const
 		{
-			wc->writeTo(o->strm, "UTF-8");
+			wc->writeTo(o->strm, "UTF-8", ec);
 		}
 };
 DECLARE_TRANSFORM(TransformWritableContentToStdStream);
 
 class TransformStaticContentToStdStream : public TransformImpl<StaticContent, ostreamWrapper> {
 	public:
-		void transform(const StaticContent * wc, ostreamWrapper * o) const
+		void transform(const StaticContent * wc, ostreamWrapper * o, ExecContext *) const
 		{
 			wc->writeTo(o->strm);
 		}
diff --git a/project2/common/transform.h b/project2/common/transform.h
index 3ae1063..34e91b7 100644
--- a/project2/common/transform.h
+++ b/project2/common/transform.h
@@ -6,6 +6,8 @@
 #include "scriptLoader.h"
 #include <map>
 
+class ExecContext;
+
 class TransformChainLink : public virtual IntrusivePtrBase {
 	public:
 		virtual ~TransformChainLink() = 0;
@@ -22,8 +24,8 @@ class TransformSource : public TransformChainLink {
 		TransformSource(ScriptNodePtr, ObjectSource);
 		void clearTargets();
 		void removeTarget(TransformChainLinkPtr);
-		void addTarget(TransformChainLinkPtr, ScriptNodePtr e = NULL);
-		void doTransforms() const;
+		void addTarget(TransformChainLinkPtr, ExecContext *, ScriptNodePtr e);
+		void doTransforms(ExecContext *) const;
 		const Targets & getTargets() const;
 	private:
 		virtual const TransformChainLink * object() const { return this; }
@@ -41,9 +43,9 @@ class SourceOf : public virtual TransformSource {
 
 class Transform : public virtual IntrusivePtrBase {
 	public:
-		virtual void transform(const TransformSource * src, TransformChainLink * dest) const = 0;
+		virtual void transform(const TransformSource * src, TransformChainLink * dest, ExecContext *) const = 0;
 		virtual bool canTransform(const TransformSource * src, TransformChainLink * dest) const = 0;
-		virtual void configure(ScriptNodePtr) { };
+		virtual void configure(ScriptNodePtr, ExecContext *) { };
 };
 
 typedef GenLoader<Transform> TransformLoader;
@@ -55,10 +57,10 @@ typedef GenLoader<TransformChainLink, ScriptNodePtr, ObjectSource> TransformTarg
 template <class Source, class Destination>
 class TransformImpl : public Transform {
 	public:
-		virtual void transform(const Source *, Destination *) const = 0;
-		void transform(const TransformSource * src, TransformChainLink * dest) const
+		virtual void transform(const Source *, Destination *, ExecContext *) const = 0;
+		void transform(const TransformSource * src, TransformChainLink * dest, ExecContext * ec) const
 		{
-			transform(dynamic_cast<const SourceOf<Source> *>(src)->operator const Source *(), dynamic_cast<Destination *>(dest));
+			transform(dynamic_cast<const SourceOf<Source> *>(src)->operator const Source *(), dynamic_cast<Destination *>(dest), ec);
 		}
 		bool canTransform(const TransformSource * src, TransformChainLink * dest) const
 		{
@@ -75,7 +77,7 @@ class WritableContent {
 		};
 		virtual Class getContentClass() const = 0;
 		virtual Glib::ustring getContentType() const = 0;
-		virtual void writeTo(std::ostream &, const std::string & encoding) const = 0;
+		virtual void writeTo(std::ostream &, const std::string & encoding, ExecContext *) const = 0;
 };
 
 class StaticContent {
diff --git a/project2/common/variables.cpp b/project2/common/variables.cpp
index 6f62dc1..a8ca808 100644
--- a/project2/common/variables.cpp
+++ b/project2/common/variables.cpp
@@ -5,7 +5,6 @@
 #include "iHaveParameters.h"
 #include "scriptLoader.h"
 #include "exceptions.h"
-#include "appEngine.h"
 #include "session.h"
 #include "rowSet.h"
 #include <stdexcept>
@@ -31,9 +30,9 @@ class VariableParent : public VariableImplDyn {
 	public:
 		VariableParent(ScriptNodePtr e) :
 			VariableImplDyn(e),
-			depth(e->value("depth", 1).as<int32_t>()),
+			depth(e->value("depth", 1, NULL).as<int32_t>()),
 			attr(e->valueExists("attribute")),
-			name((attr ? e->value("attribute") : e->value("name")).as<Glib::ustring>())
+			name((attr ? e->value("attribute", NULL) : e->value("name", NULL)).as<Glib::ustring>())
 		{
 		}
 		VariableParent(const Glib::ustring & n, bool a, unsigned int d) :
@@ -43,14 +42,14 @@ class VariableParent : public VariableImplDyn {
 			name(n)
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			try {
 				if (!getValue) {
 					if (depth > RowState::Stack().size()) {
 						throw RowSet::ParentOutOfRange(depth);
 					}
-					bind(RowState::Stack()[RowState::Stack().size() - depth]);
+					bind(ec, RowState::Stack()[RowState::Stack().size() - depth]);
 				}
 				return getValue();
 			}
@@ -58,23 +57,23 @@ class VariableParent : public VariableImplDyn {
 				if (!defaultValue) {
 					throw;
 				}
-				return (*defaultValue)();
+				return (*defaultValue)(ec);
 			}
 			catch (RowSet::FieldDoesNotExist) {
 				if (!defaultValue) {
 					throw;
 				}
-				return (*defaultValue)();
+				return (*defaultValue)(ec);
 			}
 		}
 	protected:
-		void bind(const RowState * row) const
+		void bind(ExecContext * ec, const RowState * row) const
 		{
 			if (attr) {
 				getValue = boost::bind(row->resolveAttr(name));
 			}
 			else {
-				getValue = boost::bind(&RowState::getCurrentValue, row, name);
+				getValue = boost::bind(&RowState::getCurrentValue, row, ec, name);
 			}
 		}
 		const size_t depth;
diff --git a/project2/common/variables.h b/project2/common/variables.h
index 948f2d2..7713667 100644
--- a/project2/common/variables.h
+++ b/project2/common/variables.h
@@ -10,12 +10,14 @@
 #include "variableType.h"
 #include <boost/shared_ptr.hpp>
 
+class ExecContext;
+
 SimpleMessageException(UnknownVariableSource);
 
 /// Base class for Project2 variable accessors
 class VariableImpl : public IntrusivePtrBase {
 	public:
-		virtual VariableType value() const = 0;
+		virtual VariableType value(ExecContext *) const = 0;
 
 	protected:
 		virtual ~VariableImpl() = 0;
@@ -32,8 +34,7 @@ class Variable {
 
 		static Variable makeParent(const Glib::ustring & name, bool attr, unsigned int depth);
 
-		operator VariableType () const { return var->value(); }
-		VariableType operator()() const { return var->value(); }
+		VariableType operator()(ExecContext * ec) const { return var->value(ec); }
 
 	private:
 		Variable(VariableImpl *);
@@ -45,7 +46,7 @@ class Variable {
 class VariableImplDyn : public VariableImpl {
 	public:
 		VariableImplDyn(ScriptNodePtr e);
-		virtual VariableType value() const = 0;
+		virtual VariableType value(ExecContext *) const = 0;
 
 	protected:
 		boost::optional<Variable> defaultValue;
diff --git a/project2/common/variables/config.cpp b/project2/common/variables/config.cpp
index 51759d5..9b4cccb 100644
--- a/project2/common/variables/config.cpp
+++ b/project2/common/variables/config.cpp
@@ -3,7 +3,6 @@
 #include "../scriptLoader.h"
 #include "../scriptStorage.h"
 #include <boost/algorithm/string/predicate.hpp>
-#include "../appEngine.h"
 
 typedef std::map<Glib::ustring, VariableType> ConfigOptions;
 static ConfigOptions cfgOpts;
@@ -15,17 +14,17 @@ class VariableConfig : public VariableImplDyn {
 	public:
 		VariableConfig(ScriptNodePtr e) :
 			VariableImplDyn(e),
-			name(e->value("name").as<Glib::ustring>())
+			name(e->value("name", NULL).as<Glib::ustring>())
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			const ConfigOptions::const_iterator i = cfgOpts.find(name);
 			if (i != cfgOpts.end()) {
 				return i->second;
 			}
 			if (defaultValue) {
-				return defaultValue.get()();
+				return defaultValue.get()(ec);
 			}
 			throw NoSuchConfigurationValue(name);
 		}
@@ -40,17 +39,17 @@ class VariableConfigLoader : public VariableLoader::For<VariableConfig> {
 				void reset() const {
 					cfgOpts.clear();
 				}
-				void consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v) const {
+				void consume(const Glib::ustring & n, const Glib::ustring & p, const VariableType & v, const Options::CurrentPlatform & cp) 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()) {
+							if (p.empty() || p == cp) {
 								cfgOpts.insert(ConfigOptions::value_type(k, v));
 							}
 						}
 						else {
-							if (p == Environment::getCurrent()->platform()) {
+							if (p == cp) {
 								i->second = v;
 							}
 						}
diff --git a/project2/common/variables/fixed.cpp b/project2/common/variables/fixed.cpp
index fdb67ed..4687c6a 100644
--- a/project2/common/variables/fixed.cpp
+++ b/project2/common/variables/fixed.cpp
@@ -6,7 +6,7 @@ VariableFixed::VariableFixed(VariableType v) :
 }
 
 VariableType
-VariableFixed::value() const
+VariableFixed::value(ExecContext *) const
 {
 	return var;
 }
diff --git a/project2/common/variables/fixed.h b/project2/common/variables/fixed.h
index ec8be1a..b1380dd 100644
--- a/project2/common/variables/fixed.h
+++ b/project2/common/variables/fixed.h
@@ -7,7 +7,7 @@
 class VariableFixed : public VariableImpl {
 	public:
 		VariableFixed(VariableType v);
-		VariableType value() const;
+		VariableType value(ExecContext * ec) const;
 
 	private:
 		VariableType var;
diff --git a/project2/common/variables/literal.cpp b/project2/common/variables/literal.cpp
index 11fb78a..3696346 100644
--- a/project2/common/variables/literal.cpp
+++ b/project2/common/variables/literal.cpp
@@ -19,7 +19,7 @@ append(VariableLiteral::Vals * vals, const Y & y)
 
 VariableLiteral::VariableLiteral(ScriptNodePtr s) {
 	try {
-		val = VariableType::make(s->value("value"), VariableType::getTypeFromName(s->value("type", "")));
+		val = VariableType::make(s->value("value", NULL), VariableType::getTypeFromName(s->value("type", "", NULL)));
 	}
 	catch (const ValueNotFound &) {
 		s->composeWithCallbacks(
@@ -29,17 +29,17 @@ VariableLiteral::VariableLiteral(ScriptNodePtr s) {
 }
 
 VariableType
-VariableLiteral::value() const
+VariableLiteral::value(ExecContext * ec) const
 {
 	if (vals.empty()) {
 		return val;
 	}
 	if (vals.size() == 1) {
-		return *vals.front();
+		return vals.front()->value(ec);
 	}
 	Glib::ustring v;
 	BOOST_FOREACH(PartCPtr p, vals) {
-		p->appendTo(v);
+		p->appendTo(ec, v);
 	}
 	return v;
 }
@@ -49,11 +49,12 @@ VariableLiteral::TextPart::TextPart(const Glib::ustring & e) :
 {
 }
 void
-VariableLiteral::TextPart::appendTo(Glib::ustring & str) const
+VariableLiteral::TextPart::appendTo(ExecContext *, Glib::ustring & str) const
 {
 	str += txt;
 }
-VariableLiteral::TextPart::operator VariableType() const
+VariableType
+VariableLiteral::TextPart::value(ExecContext *) const
 {
 	return txt;
 }
@@ -62,13 +63,14 @@ VariableLiteral::VarPart::VarPart(ScriptNodePtr e) : Variable(e)
 {
 }
 void
-VariableLiteral::VarPart::appendTo(Glib::ustring & str) const
+VariableLiteral::VarPart::appendTo(ExecContext * ec, Glib::ustring & str) const
 {
-	str += (*this)().operator const Glib::ustring &();
+	str += (*this)(ec).operator const Glib::ustring &();
 }
-VariableLiteral::VarPart::operator VariableType() const
+VariableType
+VariableLiteral::VarPart::value(ExecContext * ec) const
 {
-	return (*this)();
+	return (*this)(ec);
 }
 
 DECLARE_COMPONENT_LOADER("literal", VariableLiteral, VariableLoader);
diff --git a/project2/common/variables/literal.h b/project2/common/variables/literal.h
index 4128d1c..8c120b6 100644
--- a/project2/common/variables/literal.h
+++ b/project2/common/variables/literal.h
@@ -8,28 +8,28 @@ class VariableLiteral : public VariableImpl {
 	public:
 		VariableLiteral(const Glib::ustring & src, const VT_typeID format = DefaultType);
 		VariableLiteral(ScriptNodePtr);
-		virtual VariableType value() const;
+		virtual VariableType value(ExecContext * ec) const;
 		class Part;
 		typedef boost::intrusive_ptr<Part> PartCPtr;
 		typedef std::list<PartCPtr> Vals;
 
 		class Part : public IntrusivePtrBase {
 			public:
-				virtual void appendTo(Glib::ustring & str) const = 0;
-				virtual operator VariableType() const = 0;
+				virtual void appendTo(ExecContext *, Glib::ustring & str) const = 0;
+				virtual VariableType value(ExecContext *) const = 0;
 		};
 		class TextPart : public Part {
 			public:
 				TextPart(const Glib::ustring & e);
-				void appendTo(Glib::ustring & str) const;
-				operator VariableType() const;
+				void appendTo(ExecContext *, Glib::ustring & str) const;
+				VariableType value(ExecContext *) const;
 				const Glib::ustring txt;
 		};
 		class VarPart : public Part, public Variable {
 			public:
 				VarPart(ScriptNodePtr e);
-				void appendTo(Glib::ustring & str) const;
-				operator VariableType() const;
+				void appendTo(ExecContext *, Glib::ustring & str) const;
+				VariableType value(ExecContext *) const;
 		};
 	private:
 		VariableType val;
diff --git a/project2/common/variables/localparam.cpp b/project2/common/variables/localparam.cpp
index 1b789a7..bb71bde 100644
--- a/project2/common/variables/localparam.cpp
+++ b/project2/common/variables/localparam.cpp
@@ -9,19 +9,19 @@ class VariableLocalParam : public VariableImplDyn {
 	public:
 		VariableLocalParam(ScriptNodePtr e) :
 			VariableImplDyn(e),
-			name(e->value("name").as<Glib::ustring>())
+			name(e->value("name", NULL).as<Glib::ustring>())
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			try {
-				return IHaveParameters::getScopedParameter(name);
+				return IHaveParameters::getScopedParameter(name, ec);
 			}
 			catch (ParamNotFound) {
 				if (!defaultValue) {
 					throw;
 				}
-				return (*defaultValue)();
+				return (*defaultValue)(ec);
 			}
 		}
 	private:
diff --git a/project2/common/variables/lookup.cpp b/project2/common/variables/lookup.cpp
index 2a96338..b3f9002 100644
--- a/project2/common/variables/lookup.cpp
+++ b/project2/common/variables/lookup.cpp
@@ -33,38 +33,38 @@ class VariableLookup : public VariableImplDyn, public RowProcessor {
 		VariableLookup(ScriptNodePtr e) :
 			VariableImplDyn(e),
 			RowProcessor(e),
-			name(e->value("name").as<Glib::ustring>())
+			name(e->value("name", NULL).as<Glib::ustring>())
 		{
 			e->script->loader.addLoadTarget(e, Storer::into<ElementLoader>(&rowSets));
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			if (map.empty()) {
-				fillCache();
+				fillCache(ec);
 			}
 			Key k;
 			k.reserve(parameters.size());
 			BOOST_FOREACH(const Parameters::value_type & p, parameters) {
-				k.push_back(p.second);
+				k.push_back(p.second(ec));
 			}
 			return safeMapLookup<NotFound>(map, k);
 		}
 	private:
-		void fillCache() const
+		void fillCache(ExecContext * ec) const
 		{
 			BOOST_FOREACH(const RowSets::value_type & rs, rowSets) {
-				rs->execute(filter, this);
+				rs->execute(filter, boost::bind(&VariableLookup::rowReady, this, _1, ec), ec);
 			}
 			Logger()->messagef(LOG_DEBUG, "%s: %s has filled cached with %zu items",
 					__PRETTY_FUNCTION__, name.c_str(), map.size());
 		}
-		void rowReady(const RowState * rs) const
+		void rowReady(const RowState * rs, ExecContext * ec) const
 		{
 			Key k;
 			BOOST_FOREACH(const Parameters::value_type & p, parameters) {
-				k.push_back(rs->getCurrentValue(p.first));
+				k.push_back(rs->getCurrentValue(ec, p.first));
 			}
-			map[k] = rs->getCurrentValue(name);
+			map[k] = rs->getCurrentValue(ec, name);
 		}
 		mutable Map map;
 		typedef ANONSTORAGEOF(RowSet) RowSets;
diff --git a/project2/common/variables/param.cpp b/project2/common/variables/param.cpp
index 7292b0a..a1ef9b7 100644
--- a/project2/common/variables/param.cpp
+++ b/project2/common/variables/param.cpp
@@ -1,31 +1,31 @@
 #include <pch.hpp>
+#include "../execContext.h"
 #include "../variables.h"
 #include "../scriptLoader.h"
 #include "../scriptStorage.h"
-#include "../appEngine.h"
 
 /// Variable implementation to access call parameters
 class VariableParam : public VariableImplDyn {
 	public:
 		VariableParam(ScriptNodePtr e) :
 			VariableImplDyn(e),
-			name(e->value("name").as<Glib::ustring>())
+			name(e->value("name", NULL))
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			try {
-				return ApplicationEngine::getCurrent()->env()->getParamQuery(name);
+				return ec->getParameter(name);
 			}
 			catch (ParamNotFound) {
 				if (!defaultValue) {
 					throw;
 				}
-				return (*defaultValue)();
+				return (*defaultValue)(ec);
 			}
 		}
 	private:
-		const Glib::ustring name;
+		const VariableType name;
 };
 DECLARE_COMPONENT_LOADER("param", VariableParam, VariableLoader);
 
diff --git a/project2/common/variables/session.cpp b/project2/common/variables/session.cpp
index fc33d8e..ed2077d 100644
--- a/project2/common/variables/session.cpp
+++ b/project2/common/variables/session.cpp
@@ -1,27 +1,27 @@
 #include <pch.hpp>
 #include "../variables.h"
+#include "../execContext.h"
 #include "../scriptLoader.h"
 #include "../scriptStorage.h"
-#include "../appEngine.h"
 
 /// Variable implementation to access session contents
 class VariableSession : public VariableImplDyn {
 	public:
 		VariableSession(ScriptNodePtr e) :
 			VariableImplDyn(e),
-			name(e->value("name").as<Glib::ustring>())
+			name(e->value("name", NULL).as<Glib::ustring>())
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext * ec) const
 		{
 			try {
-				return ApplicationEngine::getCurrent()->session()->GetValue(name);
+				return ec->getSession()->GetValue(name);
 			}
 			catch (Session::VariableNotFound) {
 				if (!defaultValue) {
 					throw;
 				}
-				return (*defaultValue)();
+				return (*defaultValue)(ec);
 			}
 		}
 	private:
diff --git a/project2/common/view.h b/project2/common/view.h
index 75a0f3c..52a4130 100644
--- a/project2/common/view.h
+++ b/project2/common/view.h
@@ -5,6 +5,7 @@
 #include "scriptStorage.h"
 
 class MultiRowSetPresenter;
+class ExecContext;
 SimpleMessageException(EmptyRequiredRows);
 
 /// Base class for Project2 components that output data
@@ -13,7 +14,7 @@ class View : public virtual SourceObject {
 		View(ScriptNodePtr);
 		virtual ~View();
 
-		virtual void execute(const MultiRowSetPresenter *) const = 0;
+		virtual void execute(const MultiRowSetPresenter *, ExecContext *) const = 0;
 };
 
 #endif
diff --git a/project2/common/viewGroup.cpp b/project2/common/viewGroup.cpp
index b01f6c8..e6e84d0 100644
--- a/project2/common/viewGroup.cpp
+++ b/project2/common/viewGroup.cpp
@@ -11,11 +11,11 @@ class ViewGroup : public View {
 			s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&subViews));
 		}
 
-		void execute(const MultiRowSetPresenter * presenter) const
+		void execute(const MultiRowSetPresenter * presenter, ExecContext * ec) const
 		{
 			presenter->addNewRowSet(name);
 			BOOST_FOREACH(const SubViews::value_type & sq, subViews) {
-				sq->execute(presenter);
+				sq->execute(presenter, ec);
 			}
 			presenter->finishRowSet();
 		}
diff --git a/project2/common/viewHost.cpp b/project2/common/viewHost.cpp
index 04e0d88..320e86d 100644
--- a/project2/common/viewHost.cpp
+++ b/project2/common/viewHost.cpp
@@ -17,14 +17,14 @@ ViewHost::~ViewHost()
 }
 
 void
-ViewHost::executeViews() const
+ViewHost::executeViews(ExecContext * ec) const
 {
 	loadScriptComponents();
 
-	MultiRowSetPresenterPtr presenter = getPresenter();
-	presenter->init();
+	MultiRowSetPresenterPtr presenter = getPresenter(ec);
+	presenter->init(ec);
 	BOOST_FOREACH(const Views::value_type & s, views) {
-		s->execute(presenter.get());
+		s->execute(presenter.get(), ec);
 	}
 	// Caches might open transactions
 	BOOST_FOREACH(const CommonObjects::DataSources::value_type & ds, CommonObjects::datasources) {
@@ -34,12 +34,12 @@ ViewHost::executeViews() const
 }
 
 void
-ViewHost::doTransforms() const
+ViewHost::doTransforms(ExecContext * ec) const
 {
-	MultiRowSetPresenterPtr presenter = getPresenter();
+	MultiRowSetPresenterPtr presenter = getPresenter(ec);
 	TransformSourcePtr ts = boost::dynamic_pointer_cast<TransformSource>(presenter);
 	if (ts) {
-		ts->doTransforms();
+		ts->doTransforms(ec);
 	}
 }
 
diff --git a/project2/common/viewHost.h b/project2/common/viewHost.h
index d09f1af..5ede3e4 100644
--- a/project2/common/viewHost.h
+++ b/project2/common/viewHost.h
@@ -13,11 +13,11 @@ class ViewHost : virtual public CheckHost, virtual public CommonObjects {
 		ViewHost(ScriptNodePtr script); 
 		~ViewHost();
 
-		void executeViews() const;
-		void doTransforms() const;
+		void executeViews(ExecContext *) const;
+		void doTransforms(ExecContext *) const;
 
 	protected:
-		virtual MultiRowSetPresenterPtr getPresenter() const = 0;
+		virtual MultiRowSetPresenterPtr getPresenter(ExecContext *) const = 0;
 
 	private:
 		typedef ANONORDEREDSTORAGEOF(View) Views;
diff --git a/project2/compression/decompressStream.cpp b/project2/compression/decompressStream.cpp
index 92ba035..ad2e01d 100644
--- a/project2/compression/decompressStream.cpp
+++ b/project2/compression/decompressStream.cpp
@@ -14,13 +14,13 @@ class DecompressStream : public Stream {
 			p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&stream));
 		}
 
-		void runStream(const Sink & sink) const
+		void runStream(const Sink & sink, ExecContext * ec) const
 		{
-			DecompressorPtr decomp = DecompressorLoader::getFor(method())->create();
+			DecompressorPtr decomp = DecompressorLoader::getFor(method(ec))->create();
 			stream->runStream([&](const char * data, size_t len) -> size_t {
 					decomp->decompress(data, len, sink);
 					return len;
-				});
+				}, ec);
 		}
 
 		StreamPtr stream;
diff --git a/project2/console/claOptions.cpp b/project2/console/claOptions.cpp
index 79be7dc..ee28bf6 100644
--- a/project2/console/claOptions.cpp
+++ b/project2/console/claOptions.cpp
@@ -4,6 +4,7 @@
 #include "../common/optionsSource.h"
 #include "../common/exceptions.h"
 #include "claOptions.h"
+#include "consoleAppEngine.h"
 
 StaticMessageException(InvalidScriptName, "Script name should be group/name");
 SimpleMessageException(ArgumentRequired);
@@ -17,7 +18,7 @@ CommandLineArguments::CommandLineArguments(int c, const char * const * v) :
 }
 
 void
-CommandLineArguments::loadInto(const ConfigConsumer & consume) const {
+CommandLineArguments::loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const {
 	bool moreopts = true;
 
 	for (int x = 1; x < argc; x += 1) {
@@ -35,10 +36,10 @@ CommandLineArguments::loadInto(const ConfigConsumer & consume) const {
 				if (x >= argc) {
 					throw ArgumentRequired(name);
 				}
-				consume(name, Environment::getCurrent()->platform(), argv[x]);
+				consume(name, platform(), argv[x], platform);
 			}
 			else {
-				consume(name, Environment::getCurrent()->platform(), name);
+				consume(name, platform(), name, platform);
 			}
 		}
 		else if (moreopts && *(argv[x]) == '-') {
@@ -55,22 +56,22 @@ CommandLineArguments::loadInto(const ConfigConsumer & consume) const {
 						if (x >= argc) {
 							throw ArgumentRequired(name);
 						}
-						consume(name, Environment::getCurrent()->platform(), argv[x]);
+						consume(name, platform(), argv[x], platform);
 					}
 					else {
-						consume(name, Environment::getCurrent()->platform(), n);
+						consume(name, platform(), n, platform);
 						n += 1;
 					}
 				}
 				else {
-					consume(name, Environment::getCurrent()->platform(), name);
+					consume(name, platform(), name, platform);
 				}
 			}
 		}
 		else {
 			const char * sl = strchr(argv[x], '/');
 			if (sl) {
-				ConsoleEnvironment::todolist.push_back(ConsoleEnvironment::ToDo(std::string(argv[x], sl), sl + 1));
+				ConsoleApplicationEngine::todolist.push_back(ConsoleApplicationEngine::ToDo(std::string(argv[x], sl), sl + 1));
 				sl++;
 			}
 			else {
diff --git a/project2/console/claOptions.h b/project2/console/claOptions.h
index e1fee8d..ea3fb01 100644
--- a/project2/console/claOptions.h
+++ b/project2/console/claOptions.h
@@ -6,7 +6,7 @@
 class CommandLineArguments : public OptionsSource {
 	public:
 		CommandLineArguments(int c, const char * const * v);
-		void loadInto(const ConfigConsumer & consume) const;
+		void loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const;
 		bool needReload() const;
 
 	private:
diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp
index 044544c..332d7b8 100644
--- a/project2/console/consoleAppEngine.cpp
+++ b/project2/console/consoleAppEngine.cpp
@@ -2,11 +2,11 @@
 #include <glibmm/exception.h>
 #include <cxxabi.h>
 #include "consoleAppEngine.h"
-#include "consoleEnvironment.h"
 #include "consolePresenter.h"
-#include "logger.h"
 #include "safeMapFind.h"
-#include "iterate.h"
+#include "logger.h"
+#include "viewHost.h"
+#include "taskHost.h"
 #include "scriptLoader.h"
 #include <boost/foreach.hpp>
 #include <boost/bind.hpp>
@@ -15,13 +15,45 @@
 
 SimpleMessageException(UnknownPlatformAlias);
 
-ConsoleApplicationEngine::ConsoleApplicationEngine(const ConsoleEnvironment * env, ScriptReaderPtr script) :
-	SourceObject(script->root()),
-	CommonObjects(script->root()),
-	CheckHost(script->root()),
-	TaskHost(script->root()),
-	ViewHost(script->root()),
-	_env(env),
+class ShowHelpTrigger : public Options::Target {
+	public:
+		void reset() const { }
+		bool paramRequired() const {
+			return false;
+		}
+		void consume(const Glib::ustring &, const VariableType &, const Options::CurrentPlatform &) const {
+			fprintf(stdout, "Help\n");
+			Plugable::onAll<Options>(boost::bind(&ShowHelpTrigger::outputOptions, this, _1));
+			exit(1);
+		}
+	private:
+		void outputOptions(const Options * options) const {
+			fprintf(stdout, "  * %s\n", options->name.c_str());
+			BOOST_FOREACH(const auto & option, options->allOptions()) {
+				fprintf(stdout, "    * %s - %s\n", option->name().c_str(), option->description().c_str());
+			}
+		}
+};
+
+DECLARE_OPTIONS(ConsoleApplicationEngine, "Console options")
+("help", new ShowHelpTrigger(),
+ "Print usage and exit")("h")
+("console.platform", Options::value(&reqPlatform),
+ "Platform")("p")
+("console.queryParam", Options::functions(
+		[](const VariableType & v) {
+			Glib::ustring vs(v.as<Glib::ustring>());
+			parameters.insert(Parameters::value_type(vs.substr(0, vs.find('=')), vs.substr(vs.find('=') + 1)));
+		},
+		boost::bind(&Parameters::clear, &parameters)),
+ "Query parameter")("q")
+END_OPTIONS(ConsoleApplicationEngine);
+
+ConsoleApplicationEngine::ToDoList ConsoleApplicationEngine::todolist;
+ConsoleApplicationEngine::Parameters ConsoleApplicationEngine::parameters;
+Glib::ustring ConsoleApplicationEngine::reqPlatform;
+
+ConsoleApplicationEngine::ConsoleApplicationEngine() :
 	runtime(new Session(boost::uuids::random_generator()())),
 	presenter(new ConsolePresenter())
 {
@@ -31,14 +63,39 @@ ConsoleApplicationEngine::~ConsoleApplicationEngine()
 {
 }
 
+class ScriptRunner : public TaskHost, public ViewHost {
+	public:
+		ScriptRunner(ScriptReaderPtr script, MultiRowSetPresenterPtr p) :
+			SourceObject(script->root()),
+			CommonObjects(script->root()),
+			CheckHost(script->root()),
+			TaskHost(script->root()),
+			ViewHost(script->root()),
+			presenter(p)
+		{
+		}
+
+		MultiRowSetPresenterPtr getPresenter(ExecContext *) const
+		{
+			return presenter;
+		}
+
+		void process(ExecContext * ec)
+		{
+			runChecks(ec);
+			execute(ec);
+			executeViews(ec);
+		}
+	private:
+		MultiRowSetPresenterPtr presenter;
+};
+
 void
-ConsoleApplicationEngine::process() const
+ConsoleApplicationEngine::process(ScriptReaderPtr s)
 {
 	try {
-		runChecks();
-		execute();
-		executeViews();
-		addAppData(presenter.get());
+		boost::intrusive_ptr<ScriptRunner> sr = new ScriptRunner(s, presenter);
+		sr->process(this);
 	}
 	catch (const std::exception & e) {
 		char * buf = __cxxabiv1::__cxa_demangle(typeid(e).name(), NULL, NULL, NULL);
@@ -52,31 +109,29 @@ ConsoleApplicationEngine::process() const
 	}
 }
 
-MultiRowSetPresenterPtr
-ConsoleApplicationEngine::getPresenter() const
-{
-	return presenter;
-}
-
-const Environment *
-ConsoleApplicationEngine::env() const
-{
-	return _env;
-}
-
 SessionPtr
-ConsoleApplicationEngine::session() const
+ConsoleApplicationEngine::getSession() const
 {
 	return runtime;
 }
 
-void
-ConsoleApplicationEngine::addEnvData(const MultiRowSetPresenter *) const
+VariableType
+ConsoleApplicationEngine::getParameter(const VariableType & key) const
 {
+	return safeMapLookup<ParamNotFound>(parameters, key);
 }
 
 void
-ConsoleApplicationEngine::addAppData(const MultiRowSetPresenter *) const
+ConsoleApplicationEngine::process()
 {
-}
+	BOOST_FOREACH(const auto & todo, todolist) {
+		Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
+		Logger()->messagebf(LOG_DEBUG, "%s: Beginning script '%s/%s'", __FUNCTION__, todo.get<0>(), todo.get<1>());
+
+		Logger()->messagef(LOG_DEBUG, "%s: Processing file", __FUNCTION__);
+		process(ScriptReader::resolveScript(todo.get<0>(), todo.get<1>(), false));
+		Logger()->messagef(LOG_DEBUG, "%s: Complete", __FUNCTION__);
 
+		Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1));
+	}
+}
diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h
index 3bfd9ed..b75d9b1 100644
--- a/project2/console/consoleAppEngine.h
+++ b/project2/console/consoleAppEngine.h
@@ -1,39 +1,42 @@
 #ifndef CONSOLEAPPENGINE_H
 #define CONSOLEAPPENGINE_H
 
-#include "appEngine.h"
 #include "task.h"
 #include "presenter.h"
 #include "commonObjects.h"
 #include "view.h"
-#include "taskHost.h"
-#include "viewHost.h"
-#include <boost/intrusive_ptr.hpp>
+#include "execContext.h"
+#include <vector>
+#include <boost/tuple/tuple.hpp>
 
-class ConsoleEnvironment;
-
-class ConsoleApplicationEngine : public ApplicationEngine, public TaskHost, public ViewHost {
+class ConsoleApplicationEngine : public ExecContext {
 	public:
-		ConsoleApplicationEngine(const ConsoleEnvironment *, ScriptReaderPtr);
+		ConsoleApplicationEngine();
 		virtual ~ConsoleApplicationEngine();
 
-		void process() const;
-		const Environment * env() const;
-		SessionPtr session() const;
-		virtual void addAppData(const MultiRowSetPresenter * p) const;
-		virtual void addEnvData(const MultiRowSetPresenter * p) const;
+		void process();
+		VariableType getParameter(const VariableType&) const;
+		SessionPtr getSession() const;
 
-	protected:
-		const ConsoleEnvironment * _env;
-		MultiRowSetPresenterPtr getPresenter() const;
+		INITOPTIONS;
 
 	private:
+		void process(ScriptReaderPtr);
+
+		typedef boost::tuple<Glib::ustring, Glib::ustring> ToDo;
+		typedef std::vector<ToDo> ToDoList;
 		typedef std::map<Glib::ustring, const Glib::ustring> ConsolePlatforms;
-		mutable ConsolePlatforms conplat;
+		typedef std::map<std::string, std::string> Parameters;
 
-	private:
+		friend class CommandLineArguments;
+		mutable ConsolePlatforms conplat;
 		SessionPtr runtime;
 		MultiRowSetPresenterPtr presenter;
+
+		static ToDoList todolist;
+		static Parameters parameters;
+	public:
+		static Glib::ustring reqPlatform;
 };
 
 #endif
diff --git a/project2/console/consoleEnvironment.cpp b/project2/console/consoleEnvironment.cpp
deleted file mode 100644
index d9abde2..0000000
--- a/project2/console/consoleEnvironment.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <pch.hpp>
-#include "consoleEnvironment.h"
-#include <sys/utsname.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include "logger.h"
-#include "exceptions.h"
-#include "scriptLoader.h"
-#include <iostream>
-#include <string>
-#include <boost/algorithm/string/predicate.hpp>
-#include "options.h"
-#include <boost/bind.hpp>
-
-ConsoleEnvironment::ToDoList ConsoleEnvironment::todolist;
-
-class ShowHelpTrigger : public Options::Target {
-	public:
-		void reset() const { }
-		bool paramRequired() const {
-			return false;
-		}
-		void consume(const Glib::ustring &, const VariableType &) const {
-			fprintf(stdout, "Help\n");
-			Plugable::onAll<Options>(boost::bind(&ShowHelpTrigger::outputOptions, this, _1));
-			exit(1);
-		}
-	private:
-		void outputOptions(const Options * options) const {
-			fprintf(stdout, "  * %s\n", options->name.c_str());
-			BOOST_FOREACH(const auto & option, options->allOptions()) {
-				fprintf(stdout, "    * %s - %s\n", option->name().c_str(), option->description().c_str());
-			}
-		}
-};
-
-DECLARE_OPTIONS(ConsoleEnvironment, "Console options")
-("help", new ShowHelpTrigger(),
- "Print usage and exit")("h")
-("console.platform", Options::value(&reqPlatform),
- "Platform")("p")
-("console.queryParam", Options::functions(
-	[](const VariableType & v) {
-		Glib::ustring vs(v.as<Glib::ustring>());
-		queryParams.push_back(QueryParams::value_type(vs.substr(0, vs.find('=')), vs.substr(vs.find('=') + 1)));
-	},
-	boost::bind(&QueryParams::clear, &queryParams)),
-"Query parameter")("q")
-END_OPTIONS(ConsoleEnvironment);
-
-Glib::ustring ConsoleEnvironment::reqPlatform;
-ConsoleEnvironment::QueryParams ConsoleEnvironment::queryParams;
-
-ConsoleEnvironment::ConsoleEnvironment()
-{
-}
-
-ConsoleEnvironment::~ConsoleEnvironment()
-{
-}
-
-Glib::ustring
-ConsoleEnvironment::getParamQuery(const std::string & p) const
-{
-	QueryParams::const_iterator i = std::find_if(queryParams.begin(), queryParams.end(),
-			boost::bind(&boost::algorithm::equals<std::string, std::string>, p,
-				boost::bind(&ConsoleEnvironment::QueryParams::value_type::first, _1)));
-	if (i != queryParams.end()) {
-		return i->second;
-	}
-	throw ParamNotFound(p);
-}
-
-const Glib::ustring &
-ConsoleEnvironment::platform() const
-{
-	return reqPlatform;
-}
-
-std::string
-ConsoleEnvironment::getServerName() const
-{
-	struct utsname name;
-	if (uname(&name)) {
-		Logger()->messagef(LOG_WARNING, "%s: Unable to determine local host name (%d:%s)",
-				__PRETTY_FUNCTION__, errno, strerror(errno));
-		return "unknown";
-	}
-	else {
-		return name.nodename;
-	}
-}
-
-const ConsoleEnvironment::ToDoList &
-ConsoleEnvironment::todoList() const
-{
-	return todolist;
-}
-
diff --git a/project2/console/consoleEnvironment.h b/project2/console/consoleEnvironment.h
deleted file mode 100644
index 48ab439..0000000
--- a/project2/console/consoleEnvironment.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef ENVPROC_H
-#define ENVPROC_H
-
-#include <string>
-#include <vector>
-#include <boost/tuple/tuple.hpp>
-#include "environment.h"
-
-class ConsoleEnvironment : public Environment {
-	public:
-		typedef boost::tuple<Glib::ustring, Glib::ustring> ToDo;
-		typedef std::vector<ToDo> ToDoList;
-		typedef std::vector<std::pair<std::string, std::string> > QueryParams;
-
-		ConsoleEnvironment();
-		virtual ~ConsoleEnvironment();
-
-
-		Glib::ustring getParamQuery(const std::string & idx) const;
-		std::string getServerName() const;
-		const ToDoList & todoList() const;
-
-		INITOPTIONS;
-	private:
-		const Glib::ustring & platform() const;
-
-		friend class CommandLineArguments;
-		static Glib::ustring reqPlatform;
-		static QueryParams queryParams;
-		static ToDoList todolist;
-};
-
-#endif
diff --git a/project2/console/consolePresenter.cpp b/project2/console/consolePresenter.cpp
index 52bface..05285a2 100644
--- a/project2/console/consolePresenter.cpp
+++ b/project2/console/consolePresenter.cpp
@@ -10,7 +10,7 @@ ConsolePresenter::ConsolePresenter() :
 }
 
 void
-ConsolePresenter::init()
+ConsolePresenter::init(ExecContext *)
 {
 }
 
diff --git a/project2/console/consolePresenter.h b/project2/console/consolePresenter.h
index f551063..2a0e9e0 100644
--- a/project2/console/consolePresenter.h
+++ b/project2/console/consolePresenter.h
@@ -15,7 +15,7 @@ class ConsolePresenter : public Presenter {
 		void addNewArray(const Glib::ustring&, bool objects) const;
 		void finishArray(bool objects) const;
 		void write(const boost::function1<std::ostream *, const std::string &> &) const;
-		void init();
+		void init(ExecContext *);
 	private:
 		mutable unsigned int indent;
 		FileStreamVariableWriter out;
diff --git a/project2/console/p2consoleMain.cpp b/project2/console/p2consoleMain.cpp
index 57008b6..3c0f473 100644
--- a/project2/console/p2consoleMain.cpp
+++ b/project2/console/p2consoleMain.cpp
@@ -1,31 +1,18 @@
 #include <pch.hpp>
-#include "consoleEnvironment.h"
-#include "consoleAppEngine.h"
-#include "scriptLoader.h"
-#include "logger.h"
-#include <boost/foreach.hpp>
 #include <boost/bind.hpp>
 #include "claOptions.h"
+#include "consoleAppEngine.h"
 
 int
 main(int argc, char ** argv)
 {
 	Plugable::newLoader<OptionsSource, OptionsSource>("", new CommandLineArguments(argc, argv));
-	ConsoleEnvironment env;
 	Plugable::onAllComponents(boost::bind(&ComponentLoader::onBegin, _1));
-	OptionsSource::loadSources();
-	BOOST_FOREACH(const ConsoleEnvironment::ToDo & todo, env.todoList()) {
-		Plugable::onAllComponents(boost::bind(&ComponentLoader::onBefore, _1));
-		Logger()->messagebf(LOG_DEBUG, "%s: Beginning script '%s/%s'", __FUNCTION__, todo.get<0>(), todo.get<1>());
-		boost::intrusive_ptr<ConsoleApplicationEngine> app(new ConsoleApplicationEngine(&env,
-					ScriptReader::resolveScript(todo.get<0>(), todo.get<1>(), false)));
+	OptionsSource::loadSources([] { return ConsoleApplicationEngine::reqPlatform;} );
 
-		Logger()->messagef(LOG_DEBUG, "%s: Processing file", __FUNCTION__);
-		app->process();
+	ConsoleApplicationEngine app;
+	app.process();
 
-		Logger()->messagef(LOG_DEBUG, "%s: Complete", __FUNCTION__);
-		Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1));
-	}
 	Plugable::onAllComponents(boost::bind(&ComponentLoader::onPeriodic, _1));
 	Plugable::onAllComponents(boost::bind(&ComponentLoader::onIdle, _1));
 }
diff --git a/project2/console/pch.hpp b/project2/console/pch.hpp
index 30db218..4bd02fb 100644
--- a/project2/console/pch.hpp
+++ b/project2/console/pch.hpp
@@ -3,7 +3,6 @@
 #define CONSOLE_PCH
 
 #include "consoleAppEngine.h"
-#include "consoleEnvironment.h"
 #include "consolePresenter.h"
 #include "exceptions.h"
 #include "iterate.h"
diff --git a/project2/files/fileStream.cpp b/project2/files/fileStream.cpp
index 762e39b..df39406 100644
--- a/project2/files/fileStream.cpp
+++ b/project2/files/fileStream.cpp
@@ -21,9 +21,9 @@ class FileStream : public Stream {
 			throw NotSupported(__PRETTY_FUNCTION__);
 		}
 
-		void runStream(const Sink & sink) const
+		void runStream(const Sink & sink, ExecContext * ec) const
 		{
-			FILE * file = fopen(path(), "r");
+			FILE * file = fopen(path(ec), "r");
 			if (!file) {
 				throw syscall_error(errno);
 			}
diff --git a/project2/files/fsFilterMaxDepth.cpp b/project2/files/fsFilterMaxDepth.cpp
index f0d685e..089737a 100644
--- a/project2/files/fsFilterMaxDepth.cpp
+++ b/project2/files/fsFilterMaxDepth.cpp
@@ -13,8 +13,8 @@ class FsRowSpecMaxDepth : public FsRows::SpecBase {
 			maxDepth(boost::lexical_cast<unsigned int>(v))
 		{
 		}
-		bool recurse(const FsRows::SearchState * fs) const {
-			return (std::less<int64_t>()(depth(fs), maxDepth()));
+		bool recurse(const FsRows::SearchState * fs, ExecContext * ec) const {
+			return (std::less<int64_t>()(depth(fs), maxDepth(ec)));
 		}
 		Variable maxDepth;
 };
diff --git a/project2/files/fsFilterName.cpp b/project2/files/fsFilterName.cpp
index cc1104f..92279c2 100644
--- a/project2/files/fsFilterName.cpp
+++ b/project2/files/fsFilterName.cpp
@@ -12,10 +12,10 @@ class FsRowSpecName : public FsRows::SpecBase {
 			pattern(v)
 		{
 		}
-		bool matches(const FsRows::SearchState * fs) const {
+		bool matches(const FsRows::SearchState * fs, ExecContext * ec) const {
 			// Based on code written by Jack Handy - jakkhandy@hotmail.com
 			// from http://www.codeproject.com/KB/string/wildcmp.aspx
-			Glib::ustring patt = pattern();
+			Glib::ustring patt = pattern(ec);
 			Glib::ustring::const_iterator wild = patt.begin();
 			Glib::ustring leaf(curPath(fs).leaf().string());
 			Glib::ustring::const_iterator string = leaf.begin();
diff --git a/project2/files/fsFilterType.cpp b/project2/files/fsFilterType.cpp
index 0d0b27b..ba9ad72 100644
--- a/project2/files/fsFilterType.cpp
+++ b/project2/files/fsFilterType.cpp
@@ -12,8 +12,8 @@ class FsRowSpecType : public FsRows::SpecBase {
 			typelist(v)
 		{
 		}
-		bool matches(const FsRows::SearchState * fs) const {
-			const Glib::ustring types = typelist();
+		bool matches(const FsRows::SearchState * fs, ExecContext * ec) const {
+			const Glib::ustring types = typelist(ec);
 			if (S_ISREG(curStat(fs).st_mode)) {
 				return types.find('f') != Glib::ustring::npos;
 			}
diff --git a/project2/files/fsRows.cpp b/project2/files/fsRows.cpp
index e56f243..71c0dca 100644
--- a/project2/files/fsRows.cpp
+++ b/project2/files/fsRows.cpp
@@ -36,8 +36,8 @@ Columns defCols() {
 }
 const Columns FsRows::SearchState::col(defCols());
 
-bool FsRows::SpecBase::recurse(const SearchState *) const { return true; }
-bool FsRows::SpecBase::matches(const SearchState *) const { return true; }
+bool FsRows::SpecBase::recurse(const SearchState *, ExecContext *) const { return true; }
+bool FsRows::SpecBase::matches(const SearchState *, ExecContext *) const { return true; }
 const boost::filesystem::path & FsRows::SpecBase::curPath(const SearchState * fs) const { return fs->curPath; }
 unsigned int FsRows::SpecBase::depth(const SearchState * fs) const { return fs->depth; }
 const struct stat & FsRows::SpecBase::curStat(const SearchState * fs) const { return fs->curStat; }
@@ -67,11 +67,11 @@ normalisePath(const std::string & p)
 }
 
 void
-FsRows::execute(const Glib::ustring &, const RowProcessor * rp) const
+FsRows::execute(const Glib::ustring &, const RowProcessorCallback & rp, ExecContext * ec) const
 {
-	SearchState ss(normalisePath(root()));
+	SearchState ss(normalisePath(root(ec)));
 	ss.specs = this->specs;
-	Glib::ustring sss = spec();
+	Glib::ustring sss = spec(ec);
 	if (!sss.empty()) {
 		SpecSpec s;
 		typedef SpecSpec & (*splitter)(SpecSpec &, const Glib::ustring &, bool (*)(gunichar), boost::algorithm::token_compress_mode_type);
@@ -87,11 +87,11 @@ FsRows::execute(const Glib::ustring &, const RowProcessor * rp) const
 			}
 		}
 	}
-	execute(ss, ss.fsRoot, rp);
+	execute(ss, ss.fsRoot, rp, ec);
 }
 
 void
-FsRows::execute(SearchState & ss, const Path & dir, const RowProcessor * rp) const
+FsRows::execute(SearchState & ss, const Path & dir, const RowProcessorCallback & rp, ExecContext * ec) const
 {
 	ss.depth += 1;
 	try {
@@ -102,17 +102,17 @@ FsRows::execute(SearchState & ss, const Path & dir, const RowProcessor * rp) con
 			ss.curPath = itr->path();
 			lstat(ss.curPathStr.c_str(), &ss.curStat);
 
-			if (boost::algorithm::all(ss.specs, boost::bind(&SpecBase::matches, _1, &ss))) {
+			if (boost::algorithm::all(ss.specs, boost::bind(&SpecBase::matches, _1, &ss, ec))) {
 				ss.process(rp);
 			}
 
-			if (S_ISDIR(ss.curStat.st_mode) && boost::algorithm::all(ss.specs, boost::bind(&SpecBase::recurse, _1, &ss))) {
-				execute(ss, *itr, rp);
+			if (S_ISDIR(ss.curStat.st_mode) && boost::algorithm::all(ss.specs, boost::bind(&SpecBase::recurse, _1, &ss, ec))) {
+				execute(ss, *itr, rp, ec);
 			}
 		}
 	}
 	catch (const boost::filesystem::filesystem_error & e) {
-		if (!ignoreErrors()) {
+		if (!ignoreErrors(ec)) {
 			throw;
 		}
 		Logger()->messagebf(LOG_WARNING, "%s when processing '%s'", e.what(), dir);
diff --git a/project2/files/fsRows.h b/project2/files/fsRows.h
index 6b689d3..5988865 100644
--- a/project2/files/fsRows.h
+++ b/project2/files/fsRows.h
@@ -17,8 +17,8 @@ class FsRows : public RowSet {
 		class SearchState;
 		class SpecBase : public virtual IntrusivePtrBase {
 			public:
-				virtual bool recurse(const SearchState * fs) const;
-				virtual bool matches(const SearchState * fs) const;
+				virtual bool recurse(const SearchState * fs, ExecContext *) const;
+				virtual bool matches(const SearchState * fs, ExecContext *) const;
 			protected:
 				const boost::filesystem::path & curPath(const SearchState * fs) const;
 				unsigned int depth(const SearchState * fs) const;
@@ -52,7 +52,7 @@ class FsRows : public RowSet {
 		const Variable spec;
 		const Variable ignoreErrors;
 
-		void execute(const Glib::ustring &, const RowProcessor *) const;
+		void execute(const Glib::ustring &, const RowProcessorCallback &, ExecContext *) const;
 		class SearchState : public RowState {
 			public:
 				SearchState(const boost::filesystem::path & r);
@@ -79,7 +79,7 @@ class FsRows : public RowSet {
 				struct stat curStat;
 		};
 	protected:
-		void execute(SearchState &, const Path & dir, const RowProcessor *) const;
+		void execute(SearchState &, const Path & dir, const RowProcessorCallback &, ExecContext *) const;
 		friend class SpecBase;
 		SpecBases specs;
 };
diff --git a/project2/files/functions/pwd.cpp b/project2/files/functions/pwd.cpp
index ce7b068..644c934 100644
--- a/project2/files/functions/pwd.cpp
+++ b/project2/files/functions/pwd.cpp
@@ -11,7 +11,7 @@ class Pwd : public VariableImplDyn {
 			VariableImplDyn(e)
 		{
 		}
-		VariableType value() const
+		VariableType value(ExecContext *) const
 		{
 			return boost::filesystem::current_path().string();
 		}
diff --git a/project2/files/optionsSource.cpp b/project2/files/optionsSource.cpp
index 808d481..437eaf4 100644
--- a/project2/files/optionsSource.cpp
+++ b/project2/files/optionsSource.cpp
@@ -18,7 +18,7 @@ FileOptions::FileOptions(const Glib::ustring & f) :
 }
 
 void
-FileOptions::loadInto(const ConfigConsumer & consume) const {
+FileOptions::loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const {
 	try {
 		Glib::RefPtr<Glib::IOChannel> cfg = Glib::IOChannel::create_from_file(file, "r");
 		Glib::ustring line;
@@ -52,7 +52,7 @@ FileOptions::loadInto(const ConfigConsumer & consume) const {
 					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);
+					consume(prefix + name, plat, val, platform);
 					break;
 			}
 		}
diff --git a/project2/files/optionsSource.h b/project2/files/optionsSource.h
index 5cd5250..e1de4b9 100644
--- a/project2/files/optionsSource.h
+++ b/project2/files/optionsSource.h
@@ -8,7 +8,7 @@ class FileOptions : public OptionsSource {
 		FileOptions();
 		FileOptions(const Glib::ustring & file);
 
-		void loadInto(const ConfigConsumer & consume) const;
+		void loadInto(const ConfigConsumer & consume, const Options::CurrentPlatform & platform) const;
 		bool needReload() const;
 
 	private:
diff --git a/project2/files/presenterCache.cpp b/project2/files/presenterCache.cpp
index f3c3ea9..09ee9ee 100644
--- a/project2/files/presenterCache.cpp
+++ b/project2/files/presenterCache.cpp
@@ -2,7 +2,6 @@
 #include "../common/exceptions.h"
 #include "../common/options.h"
 #include <safeMapFind.h>
-#include "../common/environment.h"
 #include <fcntl.h>
 #include <attr/xattr.h>
 #include <sys/stat.h>
@@ -92,23 +91,23 @@ class FilePresenterCache : public PresenterCache {
 		~FilePresenterCache()
 		{
 		}
-		bool check(time_t scriptMtime) const
+		bool check(time_t scriptMtime, ExecContext * ec) const
 		{
-			Key key = getCacheKey();
+			Key key = getCacheKey(ec);
 			try {
 				CacheFilePtr f = defaultMapFind(openCaches, key);
 				if (!f) {
-					f = openCacheFile(key);
+					f = openCacheFile(key, ec);
 				}
 				struct stat st;
 				safesys<StatCacheFile>(-1, fstat(*f, &st));
 				if (st.st_nlink == 0) {
-					f = openCacheFile(key);
+					f = openCacheFile(key, ec);
 					safesys<StatCacheFile>(-1, fstat(*f, &st));
 				}
 				if (scriptMtime != 0) {
 					if ((st.st_mtime < (time(NULL) - FilePresenterCache::CacheLife)) || (st.st_mtime < scriptMtime)) {
-						unlink(getCacheFile().string().c_str());
+						unlink(getCacheFile(ec).string().c_str());
 						openCaches.erase(key);
 						return false;
 					}
@@ -161,9 +160,9 @@ class FilePresenterCache : public PresenterCache {
 			return this;
 		}
 
-		std::ostream & writeCache(const std::string & ct, const std::string & enc)
+		std::ostream & writeCache(const std::string & ct, const std::string & enc, ExecContext * ec)
 		{
-			int fd = safesys<OpenCacheFile>(-1, open(getCacheFile().string().c_str(),
+			int fd = safesys<OpenCacheFile>(-1, open(getCacheFile(ec).string().c_str(),
 						O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
 			safesys<LockCacheFile>(-1, ::flock(fd, LOCK_EX));
 			safesys<TruncateCacheFile>(-1, ::ftruncate(fd, 0));
@@ -186,23 +185,23 @@ class FilePresenterCache : public PresenterCache {
 
 		INITOPTIONS;
 	private:
-		Key getCacheKey() const
+		Key getCacheKey(ExecContext * ec) const
 		{
 			Key key;
-			key.get<0>().push_back(idProvider->value());
+			key.get<0>().push_back(idProvider->value(ec));
 			return key;
 		}
-		CacheFilePtr openCacheFile(const Key & key) const
+		CacheFilePtr openCacheFile(const Key & key, ExecContext * ec) const
 		{
-			CacheFilePtr c = new CacheFile(safesys<OpenCacheFile>(-1, open(getCacheFile().string().c_str(), O_RDONLY)));
+			CacheFilePtr c = new CacheFile(safesys<OpenCacheFile>(-1, open(getCacheFile(ec).string().c_str(), O_RDONLY)));
 			openCaches[key] = c;
 			return c;
 		}
-		boost::filesystem::path getCacheFile() const
+		boost::filesystem::path getCacheFile(ExecContext * ec) const
 		{
 			boost::filesystem::path cache;
 			cache = Store;
-			cache /= idProvider->value();
+			cache /= idProvider->value(ec);
 			boost::filesystem::create_directories(cache);
 			cache /= FileName;
 			return cache;
diff --git a/project2/files/writeStream.cpp b/project2/files/writeStream.cpp
index 6e49e10..954ec8b 100644
--- a/project2/files/writeStream.cpp
+++ b/project2/files/writeStream.cpp
@@ -16,16 +16,16 @@ class WriteStream : public Task {
 			s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&stream));
 		}
 
-		void execute() const
+		void execute(ExecContext * ec) const
 		{
-			std::fstream ddd(path().as<std::string>(), std::fstream::trunc | std::fstream::out);
+			std::fstream ddd(path(ec).as<std::string>(), std::fstream::trunc | std::fstream::out);
 			if (!ddd.good()) {
-				throw OpenTargetFile(path());
+				throw OpenTargetFile(path(ec));
 			}
 			stream->runStream([&ddd](const char * data, size_t len) -> size_t {
 					ddd.write(data, len);
 					return len;
-					});
+					}, ec);
 		}
 
 		const Variable path;
diff --git a/project2/json/presenter-p.cpp b/project2/json/presenter-p.cpp
index 3cb5bf8..92ba8c1 100644
--- a/project2/json/presenter-p.cpp
+++ b/project2/json/presenter-p.cpp
@@ -3,16 +3,16 @@
 
 class Json_P_Presenter : public JsonPresenter {
 	public:
-		Json_P_Presenter(ScriptNodePtr s, ObjectSource os) :
+		Json_P_Presenter(ScriptNodePtr s, ObjectSource os, ExecContext *) :
 			JsonPresenter(s, os, "application/json-p"),
 			Callback(s, "callback") {
 		}
 
-		void writeTo(std::ostream & o, const std::string & encoding) const
+		void writeTo(std::ostream & o, const std::string & encoding, ExecContext * ec) const
 		{
-			o << Callback().as<Glib::ustring>();
+			o << Callback(ec).as<Glib::ustring>();
 			o << "(";
-			JsonPresenter::writeTo(o, encoding);
+			JsonPresenter::writeTo(o, encoding, ec);
 			o << ");";
 		}
 
diff --git a/project2/json/presenter.cpp b/project2/json/presenter.cpp
index 111ae5c..2eabeac 100644
--- a/project2/json/presenter.cpp
+++ b/project2/json/presenter.cpp
@@ -15,7 +15,7 @@ JsonPresenter::JsonPresenter(ScriptNodePtr s, ObjectSource os, const Glib::ustri
 	returnObject(s, "object", Null()) {
 }
 
-JsonPresenter::JsonPresenter(ScriptNodePtr s, ObjectSource os) :
+JsonPresenter::JsonPresenter(ScriptNodePtr s, ObjectSource os, ExecContext *) :
 	TransformSource(s, os),
 	MultiRowSetPresenter(os),
 	ContentPresenter("application/json"),
@@ -25,7 +25,7 @@ JsonPresenter::JsonPresenter(ScriptNodePtr s, ObjectSource os) :
 }
 
 void
-JsonPresenter::init()
+JsonPresenter::init(ExecContext *)
 {
 	while (!curRowSet.empty()) {
 		curRowSet.pop();
@@ -131,13 +131,13 @@ JsonPresenter::getContentClass() const
 }
 
 void
-JsonPresenter::writeTo(std::ostream & o, const std::string & encoding) const
+JsonPresenter::writeTo(std::ostream & o, const std::string & encoding, ExecContext * ec) const
 {
-	if (returnObject().isNull()) {
+	if (returnObject(ec).isNull()) {
 		serializeObject(object, o, encoding);
 	}
 	else {
-		serializeValue(*object[returnObject()], o, encoding);
+		serializeValue(*object[returnObject(ec)], o, encoding);
 	}
 }
 
diff --git a/project2/json/presenter.h b/project2/json/presenter.h
index 8d5af2a..5ccecb2 100644
--- a/project2/json/presenter.h
+++ b/project2/json/presenter.h
@@ -9,9 +9,9 @@
 
 class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, public SourceOf<json::Object>, public WritableContent, public SourceOf<WritableContent> {
 	public:
-		JsonPresenter(ScriptNodePtr s, ObjectSource);
+		JsonPresenter(ScriptNodePtr s, ObjectSource, ExecContext *);
 		JsonPresenter(ScriptNodePtr s, ObjectSource, const Glib::ustring &);
-		void init();
+		void init(ExecContext * ec);
 		typedef void (JsonPresenter::*ValueAdder)(const Glib::ustring &, const VariableType &) const;
 		typedef std::stack<ValueAdder> ValueAdderStack;
 		mutable ValueAdderStack vaStack;
@@ -29,7 +29,7 @@ class JsonPresenter : public MultiRowSetPresenter, public ContentPresenter, publ
 		operator const WritableContent * () const;
 		Glib::ustring getContentType() const;
 		Class getContentClass() const;
-		void writeTo(std::ostream & o, const std::string & encoding) const;
+		void writeTo(std::ostream & o, const std::string & encoding, ExecContext *) const;
 
 	private:
 		Variable returnObject;
diff --git a/project2/mail/sendmailTask.cpp b/project2/mail/sendmailTask.cpp
index 10bfbdd..bd4094e 100644
--- a/project2/mail/sendmailTask.cpp
+++ b/project2/mail/sendmailTask.cpp
@@ -4,7 +4,6 @@
 #include <boost/bind.hpp>
 #include "scriptLoader.h"
 #include "viewHost.h"
-#include "environment.h"
 #include <stdexcept>
 #include <libesmtp.h>
 #include "xmlPresenter.h"
@@ -136,17 +135,17 @@ class TransformWritableContentToEmail : public TransformImpl<WritableContent, Se
 		TransformWritableContentToEmail() :
 			encoding(SendMailTask::defaultMailEncoding) {
 		}
-		void transform(const WritableContent * wc, SendMailTask::Parts * parts) const
+		void transform(const WritableContent * wc, SendMailTask::Parts * parts, ExecContext * ec) const
 		{
 			parts->parts.insert(new BoundaryBegin(wc->getContentType(), encoding, wc->getContentClass()));
 			std::stringstream str;
-			wc->writeTo(str, encoding);
+			wc->writeTo(str, encoding, ec);
 			parts->parts.insert(new MimeContent(str.str(), wc->getContentClass()));
 			SendMailTask::MailPart::mimeIdx += 1;
 		}
-		void configure(ScriptNodePtr s)
+		void configure(ScriptNodePtr s, ExecContext * ec)
 		{
-			s->applyValue("encoding", encoding);
+			s->applyValue("encoding", encoding, ec);
 		}
 	private:
 		VariableType encoding;
@@ -162,16 +161,16 @@ class EmailViewHost : public ViewHost {
 			parts(ps),
 			n(node) {
 		}
-		MultiRowSetPresenterPtr getPresenter() const {
+		MultiRowSetPresenterPtr getPresenter(ExecContext * ec) const {
 			if (!presenter) {
 				Logger()->message(LOG_DEBUG, "Building default email transform chain");
-				XmlPresenterPtr xpp = new XmlPresenter(n, Default);
+				XmlPresenterPtr xpp = new XmlPresenter(n, Default, ec);
 				HtmlDocument * hd = new HtmlDocument(n, Default);
 				TextDocument * td = new TextDocument(n, Default);
-				xpp->addTarget(hd, n);
-				hd->addTarget(parts);
-				hd->addTarget(td, n);
-				td->addTarget(parts);
+				xpp->addTarget(hd, ec, n);
+				hd->addTarget(parts, ec, NULL);
+				hd->addTarget(td, ec, n);
+				td->addTarget(parts, ec, NULL);
 				presenter = xpp;
 			}
 			return presenter;
@@ -183,29 +182,29 @@ class EmailViewHost : public ViewHost {
 };
 
 void
-SendMailTask::execute() const
+SendMailTask::execute(ExecContext * ec) const
 {
 	boost::intrusive_ptr<Parts> parts = new Parts();
 	MailPart::mimeIdx = 0;
-	parts->parts.insert(new Header("To", to));
-	parts->parts.insert(new Header("From", from));
-	parts->parts.insert(new Header("Subject", subject));
+	parts->parts.insert(new Header("To", to(ec)));
+	parts->parts.insert(new Header("From", from(ec)));
+	parts->parts.insert(new Header("Subject", subject(ec)));
 	parts->parts.insert(new Header("Content-Type", "multipart/alternative; boundary=\"<<divider>>\""));
 	parts->parts.insert(new Header("MIME-Version", "1.0"));
 	parts->parts.insert(new Header("Content-Transfer-Encoding", "binary"));
 	parts->parts.insert(new BoundaryEnd());
 
-	ViewHostPtr vsp = new EmailViewHost(parts, ScriptReader::resolveScript("emails", present(), false)->root());
-	vsp->executeViews();
-	vsp->doTransforms();
+	ViewHostPtr vsp = new EmailViewHost(parts, ScriptReader::resolveScript("emails", present(ec), false)->root());
+	vsp->executeViews(ec);
+	vsp->doTransforms(ec);
 	parts->part = parts->parts.begin();
 
 	// Write email
 	smtp_session_t session = smtp_create_session();
 	smtp_message_t message = smtp_add_message(session);
-	smtp_set_server(session, server());
+	smtp_set_server(session, server(ec));
 	smtp_set_header(message, "To", NULL, NULL);
-	smtp_add_recipient(message, to());
+	smtp_add_recipient(message, to(ec));
 	smtp_set_messagecb(message, writeMail, parts.get());
 	if (!smtp_start_session(session)) {
 		char buf[BUFSIZ];
diff --git a/project2/mail/sendmailTask.h b/project2/mail/sendmailTask.h
index 20435e8..035fe2b 100644
--- a/project2/mail/sendmailTask.h
+++ b/project2/mail/sendmailTask.h
@@ -34,7 +34,7 @@ class SendMailTask : public Task {
 
 		SendMailTask(ScriptNodePtr p);
 		virtual ~SendMailTask();
-		virtual void execute() const;
+		virtual void execute(ExecContext * ec) const;
 		INITOPTIONS;
 
 	protected:
diff --git a/project2/processes/processStream.cpp b/project2/processes/processStream.cpp
index 1a853e4..f2c678f 100644
--- a/project2/processes/processStream.cpp
+++ b/project2/processes/processStream.cpp
@@ -21,13 +21,13 @@ class ProcessStream : public Stream, IHaveParameters {
 	{
 	}
 
-		void runStream(const Sink & sink) const
+		void runStream(const Sink & sink, ExecContext * ec) const
 		{
 			const char * callProc[parameters.size() + 2];
-			callProc[0] = path();
+			callProc[0] = path(ec);
 			int pidx = 1;
 			BOOST_FOREACH(const Parameters::value_type & p, parameters) {
-				callProc[pidx++] = p.second();
+				callProc[pidx++] = p.second(ec);
 			}
 			callProc[pidx] = NULL;
 			int fds[2];
diff --git a/project2/regex/regexRows.cpp b/project2/regex/regexRows.cpp
index e1b18f9..514d47a 100644
--- a/project2/regex/regexRows.cpp
+++ b/project2/regex/regexRows.cpp
@@ -19,11 +19,11 @@ RegexRows::~RegexRows()
 }
 
 void
-RegexRows::execute(const Glib::ustring&, const RowProcessor * rp) const
+RegexRows::execute(const Glib::ustring&, const RowProcessorCallback & rp, ExecContext * ec) const
 {
-	Glib::RefPtr<Glib::Regex> reg = Glib::Regex::create(regex(), Glib::REGEX_CASELESS | Glib::REGEX_DOTALL);
+	Glib::RefPtr<Glib::Regex> reg = Glib::Regex::create(regex(ec), Glib::REGEX_CASELESS | Glib::REGEX_DOTALL);
 	Glib::MatchInfo matches;
-	if (reg->match(sourceText(), matches)) {
+	if (reg->match(sourceText(ec), matches)) {
 		ColumnValues cv(this);
 		do {
 			unsigned int cols = std::min<unsigned int>(matches.get_match_count(), cv.rowSet->columns.size() + 1);
diff --git a/project2/regex/regexRows.h b/project2/regex/regexRows.h
index 4d94f52..1a4ddb1 100644
--- a/project2/regex/regexRows.h
+++ b/project2/regex/regexRows.h
@@ -10,7 +10,7 @@ class RegexRows : public DefinedColumns, public RowSet {
 		RegexRows(ScriptNodePtr p);
 		~RegexRows();
 
-		void execute(const Glib::ustring&, const RowProcessor*) const;
+		void execute(const Glib::ustring&, const RowProcessorCallback &, ExecContext *) const;
 
 	private:
 		const Variable sourceText;
diff --git a/project2/regex/regexTest.cpp b/project2/regex/regexTest.cpp
index 93ee2f7..59dca68 100644
--- a/project2/regex/regexTest.cpp
+++ b/project2/regex/regexTest.cpp
@@ -18,9 +18,9 @@ RegexTest::~RegexTest()
 }
 
 bool
-RegexTest::passes() const
+RegexTest::passes(ExecContext * ec) const
 {
-	Glib::RefPtr<Glib::Regex> reg = Glib::Regex::create(regex());
-	return reg->match(applyTo());
+	Glib::RefPtr<Glib::Regex> reg = Glib::Regex::create(regex(ec));
+	return reg->match(applyTo(ec));
 }
 
diff --git a/project2/regex/regexTest.h b/project2/regex/regexTest.h
index f3459bc..00038a1 100644
--- a/project2/regex/regexTest.h
+++ b/project2/regex/regexTest.h
@@ -10,7 +10,7 @@ class RegexTest : public Test {
 		RegexTest(ScriptNodePtr p);
 		virtual ~RegexTest();
 
-		bool passes() const;
+		bool passes(ExecContext * ec) const;
 
 		const Variable applyTo;
 		const Variable regex;
diff --git a/project2/sql/rdbmsDataSource.cpp b/project2/sql/rdbmsDataSource.cpp
index 691daab..de20844 100644
--- a/project2/sql/rdbmsDataSource.cpp
+++ b/project2/sql/rdbmsDataSource.cpp
@@ -43,10 +43,10 @@ RdbmsDataSource::DSNSet RdbmsDataSource::changedDSNs;
 RdbmsDataSource::RdbmsDataSource(ScriptNodePtr p) :
 	DataSource(p),
 	masterDsn(p->child("masterdsn")),
-	preferLocal(p->value("preferlocal", true))
+	preferLocal(p->value("preferlocal", true, NULL))
 {
 	BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("readonly")) {
-		roDSNs.insert(ReadonlyDSNs::value_type(node->value("host").as<std::string>(), node));
+		roDSNs.insert(ReadonlyDSNs::value_type(node->value("host", NULL).as<std::string>(), node));
 	}
 }
 
@@ -194,8 +194,8 @@ RdbmsDataSource::RdbmsConnection::isExpired() const
 }
 
 RdbmsDataSource::ConnectionInfo::ConnectionInfo(ScriptNodePtr node) :
-	dsn(node->value("dsn").as<std::string>()),
-	typeId(Plugable::getLoader<ConnectionLoader, UnknownConnectionProvider>(node->value("provider")))
+	dsn(node->value("dsn", NULL).as<std::string>()),
+	typeId(Plugable::getLoader<ConnectionLoader, UnknownConnectionProvider>(node->value("provider", NULL)))
 {
 }
 
diff --git a/project2/sql/sqlBulkLoad.cpp b/project2/sql/sqlBulkLoad.cpp
index a8283b9..8787d3e 100644
--- a/project2/sql/sqlBulkLoad.cpp
+++ b/project2/sql/sqlBulkLoad.cpp
@@ -20,17 +20,17 @@ class SqlBulkLoad : public Task {
 
 		void loadComplete(const CommonObjects * co)
 		{
-			db = co->dataSource<RdbmsDataSource>(dataSource());
+			db = co->dataSource<RdbmsDataSource>(dataSource(NULL));
 		}
 
-		void execute() const
+		void execute(ExecContext * ec) const
 		{
 			const DB::Connection & wdb = db->getWritable();
-			wdb.beginBulkUpload(targetTable(), extras());
+			wdb.beginBulkUpload(targetTable(ec), extras(ec));
 			ScopeObject tidy([]{},
 					[&]{ wdb.endBulkUpload(NULL); },
 					[&]{ wdb.endBulkUpload("Stack unwind in progress"); });
-			stream->runStream(boost::bind(&DB::Connection::bulkUploadData, &wdb, _1, _2));
+			stream->runStream(boost::bind(&DB::Connection::bulkUploadData, &wdb, _1, _2), ec);
 		}
 
 		const Variable dataSource;
diff --git a/project2/sql/sqlCache.cpp b/project2/sql/sqlCache.cpp
index ba8dfb5..66e9288 100644
--- a/project2/sql/sqlCache.cpp
+++ b/project2/sql/sqlCache.cpp
@@ -85,7 +85,7 @@ class SqlCache : public Cache {
 						friend class SqlCacheRowSet;
 						const SqlCacheRowSet * sc;
 				};
-				void execute(const Glib::ustring&, const RowProcessor * rp) const {
+				void execute(const Glib::ustring&, const RowProcessorCallback & rp, ExecContext *) const {
 					SqlCacheRowState ss(this);
 					HandleAsVariableType h;
 					do {
@@ -125,7 +125,7 @@ class SqlCache : public Cache {
 				mutable int64_t cacheId;
 		};
 
-		RowSetCPtr getCachedRowSet(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const
+		RowSetCPtr getCachedRowSet(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const
 		{
 			Buffer sql;
 			sql.appendf("SELECT r.* \
@@ -136,12 +136,12 @@ class SqlCache : public Cache {
 					HeaderTable.c_str(),
 					HeaderTable.c_str(), n.c_str(), f.c_str(),
 					HeaderTable.c_str(),n.c_str(), f.c_str());
-			applyKeys(boost::bind(appendKeyAnds, &sql, _1), ps);
+			applyKeys(ec, boost::bind(appendKeyAnds, &sql, _1), ps);
 			sql.appendf(" ORDER BY r.p2_cacheid DESC, r.p2_row");
 			SelectPtr gh(db->getReadonly().newSelectCommand(sql));
 			unsigned int offset = 0;
 			gh->bindParamT(offset++, time(NULL) - CacheLife);
-			applyKeys(boost::bind(bindKeyValues, gh.get(), &offset, _2), ps);
+			applyKeys(ec, boost::bind(bindKeyValues, gh.get(), &offset, _2), ps);
 			if (gh->fetch()) {
 				return new SqlCacheRowSet(gh);
 			}
@@ -202,7 +202,7 @@ class SqlCache : public Cache {
 				mutable Values cols, attrs;
 		};
 
-		RowSetPresenterPtr openFor(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps)
+		RowSetPresenterPtr openFor(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps)
 		{
 			Buffer sp;
 			sp.appendf("SAVEPOINT sp%p", this);
@@ -218,19 +218,19 @@ class SqlCache : public Cache {
 			Buffer sql;
 			sql.appendf("INSERT INTO %s_%s_%s(", HeaderTable.c_str(), n.c_str(), f.c_str());
 			unsigned int offset = 0;
-			applyKeys(boost::bind(appendKeyCols, &sql, &offset, _1), ps);
+			applyKeys(ec, boost::bind(appendKeyCols, &sql, &offset, _1), ps);
 			sql.appendf(") VALUES(");
 			offset = 0;
-			applyKeys(boost::bind(appendKeyBinds, &sql, &offset), ps);
+			applyKeys(ec, boost::bind(appendKeyBinds, &sql, &offset), ps);
 			sql.appendf(")");
 			ModifyPtr m(db->getWritable().newModifyCommand(sql));
 			offset = 0;
-			applyKeys(boost::bind(bindKeyValues, m.get(), &offset, _2), ps);
+			applyKeys(ec, boost::bind(bindKeyValues, m.get(), &offset, _2), ps);
 			m->execute();
 			return new SqlCachePresenter(n, f, db);
 		}
 
-		void save(const Glib::ustring & , const Glib::ustring & , const IHaveParameters * )
+		void save(ExecContext *, const Glib::ustring & , const Glib::ustring & , const IHaveParameters * )
 		{
 			Buffer sp;
 			sp.appendf("RELEASE SAVEPOINT sp%p", this);
@@ -238,7 +238,7 @@ class SqlCache : public Cache {
 			s->execute();
 		}
 
-		void discard(const Glib::ustring & , const Glib::ustring & , const IHaveParameters * )
+		void discard(ExecContext *, const Glib::ustring & , const Glib::ustring & , const IHaveParameters * )
 		{
 			Buffer sp;
 			sp.appendf("ROLLBACK TO SAVEPOINT sp%p", this);
diff --git a/project2/sql/sqlMergeTask.cpp b/project2/sql/sqlMergeTask.cpp
index 0b19c5e..c5eb93c 100644
--- a/project2/sql/sqlMergeTask.cpp
+++ b/project2/sql/sqlMergeTask.cpp
@@ -27,10 +27,10 @@ class SqlMergeInsert : IHaveParameters, public Task {
 			Task(p),
 			insert(NULL) {
 		}
-		void execute() const {
+		void execute(ExecContext * ec) const {
 			unsigned int col = 0;
 			BOOST_FOREACH(const Parameters::value_type & v, parameters) {
-				boost::apply_visitor<const SqlVariableBinder, const VariableType>(SqlVariableBinder(insert, col++), v.second);
+				boost::apply_visitor<const SqlVariableBinder, const VariableType>(SqlVariableBinder(insert, col++), v.second(ec));
 			}
 			insert->execute();
 		}
@@ -59,26 +59,26 @@ SqlMergeTask::SqlMergeTask(ScriptNodePtr p) :
 	insCmd(NULL),
 	destdb(NULL),
 	dataSource(p, "datasource"),
-	dtable(p->value("targettable").as<std::string>()),
+	dtable(p->value("targettable", NULL).as<std::string>()),
 	dtablet(stringf("tmp_%s_%d", dtable.c_str(), getpid()))
 {
 	p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&sources));
 
-	if (!sources.empty() && useView()) {
+	if (!sources.empty() && useView(NULL)) {
 		throw NotSupported("useview not supported with iterate fillers");
 	}
 
 	BOOST_FOREACH(ScriptNodePtr e, p->childrenIn("columns")) {
 		TargetColumnPtr tcp(new TargetColumn(e->get_name()));
-		tcp->maptable = e->value("maptable", "").as<std::string>();
+		tcp->maptable = e->value("maptable", "", NULL).as<std::string>();
 		if (!tcp->maptable.empty()) {
-			if (useView()) {
+			if (useView(NULL)) {
 				throw NotSupported("useview not supported with mapped columns");
 			}
-			tcp->mapcolumn = e->value("mapcolumn").as<std::string>();
+			tcp->mapcolumn = e->value("mapcolumn", NULL).as<std::string>();
 		}
 		cols.insert(tcp);
-		tcp->isKey = e->value("key", false);
+		tcp->isKey = e->value("key", false, NULL);
 		if (tcp->isKey) {
 			keys.insert(tcp->column);
 		}
@@ -97,7 +97,7 @@ SqlMergeTask::~SqlMergeTask()
 void
 SqlMergeTask::loadComplete(const CommonObjects * co)
 {
-	destdb = &co->dataSource<RdbmsDataSource>(dataSource())->getWritable();
+	destdb = &co->dataSource<RdbmsDataSource>(dataSource(NULL))->getWritable();
 	insCmd = insertCommand();
 	BOOST_FOREACH(const Sources::value_type & i, sources) {
 		attach(i, insCmd);
@@ -116,16 +116,37 @@ SqlMergeTask::TargetColumn::Sort::operator()(const TargetColumnPtr & a, const Ta
 	return a->column < b->column;
 }
 
+class MergeWhere : public TablePatch::WhereProvider {
+	public:
+		MergeWhere(DynamicSql::SqlCommand * u, ExecContext * e) :
+			ec(e),
+			updateWhere(u)
+		{
+		}
+		void appendWhere(Buffer * buf) const
+		{
+			buf->appendf(" AND %s ", updateWhere->getSqlFor("").c_str());
+		}
+		void bindWhere(DB::Command * cmd) const
+		{
+			unsigned int off = 0;
+			updateWhere->bindParams(ec, cmd, off);
+		}
+	private:
+		ExecContext * ec;
+		const DynamicSql::SqlCommand * updateWhere;
+};
+
 void
-SqlMergeTask::execute() const
+SqlMergeTask::execute(ExecContext * ec) const
 {
 	createTempTable();
-	if (earlyKeys()) {
+	if (earlyKeys(NULL)) {
 		createTempKey();
-		copyToTempTable();
+		copyToTempTable(ec);
 	}
 	else {
-		copyToTempTable();
+		copyToTempTable(ec);
 		createTempKey();
 	}
 	std::set<std::string> colNames;
@@ -133,20 +154,21 @@ SqlMergeTask::execute() const
 		colNames.insert(c->column);
 	}
 	TablePatch tp(*destdb, dtablet, dtable, colNames);
-	tp.doDelete = doDelete();
-	tp.doUpdate = doUpdate();
-	tp.doInsert = doInsert();
+	tp.doDelete = doDelete(NULL);
+	tp.doUpdate = doUpdate(NULL);
+	tp.doInsert = doInsert(NULL);
 	BOOST_FOREACH(const Keys::value_type & k, keys) {
 		tp.addKey(k);
 	}
-	tp.patch(updateWhere ? this : NULL, patchOrder());
+	MergeWhere mw(updateWhere.get(), ec);
+	tp.patch(updateWhere ? &mw : NULL, patchOrder(NULL));
 	dropTempTable();
 }
 
 void
 SqlMergeTask::createTempTable() const
 {
-	if (useView()) {
+	if (useView(NULL)) {
 		DB::ModifyCommand * cv = destdb->newModifyCommand(stringf(
 					"CREATE VIEW %s AS %s",
 					dtablet.c_str(),
@@ -179,7 +201,7 @@ SqlMergeTask::dropTempTable() const
 {
 	if (tempTableCreated) {
 		DB::ModifyCommand * d;
-		if (useView()) {
+		if (useView(NULL)) {
 			 d = destdb->newModifyCommand("DROP VIEW " + dtablet);
 		}
 		else {
@@ -192,7 +214,7 @@ SqlMergeTask::dropTempTable() const
 void
 SqlMergeTask::createTempKey() const
 {
-	if (useView()) return;
+	if (useView(NULL)) return;
 	/* Primary key */
 	Buffer idx;
 	idx.appendf("ALTER TABLE %s ADD CONSTRAINT pk_%s PRIMARY KEY(%s)",
@@ -244,10 +266,10 @@ class Populate : public NoOutputExecute {
 			cmd(c)
 		{
 		}
-		void execute() const
+		void execute(ExecContext * ec) const
 		{
 			unsigned int idx = 0;
-			RowState::Stack().back()->foreachColumn(boost::bind(&Populate::bind, this, boost::ref(idx), _3));
+			RowState::Stack().back()->foreachColumn(ec, boost::bind(&Populate::bind, this, boost::ref(idx), _3));
 			cmd->execute();
 		}
 	private:
@@ -285,13 +307,13 @@ attach(boost::intrusive_ptr<IHaveSubTasks> i, DB::ModifyCommand * insert)
 }
 
 void
-SqlMergeTask::copyToTempTable() const
+SqlMergeTask::copyToTempTable(ExecContext * ec) const
 {
-	if (useView()) {
+	if (useView(NULL)) {
 		return;
 	}
 	BOOST_FOREACH(const Sources::value_type & i, sources) {
-		i->execute();
+		i->execute(ec);
 	}
 	if (sqlCommand) {
 		Buffer ins;
@@ -312,7 +334,7 @@ SqlMergeTask::copyToTempTable() const
 		ins.appendf(" FROM (%s) tmp_src", sqlCommand->getSqlFor("").c_str());
 		DB::ModifyCommand * cttt = destdb->newModifyCommand(ins);
 		unsigned int off = 0;
-		sqlCommand->bindParams(cttt, off);
+		sqlCommand->bindParams(ec, cttt, off);
 		cttt->execute();
 		delete cttt;
 	}
@@ -334,16 +356,3 @@ SqlMergeTask::copyToTempTable() const
 	}
 }
 
-void
-SqlMergeTask::appendWhere(Buffer * buf) const
-{
-	buf->appendf(" AND %s ", updateWhere->getSqlFor("").c_str());
-}
-
-void
-SqlMergeTask::bindWhere(DB::Command * cmd) const
-{
-	unsigned int off = 0;
-	updateWhere->bindParams(cmd, off);
-}
-
diff --git a/project2/sql/sqlMergeTask.h b/project2/sql/sqlMergeTask.h
index b63c277..6b74ccd 100644
--- a/project2/sql/sqlMergeTask.h
+++ b/project2/sql/sqlMergeTask.h
@@ -16,7 +16,7 @@
 #include <list>
 
 /// Project2 component merge arbitrary data into an RDBMS table
-class SqlMergeTask : public Task, public TablePatch::WhereProvider {
+class SqlMergeTask : public Task {
 	public:
 		typedef std::string Table;
 		typedef std::string Column;
@@ -44,7 +44,7 @@ class SqlMergeTask : public Task, public TablePatch::WhereProvider {
 		virtual ~SqlMergeTask();
 
 		virtual void loadComplete(const CommonObjects *);
-		void execute() const;
+		void execute(ExecContext *) const;
 		Columns cols;
 		Keys keys;
 		Keys indexes;
@@ -57,12 +57,10 @@ class SqlMergeTask : public Task, public TablePatch::WhereProvider {
 		const Variable doInsert;
 
 	private:
-		virtual void copyToTempTable() const;
+		virtual void copyToTempTable(ExecContext * ec) const;
 		void createTempTable() const;
 		void dropTempTable() const;
 		void createTempKey() const;
-		void appendWhere(Buffer *) const;
-		void bindWhere(DB::Command *) const;
 
 		mutable bool tempTableCreated;
 		typedef ANONSTORAGEOF(Iterate) Sources;
diff --git a/project2/sql/sqlRows.cpp b/project2/sql/sqlRows.cpp
index 83763dd..f723269 100644
--- a/project2/sql/sqlRows.cpp
+++ b/project2/sql/sqlRows.cpp
@@ -28,7 +28,7 @@ SqlRows::~SqlRows()
 void
 SqlRows::loadComplete(const CommonObjects * co)
 {
-	db = co->dataSource<RdbmsDataSource>(dataSource());
+	db = co->dataSource<RdbmsDataSource>(dataSource(NULL));
 }
 
 SqlRows::SqlState::SqlState(SelectPtr s) :
@@ -48,11 +48,11 @@ SqlRows::SqlState::getColumns() const
 }
 
 void
-SqlRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const
+SqlRows::execute(const Glib::ustring & filter, const RowProcessorCallback & rp, ExecContext * ec) const
 {
 	unsigned int offset = 0;
 	SqlState ss(SelectPtr(db->getReadonly().newSelectCommand(sqlCommand.getSqlFor(filter))));
-	sqlCommand.bindParams(ss.query.get(), offset);
+	sqlCommand.bindParams(ec, ss.query.get(), offset);
 	while (ss.query->fetch()) {
 		HandleAsVariableType h;
 		if (ss.fields.empty()) {
diff --git a/project2/sql/sqlRows.h b/project2/sql/sqlRows.h
index 7ed5d3f..6f78dcd 100644
--- a/project2/sql/sqlRows.h
+++ b/project2/sql/sqlRows.h
@@ -16,7 +16,7 @@ class SqlRows : public RowSet {
 		SqlRows(ScriptNodePtr p);
 		~SqlRows();
 
-		void execute(const Glib::ustring &, const RowProcessor *) const;
+		void execute(const Glib::ustring &, const RowProcessorCallback &, ExecContext *) const;
 		virtual void loadComplete(const CommonObjects *);
 
 		const Variable dataSource;
diff --git a/project2/sql/sqlTask.cpp b/project2/sql/sqlTask.cpp
index 03f67de..80ea08e 100644
--- a/project2/sql/sqlTask.cpp
+++ b/project2/sql/sqlTask.cpp
@@ -29,24 +29,24 @@ SqlTask::~SqlTask()
 void
 SqlTask::loadComplete(const CommonObjects * co)
 {
-	db = co->dataSource<RdbmsDataSource>(dataSource());
+	db = co->dataSource<RdbmsDataSource>(dataSource(NULL));
 }
 
 void
-SqlTask::execute() const
+SqlTask::execute(ExecContext * ec) const
 {
 	boost::shared_ptr<DB::ModifyCommand> modify = boost::shared_ptr<DB::ModifyCommand>(
-			db->getWritable().newModifyCommand(sqlCommand.getSqlFor(filter())));
+			db->getWritable().newModifyCommand(sqlCommand.getSqlFor(filter(NULL))));
 	unsigned int offset = 0;
-	sqlCommand.bindParams(modify.get(), offset);
+	sqlCommand.bindParams(ec, modify.get(), offset);
 	if (modify->execute() == 0) {
 		BOOST_FOREACH(const SubNOEs::value_type & sq, noChangesNOEs) {
-			sq->execute();
+			sq->execute(ec);
 		}
 	}
 	else {
 		BOOST_FOREACH(const SubNOEs::value_type & sq, changesNOEs) {
-			sq->execute();
+			sq->execute(ec);
 		}
 	}
 }
diff --git a/project2/sql/sqlTask.h b/project2/sql/sqlTask.h
index b0d0d27..94901a9 100644
--- a/project2/sql/sqlTask.h
+++ b/project2/sql/sqlTask.h
@@ -16,7 +16,7 @@ class SqlTask : public Task {
 		SqlTask(ScriptNodePtr p);
 		virtual ~SqlTask();
 		virtual void loadComplete(const CommonObjects *);
-		virtual void execute() const;
+		virtual void execute(ExecContext * ec) const;
 
 		const Variable dataSource;
 		const Variable filter;
diff --git a/project2/sql/sqlTest.cpp b/project2/sql/sqlTest.cpp
index f45b2c9..2723d8e 100644
--- a/project2/sql/sqlTest.cpp
+++ b/project2/sql/sqlTest.cpp
@@ -32,7 +32,7 @@ SqlTest::~SqlTest()
 void
 SqlTest::loadComplete(const CommonObjects * co)
 {
-	db = co->dataSource<RdbmsDataSource>(dataSource());
+	db = co->dataSource<RdbmsDataSource>(dataSource(NULL));
 }
 
 class HandleDoCompare : public DB::HandleField {
@@ -88,13 +88,13 @@ class HandleDoCompare : public DB::HandleField {
 		std::string testOp;
 };
 bool
-SqlTest::passes() const
+SqlTest::passes(ExecContext * ec) const
 {
 	boost::shared_ptr<DB::SelectCommand> query = boost::shared_ptr<DB::SelectCommand>(
-			db->getWritable().newSelectCommand(sqlCommand.getSqlFor(filter())));
+			db->getWritable().newSelectCommand(sqlCommand.getSqlFor(filter(NULL))));
 	unsigned int offset = 0;
-	sqlCommand.bindParams(query.get(), offset);
-	HandleDoCompare h(testValue, testOp());
+	sqlCommand.bindParams(ec, query.get(), offset);
+	HandleDoCompare h(testValue(ec), testOp(ec));
 	while (query->fetch()) {
 		(*query)[0].apply(h);
 	}
diff --git a/project2/sql/sqlTest.h b/project2/sql/sqlTest.h
index f722424..af843d1 100644
--- a/project2/sql/sqlTest.h
+++ b/project2/sql/sqlTest.h
@@ -14,7 +14,7 @@ class SqlTest : public Test {
 		virtual ~SqlTest();
 
 		virtual void loadComplete(const CommonObjects *);
-		bool passes() const;
+		bool passes(ExecContext *) const;
 
 		const Variable dataSource;
 		const Variable filter;
diff --git a/project2/sql/sqlWriter.cpp b/project2/sql/sqlWriter.cpp
index 1220211..5278759 100644
--- a/project2/sql/sqlWriter.cpp
+++ b/project2/sql/sqlWriter.cpp
@@ -64,15 +64,15 @@ DynamicSql::SqlCommand::writeSql(Glib::ustring & sql) const
 }
 
 void
-DynamicSql::SqlCommand::bindParams(DB::Command * cmd, unsigned int & offset) const
+DynamicSql::SqlCommand::bindParams(ExecContext * ec, DB::Command * cmd, unsigned int & offset) const
 {
 	BOOST_FOREACH(const SqlWriterPtr & w, writers) {
-		w->bindParams(cmd, offset);
+		w->bindParams(ec, cmd, offset);
 	}
 }
 
 DynamicSql::SqlFilter::SqlFilter(ScriptNodePtr p) :
-	name(p->value("name").as<Glib::ustring>()),
+	name(p->value("name", NULL).as<Glib::ustring>()),
 	active(false)
 {
 	p->composeWithCallbacks(
@@ -91,11 +91,11 @@ DynamicSql::SqlFilter::writeSql(Glib::ustring & sql) const
 }
 
 void
-DynamicSql::SqlFilter::bindParams(DB::Command * cmd, unsigned int & offset) const
+DynamicSql::SqlFilter::bindParams(ExecContext * ec, DB::Command * cmd, unsigned int & offset) const
 {
 	if (active) {
 		BOOST_FOREACH(const SqlWriterPtr & w, writers) {
-			w->bindParams(cmd, offset);
+			w->bindParams(ec, cmd, offset);
 		}
 	}
 }
@@ -112,9 +112,9 @@ DynamicSql::SqlParameter::writeSql(Glib::ustring & sql) const
 }
 
 void
-DynamicSql::SqlParameter::bindParams(DB::Command * cmd, unsigned int & offset) const
+DynamicSql::SqlParameter::bindParams(ExecContext * ec, DB::Command * cmd, unsigned int & offset) const
 {
-	boost::apply_visitor<const SqlVariableBinder, const VariableType>(SqlVariableBinder(cmd, offset++), (*this));
+	boost::apply_visitor<const SqlVariableBinder, const VariableType>(SqlVariableBinder(cmd, offset++), (*this)(ec));
 }
 
 DynamicSql::SqlText::SqlText(const Glib::ustring & n) :
@@ -129,7 +129,7 @@ DynamicSql::SqlText::writeSql(Glib::ustring & sql) const
 }
 
 void
-DynamicSql::SqlText::bindParams(DB::Command *, unsigned int &) const
+DynamicSql::SqlText::bindParams(ExecContext *, DB::Command *, unsigned int &) const
 {
 }
 
diff --git a/project2/sql/sqlWriter.h b/project2/sql/sqlWriter.h
index 4b57fa9..5eef9ac 100644
--- a/project2/sql/sqlWriter.h
+++ b/project2/sql/sqlWriter.h
@@ -17,13 +17,13 @@ namespace DynamicSql {
 			SqlWriter();
 			virtual ~SqlWriter();
 			virtual void writeSql(Glib::ustring & sql) const = 0;
-			virtual void bindParams(DB::Command *, unsigned int & offset) const = 0;
+			virtual void bindParams(ExecContext *, DB::Command *, unsigned int & offset) const = 0;
 	};
 	class SqlText : public SqlWriter {
 		public:
 			SqlText(const Glib::ustring &);
 			virtual void writeSql(Glib::ustring & sql) const;
-			virtual void bindParams(DB::Command *, unsigned int & offset) const;
+			virtual void bindParams(ExecContext *, DB::Command *, unsigned int & offset) const;
 
 			const Glib::ustring text;
 	};
@@ -31,13 +31,13 @@ namespace DynamicSql {
 		public:
 			SqlParameter(ScriptNodePtr);
 			virtual void writeSql(Glib::ustring & sql) const;
-			virtual void bindParams(DB::Command *, unsigned int & offset) const;
+			virtual void bindParams(ExecContext *, DB::Command *, unsigned int & offset) const;
 	};
 	class SqlFilter : public SqlWriter {
 		public:
 			SqlFilter(ScriptNodePtr);
 			virtual void writeSql(Glib::ustring & sql) const;
-			virtual void bindParams(DB::Command *, unsigned int & offset) const;
+			virtual void bindParams(ExecContext *, DB::Command *, unsigned int & offset) const;
 
 			const Glib::ustring name;
 			bool active;
@@ -49,7 +49,7 @@ namespace DynamicSql {
 		public:
 			SqlCommand(ScriptNodePtr);
 			virtual void writeSql(Glib::ustring & sql) const;
-			virtual void bindParams(DB::Command *, unsigned int & offset) const;
+			virtual void bindParams(ExecContext *, DB::Command *, unsigned int & offset) const;
 			typedef std::multimap<Glib::ustring, SqlFilterPtr> Filters;
 			Glib::ustring getSqlFor(const Glib::ustring & f) const;
 		private:
diff --git a/project2/streams/streamNvpRows.cpp b/project2/streams/streamNvpRows.cpp
index 2577ffa..3f5927f 100644
--- a/project2/streams/streamNvpRows.cpp
+++ b/project2/streams/streamNvpRows.cpp
@@ -33,7 +33,7 @@ class StreamNvpRows : public RowSet {
 						mutable size_t firstMatch;
 				};
 
-				ParseState(const StreamNvpRows * rows, const RowProcessor * proc) :
+				ParseState(const StreamNvpRows * rows, const RowProcessorCallback & proc) :
 					sr(rows),
 					rp(proc),
 					inQuotes(false),
@@ -134,7 +134,7 @@ class StreamNvpRows : public RowSet {
 				}
 
 				const StreamNvpRows * sr;
-				const RowProcessor * rp;
+				const RowProcessorCallback & rp;
 				bool inQuotes;
 				bool inValue;
 				bool prevWasQuote;
@@ -148,23 +148,23 @@ class StreamNvpRows : public RowSet {
 
 		StreamNvpRows(ScriptNodePtr p) :
 			RowSet(p),
-			fieldSep(p->value("fieldSep", ",").as<Glib::ustring>()),
-			quoteChar(p->value("quoteChar", "\"").as<Glib::ustring>()),
-			keepBlankRows(p->value("keepBlankRows", false)),
-			countBlankRows(p->value("countBlankRows", false)),
-			newline(p->value("newline", "\n").as<Glib::ustring>()),
-			assign(p->value("assign", "=").as<Glib::ustring>()),
-			encoding(p->value("encoding", "utf-8").as<std::string>())
+			fieldSep(p->value("fieldSep", ",", NULL).as<Glib::ustring>()),
+			quoteChar(p->value("quoteChar", "\"", NULL).as<Glib::ustring>()),
+			keepBlankRows(p->value("keepBlankRows", false, NULL)),
+			countBlankRows(p->value("countBlankRows", false, NULL)),
+			newline(p->value("newline", "\n", NULL).as<Glib::ustring>()),
+			assign(p->value("assign", "=", NULL).as<Glib::ustring>()),
+			encoding(p->value("encoding", "utf-8", NULL).as<std::string>())
 		{
 			p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&stream));
 		}
 
-		void execute(const Glib::ustring &, const RowProcessor * rp) const
+		void execute(const Glib::ustring &, const RowProcessorCallback & rp, ExecContext * ec) const
 		{
 			ParseState ps(this, rp);
 			TextReader::CharSink cs = boost::bind(&StreamNvpRows::ParseState::pushChar, &ps, _1);
 			TextReader t(encoding.c_str());
-			stream->runStream(boost::bind(&TextReader::read, &t, _1, _2, cs));
+			stream->runStream(boost::bind(&TextReader::read, &t, _1, _2, cs), ec);
 		}
 
 	private:
diff --git a/project2/streams/streamRows.cpp b/project2/streams/streamRows.cpp
index 78f6963..890e1d7 100644
--- a/project2/streams/streamRows.cpp
+++ b/project2/streams/streamRows.cpp
@@ -14,7 +14,7 @@ class StreamRows : public DefinedColumns, public RowSet {
 	public:
 		class ParseState : public ColumnValues {
 			public:
-				ParseState(const StreamRows * rows, const RowProcessor * proc) :
+				ParseState(const StreamRows * rows, const RowProcessorCallback & proc) :
 					ColumnValues(rows),
 					sr(rows),
 					rp(proc),
@@ -33,7 +33,7 @@ class StreamRows : public DefinedColumns, public RowSet {
 				}
 
 				const StreamRows * sr;
-				const RowProcessor * rp;
+				const RowProcessorCallback & rp;
 				size_t skipheader;
 				bool inQuotes;
 				bool prevWasQuote;
@@ -46,23 +46,23 @@ class StreamRows : public DefinedColumns, public RowSet {
 		StreamRows(ScriptNodePtr p) :
 			DefinedColumns(p, "columns", boost::bind(&Column::make, _1, _2)),
 			RowSet(p),
-			fieldSep(p->value("fieldSep", ",").as<Glib::ustring>()[0]),
-			quoteChar(p->value("quoteChar", "\"").as<Glib::ustring>()[0]),
-			keepBlankRows(p->value("keepBlankRows", false)),
-			countBlankRows(p->value("countBlankRows", false)),
-			newline(p->value("newline", "\n").as<Glib::ustring>()),
-			encoding(p->value("encoding", "utf-8").as<std::string>()),
-			skipheader(p->value("skipheader", 0).as<int64_t>())
+			fieldSep(p->value("fieldSep", ",", NULL).as<Glib::ustring>()[0]),
+			quoteChar(p->value("quoteChar", "\"", NULL).as<Glib::ustring>()[0]),
+			keepBlankRows(p->value("keepBlankRows", false, NULL)),
+			countBlankRows(p->value("countBlankRows", false, NULL)),
+			newline(p->value("newline", "\n", NULL).as<Glib::ustring>()),
+			encoding(p->value("encoding", "utf-8", NULL).as<std::string>()),
+			skipheader(p->value("skipheader", 0, NULL).as<int64_t>())
 		{
 			p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&stream));
 		}
 
-		void execute(const Glib::ustring &, const RowProcessor * rp) const
+		void execute(const Glib::ustring &, const RowProcessorCallback & rp, ExecContext * ec) const
 		{
 			ParseState ps(this, rp);
 			TextReader::CharSink cs = boost::bind(&StreamRows::pushChar, this, _1, boost::ref(ps));
 			TextReader t(encoding.c_str());
-			stream->runStream(boost::bind(&TextReader::read, &t, _1, _2, cs));
+			stream->runStream(boost::bind(&TextReader::read, &t, _1, _2, cs), ec);
 		}
 
 		void pushChar(gunichar c, ParseState & ps) const
diff --git a/project2/streams/viewStream.cpp b/project2/streams/viewStream.cpp
index 28efc17..29917f6 100644
--- a/project2/streams/viewStream.cpp
+++ b/project2/streams/viewStream.cpp
@@ -27,23 +27,23 @@ class ViewStream : public Stream, public ViewHost {
 			Stream(p),
 			ViewHost(p)
 		{
-			p->script->loader.addLoadTarget(p, Storer::into<PresenterLoader>(&presenter, Scripted));
+			p->script->loader.addLoadTarget(p, Storer::into<PresenterLoader>(&presenter, Scripted, (ExecContext*)NULL));
 		}
-		void runStream(const Stream::Sink & s) const
+		void runStream(const Stream::Sink & s, ExecContext * ec) const
 		{
-			TransformSourcePtr t = boost::dynamic_pointer_cast<TransformSource>(getPresenter());
+			TransformSourcePtr t = boost::dynamic_pointer_cast<TransformSource>(getPresenter(ec));
 			if (t) {
 				boost::iostreams::stream<SinkStream> strm(s);
 				ostreamWrapper * o = new ostreamWrapper(strm);
-				executeViews();
-				t->addTarget(o);
+				executeViews(ec);
+				t->addTarget(o, ec, NULL);
 				ScopeObject remove([&t] { t->clearTargets(); });
-				doTransforms();
+				doTransforms(ec);
 			}
 		}
 
 	private:
-		MultiRowSetPresenterPtr getPresenter() const {
+		MultiRowSetPresenterPtr getPresenter(ExecContext *) const {
 			return presenter;
 		}
 		MultiRowSetPresenterPtr presenter;
diff --git a/project2/url/curlHelper.cpp b/project2/url/curlHelper.cpp
index 7f698cb..2988be9 100644
--- a/project2/url/curlHelper.cpp
+++ b/project2/url/curlHelper.cpp
@@ -39,26 +39,26 @@ Curl::curlSendHelperHandle(char * ptr, size_t size, size_t nmemb, void *stream)
 }
 
 CurlPtr
-CurlHelper::newCurl() const
+CurlHelper::newCurl(ExecContext * ec) const
 {
 	CurlPtr c = new Curl();
 	c->setopt(CURLOPT_FOLLOWLOCATION, 1);
 	c->setopt(CURLOPT_ENCODING, "deflate, gzip");
-	c->setopt(CURLOPT_URL, getUrl().c_str());
+	c->setopt(CURLOPT_URL, getUrl(ec).c_str());
 	c->setopt(CURLOPT_FAILONERROR, 1);
 	return c;
 }
 
 CurlPtr
-VariableCurlHelper::newCurl() const
+VariableCurlHelper::newCurl(ExecContext * ec) const
 {
-	CurlPtr c = CurlHelper::newCurl();
-	setopt_s(c, CURLOPT_USERAGENT, userAgent());
-	setopt_s(c, CURLOPT_PROXY, proxy());
-	setopt_s(c, CURLOPT_REFERER, referer());
-	setopt_s(c, CURLOPT_COOKIEFILE, cookieJar());
-	setopt_s(c, CURLOPT_COOKIEJAR, cookieJar());
-	setopt_l(c, CURLOPT_TIMEOUT_MS, timeout());
+	CurlPtr c = CurlHelper::newCurl(ec);
+	setopt_s(c, CURLOPT_USERAGENT, userAgent(ec));
+	setopt_s(c, CURLOPT_PROXY, proxy(ec));
+	setopt_s(c, CURLOPT_REFERER, referer(ec));
+	setopt_s(c, CURLOPT_COOKIEFILE, cookieJar(ec));
+	setopt_s(c, CURLOPT_COOKIEJAR, cookieJar(ec));
+	setopt_l(c, CURLOPT_TIMEOUT_MS, timeout(ec));
 	return c;
 }
 
@@ -103,8 +103,8 @@ VariableCurlHelper::setopt_l(CurlPtr c, CURLoption o, int64_t v)
 }
 
 std::string
-VariableCurlHelper::getUrl() const
+VariableCurlHelper::getUrl(ExecContext * ec) const
 {
-	return url();
+	return url(ec);
 }
 
diff --git a/project2/url/curlHelper.h b/project2/url/curlHelper.h
index e3e4484..9c0bbba 100644
--- a/project2/url/curlHelper.h
+++ b/project2/url/curlHelper.h
@@ -25,10 +25,10 @@ class CurlHelper {
 		CurlHelper();
 		~CurlHelper();
 
-		virtual CurlPtr newCurl() const;
+		virtual CurlPtr newCurl(ExecContext *) const;
 
 	protected:
-		virtual std::string getUrl() const = 0;
+		virtual std::string getUrl(ExecContext *) const = 0;
 };
 
 /// Project2 helper component to configure CurlHelper from variables
@@ -40,8 +40,8 @@ class VariableCurlHelper : public CurlHelper {
 		const Variable url;
 
 	protected:
-		virtual CurlPtr newCurl() const;
-		virtual std::string getUrl() const;
+		virtual CurlPtr newCurl(ExecContext *) const;
+		virtual std::string getUrl(ExecContext *) const;
 
 	private:
 		static void setopt_s(CurlPtr, CURLoption, const char *);
diff --git a/project2/url/downloadToFile.cpp b/project2/url/downloadToFile.cpp
index 5546efc..2f6726e 100644
--- a/project2/url/downloadToFile.cpp
+++ b/project2/url/downloadToFile.cpp
@@ -16,10 +16,10 @@ class Download : public Task, VariableCurlHelper {
 		{
 		}
 
-		void execute() const
+		void execute(ExecContext * ec) const
 		{
-			CurlPtr c = newCurl();
-			FILE * file = fopen(destination(), "w");
+			CurlPtr c = newCurl(ec);
+			FILE * file = fopen(destination(ec), "w");
 			if (!file) {
 				throw syscall_error(errno);
 			}
diff --git a/project2/url/urlStream.cpp b/project2/url/urlStream.cpp
index 3e1a439..d9fa336 100644
--- a/project2/url/urlStream.cpp
+++ b/project2/url/urlStream.cpp
@@ -13,9 +13,9 @@ class UrlStream : public Stream, VariableCurlHelper {
 		{
 		}
 
-		void runStream(const Sink & sink) const
+		void runStream(const Sink & sink, ExecContext * ec) const
 		{
-			CurlPtr c = newCurl();
+			CurlPtr c = newCurl(ec);
 			c->performRead(sink);
 		}
 };
diff --git a/project2/xml/mutators/copy.cpp b/project2/xml/mutators/copy.cpp
index 087cffc..5c16ef6 100644
--- a/project2/xml/mutators/copy.cpp
+++ b/project2/xml/mutators/copy.cpp
@@ -14,10 +14,10 @@ class Copy : public XmlDocMutator {
 		}
 		void mutateElement(xmlpp::Element * root) const
 		{
-			BOOST_FOREACH(xmlpp::Node * e, root->find(from())) {
-				BOOST_FOREACH(xmlpp::Node * t, e->find(to())) {
+			BOOST_FOREACH(xmlpp::Node * e, root->find(from(NULL))) {
+				BOOST_FOREACH(xmlpp::Node * t, e->find(to(NULL))) {
 					t->import_node(e);
-					if (delAfter()) {
+					if (delAfter(NULL)) {
 						e->get_parent()->remove_child(e);
 					}
 				}
diff --git a/project2/xml/mutators/copyToAttr.cpp b/project2/xml/mutators/copyToAttr.cpp
index c87facb..9f0db5b 100644
--- a/project2/xml/mutators/copyToAttr.cpp
+++ b/project2/xml/mutators/copyToAttr.cpp
@@ -14,12 +14,12 @@ class CopyToAttr : public XmlDocMutator {
 		}
 		void mutateElement(xmlpp::Element * root) const
 		{
-			BOOST_FOREACH(xmlpp::Node * e, root->find(from())) {
+			BOOST_FOREACH(xmlpp::Node * e, root->find(from(NULL))) {
 				if (xmlpp::Element * ee = dynamic_cast<xmlpp::Element *>(e)) {
-					BOOST_FOREACH(xmlpp::Node * t, e->find(to())) {
+					BOOST_FOREACH(xmlpp::Node * t, e->find(to(NULL))) {
 						if (xmlpp::Element * te = dynamic_cast<xmlpp::Element *>(t)) {
 							te->set_attribute(e->get_name(), ee->get_child_text()->get_content());
-							if (delAfter()) {
+							if (delAfter(NULL)) {
 								e->get_parent()->remove_child(e);
 							}
 						}
diff --git a/project2/xml/mutators/create.cpp b/project2/xml/mutators/create.cpp
index a10f54a..2c271dd 100644
--- a/project2/xml/mutators/create.cpp
+++ b/project2/xml/mutators/create.cpp
@@ -13,8 +13,8 @@ class Create : public XmlDocMutator {
 		}
 		void mutateElement(xmlpp::Element * root) const
 		{
-			BOOST_FOREACH(xmlpp::Node * e, root->find(xpath())) {
-				e->add_child(name());
+			BOOST_FOREACH(xmlpp::Node * e, root->find(xpath(NULL))) {
+				e->add_child(name(NULL));
 			}
 		}
 		Variable xpath;
diff --git a/project2/xml/mutators/delete.cpp b/project2/xml/mutators/delete.cpp
index d6eba58..ed4d620 100644
--- a/project2/xml/mutators/delete.cpp
+++ b/project2/xml/mutators/delete.cpp
@@ -12,7 +12,7 @@ class Delete : public XmlDocMutator {
 		}
 		void mutateElement(xmlpp::Element * root) const
 		{
-			BOOST_FOREACH(xmlpp::Node * e, root->find(xpath())) {
+			BOOST_FOREACH(xmlpp::Node * e, root->find(xpath(NULL))) {
 				e->get_parent()->remove_child(e);
 			}
 		}
diff --git a/project2/xml/mutators/rename.cpp b/project2/xml/mutators/rename.cpp
index 74a4578..544afd9 100644
--- a/project2/xml/mutators/rename.cpp
+++ b/project2/xml/mutators/rename.cpp
@@ -13,8 +13,8 @@ class Rename : public XmlDocMutator {
 		}
 		void mutateElement(xmlpp::Element * root) const
 		{
-			BOOST_FOREACH(xmlpp::Node * e, root->find(xpath())) {
-				e->set_name(newname());
+			BOOST_FOREACH(xmlpp::Node * e, root->find(xpath(NULL))) {
+				e->set_name(newname(NULL));
 			}
 		}
 		Variable xpath;
diff --git a/project2/xml/pch.hpp b/project2/xml/pch.hpp
index 3e9c8f1..453f8cc 100644
--- a/project2/xml/pch.hpp
+++ b/project2/xml/pch.hpp
@@ -2,9 +2,7 @@
 #ifndef XML_PCH
 #define XML_PCH
 
-#include "appEngine.h"
 #include "cache.h"
-#include "environment.h"
 #include "exceptions.h"
 #include "iHaveParameters.h"
 #include "logger.h"
diff --git a/project2/xml/rawView.cpp b/project2/xml/rawView.cpp
index 5226caf..1cd1676 100644
--- a/project2/xml/rawView.cpp
+++ b/project2/xml/rawView.cpp
@@ -13,10 +13,10 @@ class RawViewBase : public View {
 		RawViewBase(ScriptNodePtr p) :
 			SourceObject(p),
 			View(p) { }
-		void execute(const MultiRowSetPresenter * mp) const
+		void execute(const MultiRowSetPresenter * mp, ExecContext * ec) const
 		{
 			if (const Presenter * p = dynamic_cast<const Presenter *>(mp)) {
-				BOOST_FOREACH(const auto * node, getCopyRoot()->get_children()) {
+				BOOST_FOREACH(const auto * node, getCopyRoot(ec)->get_children()) {
 					const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(node);
 					if (e) {
 						copyNode(p, e);
@@ -26,7 +26,7 @@ class RawViewBase : public View {
 		}
 
 	protected:
-		virtual const xmlpp::Element * getCopyRoot() const = 0;
+		virtual const xmlpp::Element * getCopyRoot(ExecContext *) const = 0;
 
 	private:
 		void copyNode(const Presenter * p, const xmlpp::Element * n) const
@@ -59,7 +59,7 @@ class RawView : public RawViewBase {
 		{
 		}
 	protected:
-		const xmlpp::Element * getCopyRoot() const { return copyRoot; }
+		const xmlpp::Element * getCopyRoot(ExecContext *) const { return copyRoot; }
 	private:
 		const xmlpp::Element * copyRoot;
 };
@@ -75,13 +75,13 @@ class XmlResourceView : public RawViewBase, XmlDocumentCache, VariableCurlHelper
 		{
 		}
 	protected:
-		const xmlpp::Element * getCopyRoot() const
+		const xmlpp::Element * getCopyRoot(ExecContext * ec) const
 		{
-			return getDocument(url(), encoding())->get_root_node();
+			return getDocument(url(ec), encoding(ec), ec)->get_root_node();
 		}
-		bool asHtml() const { return false; }
-		bool withWarnings() const { return true; }
-		CurlPtr newCurl() const { return VariableCurlHelper::newCurl(); }
+		bool asHtml(ExecContext *) const { return false; }
+		bool withWarnings(ExecContext *) const { return true; }
+		CurlPtr newCurl(ExecContext * ec) const { return VariableCurlHelper::newCurl(ec); }
 
 	private:
 		Variable encoding;
diff --git a/project2/xml/transformHtml.cpp b/project2/xml/transformHtml.cpp
index 0659ca8..adf534b 100644
--- a/project2/xml/transformHtml.cpp
+++ b/project2/xml/transformHtml.cpp
@@ -36,7 +36,7 @@ int	xmlstrmwritecallback(void * context, const char * buffer, int len)
 }
 
 void
-HtmlDocument::writeTo(std::ostream & o, const std::string & encoding) const
+HtmlDocument::writeTo(std::ostream & o, const std::string & encoding, ExecContext *) const
 {
 	xmlOutputBufferPtr buf = xmlOutputBufferCreateIO(xmlstrmwritecallback, xmlstrmclosecallback, &o, NULL);
 	if (method == "html") {
@@ -61,7 +61,7 @@ HtmlDocument::getContentClass() const {
 
 class TransformXmlToHtml : public TransformImpl<xmlpp::Document, HtmlDocument> {
 	public:
-		void transform(const xmlpp::Document * cdata, HtmlDocument * result) const
+		void transform(const xmlpp::Document * cdata, HtmlDocument * result, ExecContext *) const
 		{
 			xmlpp::Document * data = const_cast<xmlpp::Document *>(cdata);
 			typedef boost::shared_ptr<xsltStylesheet> XsltStyleSheetPtr;
diff --git a/project2/xml/transformHtml.h b/project2/xml/transformHtml.h
index cdc8906..d572244 100644
--- a/project2/xml/transformHtml.h
+++ b/project2/xml/transformHtml.h
@@ -13,7 +13,7 @@ class HtmlDocument : public SourceOf<HtmlDocument>, public WritableContent, publ
 		operator const WritableContent * () const;
 		Class getContentClass() const;
 		Glib::ustring getContentType() const;
-		void writeTo(std::ostream &, const std::string & encoding) const;
+		void writeTo(std::ostream &, const std::string & encoding, ExecContext *) const;
 		Glib::ustring contentType;
 		Glib::ustring method;
 };
diff --git a/project2/xml/transformText.cpp b/project2/xml/transformText.cpp
index 7a6e98e..179007d 100644
--- a/project2/xml/transformText.cpp
+++ b/project2/xml/transformText.cpp
@@ -20,7 +20,7 @@ TextDocument::operator const TextDocument * () const { return this; }
 TextDocument::operator const WritableContent * () const { return this; }
 
 void
-TextDocument::writeTo(std::ostream & o, const std::string & encoding) const
+TextDocument::writeTo(std::ostream & o, const std::string & encoding, ExecContext *) const
 {
 	o << Glib::convert(doc.raw(), encoding, "utf-8");
 }
@@ -28,7 +28,7 @@ TextDocument::writeTo(std::ostream & o, const std::string & encoding) const
 Glib::ustring
 TextDocument::getContentType() const
 {
-	return contentType();
+	return contentType(NULL);
 }
 
 WritableContent::Class
@@ -42,7 +42,7 @@ class TransformHtmlToText : public TransformImpl<HtmlDocument, TextDocument> {
 			width(defaultWidth),
 			links(defaultLinks) {
 		}
-		void transform(const HtmlDocument * cdoc, TextDocument * str) const
+		void transform(const HtmlDocument * cdoc, TextDocument * str, ExecContext *) const
 		{
 			xmlDoc * doc = const_cast<xmlDoc *>(cdoc->doc);
 			str->doc.clear();
@@ -76,10 +76,10 @@ class TransformHtmlToText : public TransformImpl<HtmlDocument, TextDocument> {
 				throw std::runtime_error("Lynx failed");
 			}
 		}
-		void configure(ScriptNodePtr s)
+		void configure(ScriptNodePtr s, ExecContext * ec)
 		{
-			s->applyValue("width", width);
-			s->applyValue("links", links);
+			s->applyValue("width", width, ec);
+			s->applyValue("links", links, ec);
 		}
 
 		INITOPTIONS;
diff --git a/project2/xml/transformText.h b/project2/xml/transformText.h
index 3523473..417ceb1 100644
--- a/project2/xml/transformText.h
+++ b/project2/xml/transformText.h
@@ -13,7 +13,7 @@ class TextDocument : public SourceOf<TextDocument>, public WritableContent, publ
 		operator const WritableContent * () const;
 		Class getContentClass() const;
 		Glib::ustring getContentType() const;
-		void writeTo(std::ostream &, const std::string & encoding) const;
+		void writeTo(std::ostream &, const std::string & encoding, ExecContext *) const;
 		Variable contentType;
 };
 
diff --git a/project2/xml/xmlCache.cpp b/project2/xml/xmlCache.cpp
index 3481b1e..85ef689 100644
--- a/project2/xml/xmlCache.cpp
+++ b/project2/xml/xmlCache.cpp
@@ -1,7 +1,6 @@
 #include <pch.hpp>
 #include "cache.h"
 #include "logger.h"
-#include "environment.h"
 #include "scriptLoader.h"
 #include "iHaveParameters.h"
 #include "xmlRawRows.h"
@@ -20,9 +19,9 @@ class XmlCache : public Cache {
 		{
 		}
 
-		RowSetCPtr getCachedRowSet(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const
+		RowSetCPtr getCachedRowSet(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const
 		{
-			boost::filesystem::path cache = getCacheFile(n, f, ps);
+			boost::filesystem::path cache = getCacheFile(ec, n, f, ps);
 			struct stat st;
 			if (stat(cache.string().c_str(), &st) == 0) {
 				if (st.st_mtime < time(NULL) - CacheLife) {
@@ -34,15 +33,15 @@ class XmlCache : public Cache {
 			return NULL;
 		}
 
-		RowSetPresenterPtr openFor(const Glib::ustring & n, const Glib::ustring &, const IHaveParameters *)
+		RowSetPresenterPtr openFor(ExecContext *, const Glib::ustring & n, const Glib::ustring &, const IHaveParameters *)
 		{
 			writeTo = new XmlPresenter(n, Scripts::scriptNamespace, Scripts::scriptNamespacePrefix);
 			return writeTo;
 		}
 
-		void save(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps)
+		void save(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps)
 		{
-			boost::filesystem::path target = getCacheFile(n, f, ps);
+			boost::filesystem::path target = getCacheFile(ec, n, f, ps);
 			try {
 				boost::filesystem::create_directories(target.parent_path());
 				const xmlpp::Document * d = *writeTo;
@@ -54,16 +53,16 @@ class XmlCache : public Cache {
 			}
 		}
 
-		void discard(const Glib::ustring &, const Glib::ustring &, const IHaveParameters *)
+		void discard(ExecContext *, const Glib::ustring &, const Glib::ustring &, const IHaveParameters *)
 		{
 		}
 
 		INITOPTIONS;
 	private:
-		boost::filesystem::path getCacheFile(const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const
+		boost::filesystem::path getCacheFile(ExecContext * ec, const Glib::ustring & n, const Glib::ustring & f, const IHaveParameters * ps) const
 		{
 			boost::filesystem::path cache = Store / n.raw() / f.raw();
-			applyKeys(boost::bind(&appendPath, &cache, _1, _2), ps);
+			applyKeys(ec, boost::bind(&appendPath, &cache, _1, _2), ps);
 			cache /= FileName;
 			return cache;
 		}
diff --git a/project2/xml/xmlDocumentCache.cpp b/project2/xml/xmlDocumentCache.cpp
index ec8d6a8..3f8a81e 100644
--- a/project2/xml/xmlDocumentCache.cpp
+++ b/project2/xml/xmlDocumentCache.cpp
@@ -84,11 +84,11 @@ class XmlDocumentCachePopulator : public CurlCompleteCallback {
 };
 
 XmlDocumentCache::DocumentPtr
-XmlDocumentCache::getDocument(const Glib::ustring & url, const char * encoding) const
+XmlDocumentCache::getDocument(const Glib::ustring & url, const char * encoding, ExecContext * ec) const
 {
 	Documents::const_iterator i = documents.find(url);
 	if (i == documents.end()) {
-		queue(url, encoding);
+		queue(url, encoding, ec);
 		cbf.perform();
 		queued.clear();
 	}
@@ -96,10 +96,10 @@ XmlDocumentCache::getDocument(const Glib::ustring & url, const char * encoding)
 }
 
 void
-XmlDocumentCache::queue(const Glib::ustring & url, const char * encoding) const
+XmlDocumentCache::queue(const Glib::ustring & url, const char * encoding, ExecContext * ec) const
 {
 	if (queued.find(url) == queued.end()) {
-		cbf.curls.insert(new XmlDocumentCachePopulator(newCurl(), url, asHtml(), withWarnings(), encoding));
+		cbf.curls.insert(new XmlDocumentCachePopulator(newCurl(ec), url, asHtml(ec), withWarnings(ec), encoding));
 		queued.insert(url);
 	}
 }
diff --git a/project2/xml/xmlDocumentCache.h b/project2/xml/xmlDocumentCache.h
index fe1725d..a7b7454 100644
--- a/project2/xml/xmlDocumentCache.h
+++ b/project2/xml/xmlDocumentCache.h
@@ -19,14 +19,14 @@ class XmlDocumentCache {
 		static Queued queued;
 		static Documents documents;
 
-		void queue(const Glib::ustring & url, const char * encoding) const;
+		void queue(const Glib::ustring & url, const char * encoding, ExecContext *) const;
 		
-		virtual CurlPtr newCurl() const = 0;
-		virtual bool asHtml() const = 0;
-		virtual bool withWarnings() const = 0;
+		virtual CurlPtr newCurl(ExecContext *) const = 0;
+		virtual bool asHtml(ExecContext * ec) const = 0;
+		virtual bool withWarnings(ExecContext * ec) const = 0;
 
 	protected:
-		DocumentPtr getDocument(const Glib::ustring & url, const char * encoding) const;
+		DocumentPtr getDocument(const Glib::ustring & url, const char * encoding, ExecContext * ec) const;
 
 	private:
 		static CurlBulkFetcher cbf;
diff --git a/project2/xml/xmlDocumentPrefetch.cpp b/project2/xml/xmlDocumentPrefetch.cpp
index 64b236e..4af0055 100644
--- a/project2/xml/xmlDocumentPrefetch.cpp
+++ b/project2/xml/xmlDocumentPrefetch.cpp
@@ -20,32 +20,32 @@ XmlDocumentPrefetch::~XmlDocumentPrefetch()
 }
 
 void
-XmlDocumentPrefetch::execute(const MultiRowSetPresenter*) const
+XmlDocumentPrefetch::execute(const MultiRowSetPresenter*, ExecContext * ec) const
 {
-	execute();
+	execute(ec);
 }
 
 void
-XmlDocumentPrefetch::execute() const
+XmlDocumentPrefetch::execute(ExecContext * ec) const
 {
-	queue(url(), encoding());
+	queue(url(ec), encoding(ec), ec);
 }
 
 CurlPtr
-XmlDocumentPrefetch::newCurl() const
+XmlDocumentPrefetch::newCurl(ExecContext * ec) const
 {
-	return VariableCurlHelper::newCurl();
+	return VariableCurlHelper::newCurl(ec);
 }
 
 bool
-XmlDocumentPrefetch::asHtml() const
+XmlDocumentPrefetch::asHtml(ExecContext * ec) const
 {
-	return html();
+	return html(ec);
 }
 
 bool
-XmlDocumentPrefetch::withWarnings() const
+XmlDocumentPrefetch::withWarnings(ExecContext * ec) const
 {
-	return warnings();
+	return warnings(ec);
 }
 
diff --git a/project2/xml/xmlDocumentPrefetch.h b/project2/xml/xmlDocumentPrefetch.h
index 454492a..fd9285d 100644
--- a/project2/xml/xmlDocumentPrefetch.h
+++ b/project2/xml/xmlDocumentPrefetch.h
@@ -13,16 +13,16 @@ class XmlDocumentPrefetch : public View, public Task, XmlDocumentCache, Variable
 		XmlDocumentPrefetch(ScriptNodePtr p);
 		~XmlDocumentPrefetch();
 
-		void execute(const MultiRowSetPresenter*) const;
-		void execute() const;
+		void execute(const MultiRowSetPresenter*, ExecContext *) const;
+		void execute(ExecContext *) const;
 
 		const Variable html;
 		const Variable warnings;
 		const Variable encoding;
 
-		CurlPtr newCurl() const;
-		bool asHtml() const;
-		bool withWarnings() const;
+		CurlPtr newCurl(ExecContext *) const;
+		bool asHtml(ExecContext * ec) const;
+		bool withWarnings(ExecContext * ec) const;
 };
 
 #endif
diff --git a/project2/xml/xmlPresenter.cpp b/project2/xml/xmlPresenter.cpp
index 08978ce..32960a1 100644
--- a/project2/xml/xmlPresenter.cpp
+++ b/project2/xml/xmlPresenter.cpp
@@ -4,7 +4,6 @@
 #include "scriptLoader.h"
 #include "scriptStorage.h"
 #include "variables.h"
-#include "appEngine.h"
 #include <libxml++/document.h>
 #include <boost/date_time/posix_time/time_formatters.hpp>
 #include <boost/date_time/gregorian/formatters.hpp>
@@ -51,10 +50,10 @@ XmlPresenter::XmlPresenter(const Glib::ustring & responseRootNodeName, const Gli
 {
 }
 
-XmlPresenter::XmlPresenter(ScriptNodePtr e, ObjectSource os) :
+XmlPresenter::XmlPresenter(ScriptNodePtr e, ObjectSource os, ExecContext *) :
 	TransformSource(e, os),
 	Presenter(os),
-	ContentPresenter(e->value("contenttype", "application/xml")),
+	ContentPresenter(e->value("contenttype", "application/xml", NULL)),
 	SourceOf<xmlpp::Document>(e, os),
 	SourceOf<_xmlDoc>(e, os),
 	SourceOf<boost::shared_ptr<xmlpp::Document> >(e, os),
@@ -72,16 +71,16 @@ XmlPresenter::~XmlPresenter()
 }
 
 void
-XmlPresenter::init()
+XmlPresenter::init(ExecContext * ec)
 {
 	responseDoc = XmlDocumentPtr(new xmlpp::Document("1.0"));
 	nodeStack.clear();
-	nodeStack.push_back(responseDoc->create_root_node(root()));
+	nodeStack.push_back(responseDoc->create_root_node(root(ec)));
 	declareNamespace(Scripts::scriptNamespacePrefix, Scripts::scriptNamespace);
 	// XSLT Style
 	char * buf;
-	if (!style().isNull() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"",
-				style().as<const char *>()) > 0) {
+	if (!style(ec).isNull() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"",
+				style(ec).as<const char *>()) > 0) {
 		xmlAddPrevSibling(nodeStack.back()->cobj(),
 				xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf));
 		free(buf);
@@ -247,7 +246,7 @@ XmlPresenter::getContentClass() const {
 }
 
 void
-XmlPresenter::writeTo(std::ostream & o, const std::string & enc) const {
+XmlPresenter::writeTo(std::ostream & o, const std::string & enc, ExecContext *) const {
 	responseDoc->write_to_stream_formatted(o, enc);
 }
 
diff --git a/project2/xml/xmlPresenter.h b/project2/xml/xmlPresenter.h
index 0180342..de3f65b 100644
--- a/project2/xml/xmlPresenter.h
+++ b/project2/xml/xmlPresenter.h
@@ -24,7 +24,7 @@ class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf<
 	public:
 		typedef boost::shared_ptr<xmlpp::Document> XmlDocumentPtr;
 		XmlPresenter(const Glib::ustring & responseRootNodeName, const Glib::ustring & responseStyle, const Glib::ustring & contentType);
-		XmlPresenter(ScriptNodePtr e, ObjectSource);
+		XmlPresenter(ScriptNodePtr e, ObjectSource, ExecContext *);
 		~XmlPresenter();
 
 		void declareNamespace(const Glib::ustring & prefix, const Glib::ustring & ns) const;
@@ -44,9 +44,9 @@ class XmlPresenter : public Presenter, public ContentPresenter, public SourceOf<
 		operator const WritableContent * () const;
 		Class getContentClass() const;
 		Glib::ustring getContentType() const;
-		void writeTo(std::ostream &, const std::string & enc) const;
+		void writeTo(std::ostream &, const std::string & enc, ExecContext *) const;
 		void finalizeContent() const;
-		void init();
+		void init(ExecContext *);
 
 		INITOPTIONS;
 	private:
diff --git a/project2/xml/xmlRawRows.cpp b/project2/xml/xmlRawRows.cpp
index 3511981..e686375 100644
--- a/project2/xml/xmlRawRows.cpp
+++ b/project2/xml/xmlRawRows.cpp
@@ -1,6 +1,5 @@
 #include <pch.hpp>
 #include "xmlRawRows.h"
-#include "environment.h"
 #include <boost/foreach.hpp>
 #include <libxml++/parsers/domparser.h>
 #include <libxml++/nodes/textnode.h>
@@ -53,7 +52,7 @@ XmlRawRowsBase::XmlRawRowsBase() :
 {
 }
 
-void XmlRawRowsBase::execute(const xmlpp::Document * doc, const RowProcessor * rp) const
+void XmlRawRowsBase::execute(const xmlpp::Document * doc, const RowProcessorCallback & rp, ExecContext *) const
 {
 	XmlRowState rs;
 	BOOST_FOREACH(const xmlpp::Node * n, doc->get_root_node()->get_children()) {
@@ -94,10 +93,10 @@ XmlRawRows::XmlRawRows(const Glib::ustring & p) :
 {
 }
 
-void XmlRawRows::execute(const Glib::ustring&, const RowProcessor * rp) const
+void XmlRawRows::execute(const Glib::ustring&, const RowProcessorCallback & rp, ExecContext * ec) const
 {
-	xmlpp::DomParser x(path());
-	XmlRawRowsBase::execute(x.get_document(), rp);
+	xmlpp::DomParser x(path(ec));
+	XmlRawRowsBase::execute(x.get_document(), rp, ec);
 }
 
 XmlMemRawRows::XmlMemRawRows(boost::shared_ptr<const xmlpp::Document> d) :
@@ -105,8 +104,8 @@ XmlMemRawRows::XmlMemRawRows(boost::shared_ptr<const xmlpp::Document> d) :
 {
 }
 
-void XmlMemRawRows::execute(const Glib::ustring&, const RowProcessor * rp) const
+void XmlMemRawRows::execute(const Glib::ustring&, const RowProcessorCallback & rp, ExecContext * ec) const
 {
-	XmlRawRowsBase::execute(doc.get(), rp);
+	XmlRawRowsBase::execute(doc.get(), rp, ec);
 }
 
diff --git a/project2/xml/xmlRawRows.h b/project2/xml/xmlRawRows.h
index 15dad48..ac5a30f 100644
--- a/project2/xml/xmlRawRows.h
+++ b/project2/xml/xmlRawRows.h
@@ -10,7 +10,7 @@ class XmlRawRowsBase : public RowSet {
 		XmlRawRowsBase();
 
 	protected:
-		void execute(const xmlpp::Document *, const RowProcessor * rp) const;
+		void execute(const xmlpp::Document *, const RowProcessorCallback &, ExecContext *) const;
 };
 
 class XmlRawRows : public XmlRawRowsBase {
@@ -18,7 +18,7 @@ class XmlRawRows : public XmlRawRowsBase {
 		XmlRawRows(ScriptNodePtr p);
 		XmlRawRows(const Glib::ustring & p);
 
-		void execute(const Glib::ustring&, const RowProcessor * rp) const;
+		void execute(const Glib::ustring&, const RowProcessorCallback &, ExecContext *) const;
 
 	private:
 		const Variable path;
@@ -28,7 +28,7 @@ class XmlMemRawRows : public XmlRawRowsBase {
 	public:
 		XmlMemRawRows(boost::shared_ptr<const xmlpp::Document> d);
 
-		void execute(const Glib::ustring&, const RowProcessor * rp) const;
+		void execute(const Glib::ustring&, const RowProcessorCallback &, ExecContext *) const;
 
 	private:
 		boost::shared_ptr<const xmlpp::Document> doc;
diff --git a/project2/xml/xmlRows.cpp b/project2/xml/xmlRows.cpp
index 01e626f..7916a37 100644
--- a/project2/xml/xmlRows.cpp
+++ b/project2/xml/xmlRows.cpp
@@ -23,15 +23,15 @@ XmlRows::XmlRows(ScriptNodePtr p) :
 {
 	typedef boost::split_iterator<Glib::ustring::iterator> ssi;
 
-	Glib::ustring rR = recordRoot();
+	Glib::ustring rR = recordRoot(NULL);
 	boost::split(root, rR, boost::is_any_of("/"));
-	Glib::ustring rT = recordTrigger();
+	Glib::ustring rT = recordTrigger(NULL);
 	boost::split(trigger, rT, boost::is_any_of("/"));
 
 	unsigned int col = 0;
 	BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("fields")) {
 		Path p(root);
-		Glib::ustring path = node->value("path");
+		Glib::ustring path = node->value("path", NULL);
 
 		for(ssi It = make_split_iterator(path, first_finder("/", boost::is_equal())); It!=ssi(); ++It) {
 			if (It->front() == '@') {
@@ -60,9 +60,9 @@ store(const XmlRows::Path & position, RowState::FieldValues & values, const XmlR
 }
 
 void
-XmlRows::execute(const Glib::ustring &, const RowProcessor * rp) const
+XmlRows::execute(const Glib::ustring &, const RowProcessorCallback & rp, ExecContext * ec) const
 {
-	xmlTextReaderPtr reader = xmlReaderForFile(filename(), NULL, 0);
+	xmlTextReaderPtr reader = xmlReaderForFile(filename(ec), NULL, 0);
 	if (reader == NULL) {
 		throw std::runtime_error("Failed to open file");
 	}
diff --git a/project2/xml/xmlRows.h b/project2/xml/xmlRows.h
index 975e290..bfc6514 100644
--- a/project2/xml/xmlRows.h
+++ b/project2/xml/xmlRows.h
@@ -15,7 +15,7 @@ class XmlRows : public RowSet {
 		XmlRows(ScriptNodePtr p);
 		~XmlRows();
 
-		void execute(const Glib::ustring &, const RowProcessor *) const;
+		void execute(const Glib::ustring &, const RowProcessorCallback &, ExecContext *) const;
 
 		const Variable recordRoot;
 		const Variable recordTrigger;
diff --git a/project2/xml/xmlScriptParser.cpp b/project2/xml/xmlScriptParser.cpp
index 1040667..5d0d37c 100644
--- a/project2/xml/xmlScriptParser.cpp
+++ b/project2/xml/xmlScriptParser.cpp
@@ -1,6 +1,5 @@
 #include <pch.hpp>
 #include "xmlScriptParser.h"
-#include "environment.h"
 #include "scripts.h"
 #include "commonObjects.h"
 #include "variables/literal.h"
@@ -214,7 +213,7 @@ XmlScriptNode::variable(const boost::optional<Glib::ustring> & defaultSource) co
 }
 
 bool
-XmlScriptNode::applyValue(const Glib::ustring & n, VariableType & val) const
+XmlScriptNode::applyValue(const Glib::ustring & n, VariableType & val, ExecContext * ec) const
 {
 	if (const xmlpp::Attribute * a = element->get_attribute(n)) {
 		val = a->get_value();
@@ -230,7 +229,7 @@ XmlScriptNode::applyValue(const Glib::ustring & n, VariableType & val) const
 			else {
 				v = new VariableLiteral(new XmlScriptNode(c, script));
 			}
-			val = v->value();
+			val = v->value(ec);
 			return false;
 		}
 	}
diff --git a/project2/xml/xmlScriptParser.h b/project2/xml/xmlScriptParser.h
index 0f391a1..f596c8d 100644
--- a/project2/xml/xmlScriptParser.h
+++ b/project2/xml/xmlScriptParser.h
@@ -24,7 +24,7 @@ class XmlScriptNode : public ScriptNode {
 		bool valueExists(const Glib::ustring&) const;
 		VariableImpl * variable(const boost::optional<Glib::ustring> & defaultSource) const;
 		VariableImpl * variable(const Glib::ustring&) const;
-		bool applyValue(const Glib::ustring & name, VariableType & target) const;
+		bool applyValue(const Glib::ustring & name, VariableType & target, ExecContext *) const;
 		void composeWithCallbacks(const ScriptNode::LiteralCallback&, const ScriptNode::NodeCallback&) const;
 
 	private:
diff --git a/project2/xml/xpathRows.cpp b/project2/xml/xpathRows.cpp
index eedfa8e..8537b35 100644
--- a/project2/xml/xpathRows.cpp
+++ b/project2/xml/xpathRows.cpp
@@ -29,7 +29,7 @@ XPathRows::XPathRows(ScriptNodePtr p) :
 		fvs[fv->name] = fv;
 	}
 	BOOST_FOREACH(ScriptNodePtr node, p->childrenIn("namespaces")) {
-		namespaces[node->value("prefix")] = node->value("url").as<Glib::ustring>();
+		namespaces[node->value("prefix", NULL)] = node->value("url", NULL).as<Glib::ustring>();
 	}
 }
 
@@ -38,31 +38,31 @@ XPathRows::~XPathRows()
 }
 
 bool
-XPathRows::asHtml() const
+XPathRows::asHtml(ExecContext * ec) const
 {
-	return html();
+	return html(ec);
 }
 
 bool
-XPathRows::withWarnings() const
+XPathRows::withWarnings(ExecContext * ec) const
 {
-	return warnings();
+	return warnings(ec);
 }
 
 CurlPtr
-XPathRows::newCurl() const
+XPathRows::newCurl(ExecContext * ec) const
 {
-	return VariableCurlHelper::newCurl();
+	return VariableCurlHelper::newCurl(ec);
 }
 
 void
-XPathRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const
+XPathRows::execute(const Glib::ustring & filter, const RowProcessorCallback & rp, ExecContext * ec) const
 {
 	FilterViewPtr fv = safeMapLookup<FilterNotFound>(fvs, filter);
 
 	typedef boost::shared_ptr<xmlXPathObject> xmlXPathObjectSPtr;
 	typedef boost::shared_ptr<xmlXPathContext> xmlXPathContextSPtr;
-	xmlDocPtr doc = getDocument(url(), encoding())->cobj();
+	xmlDocPtr doc = getDocument(url(ec), encoding(ec), ec)->cobj();
 	xmlXPathContextSPtr xpathCtx = xmlXPathContextSPtr(xmlXPathNewContext(doc), xmlXPathFreeContext);
 	if (!xpathCtx) {
 		throw XpathInitError(xmlGetLastError()->message);
@@ -70,18 +70,18 @@ XPathRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const
 	BOOST_FOREACH(const Namespaces::value_type & ns, namespaces) {
 		xmlXPathRegisterNs(xpathCtx.get(), BAD_CAST ns.first.c_str(), BAD_CAST ns.second.c_str());
 	}
-	xmlXPathObjectSPtr xpathObj = xmlXPathObjectSPtr(xmlXPathEvalExpression(fv->root(), xpathCtx.get()), xmlXPathFreeObject);
+	xmlXPathObjectSPtr xpathObj = xmlXPathObjectSPtr(xmlXPathEvalExpression(fv->root(ec), xpathCtx.get()), xmlXPathFreeObject);
 	if (!xpathObj || !xpathObj->nodesetval) {
 		throw XpathEvalError(xmlGetLastError()->message);
 	}
-	Logger()->messagef(LOG_INFO, "%d nodes matched %s", xpathObj->nodesetval->nodeNr, (const char *)(fv->root()));
+	Logger()->messagef(LOG_INFO, "%d nodes matched %s", xpathObj->nodesetval->nodeNr, (const char *)(fv->root(ec)));
 	XPathState xs(fv);
 	for (int row = 0; row < xpathObj->nodesetval->nodeNr; row += 1) {
 		xmlNodePtr rowRoot = xpathObj->nodesetval->nodeTab[row];
 		xpathCtx->node = rowRoot;
 		BOOST_FOREACH(const Columns::value_type & _xp, fv->columns.get<byColIdx>()) {
 			const FilterViewColumn * xp = static_cast<const FilterViewColumn *>(_xp.get());
-			const VariableType & path(xp->path);
+			const VariableType & path(xp->path(ec));
 			if (path.isNull()) {
 				continue;
 			}
diff --git a/project2/xml/xpathRows.h b/project2/xml/xpathRows.h
index 47d34eb..03929ab 100644
--- a/project2/xml/xpathRows.h
+++ b/project2/xml/xpathRows.h
@@ -17,7 +17,7 @@ class XPathRows : public RowSet, XmlDocumentCache, VariableCurlHelper {
 		XPathRows(ScriptNodePtr p);
 		~XPathRows();
 
-		void execute(const Glib::ustring &, const RowProcessor *) const;
+		void execute(const Glib::ustring &, const RowProcessorCallback &, ExecContext *) const;
 
 	private:
 		class FilterViewColumn : public Column {
@@ -40,9 +40,9 @@ class XPathRows : public RowSet, XmlDocumentCache, VariableCurlHelper {
 		typedef std::map<const Glib::ustring, FilterViewPtr> FilterViews;
 		FilterViews fvs;
 
-		virtual CurlPtr newCurl() const;
-		virtual bool asHtml() const;
-		virtual bool withWarnings() const;
+		virtual CurlPtr newCurl(ExecContext *) const;
+		virtual bool asHtml(ExecContext *) const;
+		virtual bool withWarnings(ExecContext *) const;
 
 		typedef std::map<const Glib::ustring, Glib::ustring> Namespaces;
 		Namespaces namespaces;
-- 
cgit v1.2.3