summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-12-26 03:25:34 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-12-26 03:25:34 +0000
commit0999fd565d6d629df87d3db38a84d4701b494b3b (patch)
tree287bb29d011a1c1616ca434ce6c51ab57b63dda2
parentbd4c1d47aeaf1d4bca76d5713e705b0869d3f2f7 (diff)
Simplified server configuration, HTTPD modules now use deployment composite to route service requests, minor fixes to store integration test.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@893939 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--sca-cpp/trunk/components/cache/mcache.cpp11
-rwxr-xr-xsca-cpp/trunk/components/cache/memcached-server-test8
-rw-r--r--sca-cpp/trunk/modules/eval/primitive.hpp44
-rwxr-xr-xsca-cpp/trunk/modules/http/http-test4
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-conf2
-rwxr-xr-xsca-cpp/trunk/modules/http/httpd-test4
-rw-r--r--sca-cpp/trunk/modules/http/httpd.hpp26
-rw-r--r--sca-cpp/trunk/modules/scdl/scdl-test.cpp8
-rw-r--r--sca-cpp/trunk/modules/scdl/scdl.hpp32
-rw-r--r--sca-cpp/trunk/modules/server/domain-test.composite2
-rwxr-xr-xsca-cpp/trunk/modules/server/httpd-test8
-rw-r--r--sca-cpp/trunk/modules/server/impl-test.cpp15
-rw-r--r--sca-cpp/trunk/modules/server/mod-cpp.hpp31
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.cpp287
-rw-r--r--sca-cpp/trunk/modules/server/mod-eval.hpp50
-rw-r--r--sca-cpp/trunk/modules/server/mod-scm.hpp24
-rw-r--r--sca-cpp/trunk/modules/server/mod-wiring.cpp244
-rwxr-xr-xsca-cpp/trunk/modules/server/server-test15
-rwxr-xr-xsca-cpp/trunk/modules/server/wiring-test21
-rw-r--r--sca-cpp/trunk/test/store-script/htdocs/store.html2
-rw-r--r--sca-cpp/trunk/test/store-script/htdocs/store.js6
-rw-r--r--sca-cpp/trunk/test/store-script/shopping-cart.scm24
-rwxr-xr-xsca-cpp/trunk/test/store-script/store-composite-test42
-rw-r--r--sca-cpp/trunk/test/store-script/store.composite27
24 files changed, 515 insertions, 422 deletions
diff --git a/sca-cpp/trunk/components/cache/mcache.cpp b/sca-cpp/trunk/components/cache/mcache.cpp
index b60301bbf2..926fb66674 100644
--- a/sca-cpp/trunk/components/cache/mcache.cpp
+++ b/sca-cpp/trunk/components/cache/mcache.cpp
@@ -89,15 +89,16 @@ const failable<value, std::string> del(const list<value>& params) {
extern "C" {
-const tuscany::failable<tuscany::value, std::string> eval(const tuscany::value& func, const tuscany::list<tuscany::value>& params) {
+const tuscany::value eval(const tuscany::list<tuscany::value>& params) {
+ const tuscany::value func(car(params));
if (func == "get")
- return tuscany::cache::get(params);
+ return tuscany::cache::get(cdr(params));
if (func == "post")
- return tuscany::cache::post(params);
+ return tuscany::cache::post(cdr(params));
if (func == "put")
- return tuscany::cache::put(params);
+ return tuscany::cache::put(cdr(params));
if (func == "delete")
- return tuscany::cache::del(params);
+ return tuscany::cache::del(cdr(params));
return tuscany::mkfailure<tuscany::value, std::string>(std::string("Function not supported: ") + std::string(func));
}
diff --git a/sca-cpp/trunk/components/cache/memcached-server-test b/sca-cpp/trunk/components/cache/memcached-server-test
index 7cd01fe6f5..0dc32f6613 100755
--- a/sca-cpp/trunk/components/cache/memcached-server-test
+++ b/sca-cpp/trunk/components/cache/memcached-server-test
@@ -22,11 +22,9 @@
../../modules/server/server-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
-<Location /mcache>
-SetHandler mod_tuscany_eval
+<Location />
SCAContribution `pwd`/
SCAComposite mcache.composite
-SCAComponent mcache
</Location>
EOF
@@ -34,7 +32,7 @@ apachectl -k start -d `pwd`/tmp
mc="memcached -l 127.0.0.1 -m 4 -p 11211"
$mc &
-sleep 1
+sleep 2
# Test
./mcache-client-test 2>/dev/null
@@ -43,5 +41,5 @@ rc=$?
# Cleanup
kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
apachectl -k stop -d `pwd`/tmp
-sleep 1
+sleep 2
return $rc
diff --git a/sca-cpp/trunk/modules/eval/primitive.hpp b/sca-cpp/trunk/modules/eval/primitive.hpp
index 49bb3e2087..37c53fdd0b 100644
--- a/sca-cpp/trunk/modules/eval/primitive.hpp
+++ b/sca-cpp/trunk/modules/eval/primitive.hpp
@@ -77,6 +77,10 @@ const value listProc(const list<value>& args) {
return args;
}
+const value assocProc(const list<value>& args) {
+ return assoc(car(args), (list<list<value> >)cadr(args));
+}
+
const value nulProc(const list<value>& args) {
const value v(car(args));
if (isNil(v))
@@ -136,8 +140,28 @@ const value uuidProc(unused const list<value>& args) {
return std::string(buf, APR_UUID_FORMATTED_LENGTH);
}
+const value cadrProc(unused const list<value>& args) {
+ return cadr((list<value> )car(args));
+}
+
+const value caddrProc(unused const list<value>& args) {
+ return caddr((list<value> )car(args));
+}
+
+const value cadddrProc(unused const list<value>& args) {
+ return cadddr((list<value> )car(args));
+}
+
+const value cddrProc(unused const list<value>& args) {
+ return cddr((list<value> )car(args));
+}
+
+const value cdddrProc(unused const list<value>& args) {
+ return cdddr((list<value> )car(args));
+}
+
const value applyPrimitiveProcedure(const value& proc, list<value>& args) {
- const lambda<value(list<value>&)> func(cadr((list<value>)proc));
+ const lambda<value(const list<value>&)> func(cadr((list<value>)proc));
return func(args);
}
@@ -166,7 +190,7 @@ const value primitiveImplementation(const list<value>& proc) {
}
template<typename F> const value primitiveProcedure(const F& f) {
- return mklist<value>(primitiveSymbol, (lambda<value(list<value>&)>)f);
+ return mklist<value>(primitiveSymbol, (lambda<value(const list<value>&)>)f);
}
const list<value> primitiveProcedureNames() {
@@ -176,11 +200,17 @@ const list<value> primitiveProcedureNames() {
l = cons<value>("list", l);
l = cons<value>("nul", l);
l = cons<value>("=", l);
+ l = cons<value>("equal?", l);
l = cons<value>("+", l);
l = cons<value>("-", l);
l = cons<value>("*", l);
l = cons<value>("/", l);
- l = cons<value>("equal?", l);
+ l = cons<value>("assoc", l);
+ l = cons<value>("cadr", l);
+ l = cons<value>("caddr", l);
+ l = cons<value>("cadddr", l);
+ l = cons<value>("cddr", l);
+ l = cons<value>("cdddr", l);
l = cons<value>("display", l);
l = cons<value>("log", l);
l = cons<value>("uuid", l);
@@ -194,11 +224,17 @@ const list<value> primitiveProcedureObjects() {
l = cons(primitiveProcedure(listProc), l);
l = cons(primitiveProcedure(nulProc), l);
l = cons(primitiveProcedure(equalProc), l);
+ l = cons(primitiveProcedure(equalProc), l);
l = cons(primitiveProcedure(addProc), l);
l = cons(primitiveProcedure(subProc), l);
l = cons(primitiveProcedure(mulProc), l);
l = cons(primitiveProcedure(divProc), l);
- l = cons(primitiveProcedure(equalProc), l);
+ l = cons(primitiveProcedure(assocProc), l);
+ l = cons(primitiveProcedure(cadrProc), l);
+ l = cons(primitiveProcedure(caddrProc), l);
+ l = cons(primitiveProcedure(cadddrProc), l);
+ l = cons(primitiveProcedure(cddrProc), l);
+ l = cons(primitiveProcedure(cdddrProc), l);
l = cons(primitiveProcedure(displayProc), l);
l = cons(primitiveProcedure(logProc), l);
l = cons(primitiveProcedure(uuidProc), l);
diff --git a/sca-cpp/trunk/modules/http/http-test b/sca-cpp/trunk/modules/http/http-test
index 0aaaec48df..bf6230aec8 100755
--- a/sca-cpp/trunk/modules/http/http-test
+++ b/sca-cpp/trunk/modules/http/http-test
@@ -20,7 +20,7 @@
# Setup
./httpd-conf tmp 8090 htdocs
apachectl -k start -d `pwd`/tmp
-sleep 1
+sleep 2
# Test
./curl-test
@@ -28,5 +28,5 @@ rc=$?
# Cleanup
apachectl -k stop -d `pwd`/tmp
-sleep 1
+sleep 2
return $rc
diff --git a/sca-cpp/trunk/modules/http/httpd-conf b/sca-cpp/trunk/modules/http/httpd-conf
index b00ee06ed3..686bfbcec7 100755
--- a/sca-cpp/trunk/modules/http/httpd-conf
+++ b/sca-cpp/trunk/modules/http/httpd-conf
@@ -27,7 +27,7 @@ mkdir -p $root
mkdir -p $root/logs
mkdir -p $root/conf
cat >$root/conf/httpd.conf <<EOF
-ServerName 127.0.0.1
+ServerName http://127.0.0.1:$port
Listen $port
DocumentRoot $htdocs
TypesConfig $here/conf/mime.types
diff --git a/sca-cpp/trunk/modules/http/httpd-test b/sca-cpp/trunk/modules/http/httpd-test
index 8e1d681d84..762c4c7f6b 100755
--- a/sca-cpp/trunk/modules/http/httpd-test
+++ b/sca-cpp/trunk/modules/http/httpd-test
@@ -22,7 +22,7 @@ echo "Testing..."
# Setup
./httpd-conf tmp 8090 htdocs
apachectl -k start -d `pwd`/tmp
-sleep 1
+sleep 2
# Test HTTP GET
curl http://localhost:8090/index.html 2>/dev/null >tmp/index.html
@@ -31,7 +31,7 @@ rc=$?
# Cleanup
apachectl -k stop -d `pwd`/tmp
-sleep 1
+sleep 2
if [ "$rc" = "0" ]; then
echo "OK"
fi
diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp
index 05b959f1d2..890fee8f01 100644
--- a/sca-cpp/trunk/modules/http/httpd.hpp
+++ b/sca-cpp/trunk/modules/http/httpd.hpp
@@ -69,6 +69,11 @@ template<typename C> const C& serverConf(const request_rec* r, const module* mod
return *(C*)ap_get_module_config(r->server->module_config, mod);
}
+template<typename C> C& serverConf(const cmd_parms *cmd, const module* mod) {
+ return *(C*)ap_get_module_config(cmd->server->module_config, mod);
+}
+
+
/**
* Returns a directory-scoped module configuration.
*/
@@ -88,7 +93,9 @@ template<typename C> C& dirConf(const request_rec* r, const module* mod) {
const list<std::string> pathTokens(const char* p) {
if (p == NULL || p[0] == '\0')
return list<std::string>();
- return tokenize("/", p + 1);
+ if (p[0] == '/')
+ return tokenize("/", p + 1);
+ return tokenize("/", p);
}
const list<value> pathValues(const list<std::string>& l) {
@@ -107,7 +114,7 @@ const list<value> path(const char* p) {
const std::string path(const list<value>& p) {
if (isNil(p))
return "";
- return "/" + car(p) + path(cdr(p));
+ return std::string("/") + std::string(car(p)) + path(cdr(p));
}
/**
@@ -141,11 +148,11 @@ const bool debugRequest(request_rec* r, const std::string& msg) {
std::cerr << " content type: " << contentType(r) << std::endl;
std::cerr << " content encoding: " << optional(r->content_encoding) << std::endl;
apr_table_do(debugHeader, r, r->headers_in, NULL);
- std::cerr << " uri: " << optional(r->unparsed_uri) << std::endl;
- std::cerr << " path: " << optional(r->uri) << std::endl;
+ std::cerr << " unparsed uri: " << optional(r->unparsed_uri) << std::endl;
+ std::cerr << " uri: " << optional(r->uri) << std::endl;
std::cerr << " path info: " << optional(r->path_info) << std::endl;
std::cerr << " filename: " << optional(r->filename) << std::endl;
- std::cerr << " path tokens: " << pathTokens(r->uri) << std::endl;
+ std::cerr << " uri tokens: " << pathTokens(r->uri) << std::endl;
std::cerr << " args: " << optional(r->args) << std::endl;
return true;
}
@@ -159,6 +166,15 @@ const bool debugRequest(request_rec* r, const std::string& msg) {
#endif
/**
+ * Return the remaining part of a uri after the given path (aka the path info.)
+ */
+const list<value> pathInfo(const list<value>& uri, const list<value>& path) {
+ if (isNil(path))
+ return uri;
+ return pathInfo(cdr(uri), cdr(path));
+}
+
+/**
* Returns a list of key value pairs from the args in a query string.
*/
const list<value> queryArg(const std::string& s) {
diff --git a/sca-cpp/trunk/modules/scdl/scdl-test.cpp b/sca-cpp/trunk/modules/scdl/scdl-test.cpp
index c3da1013a8..582d1ee073 100644
--- a/sca-cpp/trunk/modules/scdl/scdl-test.cpp
+++ b/sca-cpp/trunk/modules/scdl/scdl-test.cpp
@@ -28,7 +28,9 @@
#include <sstream>
#include <fstream>
#include <string>
+#include "list.hpp"
#include "slist.hpp"
+#include "tree.hpp"
#include "scdl.hpp"
namespace tuscany {
@@ -53,6 +55,9 @@ bool testComponents() {
const value catalog = named(std::string("Catalog"), c);
assert(name(catalog) == std::string("Catalog"));
+
+ const list<value> t = mkbtree(sort(nameToElementAssoc(c)));
+ assert(assoctree<value>("Catalog", t) == mklist<value>("Catalog" , cadr(c)));
return true;
}
@@ -86,6 +91,9 @@ bool testReferences() {
const value binding = car(bindings(catalog));
assert(uri(binding) == value());
assert(bindingType(binding) == "t:binding.jsonrpc");
+
+ const list<value> t = mkbtree(sort(referenceToTargetAssoc(references(store))));
+ assert(assoctree<value>("shoppingCart", t) == mklist<value>(std::string("shoppingCart"), std::string("ShoppingCart/Cart")));
return true;
}
diff --git a/sca-cpp/trunk/modules/scdl/scdl.hpp b/sca-cpp/trunk/modules/scdl/scdl.hpp
index 4d84610fb0..9d4bf38b50 100644
--- a/sca-cpp/trunk/modules/scdl/scdl.hpp
+++ b/sca-cpp/trunk/modules/scdl/scdl.hpp
@@ -53,6 +53,16 @@ const value name(const value& l) {
}
/**
+ * Convert a list of elements to a name -> element assoc list.
+ */
+const list<value> nameToElementAssoc(const list<value>& l) {
+ if (isNil(l))
+ return l;
+ const value e(car(l));
+ return cons<value>(mklist<value>(name(e), e), nameToElementAssoc(cdr(l)));
+}
+
+/**
* Returns the scdl declaration with the given name.
*/
struct filterName {
@@ -107,17 +117,20 @@ const list<value> references(const value& l) {
}
/**
- * Returns a list of properties in a component.
+ * Returns the target of a reference.
*/
-const list<value> properties(const value& l) {
- return elementChildren("property", l);
+const value target(const value& l) {
+ return attributeValue("target", l);
}
/**
- * Returns the target of a reference.
+ * Convert a list of references to a reference name -> target assoc list.
*/
-const value target(const value& l) {
- return attributeValue("target", l);
+const list<value> referenceToTargetAssoc(const list<value>& r) {
+ if (isNil(r))
+ return r;
+ const value ref(car(r));
+ return cons<value>(mklist<value>(scdl::name(ref), scdl::target(ref)), referenceToTargetAssoc(cdr(r)));
}
/**
@@ -132,6 +145,13 @@ const list<value> bindings(const value& l) {
}
/**
+ * Returns a list of properties in a component.
+ */
+const list<value> properties(const value& l) {
+ return elementChildren("property", l);
+}
+
+/**
* Returns the type of an implementation.
*/
const value implementationType(const value& l) {
diff --git a/sca-cpp/trunk/modules/server/domain-test.composite b/sca-cpp/trunk/modules/server/domain-test.composite
index 48570e64d3..b39f66c30a 100644
--- a/sca-cpp/trunk/modules/server/domain-test.composite
+++ b/sca-cpp/trunk/modules/server/domain-test.composite
@@ -41,7 +41,7 @@
<service name="client">
<t:binding.http uri="client"/>
</service>
- <reference name="ref" target="test">
+ <reference name="ref" target="server-test">
<t:binding.http/>
</reference>
</component>
diff --git a/sca-cpp/trunk/modules/server/httpd-test b/sca-cpp/trunk/modules/server/httpd-test
index 2f50c9f3c3..7dccfbf112 100755
--- a/sca-cpp/trunk/modules/server/httpd-test
+++ b/sca-cpp/trunk/modules/server/httpd-test
@@ -24,16 +24,14 @@ echo "Testing..."
./server-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
-<Location /test>
-SetHandler mod_tuscany_eval
+<Location />
SCAContribution `pwd`/
SCAComposite domain-test.composite
-SCAComponent server-test
</Location>
EOF
apachectl -k start -d `pwd`/tmp
-sleep 1
+sleep 2
# Test HTTP GET
curl http://localhost:8090/index.html 2>/dev/null >tmp/index.html
@@ -73,7 +71,7 @@ fi
# Cleanup
apachectl -k stop -d `pwd`/tmp
-sleep 1
+sleep 2
if [ "$rc" = "0" ]; then
echo "OK"
fi
diff --git a/sca-cpp/trunk/modules/server/impl-test.cpp b/sca-cpp/trunk/modules/server/impl-test.cpp
index 217c6f5171..171a78f2d5 100644
--- a/sca-cpp/trunk/modules/server/impl-test.cpp
+++ b/sca-cpp/trunk/modules/server/impl-test.cpp
@@ -51,7 +51,7 @@ const failable<value, std::string> del(unused const list<value>& params) {
}
const failable<value, std::string> hello(const list<value>& params) {
- return value("hello " + std::string(car(params)));
+ return value(std::string("hello ") + std::string(car(params)));
}
}
@@ -59,17 +59,18 @@ const failable<value, std::string> hello(const list<value>& params) {
extern "C" {
-const tuscany::failable<tuscany::value, std::string> eval(const tuscany::value& func, const tuscany::list<tuscany::value>& params) {
+const tuscany::value eval(const tuscany::list<tuscany::value>& params) {
+ const tuscany::value func(car(params));
if (func == "get")
- return tuscany::server::get(params);
+ return tuscany::server::get(cdr(params));
if (func == "post")
- return tuscany::server::post(params);
+ return tuscany::server::post(cdr(params));
if (func == "put")
- return tuscany::server::put(params);
+ return tuscany::server::put(cdr(params));
if (func == "del")
- return tuscany::server::del(params);
+ return tuscany::server::del(cdr(params));
if (func == "hello")
- return tuscany::server::hello(params);
+ return tuscany::server::hello(cdr(params));
return tuscany::mkfailure<tuscany::value, std::string>(std::string("Function not supported: ") + std::string(func));
}
diff --git a/sca-cpp/trunk/modules/server/mod-cpp.hpp b/sca-cpp/trunk/modules/server/mod-cpp.hpp
index 99b69a0d9f..664e9d2e41 100644
--- a/sca-cpp/trunk/modules/server/mod-cpp.hpp
+++ b/sca-cpp/trunk/modules/server/mod-cpp.hpp
@@ -37,10 +37,8 @@
#include "debug.hpp"
#include "monad.hpp"
#include "dynlib.hpp"
-#include "cache.hpp"
#include "../eval/driver.hpp"
#include "../http/httpd.hpp"
-#include "mod-eval.hpp"
namespace tuscany {
namespace server {
@@ -52,14 +50,14 @@ namespace cpp {
*/
struct evalImplementation {
const lib ilib;
- const ilambda impl;
+ const lambda<value(const list<value>&)> impl;
const list<value> px;
- evalImplementation(const lib& ilib, const ilambda& impl, const list<value>& px) : ilib(ilib), impl(impl), px(px) {
+ evalImplementation(const lib& ilib, const lambda<value(const list<value>&)>& impl, const list<value>& px) : ilib(ilib), impl(impl), px(px) {
}
- const failable<value, std::string> operator()(const value& func, const list<value>& params) const {
- debug(cons<value>(func, params), "modeval::cpp::evalImplementation::input");
- const failable<value, std::string> val = impl(func, append(params, px));
- debug(content(val), "modeval::cpp::evalImplementation::result");
+ const value operator()(const list<value>& params) const {
+ debug(params, "modeval::cpp::evalImplementation::input");
+ const value val = impl(append(params, px));
+ debug(val, "modeval::cpp::evalImplementation::result");
return val;
}
};
@@ -67,22 +65,15 @@ struct evalImplementation {
/**
* Read a C++ component implementation.
*/
-const failable<ilambda, std::string> readLatestImplementation(const std::string path, const list<value>& px) {
- const failable<lib, std::string> ilib(dynlib(path));
+const failable<lambda<value(const list<value>&)>, std::string> readImplementation(const std::string path, const list<value>& px) {
+ const failable<lib, std::string> ilib(dynlib(path + dynlibExt));
if (!hasContent(ilib))
- return mkfailure<ilambda, std::string>(reason(ilib));
+ return mkfailure<lambda<value(const list<value>&)>, std::string>(reason(ilib));
- const failable<ilambda, std::string> impl(dynlambda<failable<value, std::string>(value, list<value>)>("eval", content(ilib)));
+ const failable<lambda<value(const list<value>&)>, std::string> impl(dynlambda<value(const list<value>&)>("eval", content(ilib)));
if (!hasContent(impl))
return impl;
- return ilambda(evalImplementation(content(ilib), content(impl), px));
-}
-
-const cached<failable<ilambda, std::string> > readImplementation(const std::string& path, const list<value>& px) {
- const lambda<failable<ilambda, std::string>(std::string, list<value>)> ri(readLatestImplementation);
- const lambda<unsigned long(std::string)> ft(latestFileTime);
- const std::string p(path + dynlibExt);
- return cached<failable<ilambda, std::string> >(curry(ri, p, px), curry(ft, p));
+ return lambda<value(const list<value>&)>(evalImplementation(content(ilib), content(impl), px));
}
}
diff --git a/sca-cpp/trunk/modules/server/mod-eval.cpp b/sca-cpp/trunk/modules/server/mod-eval.cpp
index aa0a6067a1..d8354c6a58 100644
--- a/sca-cpp/trunk/modules/server/mod-eval.cpp
+++ b/sca-cpp/trunk/modules/server/mod-eval.cpp
@@ -30,17 +30,16 @@
#include "function.hpp"
#include "list.hpp"
+#include "tree.hpp"
#include "slist.hpp"
#include "value.hpp"
#include "element.hpp"
#include "monad.hpp"
-#include "cache.hpp"
#include "../atom/atom.hpp"
#include "../json/json.hpp"
#include "../scdl/scdl.hpp"
#include "../http/curl.hpp"
#include "../http/httpd.hpp"
-#include "mod-eval.hpp"
#include "mod-scm.hpp"
#include "mod-cpp.hpp"
@@ -57,41 +56,41 @@ namespace modeval {
*/
class ServerConf {
public:
- ServerConf(server_rec* s) : s(s), home(""), wiringHost("") {
+ ServerConf(server_rec* s) : s(s), home(""), wiringServerName("") {
}
const server_rec* s;
std::string home;
- std::string wiringHost;
+ std::string wiringServerName;
};
/**
- * Port number used for wiring requests. Set it to zero to use the current
- * server port number, set it to a port number to direct wiring requests
- * to that port, for debugging or tracing for example.
- */
-int debugWiringPort = 0;
-
-/**
* Directory configuration.
*/
class DirConf {
public:
- DirConf(char* dirspec) : dirspec(dirspec), contributionPath(""), compositeName(""), componentName(""), implementationPath("") {
+ DirConf(char* dirspec) : dirspec(dirspec), contributionPath(""), compositeName("") {
}
const char* dirspec;
std::string contributionPath;
std::string compositeName;
- std::string componentName;
- std::string implementationPath;
- cached<failable<value, std::string> > component;
- cached<failable<ilambda, std::string> > implementation;
+ list<value> implementations;
};
/**
+ * Convert a result represented as a content + failure pair to a
+ * failable monad.
+ */
+const failable<value, std::string> failableResult(const list<value>& v) {
+ if (isNil(cdr(v)))
+ return car(v);
+ return mkfailure<value, std::string>(cadr(v));
+}
+
+/**
* Handle an HTTP GET.
*/
-const failable<int, std::string> get(request_rec* r, const ilambda& impl) {
- debug(r->uri, "modeval::get::url");
+const failable<int, std::string> get(request_rec* r, const lambda<value(const list<value>&)>& impl) {
+ debug(r->uri, "modeval::get::uri");
// Inspect the query string
const list<list<value> > args = httpd::queryArgs(r);
@@ -104,10 +103,9 @@ const failable<int, std::string> get(request_rec* r, const ilambda& impl) {
// Extract the request id, method and params
const value id = cadr(ia);
const value func = std::string(cadr(ma)).c_str();
- const list<value> params = httpd::queryParams(args);
// Apply the requested function
- const failable<value, std::string> val = impl(func, params);
+ const failable<value, std::string> val = failableResult(impl(cons(func, httpd::queryParams(args))));
if (!hasContent(val))
return mkfailure<int, std::string>(reason(val));
@@ -117,16 +115,16 @@ const failable<int, std::string> get(request_rec* r, const ilambda& impl) {
}
// Evaluate an ATOM GET request and return an ATOM feed
- const list<value> id(httpd::path(r->path_info));
- if (isNil(id)) {
- const failable<value, std::string> val = impl("getall", list<value>());
+ const list<value> path(httpd::path(r->uri));
+ if (isNil(cddr(path))) {
+ const failable<value, std::string> val = failableResult(impl(cons<value>("getall", list<value>())));
if (!hasContent(val))
return mkfailure<int, std::string>(reason(val));
return httpd::writeResult(atom::writeATOMFeed(atom::feedValuesToElements(content(val))), "application/atom+xml;type=feed", r);
}
// Evaluate an ATOM GET and return an ATOM entry
- const failable<value, std::string> val = impl("get", mklist<value>(car(id)));
+ const failable<value, std::string> val = failableResult(impl(cons<value>("get", mklist<value>(caddr(path)))));
if (!hasContent(val))
return mkfailure<int, std::string>(reason(val));
return httpd::writeResult(atom::writeATOMEntry(atom::entryValuesToElements(content(val))), "application/atom+xml;type=entry", r);
@@ -135,7 +133,7 @@ const failable<int, std::string> get(request_rec* r, const ilambda& impl) {
/**
* Handle an HTTP POST.
*/
-const failable<int, std::string> post(request_rec* r, const ilambda& impl) {
+const failable<int, std::string> post(request_rec* r, const lambda<value(const list<value>&)>& impl) {
const list<std::string> ls = httpd::read(r);
debug(r->uri, "modeval::post::url");
debug(ls, "modeval::post::input");
@@ -153,7 +151,7 @@ const failable<int, std::string> post(request_rec* r, const ilambda& impl) {
const list<value> params = (list<value>)cadr(assoc(value("params"), args));
// Evaluate the request expression
- const failable<value, std::string> val = impl(func, params);
+ const failable<value, std::string> val = failableResult(impl(cons<value>(func, params)));
if (!hasContent(val))
return mkfailure<int, std::string>(reason(val));
@@ -166,7 +164,7 @@ const failable<int, std::string> post(request_rec* r, const ilambda& impl) {
// Evaluate the request expression
const value entry = atom::entryValue(content(atom::readEntry(ls)));
- const failable<value, std::string> val = impl("post", mklist<value>(entry));
+ const failable<value, std::string> val = failableResult(impl(cons<value>("post", mklist<value>(entry))));
if (!hasContent(val))
return mkfailure<int, std::string>(reason(val));
@@ -182,15 +180,15 @@ const failable<int, std::string> post(request_rec* r, const ilambda& impl) {
/**
* Handle an HTTP PUT.
*/
-const failable<int, std::string> put(request_rec* r, const ilambda& impl) {
+const failable<int, std::string> put(request_rec* r, const lambda<value(const list<value>&)>& impl) {
const list<std::string> ls = httpd::read(r);
debug(r->uri, "modeval::put::url");
debug(ls, "modeval::put::input");
// Evaluate an ATOM PUT request
- const list<value> id(httpd::path(r->path_info));
+ const list<value> path(httpd::path(r->uri));
const value entry = atom::entryValue(content(atom::readEntry(ls)));
- const failable<value, std::string> val = impl("put", mklist<value>(car(id), entry));
+ const failable<value, std::string> val = failableResult(impl(cons<value>("put", mklist<value>(caddr(path), entry))));
if (!hasContent(val))
return mkfailure<int, std::string>(reason(val));
if (val == value(false))
@@ -201,12 +199,12 @@ const failable<int, std::string> put(request_rec* r, const ilambda& impl) {
/**
* Handle an HTTP DELETE.
*/
-const failable<int, std::string> del(request_rec* r, const ilambda& impl) {
+const failable<int, std::string> del(request_rec* r, const lambda<value(const list<value>&)>& impl) {
debug(r->uri, "modeval::delete::url");
// Evaluate an ATOM delete request
- const list<value> id(httpd::path(r->path_info));
- const failable<value, std::string> val = impl("delete", mklist<value>(car(id)));
+ const list<value> path(httpd::path(r->uri));
+ const failable<value, std::string> val = failableResult(impl(cons<value>("delete", mklist<value>(caddr(path)))));
if (!hasContent(val))
return mkfailure<int, std::string>(reason(val));
if (val == value(false))
@@ -215,53 +213,13 @@ const failable<int, std::string> del(request_rec* r, const ilambda& impl) {
}
/**
- * Read the SCDL configuration of a component.
- */
-const failable<value, std::string> readComponent(const std::string& path, const std::string& name) {
-
- // Read composite
- std::ifstream is(path);
- if (is.fail() || is.bad())
- return mkfailure<value, std::string>("Could not read composite: " + path);
-
- // Return the component
- const list<value> c = scdl::components(readXML(streamList(is)));
- const value comp = scdl::named(name, c);
- if (isNil(comp))
- return mkfailure<value, std::string>("Could not find component: " + name);
- return comp;
-}
-
-const cached<failable<value, std::string> > component(DirConf* conf) {
- const std::string path(conf->contributionPath + conf->compositeName);
- const lambda<failable<value, std::string>(std::string, std::string)> rc(readComponent);
- const lambda<unsigned long(std::string)> ft(latestFileTime);
- return cached<failable<value, std::string> >(curry(rc, path, conf->componentName), curry(ft, path));
-}
-
-/**
- * Convert a list of component references to a list of HTTP proxy lambdas.
- */
-const value mkproxy(const value& ref, const std::string& base, const http::CURLSession& ch) {
- return lambda<value(list<value>&)>(http::proxy(base + std::string(scdl::name(ref)), ch));
-}
-
-const list<value> proxies(const list<value>& refs, const std::string& base, const http::CURLSession& ch) {
- if (isNil(refs))
- return refs;
- return cons(mkproxy(car(refs), base, ch), proxies(cdr(refs), base, ch));
-}
-
-/**
- * Returns the component implementation with the given implementation type and path.
- * For now only Scheme and C++ implementations are supported.
+ * Translate a component request.
*/
-const cached<failable<ilambda, std::string> > implementation(const std::string& itype, const std::string& path, const list<value>& px) {
- if (itype.find(".scheme") != std::string::npos)
- return latest(scm::readImplementation(path, px));
- if (itype.find(".cpp") != std::string::npos)
- return latest(cpp::readImplementation(path, px));
- return cached<failable<ilambda, std::string> >();
+int translate(request_rec *r) {
+ if (strncmp(r->uri, "/components/", 12) != 0)
+ return DECLINED;
+ r->handler = "mod_tuscany_eval";
+ return OK;
}
/**
@@ -277,80 +235,137 @@ int handler(request_rec *r) {
if(rc != OK)
return rc;
- // Retrieve the latest component configuration
- DirConf& conf = httpd::dirConf<DirConf>(r, &mod_tuscany_eval);
- conf.component = latest(conf.component);
- const failable<value, std::string> comp(content(conf.component));
- if (!hasContent(comp))
- return HTTP_NOT_FOUND;
-
- // Retrieve the latest implementation
- const value ielement= scdl::implementation(content(comp));
- const std::string path = conf.contributionPath + std::string(scdl::uri(ielement));
- if (path != conf.implementationPath) {
-
- // Convert component references to configured proxy lambdas
- const ServerConf& sconf = httpd::serverConf<ServerConf>(r, &mod_tuscany_eval);
- std::ostringstream base;
- if (sconf.wiringHost == "")
- base << "http://localhost:" << ap_get_server_port(r) << "/references/" << std::string(scdl::name(content(comp))) << "/";
- else
- base << "http://" << sconf.wiringHost << "/references/" << std::string(scdl::name(content(comp))) << "/";
- http::CURLSession ch;
- const list<value> px(proxies(scdl::references(content(comp)), base.str(), ch));
-
- conf.implementation = implementation(elementName(ielement), path, px);
- conf.implementationPath = path;
- }
- else
- conf.implementation = latest(conf.implementation);
- const failable<ilambda, std::string> impl(content(conf.implementation));
- if (!hasContent(impl))
+ // Get the component implementation lambda
+ DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_eval);
+ const list<value> path(httpd::path(r->uri));
+ const list<value> impl(assoctree<value>(cadr(path), dc.implementations));
+ if (isNil(impl))
return HTTP_NOT_FOUND;
// Handle HTTP method
+ const lambda<value(const list<value>&)> l(cadr<value>(impl));
if (r->header_only)
return OK;
if(r->method_number == M_GET)
- return httpd::reportStatus(get(r, content(impl)));
+ return httpd::reportStatus(get(r, l));
if(r->method_number == M_POST)
- return httpd::reportStatus(post(r, content(impl)));
+ return httpd::reportStatus(post(r, l));
if(r->method_number == M_PUT)
- return httpd::reportStatus(put(r, content(impl)));
+ return httpd::reportStatus(put(r, l));
if(r->method_number == M_DELETE)
- return httpd::reportStatus(del(r, content(impl)));
+ return httpd::reportStatus(del(r, l));
return HTTP_NOT_IMPLEMENTED;
}
/**
- * Configuration commands.
+ * Convert a list of component references to a list of HTTP proxy lambdas.
*/
-const char *confHome(cmd_parms *cmd, unused void *dummy, const char *arg) {
- ServerConf *c = (ServerConf*)ap_get_module_config(cmd->server->module_config, &mod_tuscany_eval);
- c->home = arg;
- return NULL;
+const value mkproxy(const value& ref, const std::string& base) {
+ return lambda<value(const list<value>&)>(http::proxy(base + std::string(scdl::name(ref))));
+}
+
+const list<value> proxies(const list<value>& refs, const std::string& base) {
+ if (isNil(refs))
+ return refs;
+ return cons(mkproxy(car(refs), base), proxies(cdr(refs), base));
+}
+
+/**
+ * Return a configured component implementation.
+ * For now only Scheme and C++ implementations are supported.
+ */
+const failable<lambda<value(const list<value>&)>, std::string> readImplementation(const std::string& itype, const std::string& path, const list<value>& px) {
+ if (itype.find(".scheme") != std::string::npos)
+ return scm::readImplementation(path, px);
+ if (itype.find(".cpp") != std::string::npos)
+ return cpp::readImplementation(path, px);
+ return mkfailure<lambda<value(const list<value>&)>, std::string>("Unsupported implementation type: " + itype);
+}
+
+const value confImplementation(DirConf& dc, ServerConf& sc, server_rec& server, const value& comp) {
+ const value impl = scdl::implementation(comp);
+ const std::string path = dc.contributionPath + std::string(scdl::uri(impl));
+
+ // Convert component references to configured proxy lambdas
+ std::ostringstream base;
+ if (sc.wiringServerName == "")
+ base << (server.server_scheme == NULL? "http" : server.server_scheme)
+ << "://" << (server.server_hostname == NULL? "localhost" : server.server_hostname)
+ << ":" << (server.port == 0? 80 : server.port)
+ << "/references/" << std::string(scdl::name(comp)) << "/";
+ else
+ base << sc.wiringServerName << "/references/" << std::string(scdl::name(comp)) << "/";
+ const list<value> px(proxies(scdl::references(comp), base.str()));
+
+ // Read and configure the implementation
+ const failable<lambda<value(const list<value>&)>, std::string> cimpl(readImplementation(elementName(impl), path, px));
+ if (!hasContent(cimpl))
+ return reason(cimpl);
+ return content(cimpl);
+}
+
+/**
+ * Return a tree of component-name + configured-implementation pairs.
+ */
+const list<value> componentToImplementationAssoc(DirConf& dc, ServerConf& sc, server_rec& server, const list<value>& c) {
+ if (isNil(c))
+ return c;
+ return cons<value>(mklist<value>(scdl::name(car(c)), confImplementation(dc, sc, server, car(c))), componentToImplementationAssoc(dc, sc, server, cdr(c)));
+}
+
+const list<value> componentToImplementationTree(DirConf& dc, ServerConf& sc, server_rec& server, const list<value>& c) {
+ return mkbtree(sort(componentToImplementationAssoc(dc, sc, server, c)));
+}
+
+/**
+ * Read the components declared in a composite.
+ */
+const failable<list<value>, std::string> readComponents(const std::string& path) {
+ std::ifstream is(path);
+ if (is.fail() || is.bad())
+ return mkfailure<list<value>, std::string>("Could not read composite: " + path);
+ return scdl::components(readXML(streamList(is)));
}
-const char *confWiringHost(cmd_parms *cmd, unused void *dummy, const char *arg) {
- ServerConf *c = (ServerConf*)ap_get_module_config(cmd->server->module_config, &mod_tuscany_eval);
- c->wiringHost = arg;
+
+/**
+ * Configure the components declared in the deployed composite.
+ */
+const bool confComponents(DirConf& dc, ServerConf& sc, server_rec& server) {
+ if (dc.contributionPath == "" || dc.compositeName == "")
+ return true;
+ const failable<list<value>, std::string> comps = readComponents(dc.contributionPath + dc.compositeName);
+ if (!hasContent(comps))
+ return true;
+ dc.implementations = componentToImplementationTree(dc, sc, server, content(comps));
+ debug(dc.implementations, "modeval::confComponents::implementations");
+ return true;
+}
+
+/**
+ * Configuration commands.
+ */
+const char *confHome(cmd_parms *cmd, unused void *c, const char *arg) {
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
+ sc.home = arg;
return NULL;
}
-const char *confContribution(unused cmd_parms *cmd, void *c, const char *arg) {
- DirConf* conf = (DirConf*)c;
- conf->contributionPath = arg;
- conf->component = component(conf);
+const char *confWiringServerName(cmd_parms *cmd, unused void *c, const char *arg) {
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
+ sc.wiringServerName = arg;
return NULL;
}
-const char *confComposite(unused cmd_parms *cmd, void *c, const char *arg) {
- DirConf* conf = (DirConf*)c;
- conf->compositeName = arg;
- conf->component = component(conf);
+const char *confContribution(cmd_parms *cmd, void *c, const char *arg) {
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
+ DirConf& dc = *(DirConf*)c;
+ dc.contributionPath = arg;
+ confComponents(dc, sc, *cmd->server);
return NULL;
}
-const char *confComponent(unused cmd_parms *cmd, void *c, const char *arg) {
- DirConf* conf = (DirConf*)c;
- conf->componentName = arg;
- conf->component = component(conf);
+const char *confComposite(cmd_parms *cmd, void *c, const char *arg) {
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval);
+ DirConf& dc = *(DirConf*)c;
+ dc.compositeName = arg;
+ confComponents(dc, sc, *cmd->server);
return NULL;
}
@@ -359,19 +374,18 @@ const char *confComponent(unused cmd_parms *cmd, void *c, const char *arg) {
*/
const command_rec commands[] = {
AP_INIT_TAKE1("TuscanyHome", (const char*(*)())confHome, NULL, RSRC_CONF, "Tuscany home directory"),
- AP_INIT_TAKE1("SCAWiringHost", (const char*(*)())confWiringHost, NULL, RSRC_CONF, "SCA wiring host"),
+ AP_INIT_TAKE1("SCAWiringServerName", (const char*(*)())confWiringServerName, NULL, RSRC_CONF, "SCA wiring server name"),
AP_INIT_TAKE1("SCAContribution", (const char*(*)())confContribution, NULL, ACCESS_CONF, "SCA contribution location"),
AP_INIT_TAKE1("SCAComposite", (const char*(*)())confComposite, NULL, ACCESS_CONF, "SCA composite location"),
- AP_INIT_TAKE1("SCAComponent", (const char*(*)())confComponent, NULL, ACCESS_CONF, "SCA component name"),
{NULL, NULL, NULL, 0, NO_ARGS, NULL}
};
int postConfig(unused apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, unused server_rec *s) {
- return OK;
+ return OK;
}
void childInit(unused apr_pool_t* p, server_rec* svr_rec) {
- ServerConf *c = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany_eval);
+ ServerConf* c = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany_eval);
if(c == NULL) {
std::cerr << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << std::endl;
exit(APEXIT_CHILDFATAL);
@@ -382,6 +396,7 @@ void registerHooks(unused apr_pool_t *p) {
ap_hook_post_config(postConfig, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_child_init(childInit, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_handler(handler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_translate_name(translate, NULL, NULL, APR_HOOK_FIRST);
}
}
diff --git a/sca-cpp/trunk/modules/server/mod-eval.hpp b/sca-cpp/trunk/modules/server/mod-eval.hpp
deleted file mode 100644
index a350538956..0000000000
--- a/sca-cpp/trunk/modules/server/mod-eval.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-/* $Rev$ $Date$ */
-
-#ifndef tuscany_modeval_hpp
-#define tuscany_modeval_hpp
-
-/**
- * Defines the signature of component implementation lambdas
- * expected by mod-eval.
- */
-
-#include <string>
-
-#include "function.hpp"
-#include "list.hpp"
-#include "value.hpp"
-#include "monad.hpp"
-
-namespace tuscany {
-namespace server {
-namespace modeval {
-
-/**
- * Represents a component implementation lambda function.
- */
-typedef lambda<failable<value, std::string>(value, list<value>)> ilambda;
-
-}
-}
-}
-
-#endif /* tuscany_modeval_hpp */
diff --git a/sca-cpp/trunk/modules/server/mod-scm.hpp b/sca-cpp/trunk/modules/server/mod-scm.hpp
index 586b90190f..c454c6a216 100644
--- a/sca-cpp/trunk/modules/server/mod-scm.hpp
+++ b/sca-cpp/trunk/modules/server/mod-scm.hpp
@@ -36,11 +36,9 @@
#include "value.hpp"
#include "debug.hpp"
#include "monad.hpp"
-#include "cache.hpp"
#include "../eval/primitive.hpp"
#include "../eval/driver.hpp"
#include "../http/httpd.hpp"
-#include "mod-eval.hpp"
namespace tuscany {
namespace server {
@@ -64,36 +62,30 @@ struct evalImplementation {
const list<value> px;
evalImplementation(const value& impl, const list<value>& px) : impl(impl), px(eval::quotedParameters(primitiveProcedures(px))) {
}
- const failable<value, std::string> operator()(const value& func, const list<value>& params) const {
- const value expr = cons<value>(func, append(eval::quotedParameters(params), px));
+ const value operator()(const list<value>& params) const {
+ const value expr = cons<value>(car(params), append(eval::quotedParameters(cdr(params)), px));
debug(expr, "modeval::scm::evalImplementation::input");
gc_pool pool;
eval::Env globalEnv = eval::setupEnvironment(pool);
const value val = eval::evalScript(expr, impl, globalEnv, pool);
debug(val, "modeval::scm::evalImplementation::result");
if (isNil(val))
- return mkfailure<value, std::string>("Could not evaluate expression");
- return val;
+ return mklist<value>(value(), std::string("Could not evaluate expression"));
+ return mklist<value>(val);
}
};
/**
* Read a script component implementation.
*/
-const failable<ilambda, std::string> readLatestImplementation(const std::string path, const list<value>& px) {
+const failable<lambda<value(const list<value>&)>, std::string> readImplementation(const std::string path, const list<value>& px) {
std::ifstream is(path.c_str(), std::ios_base::in);
if (is.fail() || is.bad())
- return mkfailure<ilambda, std::string>("Could not read implementation: " + path);
+ return mkfailure<lambda<value(const list<value>&)>, std::string>("Could not read implementation: " + path);
const value impl = eval::readScript(is);
if (isNil(impl))
- return mkfailure<ilambda, std::string>("Could not read implementation: " + path);
- return ilambda(evalImplementation(impl, px));
-}
-
-const cached<failable<ilambda, std::string> > readImplementation(const std::string& path, const list<value>& px) {
- const lambda<failable<ilambda, std::string>(std::string, list<value>)> ri(readLatestImplementation);
- const lambda<unsigned long(std::string)> ft(latestFileTime);
- return cached<failable<ilambda, std::string> >(curry(ri, path, px), curry(ft, path));
+ return mkfailure<lambda<value(const list<value>&)>, std::string>("Could not read implementation: " + path);
+ return lambda<value(const list<value>&)>(evalImplementation(impl, px));
}
}
diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp
index 0d5262d730..1bb5d1a687 100644
--- a/sca-cpp/trunk/modules/server/mod-wiring.cpp
+++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp
@@ -20,7 +20,8 @@
/* $Rev$ $Date$ */
/**
- * HTTPD module used to wire component references.
+ * HTTPD module used to wire component references and route requests to
+ * target service components.
*/
#include <sys/stat.h>
@@ -32,10 +33,10 @@
#include "list.hpp"
#include "slist.hpp"
+#include "tree.hpp"
#include "value.hpp"
#include "debug.hpp"
#include "monad.hpp"
-#include "cache.hpp"
#include "../scdl/scdl.hpp"
#include "../http/httpd.hpp"
@@ -52,11 +53,11 @@ namespace modwiring {
*/
class ServerConf {
public:
- ServerConf(server_rec* s) : s(s), home(""), wiringHost("") {
+ ServerConf(server_rec* s) : s(s), home(""), wiringServerName("") {
}
const server_rec* s;
std::string home;
- std::string wiringHost;
+ std::string wiringServerName;
};
/**
@@ -74,27 +75,11 @@ public:
const char* dirspec;
std::string contributionPath;
std::string compositeName;
- cached<failable<list<value>, std::string> > components;
+ list<value> references;
+ list<value> services;
};
/**
- * Read the SCDL configuration of the deployed components.
- */
-const failable<list<value>, std::string> readComponents(const std::string& path) {
- std::ifstream is(path);
- if (is.fail() || is.bad())
- return mkfailure<list<value>, std::string>("Could not read composite: " + path);
- return scdl::components(readXML(streamList(is)));
-}
-
-const cached<failable<list<value>, std::string> > components(DirConf* conf) {
- const std::string path(conf->contributionPath + conf->compositeName);
- const lambda<failable<list<value>, std::string>(std::string)> rc(readComponents);
- const lambda<unsigned long(std::string)> ft(latestFileTime);
- return cached<failable<list<value>, std::string> >(curry(rc, path), curry(ft, path));
-}
-
-/**
* Returns true if a URI is absolute.
*/
const bool isAbsolute(const std::string& uri) {
@@ -102,34 +87,29 @@ const bool isAbsolute(const std::string& uri) {
}
/**
- * Translate an HTTP request URI. Wire a URI in the form /references/component-name/reference-name
- * to the target of the reference.
+ * Route a /references/component-name/reference-name request,
+ * to the target of the component reference.
*/
-int translate(request_rec *r) {
- if (strncmp(r->uri, "/references/", 12) != 0)
- return DECLINED;
- httpdDebugRequest(r, "modwiring::translate::input");
- debug(r->uri, "modwiring::translate::uri");
+int translateReference(request_rec *r) {
+ httpdDebugRequest(r, "modwiring::translateReference::input");
+ debug(r->uri, "modwiring::translateReference::uri");
- // Find the requested component, reference and its target configuration
- DirConf& conf = httpd::dirConf<DirConf>(r, &mod_tuscany_wiring);
- conf.components = latest(conf.components);
- const failable<list<value>, std::string> comps(content(conf.components));
- if (!hasContent(comps))
- return HTTP_INTERNAL_SERVER_ERROR;
+ // Find the requested component
+ DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_wiring);
const list<value> rpath(httpd::path(r->uri));
- const value comp(scdl::named(cadr(rpath), list<value>(content(comps))));
+ const list<value> comp(assoctree(cadr(rpath), dc.references));
if (isNil(comp))
return HTTP_NOT_FOUND;
- const value ref(scdl::named(caddr(rpath), scdl::references(comp)));
+
+ // Find the requested reference and target configuration
+ const list<value> ref(assoctree<value>(caddr(rpath), cadr(comp)));
if (isNil(ref))
return HTTP_NOT_FOUND;
- const std::string target(scdl::target(ref));
+ const std::string target(cadr(ref));
+ debug(target, "modwiring::translateReference::target");
- // Absolute target URI
+ // Route to an absolute target URI using mod_proxy or an HTTP client redirect
if (isAbsolute(target)) {
-
- // Wire using mod_proxy
if (useModProxy) {
r->filename = apr_pstrdup(r->pool, std::string("proxy:" + target).c_str());
r->proxyreq = PROXYREQ_REVERSE;
@@ -137,21 +117,85 @@ int translate(request_rec *r) {
return OK;
}
- // Wire using an HTTP client redirect
r->status = HTTP_MOVED_TEMPORARILY;
apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, target.c_str()));
r->handler = "mod_tuscany_wiring";
return OK;
-
}
- // Local internal redirect
- r->filename = apr_pstrdup(r->pool, std::string("/redirect:/" + target).c_str());
+ // Route to a relative target URI using a local internal redirect
+ r->filename = apr_pstrdup(r->pool, std::string("/redirect:/components/" + target).c_str());
r->handler = "mod_tuscany_wiring";
return OK;
}
/**
+ * Find a leaf matching a request path in a tree of URI paths.
+ */
+const int matchPath(const list<value>& k, const list<value>& p) {
+ if (isNil(p))
+ return true;
+ if (isNil(k))
+ return false;
+ if (car(k) != car(p))
+ return false;
+ return matchPath(cdr(k), cdr(p));
+}
+
+const list<value> assocPath(const value& k, const list<value>& tree) {
+ if (isNil(tree))
+ return tree;
+ if (matchPath(k, car<value>(car(tree))))
+ return car(tree);
+ if (k < car<value>(car(tree)))
+ return assocPath(k, cadr(tree));
+ return assocPath(k, caddr(tree));
+}
+
+/**
+ * Route a service request to the component providing the requested service.
+ */
+int translateService(request_rec *r) {
+ httpdDebugRequest(r, "modwiring::translateService::input");
+ debug(r->uri, "modwiring::translateService::uri");
+
+ // Find the requested component
+ DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_wiring);
+ const list<value> path(httpd::path(r->uri));
+ const list<value> svc(assocPath(path, dc.services));
+ if (isNil(svc))
+ return DECLINED;
+ debug(svc, "modwiring::translateService::service");
+
+ // Build a component-name + path-info URI
+ const list<value> target(cons<value>(cadr(svc), httpd::pathInfo(path, car(svc))));
+ debug(target, "modwiring::translateService::target");
+
+ // Dispatch to the target component using a local internal redirect
+ const std::string redir(std::string("/redirect:/components") + httpd::path(target));
+ debug(redir, "modwiring::translateService::redirect");
+ r->filename = apr_pstrdup(r->pool, redir.c_str());
+ r->handler = "mod_tuscany_wiring";
+ return OK;
+}
+
+/**
+ * Translate an HTTP service or reference request and route it
+ * to the target component.
+ */
+int translate(request_rec *r) {
+ if (!strncmp(r->uri, "/components/", 12) != 0)
+ return DECLINED;
+
+ // Translate a component reference request
+ if (!strncmp(r->uri, "/references/", 12) != 0)
+ return translateReference(r);
+
+ // Translate a service request
+ return translateService(r);
+}
+
+/**
* Construct a redirect URI.
*/
const std::string redirect(const std::string& file, const std::string& pi) {
@@ -163,7 +207,7 @@ const std::string redirect(const std::string& file, const std::string& pi, const
}
/**
- * HTTP request internal redirect handler.
+ * HTTP request handler, redirect to a target component.
*/
int handler(request_rec *r) {
if(strcmp(r->handler, "mod_tuscany_wiring"))
@@ -175,6 +219,7 @@ int handler(request_rec *r) {
return DECLINED;
debug(r->uri, "modwiring::handler::uri");
debug(r->filename, "modwiring::handler::filename");
+ debug(r->path_info, "modwiring::handler::path info");
if (r->args == NULL) {
ap_internal_redirect(apr_pstrdup(r->pool, redirect(r->filename + 10, r->path_info).c_str()), r);
@@ -185,28 +230,109 @@ int handler(request_rec *r) {
}
/**
+ * Read the components declared in a composite.
+ */
+const failable<list<value>, std::string> readComponents(const std::string& path) {
+ std::ifstream is(path);
+ if (is.fail() || is.bad())
+ return mkfailure<list<value>, std::string>("Could not read composite: " + path);
+ return scdl::components(readXML(streamList(is)));
+}
+
+/**
+ * Return a tree of component-name + references pairs. The references are
+ * arranged in trees of reference-name + reference-target pairs.
+ */
+const list<value> componentReferenceToTargetTree(const value& c) {
+ return mklist<value>(scdl::name(c), mkbtree(sort(scdl::referenceToTargetAssoc(scdl::references(c)))));
+}
+
+const list<value> componentReferenceToTargetAssoc(const list<value>& c) {
+ if (isNil(c))
+ return c;
+ return cons<value>(componentReferenceToTargetTree(car(c)), componentReferenceToTargetAssoc(cdr(c)));
+}
+
+const list<value> componentReferenceToTargetTree(const list<value>& c) {
+ return mkbtree(sort(componentReferenceToTargetAssoc(c)));
+}
+
+/**
+ * Return a tree of service-URI-path + component-name pairs. Service-URI-paths are
+ * represented as lists of URI path fragments.
+ */
+const list<value> defaultBindingURI(const std::string& cn, const std::string& sn) {
+ return mklist<value>(cn, sn);
+}
+
+const list<value> bindingToComponentAssoc(const std::string& cn, const std::string& sn, const list<value>& b) {
+ if (isNil(b))
+ return b;
+ const value uri(scdl::uri(car(b)));
+ if (isNil(uri))
+ return cons<value>(mklist<value>(defaultBindingURI(cn, sn), cn), bindingToComponentAssoc(cn, sn, cdr(b)));
+ return cons<value>(mklist<value>(httpd::path(std::string(uri).c_str()), cn), bindingToComponentAssoc(cn, sn, cdr(b)));
+}
+
+const list<value> serviceToComponentAssoc(const std::string& cn, const list<value>& s) {
+ if (isNil(s))
+ return s;
+ const std::string sn(scdl::name(car(s)));
+ const list<value> btoc(bindingToComponentAssoc(cn, sn, scdl::bindings(car(s))));
+ if (isNil(btoc))
+ return cons<value>(mklist<value>(defaultBindingURI(cn, sn), cn), serviceToComponentAssoc(cn, cdr(s)));
+ return append<value>(btoc, serviceToComponentAssoc(cn, cdr(s)));
+}
+
+const list<value> uriToComponentAssoc(const list<value>& c) {
+ if (isNil(c))
+ return c;
+ return append<value>(serviceToComponentAssoc(scdl::name(car(c)), scdl::services(car(c))), uriToComponentAssoc(cdr(c)));
+}
+
+const list<value> uriToComponentTree(const list<value>& c) {
+ return mkbtree(sort(uriToComponentAssoc(c)));
+}
+
+/**
+ * Configure the components declared in the server's deployment composite.
+ */
+const bool confComponents(DirConf& dc) {
+ if (dc.contributionPath == "" || dc.compositeName == "")
+ return true;
+ const failable<list<value>, std::string> comps = readComponents(dc.contributionPath + dc.compositeName);
+ if (!hasContent(comps))
+ return true;
+ dc.references = componentReferenceToTargetTree(content(comps));
+ debug(dc.references, "modwiring::confComponents::references");
+ dc.services = uriToComponentTree(content(comps));
+ debug(dc.services, "modwiring::confComponents::services");
+ return true;
+}
+
+/**
* Configuration commands.
*/
-const char *confHome(cmd_parms *cmd, unused void *dummy, const char *arg) {
- ServerConf *c = (ServerConf*)ap_get_module_config(cmd->server->module_config, &mod_tuscany_wiring);
- c->home = arg;
+const char *confHome(cmd_parms *cmd, unused void *c, const char *arg) {
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_wiring);
+ sc.home = arg;
return NULL;
}
-const char *confWiringHost(cmd_parms *cmd, unused void *dummy, const char *arg) {
- ServerConf *c = (ServerConf*)ap_get_module_config(cmd->server->module_config, &mod_tuscany_wiring);
- c->wiringHost = arg;
+const char *confWiringServerName(cmd_parms *cmd, unused void *c, const char *arg) {
+ ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_wiring);
+ sc.wiringServerName = arg;
return NULL;
}
const char *confContribution(unused cmd_parms *cmd, void *c, const char *arg) {
- DirConf* conf = (DirConf*)c;
- conf->contributionPath = arg;
- conf->components = components(conf);
+ DirConf& dc = *(DirConf*)c;
+ dc.contributionPath = arg;
+ confComponents(dc);
return NULL;
}
const char *confComposite(unused cmd_parms *cmd, void *c, const char *arg) {
- DirConf* conf = (DirConf*)c;
- conf->compositeName = arg;
- conf->components = components(conf);
+ DirConf& dc = *(DirConf*)c;
+ dc.compositeName = arg;
+ confComponents(dc);
return NULL;
}
@@ -215,7 +341,7 @@ const char *confComposite(unused cmd_parms *cmd, void *c, const char *arg) {
*/
const command_rec commands[] = {
AP_INIT_TAKE1("TuscanyHome", (const char*(*)())confHome, NULL, RSRC_CONF, "Tuscany home directory"),
- AP_INIT_TAKE1("SCAWiringHost", (const char*(*)())confWiringHost, NULL, RSRC_CONF, "SCA wiring host"),
+ AP_INIT_TAKE1("SCAWiringServerName", (const char*(*)())confWiringServerName, NULL, ACCESS_CONF, "SCA wiring server name"),
AP_INIT_TAKE1("SCAContribution", (const char*(*)())confContribution, NULL, ACCESS_CONF, "SCA contribution location"),
AP_INIT_TAKE1("SCAComposite", (const char*(*)())confComposite, NULL, ACCESS_CONF, "SCA composite location"),
{NULL, NULL, NULL, 0, NO_ARGS, NULL}
diff --git a/sca-cpp/trunk/modules/server/server-test b/sca-cpp/trunk/modules/server/server-test
index 9c517f38b6..4c90711a30 100755
--- a/sca-cpp/trunk/modules/server/server-test
+++ b/sca-cpp/trunk/modules/server/server-test
@@ -22,23 +22,14 @@
./server-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
-<Location /test>
-SetHandler mod_tuscany_eval
+<Location />
SCAContribution `pwd`/
SCAComposite domain-test.composite
-SCAComponent server-test
-</Location>
-
-<Location /cpp>
-SetHandler mod_tuscany_eval
-SCAContribution `pwd`/
-SCAComposite domain-test.composite
-SCAComponent cpp-test
</Location>
EOF
apachectl -k start -d `pwd`/tmp
-sleep 1
+sleep 2
# Test
./client-test 2>/dev/null
@@ -46,5 +37,5 @@ rc=$?
# Cleanup
apachectl -k stop -d `pwd`/tmp
-sleep 1
+sleep 2
return $rc
diff --git a/sca-cpp/trunk/modules/server/wiring-test b/sca-cpp/trunk/modules/server/wiring-test
index 5f77d4c6f8..5b3a678f7f 100755
--- a/sca-cpp/trunk/modules/server/wiring-test
+++ b/sca-cpp/trunk/modules/server/wiring-test
@@ -24,29 +24,14 @@ echo "Testing..."
./server-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
-<Location /test>
-SetHandler mod_tuscany_eval
-SCAContribution `pwd`/
-SCAComposite domain-test.composite
-SCAComponent server-test
-</Location>
-
-<Location /client>
-SetHandler mod_tuscany_eval
-SCAContribution `pwd`/
-SCAComposite domain-test.composite
-SCAComponent client-test
-</Location>
-
-<Location /references>
-SetHandler mod_tuscany_wiring
+<Location />
SCAContribution `pwd`/
SCAComposite domain-test.composite
</Location>
EOF
apachectl -k start -d `pwd`/tmp
-sleep 1
+sleep 2
# Test HTTP GET
curl http://localhost:8090/index.html 2>/dev/null >tmp/index.html
@@ -86,7 +71,7 @@ fi
# Cleanup
apachectl -k stop -d `pwd`/tmp
-sleep 1
+sleep 2
if [ "$rc" = "0" ]; then
echo "OK"
fi
diff --git a/sca-cpp/trunk/test/store-script/htdocs/store.html b/sca-cpp/trunk/test/store-script/htdocs/store.html
index 0378b454cc..f8c6027abe 100644
--- a/sca-cpp/trunk/test/store-script/htdocs/store.html
+++ b/sca-cpp/trunk/test/store-script/htdocs/store.html
@@ -162,7 +162,7 @@
<br>
<input type="button" onClick="checkoutCart()" value="Checkout">
<input type="button" onClick="deleteCart()" value="Empty">
- <a href="../ShoppingCart/">(feed)</a>
+ <a href="../shoppingCart/">(feed)</a>
</form>
</div>
</body>
diff --git a/sca-cpp/trunk/test/store-script/htdocs/store.js b/sca-cpp/trunk/test/store-script/htdocs/store.js
index 9cb09f4b78..9cd8eb526d 100644
--- a/sca-cpp/trunk/test/store-script/htdocs/store.js
+++ b/sca-cpp/trunk/test/store-script/htdocs/store.js
@@ -650,9 +650,9 @@ tuscany.sca.Property = function (name) {
}
tuscany.sca.referenceMap = new Object();
-tuscany.sca.referenceMap.catalog = new JSONRpcClient("/Catalog").Service;
-tuscany.sca.referenceMap.shoppingCart = new AtomClient("/ShoppingCart");
-tuscany.sca.referenceMap.shoppingTotal = new JSONRpcClient("/Total").Service;
+tuscany.sca.referenceMap.catalog = new JSONRpcClient("/catalog").Service;
+tuscany.sca.referenceMap.shoppingCart = new AtomClient("/shoppingCart");
+tuscany.sca.referenceMap.shoppingTotal = new JSONRpcClient("/total").Service;
tuscany.sca.Reference = function (name) {
return tuscany.sca.referenceMap[name];
}
diff --git a/sca-cpp/trunk/test/store-script/shopping-cart.scm b/sca-cpp/trunk/test/store-script/shopping-cart.scm
index 01ca62df40..b7672345d7 100644
--- a/sca-cpp/trunk/test/store-script/shopping-cart.scm
+++ b/sca-cpp/trunk/test/store-script/shopping-cart.scm
@@ -14,21 +14,29 @@
; Post a new item to the cart, create a new cart if necessary
(define (post item cache)
(define id (uuid))
- (define cart (cons item (getcart cartId cache)))
+ (define newItem (list (car item) id (caddr item)))
+ (define cart (cons newItem (getcart cartId cache)))
(cache "put" cartId cart)
id
)
; Return the content of the cart
(define (getall cache)
- (define cart (getcart cartId cache))
- (cons "Your Cart" (cons cartId cart))
+ (cons "Your Cart" (cons cartId (getcart cartId cache)))
+)
+
+; Find an item in the cart
+(define (find id cart)
+ (if (nul cart)
+ (cons "Item" (list "0" (list)))
+ (if (= id (cadr (car cart)))
+ (car cart)
+ (find id (cdr cart))))
)
; Get an item from the cart
(define (get id cache)
- (define entry (list (list 'name "Apple") (list 'currencyCode "USD") (list 'currencySymbol "$") (list 'price 2.99)))
- (cons "Item" (list id entry))
+ (find id (getcart cartId cache))
)
; Delete the cart
@@ -38,12 +46,14 @@
; Return the price of an item
(define (price item)
- (car (cdr (car (cdr (cdr (cdr (cdr (car (cdr (cdr item))))))))))
+ (cadr (assoc 'price (caddr item)))
)
; Sum the prices of a list of items
(define (sum items)
- (if (nul items) 0 (+ (price (car items)) (sum (cdr items))))
+ (if (nul items)
+ 0
+ (+ (price (car items)) (sum (cdr items))))
)
; Return the total price of the items in the cart
diff --git a/sca-cpp/trunk/test/store-script/store-composite-test b/sca-cpp/trunk/test/store-script/store-composite-test
index 43923fca36..b41c4e5393 100755
--- a/sca-cpp/trunk/test/store-script/store-composite-test
+++ b/sca-cpp/trunk/test/store-script/store-composite-test
@@ -24,43 +24,7 @@ echo "Testing..."
../../modules/server/server-conf tmp
cat >>tmp/conf/httpd.conf <<EOF
-<Location /Catalog>
-SetHandler mod_tuscany_eval
-SCAContribution `pwd`/
-SCAComposite store.composite
-SCAComponent Catalog
-</Location>
-
-<Location /Total>
-SetHandler mod_tuscany_eval
-SCAContribution `pwd`/
-SCAComposite store.composite
-SCAComponent ShoppingCart
-</Location>
-
-<Location /ShoppingCart>
-SetHandler mod_tuscany_eval
-SCAContribution `pwd`/
-SCAComposite store.composite
-SCAComponent ShoppingCart
-</Location>
-
-<Location /CurrencyConverter>
-SetHandler mod_tuscany_eval
-SCAContribution `pwd`/
-SCAComposite store.composite
-SCAComponent CurrencyConverter
-</Location>
-
-<Location /Cache>
-SetHandler mod_tuscany_eval
-SCAContribution `pwd`/
-SCAComposite store.composite
-SCAComponent Cache
-</Location>
-
-<Location /references>
-SetHandler mod_tuscany_wiring
+<Location />
SCAContribution `pwd`/
SCAComposite store.composite
</Location>
@@ -70,7 +34,7 @@ apachectl -k start -d `pwd`/tmp
mc="memcached -l 127.0.0.1 -m 4 -p 11211"
$mc &
-sleep 1
+sleep 2
# Test HTTP GET
curl http://localhost:8090/store.html 2>/dev/null >tmp/store.html
@@ -80,7 +44,7 @@ rc=$?
# Cleanup
apachectl -k stop -d `pwd`/tmp
kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
-sleep 1
+sleep 2
if [ "$rc" = "0" ]; then
echo "OK"
fi
diff --git a/sca-cpp/trunk/test/store-script/store.composite b/sca-cpp/trunk/test/store-script/store.composite
index 2cfadf3f71..cc00ae2d65 100644
--- a/sca-cpp/trunk/test/store-script/store.composite
+++ b/sca-cpp/trunk/test/store-script/store.composite
@@ -25,26 +25,19 @@
<component name="Store">
<!-- <t:implementation.widget location="store.html"/> -->
<t:implementation.scheme uri="store.scm"/>
-
<service name="Widget">
<t:binding.http uri="store"/>
</service>
- <reference name="catalog" target="Catalog">
- <t:binding.jsonrpc uri="Catalog"/>
- </reference>
- <reference name="shoppingCart" target="ShoppingCart/Cart">
- <t:binding.atom/>
- </reference>
- <reference name="shoppingTotal" target="ShoppingCart/Total">
- <t:binding.jsonrpc/>
- </reference>
+ <reference name="catalog" target="Catalog"/>
+ <reference name="shoppingCart" target="ShoppingCart/Cart"/>
+ <reference name="shoppingTotal" target="ShoppingCart/Total"/>
</component>
<component name="Catalog">
<t:implementation.scheme uri="fruits-catalog.scm"/>
<property name="currencyCode">USD</property>
<service name="Catalog">
- <t:binding.jsonrpc uri="Catalog"/>
+ <t:binding.jsonrpc uri="catalog"/>
</service>
<reference name="currencyConverter" target="CurrencyConverter"/>
</component>
@@ -52,27 +45,25 @@
<component name="ShoppingCart">
<t:implementation.scheme uri="shopping-cart.scm"/>
<service name="ShoppingCart">
- <t:binding.atom uri="ShoppingCart"/>
+ <t:binding.atom uri="shoppingCart"/>
</service>
<service name="Total">
- <t:binding.jsonrpc uri="Total"/>
+ <t:binding.jsonrpc uri="total"/>
</service>
- <reference name="cache" target="Cache">
- <t:binding.atom/>
- </reference>
+ <reference name="cache" target="Cache"/>
</component>
<component name="CurrencyConverter">
<t:implementation.scheme uri="currency-converter.scm"/>
<service name="CurrencyConverter">
- <t:binding.jsonrpc uri="CurrencyConverter"/>
+ <t:binding.jsonrpc uri="currencyConverter"/>
</service>
</component>
<component name="Cache">
<t:implementation.cpp uri="../../components/cache/.libs/libmcache"/>
<service name="Cache">
- <t:binding.atom uri="Cache"/>
+ <t:binding.atom uri="cache"/>
</service>
</component>