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 2010/02/17 05:14:33 UTC

svn commit: r910819 [1/2] - in /tuscany/sca-cpp/trunk: ./ components/cache/ components/chat/ components/queue/ components/webservice/ etc/ kernel/ modules/http/ modules/java/ modules/java/org/apache/tuscany/ modules/java/test/ modules/json/ modules/pyt...

Author: jsdelfino
Date: Wed Feb 17 04:14:31 2010
New Revision: 910819

URL: http://svn.apache.org/viewvc?rev=910819&view=rev
Log:
Working queue and chat components.  Added a few useful start/stop scripts. Fixed lifecycle code to call start/stop/restart functions before APR pools are cleaned up in both parent and child processes. Minor build script improvements.

Added:
    tuscany/sca-cpp/trunk/bootstrap
      - copied, changed from r907470, tuscany/sca-cpp/trunk/autogen.sh
    tuscany/sca-cpp/trunk/components/cache/memcached-start
      - copied, changed from r907470, tuscany/sca-cpp/trunk/test/store-python/stop
    tuscany/sca-cpp/trunk/components/cache/memcached-stop
      - copied, changed from r907470, tuscany/sca-cpp/trunk/test/store-python/stop
    tuscany/sca-cpp/trunk/components/chat/chatter.cpp
    tuscany/sca-cpp/trunk/components/chat/client-test.cpp
    tuscany/sca-cpp/trunk/components/chat/server-test
      - copied, changed from r907470, tuscany/sca-cpp/trunk/components/cache/server-test
    tuscany/sca-cpp/trunk/components/chat/xmpp-test.cpp
    tuscany/sca-cpp/trunk/components/queue/qpidd-start
      - copied, changed from r907470, tuscany/sca-cpp/trunk/test/store-python/stop
    tuscany/sca-cpp/trunk/components/queue/qpidd-stop
      - copied, changed from r907470, tuscany/sca-cpp/trunk/components/cache/memcached-test
    tuscany/sca-cpp/trunk/components/queue/send-test
      - copied, changed from r907470, tuscany/sca-cpp/trunk/components/cache/memcached-test
    tuscany/sca-cpp/trunk/components/queue/server-test
      - copied, changed from r907470, tuscany/sca-cpp/trunk/components/cache/server-test
Removed:
    tuscany/sca-cpp/trunk/autogen.sh
    tuscany/sca-cpp/trunk/components/chat/chat-listener.cpp
    tuscany/sca-cpp/trunk/components/chat/chat-sender.cpp
Modified:
    tuscany/sca-cpp/trunk/INSTALL
    tuscany/sca-cpp/trunk/components/cache/client-test.cpp
    tuscany/sca-cpp/trunk/components/cache/mcache-test.cpp
    tuscany/sca-cpp/trunk/components/cache/mcache.cpp
    tuscany/sca-cpp/trunk/components/cache/mcache.hpp
    tuscany/sca-cpp/trunk/components/cache/memcached-test
    tuscany/sca-cpp/trunk/components/cache/server-test
    tuscany/sca-cpp/trunk/components/chat/Makefile.am
    tuscany/sca-cpp/trunk/components/chat/chat.composite
    tuscany/sca-cpp/trunk/components/chat/server-test.scm
    tuscany/sca-cpp/trunk/components/chat/xmpp.hpp
    tuscany/sca-cpp/trunk/components/queue/Makefile.am
    tuscany/sca-cpp/trunk/components/queue/client-test.cpp
    tuscany/sca-cpp/trunk/components/queue/qpid-test.cpp
    tuscany/sca-cpp/trunk/components/queue/qpid.hpp
    tuscany/sca-cpp/trunk/components/queue/queue-listener.cpp
    tuscany/sca-cpp/trunk/components/queue/queue-sender.cpp
    tuscany/sca-cpp/trunk/components/queue/queue.composite
    tuscany/sca-cpp/trunk/components/queue/server-test.scm
    tuscany/sca-cpp/trunk/components/webservice/echo-test
    tuscany/sca-cpp/trunk/components/webservice/server-test
    tuscany/sca-cpp/trunk/components/webservice/webservice-client.cpp
    tuscany/sca-cpp/trunk/configure.ac
    tuscany/sca-cpp/trunk/etc/git-exclude
    tuscany/sca-cpp/trunk/kernel/element.hpp
    tuscany/sca-cpp/trunk/kernel/parallel.hpp
    tuscany/sca-cpp/trunk/kernel/value.hpp
    tuscany/sca-cpp/trunk/modules/http/curl.hpp
    tuscany/sca-cpp/trunk/modules/http/httpd.hpp
    tuscany/sca-cpp/trunk/modules/java/eval.hpp
    tuscany/sca-cpp/trunk/modules/java/mod-java.cpp
    tuscany/sca-cpp/trunk/modules/java/mod-java.hpp
    tuscany/sca-cpp/trunk/modules/java/org/apache/tuscany/Service.java
    tuscany/sca-cpp/trunk/modules/java/test/Client.java
    tuscany/sca-cpp/trunk/modules/java/test/ClientImpl.java
    tuscany/sca-cpp/trunk/modules/java/test/Server.java
    tuscany/sca-cpp/trunk/modules/java/test/ServerImpl.java
    tuscany/sca-cpp/trunk/modules/json/json.hpp
    tuscany/sca-cpp/trunk/modules/python/client-test.py
    tuscany/sca-cpp/trunk/modules/python/eval.hpp
    tuscany/sca-cpp/trunk/modules/python/mod-python.cpp
    tuscany/sca-cpp/trunk/modules/python/mod-python.hpp
    tuscany/sca-cpp/trunk/modules/python/server-test.py
    tuscany/sca-cpp/trunk/modules/scheme/primitive.hpp
    tuscany/sca-cpp/trunk/modules/server/client-test.scm
    tuscany/sca-cpp/trunk/modules/server/impl-test.cpp
    tuscany/sca-cpp/trunk/modules/server/mod-cpp.hpp
    tuscany/sca-cpp/trunk/modules/server/mod-eval.cpp
    tuscany/sca-cpp/trunk/modules/server/mod-eval.hpp
    tuscany/sca-cpp/trunk/modules/server/mod-scheme.hpp
    tuscany/sca-cpp/trunk/modules/server/mod-wiring.cpp
    tuscany/sca-cpp/trunk/modules/server/server-test.scm
    tuscany/sca-cpp/trunk/test/store-cpp/start
    tuscany/sca-cpp/trunk/test/store-cpp/stop
    tuscany/sca-cpp/trunk/test/store-java/start
    tuscany/sca-cpp/trunk/test/store-java/stop
    tuscany/sca-cpp/trunk/test/store-python/start
    tuscany/sca-cpp/trunk/test/store-python/stop
    tuscany/sca-cpp/trunk/test/store-scheme/start
    tuscany/sca-cpp/trunk/test/store-scheme/stop

Modified: tuscany/sca-cpp/trunk/INSTALL
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/INSTALL?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/INSTALL (original)
+++ tuscany/sca-cpp/trunk/INSTALL Wed Feb 17 04:14:31 2010
@@ -55,7 +55,7 @@
 
 
 To configure the Tuscany SCA build do this:
-./autogen.sh
+./bootstrap
 ./configure --prefix=<install dir>
 
 To enable debugging and strict warning compile options, add:
@@ -64,7 +64,8 @@
 To enable gprof profiling, add:
 --enable-profiling
 
-To enable multi-threading with the HTTPD worker MPM, add:
+To enable multi-threading (required by the Queue and Chat components and
+for running with the HTTPD worker or event multi-threaded MPMs):
 --enable-threads
 
 To enable support for Python component implementations:
@@ -99,6 +100,7 @@
 --with-libcurl=/usr --with-libxml2=/usr \
 --with-js-include=/usr/include/xulrunner-1.9.1.7/unstable \
 --with-js-lib=/usr/lib/xulrunner-1.9.1.7 \
+--enable-threads \
 --enable-python --with-python=/usr \
 --enable-java --with-java=/usr/lib/jvm/default-java \
 --enable-webservice --with-axis2c=$HOME/axis2c-1.6.0-bin \
@@ -135,7 +137,7 @@
 
 Here are example build and install steps for some of the dependencies.
 
-Apache HTTPD, including APR:
+Apache HTTPD, including APR, using the HTTP prefork MPM (recommended):
 ./configure --enable-ssl --enable-proxy --enable-rewrite --with-included-apr \
 --with-mpm=prefork --prefix=$HOME/httpd-2.2.13-bin
 make
@@ -150,6 +152,11 @@
 export AXIS2C_HOME=$HOME/axis2c-1.6.0-bin
 
 Apache Qpid/C++:
+git clone git://git.apache.org/qpid.git
+cd qpid
+git checkout -b 0.6-release origin/0.6-release
+cd qpid/cpp
+./bootstrap
 ./configure --prefix=$HOME/qpidc-0.6-bin
 make
 make install
@@ -162,6 +169,7 @@
 aclocal
 automake --add-missing --foreign --copy
 autoconf
-./configure
+./configure --prefix=$HOME/libstrophe-bin
 make
+make install
 

Copied: tuscany/sca-cpp/trunk/bootstrap (from r907470, tuscany/sca-cpp/trunk/autogen.sh)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/bootstrap?p2=tuscany/sca-cpp/trunk/bootstrap&p1=tuscany/sca-cpp/trunk/autogen.sh&r1=907470&r2=910819&rev=910819&view=diff
==============================================================================
    (empty)

Modified: tuscany/sca-cpp/trunk/components/cache/client-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/cache/client-test.cpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/client-test.cpp (original)
+++ tuscany/sca-cpp/trunk/components/cache/client-test.cpp Wed Feb 17 04:14:31 2010
@@ -36,7 +36,7 @@
 namespace tuscany {
 namespace cache {
 
-const string url("http://localhost:8090/mcache");
+const string uri("http://localhost:8090/mcache");
 
 bool testCache() {
     http::CURLSession cs;
@@ -46,10 +46,12 @@
             + (list<value>() + "price" + string("$2.99"));
     const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
 
-    const failable<value> id = http::post(a, url, cs);
+    const failable<value> id = http::post(a, uri, cs);
     assert(hasContent(id));
+
+    const string p = path(content(id));
     {
-        const failable<value> val = http::get(url + "/" + content(id), cs);
+        const failable<value> val = http::get(uri + p, cs);
         assert(hasContent(val));
         assert(content(val) == a);
     }
@@ -60,22 +62,22 @@
     const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j);
 
     {
-        const failable<value> r = http::put(b, url + "/" + content(id), cs);
+        const failable<value> r = http::put(b, uri + p, cs);
         assert(hasContent(r));
         assert(content(r) == value(true));
     }
     {
-        const failable<value> val = http::get(url + "/" + content(id), cs);
+        const failable<value> val = http::get(uri + p, cs);
         assert(hasContent(val));
         assert(content(val) == b);
     }
     {
-        const failable<value> r = http::del(url + "/" + content(id), cs);
+        const failable<value> r = http::del(uri + p, cs);
         assert(hasContent(r));
         assert(content(r) == value(true));
     }
     {
-        const failable<value> val = http::get(url + "/" + content(id), cs);
+        const failable<value> val = http::get(uri + p, cs);
         assert(!hasContent(val));
     }
 
@@ -83,13 +85,13 @@
 }
 
 struct getLoop {
-    const value id;
+    const string path;
     const value entry;
     http::CURLSession cs;
-    getLoop(const value& id, const value& entry, http::CURLSession cs) : id(id), entry(entry), cs(cs) {
+    getLoop(const string& path, const value& entry, http::CURLSession cs) : path(path), entry(entry), cs(cs) {
     }
     const bool operator()() const {
-        const failable<value> val = http::get(url + "/" + id, cs);
+        const failable<value> val = http::get(uri + path, cs);
         assert(hasContent(val));
         assert(content(val) == entry);
         return true;
@@ -103,10 +105,11 @@
     const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
 
     http::CURLSession cs;
-    const failable<value> id = http::post(a, url, cs);
+    const failable<value> id = http::post(a, uri, cs);
     assert(hasContent(id));
+    const string p = path(content(id));
 
-    const lambda<bool()> gl = getLoop(content(id), a, cs);
+    const lambda<bool()> gl = getLoop(p, a, cs);
     cout << "Cache get test " << time(gl, 5, 200) << " ms" << endl;
 
     return true;

Modified: tuscany/sca-cpp/trunk/components/cache/mcache-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/cache/mcache-test.cpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/mcache-test.cpp (original)
+++ tuscany/sca-cpp/trunk/components/cache/mcache-test.cpp Wed Feb 17 04:14:31 2010
@@ -33,33 +33,36 @@
 namespace cache {
 
 bool testMemCached() {
-    MemCached ch;
+    MemCached ch("127.0.0.1", 11211);
+    const value k = mklist<value>("a");
 
-    assert(hasContent(post("a", string("AAA"), ch)));
-    assert((get("a", ch)) == value(string("AAA")));
-    assert(hasContent(put("a", string("aaa"), ch)));
-    assert((get("a", ch)) == value(string("aaa")));
-    assert(hasContent(del("a", ch)));
-    assert(!hasContent(get("a", ch)));
+    assert(hasContent(post(k, string("AAA"), ch)));
+    assert((get(k, ch)) == value(string("AAA")));
+    assert(hasContent(put(k, string("aaa"), ch)));
+    assert((get(k, ch)) == value(string("aaa")));
+    assert(hasContent(del(k, ch)));
+    assert(!hasContent(get(k, ch)));
 
     return true;
 }
 
 struct getLoop {
+    const value k;
     MemCached& ch;
-    getLoop(MemCached& ch) : ch(ch) {
+    getLoop(const value& k, MemCached& ch) : k(k), ch(ch) {
     }
     const bool operator()() const {
-        assert((get("c", ch)) == value(string("CCC")));
+        assert((get(k, ch)) == value(string("CCC")));
         return true;
     }
 };
 
 bool testGetPerf() {
-    MemCached ch;
-    assert(hasContent(post("c", string("CCC"), ch)));
+    const value k = mklist<value>("c");
+    MemCached ch("127.0.0.1", 11211);
+    assert(hasContent(post(k, string("CCC"), ch)));
 
-    const lambda<bool()> gl = getLoop(ch);
+    const lambda<bool()> gl = getLoop(k, ch);
     cout << "Memcached get test " << time(gl, 5, 200) << " ms" << endl;
     return true;
 }

Modified: tuscany/sca-cpp/trunk/components/cache/mcache.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/cache/mcache.cpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/mcache.cpp (original)
+++ tuscany/sca-cpp/trunk/components/cache/mcache.cpp Wed Feb 17 04:14:31 2010
@@ -34,14 +34,12 @@
 #include "mcache.hpp"
 
 namespace tuscany {
-namespace cache {
-
-cache::MemCached ch;
+namespace mcache {
 
 /**
  * Get an item from the cache.
  */
-const failable<value> get(const list<value>& params) {
+const failable<value> get(const list<value>& params, cache::MemCached& ch) {
     return cache::get(car(params), ch);
 }
 
@@ -56,9 +54,9 @@
     return value(string(buf, APR_UUID_FORMATTED_LENGTH));
 }
 
-const failable<value> post(const list<value>& params) {
-    const value id = uuidValue();
-    const failable<bool> val = cache::post(id, car(params), ch);
+const failable<value> post(const list<value>& params, cache::MemCached& ch) {
+    const value id = append<value>(car(params), mklist(uuidValue()));
+    const failable<bool> val = cache::post(id, cadr(params), ch);
     if (!hasContent(val))
         return mkfailure<value>(reason(val));
     return id;
@@ -67,7 +65,7 @@
 /**
  * Put an item into the cache.
  */
-const failable<value> put(const list<value>& params) {
+const failable<value> put(const list<value>& params, cache::MemCached& ch) {
     const failable<bool> val = cache::put(car(params), cadr(params), ch);
     if (!hasContent(val))
         return mkfailure<value>(reason(val));
@@ -77,13 +75,49 @@
 /**
  * Delete an item from the cache.
  */
-const failable<value> del(const list<value>& params) {
+const failable<value> del(const list<value>& params, cache::MemCached& ch) {
     const failable<bool> val = cache::del(car(params), ch);
     if (!hasContent(val))
         return mkfailure<value>(reason(val));
     return value(content(val));
 }
 
+/**
+ * Component implementation lambda function.
+ */
+class applyCache {
+public:
+    applyCache(cache::MemCached& ch) : ch(ch) {
+    }
+
+    const value operator()(const list<value>& params) const {
+        const value func(car(params));
+        if (func == "get")
+            return get(cdr(params), ch);
+        if (func == "post")
+            return post(cdr(params), ch);
+        if (func == "put")
+            return put(cdr(params), ch);
+        if (func == "delete")
+            return del(cdr(params), ch);
+        return tuscany::mkfailure<tuscany::value>();
+    }
+
+private:
+    cache::MemCached& ch;
+};
+
+/**
+ * Start the component.
+ */
+const failable<value> start(unused const list<value>& params) {
+    // Connect to memcached
+    cache::MemCached& ch = *(new (gc_new<cache::MemCached>()) cache::MemCached("127.0.0.1", 11211));
+
+    // Return the component implementation lambda function
+    return value(lambda<value(const list<value>&)>(applyCache(ch)));
+}
+
 }
 }
 
@@ -91,14 +125,8 @@
 
 const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
     const tuscany::value func(car(params));
-    if (func == "get")
-        return tuscany::cache::get(cdr(params));
-    if (func == "post")
-        return tuscany::cache::post(cdr(params));
-    if (func == "put")
-        return tuscany::cache::put(cdr(params));
-    if (func == "delete")
-        return tuscany::cache::del(cdr(params));
+    if (func == "start" || func == "restart")
+        return tuscany::mcache::start(cdr(params));
     return tuscany::mkfailure<tuscany::value>();
 }
 

Modified: tuscany/sca-cpp/trunk/components/cache/mcache.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/cache/mcache.hpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/mcache.hpp (original)
+++ tuscany/sca-cpp/trunk/components/cache/mcache.hpp Wed Feb 17 04:14:31 2010
@@ -48,23 +48,28 @@
  */
 class MemCached {
 public:
-    MemCached() {
-        apr_pool_create(&pool, NULL);
-        apr_memcache_create(pool, 1, 0, &mc);
-        init("localhost", 11211);
+    MemCached() : owner(false) {
     }
 
-    MemCached(const string host, const int port) {
+    MemCached(const string host, const int port) : owner(true) {
         apr_pool_create(&pool, NULL);
         apr_memcache_create(pool, 1, 0, &mc);
         init(host, port);
     }
 
+    MemCached(const MemCached& c) : owner(false) {
+        pool = c.pool;
+        mc = c.mc;
+    }
+
     ~MemCached() {
+        if (!owner)
+            return;
         apr_pool_destroy(pool);
     }
 
 private:
+    bool owner;
     apr_pool_t* pool;
     apr_memcache_t* mc;
 
@@ -86,7 +91,6 @@
             return mkfailure<bool>("Could not add server");
         return true;
     }
-
 };
 
 /**

Copied: tuscany/sca-cpp/trunk/components/cache/memcached-start (from r907470, tuscany/sca-cpp/trunk/test/store-python/stop)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/cache/memcached-start?p2=tuscany/sca-cpp/trunk/components/cache/memcached-start&p1=tuscany/sca-cpp/trunk/test/store-python/stop&r1=907470&r2=910819&rev=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/test/store-python/stop (original)
+++ tuscany/sca-cpp/trunk/components/cache/memcached-start Wed Feb 17 04:14:31 2010
@@ -17,7 +17,5 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-../../modules/http/httpd-stop tmp
-mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
-
+# Start memcached
+memcached -l 127.0.0.1 -m 4 -p 11211 &

Copied: tuscany/sca-cpp/trunk/components/cache/memcached-stop (from r907470, tuscany/sca-cpp/trunk/test/store-python/stop)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/cache/memcached-stop?p2=tuscany/sca-cpp/trunk/components/cache/memcached-stop&p1=tuscany/sca-cpp/trunk/test/store-python/stop&r1=907470&r2=910819&rev=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/test/store-python/stop (original)
+++ tuscany/sca-cpp/trunk/components/cache/memcached-stop Wed Feb 17 04:14:31 2010
@@ -17,7 +17,7 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-../../modules/http/httpd-stop tmp
+# Stop memcached
 mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
 
+kill `ps -f | grep -v grep | grep "${mc}" | awk '{ print $2 }'`

Modified: tuscany/sca-cpp/trunk/components/cache/memcached-test
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/cache/memcached-test?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/memcached-test (original)
+++ tuscany/sca-cpp/trunk/components/cache/memcached-test Wed Feb 17 04:14:31 2010
@@ -18,14 +18,13 @@
 #  under the License.
 
 # Setup
-mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-$mc &
+./memcached-start
 sleep 1
 
 # Test
-./mcache-test
+./mcache-test 2>/dev/null
 rc=$?
 
 # Cleanup
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
+./memcached-stop
 return $rc

Modified: tuscany/sca-cpp/trunk/components/cache/server-test
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/cache/server-test?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/server-test (original)
+++ tuscany/sca-cpp/trunk/components/cache/server-test Wed Feb 17 04:14:31 2010
@@ -26,18 +26,16 @@
 SCAComposite mcache.composite
 EOF
 
+./memcached-start
 ../../modules/http/httpd-start tmp
-
-mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-$mc &
 sleep 2
 
 # Test
-./client-test
+./client-test 2>/dev/null
 rc=$?
 
 # Cleanup
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
 ../../modules/http/httpd-stop tmp
+./memcached-stop
 sleep 2
 return $rc

Modified: tuscany/sca-cpp/trunk/components/chat/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/chat/Makefile.am?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/chat/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/components/chat/Makefile.am Wed Feb 17 04:14:31 2010
@@ -17,15 +17,20 @@
 
 if WANT_CHAT
 
-INCLUDES = -I${LIBSTROPHE_INCLUDE}
+noinst_PROGRAMS = xmpp-test client-test
+
+INCLUDES = -I${LIBSTROPHE_INCLUDE} -I${LIBSTROPHE_INCLUDE}/src
 
 compdir=$(prefix)/components/chat
-comp_LTLIBRARIES = libchat-sender.la libchat-listener.la
+comp_LTLIBRARIES = libchatter.la
+
+libchatter_la_SOURCES = chatter.cpp
+libchatter_la_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lexpat -lssl -lresolv
 
-libchat_sender_la_SOURCES = chat-sender.cpp
-libchat_sender_la_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lexpat -lssl -lresolv
+xmpp_test_SOURCES = xmpp-test.cpp
+xmpp_test_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lexpat -lssl -lresolv
 
-libchat_listener_la_SOURCES = chat-listener.cpp
-libchat_listener_la_LDFLAGS = -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lexpat -lssl -lresolv
+client_test_SOURCES = client-test.cpp
+client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${LIBSTROPHE_LIB} -R${LIBSTROPHE_LIB} -lstrophe -lexpat -lssl -lresolv
 
 endif

Modified: tuscany/sca-cpp/trunk/components/chat/chat.composite
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/chat/chat.composite?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/chat/chat.composite (original)
+++ tuscany/sca-cpp/trunk/components/chat/chat.composite Wed Feb 17 04:14:31 2010
@@ -22,17 +22,22 @@
   targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
   name="chat">
         
-    <component name="chat-sender">
-        <implementation.cpp path=".libs" library="libchat-sender"/>
-        <property name="jid">sample@apache.org</property>
-        <service name="chat-sender">
+    <component name="print-sender">
+        <implementation.cpp path=".libs" library="libchatter"/>
+        <property name="jid">sca1@localhost</property>
+        <property name="password">sca1</property>
+        <service name="print-sender">
             <t:binding.http uri="print-sender"/>
         </service>
     </component>
 
-    <component name="chat-listener">
-        <implementation.cpp path=".libs" library="libchat-listener"/>
-        <property name="jid">sample@apache.org</property>
+    <component name="print-chatter">
+        <implementation.cpp path=".libs" library="libchatter"/>
+        <property name="jid">sca2@localhost</property>
+        <property name="password">sca2</property>
+        <service name="print-chatter">
+            <t:binding.http uri="print-chatter"/>
+        </service>
         <reference name="relay" target="print"/>
     </component>
 
@@ -41,6 +46,7 @@
         <service name="print">
             <t:binding.http uri="print"/>
         </service>
+        <reference name="report" target="print-sender"/>
     </component>     
 
 </composite>

Added: tuscany/sca-cpp/trunk/components/chat/chatter.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/chat/chatter.cpp?rev=910819&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/components/chat/chatter.cpp (added)
+++ tuscany/sca-cpp/trunk/components/chat/chatter.cpp Wed Feb 17 04:14:31 2010
@@ -0,0 +1,162 @@
+/*
+ * 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$ */
+
+/**
+ * XMPP chatter component implementation.
+ */
+
+#include "string.hpp"
+#include "function.hpp"
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "parallel.hpp"
+#include "xmpp.hpp"
+
+namespace tuscany {
+namespace chat {
+
+/**
+ * Post an item to an XMPP JID.
+ */
+const failable<value> post(const list<value>& params, XMPPClient& xc) {
+    const value to = car<value>(car(params));
+    const value val = cadr(params);
+    debug(to, "chat::post::jid");
+    debug(val, "chat::post::value");
+    const failable<bool> r = post(to, val, xc);
+    if (!hasContent(r))
+        return mkfailure<value>(reason(r));
+    return value(mklist<value>(to));
+}
+
+/**
+ * A relay function that posts the XMPP messages it receives to a relay component reference.
+ */
+class relay {
+public:
+    relay(const lambda<value(const list<value>&)>& rel) : rel(rel) {
+    }
+
+    const failable<bool> operator()(const value& jid, const value& val, unused XMPPClient& xc) const {
+        if (isNil(rel))
+            return true;
+        debug(jid, "chat::relay::jid");
+        debug(val, "chat::relay::value");
+        const value res = rel(mklist<value>("post", mklist<value>(jid), val));
+        return true;
+    }
+
+private:
+    const lambda<value(const list<value>&)> rel;
+};
+
+/**
+ * Subscribe and listen to an XMPP session.
+ */
+class subscribe {
+public:
+    subscribe(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& l, XMPPClient& xc) : l(l), xc(xc) {
+    }
+
+    const failable<bool> operator()() const {
+        gc_pool pool;
+        debug("chat::subscribe::listen");
+        const failable<bool> r = listen(l, const_cast<XMPPClient&>(xc));
+        debug("chat::subscribe::stopped");
+        return r;
+    }
+
+private:
+    const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l;
+    XMPPClient xc;
+};
+
+/**
+ * Chatter component lambda function
+ */
+class chatter {
+public:
+    chatter(XMPPClient& xc, worker& w) : xc(xc), w(w) {
+    }
+
+    const value operator()(const list<value>& params) const {
+        const tuscany::value func(car(params));
+        if (func == "post")
+            return post(cdr(params), const_cast<XMPPClient&>(xc));
+
+        // Stop the chatter component
+        if (func != "stop")
+            return tuscany::mkfailure<tuscany::value>();
+        debug("chat::chatter::stop");
+
+        // Disconnect and shutdown the worker thread
+        disconnect(const_cast<XMPPClient&>(xc));
+        shutdown(const_cast<worker&>(w));
+        debug("chat::chatter::stopped");
+
+        return failable<value>(value(lambda<value(const list<value>&)>()));
+    }
+
+private:
+    const XMPPClient xc;
+    worker w;
+};
+
+/**
+ * Start the component.
+ */
+const failable<value> start(const list<value>& params) {
+    // Extract the relay reference and the XMPP JID and password
+    const bool hasRelay = !isNil(cddr(params));
+    const value rel = hasRelay? car(params) : value(lambda<value(const list<value>&)>());
+    const list<value> props = hasRelay? cdr(params) : params;
+    const value jid = ((lambda<value(list<value>)>)car(props))(list<value>());
+    const value pass = ((lambda<value(list<value>)>)cadr(props))(list<value>());
+
+    // Create an XMPP client session
+    XMPPClient xc(jid, pass, false);
+    const failable<bool> r = connect(xc);
+    if (!hasContent(r))
+        return mkfailure<value>(reason(r));
+
+    // Listen and relay messages in a worker thread
+    worker w(3);
+    const lambda<failable<bool>(const value&, const value&, XMPPClient&)> rl = relay(rel);
+    submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(rl, xc)));
+
+    // Return the chatter component lambda function
+    return value(lambda<value(const list<value>&)>(chatter(xc, w)));
+}
+
+}
+}
+
+extern "C" {
+
+const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
+    const tuscany::value func(car(params));
+    if (func == "start" || func == "restart")
+        return tuscany::chat::start(cdr(params));
+    return tuscany::mkfailure<tuscany::value>();
+}
+
+}

Added: tuscany/sca-cpp/trunk/components/chat/client-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/chat/client-test.cpp?rev=910819&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/components/chat/client-test.cpp (added)
+++ tuscany/sca-cpp/trunk/components/chat/client-test.cpp Wed Feb 17 04:14:31 2010
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * Test chat component.
+ */
+
+#include <assert.h>
+#include "stream.hpp"
+#include "string.hpp"
+#include "list.hpp"
+#include "element.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "perf.hpp"
+#include "parallel.hpp"
+#include "../../modules/http/curl.hpp"
+#include "xmpp.hpp"
+
+namespace tuscany {
+namespace chat {
+
+const value jid1("sca1@localhost");
+const value pass1("sca1");
+const value jid2("sca2@localhost");
+const value pass2("sca2");
+const value jid3("sca3@localhost");
+const value pass3("sca3");
+
+const list<value> item = list<value>()
+        + (list<value>() + "name" + string("Apple"))
+        + (list<value>() + "price" + string("$2.99"));
+const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
+
+worker w(2);
+bool received;
+
+const failable<bool> listener(const value& from, const value& val, unused XMPPClient& xc) {
+    assert(contains(from, "sca2@localhost"));
+    assert(val == entry);
+    received = true;
+    return false;
+}
+
+struct subscribe {
+    XMPPClient& xc;
+    subscribe(XMPPClient& xc) : xc(xc) {
+    }
+    const failable<bool> operator()() const {
+        const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l(listener);
+        listen(l, xc);
+        return true;
+    }
+};
+
+bool testListen() {
+    received = false;
+    XMPPClient& xc = *(new (gc_new<XMPPClient>()) XMPPClient(jid3, pass3));
+    const failable<bool> c = connect(xc);
+    assert(hasContent(c));
+    const lambda<failable<bool>()> subs = subscribe(xc);
+    submit(w, subs);
+    return true;
+}
+
+bool testPost() {
+    gc_scoped_pool pool;
+    http::CURLSession ch;
+    const failable<value> id = http::post(entry, "http://localhost:8090/print-sender/sca2@localhost", ch);
+    assert(hasContent(id));
+    return true;
+}
+
+bool testReceived() {
+    shutdown(w);
+    assert(received == true);
+    return true;
+}
+
+}
+}
+
+int main() {
+    tuscany::cout << "Testing..." << tuscany::endl;
+
+    tuscany::chat::testListen();
+    tuscany::chat::testPost();
+    tuscany::chat::testReceived();
+
+    tuscany::cout << "OK" << tuscany::endl;
+
+    return 0;
+}

Copied: tuscany/sca-cpp/trunk/components/chat/server-test (from r907470, tuscany/sca-cpp/trunk/components/cache/server-test)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/chat/server-test?p2=tuscany/sca-cpp/trunk/components/chat/server-test&p1=tuscany/sca-cpp/trunk/components/cache/server-test&r1=907470&r2=910819&rev=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/server-test (original)
+++ tuscany/sca-cpp/trunk/components/chat/server-test Wed Feb 17 04:14:31 2010
@@ -23,21 +23,17 @@
 ../../modules/server/scheme-conf tmp
 cat >>tmp/conf/httpd.conf <<EOF
 SCAContribution `pwd`/
-SCAComposite mcache.composite
+SCAComposite chat.composite
 EOF
 
 ../../modules/http/httpd-start tmp
-
-mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-$mc &
 sleep 2
 
 # Test
-./client-test
+./client-test 2>/dev/null
 rc=$?
 
 # Cleanup
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
 ../../modules/http/httpd-stop tmp
-sleep 2
+sleep 1
 return $rc

Modified: tuscany/sca-cpp/trunk/components/chat/server-test.scm
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/chat/server-test.scm?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/chat/server-test.scm (original)
+++ tuscany/sca-cpp/trunk/components/chat/server-test.scm Wed Feb 17 04:14:31 2010
@@ -17,4 +17,4 @@
 
 ; Chat test case
 
-(define (print x) (display x))
+(define (post key val report) (report "post" '("sca3@localhost") val))

Added: tuscany/sca-cpp/trunk/components/chat/xmpp-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/chat/xmpp-test.cpp?rev=910819&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/components/chat/xmpp-test.cpp (added)
+++ tuscany/sca-cpp/trunk/components/chat/xmpp-test.cpp Wed Feb 17 04:14:31 2010
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* $Rev$ $Date$ */
+
+/**
+ * Test XMPP support functions.
+ */
+
+#include <assert.h>
+#include "stream.hpp"
+#include "string.hpp"
+#include "list.hpp"
+#include "element.hpp"
+#include "monad.hpp"
+#include "value.hpp"
+#include "perf.hpp"
+#include "parallel.hpp"
+#include "xmpp.hpp"
+
+namespace tuscany {
+namespace chat {
+
+const value jid1("sca1@localhost");
+const value pass1("sca1");
+const value jid2("sca2@localhost");
+const value pass2("sca2");
+
+worker w(2);
+bool received;
+
+const failable<bool> listener(const value& from, const value& val, unused XMPPClient& xc) {
+    assert(contains(from, "sca1@localhost"));
+    assert(val == "hey");
+    received = true;
+    return false;
+}
+
+struct subscribe {
+    XMPPClient& xc;
+    subscribe(XMPPClient& xc) : xc(xc) {
+    }
+    const failable<bool> operator()() const {
+        const lambda<failable<bool>(const value&, const value&, XMPPClient&)> l(listener);
+        listen(l, xc);
+        return true;
+    }
+};
+
+bool testListen() {
+    received = false;
+    XMPPClient& xc = *(new (gc_new<XMPPClient>()) XMPPClient(jid2, pass2));
+    const failable<bool> c = connect(xc);
+    assert(hasContent(c));
+    const lambda<failable<bool>()> subs = subscribe(xc);
+    submit(w, subs);
+    return true;
+}
+
+bool testPost() {
+    XMPPClient xc(jid1, pass1);
+    const failable<bool> c = connect(xc);
+    assert(hasContent(c));
+    const failable<bool> p = post(jid2, "hey", xc);
+    assert(hasContent(p));
+    return true;
+}
+
+bool testReceived() {
+    shutdown(w);
+    assert(received == true);
+    return true;
+}
+
+}
+}
+
+int main() {
+    tuscany::cout << "Testing..." << tuscany::endl;
+
+    tuscany::chat::testListen();
+    tuscany::chat::testPost();
+    tuscany::chat::testReceived();
+
+    tuscany::cout << "OK" << tuscany::endl;
+    return 0;
+}

Modified: tuscany/sca-cpp/trunk/components/chat/xmpp.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/chat/xmpp.hpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/chat/xmpp.hpp (original)
+++ tuscany/sca-cpp/trunk/components/chat/xmpp.hpp Wed Feb 17 04:14:31 2010
@@ -26,11 +26,303 @@
  * XMPP support functions.
  */
 
+#include <apr_uuid.h>
+
 #include "strophe.h"
+extern "C" {
+#include "common.h"
+}
+#include "string.hpp"
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "../../modules/scheme/eval.hpp"
 
 namespace tuscany {
 namespace chat {
 
+/**
+ * XMPP runtime, one per process.
+ */
+class XMPPRuntime {
+public:
+    XMPPRuntime() {
+        xmpp_initialize();
+        log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
+    }
+
+    ~XMPPRuntime() {
+        xmpp_shutdown();
+    }
+
+private:
+    friend class XMPPClient;
+    xmpp_log_t* log;
+
+} xmppRuntime;
+
+/**
+ * Represents an XMPP client.
+ */
+const string resourceUUID() {
+    apr_uuid_t uuid;
+    apr_uuid_get(&uuid);
+    char buf[APR_UUID_FORMATTED_LENGTH];
+    apr_uuid_format(buf, &uuid);
+    return string(buf, APR_UUID_FORMATTED_LENGTH);
+}
+
+class XMPPClient {
+public:
+    XMPPClient(const string& jid, const string& pass, bool owner = true) : owner(owner), ctx(xmpp_ctx_new(NULL, xmppRuntime.log)), conn(xmpp_conn_new(ctx)), connecting(false), connected(false), disconnecting(false) {
+        xmpp_conn_set_jid(conn, c_str(jid + "/" + resourceUUID()));
+        xmpp_conn_set_pass(conn, c_str(pass));
+    }
+
+    XMPPClient(const XMPPClient& xc) : owner(false), ctx(xc.ctx), conn(xc.conn), listener(xc.listener),  connecting(xc.connecting), connected(xc.connected), disconnecting(xc.disconnecting) {
+    }
+
+    ~XMPPClient() {
+        extern const failable<bool> disconnect(XMPPClient& xc);
+        if (!owner)
+            return;
+        if (!disconnecting)
+            disconnect(*this);
+        xmpp_conn_release(conn);
+        xmpp_ctx_free(ctx);
+    }
+
+private:
+    friend int versionHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata);
+    friend void connHandler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, const int err, xmpp_stream_error_t* const errstream, void *const udata);
+    friend int messageHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata);
+    friend const failable<bool> connect(XMPPClient& xc);
+    friend const failable<int> send(const char* data, const int len, XMPPClient& xc);
+    friend const failable<int> send(xmpp_stanza_t* const stanza, XMPPClient& xc);
+    friend const failable<bool> post(const value& to, const value& val, XMPPClient& xc);
+    friend const failable<bool> disconnect(XMPPClient& xc);
+    friend const failable<bool> listen(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc);
+
+    const bool owner;
+    xmpp_ctx_t* ctx;
+    xmpp_conn_t* conn;
+    lambda<failable<bool>(const value&, const value&, XMPPClient&)> listener;
+    bool connecting;
+    bool connected;
+    bool disconnecting;
+};
+
+/**
+ * Make a text stanza.
+ */
+xmpp_stanza_t* textStanza(const char* text, xmpp_ctx_t* ctx) {
+    xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_text(stanza, text);
+    return stanza;
+}
+
+/**
+ * Make a named stanza.
+ */
+xmpp_stanza_t* namedStanza(const char* ns, const char* name, xmpp_ctx_t* ctx) {
+    xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(stanza, name);
+    if (ns != NULL)
+        xmpp_stanza_set_ns(stanza, ns);
+    return stanza;
+}
+
+/**
+ * Make a named stanza using a qualified name.
+ */
+xmpp_stanza_t* namedStanza(const char* name, xmpp_ctx_t* ctx) {
+    xmpp_stanza_t* stanza = xmpp_stanza_new(ctx);
+    xmpp_stanza_set_name(stanza, name);
+    return stanza;
+}
+
+/**
+ * XMPP version handler.
+ */
+int versionHandler(xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata) {
+    XMPPClient& xc = *(XMPPClient*)udata;
+
+    // Build version reply stanza
+    xmpp_stanza_t* reply = namedStanza("iq", xc.ctx);
+    xmpp_stanza_set_type(reply, "result");
+    xmpp_stanza_set_id(reply, xmpp_stanza_get_id(stanza));
+    xmpp_stanza_set_attribute(reply, "to", xmpp_stanza_get_attribute(stanza, "from"));
+    xmpp_stanza_t* query = namedStanza(xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza)), "query", xc.ctx);
+    xmpp_stanza_add_child(reply, query);
+    xmpp_stanza_t* name = namedStanza("name", xc.ctx);
+    xmpp_stanza_add_child(query, name);
+    xmpp_stanza_add_child(name, textStanza("Apache Tuscany", xc.ctx));
+    xmpp_stanza_t* version = namedStanza("version", xc.ctx);
+    xmpp_stanza_add_child(query, version);
+    xmpp_stanza_add_child(version, textStanza("1.0", xc.ctx));
+
+    // Send it
+    xmpp_send(conn, reply);
+    xmpp_stanza_release(reply);
+    return 1;
+}
+
+/**
+ * XMPP message handler
+ */
+int messageHandler(unused xmpp_conn_t* const conn, xmpp_stanza_t* const stanza, void* const udata) {
+    // Ignore noise
+    if(xmpp_stanza_get_child_by_name(stanza, "body") == NULL)
+        return 1;
+    if(!strcmp(xmpp_stanza_get_attribute(stanza, "type"), "error"))
+        return 1;
+
+    // Call the client listener function
+    XMPPClient& xc = *(XMPPClient*)udata;
+    const char* from = xmpp_stanza_get_attribute(stanza, "from");
+    const char* text = xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body"));
+    if (isNil(xc.listener))
+        return 1;
+    const value val(scheme::readValue(text));
+    debug(from, "chat::messageHandler::from");
+    debug(val, "chat::messageHandler::body");
+    const failable<bool> r = xc.listener(value(string(from)), val, xc);
+    if (!hasContent(r) || !content(r)) {
+        // Stop listening
+        xc.listener = lambda<failable<bool>(const value&, const value&, XMPPClient&)>();
+        return 0;
+    }
+    return 1;
+}
+
+/**
+ * XMPP connection handler.
+ */
+void connHandler(xmpp_conn_t * const conn, const xmpp_conn_event_t status, unused const int err, unused xmpp_stream_error_t* const errstream, void *const udata) {
+    XMPPClient& xc = *(XMPPClient*)udata;
+    xc.connecting = false;
+
+    if (status == XMPP_CONN_CONNECT) {
+        debug("chat::connHandler::connected");
+        xmpp_handler_add(conn, versionHandler, "jabber:iq:version", "iq", NULL, &xc);
+
+        // Send a <presence/> stanza so that we appear online to contacts
+        xmpp_stanza_t* pres = xmpp_stanza_new(xc.ctx);
+        xmpp_stanza_set_name(pres, "presence");
+        xmpp_send(conn, pres);
+        xmpp_stanza_release(pres);
+        xc.connected = true;
+        return;
+    }
+
+    debug("chat::connHandler::disconnected");
+    xc.connected = false;
+    if (xc.ctx->loop_status == XMPP_LOOP_RUNNING)
+        xc.ctx->loop_status = XMPP_LOOP_QUIT;
+}
+
+/**
+ * Connect to an XMPP server.
+ */
+const failable<bool> connect(XMPPClient& xc) {
+    xc.connecting = true;
+    xmpp_connect_client(xc.conn, NULL, 0, connHandler, &xc);
+    while(xc.connecting)
+        xmpp_run_once(xc.ctx, 20L);
+    if (!xc.connected)
+        return mkfailure<bool>("Couldn't connect to XMPP server");
+    return true;
+}
+
+/**
+ * Send a buffer on an XMPP session.
+ */
+const failable<int> send(const char* data, const int len, XMPPClient& xc) {
+    if (len == 0)
+        return 0;
+    const int written = xc.conn->tls? tls_write(xc.conn->tls, data, len) : sock_write(xc.conn->sock, data, len);
+    if (written < 0) {
+        xc.conn->error = xc.conn->tls? tls_error(xc.conn->tls) : sock_error();
+        return mkfailure<int>("Couldn't send stanza to XMPP server");
+    }
+    return send(data + written, len - written, xc);
+}
+
+/**
+ * Send a string on an XMPP session.
+ */
+const failable<int> send(const string& data, XMPPClient& xc) {
+    return send(c_str(data), length(data), xc);
+}
+
+/**
+ * Send a stanza on an XMPP session.
+ */
+const failable<int> send(xmpp_stanza_t* const stanza, XMPPClient& xc) {
+    char *buf;
+    size_t len;
+    const int rc = xmpp_stanza_to_text(stanza, &buf, &len);
+     if (rc != 0)
+         return mkfailure<int>("Couldn't convert stanza to text");
+     const failable<int> r = send(buf, len, xc);
+     if (!hasContent(r)) {
+         xmpp_free(xc.conn->ctx, buf);
+         return r;
+     }
+     xmpp_debug(xc.conn->ctx, "conn", "SENT: %s", buf);
+     xmpp_free(xc.conn->ctx, buf);
+     return content(r);
+}
+
+/**
+ * Post a message to an XMPP jid.
+ */
+const failable<bool> post(const value& to, const value& val, XMPPClient& xc) {
+    debug(to, "chat::post::to");
+    debug(val, "chat::post::body");
+
+    // Convert the value to a string
+    const string vs(scheme::writeValue(val));
+
+    // Build message stanza
+    xmpp_stanza_t* stanza = namedStanza("message", xc.ctx);
+    xmpp_stanza_set_type(stanza, "chat");
+    xmpp_stanza_set_attribute(stanza, "to", c_str(string(to)));
+    xmpp_stanza_t* body = namedStanza("body", xc.ctx);
+    xmpp_stanza_add_child(stanza, body);
+    xmpp_stanza_add_child(body, textStanza(c_str(vs), xc.ctx));
+
+    // Send it
+    const failable<int> r = send(stanza, xc);
+    xmpp_stanza_release(stanza);
+    if (!hasContent(r))
+        return mkfailure<bool>(reason(r));
+    return true;
+}
+
+/**
+ * Disconnect an XMPP session.
+ */
+const failable<bool> disconnect(XMPPClient& xc) {
+    xc.disconnecting = true;
+    const failable<int> r = send("</stream:stream>", xc);
+    if (!hasContent(r))
+        return mkfailure<bool>(reason(r));
+    return true;
+}
+
+/**
+ * Listen to messages received by an XMPP client.
+ */
+const failable<bool> listen(const lambda<failable<bool>(const value&, const value&, XMPPClient&)>& listener, XMPPClient& xc) {
+    debug("chat::listen");
+    xc.listener = listener;
+    xmpp_handler_add(xc.conn, messageHandler, NULL, "message", NULL, &xc);
+    while(xc.connected && !isNil(xc.listener))
+        xmpp_run_once(xc.ctx, 1000L);
+    return true;
+}
+
 }
 }
 

Modified: tuscany/sca-cpp/trunk/components/queue/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/Makefile.am?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/queue/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/components/queue/Makefile.am Wed Feb 17 04:14:31 2010
@@ -35,11 +35,11 @@
 qpid_test_LDFLAGS = -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient
 
 client_test_SOURCES = client-test.cpp
-client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
+client_test_LDFLAGS = -lxml2 -lcurl -lmozjs -L${QPIDC_LIB} -R${QPIDC_LIB} -lqpidclient
 
 qpidc.prefix: $(top_builddir)/config.status
 	echo ${QPIDC_PREFIX} >qpidc.prefix
 
-#TESTS = qpid-test server-test
+TESTS = send-test server-test
 
 endif

Modified: tuscany/sca-cpp/trunk/components/queue/client-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/client-test.cpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/queue/client-test.cpp (original)
+++ tuscany/sca-cpp/trunk/components/queue/client-test.cpp Wed Feb 17 04:14:31 2010
@@ -32,28 +32,54 @@
 #include "monad.hpp"
 #include "perf.hpp"
 #include "../../modules/http/curl.hpp"
+#include "qpid.hpp"
+
+// Ignore conversion issues and redundant declarations in Qpid headers
+#ifdef WANT_MAINTAINER_MODE
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
 
 namespace tuscany {
 namespace queue {
 
+const value key(mklist<value>(string("report")));
+const string qname("reportq");
 
-bool testPost() {
-    http::CURLSession cs;
+const list<value> item = list<value>()
+        + (list<value>() + "name" + string("Apple"))
+        + (list<value>() + "price" + string("$2.99"));
+const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
+
+bool testDeclareQueue() {
+    QpidConnection qc;
+    QpidSession qs(qc);
+    const failable<bool> r = declareQueue(key, qname, qs);
+    assert(hasContent(r));
+    return true;
+}
+
+const bool listener(const value& k, const value& v) {
+    cerr << "k " << k << " v " << v << endl;
+    assert(k == key);
+    assert(v == entry);
+    return false;
+}
 
-    const value func = "http://ws.apache.org/axis2/c/samples/echoString";
-    const list<value> arg = mklist<value>(
-            list<value>() + "ns1:echoString"
-            + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo"))
-            + (list<value>() + "text" + string("Hello World!")));
-
-    const failable<value> rval = http::evalExpr(mklist<value>(func, arg), "http://localhost:8090/echo-client", cs);
-    assert(hasContent(rval));
-
-    const list<value> r = mklist<value>(
-            list<value>() + "ns1:echoString"
-            + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/c/samples"))
-            + (list<value>() + "text" + string("Hello World!")));
-    assert(content(rval) == r);
+bool testListen() {
+    QpidConnection qc;
+    QpidSession qs(qc);
+    QpidSubscription qsub(qs);
+    const lambda<bool(const value&, const value&)> l(listener);
+    listen(qname, l, qsub);
+    return true;
+}
+
+bool testPost() {
+    gc_scoped_pool pool;
+    http::CURLSession ch;
+    const failable<value> id = http::post(entry, "http://localhost:8090/print-sender", ch);
+    assert(hasContent(id));
     return true;
 }
 
@@ -63,7 +89,9 @@
 int main() {
     tuscany::cout << "Testing..." << tuscany::endl;
 
+    tuscany::queue::testDeclareQueue();
     tuscany::queue::testPost();
+    tuscany::queue::testListen();
 
     tuscany::cout << "OK" << tuscany::endl;
 

Modified: tuscany/sca-cpp/trunk/components/queue/qpid-test.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/qpid-test.cpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/queue/qpid-test.cpp (original)
+++ tuscany/sca-cpp/trunk/components/queue/qpid-test.cpp Wed Feb 17 04:14:31 2010
@@ -33,20 +33,51 @@
 #include "perf.hpp"
 #include "qpid.hpp"
 
+// Ignore conversion issues and redundant declarations in Qpid headers
+#ifdef WANT_MAINTAINER_MODE
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
 namespace tuscany {
 namespace queue {
 
-bool testPost() {
+const value key(mklist<value>("test"));
+const string qname("testq");
+
+bool testDeclareQueue() {
     QpidConnection qc;
+    QpidSession qs(qc);
+    const failable<bool> r = declareQueue(key, qname, qs);
+    assert(hasContent(r));
+    return true;
+}
+
+const list<value> item = list<value>()
+        + (list<value>() + "name" + string("Apple"))
+        + (list<value>() + "price" + string("$2.99"));
+const list<value> entry = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), item);
 
+bool testPost() {
+    QpidConnection qc;
     QpidSession qs(qc);
+    const failable<bool> r = post(key, entry, qs);
+    assert(hasContent(r));
+    return true;
+}
 
-    // Post the item
-    const list<value> params;
-    const value key = ((lambda<value(list<value>)>)cadr(params))(list<value>());
-    post(key, car(params), qs);
+const bool listener(const value& k, const value& v) {
+    assert(k == key);
+    assert(v == entry);
+    return false;
+}
 
-    return value(true);
+bool testListen() {
+    QpidConnection qc;
+    QpidSession qs(qc);
+    QpidSubscription qsub(qs);
+    const lambda<bool(const value&, const value&)> l(listener);
+    listen(qname, l, qsub);
     return true;
 }
 
@@ -56,7 +87,9 @@
 int main() {
     tuscany::cout << "Testing..." << tuscany::endl;
 
+    tuscany::queue::testDeclareQueue();
     tuscany::queue::testPost();
+    tuscany::queue::testListen();
 
     tuscany::cout << "OK" << tuscany::endl;
 

Modified: tuscany/sca-cpp/trunk/components/queue/qpid.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/qpid.hpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/queue/qpid.hpp (original)
+++ tuscany/sca-cpp/trunk/components/queue/qpid.hpp Wed Feb 17 04:14:31 2010
@@ -34,6 +34,8 @@
 
 #include <qpid/client/Connection.h>
 #include <qpid/client/Session.h>
+#include <qpid/client/MessageListener.h>
+#include <qpid/client/SubscriptionManager.h>
 
 #include "string.hpp"
 #include "list.hpp"
@@ -53,6 +55,10 @@
         c.open("localhost", 5672);
     }
 
+    QpidConnection(const bool owner) : owner(owner) {
+        c.open("localhost", 5672);
+    }
+
     QpidConnection(const QpidConnection& qc) : owner(false), c(qc.c) {
     }
 
@@ -63,6 +69,7 @@
     }
 
 private:
+    friend const failable<bool> close(QpidConnection& qc);
     friend class QpidSession;
 
     const bool owner;
@@ -71,6 +78,14 @@
 };
 
 /**
+ * Close a Qpid connection.
+ */
+const failable<bool> close(QpidConnection& qc) {
+    qc.c.close();
+    return true;
+}
+
+/**
  * Represents a Qpid session.
  */
 class QpidSession {
@@ -78,6 +93,9 @@
     QpidSession(QpidConnection& qc) : owner(true), s(qc.c.newSession()) {
     }
 
+    QpidSession(QpidConnection& qc, const bool owner) : owner(owner), s(qc.c.newSession()) {
+    }
+
     QpidSession(const QpidSession& qs) : owner(false), s(qs.s) {
     }
 
@@ -88,38 +106,145 @@
     }
 
 private:
-    friend qpid::client::Session session(const QpidSession& qs);
+    friend const failable<bool> close(QpidSession& qs);
+    friend const failable<bool> declareQueue(const value& key, const string& name, QpidSession& qs);
+    friend const failable<bool> post(const value& key, const value& val, QpidSession& qs);
+    friend class QpidSubscription;
 
     const bool owner;
     qpid::client::Session s;
 };
 
-qpid::client::Session session(const QpidSession& qs) {
-    return qs.s;
+/**
+ * Close a Qpid session.
+ */
+const failable<bool> close(QpidSession& qs) {
+    try {
+        qs.s.close();
+    } catch (const qpid::Exception& e) {
+        return mkfailure<bool>(string("Qpid failure: ") + e.what());
+    }
+    return true;
 }
 
 /**
  * Declare a key / AMQP queue pair.
  */
-const failable<bool> declareQueue(const string& key, const string& name, QpidSession& qs) {
-    session(qs).queueDeclare(qpid::client::arg::queue=c_str(name));
-    session(qs).exchangeBind(qpid::client::arg::exchange="amq.direct", qpid::client::arg::queue=c_str(name), qpid::client::arg::bindingKey=c_str(key));
+const failable<bool> declareQueue(const value& key, const string& name, QpidSession& qs) {
+    const string ks(scheme::writeValue(key));
+    try {
+        qs.s.queueDeclare(qpid::client::arg::queue=c_str(name));
+        qs.s.exchangeBind(qpid::client::arg::exchange="amq.direct", qpid::client::arg::queue=c_str(name), qpid::client::arg::bindingKey=c_str(ks));
+    } catch (const qpid::Exception& e) {
+        return mkfailure<bool>(string("Qpid failure: ") + e.what());
+    }
     return true;
 }
 
 /**
- * Post a key / value pair in message to an AMQP broker.
+ * Post a key / value pair message to an AMQP broker.
  */
-const failable<bool> post(const string& key, const value& val, QpidSession& qs) {
+const failable<bool> post(const value& key, const value& val, QpidSession& qs) {
 
-    // Convert the value to a string
+    // Send in a message with the given key.
+    const string ks(scheme::writeValue(key));
     const string vs(scheme::writeValue(val));
+    try {
+        qpid::client::Message message;
+        message.getDeliveryProperties().setRoutingKey(c_str(ks));
+        message.setData(c_str(vs));
+        qs.s.messageTransfer(qpid::client::arg::content=message,  qpid::client::arg::destination="amq.direct");
+    } catch (const qpid::Exception& e) {
+        return mkfailure<bool>(string("Qpid failure: ") + e.what());
+    }
+    return true;
+}
 
-    // Send in a message with the given key.
-    qpid::client::Message message;
-    message.getDeliveryProperties().setRoutingKey(c_str(key));
-    message.setData(c_str(vs));
-    session(qs).messageTransfer(qpid::client::arg::content=message,  qpid::client::arg::destination="amq.direct");
+/**
+ * Represents a Qpid subscription.
+ */
+class QpidSubscription {
+public:
+    QpidSubscription(QpidSession& qs) : owner(true), subs(qs.s) {
+    }
+
+    QpidSubscription(QpidSession& qs, const bool owner) : owner(owner), subs(qs.s) {
+    }
+
+    QpidSubscription(const QpidSubscription& qsub) : owner(false), subs(qsub.subs) {
+    }
+
+    ~QpidSubscription() {
+        if (!owner)
+            return;
+        try {
+            subs.stop();
+        } catch (const qpid::Exception& e) {
+            mkfailure<bool>(string("Qpid failure: ") + e.what());
+        }
+    }
+
+private:
+    friend const failable<bool> listen(const string& name, const lambda<bool(const value&, const value&)>& l, QpidSubscription& qsub);
+    friend const failable<bool> stop(QpidSubscription& qsub);
+
+    const bool owner;
+    qpid::client::SubscriptionManager subs;
+};
+
+/**
+ * Register a listener function with an AMQP queue.
+ */
+class Listener : public qpid::client::MessageListener {
+public:
+    Listener(const lambda<bool(const value&, const value&)> l, qpid::client::SubscriptionManager& subs) : l(l), subs(subs) {
+    }
+
+    virtual void received(qpid::client::Message& msg) {
+
+        // Call the listener function
+        const value k(scheme::readValue(msg.getDeliveryProperties().getRoutingKey().c_str()));
+        const value v(scheme::readValue(msg.getData().c_str()));
+        const bool r = l(k, v);
+        if (!r) {
+            try {
+                subs.cancel(msg.getDestination());
+            } catch (const qpid::Exception& e) {
+                mkfailure<bool>(string("Qpid failure: ") + e.what());
+            }
+        }
+    }
+
+private:
+    const lambda<bool(const value&, const value&)> l;
+    qpid::client::SubscriptionManager& subs;
+};
+
+
+const failable<bool> listen(const string& name, const lambda<bool(const value&, const value&)>& l, QpidSubscription& qsub) {
+    debug("queue::listen");
+    Listener listener(l, qsub.subs);
+    try {
+        qsub.subs.subscribe(listener, c_str(name));
+        qsub.subs.run();
+    } catch (const qpid::Exception& e) {
+        return mkfailure<bool>(string("Qpid failure: ") + e.what());
+    }
+    debug("queue::listen::stopped");
+    return true;
+}
+
+/**
+ * Stop an AMQP subscription.
+ */
+const failable<bool> stop(QpidSubscription& qsub) {
+    debug("queue::stop");
+    try {
+        qsub.subs.stop();
+    } catch (const qpid::Exception& e) {
+        return mkfailure<bool>(string("Qpid failure: ") + e.what());
+    }
+    debug("queue::stopped");
     return true;
 }
 

Copied: tuscany/sca-cpp/trunk/components/queue/qpidd-start (from r907470, tuscany/sca-cpp/trunk/test/store-python/stop)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/qpidd-start?p2=tuscany/sca-cpp/trunk/components/queue/qpidd-start&p1=tuscany/sca-cpp/trunk/test/store-python/stop&r1=907470&r2=910819&rev=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/test/store-python/stop (original)
+++ tuscany/sca-cpp/trunk/components/queue/qpidd-start Wed Feb 17 04:14:31 2010
@@ -17,7 +17,8 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-../../modules/http/httpd-stop tmp
-mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
+# Start qpidd
+here=`readlink -f $0`; here=`dirname $here`
 
+qpid_prefix=`cat $here/qpidc.prefix`
+$qpid_prefix/sbin/qpidd &

Copied: tuscany/sca-cpp/trunk/components/queue/qpidd-stop (from r907470, tuscany/sca-cpp/trunk/components/cache/memcached-test)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/qpidd-stop?p2=tuscany/sca-cpp/trunk/components/queue/qpidd-stop&p1=tuscany/sca-cpp/trunk/components/cache/memcached-test&r1=907470&r2=910819&rev=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/memcached-test (original)
+++ tuscany/sca-cpp/trunk/components/queue/qpidd-stop Wed Feb 17 04:14:31 2010
@@ -17,15 +17,10 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
-# Setup
-mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-$mc &
-sleep 1
+# Stop qpidd
+here=`readlink -f $0`; here=`dirname $here`
 
-# Test
-./mcache-test
-rc=$?
+qpid_prefix=`cat $here/qpidc.prefix`
+qpidd="$qpid_prefix/sbin/qpidd"
 
-# Cleanup
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
-return $rc
+kill `ps -f | grep -v grep | grep "${qpidd}" | awk '{ print $2 }'`

Modified: tuscany/sca-cpp/trunk/components/queue/queue-listener.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/queue-listener.cpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/queue/queue-listener.cpp (original)
+++ tuscany/sca-cpp/trunk/components/queue/queue-listener.cpp Wed Feb 17 04:14:31 2010
@@ -28,6 +28,7 @@
 #include "list.hpp"
 #include "value.hpp"
 #include "monad.hpp"
+#include "parallel.hpp"
 #include "qpid.hpp"
 
 // Ignore conversion issues and redundant declarations in Qpid headers
@@ -39,22 +40,107 @@
 namespace tuscany {
 namespace queue {
 
-QpidConnection qc;
+/**
+ * A relay function that posts the AMQP messages it receives to a relay component reference.
+ */
+class relay {
+public:
+    relay(const lambda<value(const list<value>&)>& rel) : rel(rel) {
+    }
+
+    const bool operator()(const value& k, const value& v) const {
+        debug(k, "queue::relay::key");
+        debug(v, "queue::relay::value");
+        const value res = rel(mklist<value>("post", isList(k)? (list<value>)k : mklist<value>(k), v));
+        return true;
+    }
+
+private:
+    const lambda<value(const list<value>&)> rel;
+};
+
+/**
+ * Subscribe and listen to an AMQP queue.
+ */
+class subscribe {
+public:
+    subscribe(const string& qname, const lambda<bool(const value&, const value&)>& l, const QpidSubscription& qsub) : qname(qname), l(l), qsub(qsub) {
+    }
+
+    const failable<bool> operator()() const {
+        gc_pool pool;
+        debug(qname, "queue::subscribe::listen");
+        const failable<bool> r =  listen(qname, l, const_cast<QpidSubscription&>(qsub));
+        debug(qname, "queue::subscribe::stopped");
+        return r;
+    }
+
+private:
+    const string qname;
+    const lambda<bool(const value&, const value&)> l;
+    const QpidSubscription qsub;
+};
+
+/**
+ * Listener lambda function, responsible for starting an AMQP subscription in a worker thread, and
+ * apply any function calls to the listener component. The only supported function is stop(),
+ * called to stop the listener component and shutdown the worker thread.
+ */
+class listener {
+public:
+    listener(QpidConnection& qc, QpidSession& qs, QpidSubscription& qsub, worker& w) : qc(qc), qs(qs), qsub(qsub), w(w) {
+    }
+
+    const value operator()(const list<value>& params) const {
+        const tuscany::value func(car(params));
+
+        // Stop the component
+        if (func != "stop")
+            return tuscany::mkfailure<tuscany::value>();
+        debug("queue::listener::stop");
+
+        // TODO check why stop() and close() hang in child processes
+        //stop(const_cast<QpidSubscription&>(qsub));
+        //close(const_cast<QpidSession&>(qs));
+        //close(const_cast<QpidConnection&>(qc));
+        cancel(const_cast<worker&>(w));
+
+        debug("queue::listener::stopped");
+        return failable<value>(value(lambda<value(const list<value>&)>()));
+    }
+
+private:
+    QpidConnection qc;
+    QpidSession qs;
+    QpidSubscription qsub;
+    worker w;
+};
 
 /**
- * Initialize the component.
+ * Start the component.
  */
 const failable<value> start(const list<value>& params) {
-    QpidSession qs(qc);
+    // Extract the relay reference and the AMQP key and queue name
+    const value rel = car(params);
+    const value pk = ((lambda<value(list<value>)>)cadr(params))(list<value>());
+    const value key = isList(pk)? (list<value>)pk : mklist<value>(pk);
+    const value qname = ((lambda<value(list<value>)>)caddr(params))(list<value>());
+
+    // Create an AMQP session
+    QpidConnection qc(false);
+    QpidSession qs(qc, false);
 
     // Declare the configured AMQP key / queue pair
-    const value key = ((lambda<value(list<value>)>)caddr(params))(list<value>());
-    const value qname = ((lambda<value(list<value>)>)cadddr(params))(list<value>());
     declareQueue(key, qname, qs);
 
-    //TODO create a subscription and mark the current server instance busy
+    // Listen and relay messages in a worker thread
+    QpidSubscription qsub(qs, false);
+    worker w(3);
+    const lambda<bool(const value&, const value&)> rl = relay(rel);
+    submit<failable<bool> >(w, lambda<failable<bool>()>(subscribe(qname, rl, qsub)));
 
-    return value(true);
+    // Return the listener component lambda function
+    return value(lambda<value(const list<value>&)>(listener(qc, qs, qsub, w)));
 }
 
 }
@@ -64,7 +150,7 @@
 
 const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
     const tuscany::value func(car(params));
-    if (func == "start")
+    if (func == "start" || func == "restart")
         return tuscany::queue::start(cdr(params));
     return tuscany::mkfailure<tuscany::value>();
 }

Modified: tuscany/sca-cpp/trunk/components/queue/queue-sender.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/queue-sender.cpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/queue/queue-sender.cpp (original)
+++ tuscany/sca-cpp/trunk/components/queue/queue-sender.cpp Wed Feb 17 04:14:31 2010
@@ -39,19 +39,22 @@
 namespace tuscany {
 namespace queue {
 
-QpidConnection qc;
-
 /**
  * Post an item to a queue.
  */
 const failable<value> post(const list<value>& params) {
+    QpidConnection qc;
     QpidSession qs(qc);
 
     // Post the item
-    const value key = ((lambda<value(list<value>)>)cadr(params))(list<value>());
-    post(key, car(params), qs);
-
-    return value(true);
+    const value pk = ((lambda<value(list<value>)>)caddr(params))(list<value>());
+    const value key = isList(pk)? append<value>(pk, (list<value>)car(params)) : cons<value>(pk, (list<value>)car(params));
+    debug(key, "queue::post::key");
+    debug(cadr(params), "queue::post::value");
+    const failable<bool> r = post(key, cadr(params), qs);
+    if (!hasContent(r))
+        return mkfailure<value>(reason(r));
+    return key;
 }
 
 }

Modified: tuscany/sca-cpp/trunk/components/queue/queue.composite
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/queue.composite?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/queue/queue.composite (original)
+++ tuscany/sca-cpp/trunk/components/queue/queue.composite Wed Feb 17 04:14:31 2010
@@ -22,15 +22,15 @@
   targetNamespace="http://tuscany.apache.org/xmlns/sca/components"
   name="queue">
         
-    <component name="queue-sender">
+    <component name="print-sender">
         <implementation.cpp path=".libs" library="libqueue-sender"/>
         <property name="key">print</property>
-        <service name="queue-sender">
+        <service name="print-sender">
             <t:binding.http uri="print-sender"/>
         </service>
     </component>
 
-    <component name="queue-listener">
+    <component name="print-listener">
         <implementation.cpp path=".libs" library="libqueue-listener"/>
         <property name="key">print</property>
         <property name="queue">printq</property>
@@ -42,6 +42,15 @@
         <service name="print">
             <t:binding.http uri="print"/>
         </service>
+        <reference name="report" target="report-sender"/>
+    </component>     
+
+    <component name="report-sender">
+        <implementation.cpp path=".libs" library="libqueue-sender"/>
+        <property name="key">report</property>
+        <service name="report-sender">
+            <t:binding.http uri="report-sender"/>
+        </service>
     </component>     
 
 </composite>

Copied: tuscany/sca-cpp/trunk/components/queue/send-test (from r907470, tuscany/sca-cpp/trunk/components/cache/memcached-test)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/send-test?p2=tuscany/sca-cpp/trunk/components/queue/send-test&p1=tuscany/sca-cpp/trunk/components/cache/memcached-test&r1=907470&r2=910819&rev=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/memcached-test (original)
+++ tuscany/sca-cpp/trunk/components/queue/send-test Wed Feb 17 04:14:31 2010
@@ -18,14 +18,14 @@
 #  under the License.
 
 # Setup
-mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-$mc &
+./qpidd-start
 sleep 1
 
 # Test
-./mcache-test
+./qpid-test 2>/dev/null
 rc=$?
 
 # Cleanup
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
+./qpidd-stop
+sleep 1
 return $rc

Copied: tuscany/sca-cpp/trunk/components/queue/server-test (from r907470, tuscany/sca-cpp/trunk/components/cache/server-test)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/server-test?p2=tuscany/sca-cpp/trunk/components/queue/server-test&p1=tuscany/sca-cpp/trunk/components/cache/server-test&r1=907470&r2=910819&rev=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/cache/server-test (original)
+++ tuscany/sca-cpp/trunk/components/queue/server-test Wed Feb 17 04:14:31 2010
@@ -23,21 +23,21 @@
 ../../modules/server/scheme-conf tmp
 cat >>tmp/conf/httpd.conf <<EOF
 SCAContribution `pwd`/
-SCAComposite mcache.composite
+SCAComposite queue.composite
 EOF
 
+./qpidd-start
+sleep 1
 ../../modules/http/httpd-start tmp
-
-mc="memcached -l 127.0.0.1 -m 4 -p 11211"
-$mc &
 sleep 2
 
 # Test
-./client-test
+./client-test 2>/dev/null
 rc=$?
 
 # Cleanup
-kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
 ../../modules/http/httpd-stop tmp
-sleep 2
+sleep 1
+./qpidd-stop
+sleep 1
 return $rc

Modified: tuscany/sca-cpp/trunk/components/queue/server-test.scm
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/queue/server-test.scm?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/queue/server-test.scm (original)
+++ tuscany/sca-cpp/trunk/components/queue/server-test.scm Wed Feb 17 04:14:31 2010
@@ -17,4 +17,4 @@
 
 ; Queue test case
 
-(define (print x) (display x))
+(define (post key val report) (report "post" '() val))

Modified: tuscany/sca-cpp/trunk/components/webservice/echo-test
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/webservice/echo-test?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/webservice/echo-test (original)
+++ tuscany/sca-cpp/trunk/components/webservice/echo-test Wed Feb 17 04:14:31 2010
@@ -28,7 +28,7 @@
 sleep 1
 
 # Test
-./axis2-test
+./axis2-test 2>/dev/null
 rc=$?
 
 # Cleanup

Modified: tuscany/sca-cpp/trunk/components/webservice/server-test
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/webservice/server-test?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/webservice/server-test (original)
+++ tuscany/sca-cpp/trunk/components/webservice/server-test Wed Feb 17 04:14:31 2010
@@ -39,7 +39,7 @@
 sleep 2
 
 # Test
-./client-test
+./client-test 2>/dev/null
 rc=$?
 
 # Cleanup

Modified: tuscany/sca-cpp/trunk/components/webservice/webservice-client.cpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/components/webservice/webservice-client.cpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/components/webservice/webservice-client.cpp (original)
+++ tuscany/sca-cpp/trunk/components/webservice/webservice-client.cpp Wed Feb 17 04:14:31 2010
@@ -57,7 +57,7 @@
 
 const tuscany::value apply(const tuscany::list<tuscany::value>& params) {
     const tuscany::value func(car(params));
-    if (func == "start" || func == "stop" || func == "restart")
+    if (func == "start" || func == "restart")
         return tuscany::mkfailure<tuscany::value>();
     return tuscany::webservice::apply(func, cdr(params));
 }

Modified: tuscany/sca-cpp/trunk/configure.ac
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/configure.ac?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/configure.ac (original)
+++ tuscany/sca-cpp/trunk/configure.ac Wed Feb 17 04:14:31 2010
@@ -341,8 +341,8 @@
   esac ],
 [ AC_MSG_RESULT(no)])
 if test "${want_java}" = "true"; then
-  LIBS="-L${JAVA_LIB} ${default_LIBS}"
-  #AC_CHECK_LIB([java], [JNI_OnLoad], [], [AC_MSG_ERROR([couldn't find a suitable libjava, use --with-java=PATH])])
+  LIBS="-L${JAVA_LIB} -L${JAVA_LIB}/server ${default_LIBS}"
+  AC_CHECK_LIB([java], [JNI_CreateJavaVM], [], [AC_MSG_ERROR([couldn't find a suitable libjava, use --with-java=PATH])], [-ljvm -lverify])
   AC_PROG_JAVAC
   AC_PROG_JAR
   AM_CONDITIONAL([WANT_JAVA], true)
@@ -441,8 +441,11 @@
   esac ],
 [ AC_MSG_RESULT(no)])
 if test "${want_queue}" = "true"; then
+  if test "${want_threads}" != "true"; then
+    AC_MSG_ERROR([--enable-queue requires multi-threading, use --enable-threads])
+  fi
   LIBS="-L${QPIDC_LIB} ${default_LIBS}"
-  #AC_CHECK_LIB([qpidclient], [], [], [AC_MSG_ERROR([couldn't find a suitable libqpidclient, use --with-qpidc=PATH])])
+  AC_CHECK_LIB([qpidclient], [_init], [], [AC_MSG_ERROR([couldn't find a suitable libqpidclient, use --with-qpidc=PATH])])
   AM_CONDITIONAL([WANT_QUEUE], true)
   AC_DEFINE([WANT_QUEUE], 1, [enable Queue component])
 else
@@ -451,7 +454,7 @@
 
 # Configure path to Libstrophe includes and lib.
 AC_MSG_CHECKING([for libstrophe])
-AC_ARG_WITH([libstrophe], [AC_HELP_STRING([--with-libstrophe=PATH], [path to libstrophe source build [default=${HOME}/libstrophe]])], [
+AC_ARG_WITH([libstrophe], [AC_HELP_STRING([--with-libstrophe=PATH], [path to libstrophe source [default=${HOME}/libstrophe]])], [
   LIBSTROPHE_INCLUDE="${withval}"
   LIBSTROPHE_LIB="${withval}"
   AC_MSG_RESULT("${withval}")
@@ -477,8 +480,11 @@
   esac ],
 [ AC_MSG_RESULT(no)])
 if test "${want_chat}" = "true"; then
+  if test "${want_threads}" != "true"; then
+    AC_MSG_ERROR([--enable-chat requires multi-threading, use --enable-threads])
+  fi
   LIBS="-L${LIBSTROPHE_LIB} ${default_LIBS}"
-  #AC_CHECK_LIB([strophe], [xmpp_initialize], [], [AC_MSG_ERROR([couldn't find a suitable libstrophe, use --with-libstrophe=PATH])], [-lexpat -lssl -lresolv])
+  AC_CHECK_LIB([strophe], [xmpp_initialize], [], [AC_MSG_ERROR([couldn't find a suitable libstrophe, use --with-libstrophe=PATH])], [-lexpat -lssl -lresolv])
   AM_CONDITIONAL([WANT_CHAT], true)
   AC_DEFINE([WANT_CHAT], 1, [enable Chat component])
 else

Modified: tuscany/sca-cpp/trunk/etc/git-exclude
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/etc/git-exclude?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/etc/git-exclude (original)
+++ tuscany/sca-cpp/trunk/etc/git-exclude Wed Feb 17 04:14:31 2010
@@ -20,6 +20,7 @@
 .settings/
 .deployables/
 .wtpmodules/
+.pydevproject
 .svn/
 .cvs/
 .dotest/
@@ -85,4 +86,5 @@
 axiom-test
 axis2-test
 qpid-test
+xmpp-test
 

Modified: tuscany/sca-cpp/trunk/kernel/element.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/kernel/element.hpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/kernel/element.hpp (original)
+++ tuscany/sca-cpp/trunk/kernel/element.hpp Wed Feb 17 04:14:31 2010
@@ -193,7 +193,7 @@
     const list<value> valuesToElements(const list<value>& l);
 
     // Convert a name value pair
-    if (isList(t) && isSymbol(car<value>(t))) {
+    if (isList(t) && !isNil((list<value>)t) && isSymbol(car<value>(t))) {
         const value n = car<value>(t);
         const value v = cadr<value>(t);
 

Modified: tuscany/sca-cpp/trunk/kernel/parallel.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/kernel/parallel.hpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/kernel/parallel.hpp (original)
+++ tuscany/sca-cpp/trunk/kernel/parallel.hpp Wed Feb 17 04:14:31 2010
@@ -59,9 +59,12 @@
             pthread_cond_init(&valueCond, NULL);
         }
 
+        futureValue(const futureValue& fv) : valueMutex(fv.valueMutex), valueCond(fv.valueCond), hasValue(fv.hasValue), value(fv.value) {
+        }
+
         ~futureValue() {
-            pthread_mutex_destroy(&valueMutex);
-            pthread_cond_destroy(&valueCond);
+            //pthread_mutex_destroy(&valueMutex);
+            //pthread_cond_destroy(&valueCond);
         }
 
         bool set(const T& v) {
@@ -129,18 +132,21 @@
 /**
  * A bounded thread safe queue.
  */
-template<typename T> class queue {
+template<typename T> class wqueue {
 public:
-    queue(int max) : max(max), size(0), tail(0), head(0), values(new (gc_anew<T>(max)) T[max]) {
+    wqueue(int max) : max(max), size(0), tail(0), head(0), values(new (gc_anew<T>(max)) T[max]) {
         pthread_mutex_init(&mutex, NULL);
         pthread_cond_init(&full, NULL);
         pthread_cond_init(&empty, NULL);
     }
 
-    ~queue() {
-        pthread_mutex_destroy(&mutex);
-        pthread_cond_destroy(&full);
-        pthread_cond_destroy(&empty);
+    wqueue(const wqueue& wq) : max(wq.max), size(wq.size), tail(wq.tail), head(wq.head), mutex(wq.mutex), full(wq.full), empty(wq.empty), values(wq.values) {
+    }
+
+    ~wqueue() {
+        //pthread_mutex_destroy(&mutex);
+        //pthread_cond_destroy(&full);
+        //pthread_cond_destroy(&empty);
     }
 
 private:
@@ -153,14 +159,14 @@
     pthread_cond_t empty;
     gc_ptr<T> values;
 
-    template<typename X> friend const int enqueue(queue<X>& q, const X& v);
-    template<typename X> friend const X dequeue(queue<X>& q);
+    template<typename X> friend const int enqueue(wqueue<X>& q, const X& v);
+    template<typename X> friend const X dequeue(wqueue<X>& q);
 };
 
 /**
  * Adds an element to the tail of the queue.
  */
-template<typename T> const int enqueue(queue<T>&q, const T& v) {
+template<typename T> const int enqueue(wqueue<T>&q, const T& v) {
     pthread_mutex_lock(&q.mutex);
     while(q.size == q.max)
         pthread_cond_wait(&q.full, &q.mutex);
@@ -175,7 +181,7 @@
 /**
  * Returns the element at the head of the queue.
  */
-template<typename T> const T dequeue(queue<T>& q) {
+template<typename T> const T dequeue(wqueue<T>& q) {
     pthread_mutex_lock(&q.mutex);
     while(q.size == 0)
         pthread_cond_wait(&q.empty, &q.mutex);
@@ -191,7 +197,12 @@
  * The worker thread function.
  */
 void *workerThreadFunc(void *arg) {
-    queue<lambda<bool()> >* work = reinterpret_cast<queue<lambda<bool()> >*>(arg);
+    int ost;
+    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ost);
+    int ot;
+    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &ot);
+
+    wqueue<lambda<bool()> >* work = reinterpret_cast<wqueue<lambda<bool()> >*>(arg);
     while(dequeue(*work)())
         ;
     return NULL;
@@ -200,28 +211,44 @@
 /**
  * Returns a list of worker threads.
  */
-const list<pthread_t> workerThreads(queue<lambda<bool()> >& queue, const int count) {
+const list<pthread_t> workerThreads(wqueue<lambda<bool()> >& wqueue, const int count) {
     if (count == 0)
         return list<pthread_t>();
     pthread_t thread;
-    pthread_create(&thread, NULL, workerThreadFunc, &queue);
-    return cons(thread, workerThreads(queue, count - 1));
+    pthread_create(&thread, NULL, workerThreadFunc, &wqueue);
+    return cons(thread, workerThreads(wqueue, count - 1));
 }
 
 /**
  * A worker, implemented with a work queue and a pool of threads.
  */
 class worker {
+private:
+
+    // The worker holds a reference to a sharedWorker, to avoid non-thread-safe
+    // copies of the queue and thread pool when a worker is copied 
+    class sharedWorker {
+    public:
+        sharedWorker(int max) : work(wqueue<lambda<bool()> >(max)), threads(workerThreads(work, max)) {
+        }
+
+        wqueue<lambda<bool()> > work;
+        const list<pthread_t> threads;
+    };
+
 public:
-    worker(int max) : work(queue<lambda<bool()> >(max)), threads(workerThreads(work, max)) {
+    worker(int max) : w(*(new (gc_new<sharedWorker>()) sharedWorker(max))) {
+    }
+
+    worker(const worker& wk) : w(wk.w) {
     }
 
 private:
-    queue<lambda<bool()> > work;
-    const list<pthread_t> threads;
+    sharedWorker& w;
 
     template<typename X> friend const future<X> submit(worker& w, const lambda<X()>& func);
     friend const bool shutdown(worker& w);
+    friend const bool cancel(worker& w);
 };
 
 /**
@@ -238,14 +265,14 @@
 template<typename R> const future<R> submit(worker& w, const lambda<R()>& func) {
     const future<R> fut;
     const lambda<bool()> f = curry(lambda<bool(const lambda<R()>, future<R>)>(submitFunc<R>), func, fut);
-    enqueue(w.work, f);
+    enqueue(w.w.work, f);
     return fut;
 }
 
 /**
  * Enqueues shutdown requests.
  */
-const bool shutdownEnqueue(const list<pthread_t>& threads, queue<lambda<bool()> >& work) {
+const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<lambda<bool()> >& work) {
     if (isNil(threads))
         return true;
     enqueue(work, result(false));
@@ -266,8 +293,23 @@
  * Shutdown a worker.
  */
 const bool shutdown(worker& w) {
-    shutdownEnqueue(w.threads, w.work);
-    shutdownJoin(w.threads);
+    shutdownEnqueue(w.w.threads, w.w.work);
+    shutdownJoin(w.w.threads);
+    return true;
+}
+
+/**
+ * Cancel a worker.
+ */
+const bool cancel(const list<pthread_t>& threads) {
+    if (isNil(threads))
+        return true;
+    pthread_cancel(car(threads));
+    return cancel(cdr(threads));
+}
+
+const bool cancel(worker& w) {
+    cancel(w.w.threads);
     return true;
 }
 

Modified: tuscany/sca-cpp/trunk/kernel/value.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/kernel/value.hpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/kernel/value.hpp (original)
+++ tuscany/sca-cpp/trunk/kernel/value.hpp Wed Feb 17 04:14:31 2010
@@ -556,5 +556,29 @@
     return cons<value>(car(l), mkvalues(cdr(l)));
 }
 
+/**
+ * Convert a path string value to a list of values.
+ */
+const list<string> pathTokens(const char* p) {
+    if (p == NULL || p[0] == '\0')
+        return list<string>();
+    if (p[0] == '/')
+        return tokenize("/", p + 1);
+    return tokenize("/", p);
+}
+
+const list<value> pathValues(const value& p) {
+    return mkvalues(pathTokens(c_str(p)));
+}
+
+/**
+ * Convert a path represented as a list of values to a string value.
+ */
+const value path(const list<value>& p) {
+    if (isNil(p))
+        return "";
+    return string("/") + car(p) + path(cdr(p));
+}
+
 }
 #endif /* tuscany_value_hpp */

Modified: tuscany/sca-cpp/trunk/modules/http/curl.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/http/curl.hpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/http/curl.hpp (original)
+++ tuscany/sca-cpp/trunk/modules/http/curl.hpp Wed Feb 17 04:14:31 2010
@@ -252,7 +252,7 @@
     if (!hasContent(l))
         return mkfailure<value>(reason(l));
     const string ls(content(l));
-    return value(string(substr(ls, find_last(ls, '/') + 1)));
+    return value(mklist<value>(string(substr(ls, find_last(ls, '/') + 1))));
 }
 
 /**
@@ -381,18 +381,18 @@
  * HTTP client proxy function.
  */
 struct proxy {
-    proxy(const string& url) : url(url) {
+    proxy(const string& uri) : uri(uri) {
     }
 
     const value operator()(const list<value>& args) const {
         CURLSession cs;
-        failable<value> val = evalExpr(args, url, cs);
+        failable<value> val = evalExpr(args, uri, cs);
         if (!hasContent(val))
             return value();
         return content(val);
     }
 
-    const string url;
+    const string uri;
 };
 
 }

Modified: tuscany/sca-cpp/trunk/modules/http/httpd.hpp
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/http/httpd.hpp?rev=910819&r1=910818&r2=910819&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/http/httpd.hpp (original)
+++ tuscany/sca-cpp/trunk/modules/http/httpd.hpp Wed Feb 17 04:14:31 2010
@@ -75,30 +75,6 @@
 
 
 /**
- * Convert a path string to a list of values.
- */
-const list<string> pathTokens(const char* p) {
-    if (p == NULL || p[0] == '\0')
-        return list<string>();
-    if (p[0] == '/')
-        return tokenize("/", p + 1);
-    return tokenize("/", p);
-}
-
-const list<value> pathValues(const char* p) {
-    return mkvalues(pathTokens(p));
-}
-
-/**
- * Convert a path represented as a list of values to a string.
- */
-const string path(const list<value>& p) {
-    if (isNil(p))
-        return "";
-    return string("/") + car(p) + path(cdr(p));
-}
-
-/**
  * Return the content type of a request.
  */
 const char* optional(const char* s) {
@@ -219,10 +195,10 @@
 }
 
 /**
- * Convert a URI value to an absolute URL.
+ * Convert a URI represented as a list to an absolute URL.
  */
-const char* url(const value& v, request_rec* r) {
-    const string u = string(r->uri) + "/" + v;
+const char* url(const list<value>& v, request_rec* r) {
+    const string u = string(r->uri) + path(v);
     return ap_construct_url(r->pool, c_str(u), r);
 }
 
@@ -400,7 +376,7 @@
 /**
  * Put a value in the process user data.
  */
-const bool putUserData(const string& k, const int v, const server_rec* s) {
+const bool putUserData(const string& k, const void* v, const server_rec* s) {
     apr_pool_userdata_set((const void *)v, c_str(k), apr_pool_cleanup_null, s->process->pool);
     return true;
 }
@@ -408,10 +384,10 @@
 /**
  * Return a user data value.
  */
-const int userData(const string& k, const server_rec* s) {
-    void* v = (int)0;
+const void* userData(const string& k, const server_rec* s) {
+    void* v = NULL;
     apr_pool_userdata_get(&v, c_str(k), s->process->pool);
-    return (int)v;
+    return v;
 }
 
 }