diff options
Diffstat (limited to '')
21 files changed, 1239 insertions, 141 deletions
diff --git a/cpp/sca/configure.ac b/cpp/sca/configure.ac index 46584271b4..a799eb4764 100644 --- a/cpp/sca/configure.ac +++ b/cpp/sca/configure.ac @@ -268,7 +268,7 @@ AC_CONFIG_FILES([Makefile modules/Makefile modules/atom/Makefile modules/eval/Makefile - modules/httpd/Makefile + modules/http/Makefile modules/json/Makefile test/Makefile test/store-object/Makefile diff --git a/cpp/sca/etc/git-exclude b/cpp/sca/etc/git-exclude index 70284ba699..450e879202 100644 --- a/cpp/sca/etc/git-exclude +++ b/cpp/sca/etc/git-exclude @@ -54,6 +54,8 @@ Doxyfile *_Wrapper.cpp *_Wrapper.h gmon.out +*~ +valgrind.txt # Specific ignores sca/runtime/extensions/cpp/tools/scagen/docs/ @@ -65,6 +67,7 @@ atom-test eval-test eval-shell json-test +curl-test store-function-test store-object-test store-script-test diff --git a/cpp/sca/kernel/Makefile.am b/cpp/sca/kernel/Makefile.am index bed68e17cd..d3caa16b3b 100644 --- a/cpp/sca/kernel/Makefile.am +++ b/cpp/sca/kernel/Makefile.am @@ -26,3 +26,6 @@ kernel_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 xsd_test_SOURCES = xsd-test.cpp xsd_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 + +TESTS = kernel-test + diff --git a/cpp/sca/modules/Makefile.am b/cpp/sca/modules/Makefile.am index 025a549df3..fef28b5120 100644 --- a/cpp/sca/modules/Makefile.am +++ b/cpp/sca/modules/Makefile.am @@ -15,5 +15,5 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = atom eval httpd json +SUBDIRS = atom eval http json diff --git a/cpp/sca/modules/atom/Makefile.am b/cpp/sca/modules/atom/Makefile.am index 90e3207bb2..5373587c43 100644 --- a/cpp/sca/modules/atom/Makefile.am +++ b/cpp/sca/modules/atom/Makefile.am @@ -21,3 +21,6 @@ INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} atom_test_SOURCES = atom-test.cpp atom_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 + +TESTS = atom-test + diff --git a/cpp/sca/modules/httpd/Makefile.am b/cpp/sca/modules/http/Makefile.am index 13cb3045f6..d34da0822f 100644 --- a/cpp/sca/modules/httpd/Makefile.am +++ b/cpp/sca/modules/http/Makefile.am @@ -15,10 +15,18 @@ # specific language governing permissions and limitations # under the License. +noinst_PROGRAMS = curl-test + libdir=$(prefix)/lib lib_LTLIBRARIES = libmod_tuscany.la -INCLUDES = -I. -I$(top_builddir)/kernel -I${HTTPD_INCLUDE} -I${APR_INCLUDE} -I${LIBXML2_INCLUDE} -I${LIBMOZJS_INCLUDE} +INCLUDES = -I. -I$(top_builddir)/kernel -I${HTTPD_INCLUDE} -I${APR_INCLUDE} -I${LIBXML2_INCLUDE} -I${LIBMOZJS_INCLUDE} -I${CURL_INCLUDE} libmod_tuscany_la_SOURCES = mod.cpp libmod_tuscany_la_LIBADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${LIBMOZJS_LIB} -lmozjs + +curl_test_SOURCES = curl-test.cpp +curl_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${CURL_LIB} -lcurl + +TESTS = httpd-test http-test + diff --git a/cpp/sca/modules/http/curl-test.cpp b/cpp/sca/modules/http/curl-test.cpp new file mode 100644 index 0000000000..4e23a036da --- /dev/null +++ b/cpp/sca/modules/http/curl-test.cpp @@ -0,0 +1,73 @@ +/* + * 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 JSON data conversion functions. + */ + +#include <assert.h> +#include <iostream> +#include <sstream> +#include <string> +#include "slist.hpp" +#include "curl.hpp" + +namespace tuscany { +namespace http { + +bool contains(const std::string& str, const std::string& pattern) { + return str.find(pattern) != str.npos; +} + +std::ostringstream* curlWriter(std::ostringstream* os, const std::string& s) { + (*os) << s; + return os; +} + +const bool testCURL() { + { + std::ostringstream os; + const failable<std::ostringstream*, int> r = get<std::ostringstream*>(curlWriter, &os, "http://localhost:9091"); + assert(hasValue(r)); + assert(contains(os.str(), "It works")); + } + { + std::ostringstream os; + const failable<list<std::string>, int> r = get("http://localhost:9091"); + assert(hasValue(r)); + write(r, os); + assert(contains(os.str(), "It works")); + } + return true; +} + +} +} + +int main() { + std::cout << "Testing..." << std::endl; + + tuscany::http::testCURL(); + + std::cout << "OK" << std::endl; + + return 0; +} diff --git a/cpp/sca/modules/http/curl.hpp b/cpp/sca/modules/http/curl.hpp new file mode 100644 index 0000000000..2ea23010cb --- /dev/null +++ b/cpp/sca/modules/http/curl.hpp @@ -0,0 +1,150 @@ +/* + * 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_curl_hpp +#define tuscany_curl_hpp + +/** + * CURL HTTP client functions. + */ + +#include <curl/curl.h> +#include <curl/types.h> +#include <curl/easy.h> +#include <string> +#include "list.hpp" +#include "value.hpp" +#include "element.hpp" +#include "monad.hpp" + +namespace tuscany { +namespace http { + +/** + * CURL library context, one per process. + */ +class CURLContext { +public: + CURLContext() { + curl_global_init(CURL_GLOBAL_ALL); + } + ~CURLContext() { + curl_global_cleanup(); + } +}; + +CURLContext curlContext; + +/** + * Represents a CURL session handle. + */ +class CURLHandle { +public: + CURLHandle() : h(curl_easy_init()) { + } + ~CURLHandle() { + curl_easy_cleanup(h); + } + + operator CURL*() const { + return h; + } +private: + CURL* h; +}; + +/** + * Context passed to CURL write callback function. + */ +template<typename R> class CURLWriteContext { +public: + CURLWriteContext(const lambda<R(R, std::string)>& reduce, const R& accum) : reduce(reduce), accum(accum) { + } + const lambda<R(R, std::string)> reduce; + R accum; +}; + +/** + * Called by CURL to write received data. + */ +template<typename R> size_t writeCallback(void *ptr, size_t size, size_t nmemb, void *data) { + CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data)); + const size_t realsize = size * nmemb; + wcx.accum = wcx.reduce(wcx.accum, std::string((const char*)ptr, realsize)); + return realsize; +} + +/** + * Called by CURL to write received header data. + */ +template<typename R> size_t headerCallback(void *ptr, size_t size, size_t nmemb, void *data) { + CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data)); + const size_t realsize = size * nmemb; + wcx.accum = wcx.reduce(wcx.accum, std::string((const char*)ptr, realsize)); + return realsize; +} + +/** + * HTTP GET, get a resource from a URL. + */ +template<typename R> const failable<R, int> get(const lambda<R(R, std::string)>& reduce, const R& initial, const std::string& url) { + CURLWriteContext<R> wcx(reduce, initial); + + // Init the curl session + CURLHandle ch; + curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + curl_easy_setopt(ch, CURLOPT_URL, url.c_str()); + curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, (size_t (*)(void*, size_t, size_t, void*))writeCallback<R>); + curl_easy_setopt(ch, CURLOPT_WRITEDATA, &wcx); + curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, (size_t (*)(void*, size_t, size_t, void*))headerCallback<R>); + curl_easy_setopt(ch, CURLOPT_HEADERDATA, &wcx); + + // Perform the HTTP GET + const CURLcode rc = curl_easy_perform(ch); + if (rc) + return rc; + + // Return the HTTP return code or content + long httprc; + curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc); + if (httprc != 200) + return httprc; + return wcx.accum; +} + +/** + * HTTP GET, get a list of values representing a resource from a URL. + */ +const list<std::string> writeStringList(const list<std::string>& listSoFar, const std::string& s) { + return cons(s, listSoFar); +} + +const failable<list<std::string>, int> get(const std::string& url) { + const failable<list<std::string>, int> r = get<list<std::string> >(writeStringList, list<std::string>(), url); + if (!hasValue(r)) + return r; + return reverse(list<std::string>(r)); +} + +} +} + +#endif /* tuscany_curl_hpp */ diff --git a/cpp/sca/modules/http/http-test b/cpp/sca/modules/http/http-test new file mode 100755 index 0000000000..b0dd21cbd1 --- /dev/null +++ b/cpp/sca/modules/http/http-test @@ -0,0 +1,34 @@ +#!/bin/sh + +# 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. + +mkdir -p tmp +mkdir -p tmp/conf +cp test-conf/* tmp/conf +cat >tmp/conf/httpd.conf <<EOF +ServerName 127.0.0.1 +Listen 9091 +DocumentRoot `pwd`/test-htdocs +EOF +mkdir -p tmp/logs +apachectl -k start -d `pwd`/tmp +sleep 1 +./curl-test +rc=$? +apachectl -k stop -d `pwd`/tmp +return $rc diff --git a/cpp/sca/modules/http/httpd-test b/cpp/sca/modules/http/httpd-test new file mode 100755 index 0000000000..3e4c5f82de --- /dev/null +++ b/cpp/sca/modules/http/httpd-test @@ -0,0 +1,38 @@ +#!/bin/sh + +# 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. + +echo "Testing..." +mkdir -p tmp +mkdir -p tmp/conf +cp test-conf/* tmp/conf +cat >tmp/conf/httpd.conf <<EOF +ServerName 127.0.0.1 +Listen 9090 +DocumentRoot `pwd`/test-htdocs +EOF +mkdir -p tmp/logs +apachectl -k start -d `pwd`/tmp +sleep 1 +curl http://localhost:9090/index.html 2>&1 | grep "It works" >/dev/null +rc=$? +apachectl -k stop -d `pwd`/tmp +if [ "$rc" = "0" ]; then + echo "OK" +fi +return $rc diff --git a/cpp/sca/modules/httpd/mod.cpp b/cpp/sca/modules/http/mod.cpp index 81e12934e7..88891a668c 100644 --- a/cpp/sca/modules/httpd/mod.cpp +++ b/cpp/sca/modules/http/mod.cpp @@ -52,6 +52,7 @@ #include "value.hpp" #include "element.hpp" #include "monad.hpp" +#include "../atom/atom.hpp" #include "../json/json.hpp" #include "../eval/driver.hpp" @@ -60,6 +61,7 @@ extern module AP_MODULE_DECLARE_DATA mod_tuscany; } namespace tuscany { +namespace httpd { /** * Server configuration. @@ -106,13 +108,36 @@ const std::string implementation(request_rec* r) { /** * Returns an HTTP request path as a list of strings. */ -const list<std::string> path(const request_rec* r) { +const list<std::string> pathTokens(const request_rec* r) { const char* p = r->path_info; if (p == NULL || p[0] == '\0') return list<std::string>(); return tokenize("/", p + 1); } +const list<value> pathValues(const list<std::string>& l) { + if (isNil(l)) + return list<value>(); + return cons<value>(car(l), pathValues(cdr(l))); +} + +const list<value> path(const request_rec* r) { + return pathValues(pathTokens(r)); +} + +/** + * Return the content type of a request. + */ +const char* optional(const char* s) { + if (s == NULL) + return "(null)"; + return s; +} + +const std::string contentType(const request_rec* r) { + return optional(apr_table_get(r->headers_in, "Content-Type")); +} + /** * Log HTTP request info to standard out for now, for debugging purposes. */ @@ -123,12 +148,6 @@ int logHeader(void* r, const char* key, const char* value) { return 1; } -const char* optional(const char* s) { - if (s == NULL) - return "(null)"; - return s; -} - const bool logRequest(request_rec* r) { std::cout << "mod-tuscany..." << std::endl; std::cout << "tuscany home: " << home(r) << std::endl; @@ -137,23 +156,49 @@ const bool logRequest(request_rec* r) { 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: " << optional(apr_table_get(r->headers_in, "Content-Type")) << 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->uri) << std::endl; std::cout << "path info: " << optional(r->path_info) << std::endl; - std::cout << "path: " << path(r) << std::endl; + std::cout << "path: " << pathTokens(r) << std::endl; std::cout << "args: " << optional(r->args) << std::endl; std::cout.flush(); return true; } -const value evalLoop(std::istream& is, const value& req, Env& globalEnv) { - value in = read(is); +/** + * Evaluate an expression against a component implementation. + */ +const value evalExprLoop(std::istream& is, const value& req, eval::Env& globalEnv) { + value in = eval::read(is); if (isNil(in)) - return eval(req, globalEnv); - eval(in, globalEnv); - return evalLoop(is, req, globalEnv); + return eval::evalApply(req, globalEnv); + eval::evalApply(in, globalEnv); + return evalExprLoop(is, req, globalEnv); +} + +const failable<value, int> evalExpr(const value& expr, const std::string& contrib, const std::string& impl) { + // Setup the evaluator + eval::Env globalEnv = eval::setupEnvironment(); + std::ostringstream nullos; + eval::setupEvalOut(nullos); + + // Retrieve the component implementation + const std::string path = contrib + impl; + std::ifstream is(path.c_str(), std::ios_base::in); + if (is.fail() || is.bad()) + return HTTP_NOT_FOUND; + + // Evaluate the expr + std::cout<< "expr: " << expr << std::endl; + std::cout.flush(); + const value val = evalExprLoop(is, expr, globalEnv); + std::cout<< "val: " << val << std::endl; + std::cout.flush(); + if (isNil(val)) + return HTTP_INTERNAL_SERVER_ERROR; + return val; } /** @@ -178,67 +223,133 @@ const list<list<value> > queryArgs(const request_rec* r) { const list<value> queryParams(list<list<value> > a) { if (isNil(a)) return list<value>(); - if (car(a) == value("id") || car(a) == value("method")) + const list<value> p = car(a); + if (car(p) == value("id") || car(p) == value("method")) return queryParams(cdr(a)); - return cons(cadr(car(a)), queryParams(cdr(a))); + return cons(cadr(p), queryParams(cdr(a))); } /** - * Handle an HTTP GET request. + * Convert a value to a JSON result. */ -const int get(request_rec* r) { - - // Setup the script evaluator - Env globalEnv = setupEnvironment(); - std::ostringstream nullos; - setupEvalOut(nullos); - - // Open the component implementation - const std::string impl = contribution(r) + implementation(r); - std::ifstream is(impl.c_str(), std::ios_base::in); - if (is.fail() || is.bad()) - return HTTP_NOT_FOUND; +const failable<list<std::string>, int> jsonResult(json::JSONContext& cx, const value& id, const failable<value, int>& val) { + if (!hasValue(val)) + return int(val); + const list<value> r = mklist<value>(mklist<value>("id", id), mklist<value>("result", val)); + failable<list<std::string>, std::string> ls = json::write(cx, valuesToElements(r)); + if (!hasValue(ls)) + return HTTP_INTERNAL_SERVER_ERROR; + std::cout<< "content: " << std::endl; + write(ls, std::cout); + std::cout<< std::endl; + std::cout.flush(); + return list<std::string>(ls); +} - // Extract the request id, method and params from the query string - const list<list<value> > args = queryArgs(r); - const value id = cadr(assoc(value("id"), args)); - const value method = std::string(cadr(assoc(value("method"), args))).c_str(); - const list<value> params = queryParams(args); +/** + * Convert a value to an ATOM entry. + */ +const list<value> feedEntryResult(const list<value> e) { + return cons(car(e), cons(cadr(e), valuesToElements(mklist<value>(cons<value>("item", (list<value>)caddr(e)))))); +} - // Build expr to evaluate - const value expr = cons<value>(method, params); - std::cout<< "expr: " << expr << std::endl; - std::cout.flush(); +/** + * Convert a value to an ATOM feed. + */ +const list<value> feedEntriesResults(const list<value> e) { + if (isNil(e)) + return list<value>(); + return cons<value>(feedEntryResult(car(e)), feedEntriesResults(cdr(e))); +} - // Evaluate the expr - const tuscany::value val = evalLoop(is, expr, globalEnv); - if (isNil(val)) +const failable<list<std::string>, int> feedResult(const failable<value, int>& val) { + if (!hasValue(val)) + return int(val); + const value v = val; + list<value> f = cons(car<value>(v), cons<value>(cadr<value>(v), feedEntriesResults(cddr<value>(v)))); + failable<list<std::string>, std::string> ls = atom::writeFeed(f); + if (!hasValue(ls)) return HTTP_INTERNAL_SERVER_ERROR; - std::cout<< "val: " << val << std::endl; - std::cout.flush(); + return list<std::string>(ls); +} - // Convert the expr value to JSON - const JSONContext cx; - failable<list<std::string>, std::string> jsval = writeJSON(cx, mklist<value>(mklist<value>("id", id), mklist<value>("result", val))); - if (!hasValue(jsval)) +/** + * Convert a value to an ATOM entry result. + */ +const failable<list<std::string>, int> entryResult(const failable<value, int>& val) { + if (!hasValue(val)) + return int(val); + const value v = val; + list<value> e = feedEntryResult(v); + std::cout<< "entry: " << e << std::endl; + failable<list<std::string>, std::string> ls = atom::writeEntry(e); + if (!hasValue(ls)) return HTTP_INTERNAL_SERVER_ERROR; + return list<std::string>(ls); +} - // Send the response - ap_set_content_type(r, "application/json-rpc"); +/** + * Write an HTTP result. + */ +const int writeResult(const failable<list<std::string>, int> ls, const std::string& ct, request_rec* r) { + if (!hasValue(ls)) + return ls; std::ostringstream os; - write(jsval, os); - std::string sval = os.str(); - std::string etag(ap_md5(r->pool, (const unsigned char*)sval.c_str())); + write(ls, os); + std::cout<< "content: " << os.str() << std::endl; + std::cout.flush(); + + 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"); - if (match != NULL && etag == match) - r->status = HTTP_NOT_MODIFIED; apr_table_setn(r->headers_out, "ETag", etag.c_str()); - ap_rputs(sval.c_str(), r); - + if (match != NULL && etag == match) { + r->status = HTTP_NOT_MODIFIED; + return OK; + } + ap_set_content_type(r, ct.c_str()); + ap_rputs(std::string(os.str()).c_str(), r); return OK; } /** + * Handle an HTTP GET. + */ +const int get(request_rec* r) { + + // Inspect the query string + const list<list<value> > args = queryArgs(r); + const list<value> ia = assoc(value("id"), args); + const list<value> ma = assoc(value("method"), args); + + // Evaluate a JSON-RPC request and return a JSON result + if (!isNil(ia) && !isNil(ma)) { + + // Extract the request id, method and params + const value id = cadr(ia); + const value method = std::string(cadr(ma)).c_str(); + const list<value> params = queryParams(args); + + // Evaluate the request expression + const failable<value, int> val = evalExpr(cons(method, params), contribution(r), implementation(r)); + + // Return JSON result + json::JSONContext cx; + return writeResult(jsonResult(cx, id, val), "application/json-rpc", r); + } + + // Evaluate an ATOM GET request and return an ATOM feed + if (length(path(r)) < 2) { + const failable<value, int> val = evalExpr(cons<value>("getall"), contribution(r), implementation(r)); + return writeResult(feedResult(val), "application/atom+xml", r); + } + + // Evaluate an ATOM GET and return an ATOM entry + const failable<value, int> val = evalExpr(cons<value>("get", cdr(path(r))), contribution(r), implementation(r)); + return writeResult(entryResult(val), "application/atom+xml", r); + +} + +/** * Read the content of a POST. */ const list<std::string> read(request_rec* r) { @@ -259,71 +370,83 @@ const list<list<value> > postArgs(list<value> a) { return cons(l, postArgs(cdr(a))); } +const char* url(const std::string& loc, request_rec* r) { + std::string u = r->uri; + u.append("/"); + u.append(loc); + return ap_construct_url(r->pool, u.c_str(), r); +} + /** - * Handle an HTTP POST request. + * Convert an ATOM entry to a value. */ -const int post(request_rec* r) { - - // Setup the script evaluator - Env globalEnv = setupEnvironment(); - std::ostringstream nullos; - setupEvalOut(nullos); - - // Open the component implementation - const std::string impl = contribution(r) + implementation(r); - std::ifstream is(impl.c_str(), std::ios_base::in); - if (is.fail() || is.bad()) - return HTTP_NOT_FOUND; +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)))); +} - // Read the JSON request - const list<std::string> req = read(r); - JSONContext cx; - const list<value> json = elementsToValues(readJSON(cx, req)); - const list<list<value> > args = postArgs(json); +/** + * Handle an HTTP POST. + */ +const int post(request_rec* r) { + const std::string ct = contentType(r); - // Extract the request id, method and params - const value id = cadr(assoc(value("id"), args)); - const value method = std::string(cadr(assoc(value("method"), args))).c_str(); - const list<value> params = (list<value>)cadr(assoc(value("params"), args)); + // Evaluate a JSON-RPC request and return a JSON result + if (ct.find("application/json-rpc") != std::string::npos || ct.find("text/plain") != std::string::npos) { + json::JSONContext cx; + const list<value> json = elementsToValues(json::read(cx, read(r))); + const list<list<value> > args = postArgs(json); - // Build expr to evaluate - const value expr = cons<value>(method, params); - std::cout<< "expr: " << expr << std::endl; - std::cout.flush(); + // Extract the request id, method and params + const value id = cadr(assoc(value("id"), args)); + const value method = std::string(cadr(assoc(value("method"), args))).c_str(); + const list<value> params = (list<value>)cadr(assoc(value("params"), args)); - // Evaluate the expr - const tuscany::value val = evalLoop(is, expr, globalEnv); - if (isNil(val)) - return HTTP_INTERNAL_SERVER_ERROR; - std::cout<< "val: " << val << std::endl; - std::cout.flush(); + // Evaluate the request expression + const failable<value, int> val = evalExpr(cons(method, params), contribution(r), implementation(r)); - // Convert the expr value to JSON - const list<value> result = valuesToElements(mklist<value>(mklist<value>("id", id), mklist<value>("result", val))); - failable<list<std::string>, std::string> jsval = writeJSON(cx, result); - if (!hasValue(jsval)) - return HTTP_INTERNAL_SERVER_ERROR; + // Return JSON result + return writeResult(jsonResult(cx, id, val), "application/json-rpc", r); + } - // Send the JSON response - ap_set_content_type(r, "application/json-rpc"); - std::ostringstream os; - write(jsval, os); - ap_rputs(os.str().c_str(), r); + // Evaluate an ATOM POST request and return the created resource location + if (ct.find("application/atom+xml") != std::string::npos) { + const list<std::string> c = read(r); + std::cout << "POST content: " << c << std::endl; + const list<value> e = atom::readEntry(c); + std::cout << "POST entry: " << e << std::endl; + const value v = feedEntry(e); + std::cout << "POST param: " << v << std::endl; + + // Evaluate the request expression + const failable<value, int> val = evalExpr(mklist<value>("post", mklist(v)), contribution(r), implementation(r)); + + const char* u = url("abcd", r); + apr_table_setn(r->headers_out, "Location", u); + apr_table_setn(r->headers_out, "Content-Location", u); + return HTTP_CREATED; + } - return OK; + return HTTP_NOT_IMPLEMENTED; } /** - * Handle an HTTP PUT request. + * Handle an HTTP PUT. */ const int put(request_rec* r) { + // TODO later return OK; } /** - * Handle an HTTP DELETE request. + * Handle an HTTP DELETE. */ const int del(request_rec* r) { + + // Evaluate an ATOM delete request + const failable<value, int> val = evalExpr(cons<value>("delete", cdr(path(r))), contribution(r), implementation(r)); + if (!hasValue(val)) + return val; return OK; } @@ -426,23 +549,24 @@ void registerHooks(apr_pool_t *p) { } } +} extern "C" { module AP_MODULE_DECLARE_DATA mod_tuscany = { STANDARD20_MODULE_STUFF, // dir config - tuscany::makeDirConf, + tuscany::httpd::makeDirConf, // dir merger, default is to override NULL, // server config - tuscany::makeServerConf, + tuscany::httpd::makeServerConf, // merge server config NULL, // command table - tuscany::commands, + tuscany::httpd::commands, // register hooks - tuscany::registerHooks + tuscany::httpd::registerHooks }; } diff --git a/cpp/sca/modules/http/test-conf/mime.types b/cpp/sca/modules/http/test-conf/mime.types new file mode 100644 index 0000000000..4279f51bca --- /dev/null +++ b/cpp/sca/modules/http/test-conf/mime.types @@ -0,0 +1,607 @@ +# 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. + +# This file controls what Internet media types are sent to the client for +# given file extension(s). Sending the correct media type to the client +# is important so they know how to handle the content of the file. +# Extra types can either be added here or by using an AddType directive +# in your config files. For more information about Internet media types, +# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type +# registry is at <http://www.iana.org/assignments/media-types/>. + +# MIME type Extensions +application/activemessage +application/andrew-inset ez +application/applefile +application/atom+xml atom +application/atomicmail +application/batch-smtp +application/beep+xml +application/cals-1840 +application/cnrp+xml +application/commonground +application/cpl+xml +application/cybercash +application/dca-rft +application/dec-dx +application/dvcs +application/edi-consent +application/edifact +application/edi-x12 +application/eshop +application/font-tdpfr +application/http +application/hyperstudio +application/iges +application/index +application/index.cmd +application/index.obj +application/index.response +application/index.vnd +application/iotp +application/ipp +application/isup +application/mac-binhex40 hqx +application/mac-compactpro cpt +application/macwriteii +application/marc +application/mathematica +application/mathml+xml mathml +application/msword doc +application/news-message-id +application/news-transmission +application/ocsp-request +application/ocsp-response +application/octet-stream bin dms lha lzh exe class so dll dmg +application/oda oda +application/ogg ogg +application/parityfec +application/pdf pdf +application/pgp-encrypted +application/pgp-keys +application/pgp-signature +application/pkcs10 +application/pkcs7-mime +application/pkcs7-signature +application/pkix-cert +application/pkix-crl +application/pkixcmp +application/postscript ai eps ps +application/prs.alvestrand.titrax-sheet +application/prs.cww +application/prs.nprend +application/prs.plucker +application/qsig +application/rdf+xml rdf +application/reginfo+xml +application/remote-printing +application/riscos +application/rtf +application/sdp +application/set-payment +application/set-payment-initiation +application/set-registration +application/set-registration-initiation +application/sgml +application/sgml-open-catalog +application/sieve +application/slate +application/smil smi smil +application/srgs gram +application/srgs+xml grxml +application/timestamp-query +application/timestamp-reply +application/tve-trigger +application/vemmi +application/vnd.3gpp.pic-bw-large +application/vnd.3gpp.pic-bw-small +application/vnd.3gpp.pic-bw-var +application/vnd.3gpp.sms +application/vnd.3m.post-it-notes +application/vnd.accpac.simply.aso +application/vnd.accpac.simply.imp +application/vnd.acucobol +application/vnd.acucorp +application/vnd.adobe.xfdf +application/vnd.aether.imp +application/vnd.amiga.ami +application/vnd.anser-web-certificate-issue-initiation +application/vnd.anser-web-funds-transfer-initiation +application/vnd.audiograph +application/vnd.blueice.multipass +application/vnd.bmi +application/vnd.businessobjects +application/vnd.canon-cpdl +application/vnd.canon-lips +application/vnd.cinderella +application/vnd.claymore +application/vnd.commerce-battelle +application/vnd.commonspace +application/vnd.contact.cmsg +application/vnd.cosmocaller +application/vnd.criticaltools.wbs+xml +application/vnd.ctc-posml +application/vnd.cups-postscript +application/vnd.cups-raster +application/vnd.cups-raw +application/vnd.curl +application/vnd.cybank +application/vnd.data-vision.rdz +application/vnd.dna +application/vnd.dpgraph +application/vnd.dreamfactory +application/vnd.dxr +application/vnd.ecdis-update +application/vnd.ecowin.chart +application/vnd.ecowin.filerequest +application/vnd.ecowin.fileupdate +application/vnd.ecowin.series +application/vnd.ecowin.seriesrequest +application/vnd.ecowin.seriesupdate +application/vnd.enliven +application/vnd.epson.esf +application/vnd.epson.msf +application/vnd.epson.quickanime +application/vnd.epson.salt +application/vnd.epson.ssf +application/vnd.ericsson.quickcall +application/vnd.eudora.data +application/vnd.fdf +application/vnd.ffsns +application/vnd.fints +application/vnd.flographit +application/vnd.framemaker +application/vnd.fsc.weblaunch +application/vnd.fujitsu.oasys +application/vnd.fujitsu.oasys2 +application/vnd.fujitsu.oasys3 +application/vnd.fujitsu.oasysgp +application/vnd.fujitsu.oasysprs +application/vnd.fujixerox.ddd +application/vnd.fujixerox.docuworks +application/vnd.fujixerox.docuworks.binder +application/vnd.fut-misnet +application/vnd.grafeq +application/vnd.groove-account +application/vnd.groove-help +application/vnd.groove-identity-message +application/vnd.groove-injector +application/vnd.groove-tool-message +application/vnd.groove-tool-template +application/vnd.groove-vcard +application/vnd.hbci +application/vnd.hhe.lesson-player +application/vnd.hp-hpgl +application/vnd.hp-hpid +application/vnd.hp-hps +application/vnd.hp-pcl +application/vnd.hp-pclxl +application/vnd.httphone +application/vnd.hzn-3d-crossword +application/vnd.ibm.afplinedata +application/vnd.ibm.electronic-media +application/vnd.ibm.minipay +application/vnd.ibm.modcap +application/vnd.ibm.rights-management +application/vnd.ibm.secure-container +application/vnd.informix-visionary +application/vnd.intercon.formnet +application/vnd.intertrust.digibox +application/vnd.intertrust.nncp +application/vnd.intu.qbo +application/vnd.intu.qfx +application/vnd.irepository.package+xml +application/vnd.is-xpr +application/vnd.japannet-directory-service +application/vnd.japannet-jpnstore-wakeup +application/vnd.japannet-payment-wakeup +application/vnd.japannet-registration +application/vnd.japannet-registration-wakeup +application/vnd.japannet-setstore-wakeup +application/vnd.japannet-verification +application/vnd.japannet-verification-wakeup +application/vnd.jisp +application/vnd.kde.karbon +application/vnd.kde.kchart +application/vnd.kde.kformula +application/vnd.kde.kivio +application/vnd.kde.kontour +application/vnd.kde.kpresenter +application/vnd.kde.kspread +application/vnd.kde.kword +application/vnd.kenameaapp +application/vnd.koan +application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop +application/vnd.llamagraphics.life-balance.exchange+xml +application/vnd.lotus-1-2-3 +application/vnd.lotus-approach +application/vnd.lotus-freelance +application/vnd.lotus-notes +application/vnd.lotus-organizer +application/vnd.lotus-screencam +application/vnd.lotus-wordpro +application/vnd.mcd +application/vnd.mediastation.cdkey +application/vnd.meridian-slingshot +application/vnd.micrografx.flo +application/vnd.micrografx.igx +application/vnd.mif mif +application/vnd.minisoft-hp3000-save +application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf +application/vnd.mobius.dis +application/vnd.mobius.mbk +application/vnd.mobius.mqy +application/vnd.mobius.msl +application/vnd.mobius.plc +application/vnd.mobius.txf +application/vnd.mophun.application +application/vnd.mophun.certificate +application/vnd.motorola.flexsuite +application/vnd.motorola.flexsuite.adsi +application/vnd.motorola.flexsuite.fis +application/vnd.motorola.flexsuite.gotap +application/vnd.motorola.flexsuite.kmr +application/vnd.motorola.flexsuite.ttc +application/vnd.motorola.flexsuite.wem +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry +application/vnd.ms-asf +application/vnd.ms-excel xls +application/vnd.ms-lrm +application/vnd.ms-powerpoint ppt +application/vnd.ms-project +application/vnd.ms-tnef +application/vnd.ms-works +application/vnd.ms-wpl +application/vnd.mseq +application/vnd.msign +application/vnd.music-niff +application/vnd.musician +application/vnd.netfpx +application/vnd.noblenet-directory +application/vnd.noblenet-sealer +application/vnd.noblenet-web +application/vnd.novadigm.edm +application/vnd.novadigm.edx +application/vnd.novadigm.ext +application/vnd.obn +application/vnd.osa.netdeploy +application/vnd.palm +application/vnd.pg.format +application/vnd.pg.osasli +application/vnd.powerbuilder6 +application/vnd.powerbuilder6-s +application/vnd.powerbuilder7 +application/vnd.powerbuilder7-s +application/vnd.powerbuilder75 +application/vnd.powerbuilder75-s +application/vnd.previewsystems.box +application/vnd.publishare-delta-tree +application/vnd.pvi.ptid1 +application/vnd.pwg-multiplexed +application/vnd.pwg-xhtml-print+xml +application/vnd.quark.quarkxpress +application/vnd.rapid +application/vnd.s3sms +application/vnd.sealed.net +application/vnd.seemail +application/vnd.shana.informed.formdata +application/vnd.shana.informed.formtemplate +application/vnd.shana.informed.interchange +application/vnd.shana.informed.package +application/vnd.smaf +application/vnd.sss-cod +application/vnd.sss-dtf +application/vnd.sss-ntf +application/vnd.street-stream +application/vnd.svd +application/vnd.swiftview-ics +application/vnd.triscape.mxs +application/vnd.trueapp +application/vnd.truedoc +application/vnd.ufdl +application/vnd.uplanet.alert +application/vnd.uplanet.alert-wbxml +application/vnd.uplanet.bearer-choice +application/vnd.uplanet.bearer-choice-wbxml +application/vnd.uplanet.cacheop +application/vnd.uplanet.cacheop-wbxml +application/vnd.uplanet.channel +application/vnd.uplanet.channel-wbxml +application/vnd.uplanet.list +application/vnd.uplanet.list-wbxml +application/vnd.uplanet.listcmd +application/vnd.uplanet.listcmd-wbxml +application/vnd.uplanet.signal +application/vnd.vcx +application/vnd.vectorworks +application/vnd.vidsoft.vidconference +application/vnd.visio +application/vnd.visionary +application/vnd.vividence.scriptfile +application/vnd.vsf +application/vnd.wap.sic +application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo +application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf +application/vnd.wv.csp+wbxml +application/vnd.xara +application/vnd.xfdl +application/vnd.yamaha.hv-dic +application/vnd.yamaha.hv-script +application/vnd.yamaha.hv-voice +application/vnd.yellowriver-custom-menu +application/voicexml+xml vxml +application/watcherinfo+xml +application/whoispp-query +application/whoispp-response +application/wita +application/wordperfect5.1 +application/x-bcpio bcpio +application/x-cdlink vcd +application/x-chess-pgn pgn +application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-director dcr dir dxr +application/x-dvi dvi +application/x-futuresplash spl +application/x-gtar gtar +application/x-gzip +application/x-hdf hdf +application/x-javascript js +application/x-koan skp skd skt skm +application/x-latex latex +application/x-netcdf nc cdf +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-stuffit sit +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-texinfo texinfo texi +application/x-troff t tr roff +application/x-troff-man man +application/x-troff-me me +application/x-troff-ms ms +application/x-ustar ustar +application/x-wais-source src +application/x400-bp +application/xhtml+xml xhtml xht +application/xslt+xml xslt +application/xml xml xsl +application/xml-dtd dtd +application/xml-external-parsed-entity +application/zip zip +audio/32kadpcm +audio/amr +audio/amr-wb +audio/basic au snd +audio/cn +audio/dat12 +audio/dsr-es201108 +audio/dvi4 +audio/evrc +audio/evrc0 +audio/g722 +audio/g.722.1 +audio/g723 +audio/g726-16 +audio/g726-24 +audio/g726-32 +audio/g726-40 +audio/g728 +audio/g729 +audio/g729D +audio/g729E +audio/gsm +audio/gsm-efr +audio/l8 +audio/l16 +audio/l20 +audio/l24 +audio/lpc +audio/midi mid midi kar +audio/mpa +audio/mpa-robust +audio/mp4a-latm +audio/mpeg mpga mp2 mp3 +audio/parityfec +audio/pcma +audio/pcmu +audio/prs.sid +audio/qcelp +audio/red +audio/smv +audio/smv0 +audio/telephone-event +audio/tone +audio/vdvi +audio/vnd.3gpp.iufp +audio/vnd.cisco.nse +audio/vnd.cns.anp1 +audio/vnd.cns.inf1 +audio/vnd.digital-winds +audio/vnd.everad.plj +audio/vnd.lucent.voice +audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 +audio/vnd.nuera.ecelp7470 +audio/vnd.nuera.ecelp9600 +audio/vnd.octel.sbc +audio/vnd.qcelp +audio/vnd.rhetorex.32kadpcm +audio/vnd.vmx.cvsd +audio/x-aiff aif aiff aifc +audio/x-alaw-basic +audio/x-mpegurl m3u +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin +application/vnd.rn-realmedia rm +audio/x-wav wav +chemical/x-pdb pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +image/g3fax +image/gif gif +image/ief ief +image/jpeg jpeg jpg jpe +image/naplps +image/png png +image/prs.btif +image/prs.pti +image/svg+xml svg +image/t38 +image/tiff tiff tif +image/tiff-fx +image/vnd.cns.inf2 +image/vnd.djvu djvu djv +image/vnd.dwg +image/vnd.dxf +image/vnd.fastbidsheet +image/vnd.fpx +image/vnd.fst +image/vnd.fujixerox.edmics-mmr +image/vnd.fujixerox.edmics-rlc +image/vnd.globalgraphics.pgb +image/vnd.mix +image/vnd.ms-modi +image/vnd.net-fpx +image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff +image/x-cmu-raster ras +image/x-icon ico +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +message/delivery-status +message/disposition-notification +message/external-body +message/http +message/news +message/partial +message/rfc822 +message/s-http +message/sip +message/sipfrag +model/iges igs iges +model/mesh msh mesh silo +model/vnd.dwf +model/vnd.flatland.3dml +model/vnd.gdl +model/vnd.gs-gdl +model/vnd.gtw +model/vnd.mts +model/vnd.parasolid.transmit.binary +model/vnd.parasolid.transmit.text +model/vnd.vtu +model/vrml wrl vrml +multipart/alternative +multipart/appledouble +multipart/byteranges +multipart/digest +multipart/encrypted +multipart/form-data +multipart/header-set +multipart/mixed +multipart/parallel +multipart/related +multipart/report +multipart/signed +multipart/voice-message +text/calendar ics ifb +text/css css +text/directory +text/enriched +text/html html htm +text/parityfec +text/plain asc txt +text/prs.lines.tag +text/rfc822-headers +text/richtext rtx +text/rtf rtf +text/sgml sgml sgm +text/t140 +text/tab-separated-values tsv +text/uri-list +text/vnd.abc +text/vnd.curl +text/vnd.dmclientscript +text/vnd.fly +text/vnd.fmi.flexstor +text/vnd.in3d.3dml +text/vnd.in3d.spot +text/vnd.iptc.nitf +text/vnd.iptc.newsml +text/vnd.latex-z +text/vnd.motorola.reflex +text/vnd.ms-mediapackage +text/vnd.net2phone.commcenter.command +text/vnd.sun.j2me.app-descriptor +text/vnd.wap.si +text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-setext etx +text/xml +text/xml-external-parsed-entity +video/bmpeg +video/bt656 +video/celb +video/dv +video/h261 +video/h263 +video/h263-1998 +video/h263-2000 +video/jpeg +video/mp1s +video/mp2p +video/mp2t +video/mp4v-es +video/mpv +video/mpeg mpeg mpg mpe +video/nv +video/parityfec +video/pointer +video/quicktime qt mov +video/smpte292m +video/vnd.fvt +video/vnd.motorola.video +video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.nokia.interleaved-multimedia +video/vnd.objectvideo +video/vnd.vivo +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/cpp/sca/modules/http/test-htdocs/index.html b/cpp/sca/modules/http/test-htdocs/index.html new file mode 100644 index 0000000000..1bfb3e30c2 --- /dev/null +++ b/cpp/sca/modules/http/test-htdocs/index.html @@ -0,0 +1,21 @@ +<!-- + 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. +--> + +<html><body><h1>It works!</h1></body></html> + diff --git a/cpp/sca/modules/json/Makefile.am b/cpp/sca/modules/json/Makefile.am index d14b5165e6..059eac97a2 100644 --- a/cpp/sca/modules/json/Makefile.am +++ b/cpp/sca/modules/json/Makefile.am @@ -22,3 +22,5 @@ INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${LIBMOZJS_INCLUD json_test_SOURCES = json-test.cpp json_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${LIBMOZJS_LIB} -lmozjs +TESTS = json-test + diff --git a/cpp/sca/test/store-function/Makefile.am b/cpp/sca/test/store-function/Makefile.am index b63381c0cf..d969e01f59 100644 --- a/cpp/sca/test/store-function/Makefile.am +++ b/cpp/sca/test/store-function/Makefile.am @@ -26,3 +26,5 @@ store_function_test_LDADD = -L${LIBXML2_LIB} -lxml2 -lpthread EXTRA_DIST = *.composite store_function_DATA = *.composite +TESTS = store-function-test + diff --git a/cpp/sca/test/store-object/Makefile.am b/cpp/sca/test/store-object/Makefile.am index c79bf6ebde..d4ad4e5fc0 100644 --- a/cpp/sca/test/store-object/Makefile.am +++ b/cpp/sca/test/store-object/Makefile.am @@ -26,3 +26,5 @@ store_object_test_LDADD = -L${LIBXML2_LIB} -lxml2 -lpthread EXTRA_DIST = *.composite store_object_DATA = *.composite +TESTS = store-object-test + diff --git a/cpp/sca/test/store-script/Makefile.am b/cpp/sca/test/store-script/Makefile.am index aded08f6b3..2bd969b5ba 100644 --- a/cpp/sca/test/store-script/Makefile.am +++ b/cpp/sca/test/store-script/Makefile.am @@ -18,11 +18,13 @@ store_script_PROGRAMS = store-script-test store_scriptdir=$(prefix)/test/store-script/deploy -INCLUDES = -I. -I$(top_builddir)/kernel -I$(top_builddir)/modules/eval -I${LIBXML2_INCLUDE} +INCLUDES = -I. -I$(top_builddir)/kernel -I$(top_builddir)/modules/eval -I${LIBXML2_INCLUDE} -I${LIBMOZJS_INCLUDE} store_script_test_SOURCES = store-script-test.cpp -store_script_test_LDADD = -L${LIBXML2_LIB} -lxml2 -lpthread +store_script_test_LDADD = -L${LIBXML2_LIB} -lxml2 -lpthread -L${LIBMOZJS_LIB} -lmozjs EXTRA_DIST = *.composite store_script_DATA = *.composite +TESTS = store-script-test + diff --git a/cpp/sca/test/store-script/htdocs/store.html b/cpp/sca/test/store-script/htdocs/store.html index 4a2c65d07c..98d6ec8e8e 100644 --- a/cpp/sca/test/store-script/htdocs/store.html +++ b/cpp/sca/test/store-script/htdocs/store.html @@ -28,7 +28,7 @@ var catalog = new tuscany.sca.Reference("catalog");
//@Reference
- //var shoppingCart = new tuscany.sca.Reference("shoppingCart");
+ var shoppingCart = new tuscany.sca.Reference("shoppingCart");
//@Reference
var shoppingTotal = new tuscany.sca.Reference("shoppingTotal");
@@ -86,7 +86,7 @@ }
function shoppingCart_postResponse(entry) {
- //shoppingCart.get("", shoppingCart_getResponse);
+ shoppingCart.get("", shoppingCart_getResponse);
}
function addToCart() {
@@ -127,7 +127,7 @@ try {
catalog.get(catalog_getResponse);
- //shoppingCart.get("", shoppingCart_getResponse);
+ shoppingCart.get("", shoppingCart_getResponse);
}
catch(e){
alert(e);
diff --git a/cpp/sca/test/store-script/htdocs/store.js b/cpp/sca/test/store-script/htdocs/store.js index 526d36790a..64749ce6c1 100644 --- a/cpp/sca/test/store-script/htdocs/store.js +++ b/cpp/sca/test/store-script/htdocs/store.js @@ -651,7 +651,7 @@ 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/Cart"); +tuscany.sca.referenceMap.shoppingCart = new AtomClient("/ShoppingCart/Cart"); tuscany.sca.referenceMap.shoppingTotal = new JSONRpcClient("/ShoppingCart/Total").Service; tuscany.sca.Reference = function (name) { return tuscany.sca.referenceMap[name]; diff --git a/cpp/sca/test/store-script/store-script-test.cpp b/cpp/sca/test/store-script/store-script-test.cpp index 8eac2f7b8b..2d1891dd14 100644 --- a/cpp/sca/test/store-script/store-script-test.cpp +++ b/cpp/sca/test/store-script/store-script-test.cpp @@ -27,10 +27,16 @@ #include <iostream> #include <fstream> #include <string> +#include "list.hpp" #include "driver.hpp" +#include "slist.hpp" +#include "xml.hpp" +#include "../json/json.hpp" namespace store { +using namespace tuscany; + bool contains(const std::string& str, const std::string& pattern) { return str.find(pattern) != str.npos; } @@ -38,16 +44,16 @@ bool contains(const std::string& str, const std::string& pattern) { bool testScript() { std::ifstream is("store.scm", std::ios_base::in); std::ostringstream os; - tuscany::evalDriverRun(is, os); - assert(contains(os.str(), "List::(List::(List::(Symbol::name, (String::\"apple\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::2.99, ())), ())))), ())")); + eval::evalDriverRun(is, os); + assert(contains(os.str(), "(string::\"Sample Feed\", string::\"123\", (string::\"Item\", string::\"123456789\", ((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Orange\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::3.55))), (string::\"Item\", string::\"123456789\", ((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Apple\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::2.99))))")); return true; } -const tuscany::value evalLoop(std::istream& is, const tuscany::value& req, tuscany::Env& globalEnv) { - tuscany::value in = tuscany::read(is); - if(tuscany::isNil(in)) - return tuscany::eval(req, globalEnv); - tuscany::eval(in, globalEnv); +const value evalLoop(std::istream& is, const value& req, eval::Env& globalEnv) { + value in = eval::read(is); + if(isNil(in)) + return eval::evalApply(req, globalEnv); + eval::evalApply(in, globalEnv); return evalLoop(is, req, globalEnv); } @@ -55,31 +61,30 @@ bool testEval() { { std::ifstream is("store.scm", std::ios_base::in); std::ostringstream os; + eval::setupEvalOut(os); + eval::Env globalEnv = eval::setupEnvironment(); - tuscany::setupEvalOut(os); - tuscany::Env globalEnv = tuscany::setupEnvironment(); - - const tuscany::value req(tuscany::mklist<tuscany::value>("storeui_service", std::string("getcatalog"))); - const tuscany::value res = evalLoop(is, req, globalEnv); + const value req(mklist<value>("storeui_service", std::string("getcatalog"))); + const value val = evalLoop(is, req, globalEnv); - std::ostringstream rs; - rs << res; - assert(contains(rs.str(), "List::(List::(List::(Symbol::name, (String::\"apple\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::2.99, ())), ())))), (List::(List::(Symbol::name, (String::\"orange\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::3.55, ())), ())))), (List::(List::(Symbol::name, (String::\"pear\", ())), (List::(Symbol::currency, (String::\"USD\", ())), (List::(Symbol::symbol, (String::\"$\", ())), (List::(Symbol::price, (Number::1.55, ())), ())))), ())))")); + std::ostringstream vs; + vs << val; + assert(contains(vs.str(),"(((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Apple\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::2.99)), ((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Orange\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::3.55)), ((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Pear\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::1.55)))")); } { std::ifstream is("store.scm", std::ios_base::in); std::ostringstream os; - tuscany::setupEvalOut(os); - tuscany::Env globalEnv = tuscany::setupEnvironment(); + eval::setupEvalOut(os); + eval::Env globalEnv = eval::setupEnvironment(); - const tuscany::value req(tuscany::mklist<tuscany::value>("storeui_service", std::string("gettotal"))); - const tuscany::value res = evalLoop(is, req, globalEnv); + const value req(mklist<value>("storeui_service", std::string("gettotal"))); + const value res = evalLoop(is, req, globalEnv); std::ostringstream rs; rs << res; - assert(contains(rs.str(), "Number::10")); + assert(contains(rs.str(), "number::10")); } return true; } diff --git a/cpp/sca/test/store-script/store.scm b/cpp/sca/test/store-script/store.scm index 323a2ca304..99ae33481c 100644 --- a/cpp/sca/test/store-script/store.scm +++ b/cpp/sca/test/store-script/store.scm @@ -28,9 +28,10 @@ (define code "USD") (define symbol (converter "symbol" code)) - (list (list (list 'name "apple") (list 'currency code) (list 'symbol symbol) (list 'price (convert 2.99))) - (list (list 'name "orange") (list 'currency code) (list 'symbol symbol) (list 'price (convert 3.55))) - (list (list 'name "pear") (list 'currency code) (list 'symbol symbol) (list 'price (convert 1.55))) + (list + (list (list 'javaClass "services.Item") (list 'name "Apple") (list 'currency code) (list 'symbol symbol) (list 'price 2.99)) + (list (list 'javaClass "services.Item") (list 'name "Orange") (list 'currency code) (list 'symbol symbol) (list 'price 3.55)) + (list (list 'javaClass "services.Item") (list 'name "Pear") (list 'currency code) (list 'symbol symbol) (list 'price 1.55)) ) ) @@ -47,11 +48,16 @@ (; "Cart implementation") (define (cart_post content item) - (cons item content) + (cons (cons "Item" (list "123456789" item)) content) ) (define (cart_getall content) - content + (cons "Sample Feed" (cons "123" content)) +) + +(define (cart_getentry id) + (define entry (list (list 'name "Apple") (list 'currency "USD") (list 'symbol "$") (list 'price 2.99))) + (cons "Item" (list id entry)) ) (define (cart_gettotal) @@ -62,6 +68,7 @@ (cond ((equal? op "post") (apply cart_post args)) ((equal? op "getall") (apply cart_getall args)) + ((equal? op "getentry") (apply cart_getentry args)) ((equal? op "gettotal") (apply cart_gettotal args)) ) ) @@ -76,6 +83,10 @@ (cart "getall" content) ) +(define (storeui_getentry cart id) + (cart "getentry" id) +) + (define (storeui_getcatalog catalog) (catalog "get") ) @@ -88,6 +99,7 @@ (cond ((equal? op "post") (apply storeui_post (cons cart args))) ((equal? op "getall") (apply storeui_getcart (cons cart args))) + ((equal? op "getentry") (apply storeui_getentry (cons cart args))) ((equal? op "getcatalog") (apply storeui_getcatalog (cons catalog args))) ((equal? op "gettotal") (apply storeui_gettotal (cons cart args))) ) @@ -104,13 +116,22 @@ (define catalog (storeui_service "getcatalog")) (define empty (list)) (define apple (car catalog)) -(define full (storeui_service "post" empty apple)) -(display (storeui_service "getall" full)) +(define orange (car (cdr catalog))) +(define added1 (storeui_service "post" empty apple)) +(define added2 (storeui_service "post" added1 orange)) +(display (storeui_service "getall" added2)) (display (storeui_service "gettotal")) (; "Store UI JSON-RPC interop test case") (define (system.listMethods) (list "Service.get" "Service.getTotal")) (define (Service.get) (storeui_service "getcatalog")) +(define (.get) (storeui_service "getcatalog")) (define (Service.getTotal) (storeui_service "gettotal")) +(; "Store UI ATOMPub interop test case") + +(define (getall) (storeui_service "getall" added2)) +(define (get id) (storeui_service "getentry" id)) +(define (post entry) (display entry)) + |