diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-30 08:36:32 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-30 08:36:32 +0000 |
commit | ff124040623879bc48a0ba5cf06a841642adef53 (patch) | |
tree | e0bee552780b0852c10744017b7826b08f57d377 /sca-cpp/trunk/modules | |
parent | cd7dae28b034deebc9c2c2469ed9d8f1f3dab1ed (diff) |
Fixes to the http client, httpd modules and memcached component to get the store and shopping cart test case working end to end.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@885349 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
17 files changed, 409 insertions, 235 deletions
diff --git a/sca-cpp/trunk/modules/atom/atom.hpp b/sca-cpp/trunk/modules/atom/atom.hpp index ac19b93e38..22489fd1d1 100644 --- a/sca-cpp/trunk/modules/atom/atom.hpp +++ b/sca-cpp/trunk/modules/atom/atom.hpp @@ -38,7 +38,7 @@ namespace atom { /** * Convert a list of elements to a list of values representing an ATOM entry. */ -const list<value> entryValue(const list<value>& e) { +const list<value> entryValues(const list<value>& e) { const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), e); const value t = isNil(lt)? value(std::string("")) : elementValue(car(lt)); const list<value> li = filter<value>(selector(mklist<value>(element, "id")), e); @@ -53,7 +53,7 @@ const list<value> entryValue(const list<value>& e) { const list<value> entriesValues(const list<value>& e) { if (isNil(e)) return e; - return cons<value>(entryValue(car(e)), entriesValues(cdr(e))); + return cons<value>(entryValues(car(e)), entriesValues(cdr(e))); } /** @@ -63,7 +63,15 @@ const failable<list<value>, std::string> readEntry(const list<std::string>& ilis const list<value> e = readXML(ilist); if (isNil(e)) return mkfailure<list<value>, std::string>("Empty entry"); - return entryValue(car(e)); + return entryValues(car(e)); +} + +/** + * Convert a list of values representing an ATOM entry to a value. + */ +const value entryValue(const list<value>& e) { + const list<value> v = elementsToValues(mklist<value>(caddr(e))); + return cons(car(e), mklist<value>(cadr(e), cdr<value>(car(v)))); } /** diff --git a/sca-cpp/trunk/modules/http/curl-test.cpp b/sca-cpp/trunk/modules/http/curl-test.cpp index 0a6fbcd8a6..59944546a1 100644 --- a/sca-cpp/trunk/modules/http/curl-test.cpp +++ b/sca-cpp/trunk/modules/http/curl-test.cpp @@ -50,7 +50,7 @@ std::ostringstream* curlWriter(const std::string& s, std::ostringstream* os) { } const bool testGet() { - CURLHandle ch; + CURLSession ch; { std::ostringstream os; const failable<list<std::ostringstream*>, std::string> r = get<std::ostringstream*>(curlWriter, &os, "http://localhost:8090", ch); @@ -66,7 +66,7 @@ const bool testGet() { return true; } -const bool testGetLoop(const int count, CURLHandle& ch) { +const bool testGetLoop(const int count, CURLSession& ch) { if (count == 0) return true; const failable<value, std::string> r = get("http://localhost:8090", ch); @@ -77,7 +77,7 @@ const bool testGetLoop(const int count, CURLHandle& ch) { const bool testGetPerf() { const int count = 50; - CURLHandle ch; + CURLSession ch; struct timeval start; struct timeval end; { diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/curl.hpp index 6c3a3a47dc..fd2e9857d1 100644 --- a/sca-cpp/trunk/modules/http/curl.hpp +++ b/sca-cpp/trunk/modules/http/curl.hpp @@ -30,6 +30,7 @@ #include <curl/types.h> #include <curl/easy.h> #include <string> +#include "gc.hpp" #include "list.hpp" #include "value.hpp" #include "element.hpp" @@ -41,11 +42,6 @@ namespace tuscany { namespace http { /** - * Set to true to log HTTP content. - */ -bool logContent = false; - -/** * CURL library context, one per process. */ class CURLContext { @@ -63,22 +59,45 @@ CURLContext curlContext; /** * Represents a CURL session handle. */ -class CURLHandle { +class CURLSession { public: - CURLHandle() : h(curl_easy_init()) { + CURLSession() : ch(new CURLHandle()) { } - ~CURLHandle() { - curl_easy_cleanup(h); + + ~CURLSession() { } - operator CURL*() const { - return h; + CURLSession(const CURLSession& c) : ch(c.ch) { } + private: - CURL* h; + class CURLHandle { + public: + CURLHandle() : h(curl_easy_init()) { + } + ~CURLHandle() { + curl_easy_cleanup(h); + h = NULL; + } + private: + CURL* h; + + friend CURL* handle(const CURLSession& c); + }; + + const gc_ptr<CURLHandle> ch; + + friend CURL* handle(const CURLSession& c); }; /** + * Returns the CURL handle used by a CURL session. + */ +CURL* handle(const CURLSession& c) { + return c.ch->h; +} + +/** * Context passed to the read callback function. */ class CURLReadContext { @@ -143,9 +162,10 @@ curl_slist* headers(curl_slist* cl, const list<std::string>& h) { return headers(curl_slist_append(cl, std::string(car(h)).c_str()), cdr(h)); } -template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLHandle& ch) { +template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLSession& cs) { // Init the curl session + CURL* ch = handle(cs); curl_easy_reset(ch); curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0"); @@ -204,7 +224,9 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list< /** * Evaluate an expression remotely, at the given URL. */ -const failable<value, std::string> evalExpr(const value& expr, const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> evalExpr(const value& expr, const std::string& url, const CURLSession& ch) { + debug(url, "http::evalExpr::url"); + debug(expr, "http::evalExpr::input"); // Convert expression to a JSON-RPC request json::JSONContext cx; @@ -212,13 +234,6 @@ const failable<value, std::string> evalExpr(const value& expr, const std::string if (!hasContent(jsreq)) return mkfailure<value, std::string>(reason(jsreq)); - if (logContent) { - std::cout<< "content: " << std::endl; - write(content(jsreq), std::cout); - std::cout<< std::endl; - std::cout.flush(); - } - // POST it to the URL const list<std::string> h = mklist<std::string>("Content-Type: application/json-rpc"); const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(mklist<list<std::string> >(h, content(jsreq)), rcons<std::string>, list<std::string>(), url, "POST", ch); @@ -226,19 +241,58 @@ const failable<value, std::string> evalExpr(const value& expr, const std::string return mkfailure<value, std::string>(reason(res)); // Return result - if (logContent) { - std::cout << "content:" << std::endl; - write(cadr<list<std::string> >(content(res)), std::cout); - std::cout << std::endl; - } - const list<value> val = elementsToValues(content(json::readJSON(cadr<list<std::string> >(content(res)), cx))); - return cadr<value>(cadr<value>(val)); + failable<list<value>, std::string> jsres = json::readJSON(cadr<list<std::string> >(content(res)), cx); + if (!hasContent(jsres)) + return mkfailure<value, std::string>(reason(jsres)); + const list<value> val = elementsToValues(content(jsres)); + + const value rval(cadr<value>(cadr<value>(val))); + debug(rval, "http::evalExpr::result"); + return rval; +} + +/** + * Find and return a header. + */ +const failable<std::string, std::string> header(const std::string& prefix, const list<std::string>& h) { + if (isNil(h)) + return mkfailure<std::string, std::string>(std::string("Couldn't find header: ") + prefix); + const std::string s = car(h); + if (s.find(prefix) != 0) + return header(prefix, cdr(h)); + const std::string l(s.substr(prefix.length())); + return l.substr(0, l.find_first_of("\r\n")); +} + +/** + * Find and return a location header. + */ +const failable<std::string, std::string> location(const list<std::string>& h) { + return header("Location: ", h); +} + +/** + * Convert a location to an entry id. + */ +const failable<value, std::string> entryId(const failable<std::string, std::string> l) { + if (!hasContent(l)) + return mkfailure<value, std::string>(reason(l)); + const std::string ls(content(l)); + return value(ls.substr(ls.find_last_of("/") + 1)); +} + +/** + * Find and return a content-type header. + */ +const failable<std::string, std::string> contentType(const list<std::string>& h) { + return header("Content-Type: ", h); } /** * HTTP GET, return the resource at the given URL. */ -template<typename R> const failable<list<R>, std::string> get(const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const CURLHandle& ch) { +template<typename R> const failable<list<R>, std::string> get(const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const CURLSession& ch) { + debug(url, "http::get::url"); const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>()); return apply(req, reduce, initial, url, "GET", ch); } @@ -246,38 +300,41 @@ template<typename R> const failable<list<R>, std::string> get(const lambda<R(std /** * HTTP GET, return a list of values representing the resource at the given URL. */ -const failable<value, std::string> get(const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> get(const std::string& url, const CURLSession& ch) { + debug(url, "http::get::url"); // Get the contents of the resource at the given URL const failable<list<list<std::string> >, std::string> res = get<list<std::string> >(rcons<std::string>, list<std::string>(), url, ch); if (!hasContent(res)) return mkfailure<value, std::string>(reason(res)); + const list<std::string> ls(reverse(cadr(content(res)))); - const std::string ct; - if (ct.find("application/atom+xml") != std::string::npos) { - // TODO Return an ATOM feed + const std::string ct(content(contentType(car(content(res))))); + if (ct == "application/atom+xml;type=entry") { + const value val(atom::entryValue(content(atom::readEntry(ls)))); + debug(val, "http::get::result"); + return val; } // Return the content as a string value std::ostringstream os; - write(reverse(cadr(content(res))), os); - return value(os.str()); + write(ls, os); + const value val(os.str()); + debug(val, "http::get::result"); + return val; } /** * HTTP POST. */ -const failable<value, std::string> post(const value& val, const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> post(const value& val, const std::string& url, const CURLSession& ch) { // Convert value to an ATOM entry const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); if (!hasContent(entry)) return mkfailure<value, std::string>(reason(entry)); - if (logContent) { - std::cout << "content:" << std::endl; - write(list<std::string>(content(entry)), std::cout); - std::cout << std::endl; - } + debug(url, "http::post::url"); + debug(content(entry), "http::post::input"); // POST it to the URL const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml"); @@ -285,23 +342,24 @@ const failable<value, std::string> post(const value& val, const std::string& url const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "POST", ch); if (!hasContent(res)) return mkfailure<value, std::string>(reason(res)); - return value(true); + + // Return the new entry id from the HTTP location header + const failable<value, std::string> eid(entryId(location(car(content(res))))); + debug(eid, "http::post::result"); + return eid; } /** * HTTP PUT. */ -const failable<value, std::string> put(const value& val, const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> put(const value& val, const std::string& url, const CURLSession& ch) { // Convert value to an ATOM entry const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); if (!hasContent(entry)) return mkfailure<value, std::string>(reason(entry)); - if (logContent) { - std::cout << "content:" << std::endl; - write(list<std::string>(content(entry)), std::cout); - std::cout << std::endl; - } + debug(url, "http::put::url"); + debug(content(entry), "http::put::input"); // PUT it to the URL const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml"); @@ -309,17 +367,23 @@ const failable<value, std::string> put(const value& val, const std::string& url, const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "PUT", ch); if (!hasContent(res)) return mkfailure<value, std::string>(reason(res)); + + debug(true, "http::put::result"); return value(true); } /** * HTTP DELETE. */ -const failable<value, std::string> del(const std::string& url, const CURLHandle& ch) { +const failable<value, std::string> del(const std::string& url, const CURLSession& ch) { + debug(url, "http::delete::url"); + const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>()); const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "DELETE", ch); if (!hasContent(res)) return mkfailure<value, std::string>(reason(res)); + + debug(true, "http::delete::result"); return value(true); } @@ -327,7 +391,7 @@ const failable<value, std::string> del(const std::string& url, const CURLHandle& * HTTP client proxy function. */ struct proxy { - proxy(const std::string& url, const CURLHandle& ch) : url(url), ch(ch) { + proxy(const std::string& url, const CURLSession& ch) : url(url), ch(ch) { } const value operator()(const list<value>& args) const { @@ -338,7 +402,7 @@ struct proxy { } const std::string url; - const CURLHandle& ch; + const CURLSession ch; }; } diff --git a/sca-cpp/trunk/modules/http/http-test b/sca-cpp/trunk/modules/http/http-test index 1ab0da64b9..0aaaec48df 100755 --- a/sca-cpp/trunk/modules/http/http-test +++ b/sca-cpp/trunk/modules/http/http-test @@ -28,5 +28,5 @@ rc=$? # Cleanup apachectl -k stop -d `pwd`/tmp -sleep 2 +sleep 1 return $rc diff --git a/sca-cpp/trunk/modules/http/httpd-test b/sca-cpp/trunk/modules/http/httpd-test index 57c35c5cc9..8e1d681d84 100755 --- a/sca-cpp/trunk/modules/http/httpd-test +++ b/sca-cpp/trunk/modules/http/httpd-test @@ -31,7 +31,7 @@ rc=$? # Cleanup apachectl -k stop -d `pwd`/tmp -sleep 2 +sleep 1 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 a9ced05208..05b959f1d2 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -50,18 +50,13 @@ #include "list.hpp" #include "value.hpp" +#include "debug.hpp" namespace tuscany { namespace httpd { /** - * Set to true to log requests and content. - */ -bool logRequests = false; -bool logContent = false; - -/** * Returns a server-scoped module configuration. */ template<typename C> void* makeServerConf(apr_pool_t *p, server_rec *s) { @@ -120,7 +115,7 @@ const std::string path(const list<value>& p) { */ const char* optional(const char* s) { if (s == NULL) - return "(null)"; + return ""; return s; } @@ -128,59 +123,40 @@ const std::string contentType(const request_rec* r) { return optional(apr_table_get(r->headers_in, "Content-Type")); } +#ifdef _DEBUG + /** - * Log HTTP request info. + * Debug log. */ -int logHeader(void* r, const char* key, const char* value) { - std::cout << "header key: " << key << ", value: " << value << std::endl; +int debugHeader(unused void* r, const char* key, const char* value) { + std::cerr << " header key: " << key << ", value: " << value << std::endl; return 1; } -const bool logRequest(request_rec* r, const std::string& msg) { - if (!logRequests) - return true; - std::cout << msg << std::endl; - std::cout << "protocol: " << optional(r->protocol) << std::endl; - std::cout << "method: " << optional(r->method) << std::endl; - std::cout << "method number: " << r->method_number << std::endl; - std::cout << "content type: " << contentType(r) << std::endl; - std::cout << "content encoding: " << optional(r->content_encoding) << std::endl; - apr_table_do(logHeader, r, r->headers_in, NULL); - std::cout << "uri: " << optional(r->unparsed_uri) << std::endl; - std::cout << "path: " << optional(r->uri) << std::endl; - std::cout << "path info: " << optional(r->path_info) << std::endl; - std::cout << "filename: " << optional(r->filename) << std::endl; - std::cout << "path tokens: " << pathTokens(r->uri) << std::endl; - std::cout << "args: " << optional(r->args) << std::endl; - std::cout.flush(); +const bool debugRequest(request_rec* r, const std::string& msg) { + std::cerr << msg << ":" << std::endl; + std::cerr << " protocol: " << optional(r->protocol) << std::endl; + std::cerr << " method: " << optional(r->method) << std::endl; + std::cerr << " method number: " << r->method_number << std::endl; + 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 << " 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 << " args: " << optional(r->args) << std::endl; return true; } -const bool logValue(const value& v, const std::string& msg) { - if (!logContent) - return true; - std::cout<< msg << ": " << v << std::endl; - std::cout.flush(); - return true; -} +#define httpdDebugRequest(r, msg) httpd::debugRequest(r, msg) -const bool logValue(const failable<value, std::string>& v, const std::string& msg) { - if (!logContent) - return true; - std::cout<< msg << ": " << v << std::endl; - std::cout.flush(); - return true; -} +#else -const bool logStrings(const list<std::string>& ls, const std::string& msg) { - if (!logContent) - return true; - std::cout<< msg << ": " << std::endl; - write(ls, std::cout); - std::cout<< std::endl; - std::cout.flush(); - return true; -} +#define httpdDebugRequest(r, msg) + +#endif /** * Returns a list of key value pairs from the args in a query string. @@ -256,14 +232,6 @@ const char* url(const value& v, request_rec* r) { } /** - * Convert an ATOM entry to a value. - */ -const value feedEntry(const list<value>& e) { - const list<value> v = elementsToValues(mklist<value>(caddr(e))); - return cons(car(e), mklist<value>(cadr(e), cdr<value>(car(v)))); -} - -/** * Write an HTTP result. */ const failable<int, std::string> writeResult(const failable<list<std::string>, std::string>& ls, const std::string& ct, request_rec* r) { @@ -271,10 +239,7 @@ const failable<int, std::string> writeResult(const failable<list<std::string>, s return mkfailure<int, std::string>(reason(ls)); std::ostringstream os; write(content(ls), os); - if (logContent) { - std::cout<< "content: " << std::endl << os.str() << std::endl; - std::cout.flush(); - } + debug(os.str(), "httpd::result"); const std::string etag(ap_md5(r->pool, (const unsigned char*)std::string(os.str()).c_str())); const char* match = apr_table_get(r->headers_in, "If-None-Match"); @@ -283,7 +248,7 @@ const failable<int, std::string> writeResult(const failable<list<std::string>, s r->status = HTTP_NOT_MODIFIED; return OK; } - ap_set_content_type(r, ct.c_str()); + ap_set_content_type(r, apr_pstrdup(r->pool, ct.c_str())); ap_rputs(std::string(os.str()).c_str(), r); return OK; } diff --git a/sca-cpp/trunk/modules/server/client-test.cpp b/sca-cpp/trunk/modules/server/client-test.cpp index b43cb92c52..5888c481e3 100644 --- a/sca-cpp/trunk/modules/server/client-test.cpp +++ b/sca-cpp/trunk/modules/server/client-test.cpp @@ -50,7 +50,7 @@ std::ostringstream* curlWriter(const std::string& s, std::ostringstream* os) { } const bool testGet() { - http::CURLHandle ch; + http::CURLSession ch; { std::ostringstream os; const failable<list<std::ostringstream*>, std::string> r = http::get<std::ostringstream*>(curlWriter, &os, "http://localhost:8090", ch); @@ -66,7 +66,7 @@ const bool testGet() { return true; } -const bool testGetLoop(const int count, http::CURLHandle& ch) { +const bool testGetLoop(const int count, http::CURLSession& ch) { if (count == 0) return true; const failable<value, std::string> r = get("http://localhost:8090", ch); @@ -77,16 +77,13 @@ const bool testGetLoop(const int count, http::CURLHandle& ch) { const bool testGetPerf() { const int count = 50; - http::CURLHandle ch; + http::CURLSession ch; struct timeval start; struct timeval end; { testGetLoop(5, ch); - gettimeofday(&start, NULL); - testGetLoop(count, ch); - gettimeofday(&end, NULL); std::cout << "Static GET test " << duration(start, end, count) << " ms" << std::endl; } @@ -94,13 +91,13 @@ const bool testGetPerf() { } const bool testEval() { - http::CURLHandle ch; + http::CURLSession ch; const value val = content(http::evalExpr(mklist<value>(std::string("echo"), std::string("Hello")), "http://localhost:8090/test", ch)); assert(val == std::string("Hello")); return true; } -const bool testEvalLoop(const int count, http::CURLHandle& ch) { +const bool testEvalLoop(const int count, http::CURLSession& ch) { if (count == 0) return true; const value val = content(http::evalExpr(mklist<value>(std::string("echo"), std::string("Hello")), "http://localhost:8090/test", ch)); @@ -111,7 +108,7 @@ const bool testEvalLoop(const int count, http::CURLHandle& ch) { const value blob(std::string(3000, 'A')); const list<value> blobs = mklist(blob, blob, blob, blob, blob); -const bool testBlobEvalLoop(const int count, http::CURLHandle& ch) { +const bool testBlobEvalLoop(const int count, http::CURLSession& ch) { if (count == 0) return true; const value val = content(http::evalExpr(mklist<value>(std::string("echo"), blobs), "http://localhost:8090/test", ch)); @@ -121,26 +118,20 @@ const bool testBlobEvalLoop(const int count, http::CURLHandle& ch) { const bool testEvalPerf() { const int count = 50; - http::CURLHandle ch; + http::CURLSession ch; struct timeval start; struct timeval end; { testEvalLoop(5, ch); - gettimeofday(&start, NULL); - testEvalLoop(count, ch); - gettimeofday(&end, NULL); std::cout << "JSON-RPC eval echo test " << duration(start, end, count) << " ms" << std::endl; } { testBlobEvalLoop(5, ch); - gettimeofday(&start, NULL); - testBlobEvalLoop(count, ch); - gettimeofday(&end, NULL); std::cout << "JSON-RPC eval blob test " << duration(start, end, count) << " ms" << std::endl; } @@ -156,23 +147,23 @@ bool testPost() { << (list<value>() << "name" << std::string("Apple")) << (list<value>() << "price" << std::string("$2.99")); const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLHandle ch; - value rc = content(http::post(a, "http://localhost:8090/test", ch)); - assert(rc == value(true)); + http::CURLSession ch; + const failable<value, std::string> id = http::post(a, "http://localhost:8090/test", ch); + assert(hasContent(id)); return true; } -const bool testPostLoop(const int count, const value& val, http::CURLHandle& ch) { +const bool testPostLoop(const int count, const value& val, http::CURLSession& ch) { if (count == 0) return true; - const value rc = content(http::post(val, "http://localhost:8090/test", ch)); - assert(rc == value(true)); + const failable<value, std::string> id = http::post(val, "http://localhost:8090/test", ch); + assert(hasContent(id)); return testPostLoop(count - 1, val, ch); } const bool testPostPerf() { const int count = 50; - http::CURLHandle ch; + http::CURLSession ch; struct timeval start; struct timeval end; { @@ -181,11 +172,8 @@ const bool testPostPerf() { << (list<value>() << "price" << std::string("$2.99")); const list<value> val = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); testPostLoop(5, val, ch); - gettimeofday(&start, NULL); - testPostLoop(count, val, ch); - gettimeofday(&end, NULL); std::cout << "ATOMPub POST small test " << duration(start, end, count) << " ms" << std::endl; } @@ -200,11 +188,8 @@ const bool testPostPerf() { << (list<value>() << "price" << std::string("$2.99")); const list<value> val = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); testPostLoop(5, val, ch); - gettimeofday(&start, NULL); - testPostLoop(count, val, ch); - gettimeofday(&end, NULL); std::cout << "ATOMPub POST blob test " << duration(start, end, count) << " ms" << std::endl; } @@ -216,19 +201,49 @@ const bool testPut() { << (list<value>() << "name" << std::string("Apple")) << (list<value>() << "price" << std::string("$2.99")); const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - http::CURLHandle ch; + http::CURLSession ch; value rc = content(http::put(a, "http://localhost:8090/test/111", ch)); assert(rc == value(true)); return true; } const bool testDel() { - http::CURLHandle ch; + http::CURLSession ch; value rc = content(http::del("http://localhost:8090/test/123456789", ch)); assert(rc == value(true)); return true; } +const bool testEvalCpp() { + http::CURLSession ch; + const value val = content(http::evalExpr(mklist<value>(std::string("hello"), std::string("world")), "http://localhost:8090/cpp", ch)); + assert(val == std::string("hello world")); + return true; +} + +const bool testEvalCppLoop(const int count, http::CURLSession& ch) { + if (count == 0) + return true; + const value val = content(http::evalExpr(mklist<value>(std::string("hello"), std::string("world")), "http://localhost:8090/cpp", ch)); + assert(val == std::string("hello world")); + return testEvalCppLoop(count - 1, ch); +} + +const bool testEvalCppPerf() { + const int count = 50; + http::CURLSession ch; + struct timeval start; + struct timeval end; + { + testEvalCppLoop(5, ch); + gettimeofday(&start, NULL); + testEvalCppLoop(count, ch); + gettimeofday(&end, NULL); + std::cout << "JSON-RPC C++ eval test " << duration(start, end, count) << " ms" << std::endl; + } + return true; +} + } } @@ -244,6 +259,8 @@ int main() { tuscany::server::testFeed(); tuscany::server::testPut(); tuscany::server::testDel(); + tuscany::server::testEvalCpp(); + tuscany::server::testEvalCppPerf(); std::cout << "OK" << std::endl; diff --git a/sca-cpp/trunk/modules/server/httpd-client.scm b/sca-cpp/trunk/modules/server/client-test.scm index 12275693f4..12275693f4 100644 --- a/sca-cpp/trunk/modules/server/httpd-client.scm +++ b/sca-cpp/trunk/modules/server/client-test.scm diff --git a/sca-cpp/trunk/modules/server/httpd-test.composite b/sca-cpp/trunk/modules/server/domain-test.composite index 875d26ae1b..48570e64d3 100644 --- a/sca-cpp/trunk/modules/server/httpd-test.composite +++ b/sca-cpp/trunk/modules/server/domain-test.composite @@ -19,18 +19,25 @@ --> <composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200903" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" - targetNamespace="http://test" - name="httpd-test"> + targetNamespace="http://domain/test" + name="domain-test"> - <component name="httpd-test"> - <t:implementation.scheme uri="httpd-test.scm"/> + <component name="server-test"> + <t:implementation.scheme uri="server-test.scm"/> <service name="test"> <t:binding.http uri="test"/> </service> </component> - <component name="httpd-client"> - <t:implementation.scheme uri="httpd-client.scm"/> + <component name="cpp-test"> + <t:implementation.cpp uri=".libs/libimpl-test"/> + <service name="cpp"> + <t:binding.http uri="cpp"/> + </service> + </component> + + <component name="client-test"> + <t:implementation.scheme uri="client-test.scm"/> <service name="client"> <t:binding.http uri="client"/> </service> diff --git a/sca-cpp/trunk/modules/server/httpd-test b/sca-cpp/trunk/modules/server/httpd-test index 7fa2112f75..2f50c9f3c3 100755 --- a/sca-cpp/trunk/modules/server/httpd-test +++ b/sca-cpp/trunk/modules/server/httpd-test @@ -27,8 +27,8 @@ cat >>tmp/conf/httpd.conf <<EOF <Location /test> SetHandler mod_tuscany_eval SCAContribution `pwd`/ -SCAComposite httpd-test.composite -SCAComponent httpd-test +SCAComposite domain-test.composite +SCAComponent server-test </Location> EOF @@ -73,7 +73,7 @@ fi # Cleanup apachectl -k stop -d `pwd`/tmp -sleep 2 +sleep 1 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 new file mode 100644 index 0000000000..217c6f5171 --- /dev/null +++ b/sca-cpp/trunk/modules/server/impl-test.cpp @@ -0,0 +1,76 @@ +/* + * 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$ */ + +/** + * Test component implementation. + */ + +#include <string> + +#include "function.hpp" +#include "list.hpp" +#include "value.hpp" +#include "monad.hpp" +#include "debug.hpp" + +namespace tuscany { +namespace server { + +const failable<value, std::string> get(unused const list<value>& params) { + return value(std::string("Hey")); +} + +const failable<value, std::string> post(unused const list<value>& params) { + return value(std::string("1234")); +} + +const failable<value, std::string> put(unused const list<value>& params) { + return value(true); +} + +const failable<value, std::string> del(unused const list<value>& params) { + return value(true); +} + +const failable<value, std::string> hello(const list<value>& params) { + return value("hello " + std::string(car(params))); +} + +} +} + +extern "C" { + +const tuscany::failable<tuscany::value, std::string> eval(const tuscany::value& func, const tuscany::list<tuscany::value>& params) { + if (func == "get") + return tuscany::server::get(params); + if (func == "post") + return tuscany::server::post(params); + if (func == "put") + return tuscany::server::put(params); + if (func == "del") + return tuscany::server::del(params); + if (func == "hello") + return tuscany::server::hello(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 cb24b76f6c..99b69a0d9f 100644 --- a/sca-cpp/trunk/modules/server/mod-cpp.hpp +++ b/sca-cpp/trunk/modules/server/mod-cpp.hpp @@ -34,6 +34,7 @@ #include "function.hpp" #include "list.hpp" #include "value.hpp" +#include "debug.hpp" #include "monad.hpp" #include "dynlib.hpp" #include "cache.hpp" @@ -52,12 +53,13 @@ namespace cpp { struct evalImplementation { const lib ilib; const ilambda impl; - evalImplementation(const lib& ilib, const ilambda& impl) : ilib(ilib), impl(impl) { + const list<value> px; + evalImplementation(const lib& ilib, const ilambda& 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 { - httpd::logValue(cons<value>(func, params), "expr"); - const failable<value, std::string> val = impl(func, params); - httpd::logValue(content(val), "val"); + 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"); return val; } }; @@ -65,7 +67,7 @@ struct evalImplementation { /** * Read a C++ component implementation. */ -const failable<ilambda, std::string> readLatestImplementation(const std::string path) { +const failable<ilambda, std::string> readLatestImplementation(const std::string path, const list<value>& px) { const failable<lib, std::string> ilib(dynlib(path)); if (!hasContent(ilib)) return mkfailure<ilambda, std::string>(reason(ilib)); @@ -73,14 +75,14 @@ const failable<ilambda, std::string> readLatestImplementation(const std::string const failable<ilambda, std::string> impl(dynlambda<failable<value, std::string>(value, list<value>)>("eval", content(ilib))); if (!hasContent(impl)) return impl; - return ilambda(evalImplementation(content(ilib), content(impl))); + return ilambda(evalImplementation(content(ilib), content(impl), px)); } -const cached<failable<ilambda, std::string> > readImplementation(const std::string& path) { - const lambda<failable<ilambda, std::string>(std::string)> ri(readLatestImplementation); +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), curry(ft, p)); + return cached<failable<ilambda, std::string> >(curry(ri, p, px), curry(ft, p)); } } diff --git a/sca-cpp/trunk/modules/server/mod-eval.cpp b/sca-cpp/trunk/modules/server/mod-eval.cpp index f843b9bdc5..aa0a6067a1 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.cpp +++ b/sca-cpp/trunk/modules/server/mod-eval.cpp @@ -57,10 +57,11 @@ namespace modeval { */ class ServerConf { public: - ServerConf(server_rec* s) : s(s), home("") { + ServerConf(server_rec* s) : s(s), home(""), wiringHost("") { } - server_rec* s; + const server_rec* s; std::string home; + std::string wiringHost; }; /** @@ -77,7 +78,7 @@ class DirConf { public: DirConf(char* dirspec) : dirspec(dirspec), contributionPath(""), compositeName(""), componentName(""), implementationPath("") { } - char* dirspec; + const char* dirspec; std::string contributionPath; std::string compositeName; std::string componentName; @@ -89,7 +90,8 @@ public: /** * Handle an HTTP GET. */ -const failable<int, std::string> get(request_rec* r, const ilambda& impl, const list<value>& px) { +const failable<int, std::string> get(request_rec* r, const ilambda& impl) { + debug(r->uri, "modeval::get::url"); // Inspect the query string const list<list<value> > args = httpd::queryArgs(r); @@ -105,7 +107,7 @@ const failable<int, std::string> get(request_rec* r, const ilambda& impl, const const list<value> params = httpd::queryParams(args); // Apply the requested function - const failable<value, std::string> val = impl(func, append(params, px)); + const failable<value, std::string> val = impl(func, params); if (!hasContent(val)) return mkfailure<int, std::string>(reason(val)); @@ -117,14 +119,14 @@ const failable<int, std::string> get(request_rec* r, const ilambda& impl, const // 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", px); + const failable<value, std::string> val = impl("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", cons<value>(car(id), px)); + const failable<value, std::string> val = impl("get", mklist<value>(car(id))); 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); @@ -133,9 +135,10 @@ const failable<int, std::string> get(request_rec* r, const ilambda& impl, const /** * Handle an HTTP POST. */ -const failable<int, std::string> post(request_rec* r, const ilambda& impl, const list<value>& px) { +const failable<int, std::string> post(request_rec* r, const ilambda& impl) { const list<std::string> ls = httpd::read(r); - httpd::logStrings(ls, "content"); + debug(r->uri, "modeval::post::url"); + debug(ls, "modeval::post::input"); // Evaluate a JSON-RPC request and return a JSON result const std::string ct = httpd::contentType(r); @@ -150,7 +153,7 @@ const failable<int, std::string> post(request_rec* r, const ilambda& impl, const const list<value> params = (list<value>)cadr(assoc(value("params"), args)); // Evaluate the request expression - const failable<value, std::string> val = impl(func, append(params, px)); + const failable<value, std::string> val = impl(func, params); if (!hasContent(val)) return mkfailure<int, std::string>(reason(val)); @@ -162,8 +165,8 @@ const failable<int, std::string> post(request_rec* r, const ilambda& impl, const if (ct.find("application/atom+xml") != std::string::npos) { // Evaluate the request expression - const value entry = httpd::feedEntry(content(atom::readEntry(ls))); - const failable<value, std::string> val = impl("post", cons<value>(entry, px)); + const value entry = atom::entryValue(content(atom::readEntry(ls))); + const failable<value, std::string> val = impl("post", mklist<value>(entry)); if (!hasContent(val)) return mkfailure<int, std::string>(reason(val)); @@ -179,14 +182,15 @@ const failable<int, std::string> post(request_rec* r, const ilambda& impl, const /** * Handle an HTTP PUT. */ -const failable<int, std::string> put(request_rec* r, const ilambda& impl, const list<value>& px) { +const failable<int, std::string> put(request_rec* r, const ilambda& impl) { const list<std::string> ls = httpd::read(r); - httpd::logStrings(ls, "content"); + 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 value entry = httpd::feedEntry(content(atom::readEntry(ls))); - const failable<value, std::string> val = impl("put", append(mklist<value>(entry, car(id)), px)); + const value entry = atom::entryValue(content(atom::readEntry(ls))); + const failable<value, std::string> val = impl("put", mklist<value>(car(id), entry)); if (!hasContent(val)) return mkfailure<int, std::string>(reason(val)); if (val == value(false)) @@ -197,11 +201,12 @@ const failable<int, std::string> put(request_rec* r, const ilambda& impl, const /** * Handle an HTTP DELETE. */ -const failable<int, std::string> del(request_rec* r, const ilambda& impl, const list<value>& px) { +const failable<int, std::string> del(request_rec* r, const ilambda& 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", cons<value>(car(id), px)); + const failable<value, std::string> val = impl("delete", mklist<value>(car(id))); if (!hasContent(val)) return mkfailure<int, std::string>(reason(val)); if (val == value(false)) @@ -237,11 +242,11 @@ const cached<failable<value, std::string> > component(DirConf* conf) { /** * 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::CURLHandle& ch) { - return eval::primitiveProcedure(http::proxy(base + std::string(scdl::name(ref)), ch)); +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::CURLHandle& 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)); @@ -251,11 +256,11 @@ const list<value> proxies(const list<value>& refs, const std::string& base, cons * Returns the component implementation with the given implementation type and path. * For now only Scheme and C++ implementations are supported. */ -const cached<failable<ilambda, std::string> > implementation(const std::string& itype, const std::string& path) { +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)); + return latest(scm::readImplementation(path, px)); if (itype.find(".cpp") != std::string::npos) - return latest(cpp::readImplementation(path)); + return latest(cpp::readImplementation(path, px)); return cached<failable<ilambda, std::string> >(); } @@ -265,7 +270,7 @@ const cached<failable<ilambda, std::string> > implementation(const std::string& int handler(request_rec *r) { if(strcmp(r->handler, "mod_tuscany_eval")) return DECLINED; - httpd::logRequest(r, "mod_tuscany_eval::handler"); + httpdDebugRequest(r, "modeval::handler::input"); // Set up the read policy const int rc = httpd::setupReadPolicy(r); @@ -283,8 +288,19 @@ int handler(request_rec *r) { 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; - conf.implementation = implementation(elementName(ielement), path); } else conf.implementation = latest(conf.implementation); @@ -292,47 +308,46 @@ int handler(request_rec *r) { if (!hasContent(impl)) return HTTP_NOT_FOUND; - // Convert component references to configured proxy lambdas - std::ostringstream base; - base << "http://localhost:" << (debugWiringPort == 0? ap_get_server_port(r) : debugWiringPort) << "/references/" << std::string(scdl::name(content(comp))) << "/"; - http::CURLHandle ch; - const list<value> px(proxies(scdl::references(content(comp)), base.str(), ch)); - // Handle HTTP method if (r->header_only) return OK; if(r->method_number == M_GET) - return httpd::reportStatus(get(r, content(impl), px)); + return httpd::reportStatus(get(r, content(impl))); if(r->method_number == M_POST) - return httpd::reportStatus(post(r, content(impl), px)); + return httpd::reportStatus(post(r, content(impl))); if(r->method_number == M_PUT) - return httpd::reportStatus(put(r, content(impl), px)); + return httpd::reportStatus(put(r, content(impl))); if(r->method_number == M_DELETE) - return httpd::reportStatus(del(r, content(impl), px)); + return httpd::reportStatus(del(r, content(impl))); return HTTP_NOT_IMPLEMENTED; } /** * Configuration commands. */ -const char *confHome(cmd_parms *cmd, void *dummy, const char *arg) { +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 char *confContribution(cmd_parms *cmd, void *c, const char *arg) { +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; + 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); return NULL; } -const char *confComposite(cmd_parms *cmd, void *c, const char *arg) { +const char *confComposite(unused cmd_parms *cmd, void *c, const char *arg) { DirConf* conf = (DirConf*)c; conf->compositeName = arg; conf->component = component(conf); return NULL; } -const char *confComponent(cmd_parms *cmd, void *c, const char *arg) { +const char *confComponent(unused cmd_parms *cmd, void *c, const char *arg) { DirConf* conf = (DirConf*)c; conf->componentName = arg; conf->component = component(conf); @@ -344,17 +359,18 @@ const char *confComponent(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("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, NULL, 0, NO_ARGS, NULL} }; -int postConfig(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { +int postConfig(unused apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t *ptemp, unused server_rec *s) { return OK; } -void childInit(apr_pool_t* p, server_rec* svr_rec) { +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); if(c == NULL) { std::cerr << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << std::endl; @@ -362,7 +378,7 @@ void childInit(apr_pool_t* p, server_rec* svr_rec) { } } -void registerHooks(apr_pool_t *p) { +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); diff --git a/sca-cpp/trunk/modules/server/mod-scm.hpp b/sca-cpp/trunk/modules/server/mod-scm.hpp index 386d032695..586b90190f 100644 --- a/sca-cpp/trunk/modules/server/mod-scm.hpp +++ b/sca-cpp/trunk/modules/server/mod-scm.hpp @@ -34,8 +34,10 @@ #include "function.hpp" #include "list.hpp" #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" @@ -46,19 +48,29 @@ namespace modeval { namespace scm { /** + * Convert proxy lambdas to evaluator primitive procedures. + */ +const list<value> primitiveProcedures(const list<value>& l) { + if (isNil(l)) + return l; + return cons<value>(mklist<value>(eval::primitiveSymbol, car(l)), primitiveProcedures(cdr(l))); +} + +/** * Evaluate a script component implementation function. */ struct evalImplementation { const value impl; - evalImplementation(const value& impl) : impl(impl) { + 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, eval::quotedParameters(params)); - httpd::logValue(expr, "expr"); + const value expr = cons<value>(func, append(eval::quotedParameters(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); - httpd::logValue(val, "val"); + debug(val, "modeval::scm::evalImplementation::result"); if (isNil(val)) return mkfailure<value, std::string>("Could not evaluate expression"); return val; @@ -68,20 +80,20 @@ struct evalImplementation { /** * Read a script component implementation. */ -const failable<ilambda, std::string> readLatestImplementation(const std::string path) { +const failable<ilambda, std::string> readLatestImplementation(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); const value impl = eval::readScript(is); if (isNil(impl)) return mkfailure<ilambda, std::string>("Could not read implementation: " + path); - return ilambda(evalImplementation(impl)); + return ilambda(evalImplementation(impl, px)); } -const cached<failable<ilambda, std::string> > readImplementation(const std::string& path) { - const lambda<failable<ilambda, std::string>(std::string)> ri(readLatestImplementation); +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), curry(ft, path)); + return cached<failable<ilambda, std::string> >(curry(ri, path, px), curry(ft, path)); } } diff --git a/sca-cpp/trunk/modules/server/http-test b/sca-cpp/trunk/modules/server/server-test index 6d23911c31..9c517f38b6 100755 --- a/sca-cpp/trunk/modules/server/http-test +++ b/sca-cpp/trunk/modules/server/server-test @@ -25,8 +25,15 @@ cat >>tmp/conf/httpd.conf <<EOF <Location /test> SetHandler mod_tuscany_eval SCAContribution `pwd`/ -SCAComposite httpd-test.composite -SCAComponent httpd-test +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 @@ -34,10 +41,10 @@ apachectl -k start -d `pwd`/tmp sleep 1 # Test -./client-test +./client-test 2>/dev/null rc=$? # Cleanup apachectl -k stop -d `pwd`/tmp -sleep 2 +sleep 1 return $rc diff --git a/sca-cpp/trunk/modules/server/httpd-test.scm b/sca-cpp/trunk/modules/server/server-test.scm index 0566eaf36f..0566eaf36f 100644 --- a/sca-cpp/trunk/modules/server/httpd-test.scm +++ b/sca-cpp/trunk/modules/server/server-test.scm diff --git a/sca-cpp/trunk/modules/server/wiring-test b/sca-cpp/trunk/modules/server/wiring-test index c50732ddb2..5f77d4c6f8 100755 --- a/sca-cpp/trunk/modules/server/wiring-test +++ b/sca-cpp/trunk/modules/server/wiring-test @@ -27,21 +27,21 @@ cat >>tmp/conf/httpd.conf <<EOF <Location /test> SetHandler mod_tuscany_eval SCAContribution `pwd`/ -SCAComposite httpd-test.composite -SCAComponent httpd-test +SCAComposite domain-test.composite +SCAComponent server-test </Location> <Location /client> SetHandler mod_tuscany_eval -SCAContribution /home/delfinoj/SCAZone/Source/tuscany-cpp/sca/modules/http/ -SCAComposite httpd-test.composite -SCAComponent httpd-client +SCAContribution `pwd`/ +SCAComposite domain-test.composite +SCAComponent client-test </Location> <Location /references> SetHandler mod_tuscany_wiring SCAContribution `pwd`/ -SCAComposite httpd-test.composite +SCAComposite domain-test.composite </Location> EOF @@ -86,7 +86,7 @@ fi # Cleanup apachectl -k stop -d `pwd`/tmp -sleep 2 +sleep 1 if [ "$rc" = "0" ]; then echo "OK" fi |