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;