summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--cpp/etc/git-exclude69
-rw-r--r--cpp/sca/configure.ac9
-rw-r--r--cpp/sca/etc/git-exclude5
-rw-r--r--cpp/sca/modules/Makefile.am2
-rw-r--r--cpp/sca/modules/atom/Makefile.am2
-rw-r--r--cpp/sca/modules/cache/Makefile.am13
-rw-r--r--cpp/sca/modules/cache/cache.hpp133
-rw-r--r--cpp/sca/modules/cache/diskcache-test.cpp (renamed from cpp/sca/modules/cache/cache-test.cpp)40
-rwxr-xr-xcpp/sca/modules/cache/diskcached-test27
-rw-r--r--cpp/sca/modules/cache/memcache-test.cpp96
-rwxr-xr-xcpp/sca/modules/cache/memcached-test2
-rw-r--r--cpp/sca/modules/cache/memcached.hpp143
-rw-r--r--cpp/sca/modules/eval/Makefile.am2
-rw-r--r--cpp/sca/modules/http/Makefile.am13
-rw-r--r--cpp/sca/modules/json/Makefile.am2
-rw-r--r--cpp/sca/modules/scdl/Makefile.am28
-rwxr-xr-xcpp/sca/modules/scdl/scdl-testbin0 -> 477277 bytes
-rw-r--r--cpp/sca/modules/scdl/scdl-test.cpp119
-rw-r--r--cpp/sca/modules/scdl/scdl.hpp158
-rw-r--r--cpp/sca/modules/scdl/test.composite67
-rw-r--r--cpp/sca/test/store-function/Makefile.am2
-rw-r--r--cpp/sca/test/store-object/Makefile.am2
22 files changed, 775 insertions, 159 deletions
diff --git a/cpp/etc/git-exclude b/cpp/etc/git-exclude
deleted file mode 100644
index dd9e85e738..0000000000
--- a/cpp/etc/git-exclude
+++ /dev/null
@@ -1,69 +0,0 @@
-# git-ls-files --others --exclude-from=.git/info/exclude
-# Lines that start with '#' are comments.
-# For a project mostly in C, the following would be a good set of
-# exclude patterns (uncomment them if you want to use them):
-# *.[oa]
-# *~
-
-# Generic ignores
-target/
-work/
-tmp/
-build/
-*_build
-.project
-.cproject
-.classpath
-*.log
-junit*.properties
-surefire*.properties
-.settings/
-.deployables/
-.wtpmodules/
-.svn/
-.cvs/
-.dotest/
-*.la
-*.lo
-*.o
-*.in
-Makefile
-.deps/
-.libs/
-*.m4
-config.guess
-config.sub
-config.status
-depcomp
-install-sh
-ltmain.sh
-missing
-stamp-h1
-autom4te.cache/
-deploy/
-libtool
-configure
-config.h
-Doxyfile
-*.tar
-*.tar.gz
-*-bin/
-*-src/
-*_Proxy.cpp
-*_Proxy.h
-*_Wrapper.cpp
-*_Wrapper.h
-gmon.out
-
-# Specific ignores
-tuscany_sdo_test
-sdo/runtime/core/test/
-sca/runtime/extensions/cpp/tools/scagen/docs/
-account_client
-calculator_client
-sdo_misc
-store-test
-store2-test
-core-test
-xml-test
-
diff --git a/cpp/sca/configure.ac b/cpp/sca/configure.ac
index 30f263a73a..22eae7f4e3 100644
--- a/cpp/sca/configure.ac
+++ b/cpp/sca/configure.ac
@@ -93,11 +93,11 @@ fi
# Configure LIBMOZJS_INCLUDE and LIBMOZJS_LIB
LIBMOZJS_INCLUDE=`echo "$LIBMOZJS_INCLUDE"`
if test "x$LIBMOZJS_INCLUDE" = "x"; then
- AC_SUBST([LIBMOZJS_INCLUDE], ["/usr/include/xulrunner-1.9.1.3/unstable"])
+ AC_SUBST([LIBMOZJS_INCLUDE], ["/usr/include/xulrunner-1.9.1.5/unstable"])
fi
LIBMOZJS_LIB=`echo "$LIBMOZJS_LIB"`
if test "x$LIBMOZJS_LIB" = "x"; then
- AC_SUBST([LIBMOZJS_LIB], ["/usr/lib/xulrunner-1.9.1.3"])
+ AC_SUBST([LIBMOZJS_LIB], ["/usr/lib/xulrunner-1.9.1.5"])
fi
# Configure GCC C++ compile options
@@ -263,6 +263,10 @@ if test x$want_doxygen = xyes; then
fi
AM_CONDITIONAL([WANT_DOXYGEN], [test x$want_doxygen = xtrue])
+# Configure exuberant ctags
+TAGSFILE="`pwd`/tags"
+AC_SUBST([CTAGSFLAGS], ["$(CTAGSFLAGS) --c++-kinds=+p --fields=+iaS --extra=+q --append --tag-relative=yes -f $TAGSFILE"])
+
AC_CONFIG_FILES([Makefile
kernel/Makefile
modules/Makefile
@@ -271,6 +275,7 @@ AC_CONFIG_FILES([Makefile
modules/eval/Makefile
modules/http/Makefile
modules/json/Makefile
+ modules/scdl/Makefile
test/Makefile
test/store-object/Makefile
test/store-function/Makefile
diff --git a/cpp/sca/etc/git-exclude b/cpp/sca/etc/git-exclude
index fd55cecff2..d9198b48ce 100644
--- a/cpp/sca/etc/git-exclude
+++ b/cpp/sca/etc/git-exclude
@@ -55,6 +55,7 @@ Doxyfile
*_Wrapper.h
gmon.out
*~
+tags
# Specific ignores
sca/runtime/extensions/cpp/tools/scagen/docs/
@@ -66,8 +67,10 @@ atom-test
eval-test
eval-shell
json-test
-cache-test
+diskcache-test
+memcache-test
curl-test
+scdl-test
store-function-test
store-object-test
store-script-test
diff --git a/cpp/sca/modules/Makefile.am b/cpp/sca/modules/Makefile.am
index dd085903f0..89256ae1a0 100644
--- a/cpp/sca/modules/Makefile.am
+++ b/cpp/sca/modules/Makefile.am
@@ -15,5 +15,5 @@
# specific language governing permissions and limitations
# under the License.
-SUBDIRS = atom cache eval http json
+SUBDIRS = atom cache eval http json scdl
diff --git a/cpp/sca/modules/atom/Makefile.am b/cpp/sca/modules/atom/Makefile.am
index 2e4eb4b89f..61998ece8b 100644
--- a/cpp/sca/modules/atom/Makefile.am
+++ b/cpp/sca/modules/atom/Makefile.am
@@ -17,6 +17,8 @@
noinst_PROGRAMS = atom-test
+nobase_include_HEADERS = *.hpp
+
INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
atom_test_SOURCES = atom-test.cpp
diff --git a/cpp/sca/modules/cache/Makefile.am b/cpp/sca/modules/cache/Makefile.am
index 581b8b6682..0597e91804 100644
--- a/cpp/sca/modules/cache/Makefile.am
+++ b/cpp/sca/modules/cache/Makefile.am
@@ -15,12 +15,17 @@
# specific language governing permissions and limitations
# under the License.
-noinst_PROGRAMS = cache-test
+noinst_PROGRAMS = diskcache-test memcache-test
+
+nobase_include_HEADERS = *.hpp
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
+diskcache_test_SOURCES = diskcache-test.cpp
+diskcache_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
+
+memcache_test_SOURCES = memcache-test.cpp
+memcache_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
-TESTS = memcached-test
+TESTS = memcached-test diskcached-test
diff --git a/cpp/sca/modules/cache/cache.hpp b/cpp/sca/modules/cache/cache.hpp
index d4a24ca3d9..ba66021f3d 100644
--- a/cpp/sca/modules/cache/cache.hpp
+++ b/cpp/sca/modules/cache/cache.hpp
@@ -23,100 +23,97 @@
#define tuscany_cache_hpp
/**
- * Memcached access functions.
+ * Simple cache monad implementation.
*/
-#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 <sys/stat.h>
#include <string>
-#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
namespace tuscany {
namespace cache {
-class Cache {
+/**
+ * Cached monad. Used to represent a value that can be cached.
+ * To get the value in the monad, just cast it to the value type.
+ */
+template<typename V> class cached {
public:
- Cache() {
- apr_pool_create(&pool, NULL);
- apr_memcache_create(pool, 1, 0, &mc);
+ cached() : mtime(0) {
}
- ~Cache() {
- apr_pool_destroy(pool);
+
+ cached(const lambda<V()>& lvalue, const lambda<unsigned long()> ltime) : lvalue(lvalue), ltime(ltime), mtime(0) {
}
- operator apr_memcache_t*() const {
- return mc;
+ cached(const lambda<V()>& lvalue, const lambda<unsigned long()> ltime, const unsigned long mtime, const V& v) : lvalue(lvalue), ltime(ltime), mtime(mtime), v(v) {
}
- operator apr_pool_t*() const {
- return pool;
+ cached(const cached<V>& c) : lvalue(c.lvalue), ltime(c.ltime), mtime(c.mtime), v(c.v) {
}
-private:
- apr_pool_t* pool;
- apr_memcache_t* mc;
+ operator const V() const {
+ return v;
+ }
-};
+ const cached<V>& operator=(const cached<V>& c) {
+ if(this == &c)
+ return *this;
+ this->lvalue = c.lvalue;
+ this->ltime = c.ltime;
+ this->mtime = c.mtime;
+ this->v = c.v;
+ return *this;
+ }
-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 bool operator!=(const cached<V>& m) const {
+ return !this->operator==(m);
+ }
-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 bool operator==(const cached<V>& m) const {
+ if (this == &m)
+ return true;
+ return mtime == m.mtime && v == m.v;
+ }
-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;
-}
+private:
+ lambda<V()> lvalue;
+ lambda<time_t()> ltime;
+ unsigned long mtime;
+ V v;
-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");
- }
+ template<typename X> friend const cached<X> latest(const cached<X>& c);
+ template<typename X> friend std::ostream& operator<<(std::ostream& out, const cached<X>& c);
+};
- const value val(std::string(data, size));
- apr_pool_destroy(vpool);
- return val;
+/**
+ * Write a cached monad to a stream.
+ */
+template<typename V> std::ostream& operator<<(std::ostream& out, const cached<V>& c) {
+ out << c.v;
+ return out;
}
-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;
+/**
+ * Returns the latest value of a cached monad.
+ */
+template<typename V> const cached<V> latest(const cached<V>& c) {
+ unsigned long nt = c.ltime();
+ if (nt == c.mtime)
+ return c;
+ return cached<V>(c.lvalue, c.ltime, nt, c.lvalue());
+}
+
+/**
+ * Returns the latest modification time of a file.
+ */
+const unsigned long latestFileTime(const std::string& path) {
+ struct stat st;
+ int rc = stat(path.c_str(), &st);
+ if (rc < 0)
+ return 0;
+ return st.st_mtim.tv_nsec;
}
}
diff --git a/cpp/sca/modules/cache/cache-test.cpp b/cpp/sca/modules/cache/diskcache-test.cpp
index 776ac72363..3b21de7b9e 100644
--- a/cpp/sca/modules/cache/cache-test.cpp
+++ b/cpp/sca/modules/cache/diskcache-test.cpp
@@ -20,28 +20,50 @@
/* $Rev$ $Date$ */
/**
- * Test Memcached access functions.
+ * Test cache functions.
*/
#include <assert.h>
+#include <sys/time.h>
+#include <time.h>
#include <iostream>
#include <string>
+#include <fstream>
+#include "slist.hpp"
#include "cache.hpp"
namespace tuscany {
namespace cache {
+const std::string fileRead(const std::string path) {
+ std::ifstream is(path);
+ return car(streamList(is));
+}
+
bool testCache() {
- Cache cache;
- addServer("localhost", 11311, cache);
+ const std::string p("tmp/test.txt");
+ const lambda<std::string(std::string)> fr(fileRead);
+ const lambda<time_t(std::string)> ft(latestFileTime);
+
+ const cached<std::string> c(curry(fr, p), curry(ft, p));
+
+ {
+ std::ofstream os(p);
+ os << "initial";
+ os.close();
+ assert(std::string(latest(c)) == std::string("initial"));
+ }
- 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)));
+ usleep(1000000);
+ {
+ std::ofstream os(p);
+ os << "updated";
+ os.close();
+ assert(latest(c) != c);
+ assert(std::string(latest(c)) == std::string("updated"));
+ assert(latest(c) == latest(c));
+ }
return true;
}
diff --git a/cpp/sca/modules/cache/diskcached-test b/cpp/sca/modules/cache/diskcached-test
new file mode 100755
index 0000000000..4c10abeceb
--- /dev/null
+++ b/cpp/sca/modules/cache/diskcached-test
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Setup
+mkdir -p tmp
+
+# Test
+./diskcache-test
+rc=$?
+
+return $rc
diff --git a/cpp/sca/modules/cache/memcache-test.cpp b/cpp/sca/modules/cache/memcache-test.cpp
new file mode 100644
index 0000000000..3522094126
--- /dev/null
+++ b/cpp/sca/modules/cache/memcache-test.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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 Memcached access functions.
+ */
+
+#include <assert.h>
+#include <sys/time.h>
+#include <time.h>
+#include <iostream>
+#include <string>
+#include <fstream>
+#include "memcached.hpp"
+
+namespace tuscany {
+namespace cache {
+
+bool testMemCached() {
+ memcached::Cache cache;
+ memcached::addServer("localhost", 11311, cache);
+
+ assert(hasValue(memcached::post("a", "AAA", cache)));
+ assert(memcached::get("a", cache) == value(std::string("AAA")));
+ assert(hasValue(memcached::put("a", "aaa", cache)));
+ assert(memcached::get("a", cache) == value(std::string("aaa")));
+ assert(hasValue(memcached::del("a", cache)));
+ assert(!hasValue(memcached::get("a", cache)));
+
+ return true;
+}
+
+const double duration(struct timeval start, struct timeval end, int count) {
+ long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ return (double)t / (double)count;
+}
+
+bool testGetLoop(const int count, memcached::Cache& cache) {
+ if (count == 0)
+ return true;
+ assert(memcached::get("c", cache) == value(std::string("CCC")));
+ return testGetLoop(count - 1, cache);
+}
+
+bool testGetPerf() {
+ const int count = 50;
+ struct timeval start;
+ struct timeval end;
+ {
+ memcached::Cache cache;
+ memcached::addServer("localhost", 11311, cache);
+ assert(hasValue(memcached::post("c", "CCC", cache)));
+
+ testGetLoop(5, cache);
+
+ gettimeofday(&start, NULL);
+
+ testGetLoop(count, cache);
+
+ gettimeofday(&end, NULL);
+ std::cout << "Memcached get test " << duration(start, end, count) << " ms" << std::endl;
+ }
+ return true;
+}
+
+}
+}
+
+int main() {
+ std::cout << "Testing..." << std::endl;
+
+ tuscany::cache::testMemCached();
+ tuscany::cache::testGetPerf();
+
+ std::cout << "OK" << std::endl;
+
+ return 0;
+}
diff --git a/cpp/sca/modules/cache/memcached-test b/cpp/sca/modules/cache/memcached-test
index 2f9870a49b..d0e0dff3de 100755
--- a/cpp/sca/modules/cache/memcached-test
+++ b/cpp/sca/modules/cache/memcached-test
@@ -23,7 +23,7 @@ $cmd &
sleep 1
# Test
-./cache-test
+./memcache-test
rc=$?
# Cleanup
diff --git a/cpp/sca/modules/cache/memcached.hpp b/cpp/sca/modules/cache/memcached.hpp
new file mode 100644
index 0000000000..28bdc0fc89
--- /dev/null
+++ b/cpp/sca/modules/cache/memcached.hpp
@@ -0,0 +1,143 @@
+/*
+ * 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_memcached_hpp
+#define tuscany_memcached_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 memcached {
+
+/**
+ * Represents a memcached context.
+ */
+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;
+
+};
+
+/**
+ * Add a server to the memcached context.
+ */
+const failable<bool, std::string> addServer(const std::string& host, const int port, const 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 mkfailure<bool, std::string>("Could not create server");
+ const apr_status_t as = apr_memcache_add_server(cache, server);
+ if (as != APR_SUCCESS)
+ return mkfailure<bool, std::string>("Could not add server");
+ return true;
+}
+
+/**
+ * Post a new item to the cache.
+ */
+const failable<bool, std::string> post(const value& key, const value& val, const 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 mkfailure<bool, std::string>("Could not add entry");
+ return true;
+}
+
+/**
+ * Update an item in the cache.
+ */
+const failable<bool, std::string> put(const value& key, const value& val, const 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 mkfailure<bool, std::string>("Could not add entry");
+ return true;
+}
+
+/**
+ * Get an item from the cache.
+ */
+const failable<value, std::string> get(const value& key, const Cache& cache) {
+ apr_pool_t* vpool;
+ const apr_status_t pc = apr_pool_create(&vpool, cache);
+ if (pc != APR_SUCCESS)
+ return mkfailure<value, 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 mkfailure<value, std::string>("Could not get entry");
+ }
+
+ const value val(std::string(data, size));
+ apr_pool_destroy(vpool);
+ return val;
+}
+
+/**
+ * Delete an item from the cache
+ */
+const failable<bool, std::string> del(const value& key, const Cache& cache) {
+ const apr_status_t rc = apr_memcache_delete(cache, std::string(key).c_str(), 0);
+ if (rc != APR_SUCCESS)
+ return mkfailure<bool, std::string>("Could not add entry");
+ return true;
+}
+
+}
+}
+
+#endif /* tuscany_memcached_hpp */
diff --git a/cpp/sca/modules/eval/Makefile.am b/cpp/sca/modules/eval/Makefile.am
index b6b85c6965..68e01d42e2 100644
--- a/cpp/sca/modules/eval/Makefile.am
+++ b/cpp/sca/modules/eval/Makefile.am
@@ -20,6 +20,8 @@ noinst_PROGRAMS = eval-test eval-shell
datadir=$(prefix)/modules/eval
nobase_data_DATA = *.xsd
+nobase_include_HEADERS = *.hpp
+
INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
eval_test_SOURCES = eval-test.cpp
diff --git a/cpp/sca/modules/http/Makefile.am b/cpp/sca/modules/http/Makefile.am
index 6fe3b944d1..ba5eadbab4 100644
--- a/cpp/sca/modules/http/Makefile.am
+++ b/cpp/sca/modules/http/Makefile.am
@@ -18,15 +18,20 @@
noinst_PROGRAMS = curl-test
libdir=$(prefix)/lib
-lib_LTLIBRARIES = libmod_tuscany.la
+lib_LTLIBRARIES = libmod_tuscany_eval.la libmod_tuscany_wiring.la
+
+nobase_include_HEADERS = *.hpp
INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${HTTPD_INCLUDE} -I${APR_INCLUDE} -I${LIBMOZJS_INCLUDE} -I${CURL_INCLUDE}
-libmod_tuscany_la_SOURCES = mod.cpp
-libmod_tuscany_la_LIBADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${LIBMOZJS_LIB} -lmozjs
+libmod_tuscany_eval_la_SOURCES = mod-eval.cpp
+libmod_tuscany_eval_la_LIBADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${LIBMOZJS_LIB} -lmozjs
+
+libmod_tuscany_wiring_la_SOURCES = mod-wiring.cpp
+libmod_tuscany_wiring_la_LIBADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${LIBMOZJS_LIB} -lmozjs
curl_test_SOURCES = curl-test.cpp
curl_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${LIBMOZJS_LIB} -lmozjs
-TESTS = httpd-test http-test
+TESTS = httpd-test http-test wiring-test
diff --git a/cpp/sca/modules/json/Makefile.am b/cpp/sca/modules/json/Makefile.am
index 1c4222870c..ab85d910ad 100644
--- a/cpp/sca/modules/json/Makefile.am
+++ b/cpp/sca/modules/json/Makefile.am
@@ -17,6 +17,8 @@
noinst_PROGRAMS = json-test
+nobase_include_HEADERS = *.hpp
+
INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${LIBMOZJS_INCLUDE}
json_test_SOURCES = json-test.cpp
diff --git a/cpp/sca/modules/scdl/Makefile.am b/cpp/sca/modules/scdl/Makefile.am
new file mode 100644
index 0000000000..55a190579c
--- /dev/null
+++ b/cpp/sca/modules/scdl/Makefile.am
@@ -0,0 +1,28 @@
+# 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.
+
+noinst_PROGRAMS = scdl-test
+
+nobase_include_HEADERS = *.hpp
+
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
+
+scdl_test_SOURCES = scdl-test.cpp
+scdl_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
+
+TESTS = scdl-test
+
diff --git a/cpp/sca/modules/scdl/scdl-test b/cpp/sca/modules/scdl/scdl-test
new file mode 100755
index 0000000000..acef45d225
--- /dev/null
+++ b/cpp/sca/modules/scdl/scdl-test
Binary files differ
diff --git a/cpp/sca/modules/scdl/scdl-test.cpp b/cpp/sca/modules/scdl/scdl-test.cpp
new file mode 100644
index 0000000000..c3da1013a8
--- /dev/null
+++ b/cpp/sca/modules/scdl/scdl-test.cpp
@@ -0,0 +1,119 @@
+/*
+ * 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 SCDL read functions.
+ */
+
+#include <assert.h>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include "slist.hpp"
+#include "scdl.hpp"
+
+namespace tuscany {
+namespace scdl {
+
+bool testComposite() {
+ std::ifstream is("test.composite");
+ const list<value> c = readXML(streamList(is));
+ return true;
+}
+
+bool testComponents() {
+ std::ifstream is("test.composite");
+ const list<value> c = components(readXML(streamList(is)));
+ assert(length(c) == 4);
+
+ const value store = car(c);
+ assert(name(store) == std::string("Store"));
+ const value impl = implementation(store);
+ assert(uri(impl) == std::string("store.html"));
+ assert(implementationType(impl) == "t:implementation.widget");
+
+ const value catalog = named(std::string("Catalog"), c);
+ assert(name(catalog) == std::string("Catalog"));
+ return true;
+}
+
+bool testServices() {
+ std::ifstream is("test.composite");
+ const list<value> c = components(readXML(streamList(is)));
+ const value store = car(c);
+
+ assert(length(services(store)) == 1);
+ const value widget = car(services(store));
+ assert(name(widget) == std::string("Widget"));
+
+ assert(length(bindings(widget)) == 1);
+ const value binding = car(bindings(widget));
+ assert(uri(binding) == std::string("/store"));
+ assert(bindingType(binding) == "t:binding.http");
+ return true;
+}
+
+bool testReferences() {
+ std::ifstream is("test.composite");
+ const list<value> c = components(readXML(streamList(is)));
+ const value store = car(c);
+
+ assert(length(references(store)) == 3);
+ const value catalog = car(references(store));
+ assert(name(catalog) == std::string("catalog"));
+ assert(target(catalog) == std::string("Catalog"));
+
+ assert(length(bindings(catalog)) == 1);
+ const value binding = car(bindings(catalog));
+ assert(uri(binding) == value());
+ assert(bindingType(binding) == "t:binding.jsonrpc");
+ return true;
+}
+
+bool testProperties() {
+ std::ifstream is("test.composite");
+ const list<value> c = components(readXML(streamList(is)));
+ const value catalog = named(std::string("Catalog"), c);
+
+ assert(length(properties(catalog)) == 1);
+ const value currencyCode = car(properties(catalog));
+ assert(name(currencyCode) == std::string("currencyCode"));
+ assert(propertyValue(currencyCode) == std::string("USD"));
+ return true;
+}
+
+}
+}
+
+int main() {
+ std::cout << "Testing..." << std::endl;
+
+ tuscany::scdl::testComposite();
+ tuscany::scdl::testComponents();
+ tuscany::scdl::testServices();
+ tuscany::scdl::testReferences();
+ tuscany::scdl::testProperties();
+
+ std::cout << "OK" << std::endl;
+
+ return 0;
+}
diff --git a/cpp/sca/modules/scdl/scdl.hpp b/cpp/sca/modules/scdl/scdl.hpp
new file mode 100644
index 0000000000..4d84610fb0
--- /dev/null
+++ b/cpp/sca/modules/scdl/scdl.hpp
@@ -0,0 +1,158 @@
+/*
+ * 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_scdl_hpp
+#define tuscany_scdl_hpp
+
+/**
+ * SCDL read functions.
+ */
+
+#include <string>
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "xml.hpp"
+
+namespace tuscany {
+namespace scdl {
+
+/**
+ * Returns a list of components in a composite.
+ */
+const list<value> components(const value& l) {
+ const list<value> cs = elementChildren("composite", l);
+ if (isNil(cs))
+ return cs;
+ return elementChildren("component", car(cs));
+}
+
+/**
+ * Returns the name of a component, service or reference.
+ */
+const value name(const value& l) {
+ return attributeValue("name", l);
+}
+
+/**
+ * Returns the scdl declaration with the given name.
+ */
+struct filterName {
+ const value n;
+ filterName(const value& n) : n(n) {
+ }
+ const bool operator()(const value& v) const {
+ return name(v) == n;
+ }
+};
+
+const value named(const value& name, const value& l) {
+ const list<value> c = filter<value>(filterName(name), l);
+ if (isNil(c))
+ return value();
+ return car(c);
+}
+
+/**
+ * Returns the implementation of a component.
+ */
+const bool filterImplementation(const value& v) {
+ return isElement(v) && std::string(cadr<value>(v)).find("implementation.") != std::string::npos;
+}
+
+const value implementation(const value& l) {
+ const list<value> n = filter<value>(filterImplementation, l);
+ if (isNil(n))
+ return value();
+ return car(n);
+}
+
+/**
+ * Returns the URI of a service, reference or implementation.
+ */
+const value uri(const value& l) {
+ return attributeValue("uri", l);
+}
+
+/**
+ * Returns a list of services in a component.
+ */
+const list<value> services(const value& l) {
+ return elementChildren("service", l);
+}
+
+/**
+ * Returns a list of references in a component.
+ */
+const list<value> references(const value& l) {
+ return elementChildren("reference", l);
+}
+
+/**
+ * Returns a list of properties in a component.
+ */
+const list<value> properties(const value& l) {
+ return elementChildren("property", l);
+}
+
+/**
+ * Returns the target of a reference.
+ */
+const value target(const value& l) {
+ return attributeValue("target", l);
+}
+
+/**
+ * Returns a list of bindings in a service or reference.
+ */
+const bool filterBinding(const value& v) {
+ return isElement(v) && std::string(cadr<value>(v)).find("binding.") != std::string::npos;
+}
+
+const list<value> bindings(const value& l) {
+ return filter<value>(filterBinding, l);
+}
+
+/**
+ * Returns the type of an implementation.
+ */
+const value implementationType(const value& l) {
+ return elementName(l);
+}
+
+/**
+ * Returns the type of a binding.
+ */
+const value bindingType(const value& l) {
+ return elementName(l);
+}
+
+/**
+ * Returns the value of a property.
+ */
+const value propertyValue(const value& l) {
+ return elementValue(l);
+}
+
+}
+}
+
+#endif /* tuscany_scdl_hpp */
diff --git a/cpp/sca/modules/scdl/test.composite b/cpp/sca/modules/scdl/test.composite
new file mode 100644
index 0000000000..b315f23f9a
--- /dev/null
+++ b/cpp/sca/modules/scdl/test.composite
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200903"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://store"
+ name="store">
+
+ <component name="Store">
+ <t:implementation.widget uri="store.html"/>
+ <service name="Widget">
+ <t:binding.http uri="/store"/>
+ </service>
+ <reference name="catalog" target="Catalog">
+ <t:binding.jsonrpc/>
+ </reference>
+ <reference name="shoppingCart" target="ShoppingCart/Cart">
+ <t:binding.atom/>
+ </reference>
+ <reference name="shoppingTotal" target="ShoppingCart/Total">
+ <t:binding.jsonrpc/>
+ </reference>
+ </component>
+
+ <component name="Catalog">
+ <t:implementation.scheme uri="fruits-catalog.scm"/>
+ <property name="currencyCode">USD</property>
+ <service name="Catalog">
+ <t:binding.jsonrpc/>
+ </service>
+ <reference name="currencyConverter" target="CurrencyConverter"/>
+ </component>
+
+ <component name="ShoppingCart">
+ <t:implementation.scheme uri="shopping-cart.scm"/>
+ <service name="Cart">
+ <t:binding.atom uri="/ShoppingCart"/>
+ </service>
+ <service name="Total">
+ <t:binding.jsonrpc/>
+ </service>
+ <reference name="cache">
+ <binding.memcached uri="localhost:11311"/>
+ </reference>
+ </component>
+
+ <component name="CurrencyConverter">
+ <t:implementation.scheme uri="currency-converter.scm"/>
+ </component>
+
+</composite>
diff --git a/cpp/sca/test/store-function/Makefile.am b/cpp/sca/test/store-function/Makefile.am
index 57a5c114d3..8d73bf3bff 100644
--- a/cpp/sca/test/store-function/Makefile.am
+++ b/cpp/sca/test/store-function/Makefile.am
@@ -18,6 +18,8 @@
store_function_PROGRAMS = store-function-test
store_functiondir=$(prefix)/test/store-function/deploy
+nobase_include_HEADERS = *.hpp
+
INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
store_function_test_SOURCES = store-function-test.cpp
diff --git a/cpp/sca/test/store-object/Makefile.am b/cpp/sca/test/store-object/Makefile.am
index 18b4aa8cc7..9e5621c6ca 100644
--- a/cpp/sca/test/store-object/Makefile.am
+++ b/cpp/sca/test/store-object/Makefile.am
@@ -18,6 +18,8 @@
store_object_PROGRAMS = store-object-test
store_objectdir=$(prefix)/test/store-object/deploy
+nobase_include_HEADERS = *.hpp
+
INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
store_object_test_SOURCES = store-object-test.cpp