You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by js...@apache.org on 2009/11/01 06:25:16 UTC
svn commit: r831640 [1/2] - in /tuscany/cpp/sca: ./ etc/ modules/
modules/atom/ modules/cache/ modules/eval/ modules/http/ modules/http/conf/
modules/http/htdocs/ modules/http/test-conf/ modules/http/test-htdocs/
modules/json/ test/store-script/ test/s...
Author: jsdelfino
Date: Sun Nov 1 05:25:14 2009
New Revision: 831640
URL: http://svn.apache.org/viewvc?rev=831640&view=rev
Log:
Minor refactoring of read/write functions and primitive procs. Added functions to help store data in memcached. Fixes to HTTP support and more tests.
Added:
tuscany/cpp/sca/etc/httpd-ipcrm (contents, props changed)
- copied, changed from r831639, tuscany/cpp/sca/modules/Makefile.am
tuscany/cpp/sca/modules/cache/
tuscany/cpp/sca/modules/cache/Makefile.am
- copied, changed from r831639, tuscany/cpp/sca/modules/Makefile.am
tuscany/cpp/sca/modules/cache/cache-test.cpp
- copied, changed from r831639, tuscany/cpp/sca/modules/http/curl-test.cpp
tuscany/cpp/sca/modules/cache/cache.hpp
tuscany/cpp/sca/modules/cache/memcached-test (contents, props changed)
- copied, changed from r831639, tuscany/cpp/sca/modules/Makefile.am
tuscany/cpp/sca/modules/eval/io.hpp
- copied, changed from r831639, tuscany/cpp/sca/modules/eval/read.hpp
tuscany/cpp/sca/modules/http/conf/
tuscany/cpp/sca/modules/http/conf/mime.types
- copied, changed from r831639, tuscany/cpp/sca/modules/http/test-conf/mime.types
tuscany/cpp/sca/modules/http/htdocs/
tuscany/cpp/sca/modules/http/htdocs/entry.xml
tuscany/cpp/sca/modules/http/htdocs/feed.xml
tuscany/cpp/sca/modules/http/htdocs/index.html
- copied, changed from r831639, tuscany/cpp/sca/modules/http/test-htdocs/index.html
tuscany/cpp/sca/modules/http/htdocs/json-request.txt
tuscany/cpp/sca/modules/http/htdocs/json-result.txt
tuscany/cpp/sca/modules/http/httpd-conf
- copied, changed from r831639, tuscany/cpp/sca/modules/http/http-test
tuscany/cpp/sca/modules/http/httpd-test.scm
tuscany/cpp/sca/test/store-script/store-http-test
- copied, changed from r831639, tuscany/cpp/sca/modules/http/httpd-test
Removed:
tuscany/cpp/sca/modules/eval/read.hpp
tuscany/cpp/sca/modules/http/test-conf/
tuscany/cpp/sca/modules/http/test-htdocs/
Modified:
tuscany/cpp/sca/configure.ac
tuscany/cpp/sca/etc/git-exclude
tuscany/cpp/sca/modules/Makefile.am
tuscany/cpp/sca/modules/atom/atom-test.cpp
tuscany/cpp/sca/modules/atom/atom.hpp
tuscany/cpp/sca/modules/eval/driver.hpp
tuscany/cpp/sca/modules/eval/environment.hpp
tuscany/cpp/sca/modules/eval/eval-test.cpp
tuscany/cpp/sca/modules/eval/eval.hpp
tuscany/cpp/sca/modules/eval/primitive.hpp
tuscany/cpp/sca/modules/http/curl-test.cpp
tuscany/cpp/sca/modules/http/curl.hpp
tuscany/cpp/sca/modules/http/http-test
tuscany/cpp/sca/modules/http/httpd-test
tuscany/cpp/sca/modules/http/mod.cpp
tuscany/cpp/sca/modules/json/json-test.cpp
tuscany/cpp/sca/modules/json/json.hpp
tuscany/cpp/sca/test/store-script/htdocs/store.html
tuscany/cpp/sca/test/store-script/htdocs/store.js
tuscany/cpp/sca/test/store-script/store-script-test.cpp
tuscany/cpp/sca/test/store-script/store.scm
Modified: tuscany/cpp/sca/configure.ac
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/configure.ac?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/configure.ac (original)
+++ tuscany/cpp/sca/configure.ac Sun Nov 1 05:25:14 2009
@@ -267,6 +267,7 @@
kernel/Makefile
modules/Makefile
modules/atom/Makefile
+ modules/cache/Makefile
modules/eval/Makefile
modules/http/Makefile
modules/json/Makefile
Modified: tuscany/cpp/sca/etc/git-exclude
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/etc/git-exclude?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/etc/git-exclude (original)
+++ tuscany/cpp/sca/etc/git-exclude Sun Nov 1 05:25:14 2009
@@ -55,7 +55,6 @@
*_Wrapper.h
gmon.out
*~
-valgrind.txt
# Specific ignores
sca/runtime/extensions/cpp/tools/scagen/docs/
@@ -67,6 +66,7 @@
eval-test
eval-shell
json-test
+cache-test
curl-test
store-function-test
store-object-test
Copied: tuscany/cpp/sca/etc/httpd-ipcrm (from r831639, tuscany/cpp/sca/modules/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/etc/httpd-ipcrm?p2=tuscany/cpp/sca/etc/httpd-ipcrm&p1=tuscany/cpp/sca/modules/Makefile.am&r1=831639&r2=831640&rev=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/Makefile.am (original)
+++ tuscany/cpp/sca/etc/httpd-ipcrm Sun Nov 1 05:25:14 2009
@@ -1,3 +1,5 @@
+#!/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
@@ -15,5 +17,7 @@
# specific language governing permissions and limitations
# under the License.
-SUBDIRS = atom eval http json
+# Remove ipcs created by httpd
+
+ipcs -s | grep 0x | awk '{ print $2 }' | xargs -i -t ipcrm -s {}
Propchange: tuscany/cpp/sca/etc/httpd-ipcrm
------------------------------------------------------------------------------
svn:executable = *
Modified: tuscany/cpp/sca/modules/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/Makefile.am?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/Makefile.am (original)
+++ tuscany/cpp/sca/modules/Makefile.am Sun Nov 1 05:25:14 2009
@@ -15,5 +15,5 @@
# specific language governing permissions and limitations
# under the License.
-SUBDIRS = atom eval http json
+SUBDIRS = atom cache eval http json
Modified: tuscany/cpp/sca/modules/atom/atom-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/atom/atom-test.cpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/atom/atom-test.cpp (original)
+++ tuscany/cpp/sca/modules/atom/atom-test.cpp Sun Nov 1 05:25:14 2009
@@ -33,7 +33,7 @@
namespace tuscany {
namespace atom {
-std::ostringstream* writer(std::ostringstream* os, const std::string& s) {
+std::ostringstream* writer(const std::string& s, std::ostringstream* os) {
(*os) << s;
return os;
}
@@ -78,19 +78,19 @@
<< (list<value>() << element << "price" << std::string("$2.99"));
const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
std::ostringstream os;
- writeEntry<std::ostringstream*>(writer, &os, a);
+ writeATOMEntry<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemEntry);
}
{
const list<value> a = readEntry(mklist(itemEntry));
std::ostringstream os;
- writeEntry<std::ostringstream*>(writer, &os, a);
+ writeATOMEntry<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemEntry);
}
{
const list<value> a = readEntry(mklist(incompleteEntry));
std::ostringstream os;
- writeEntry<std::ostringstream*>(writer, &os, a);
+ writeATOMEntry<std::ostringstream*>(writer, &os, a);
assert(os.str() == completedEntry);
}
return true;
@@ -131,13 +131,13 @@
bool testFeed() {
{
std::ostringstream os;
- writeFeed<std::ostringstream*>(writer, &os, mklist<value>("Feed", "1234"));
+ writeATOMFeed<std::ostringstream*>(writer, &os, mklist<value>("Feed", "1234"));
assert(os.str() == emptyFeed);
}
{
const list<value> a = readFeed(mklist(emptyFeed));
std::ostringstream os;
- writeFeed<std::ostringstream*>(writer, &os, a);
+ writeATOMFeed<std::ostringstream*>(writer, &os, a);
assert(os.str() == emptyFeed);
}
{
@@ -152,7 +152,7 @@
<< (list<value>() << element << "price" << "$3.55")));
const list<value> a = cons<value>("Feed", cons<value>("1234", i));
std::ostringstream os;
- writeFeed<std::ostringstream*>(writer, &os, a);
+ writeATOMFeed<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemFeed);
}
{
@@ -167,13 +167,13 @@
<< (list<value>() << "price" << "$3.55")));
const list<value> a = cons<value>("Feed", cons<value>("1234", i));
std::ostringstream os;
- writeFeed<std::ostringstream*>(writer, &os, a);
+ writeATOMFeed<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemFeed);
}
{
const list<value> a = readFeed(mklist(itemFeed));
std::ostringstream os;
- writeFeed<std::ostringstream*>(writer, &os, a);
+ writeATOMFeed<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemFeed);
}
return true;
Modified: tuscany/cpp/sca/modules/atom/atom.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/atom/atom.hpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/atom/atom.hpp (original)
+++ tuscany/cpp/sca/modules/atom/atom.hpp Sun Nov 1 05:25:14 2009
@@ -38,7 +38,7 @@
/**
* Convert a list of elements to a list of values representing an ATOM entry.
*/
-const list<value> entry(const list<value>& e) {
+const list<value> entryValue(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);
@@ -50,10 +50,10 @@
/**
* Convert a list of elements to a list of values representing ATOM entries.
*/
-const list<value> entries(const list<value>& e) {
+const list<value> entriesValues(const list<value>& e) {
if (isNil(e))
return list<value>();
- return cons<value>(entry(car(e)), entries(cdr(e)));
+ return cons<value>(entryValue(car(e)), entriesValues(cdr(e)));
}
/**
@@ -63,7 +63,7 @@
const list<value> e = readXML(ilist);
if (isNil(e))
return std::string("Empty entry");
- return entry(car(e));
+ return entryValue(car(e));
}
/**
@@ -78,7 +78,7 @@
const list<value> e = filter<value>(selector(mklist<value>(element, "entry")), car(f));
if (isNil(e))
return mklist<value>(elementValue(car(t)), elementValue(car(i)));
- return cons<value>(elementValue(car(t)), cons(elementValue(car(i)), entries(e)));
+ return cons<value>(elementValue(car(t)), cons(elementValue(car(i)), entriesValues(e)));
}
/**
@@ -107,20 +107,12 @@
* Convert a list of values representing an ATOM entry to an ATOM entry.
* The first two values in the list are the entry id and title.
*/
-template<typename R> const failable<R, std::string> writeEntry(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R, std::string> writeATOMEntry(const lambda<R(std::string, R)>& reduce, const R& initial, const list<value>& l) {
return writeXML<R>(reduce, initial, mklist<value>(entryElement(l)));
}
-/**
- * Convert a list of values representing an ATOM entry to a list of strings.
- * The first two values in the list are the entry id and title.
- */
-const list<std::string> writeStrings(const list<std::string>& listSoFar, const std::string& s) {
- return cons(s, listSoFar);
-}
-
-const failable<list<std::string>, std::string> writeEntry(const list<value>& l) {
- const failable<list<std::string>, std::string> ls = writeEntry<list<std::string> >(writeStrings, list<std::string>(), l);
+const failable<list<std::string>, std::string> writeATOMEntry(const list<value>& l) {
+ const failable<list<std::string>, std::string> ls = writeATOMEntry<list<std::string> >(rcons<std::string>, list<std::string>(), l);
if (!hasValue(ls))
return ls;
return reverse(list<std::string>(ls));
@@ -130,7 +122,7 @@
* Convert a list of values representing an ATOM feed to an ATOM feed.
* The first two values in the list are the feed id and title.
*/
-template<typename R> const failable<R, std::string> writeFeed(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R, std::string> writeATOMFeed(const lambda<R(std::string, R)>& reduce, const R& initial, const list<value>& l) {
const list<value> f = list<value>()
<< element << "feed" << (list<value>() << attribute << "xmlns" << "http://www.w3.org/2005/Atom")
<< (list<value>() << element << "title" << (list<value>() << attribute << "type" << "text") << car(l))
@@ -145,13 +137,33 @@
* Convert a list of values representing an ATOM feed to a list of strings.
* The first two values in the list are the feed id and title.
*/
-const failable<list<std::string>, std::string> writeFeed(const list<value>& l) {
- const failable<list<std::string>, std::string> ls = writeFeed<list<std::string> >(writeStrings, list<std::string>(), l);
+const failable<list<std::string>, std::string> writeATOMFeed(const list<value>& l) {
+ const failable<list<std::string>, std::string> ls = writeATOMFeed<list<std::string> >(rcons<std::string>, list<std::string>(), l);
if (!hasValue(ls))
return ls;
return reverse(list<std::string>(ls));
}
+/**
+ * Convert an ATOM entry containing a value to an ATOM entry containing an item element.
+ */
+const list<value> entryValuesToElements(const list<value> val) {
+ return cons(car(val), cons(cadr(val), valuesToElements(mklist<value>(cons<value>("item", (list<value>)caddr(val))))));
+}
+
+/**
+ * Convert an ATOM feed containing values to an ATOM feed containing elements.
+ */
+const list<value> feedValuesToElementsLoop(const list<value> val) {
+ if (isNil(val))
+ return list<value>();
+ return cons<value>(entryValuesToElements(car(val)), feedValuesToElementsLoop(cdr(val)));
+}
+
+const list<value> feedValuesToElements(const list<value>& val) {
+ return cons(car<value>(val), cons<value>(cadr<value>(val), feedValuesToElementsLoop(cddr<value>(val))));
+}
+
}
}
Copied: tuscany/cpp/sca/modules/cache/Makefile.am (from r831639, tuscany/cpp/sca/modules/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/cache/Makefile.am?p2=tuscany/cpp/sca/modules/cache/Makefile.am&p1=tuscany/cpp/sca/modules/Makefile.am&r1=831639&r2=831640&rev=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/Makefile.am (original)
+++ tuscany/cpp/sca/modules/cache/Makefile.am Sun Nov 1 05:25:14 2009
@@ -15,5 +15,12 @@
# specific language governing permissions and limitations
# under the License.
-SUBDIRS = atom eval http json
+noinst_PROGRAMS = cache-test
+
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
+
+cache_test_SOURCES = cache-test.cpp
+cache_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
+
+TESTS = memcached-test
Copied: tuscany/cpp/sca/modules/cache/cache-test.cpp (from r831639, tuscany/cpp/sca/modules/http/curl-test.cpp)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/cache/cache-test.cpp?p2=tuscany/cpp/sca/modules/cache/cache-test.cpp&p1=tuscany/cpp/sca/modules/http/curl-test.cpp&r1=831639&r2=831640&rev=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/http/curl-test.cpp (original)
+++ tuscany/cpp/sca/modules/cache/cache-test.cpp Sun Nov 1 05:25:14 2009
@@ -20,42 +20,28 @@
/* $Rev$ $Date$ */
/**
- * Test JSON data conversion functions.
+ * Test Memcached access functions.
*/
#include <assert.h>
#include <iostream>
-#include <sstream>
#include <string>
-#include "slist.hpp"
-#include "curl.hpp"
+#include "cache.hpp"
namespace tuscany {
-namespace http {
+namespace cache {
-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;
-}
+bool testCache() {
+ Cache cache;
+ addServer("localhost", 11311, cache);
+
+ assert(hasValue(post("a", "AAA", cache)));
+ assert(get("a", cache) == value(std::string("AAA")));
+ assert(hasValue(put("a", "aaa", cache)));
+ assert(get("a", cache) == value(std::string("aaa")));
+ assert(hasValue(del("a", cache)));
+ assert(!hasValue(get("a", cache)));
-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;
}
@@ -65,7 +51,7 @@
int main() {
std::cout << "Testing..." << std::endl;
- tuscany::http::testCURL();
+ tuscany::cache::testCache();
std::cout << "OK" << std::endl;
Added: tuscany/cpp/sca/modules/cache/cache.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/cache/cache.hpp?rev=831640&view=auto
==============================================================================
--- tuscany/cpp/sca/modules/cache/cache.hpp (added)
+++ tuscany/cpp/sca/modules/cache/cache.hpp Sun Nov 1 05:25:14 2009
@@ -0,0 +1,125 @@
+/*
+ * 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_cache_hpp
+#define tuscany_cache_hpp
+
+/**
+ * Memcached access functions.
+ */
+
+#include "apr.h"
+#include "apu.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_hash.h"
+#include "apr_memcache.h"
+#include "apr_network_io.h"
+
+#include <string>
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+
+namespace tuscany {
+namespace cache {
+
+class Cache {
+public:
+ Cache() {
+ apr_pool_create(&pool, NULL);
+ apr_memcache_create(pool, 1, 0, &mc);
+ }
+ ~Cache() {
+ apr_pool_destroy(pool);
+ }
+
+ operator apr_memcache_t*() const {
+ return mc;
+ }
+
+ operator apr_pool_t*() const {
+ return pool;
+ }
+
+private:
+ apr_pool_t* pool;
+ apr_memcache_t* mc;
+
+};
+
+const failable<bool, std::string> addServer(const std::string& host, const int port, Cache& cache) {
+ apr_memcache_server_t *server;
+ const apr_status_t sc = apr_memcache_server_create(cache, host.c_str(), port, 0, 1, 1, 60, &server);
+ if (sc != APR_SUCCESS)
+ return "Could not create server";
+ const apr_status_t as = apr_memcache_add_server(cache, server);
+ if (as != APR_SUCCESS)
+ return "Could not add server";
+ return true;
+}
+
+const failable<bool, std::string> post(const value& key, const value& val, Cache& cache) {
+ const std::string v(val);
+ const apr_status_t rc = apr_memcache_add(cache, std::string(key).c_str(), const_cast<char*>(v.c_str()), v.size(), 0, 27);
+ if (rc != APR_SUCCESS)
+ return "Could not add entry";
+ return true;
+}
+
+const failable<bool, std::string> put(const value& key, const value& val, Cache& cache) {
+ const std::string v(val);
+ const apr_status_t rc = apr_memcache_replace(cache, std::string(key).c_str(), const_cast<char*>(v.c_str()), v.size(), 0, 27);
+ if (rc != APR_SUCCESS)
+ return "Could not add entry";
+ return true;
+}
+
+const failable<value, std::string> get(const value& key, Cache& cache) {
+ apr_pool_t* vpool;
+ const apr_status_t pc = apr_pool_create(&vpool, cache);
+ if (pc != APR_SUCCESS)
+ return std::string("Could not allocate memory");
+
+ char *data;
+ apr_size_t size;
+ const apr_status_t rc = apr_memcache_getp(cache, cache, std::string(key).c_str(), &data, &size, NULL);
+ if (rc != APR_SUCCESS) {
+ apr_pool_destroy(vpool);
+ return std::string("Could not get entry");
+ }
+
+ const value val(std::string(data, size));
+ apr_pool_destroy(vpool);
+ return val;
+}
+
+const failable<bool, std::string> del(const value& key, Cache& cache) {
+ const apr_status_t rc = apr_memcache_delete(cache, std::string(key).c_str(), 0);
+ if (rc != APR_SUCCESS)
+ return "Could not add entry";
+ return true;
+}
+
+}
+}
+
+#endif /* tuscany_cache_hpp */
Copied: tuscany/cpp/sca/modules/cache/memcached-test (from r831639, tuscany/cpp/sca/modules/Makefile.am)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/cache/memcached-test?p2=tuscany/cpp/sca/modules/cache/memcached-test&p1=tuscany/cpp/sca/modules/Makefile.am&r1=831639&r2=831640&rev=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/Makefile.am (original)
+++ tuscany/cpp/sca/modules/cache/memcached-test Sun Nov 1 05:25:14 2009
@@ -1,3 +1,5 @@
+#!/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
@@ -15,5 +17,15 @@
# specific language governing permissions and limitations
# under the License.
-SUBDIRS = atom eval http json
+# Setup
+cmd="memcached -l 127.0.0.1 -m 4 -p 11311"
+$cmd &
+sleep 1
+
+# Test
+./cache-test
+rc=$?
+# Cleanup
+ps -f | grep -v grep | grep "$cmd" | awk '{ print $2 }' | xargs kill
+return $rc
Propchange: tuscany/cpp/sca/modules/cache/memcached-test
------------------------------------------------------------------------------
svn:executable = *
Modified: tuscany/cpp/sca/modules/eval/driver.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/eval/driver.hpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/eval/driver.hpp (original)
+++ tuscany/cpp/sca/modules/eval/driver.hpp Sun Nov 1 05:25:14 2009
@@ -36,40 +36,39 @@
const std::string evalOutputPrompt("; ");
const std::string evalInputPrompt("=> ");
-const bool promptForInput(std::ostream& out, const std::string str) {
+const bool promptForInput(const std::string str, std::ostream& out) {
out << "\n\n" << str;
return true;
}
-const bool announceOutput(std::ostream& out, const std::string str) {
+const bool announceOutput(const std::string str, std::ostream& out) {
out << "\n" << str;
return true;
}
-const bool userPrint(std::ostream& out, const value object) {
- if(isCompoundProcedure(object))
- out << mklist<value>(compoundProcedureSymbol, procedureParameters(object), procedureBody(object), "<procedure-env>");
- out << object;
+const bool userPrint(const value val, std::ostream& out) {
+ if(isCompoundProcedure(val))
+ writeValue(mklist<value>(compoundProcedureSymbol, procedureParameters(val), procedureBody(val), "<procedure-env>"), out);
+ writeValue(val, out);
return true;
}
const value evalDriverLoop(std::istream& in, std::ostream& out, Env& globalEnv, const gc_pool& pool) {
- promptForInput(out, evalInputPrompt);
- value input = read(in);
+ promptForInput(evalInputPrompt, out);
+ value input = readValue(in);
if (isNil(input))
return input;
const value output = evalExpr(input, globalEnv, pool);
- announceOutput(out, evalOutputPrompt);
- userPrint(out, output);
+ announceOutput(evalOutputPrompt, out);
+ userPrint(output, out);
return evalDriverLoop(in, out, globalEnv, pool);
}
const bool evalDriverRun(std::istream& in, std::ostream& out) {
gc_pool pool;
- setupEvalOut(out);
+ setupDisplay(out);
Env globalEnv = setupEnvironment(pool);
evalDriverLoop(in, out, globalEnv, pool);
- cleanupEnvironment(globalEnv);
return true;
}
Modified: tuscany/cpp/sca/modules/eval/environment.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/eval/environment.hpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/eval/environment.hpp (original)
+++ tuscany/cpp/sca/modules/eval/environment.hpp Sun Nov 1 05:25:14 2009
@@ -151,14 +151,6 @@
return env;
}
-const bool cleanupEnvironment(Env& env) {
- if (isNil(env))
- return true;
- *firstFrame(env) = list<value>();
- Env enclosing = enclosingEnvironment(env);
- return cleanupEnvironment(enclosing);
-}
-
const value lookupEnvLoop(const value& var, const Env& env);
const value lookupEnvScan(const value& var, const list<value>& vars, const list<value>& vals, const Env& env) {
Modified: tuscany/cpp/sca/modules/eval/eval-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/eval/eval-test.cpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/eval/eval-test.cpp (original)
+++ tuscany/cpp/sca/modules/eval/eval-test.cpp Sun Nov 1 05:25:14 2009
@@ -39,7 +39,6 @@
defineVariable("x", env, env);
assert(lookupVariableValue(value("x"), env) == env);
assert(lookupVariableValue("a", env) == value(1));
- cleanupEnvironment(env);
return true;
}
@@ -59,23 +58,41 @@
bool testRead() {
std::istringstream is("abcd");
- assert(read(is) == "abcd");
+ assert(readValue(is) == "abcd");
std::istringstream is2("123");
- assert(read(is2) == value(123));
+ assert(readValue(is2) == value(123));
std::istringstream is3("(abcd)");
- assert(read(is3) == mklist(value("abcd")));
+ assert(readValue(is3) == mklist(value("abcd")));
std::istringstream is4("(abcd xyz)");
- assert(read(is4) == mklist<value>("abcd", "xyz"));
+ assert(readValue(is4) == mklist<value>("abcd", "xyz"));
std::istringstream is5("(abcd (xyz tuv))");
- assert(read(is5) == mklist<value>("abcd", mklist<value>("xyz", "tuv")));
+ assert(readValue(is5) == mklist<value>("abcd", mklist<value>("xyz", "tuv")));
return true;
}
+bool testWrite() {
+ const list<value> i = list<value>()
+ << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"
+ << (list<value>() << "item"
+ << (list<value>() << "name" << "Apple")
+ << (list<value>() << "price" << "$2.99")))
+ << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"
+ << (list<value>() << "item"
+ << (list<value>() << "name" << "Orange")
+ << (list<value>() << "price" << "$3.55")));
+ const list<value> a = cons<value>("Feed", cons<value>("feed-1234", i));
+ std::ostringstream os;
+ writeValue(a, os);
+ std::istringstream is(os.str());
+ assert(readValue(is) == a);
+ return true;
+}
+
const std::string testSchemeNumber(
"(define (testNumber) (if (= 1 1) (display \"testNumber ok\") (error \"testNumber\"))) "
"(testNumber)");
@@ -178,6 +195,7 @@
tuscany::eval::testEnv();
tuscany::eval::testEnvGC();
tuscany::eval::testRead();
+ tuscany::eval::testWrite();
tuscany::eval::testEval();
tuscany::eval::testEvalExpr();
tuscany::eval::testEvalGC();
Modified: tuscany/cpp/sca/modules/eval/eval.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/eval/eval.hpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/eval/eval.hpp (original)
+++ tuscany/cpp/sca/modules/eval/eval.hpp Sun Nov 1 05:25:14 2009
@@ -30,7 +30,7 @@
#include "list.hpp"
#include "value.hpp"
#include "primitive.hpp"
-#include "read.hpp"
+#include "io.hpp"
#include "environment.hpp"
namespace tuscany {
Copied: tuscany/cpp/sca/modules/eval/io.hpp (from r831639, tuscany/cpp/sca/modules/eval/read.hpp)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/eval/io.hpp?p2=tuscany/cpp/sca/modules/eval/io.hpp&p1=tuscany/cpp/sca/modules/eval/read.hpp&r1=831639&r2=831640&rev=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/eval/read.hpp (original)
+++ tuscany/cpp/sca/modules/eval/io.hpp Sun Nov 1 05:25:14 2009
@@ -19,11 +19,11 @@
/* $Rev$ $Date$ */
-#ifndef tuscany_eval_read_hpp
-#define tuscany_eval_read_hpp
+#ifndef tuscany_eval_io_hpp
+#define tuscany_eval_io_hpp
/**
- * Script evaluator read functions.
+ * Script evaluator IO functions.
*/
#include <iostream>
@@ -96,7 +96,7 @@
const value readIdentifier(const char chr, std::istream& in);
const value readString(const char chr, std::istream& in);
const value readNumber(const char chr, std::istream& in);
-const value read(std::istream& in);
+const value readValue(std::istream& in);
const value readToken(std::istream& in) {
const char firstChar = readChar(in);
@@ -121,7 +121,7 @@
}
const value readQuoted(std::istream& in) {
- return mklist(quoteSymbol, read(in));
+ return mklist(quoteSymbol, readValue(in));
}
const list<value> readList(const list<value>& listSoFar, std::istream& in) {
@@ -172,13 +172,17 @@
return stringToNumber(listToString(readNumberHelper(mklist(chr), in)));
}
-const value read(std::istream& in) {
+const value readValue(std::istream& in) {
const value nextToken = readToken(in);
if(isLeftParenthesis(nextToken))
return readList(list<value> (), in);
return nextToken;
}
+const bool writeValue(const value& val, std::ostream& out) {
+ out << val;
+}
+
}
}
-#endif /* tuscany_eval_read_hpp */
+#endif /* tuscany_eval_io_hpp */
Modified: tuscany/cpp/sca/modules/eval/primitive.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/eval/primitive.hpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/eval/primitive.hpp (original)
+++ tuscany/cpp/sca/modules/eval/primitive.hpp Sun Nov 1 05:25:14 2009
@@ -40,73 +40,67 @@
const value quoteSymbol("'");
const value lambdaSymbol("lambda");
-std::ostream* evalOut = &std::cout;
+std::ostream* displayOut = &std::cout;
-const bool setupEvalOut(std::ostream& out) {
- evalOut = &out;
+const bool setupDisplay(std::ostream& out) {
+ displayOut = &out;
return true;
}
-const value valueCar(list<value>& args) {
+const value carProc(list<value>& args) {
return car((list<value> )car(args));
}
-const value valueCdr(list<value>& args) {
+const value cdrProc(list<value>& args) {
return cdr((list<value> )car(args));
}
-const value valueCons(list<value>& args) {
+const value consProc(list<value>& args) {
return cons(car(args), (list<value> )cadr(args));
}
-const value valueList(list<value>& args) {
+const value listProc(list<value>& args) {
return args;
}
-const value valueNul(list<value>& args) {
+const value nulProc(list<value>& args) {
return (bool)isNil(car(args));
}
-const value valueEqual(list<value>& args) {
+const value equalProc(list<value>& args) {
return (bool)(car(args) == cadr(args));
}
-const value valueAdd(list<value>& args) {
+const value addProc(list<value>& args) {
if (isNil(cdr(args)))
return (double)car(args);
return (double)car(args) + (double)cadr(args);
}
-const value valueSub(list<value>& args) {
+const value subProc(list<value>& args) {
if (isNil(cdr(args)))
return (double)0 - (double)car(args);
return (double)car(args) - (double)cadr(args);
}
-const value valueMul(list<value>& args) {
+const value mulProc(list<value>& args) {
return (double)car(args) * (double)cadr(args);
}
-const value valueDiv(list<value>& args) {
+const value divProc(list<value>& args) {
return (double)car(args) / (double)cadr(args);
}
-const value valueDisplay(list<value>& args) {
- *evalOut << car(args);
+const value displayProc(list<value>& args) {
+ *displayOut << car(args);
return true;
}
-const value valueComment(list<value>& args) {
- *evalOut << "; " << car(args);
+const value commentProc(list<value>& args) {
return true;
}
-const value valueError(list<value>& args) {
- std::cerr << (std::string)car(args);
- return true;
-}
-
-const value valueUuid(list<value>& args) {
+const value uuidProc(list<value>& args) {
apr_uuid_t uuid;
apr_uuid_get(&uuid);
char buf[APR_UUID_FORMATTED_LENGTH];
@@ -164,20 +158,20 @@
}
const list<value> primitiveProcedureObjects() {
- list<value> l = mklist(primitiveProcedure(valueCar));
- l = cons(primitiveProcedure(valueCdr), l);
- l = cons(primitiveProcedure(valueCons), l);
- l = cons(primitiveProcedure(valueList), l);
- l = cons(primitiveProcedure(valueNul), l);
- l = cons(primitiveProcedure(valueEqual), l);
- l = cons(primitiveProcedure(valueAdd), l);
- l = cons(primitiveProcedure(valueSub), l);
- l = cons(primitiveProcedure(valueMul), l);
- l = cons(primitiveProcedure(valueDiv), l);
- l = cons(primitiveProcedure(valueEqual), l);
- l = cons(primitiveProcedure(valueDisplay), l);
- l = cons(primitiveProcedure(valueUuid), l);
- l = cons(primitiveProcedure(valueComment), l);
+ list<value> l = mklist(primitiveProcedure(carProc));
+ l = cons(primitiveProcedure(cdrProc), l);
+ l = cons(primitiveProcedure(consProc), l);
+ l = cons(primitiveProcedure(listProc), l);
+ l = cons(primitiveProcedure(nulProc), l);
+ l = cons(primitiveProcedure(equalProc), l);
+ l = cons(primitiveProcedure(addProc), l);
+ l = cons(primitiveProcedure(subProc), l);
+ l = cons(primitiveProcedure(mulProc), l);
+ l = cons(primitiveProcedure(divProc), l);
+ l = cons(primitiveProcedure(equalProc), l);
+ l = cons(primitiveProcedure(displayProc), l);
+ l = cons(primitiveProcedure(uuidProc), l);
+ l = cons(primitiveProcedure(commentProc), l);
return l;
}
Copied: tuscany/cpp/sca/modules/http/conf/mime.types (from r831639, tuscany/cpp/sca/modules/http/test-conf/mime.types)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/conf/mime.types?p2=tuscany/cpp/sca/modules/http/conf/mime.types&p1=tuscany/cpp/sca/modules/http/test-conf/mime.types&r1=831639&r2=831640&rev=831640&view=diff
==============================================================================
(empty)
Modified: tuscany/cpp/sca/modules/http/curl-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/curl-test.cpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/http/curl-test.cpp (original)
+++ tuscany/cpp/sca/modules/http/curl-test.cpp Sun Nov 1 05:25:14 2009
@@ -24,6 +24,8 @@
*/
#include <assert.h>
+#include <sys/time.h>
+#include <time.h>
#include <iostream>
#include <sstream>
#include <string>
@@ -37,35 +39,181 @@
return str.find(pattern) != str.npos;
}
-std::ostringstream* curlWriter(std::ostringstream* os, const std::string& s) {
+std::ostringstream* curlWriter(const std::string& s, std::ostringstream* os) {
(*os) << s;
return os;
}
-const bool testCURL() {
+const bool testEval() {
+ CURLHandle ch;
+ const value val = evalExpr(mklist<value>(std::string("echo"), std::string("Hello")), "http://localhost:8091/test", ch);
+ assert(val == std::string("Hello"));
+ return true;
+}
+
+const bool testEvalLoop(const int count, CURLHandle& ch) {
+ if (count == 0)
+ return true;
+ const value val = evalExpr(mklist<value>(std::string("echo"), std::string("Hello")), "http://localhost:8091/test", ch);
+ assert(val == std::string("Hello"));
+ return testEvalLoop(count - 1, ch);
+}
+
+const value blob(std::string(3000, 'A'));
+const list<value> blobs = mklist(blob, blob, blob, blob, blob);
+
+const bool testBlobEvalLoop(const int count, CURLHandle& ch) {
+ if (count == 0)
+ return true;
+ const value val = evalExpr(mklist<value>(std::string("echo"), blobs), "http://localhost:8091/test", ch);
+ assert(val == blobs);
+ return testBlobEvalLoop(count - 1, ch);
+}
+
+const bool testEvalPerf() {
+ const int count = 50;
+ CURLHandle ch;
+ struct timeval start;
+ struct timeval end;
+ {
+ testEvalLoop(5, ch);
+
+ gettimeofday(&start, NULL);
+
+ testEvalLoop(count, ch);
+
+ gettimeofday(&end, NULL);
+ long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ std::cout << "JSON-RPC eval echo test " << (t / count) << " ms" << std::endl;
+ }
+ {
+ testBlobEvalLoop(5, ch);
+
+ gettimeofday(&start, NULL);
+
+ testBlobEvalLoop(count, ch);
+
+ gettimeofday(&end, NULL);
+ long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ std::cout << "JSON-RPC eval blob test " << (t / count) << " ms" << std::endl;
+ }
+}
+
+const bool testGet() {
+ CURLHandle ch;
{
std::ostringstream os;
- const failable<std::ostringstream*, int> r = get<std::ostringstream*>(curlWriter, &os, "http://localhost:9091");
+ const failable<list<std::ostringstream*>, std::string> r = get<std::ostringstream*>(curlWriter, &os, "http://localhost:8091", ch);
assert(hasValue(r));
+ assert(contains(os.str(), "HTTP/1.1 200 OK"));
assert(contains(os.str(), "It works"));
}
{
- std::ostringstream os;
- const failable<list<std::string>, int> r = get("http://localhost:9091");
+ const failable<value, std::string> r = get("http://localhost:8091", ch);
assert(hasValue(r));
- write(r, os);
- assert(contains(os.str(), "It works"));
+ const value val = r;
+ assert(contains(val, "It works"));
}
return true;
}
+const bool testFeed() {
+ return true;
+}
+
+bool testPost() {
+ const list<value> i = list<value>()
+ << (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);
+ CURLHandle ch;
+ value rc = post(a, "http://localhost:8091/test", ch);
+ assert(rc == value(true));
+ return true;
+}
+
+const bool testPostLoop(const int count, const value& val, CURLHandle& ch) {
+ if (count == 0)
+ return true;
+ const value rc = post(val, "http://localhost:8091/test", ch);
+ assert(rc == value(true));
+ return testPostLoop(count - 1, val, ch);
+}
+
+const bool testPostPerf() {
+ const int count = 50;
+ CURLHandle ch;
+ struct timeval start;
+ struct timeval end;
+ {
+ const list<value> i = list<value>()
+ << (list<value>() << "name" << std::string("Apple"))
+ << (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);
+ long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ std::cout << "ATOMPub POST small test " << (t / count) << " ms" << std::endl;
+ }
+ {
+ const list<value> i = list<value>()
+ << (list<value>() << "name" << std::string("Apple"))
+ << (list<value>() << "blob1" << blob)
+ << (list<value>() << "blob2" << blob)
+ << (list<value>() << "blob3" << blob)
+ << (list<value>() << "blob4" << blob)
+ << (list<value>() << "blob5" << blob)
+ << (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);
+ long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ std::cout << "ATOMPub POST blob test " << (t / count) << " ms" << std::endl;
+ }
+}
+
+const bool testPut() {
+ const list<value> i = list<value>()
+ << (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);
+ CURLHandle ch;
+ value rc = put(a, "http://localhost:8091/test", ch);
+ assert(rc == value(true));
+ return true;
+}
+
+const bool testDel() {
+ CURLHandle ch;
+ value rc = del("http://localhost:8091/test/123456789", ch);
+ assert(rc == value(true));
+ return true;
+}
+
}
}
int main() {
std::cout << "Testing..." << std::endl;
- tuscany::http::testCURL();
+ tuscany::http::testGet();
+ tuscany::http::testPost();
+ //tuscany::http::testPostPerf();
+ tuscany::http::testEval();
+ //tuscany::http::testEvalPerf();
+ tuscany::http::testFeed();
+ tuscany::http::testPut();
+ tuscany::http::testDel();
std::cout << "OK" << std::endl;
Modified: tuscany/cpp/sca/modules/http/curl.hpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/curl.hpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/http/curl.hpp (original)
+++ tuscany/cpp/sca/modules/http/curl.hpp Sun Nov 1 05:25:14 2009
@@ -34,11 +34,18 @@
#include "value.hpp"
#include "element.hpp"
#include "monad.hpp"
+#include "../atom/atom.hpp"
+#include "../json/json.hpp"
namespace tuscany {
namespace http {
/**
+ * Set to true to log HTTP content.
+ */
+bool logContent = false;
+
+/**
* CURL library context, one per process.
*/
class CURLContext {
@@ -72,13 +79,37 @@
};
/**
+ * Context passed to the read callback function.
+ */
+class CURLReadContext {
+public:
+ CURLReadContext(const list<std::string>& ilist) : ilist(ilist) {
+ }
+ list<std::string> ilist;
+};
+
+/**
+ * Called by CURL to read data to send.
+ */
+size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) {
+ CURLReadContext& rcx = *static_cast<CURLReadContext*>(data);
+ if (isNil(rcx.ilist))
+ return 0;
+ rcx.ilist = fragment(rcx.ilist, size * nmemb);
+ const std::string s = car(rcx.ilist);
+ rcx.ilist = cdr(rcx.ilist);
+ s.copy((char*)ptr, s.length());
+ return s.length();
+}
+
+/**
* 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) {
+ CURLWriteContext(const lambda<R(std::string, R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
}
- const lambda<R(R, std::string)> reduce;
+ const lambda<R(std::string, R)> reduce;
R accum;
};
@@ -88,7 +119,7 @@
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));
+ wcx.accum = wcx.reduce(std::string((const char*)ptr, realsize), wcx.accum);
return realsize;
}
@@ -98,50 +129,199 @@
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));
+ wcx.accum = wcx.reduce(std::string((const char*)ptr, realsize), wcx.accum);
return realsize;
}
/**
- * HTTP GET, get a resource from a URL.
+ * Apply an HTTP verb to a list containing a list of headers and a list of content, and
+ * a reduce function used to process the response.
*/
-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);
+curl_slist* headers(curl_slist* cl, const list<std::string> h) {
+ if (isNil(h))
+ return cl;
+ 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, CURLHandle& ch) {
// 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_reset(ch);
+ curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0");
+
+ //TODO use HTTP chunking, for now just convert request to a single string
+ std::ostringstream os;
+ write(cadr(req), os);
+ const std::string s = os.str();
+ const int sz = s.length();
+ if (sz < 1400)
+ curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true);
+
+ // Setup the read, header and write callbacks
+ CURLReadContext rcx(mklist(s));
+ curl_easy_setopt(ch, CURLOPT_READFUNCTION, (size_t (*)(void*, size_t, size_t, void*))readCallback);
+ curl_easy_setopt(ch, CURLOPT_READDATA, &rcx);
+ CURLWriteContext<R> hcx(reduce, initial);
+ curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, (size_t (*)(void*, size_t, size_t, void*))headerCallback<R>);
+ curl_easy_setopt(ch, CURLOPT_HEADERDATA, &hcx);
+ CURLWriteContext<R> wcx(reduce, initial);
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
+
+ // Set the request headers
+ curl_slist* hl = headers(NULL, car(req));
+ if (hl != NULL)
+ curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl);
+
+ // Apply the HTTP verb
+ curl_easy_setopt(ch, CURLOPT_URL, url.c_str());
+ if (verb == "POST") {
+ curl_easy_setopt(ch, CURLOPT_POST, true);
+ curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, sz);
+ } else if (verb == "PUT") {
+ curl_easy_setopt(ch, CURLOPT_UPLOAD, true);
+ curl_easy_setopt(ch, CURLOPT_INFILESIZE, sz);
+ } else if (verb == "DELETE")
+ curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, "DELETE");
const CURLcode rc = curl_easy_perform(ch);
- if (rc)
- return rc;
+
+ if (hl != NULL)
+ curl_slist_free_all(hl);
// Return the HTTP return code or content
+ if (rc)
+ return std::string(curl_easy_strerror(rc));
long httprc;
curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc);
- if (httprc != 200)
- return httprc;
- return wcx.accum;
+ if (httprc != 200 && httprc != 201) {
+ std::ostringstream es;
+ es << "HTTP code " << httprc;
+ return es.str();
+ }
+ return mklist<R>(hcx.accum, wcx.accum);
}
/**
- * HTTP GET, get a list of values representing a resource from a URL.
+ * Evaluate an expression remotely, at the given URL.
*/
-const list<std::string> writeStringList(const list<std::string>& listSoFar, const std::string& s) {
- return cons(s, listSoFar);
+const failable<value, std::string> evalExpr(const value expr, const std::string& url, CURLHandle& ch) {
+
+ // Convert expression to a JSON-RPC request
+ json::JSONContext cx;
+ const failable<list<std::string>, std::string> jsreq = jsonRequest(1, car<value>(expr), cdr<value>(expr), cx);
+ if (!hasValue(jsreq))
+ return std::string(jsreq);
+
+ if (logContent) {
+ std::cout<< "content: " << std::endl;
+ write(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, jsreq), rcons<std::string>, list<std::string>(), url, "POST", ch);
+ if (!hasValue(res))
+ return std::string(res);
+
+ // Return result
+ if (logContent) {
+ std::cout << "content:" << std::endl;
+ write(cadr<list<std::string> >(res), std::cout);
+ std::cout << std::endl;
+ }
+ const list<value> val = elementsToValues(json::readJSON(cadr<list<std::string> >(res), cx));
+ return cadr<value>(cadr<value>(val));
+}
+
+/**
+ * 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, CURLHandle& ch) {
+ const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>());
+ return apply(req, reduce, initial, url, "GET", ch);
}
-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));
+/**
+ * HTTP GET, return a list of values representing the resource at the given URL.
+ */
+const failable<value, std::string> get(const std::string& url, CURLHandle& ch) {
+
+ // 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 (!hasValue(res))
+ return std::string(res);
+ const list<list<std::string> > ls = res;
+
+ // TODO Return an ATOM feed
+ const std::string ct;
+ if (ct.find("application/atom+xml") != std::string::npos) {
+ }
+
+ // Return the content as a string value
+ std::ostringstream os;
+ write(reverse(cadr(ls)), os);
+ return value(os.str());
+}
+
+/**
+ * HTTP POST.
+ */
+const failable<value, std::string> post(const value& val, const std::string& url, CURLHandle& ch) {
+
+ // Convert value to an ATOM entry
+ const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
+ if (!hasValue(entry))
+ return std::string(entry);
+ if (logContent) {
+ std::cout << "content:" << std::endl;
+ write(list<std::string>(entry), std::cout);
+ std::cout << std::endl;
+ }
+
+ // POST it to the URL
+ const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml");
+ const list<list<std::string> > req = mklist<list<std::string> >(h, entry);
+ const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "POST", ch);
+ if (!hasValue(res))
+ return std::string(res);
+ return value(true);
+}
+
+/**
+ * HTTP PUT.
+ */
+const failable<value, std::string> put(const value& val, const std::string& url, CURLHandle& ch) {
+
+ // Convert value to an ATOM entry
+ const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val));
+ if (!hasValue(entry))
+ return std::string(entry);
+ if (logContent) {
+ std::cout << "content:" << std::endl;
+ write(list<std::string>(entry), std::cout);
+ std::cout << std::endl;
+ }
+
+ // POST it to the URL
+ const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml");
+ const list<list<std::string> > req = mklist<list<std::string> >(h, entry);
+ const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "PUT", ch);
+ if (!hasValue(res))
+ return std::string(res);
+ return value(true);
+}
+
+/**
+ * HTTP DELETE.
+ */
+const failable<value, std::string> del(const std::string& url, CURLHandle& ch) {
+ 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 (!hasValue(res))
+ return std::string(res);
+ return value(true);
}
}
Added: tuscany/cpp/sca/modules/http/htdocs/entry.xml
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/htdocs/entry.xml?rev=831640&view=auto
==============================================================================
--- tuscany/cpp/sca/modules/http/htdocs/entry.xml (added)
+++ tuscany/cpp/sca/modules/http/htdocs/entry.xml Sun Nov 1 05:25:14 2009
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>111</id><content type="application/xml"><item><javaClass>services.Item</javaClass><name>Apple</name><currency>USD</currency><symbol>$</symbol><price>2.99</price></item></content><link href="111"/></entry>
Added: tuscany/cpp/sca/modules/http/htdocs/feed.xml
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/htdocs/feed.xml?rev=831640&view=auto
==============================================================================
--- tuscany/cpp/sca/modules/http/htdocs/feed.xml (added)
+++ tuscany/cpp/sca/modules/http/htdocs/feed.xml Sun Nov 1 05:25:14 2009
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Sample Feed</title><id>123456789</id><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>111</id><content type="application/xml"><item>javaClass</item></content><link href="111"/></entry><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>222</id><content type="application/xml"><item>javaClass</item></content><link href="222"/></entry><entry xmlns="http://www.w3.org/2005/Atom"><title type="text">Item</title><id>333</id><content type="application/xml"><item>javaClass</item></content><link href="333"/></entry></feed>
Copied: tuscany/cpp/sca/modules/http/htdocs/index.html (from r831639, tuscany/cpp/sca/modules/http/test-htdocs/index.html)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/htdocs/index.html?p2=tuscany/cpp/sca/modules/http/htdocs/index.html&p1=tuscany/cpp/sca/modules/http/test-htdocs/index.html&r1=831639&r2=831640&rev=831640&view=diff
==============================================================================
(empty)
Added: tuscany/cpp/sca/modules/http/htdocs/json-request.txt
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/htdocs/json-request.txt?rev=831640&view=auto
==============================================================================
--- tuscany/cpp/sca/modules/http/htdocs/json-request.txt (added)
+++ tuscany/cpp/sca/modules/http/htdocs/json-request.txt Sun Nov 1 05:25:14 2009
@@ -0,0 +1 @@
+{"id":1,"method":"echo","params":["Hello"]}
Added: tuscany/cpp/sca/modules/http/htdocs/json-result.txt
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/htdocs/json-result.txt?rev=831640&view=auto
==============================================================================
--- tuscany/cpp/sca/modules/http/htdocs/json-result.txt (added)
+++ tuscany/cpp/sca/modules/http/htdocs/json-result.txt Sun Nov 1 05:25:14 2009
@@ -0,0 +1 @@
+{"id":1,"result":"Hello"}
\ No newline at end of file
Modified: tuscany/cpp/sca/modules/http/http-test
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/http-test?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/http/http-test (original)
+++ tuscany/cpp/sca/modules/http/http-test Sun Nov 1 05:25:14 2009
@@ -17,18 +17,24 @@
# 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
+# Setup
+./httpd-conf tmp 8091 htdocs
+cat >>tmp/conf/httpd.conf <<EOF
+<Location /test>
+SetHandler mod_tuscany
+SCAContribution `pwd`/
+SCAComponent httpd-test
+SCAImplementation httpd-test.scm
+</Location>
EOF
-mkdir -p tmp/logs
apachectl -k start -d `pwd`/tmp
sleep 1
+
+# Test
./curl-test
rc=$?
+
+# Cleanup
apachectl -k stop -d `pwd`/tmp
+sleep 1
return $rc
Copied: tuscany/cpp/sca/modules/http/httpd-conf (from r831639, tuscany/cpp/sca/modules/http/http-test)
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/httpd-conf?p2=tuscany/cpp/sca/modules/http/httpd-conf&p1=tuscany/cpp/sca/modules/http/http-test&r1=831639&r2=831640&rev=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/http/http-test (original)
+++ tuscany/cpp/sca/modules/http/httpd-conf Sun Nov 1 05:25:14 2009
@@ -17,18 +17,20 @@
# 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
+# Generate a minimal httpd.conf
+here=`readlink -f $0`; here=`dirname $here`
+root=`readlink -f $1`
+port=$2
+htdocs=`readlink -f $3`
+
+mkdir -p $root
+mkdir -p $root/logs
+mkdir -p $root/conf
+cat >$root/conf/httpd.conf <<EOF
ServerName 127.0.0.1
-Listen 9091
-DocumentRoot `pwd`/test-htdocs
+Listen $port
+DocumentRoot $htdocs
+TypesConfig $here/conf/mime.types
+LoadModule mod_tuscany $here/.libs/libmod_tuscany.so
EOF
-mkdir -p tmp/logs
-apachectl -k start -d `pwd`/tmp
-sleep 1
-./curl-test
-rc=$?
-apachectl -k stop -d `pwd`/tmp
-return $rc
+
Modified: tuscany/cpp/sca/modules/http/httpd-test
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/httpd-test?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/http/httpd-test (original)
+++ tuscany/cpp/sca/modules/http/httpd-test Sun Nov 1 05:25:14 2009
@@ -18,20 +18,59 @@
# 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
+
+# Setup
+./httpd-conf tmp 8090 htdocs
+cat >>tmp/conf/httpd.conf <<EOF
+<Location /test>
+SetHandler mod_tuscany
+SCAContribution `pwd`/
+SCAComponent httpd-test
+SCAImplementation httpd-test.scm
+</Location>
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
+
+# Test HTTP GET
+curl http://localhost:8090/index.html 2>/dev/null >tmp/index.html
+diff tmp/index.html htdocs/index.html
rc=$?
+
+# Test ATOMPub
+if [ "$rc" = "0" ]; then
+ curl http://localhost:8090/test/ >tmp/feed.xml 2>/dev/null
+ diff tmp/feed.xml htdocs/feed.xml
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ curl http://localhost:8090/test/111 >tmp/entry.xml 2>/dev/null
+ diff tmp/entry.xml htdocs/entry.xml
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ curl http://localhost:8090/test/ -X POST -H "Content-type: application/atom+xml" --data @htdocs/entry.xml 2>/dev/null
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ curl http://localhost:8090/test/111 -X PUT -H "Content-type: application/atom+xml" --data @htdocs/entry.xml 2>/dev/null
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ curl http://localhost:8090/test/111 -X DELETE 2>/dev/null
+ rc=$?
+fi
+
+# Test JSON-RPC
+if [ "$rc" = "0" ]; then
+ curl http://localhost:8090/test/ -X POST -H "Content-type: application/json-rpc" --data @htdocs/json-request.txt >tmp/json-result.txt 2>/dev/null
+ diff tmp/json-result.txt htdocs/json-result.txt
+ rc=$?
+fi
+
+# Cleanup
apachectl -k stop -d `pwd`/tmp
+sleep 1
if [ "$rc" = "0" ]; then
echo "OK"
fi
Added: tuscany/cpp/sca/modules/http/httpd-test.scm
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/httpd-test.scm?rev=831640&view=auto
==============================================================================
--- tuscany/cpp/sca/modules/http/httpd-test.scm (added)
+++ tuscany/cpp/sca/modules/http/httpd-test.scm Sun Nov 1 05:25:14 2009
@@ -0,0 +1,33 @@
+(; "JSON-RPC test case")
+
+(define (echo x) x)
+
+(; "ATOMPub test case")
+
+(define (getall)
+ '("Sample Feed" "123456789"
+ ("Item" "111" (javaClass "services.Item") (name "Apple") (currency "USD") (symbol "$") (price 2.99))
+ ("Item" "222" (javaClass "services.Item") (name "Orange") (currency "USD") (symbol "$") (price 3.55))
+ ("Item" "333" (javaClass "services.Item") (name "Pear") (currency "USD") (symbol "$") (price 1.55)))
+)
+
+(define (get id)
+ (define entry '((javaClass "services.Item") (name "Apple") (currency "USD") (symbol "$") (price 2.99)))
+ (cons "Item" (list id entry))
+)
+
+(define (post entry)
+ (display entry)
+ "123456789"
+)
+
+(define (put entry)
+ (display entry)
+ true
+)
+
+(define (delete . args)
+ (display args)
+ true
+)
+
Modified: tuscany/cpp/sca/modules/http/mod.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/http/mod.cpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/http/mod.cpp (original)
+++ tuscany/cpp/sca/modules/http/mod.cpp Sun Nov 1 05:25:14 2009
@@ -64,6 +64,12 @@
namespace httpd {
/**
+ * Set to true to log requests and content.
+ */
+bool logRequests = false;
+bool logContent = false;
+
+/**
* Server configuration.
*/
struct ServerConf {
@@ -139,10 +145,8 @@
}
/**
- * Log HTTP request info to standard out for now, for debugging purposes.
+ * Log HTTP request info.
*/
-bool logRequests = true;
-
int logHeader(void* r, const char* key, const char* value) {
std::cout << "header key: " << key << ", value: " << value << std::endl;
return 1;
@@ -161,6 +165,7 @@
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 << "filename: " << optional(r->filename) << std::endl;
std::cout << "path: " << pathTokens(r) << std::endl;
std::cout << "args: " << optional(r->args) << std::endl;
std::cout.flush();
@@ -170,34 +175,32 @@
/**
* Evaluate an expression against a component implementation.
*/
-const value evalExprLoop(std::istream& is, const value& req, eval::Env& globalEnv) {
- value in = eval::read(is);
+const value evalExprLoop(std::istream& is, const value& expr, eval::Env& globalEnv, const gc_pool& pool) {
+ value in = eval::readValue(is);
if (isNil(in))
- return eval::evalApply(req, globalEnv);
- eval::evalApply(in, globalEnv);
- return evalExprLoop(is, req, globalEnv);
+ return eval::evalExpr(expr, globalEnv, pool);
+ eval::evalExpr(in, globalEnv, pool);
+ return evalExprLoop(is, expr, globalEnv, pool);
}
-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);
-
+const failable<value, std::string> evalExpr(const value& expr, const std::string& contrib, const std::string& impl) {
// 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;
+ return std::string("HTTP_NOT_FOUND");
// Evaluate the expr
+ gc_pool pool;
+ eval::Env globalEnv = eval::setupEnvironment(pool);
std::cout<< "expr: " << expr << std::endl;
std::cout.flush();
- const value val = evalExprLoop(is, expr, globalEnv);
+ const value val = evalExprLoop(is, expr, globalEnv, pool);
std::cout<< "val: " << val << std::endl;
std::cout.flush();
+
if (isNil(val))
- return HTTP_INTERNAL_SERVER_ERROR;
+ return std::string("Could not evaluate expression");
return val;
}
@@ -230,74 +233,17 @@
}
/**
- * Convert a value to a JSON result.
- */
-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);
-}
-
-/**
- * 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))))));
-}
-
-/**
- * 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)));
-}
-
-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;
- return list<std::string>(ls);
-}
-
-/**
- * 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);
-}
-
-/**
* Write an HTTP result.
*/
-const int writeResult(const failable<list<std::string>, int> ls, const std::string& ct, request_rec* r) {
+const failable<int, std::string> writeResult(const failable<list<std::string>, std::string> ls, const std::string& ct, request_rec* r) {
if (!hasValue(ls))
- return ls;
+ return std::string(ls);
std::ostringstream os;
write(ls, os);
- std::cout<< "content: " << os.str() << std::endl;
- std::cout.flush();
+ if (logContent) {
+ std::cout<< "content: " << std::endl << 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");
@@ -314,7 +260,7 @@
/**
* Handle an HTTP GET.
*/
-const int get(request_rec* r) {
+const failable<int, std::string> get(request_rec* r) {
// Inspect the query string
const list<list<value> > args = queryArgs(r);
@@ -326,26 +272,34 @@
// Extract the request id, method and params
const value id = cadr(ia);
- const value method = std::string(cadr(ma)).c_str();
+ const value func = 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));
+ const failable<value, std::string> val = evalExpr(cons(func, eval::quotedParameters(params)), contribution(r), implementation(r));
+ if (!hasValue(val))
+ return std::string(val);
// Return JSON result
json::JSONContext cx;
- return writeResult(jsonResult(cx, id, val), "application/json-rpc", r);
+ return writeResult(json::jsonResult(id, val, cx), "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);
+ if (isNil(path(r))) {
+ const failable<value, std::string> val = evalExpr(mklist<value>("getall"), contribution(r), implementation(r));
+ if (!hasValue(val))
+ return std::string(val);
+ const value feed = val;
+ return writeResult(atom::writeATOMFeed(atom::feedValuesToElements(feed)), "application/atom+xml;type=feed", 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);
+ const failable<value, std::string> val = evalExpr(cons<value>("get", path(r)), contribution(r), implementation(r));
+ if (!hasValue(val))
+ return std::string(val);
+ const value entry = val;
+ return writeResult(atom::writeATOMEntry(atom::entryValuesToElements(entry)), "application/atom+xml;type=entry", r);
}
@@ -370,10 +324,10 @@
return cons(l, postArgs(cdr(a)));
}
-const char* url(const std::string& loc, request_rec* r) {
+const char* url(const value& v, request_rec* r) {
std::string u = r->uri;
u.append("/");
- u.append(loc);
+ u.append(v);
return ap_construct_url(r->pool, u.c_str(), r);
}
@@ -388,43 +342,49 @@
/**
* Handle an HTTP POST.
*/
-const int post(request_rec* r) {
- const std::string ct = contentType(r);
+const failable<int, std::string> post(request_rec* r) {
+ const list<std::string> ls = read(r);
+ if (logContent) {
+ std::cout<< "content: " << std::endl;
+ write(ls, std::cout);
+ std::cout<< std::endl;
+ std::cout.flush();
+ }
// Evaluate a JSON-RPC request and return a JSON result
+ const std::string ct = contentType(r);
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<value> json = elementsToValues(json::readJSON(ls, cx));
const list<list<value> > args = postArgs(json);
// 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 value func = std::string(cadr(assoc(value("method"), args))).c_str();
const list<value> params = (list<value>)cadr(assoc(value("params"), args));
// Evaluate the request expression
- const failable<value, int> val = evalExpr(cons(method, params), contribution(r), implementation(r));
+ const failable<value, std::string> val = evalExpr(cons(func, eval::quotedParameters(params)), contribution(r), implementation(r));
+ if (!hasValue(val))
+ return std::string(val);
// Return JSON result
- return writeResult(jsonResult(cx, id, val), "application/json-rpc", r);
+ return writeResult(json::jsonResult(id, val, cx), "application/json-rpc", 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;
+ const value entry = feedEntry(atom::readEntry(ls));
+ const failable<value, std::string> val = evalExpr(cons<value>("post", eval::quotedParameters(mklist<value>(entry))), contribution(r), implementation(r));
+ if (!hasValue(val))
+ return std::string(val);
+
+ // Return the created resource location
+ apr_table_setn(r->headers_out, "Location", url(val, r));
+ r->status = HTTP_CREATED;
+ return OK;
}
return HTTP_NOT_IMPLEMENTED;
@@ -433,25 +393,48 @@
/**
* Handle an HTTP PUT.
*/
-const int put(request_rec* r) {
- // TODO later
+const failable<int, std::string> put(request_rec* r) {
+ const list<std::string> ls = read(r);
+ std::cout<< "content: " << std::endl;
+ write(ls, std::cout);
+ std::cout<< std::endl;
+ std::cout.flush();
+
+ // Evaluate an ATOM PUT request
+ const value entry = feedEntry(atom::readEntry(ls));
+ const failable<value, std::string> val = evalExpr(cons<value>("put", eval::quotedParameters(mklist<value>(entry))), contribution(r), implementation(r));
+ if (!hasValue(val))
+ return std::string(val);
+ if (val == value(false))
+ return HTTP_NOT_FOUND;
return OK;
}
/**
* Handle an HTTP DELETE.
*/
-const int del(request_rec* r) {
+const failable<int, std::string> 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));
+ const failable<value, std::string> val = evalExpr(cons<value>("delete", path(r)), contribution(r), implementation(r));
if (!hasValue(val))
- return val;
+ return std::string(val);
+ if (val == value(false))
+ return HTTP_NOT_FOUND;
return OK;
}
/**
- * HTTP handler entry point.
+ * Report request execution status.
+ */
+const int reportStatus(const failable<int, std::string> rc) {
+ if (!hasValue(rc))
+ return HTTP_INTERNAL_SERVER_ERROR;
+ return rc;
+}
+
+/**
+ * HTTP request handler entry point.
*/
int handler(request_rec *r) {
if(strcmp(r->handler, "mod_tuscany"))
@@ -468,19 +451,19 @@
ap_should_client_block(r);
if(r->read_chunked == true && r->remaining == 0)
r->chunked = true;
- apr_table_setn(r->headers_out, "Connection", "close");
+ //apr_table_setn(r->headers_out, "Connection", "close");
// Handle HTTP method
if (r->header_only)
return OK;
if(r->method_number == M_GET)
- return get(r);
+ return reportStatus(get(r));
if(r->method_number == M_POST)
- return post(r);
+ return reportStatus(post(r));
if(r->method_number == M_PUT)
- return put(r);
+ return reportStatus(put(r));
if(r->method_number == M_DELETE)
- return del(r);
+ return reportStatus(del(r));
return HTTP_NOT_IMPLEMENTED;
}
Modified: tuscany/cpp/sca/modules/json/json-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/cpp/sca/modules/json/json-test.cpp?rev=831640&r1=831639&r2=831640&view=diff
==============================================================================
--- tuscany/cpp/sca/modules/json/json-test.cpp (original)
+++ tuscany/cpp/sca/modules/json/json-test.cpp Sun Nov 1 05:25:14 2009
@@ -43,7 +43,7 @@
return true;
}
-std::ostringstream* jsonWriter(std::ostringstream* os, const std::string& s) {
+std::ostringstream* jsonWriter(const std::string& s, std::ostringstream* os) {
(*os) << s;
return os;
}
@@ -57,7 +57,7 @@
const list<value> cr = mklist<value>(mklist<value> (attribute, "name", std::string("jdoe")), cons<value>(element, cons<value>("address", ad)), cons<value>(element, cons<value>("account", ac)));
const list<value> c = mklist<value>(cons<value>(element, cons<value>("customer", cr)));
std::ostringstream os;
- write<std::ostringstream*>(cx, jsonWriter, &os, c);
+ writeJSON<std::ostringstream*>(jsonWriter, &os, c, cx);
assert(os.str() == "{\"customer\":{\"name\":\"jdoe\",\"address\":{\"city\":\"san francisco\",\"state\":\"ca\"},\"account\":{\"id\":\"1234\",\"balance\":1000}}}");
}
{
@@ -65,16 +65,16 @@
const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (element, "lastName", std::string("test\ttab")), mklist<value> (element, "firstName", std::string("test1")));
std::ostringstream os;
- write<std::ostringstream*>(cx, jsonWriter, &os, l);
+ writeJSON<std::ostringstream*>(jsonWriter, &os, l, cx);
assert(os.str() == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"firstName\":\"test1\"}");
std::istringstream is(os.str());
const list<std::string> il = streamList(is);
- const list<value> r = read(cx, il);
+ const list<value> r = readJSON(il, cx);
assert(r == l);
std::ostringstream wos;
- write(write(cx, r), wos);
+ write(writeJSON(r, cx), wos);
assert(wos.str() == os.str());
}
return true;
@@ -84,7 +84,7 @@
JSONContext cx;
{
const std::string lm("{\"id\": 1, \"method\": \"system.listMethods\", \"params\": []}");
- const list<value> e = read(cx, mklist(lm));
+ const list<value> e = readJSON(mklist(lm), cx);
const list<value> v = elementsToValues(e);
assert(assoc<value>("id", v) == mklist<value>("id", 1));
assert(assoc<value>("method", v) == mklist<value>("method", std::string("system.listMethods")));
@@ -92,16 +92,16 @@
}
{
const std::string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}");
- const list<value> e = read(cx, mklist(i));
+ const list<value> e = readJSON(mklist(i), cx);
const std::string i2("{\"id\":3,\"result\":{\"0\":{\"price\":\"$2.99\",\"name\":\"Apple\"},\"1\":{\"price\":\"$3.55\",\"name\":\"Orange\"},\"2\":{\"price\":\"$1.55\",\"name\":\"Pear\"}}}");
- const list<value> e2 = read(cx, mklist(i));
+ const list<value> e2 = readJSON(mklist(i), cx);
assert(e == e2);
}
{
const std::string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}");
- const list<value> e = read(cx, mklist(i));
+ const list<value> e = readJSON(mklist(i), cx);
std::ostringstream os;
- write(write(cx, e), os);
+ write(writeJSON(e, cx), os);
assert(os.str() == i);
const list<value> v = elementsToValues(e);
const list<value> r = valuesToElements(v);
@@ -111,7 +111,7 @@
const list<value> r = mklist<value>(mklist<value>("id", 1), mklist<value>("result", mklist<value>(std::string("Service.get"), std::string("Service.getTotal"))));
const list<value> e = valuesToElements(r);
std::ostringstream os;
- write(write(cx, e), os);
+ write(writeJSON(e, cx), os);
assert(os.str() == "{\"id\":1,\"result\":[\"Service.get\",\"Service.getTotal\"]}");
}
return true;