summaryrefslogtreecommitdiffstats
path: root/sca-cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp')
-rw-r--r--sca-cpp/trunk/etc/git-exclude1
-rw-r--r--sca-cpp/trunk/modules/java/Makefile.am9
-rw-r--r--sca-cpp/trunk/modules/java/driver.hpp2
-rw-r--r--sca-cpp/trunk/modules/java/eval.hpp137
-rwxr-xr-xsca-cpp/trunk/modules/java/java-conf1
-rw-r--r--sca-cpp/trunk/modules/java/java-test.cpp48
-rw-r--r--sca-cpp/trunk/modules/java/mod-java.hpp4
-rw-r--r--sca-cpp/trunk/modules/java/org/apache/tuscany/ClassLoader.java78
-rw-r--r--sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java11
-rw-r--r--sca-cpp/trunk/modules/java/org/apache/tuscany/IterableUtil.java379
-rw-r--r--sca-cpp/trunk/modules/java/org/apache/tuscany/Service.java41
-rwxr-xr-xsca-cpp/trunk/modules/java/server-test2
-rw-r--r--sca-cpp/trunk/modules/java/test/CalcImpl.java14
-rw-r--r--sca-cpp/trunk/modules/java/test/Client.java8
-rw-r--r--sca-cpp/trunk/modules/java/test/ClientImpl.java8
-rw-r--r--sca-cpp/trunk/modules/java/test/Server.java8
-rw-r--r--sca-cpp/trunk/modules/java/test/ServerImpl.java18
-rwxr-xr-xsca-cpp/trunk/modules/java/wiring-test2
-rw-r--r--sca-cpp/trunk/test/store-cpp/fruits-catalog.cpp5
-rw-r--r--sca-cpp/trunk/test/store-java/Makefile.am10
-rwxr-xr-xsca-cpp/trunk/test/store-java/start2
-rwxr-xr-xsca-cpp/trunk/test/store-java/stop2
-rw-r--r--sca-cpp/trunk/test/store-java/store.composite10
-rw-r--r--sca-cpp/trunk/test/store-java/store/CurrencyConverter.java28
-rw-r--r--sca-cpp/trunk/test/store-java/store/CurrencyConverterImpl.java45
-rw-r--r--sca-cpp/trunk/test/store-java/store/FruitsCatalogImpl.java57
-rw-r--r--sca-cpp/trunk/test/store-java/store/ShoppingCartImpl.java130
27 files changed, 983 insertions, 77 deletions
diff --git a/sca-cpp/trunk/etc/git-exclude b/sca-cpp/trunk/etc/git-exclude
index c08230fe5a..023a2c6fc8 100644
--- a/sca-cpp/trunk/etc/git-exclude
+++ b/sca-cpp/trunk/etc/git-exclude
@@ -61,6 +61,7 @@ doxygen
*.pyc
*.class
*.stamp
+*.jar
# Specific ignores
kernel-test
diff --git a/sca-cpp/trunk/modules/java/Makefile.am b/sca-cpp/trunk/modules/java/Makefile.am
index f103a232fa..5ef145c6e3 100644
--- a/sca-cpp/trunk/modules/java/Makefile.am
+++ b/sca-cpp/trunk/modules/java/Makefile.am
@@ -38,6 +38,15 @@ java_shell_LDFLAGS = -L${JAVA_LIB} -R${JAVA_LIB} -R${JAVA_LIB}/server -ljava
noinst_JAVA = org/apache/tuscany/*.java test/*.java
+jarfile = libmod-tuscany-java-${PACKAGE_VERSION}.jar
+jardir = ${libdir}
+jar_DATA = ${jarfile}
+
+${jarfile}: ${noinst_JAVA}
+ ${JAR} cf $@ org/apache/tuscany/*.class
+
+CLEANFILES = ${jarfile} org/apache/tuscany/*.class test/*.class
+
client_test_SOURCES = client-test.cpp
client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
diff --git a/sca-cpp/trunk/modules/java/driver.hpp b/sca-cpp/trunk/modules/java/driver.hpp
index 9bc55915c5..5f117b8e68 100644
--- a/sca-cpp/trunk/modules/java/driver.hpp
+++ b/sca-cpp/trunk/modules/java/driver.hpp
@@ -48,7 +48,7 @@ const value evalDriverLoop(const JavaRuntime& jr, const JavaClass jc, istream& i
const bool evalDriverRun(const char* name, istream& in, ostream& out) {
scheme::setupDisplay(out);
- const failable<JavaClass> jc = readClass(javaRuntime, name);
+ const failable<JavaClass> jc = readClass(javaRuntime, ".", name);
if (!hasContent(jc))
return true;
evalDriverLoop(javaRuntime, content(jc), in, out);
diff --git a/sca-cpp/trunk/modules/java/eval.hpp b/sca-cpp/trunk/modules/java/eval.hpp
index 7641c5de79..9dbb50abb5 100644
--- a/sca-cpp/trunk/modules/java/eval.hpp
+++ b/sca-cpp/trunk/modules/java/eval.hpp
@@ -52,31 +52,45 @@ public:
JavaVMInitArgs args;
args.version = JNI_VERSION_1_6;
args.ignoreUnrecognized = JNI_FALSE;
- JavaVMOption options[1];
- options[0].optionString = const_cast<char*>("-Djava.class.path=.");
+ JavaVMOption options[3];
args.options = options;
- args.nOptions = 1;
+ args.nOptions = 0;
+
+ // Configure classpath
+ const char* envcp = getenv("CLASSPATH");
+ const string cp = string("-Djava.class.path=") + (envcp == NULL? "." : envcp);
+ options[args.nOptions++].optionString = const_cast<char*>(c_str(cp));
+
+#ifdef WANT_MAINTAINER_MODE
+ // Enable assertions
+ options[args.nOptions++].optionString = const_cast<char*>("-ea");
+#endif
+
+ // Configure Java debugging
+ const char* jpdaopts = getenv("JPDA_OPTS");
+ if (jpdaopts != NULL) {
+ options[args.nOptions++].optionString = const_cast<char*>(jpdaopts);
+ } else {
+ const char* jpdaaddr = getenv("JPDA_ADDRESS");
+ if (jpdaaddr != NULL) {
+ const string jpda = string("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=") + jpdaaddr;
+ options[args.nOptions++].optionString = const_cast<char*>(c_str(jpda));
+ }
+ }
+
+ // Create the JVM
JNI_CreateJavaVM(&jvm, (void**)&env, &args);
- // Register our native invocation handler function
- invokerClass = env->FindClass("org/apache/tuscany/InvocationHandler");
- JNINativeMethod nm;
- nm.name = const_cast<char*>("invoke");
- nm.signature = const_cast<char*>("(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
- nm.fnPtr = (void*)nativeInvoke;
- env->RegisterNatives(invokerClass, &nm, 1);
-
} else {
- // Just hook to existing JVM
+ // Just point to existing JVM
jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
- invokerClass = env->FindClass("org/apache/tuscany/InvocationHandler");
}
// Capture JVM standard IO
setupIO();
- // Lookup the classes and methods we need
+ // Lookup System classes and methods
classClass = env->FindClass("java/lang/Class");
methodClass = env->FindClass("java/lang/reflect/Method");
objectClass = env->FindClass("java/lang/Object");
@@ -84,6 +98,8 @@ public:
booleanClass = env->FindClass("java/lang/Boolean");
stringClass = env->FindClass("java/lang/String");
objectArrayClass = env->FindClass("[Ljava/lang/Object;");
+ iterableClass = env->FindClass("Ljava/lang/Iterable;");
+ classForName = env->GetStaticMethodID(classClass, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
doubleValueOf = env->GetStaticMethodID(doubleClass, "valueOf", "(D)Ljava/lang/Double;");
doubleValue = env->GetMethodID(doubleClass, "doubleValue", "()D");
booleanValueOf = env->GetStaticMethodID(booleanClass, "valueOf", "(Z)Ljava/lang/Boolean;");
@@ -91,8 +107,27 @@ public:
declaredMethods = env->GetMethodID(classClass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
methodName = env->GetMethodID(methodClass, "getName", "()Ljava/lang/String;");
parameterTypes = env->GetMethodID(methodClass, "getParameterTypes", "()[Ljava/lang/Class;");
+
+ // Lookup Tuscany classes and methods
+ loaderClass = env->FindClass("org/apache/tuscany/ClassLoader");
+ loaderValueOf = env->GetStaticMethodID(loaderClass, "valueOf", "(Ljava/lang/String;)Ljava/lang/ClassLoader;");
+ loaderForName = env->GetStaticMethodID(loaderClass, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
+ invokerClass = env->FindClass("org/apache/tuscany/InvocationHandler");
invokerValueOf = env->GetStaticMethodID(invokerClass, "valueOf", "(Ljava/lang/Class;J)Ljava/lang/Object;");
invokerLambda = env->GetFieldID(invokerClass, "lambda", "J");
+ iterableUtilClass = env->FindClass("org/apache/tuscany/IterableUtil");
+ iterableValueOf = env->GetStaticMethodID(iterableUtilClass, "list", "([Ljava/lang/Object;)Ljava/lang/Iterable;");
+ iterableIsNil = env->GetStaticMethodID(iterableUtilClass, "isNil", "(Ljava/lang/Object;)Z");
+ iterableCar = env->GetStaticMethodID(iterableUtilClass, "car", "(Ljava/lang/Object;)Ljava/lang/Object;");
+ iterableCdr = env->GetStaticMethodID(iterableUtilClass, "cdr", "(Ljava/lang/Object;)Ljava/lang/Iterable;");
+
+ // Register our native invocation handler function
+ JNINativeMethod nm;
+ nm.name = const_cast<char*>("invoke");
+ nm.signature = const_cast<char*>("(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
+ nm.fnPtr = (void*)nativeInvoke;
+ env->RegisterNatives(invokerClass, &nm, 1);
+
}
JavaVM* jvm;
@@ -105,6 +140,7 @@ public:
jclass booleanClass;
jclass stringClass;
jclass objectArrayClass;
+ jclass iterableClass;
jmethodID doubleValueOf;
jmethodID doubleValue;
jmethodID booleanValueOf;
@@ -112,10 +148,18 @@ public:
jmethodID declaredMethods;
jmethodID methodName;
jmethodID parameterTypes;
-
+ jmethodID classForName;
+ jclass loaderClass;
+ jmethodID loaderValueOf;
+ jmethodID loaderForName;
jclass invokerClass;
jmethodID invokerValueOf;
jfieldID invokerLambda;
+ jclass iterableUtilClass;
+ jmethodID iterableValueOf;
+ jmethodID iterableCar;
+ jmethodID iterableCdr;
+ jmethodID iterableIsNil;
} javaRuntime;
@@ -137,6 +181,7 @@ const jobject valueToJobject(const JavaRuntime& jr, const value& jtype, const va
const value jobjectToValue(const JavaRuntime& jr, const jobject o);
const jobjectArray valuesToJarray(const JavaRuntime& jr, const list<value>& v);
const list<value> jarrayToValues(const JavaRuntime& jr, const jobjectArray o);
+const list<value> jiterableToValues(const JavaRuntime& jr, const jobject o);
/**
* Convert a Java class name to a JNI class name.
@@ -204,9 +249,11 @@ jobject JNICALL nativeInvoke(JNIEnv* env, jobject self, unused jobject proxy, jo
// Build the expression to evaluate
const list<value> expr = cons<value>(func, jarrayToValues(jl.jr, args));
+ debug(expr, "java::nativeInvoke::expr");
// Invoke the lambda function
value result = jl(expr);
+ debug(result, "java::nativeInvoke::result");
// Convert result to a jobject
return valueToJobject(jl.jr, value(), result);
@@ -238,12 +285,19 @@ const jobjectArray valuesToJarray(const JavaRuntime& jr, const list<value>& v) {
}
/**
+ * Convert a Java jobjectArray to a Java iterable.
+ */
+const jobject jarrayToJiterable(const JavaRuntime& jr, jobjectArray a) {
+ return jr.env->CallStaticObjectMethod(jr.iterableClass, jr.iterableValueOf, a);
+}
+
+/**
* Convert a value to a Java jobject.
*/
const jobject valueToJobject(const JavaRuntime& jr, const value& jtype, const value& v) {
switch (type(v)) {
case value::List:
- return valuesToJarray(jr, v);
+ return jarrayToJiterable(jr, valuesToJarray(jr, v));
case value::Lambda:
return mkJavaLambda(jr, jtype, v);
case value::Symbol:
@@ -253,7 +307,7 @@ const jobject valueToJobject(const JavaRuntime& jr, const value& jtype, const va
case value::Number:
return jr.env->CallStaticObjectMethod(jr.doubleClass, jr.doubleValueOf, (double)v);
case value::Bool:
- return jr.env->CallStaticObjectMethod(jr.booleanClass, jr.booleanValueOf, (double)v);
+ return jr.env->CallStaticObjectMethod(jr.booleanClass, jr.booleanValueOf, (bool)v);
default:
return NULL;
}
@@ -292,6 +346,23 @@ const list<value> jarrayToValues(const JavaRuntime& jr, jobjectArray o) {
}
/**
+ * Convert a Java Iterable to a list of values.
+ */
+const list<value> jiterableToValuesHelper(const JavaRuntime& jr, jobject o) {
+ if ((bool)jr.env->CallStaticBooleanMethod(jr.iterableUtilClass, jr.iterableIsNil, o))
+ return list<value>();
+ jobject car = jr.env->CallStaticObjectMethod(jr.iterableUtilClass, jr.iterableCar, o);
+ jobject cdr = jr.env->CallStaticObjectMethod(jr.iterableUtilClass, jr.iterableCdr, o);
+ return cons(jobjectToValue(jr, car), jiterableToValuesHelper(jr, cdr));
+}
+
+const list<value> jiterableToValues(const JavaRuntime& jr, jobject o) {
+ if (o == NULL)
+ return list<value>();
+ return jiterableToValuesHelper(jr, o);
+}
+
+/**
* Lambda function used to represent a Java callable object.
*/
struct javaCallable {
@@ -330,8 +401,8 @@ const value jobjectToValue(const JavaRuntime& jr, const jobject o) {
return value((bool)jr.env->CallBooleanMethod(o, jr.booleanValue));
if (jr.env->IsSameObject(clazz, jr.doubleClass))
return value((double)jr.env->CallDoubleMethod(o, jr.doubleValue));
- if ((jr.env->IsSameObject(clazz, jr.objectArrayClass)))
- return jarrayToValues(jr, (jobjectArray)o);
+ if ((jr.env->IsAssignableFrom(clazz, jr.iterableClass)))
+ return jiterableToValues(jr, o);
return lambda<value(const list<value>&)>(javaCallable(jr, o));
}
@@ -378,12 +449,12 @@ const list<value> methodsToValues(const JavaRuntime& jr, const jclass clazz) {
*/
class JavaClass {
public:
- JavaClass() : clazz(NULL), obj(NULL) {
+ JavaClass() : loader(NULL), clazz(NULL), obj(NULL) {
}
-
- JavaClass(const jclass clazz, const jobject obj, const list<value> m) : clazz(clazz), obj(obj), m(m) {
+ JavaClass(const jobject loader, const jclass clazz, const jobject obj, const list<value> m) : loader(loader), clazz(clazz), obj(obj), m(m) {
}
+ const jobject loader;
const jclass clazz;
const jobject obj;
const list<value> m;
@@ -392,24 +463,34 @@ public:
/**
* Read a class.
*/
-const failable<JavaClass> readClass(const JavaRuntime& jr, const string& name) {
- const string jname = jniClassName(name);
- const jclass clazz = jr.env->FindClass(c_str(jname));
+const failable<JavaClass> readClass(const JavaRuntime& jr, const string& path, const string& name) {
+
+ // Create a class loader from the given path
+ const jobject jpath = jr.env->NewStringUTF(c_str(path));
+ jobject loader = jr.env->CallStaticObjectMethod(jr.loaderClass, jr.loaderValueOf, jpath);
+
+ // Load the class
+ const jobject jname = jr.env->NewStringUTF(c_str(name));
+ const jclass clazz = (jclass)jr.env->CallStaticObjectMethod(jr.loaderClass, jr.loaderForName, jname, JNI_TRUE, loader);
if (clazz == NULL)
return mkfailure<JavaClass>(string("Couldn't load class: ") + name + " : " + lastException(jr));
+
+ // Create an instance
const jmethodID constr = jr.env->GetMethodID(clazz, "<init>", "()V");
if (constr == NULL)
return mkfailure<JavaClass>(string("Couldn't find constructor: ") + name + " : " + lastException(jr));
const jobject obj = jr.env->NewObject(clazz, constr);
if (obj == NULL)
return mkfailure<JavaClass>(string("Couldn't construct object: ") + name + " : " + lastException(jr));
- return JavaClass(clazz, obj, methodsToValues(jr, clazz));
+
+ return JavaClass(loader, clazz, obj, methodsToValues(jr, clazz));
}
/**
* Evaluate an expression against a Java class.
*/
const failable<value> evalClass(const JavaRuntime& jr, const value& expr, const JavaClass jc) {
+ debug(expr, "java::evalClass::expr");
// Lookup the Java function named as the expression operand
const list<value> func = assoc<value>(car<value>(expr), jc.m);
@@ -426,7 +507,9 @@ const failable<value> evalClass(const JavaRuntime& jr, const value& expr, const
return mkfailure<value>(string("Function call failed: ") + car<value>(expr) + " : " + lastException(jr));
// Convert Java result to a value
- return jobjectToValue(jr, result);
+ const value v = jobjectToValue(jr, result);
+ debug(v, "java::evalClass::result");
+ return v;
}
}
diff --git a/sca-cpp/trunk/modules/java/java-conf b/sca-cpp/trunk/modules/java/java-conf
index d81a14a6c1..fb02f7fe57 100755
--- a/sca-cpp/trunk/modules/java/java-conf
+++ b/sca-cpp/trunk/modules/java/java-conf
@@ -24,3 +24,4 @@ root=`readlink -f $1`
cat >>$root/conf/httpd.conf <<EOF
LoadModule mod_tuscany_eval $here/.libs/libmod_tuscany_java.so
EOF
+
diff --git a/sca-cpp/trunk/modules/java/java-test.cpp b/sca-cpp/trunk/modules/java/java-test.cpp
index 7ece2dfc68..da73602f12 100644
--- a/sca-cpp/trunk/modules/java/java-test.cpp
+++ b/sca-cpp/trunk/modules/java/java-test.cpp
@@ -34,7 +34,7 @@ namespace java {
bool testEvalExpr() {
gc_scoped_pool pool;
{
- const failable<JavaClass> obj = readClass(javaRuntime, "test.CalcImpl");
+ const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.CalcImpl");
assert(hasContent(obj));
const value exp = mklist<value>("mult", 2, 3);
const failable<value> r = evalClass(javaRuntime, exp, content(obj));
@@ -42,13 +42,29 @@ bool testEvalExpr() {
assert(content(r) == value(6));
}
{
- const failable<JavaClass> obj = readClass(javaRuntime, "test.AdderImpl");
+ const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.CalcImpl");
+ assert(hasContent(obj));
+ const value exp = mklist<value>("even", 2);
+ const failable<value> r = evalClass(javaRuntime, exp, content(obj));
+ assert(hasContent(r));
+ assert(content(r) == value(true));
+ }
+ {
+ const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.AdderImpl");
assert(hasContent(obj));
const value exp = mklist<value>("add", 2, 3);
const failable<value> r = evalClass(javaRuntime, exp, content(obj));
assert(hasContent(r));
assert(content(r) == value(5));
}
+ {
+ const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.CalcImpl");
+ assert(hasContent(obj));
+ const value exp = mklist<value>("square", mklist<value>(1, 2, 3));
+ const failable<value> r = evalClass(javaRuntime, exp, content(obj));
+ assert(hasContent(r));
+ assert(content(r) == mklist<value>(1, 4, 9));
+ }
return true;
}
@@ -61,7 +77,7 @@ const value add(const list<value>& args) {
bool testEvalLambda() {
gc_scoped_pool pool;
- const failable<JavaClass> obj = readClass(javaRuntime, "test.CalcImpl");
+ const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.CalcImpl");
assert(hasContent(obj));
const value tcel = mklist<value>("add", 3, 4, lambda<value(const list<value>&)>(add));
const failable<value> r = evalClass(javaRuntime, tcel, content(obj));
@@ -70,14 +86,38 @@ bool testEvalLambda() {
return true;
}
+bool testClassLoader() {
+ gc_scoped_pool pool;
+ const failable<JavaClass> obj = readClass(javaRuntime, ".", "org.apache.tuscany.ClassLoader$Test");
+ assert(hasContent(obj));
+ const value exp = mklist<value>("testClassLoader");
+ const failable<value> r = evalClass(javaRuntime, exp, content(obj));
+ assert(hasContent(r));
+ assert(content(r) == value(true));
+ return true;
+}
+
+bool testIterableUtil() {
+ gc_scoped_pool pool;
+ const failable<JavaClass> obj = readClass(javaRuntime, ".", "org.apache.tuscany.IterableUtil$Test");
+ assert(hasContent(obj));
+ const value exp = mklist<value>("testList");
+ const failable<value> r = evalClass(javaRuntime, exp, content(obj));
+ assert(hasContent(r));
+ assert(content(r) == value(true));
+ return true;
+}
+
}
}
int main() {
tuscany::cout << "Testing..." << tuscany::endl;
- //tuscany::java::testEvalExpr();
+ tuscany::java::testEvalExpr();
tuscany::java::testEvalLambda();
+ tuscany::java::testClassLoader();
+ tuscany::java::testIterableUtil();
tuscany::cout << "OK" << tuscany::endl;
return 0;
diff --git a/sca-cpp/trunk/modules/java/mod-java.hpp b/sca-cpp/trunk/modules/java/mod-java.hpp
index 933550b7c3..a2235fc17f 100644
--- a/sca-cpp/trunk/modules/java/mod-java.hpp
+++ b/sca-cpp/trunk/modules/java/mod-java.hpp
@@ -63,9 +63,9 @@ struct applyImplementation {
* Evaluate a Java component implementation and convert it to an applicable
* lambda function.
*/
-const failable<lambda<value(const list<value>&)> > evalImplementation(unused const string& path, const value& impl, const list<value>& px) {
+const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px) {
const string cn(attributeValue("class", impl));
- const failable<java::JavaClass> jc = java::readClass(java::javaRuntime, cn);
+ const failable<java::JavaClass> jc = java::readClass(java::javaRuntime, path, cn);
if (!hasContent(jc))
return mkfailure<lambda<value(const list<value>&)> >(reason(jc));
return lambda<value(const list<value>&)>(applyImplementation(content(jc), px));
diff --git a/sca-cpp/trunk/modules/java/org/apache/tuscany/ClassLoader.java b/sca-cpp/trunk/modules/java/org/apache/tuscany/ClassLoader.java
new file mode 100644
index 0000000000..78b9ec7d90
--- /dev/null
+++ b/sca-cpp/trunk/modules/java/org/apache/tuscany/ClassLoader.java
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+package org.apache.tuscany;
+
+import static org.apache.tuscany.ClassLoader.Test.*;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+/**
+ * Class loader used to load SCA component implementation classes.
+ */
+class ClassLoader extends URLClassLoader {
+
+ ClassLoader(final URL... urls) {
+ super(urls);
+ }
+
+ /**
+ * Create a class loader for an SCA contribution path.
+ */
+ static java.lang.ClassLoader valueOf(final String path) throws MalformedURLException {
+ return new ClassLoader(new File(path).toURI().toURL());
+ }
+
+ /**
+ * Load a class.
+ */
+ static Class<?> forName(final String name, final boolean resolve, final java.lang.ClassLoader loader) throws ClassNotFoundException {
+ return Class.forName(name, resolve, loader);
+ }
+
+ /**
+ * Test the class loader.
+ */
+ static class Test {
+ Boolean testClassLoader() {
+ try {
+ final Class<?> clazz = ClassLoader.forName("test.CalcImpl", true, ClassLoader.valueOf("."));
+ assert clazz != null;
+ } catch(final MalformedURLException e) {
+ throw new RuntimeException(e);
+ } catch(final ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ return true;
+ }
+ }
+
+ public static void main(final String[] args) {
+ System.out.println("Testing...");
+
+ Test.class.getClassLoader().setDefaultAssertionStatus(true);
+ new Test().testClassLoader();
+
+ System.out.println("OK");
+ }
+
+}
diff --git a/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java b/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java
index 1c159a99d5..5707a07bc7 100644
--- a/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java
+++ b/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java
@@ -22,14 +22,21 @@ package org.apache.tuscany;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
-public class InvocationHandler implements java.lang.reflect.InvocationHandler {
+/**
+ * Proxy Invocation handler used to represent SCA component references.
+ */
+class InvocationHandler implements java.lang.reflect.InvocationHandler {
final long lambda;
InvocationHandler(final long lambda) {
this.lambda = lambda;
}
- public static Object valueOf(final Class<?> iface, final long lambda) {
+ /**
+ * Create a proxy for an interface and the lambda function representing
+ * an SCA component reference.
+ */
+ static Object valueOf(final Class<?> iface, final long lambda) {
return Proxy.newProxyInstance(iface.getClassLoader(), new Class[]{iface}, new InvocationHandler(lambda));
}
diff --git a/sca-cpp/trunk/modules/java/org/apache/tuscany/IterableUtil.java b/sca-cpp/trunk/modules/java/org/apache/tuscany/IterableUtil.java
new file mode 100644
index 0000000000..ef18b856db
--- /dev/null
+++ b/sca-cpp/trunk/modules/java/org/apache/tuscany/IterableUtil.java
@@ -0,0 +1,379 @@
+/*
+ * 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.
+ */
+
+package org.apache.tuscany;
+
+import static java.util.Arrays.*;
+import static org.apache.tuscany.IterableUtil.Test.*;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Utility functions to help work efficiently with iterable lists, inspired from Lisp.
+ */
+public class IterableUtil {
+
+ /**
+ * Convert an array or a variable list of arguments to an iterable list.
+ */
+ public static <T> Iterable<T> list(final Object... a) {
+ return new ArrayIterable<T>(a, 0);
+ }
+
+ /**
+ * Convert an iterable list to a java.util.Collection.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Collection<T> collection(final Object l) {
+ final Collection<T> c = new ArrayList<T>();
+ for(final Object x : (Iterable<?>)l)
+ c.add((T)x);
+ return c;
+ }
+
+ /**
+ * Construct a new list from an element and a list.
+ */
+ public static <T> Iterable<T> cons(final Object car, final Iterable<?> cdr) {
+ return new PairIterable<T>(car, cdr);
+ }
+
+ /**
+ * Return true if a list is nil (empty).
+ */
+ public static boolean isNil(final Object l) {
+ if(l instanceof BasicIterable<?>)
+ return ((BasicIterable<?>)l).isNil();
+ if(l instanceof Collection<?>)
+ return ((Collection<?>)l).isEmpty();
+ return !((Iterable<?>)l).iterator().hasNext();
+ }
+
+ /**
+ * Return the car (first element) of a list.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T car(final Object l) {
+ if(l instanceof BasicIterable<?>)
+ return ((BasicIterable<T>)l).car();
+ if(l instanceof List<?>)
+ return (T)((List<?>)l).get(0);
+ return (T)((Iterable<?>)l).iterator().next();
+ }
+
+ /**
+ * Return the cdr (rest after the first element) of a list.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterable<T> cdr(final Object l) {
+ if(l instanceof BasicIterable<?>)
+ return ((BasicIterable<T>)l).cdr();
+ if(l instanceof List<?>)
+ return new ListIterable<T>((List<?>)l, 1);
+ if(l instanceof Collection<?>)
+ return new ArrayIterable<T>(((Collection<?>)l).toArray(), 1);
+ return new Iterable<T>() {
+ @Override
+ public Iterator<T> iterator() {
+ final Iterator<T> i = ((Iterable<T>)l).iterator();
+ i.next();
+ return i;
+ }
+ };
+ }
+
+ /**
+ * Return the car of the cdr of a list.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T cadr(final Object l) {
+ return (T)car(cdr(l));
+ }
+
+ /**
+ * Return the cdr of the cdr of a list.
+ */
+ public static <T> Iterable<T> cddr(final Object l) {
+ return cdr(cdr(l));
+ }
+
+ /**
+ * Return the car of the cdr of the cdr of a list.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T caddr(final Object l) {
+ return (T)car(cddr(l));
+ }
+
+ /**
+ * Return the first pair matching a key from a list of key value pairs.
+ */
+ public static <T> Iterable<T> assoc(final Object k, final Object l) {
+ if(isNil(l))
+ return list();
+ if(k.equals(car(car(l))))
+ return car(l);
+ return assoc(k, cdr(l));
+ }
+
+ /**
+ * Internal base implementation class for iterable and immutable lists.
+ */
+ static abstract class BasicIterable<T> extends AbstractList<T> {
+ abstract T car();
+
+ abstract Iterable<T> cdr();
+
+ abstract Boolean isNil();
+
+ @Override
+ public int size() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public T get(final int index) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Internal implementation of a list backed by an array.
+ */
+ static class ArrayIterable<T> extends BasicIterable<T> {
+ final Object[] a;
+ final int start;
+
+ ArrayIterable(final Object[] a, final int start) {
+ this.a = a;
+ this.start = start;
+ }
+
+ @Override
+ Boolean isNil() {
+ return this.a.length - this.start == 0;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ T car() {
+ return (T)this.a[this.start];
+ }
+
+ @Override
+ BasicIterable<T> cdr() {
+ return new ArrayIterable<T>(this.a, this.start + 1);
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return new Iterator<T>() {
+ int i = ArrayIterable.this.start;
+
+ @Override
+ public boolean hasNext() {
+ return this.i < ArrayIterable.this.a.length;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T next() {
+ return (T)ArrayIterable.this.a[this.i++];
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ }
+
+ /**
+ * Internal implementation of a list backed by a java.util.List.
+ */
+ static class ListIterable<T> extends BasicIterable<T> {
+ final List<?> l;
+ final int start;
+
+ ListIterable(final List<?> l, final int start) {
+ this.l = l;
+ this.start = start;
+ }
+
+ @Override
+ Boolean isNil() {
+ return this.l.size() - this.start == 0;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ T car() {
+ return (T)this.l.get(this.start);
+ }
+
+ @Override
+ BasicIterable<T> cdr() {
+ return new ListIterable<T>(this.l, this.start + 1);
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return new Iterator<T>() {
+ int i = ListIterable.this.start;
+
+ @Override
+ public boolean hasNext() {
+ return this.i < ListIterable.this.l.size();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T next() {
+ return (T)ListIterable.this.l.get(this.i++);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ }
+
+ /**
+ * Internal implementation of a list backed by an element / iterable pair.
+ */
+ static class PairIterable<T> extends BasicIterable<T> {
+ final Object car;
+ final Iterable<?> cdr;
+
+ PairIterable(final Object car, final Iterable<?> cdr) {
+ this.car = car;
+ this.cdr = cdr;
+ }
+
+ @Override
+ Boolean isNil() {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ T car() {
+ return (T)this.car;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ Iterable<T> cdr() {
+ return (Iterable<T>)this.cdr;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return new Iterator<T>() {
+ boolean carIterator = true;
+ Iterator<?> cdrIterator = PairIterable.this.cdr.iterator();
+
+ @Override
+ public boolean hasNext() {
+ if(this.carIterator)
+ return true;
+ return this.cdrIterator.hasNext();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T next() {
+ if(this.carIterator) {
+ this.carIterator = false;
+ return (T)PairIterable.this.car;
+ }
+ return (T)this.cdrIterator.next();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ }
+
+ /**
+ * Test the list functions.
+ */
+ static class Test {
+ Boolean testList() {
+ final Iterable<Object> l = list(2, 3, 4);
+ assert car(l) == Integer.valueOf(2);
+ assert cadr(l) == Integer.valueOf(3);
+ assert caddr(l) == Integer.valueOf(4);
+
+ final Iterable<Object> c = cons(0, cons(1, l));
+ assert car(c) == Integer.valueOf(0);
+ assert cadr(c) == Integer.valueOf(1);
+ assert caddr(c) == Integer.valueOf(2);
+ assert c.toString().equals("[0, 1, 2, 3, 4]");
+
+ final Iterable<Object> cl = cons(0, cons(1, new ArrayList<Object>(asList(2, 3, 4))));
+ assert car(cl) == Integer.valueOf(0);
+ assert cadr(cl) == Integer.valueOf(1);
+ assert caddr(cl) == Integer.valueOf(2);
+ assert cl.toString().equals("[0, 1, 2, 3, 4]");
+
+ final List<Object> jl = new ArrayList<Object>(collection(cl));
+ assert jl.size() == 5;
+ assert jl.get(0) == Integer.valueOf(0);
+ assert jl.get(1) == Integer.valueOf(1);
+ assert jl.get(2) == Integer.valueOf(2);
+
+ final Iterable<Object> n = list();
+ assert isNil(n);
+ assert n.toString().equals("[]");
+
+ final Iterable<Object> cn = cons(0, n);
+ assert !isNil(cn);
+ assert isNil(cdr(cn));
+ assert cn.toString().equals("[0]");
+
+ final Iterable<Object> al = new ArrayList<Object>(Arrays.asList(1, 2, 3));
+ assert car(al) == Integer.valueOf(1);
+ assert cadr(al) == Integer.valueOf(2);
+ assert caddr(al) == Integer.valueOf(3);
+ return true;
+ }
+ }
+
+ public static void main(final String[] args) {
+ System.out.println("Testing...");
+
+ Test.class.getClassLoader().setDefaultAssertionStatus(true);
+ new Test().testList();
+
+ System.out.println("OK");
+ }
+
+}
diff --git a/sca-cpp/trunk/modules/java/org/apache/tuscany/Service.java b/sca-cpp/trunk/modules/java/org/apache/tuscany/Service.java
index c8152463b4..6150b7d1cd 100644
--- a/sca-cpp/trunk/modules/java/org/apache/tuscany/Service.java
+++ b/sca-cpp/trunk/modules/java/org/apache/tuscany/Service.java
@@ -19,20 +19,45 @@
package org.apache.tuscany;
+/**
+ * Interface used to represent SCA component references providing both REST
+ * access to a resource and function application.
+ */
public interface Service {
- String post(Object[] item);
-
- Object[] get(String id);
-
- Object[] getall();
-
- boolean put(String id, Object[] item);
-
+ /**
+ * Post a new item to a resource.
+ */
+ String post(Iterable<?> item);
+
+ /**
+ * Return an item.
+ */
+ Iterable<?> get(String id);
+
+ /**
+ * Return all items in the resource.
+ */
+ Iterable<?> getall();
+
+ /**
+ * Update am item.
+ */
+ boolean put(String id, Iterable<?> item);
+
+ /**
+ * Delete an item.
+ */
boolean delete(String id);
+ /**
+ * Delete all items in the resource.
+ */
boolean deleteall();
+ /**
+ * Apply a function.
+ */
<T> T apply(Object... params);
}
diff --git a/sca-cpp/trunk/modules/java/server-test b/sca-cpp/trunk/modules/java/server-test
index 08e381690d..45c5efafb2 100755
--- a/sca-cpp/trunk/modules/java/server-test
+++ b/sca-cpp/trunk/modules/java/server-test
@@ -29,6 +29,8 @@ SCAComposite domain-test.composite
</Location>
EOF
+export CLASSPATH="`pwd`/libmod-tuscany-java-1.0.jar:`pwd`"
+
apachectl -k start -d `pwd`/tmp
sleep 2
diff --git a/sca-cpp/trunk/modules/java/test/CalcImpl.java b/sca-cpp/trunk/modules/java/test/CalcImpl.java
index 51753785e4..37dc642e75 100644
--- a/sca-cpp/trunk/modules/java/test/CalcImpl.java
+++ b/sca-cpp/trunk/modules/java/test/CalcImpl.java
@@ -19,6 +19,9 @@
package test;
+import java.util.List;
+import java.util.ArrayList;
+
public class CalcImpl {
public Double add(Double x, Double y, Adder adder) {
@@ -29,4 +32,15 @@ public class CalcImpl {
return x * y;
}
+ public Boolean even(Double x) {
+ return (double)(((int)(double)x / 2) * 2) == (double)x;
+ }
+
+ public Iterable<Double> square(Iterable<Double> l) {
+ List r = new ArrayList();
+ for (Double x: l)
+ r.add(x * x);
+ return r;
+ }
+
}
diff --git a/sca-cpp/trunk/modules/java/test/Client.java b/sca-cpp/trunk/modules/java/test/Client.java
index 447b408cd4..ff2d3fee13 100644
--- a/sca-cpp/trunk/modules/java/test/Client.java
+++ b/sca-cpp/trunk/modules/java/test/Client.java
@@ -23,13 +23,13 @@ public interface Client {
String echo(String x);
- Object[] getall();
+ Iterable<?> getall();
- Object[] get(String id);
+ Iterable<?> get(String id);
- String post(Object[] item);
+ String post(Iterable<?> item);
- Boolean put(String id, Object[] entry);
+ Boolean put(String id, Iterable<?> entry);
Boolean deleteall();
diff --git a/sca-cpp/trunk/modules/java/test/ClientImpl.java b/sca-cpp/trunk/modules/java/test/ClientImpl.java
index 3d3063b608..4bd3498dd5 100644
--- a/sca-cpp/trunk/modules/java/test/ClientImpl.java
+++ b/sca-cpp/trunk/modules/java/test/ClientImpl.java
@@ -25,19 +25,19 @@ public class ClientImpl {
return server.echo(x);
}
- public Object[] getall(Server server) {
+ public Iterable<?> getall(Server server) {
return server.getall();
}
- public Object[] get(String id, Server server) {
+ public Iterable<?> get(String id, Server server) {
return server.get(id);
}
- public String post(Object[] item, Server server) {
+ public String post(Iterable<?> item, Server server) {
return server.post(item);
}
- public Boolean put(String id, Object[] item, Server server) {
+ public Boolean put(String id, Iterable<?> item, Server server) {
return server.put(id, item);
}
diff --git a/sca-cpp/trunk/modules/java/test/Server.java b/sca-cpp/trunk/modules/java/test/Server.java
index a165988550..917ccfd6b9 100644
--- a/sca-cpp/trunk/modules/java/test/Server.java
+++ b/sca-cpp/trunk/modules/java/test/Server.java
@@ -23,13 +23,13 @@ public interface Server {
String echo(String x);
- Object[] getall();
+ Iterable<?> getall();
- Object[] get(String id);
+ Iterable<?> get(String id);
- String post(Object[] item);
+ String post(Iterable<?> item);
- Boolean put(String id, Object[] entry);
+ Boolean put(String id, Iterable<?> entry);
Boolean deleteall();
diff --git a/sca-cpp/trunk/modules/java/test/ServerImpl.java b/sca-cpp/trunk/modules/java/test/ServerImpl.java
index f82a8a24b5..dd4e227123 100644
--- a/sca-cpp/trunk/modules/java/test/ServerImpl.java
+++ b/sca-cpp/trunk/modules/java/test/ServerImpl.java
@@ -19,33 +19,31 @@
package test;
+import static org.apache.tuscany.IterableUtil.*;
+
public class ServerImpl {
- Object[] list(Object... o) {
- return o;
- }
-
public String echo(String x) {
return x;
}
- public Object[] getall() {
+ public Iterable<?> getall() {
return list("Sample Feed", "123456789",
list("Item", "111", list(list("'javaClass", "services.Item"), list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99))),
list("Item", "222", list(list("'javaClass", "services.Item"), list("'name", "Orange"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 3.55))),
- list("Item", "333", list(list("'javaClass", "services.Item"), list("name", "Pear"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 1.55))));
+ list("Item", "333", list(list("'javaClass", "services.Item"), list("'name", "Pear"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 1.55))));
}
- public Object[] get(String id) {
- Object[] entry = list(list("'javaClass", "services.Item"), list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99));
+ public Iterable<?> get(String id) {
+ Iterable<?> entry = list(list("'javaClass", "services.Item"), list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99));
return list("Item", id, entry);
}
- public String post(Object[] item) {
+ public String post(Iterable<?> item) {
return "123456789";
}
- public Boolean put(String id, Object[] entry) {
+ public Boolean put(String id, Iterable<?> entry) {
return true;
}
diff --git a/sca-cpp/trunk/modules/java/wiring-test b/sca-cpp/trunk/modules/java/wiring-test
index b92f76c403..7b47787b28 100755
--- a/sca-cpp/trunk/modules/java/wiring-test
+++ b/sca-cpp/trunk/modules/java/wiring-test
@@ -31,6 +31,8 @@ SCAComposite domain-test.composite
</Location>
EOF
+export CLASSPATH="`pwd`/libmod-tuscany-java-1.0.jar:`pwd`"
+
apachectl -k start -d `pwd`/tmp
sleep 2
diff --git a/sca-cpp/trunk/test/store-cpp/fruits-catalog.cpp b/sca-cpp/trunk/test/store-cpp/fruits-catalog.cpp
index a7d502a9b9..4c93b2a58e 100644
--- a/sca-cpp/trunk/test/store-cpp/fruits-catalog.cpp
+++ b/sca-cpp/trunk/test/store-cpp/fruits-catalog.cpp
@@ -33,7 +33,7 @@ namespace tuscany {
namespace store {
/**
- * Returns a catalog.
+ * Returns the catalog.
*/
struct convert {
const lambda<value(const list<value>&)> converter;
@@ -61,6 +61,9 @@ const failable<value> get(const lambda<value(const list<value>&)> converter) {
mkfruit("Pear", currency, symbol, conv(1.55)));
}
+/**
+ * TODO remove this JSON-RPC specific function.
+ */
const failable<value> listMethods(unused const lambda<value(const list<value>&)> converter) {
return value(mklist<value>(string("Service.get")));
}
diff --git a/sca-cpp/trunk/test/store-java/Makefile.am b/sca-cpp/trunk/test/store-java/Makefile.am
index f18bb991c1..a381f0a3fd 100644
--- a/sca-cpp/trunk/test/store-java/Makefile.am
+++ b/sca-cpp/trunk/test/store-java/Makefile.am
@@ -15,6 +15,16 @@
# specific language governing permissions and limitations
# under the License.
+JAVAROOT = ${top_builddir}/test/store-java
+
if WANT_JAVA
+AM_JAVACFLAGS = -classpath ${top_builddir}/modules/java/libmod-tuscany-java-${PACKAGE_VERSION}.jar
+
+noinst_JAVA = store/*.java
+
+CLEANFILES = store/*.class
+
+TESTS = server-test
+
endif
diff --git a/sca-cpp/trunk/test/store-java/start b/sca-cpp/trunk/test/store-java/start
index eb8c174999..43a2b90c2a 100755
--- a/sca-cpp/trunk/test/store-java/start
+++ b/sca-cpp/trunk/test/store-java/start
@@ -28,6 +28,8 @@ SCAComposite store.composite
</Location>
EOF
+export CLASSPATH=`pwd`/../../modules/java/libmod-tuscany-java-1.0.jar:`pwd`
+
apachectl -k start -d `pwd`/tmp
mc="memcached -l 127.0.0.1 -m 4 -p 11211"
diff --git a/sca-cpp/trunk/test/store-java/stop b/sca-cpp/trunk/test/store-java/stop
index 34731dbbe1..3c4f59e76e 100755
--- a/sca-cpp/trunk/test/store-java/stop
+++ b/sca-cpp/trunk/test/store-java/stop
@@ -17,6 +17,8 @@
# specific language governing permissions and limitations
# under the License.
+export CLASSPATH=`pwd`/../../modules/java/libmod-tuscany-java-1.0.jar:`pwd`
+
apachectl -k stop -d `pwd`/tmp
mc="memcached -l 127.0.0.1 -m 4 -p 11211"
kill `ps -f | grep -v grep | grep "$mc" | awk '{ print $2 }'`
diff --git a/sca-cpp/trunk/test/store-java/store.composite b/sca-cpp/trunk/test/store-java/store.composite
index 15e778ca36..5024d79ee6 100644
--- a/sca-cpp/trunk/test/store-java/store.composite
+++ b/sca-cpp/trunk/test/store-java/store.composite
@@ -22,16 +22,6 @@
targetNamespace="http://store"
name="store">
- <component name="Store">
- <implementation.java class="store.StoreImpl"/>
- <service name="Widget">
- <t:binding.http uri="store"/>
- </service>
- <reference name="catalog" target="Catalog"/>
- <reference name="shoppingCart" target="ShoppingCart/Cart"/>
- <reference name="shoppingTotal" target="ShoppingCart/Total"/>
- </component>
-
<component name="Catalog">
<implementation.java class="store.FruitsCatalogImpl"/>
<property name="currencyCode">USD</property>
diff --git a/sca-cpp/trunk/test/store-java/store/CurrencyConverter.java b/sca-cpp/trunk/test/store-java/store/CurrencyConverter.java
new file mode 100644
index 0000000000..1ed15a670a
--- /dev/null
+++ b/sca-cpp/trunk/test/store-java/store/CurrencyConverter.java
@@ -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.
+ */
+
+package store;
+
+public interface CurrencyConverter {
+
+ Double convert(String from, String to, Double amount);
+
+ String symbol(String currency);
+
+}
diff --git a/sca-cpp/trunk/test/store-java/store/CurrencyConverterImpl.java b/sca-cpp/trunk/test/store-java/store/CurrencyConverterImpl.java
new file mode 100644
index 0000000000..a6d0fd00b3
--- /dev/null
+++ b/sca-cpp/trunk/test/store-java/store/CurrencyConverterImpl.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package store;
+
+/**
+ * Currency converter component implementation.
+ */
+public class CurrencyConverterImpl {
+
+ /**
+ * Convert an amount from USD to a currency.
+ */
+ public Double convert(String from, String to, Double amount) {
+ if ("EUR".equals(to))
+ return amount * 0.70;
+ return amount;
+ }
+
+ /**
+ * Return a currency symbol.
+ */
+ public String symbol(String currency) {
+ if ("EUR".equals(currency))
+ return "E";
+ return "$";
+ }
+
+}
diff --git a/sca-cpp/trunk/test/store-java/store/FruitsCatalogImpl.java b/sca-cpp/trunk/test/store-java/store/FruitsCatalogImpl.java
new file mode 100644
index 0000000000..3caa785416
--- /dev/null
+++ b/sca-cpp/trunk/test/store-java/store/FruitsCatalogImpl.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package store;
+
+import static org.apache.tuscany.IterableUtil.list;
+
+/**
+ * Catalog component implementation.
+ */
+public class FruitsCatalogImpl {
+
+ /**
+ * Returns the catalog.
+ */
+ public Iterable<?> get(final CurrencyConverter converter) {
+ class Converter {
+ Double convert(Double price) {
+ return converter.convert("USD", "USD", price);
+ }
+ };
+ Converter c = new Converter();
+
+ String code = "USD";
+ String symbol = converter.symbol(code);
+
+ return list(
+ list(list("'javaClass", "services.Item"), list("'name", "Apple"), list("'currencyCode", code), list("'currencySymbol", symbol), list("'price", c.convert(2.99))),
+ list(list("'javaClass", "services.Item"), list("'name", "Orange"), list("'currencyCode", code), list("'currencySymbol", symbol), list("'price", c.convert(3.55))),
+ list(list("'javaClass", "services.Item"), list("'name", "Pear"), list("'currencyCode", code), list("'currencySymbol", symbol), list("'price", c.convert(1.55)))
+ );
+ }
+
+ /**
+ * TODO remove this JSON-RPC specific function.
+ */
+ public Iterable<?> listMethods(final CurrencyConverter converter) {
+ return list("Service.get");
+ }
+
+}
diff --git a/sca-cpp/trunk/test/store-java/store/ShoppingCartImpl.java b/sca-cpp/trunk/test/store-java/store/ShoppingCartImpl.java
new file mode 100644
index 0000000000..30ee59932a
--- /dev/null
+++ b/sca-cpp/trunk/test/store-java/store/ShoppingCartImpl.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+package store;
+
+import org.apache.tuscany.Service;
+import java.lang.System;
+import java.util.UUID;
+import static org.apache.tuscany.IterableUtil.*;
+
+/**
+ * Shopping cart component implementation.
+ */
+public class ShoppingCartImpl {
+
+ static String cartId = "1234";
+
+ /**
+ * Get the shopping cart from the cache. Return an empty
+ * cart if not found.
+ */
+ public Iterable<?> getcart(String id, Service cache) {
+ Iterable<?> cart = cache.get(id);
+ if (cart == null)
+ return list();
+ return cart;
+ }
+
+ /**
+ * Returns a UUID.
+ */
+ String uuid() {
+ return UUID.randomUUID().toString();
+ }
+
+ /**
+ * Post a new item to the cart. Create a new cart if necessary.
+ */
+ public String post(Iterable<?> item, Service cache) {
+ String id = uuid();
+ Iterable<?> newItem = list(car(item), id, caddr(item));
+ Iterable<?> cart = cons(newItem, getcart(cartId, cache));
+ cache.put(cartId, cart);
+ return id;
+ }
+
+ /**
+ * Return the contents of the cart.
+ */
+ public Iterable<?> getall(Service cache) {
+ return cons("Your Cart", cons(cartId, getcart(cartId, cache)));
+ }
+
+ /**
+ * Find an item in the cart.
+ */
+ public Iterable<?> find(String id, Iterable<?> cart) {
+ if (isNil(cart))
+ return cons("Item", list("0", list()));
+ if (id.equals(cadr(car(cart))))
+ return car(cart);
+ return find(id, cdr(cart));
+ }
+
+ public Iterable<?> get(String id, Service cache) {
+ return find(id, getcart(cartId, cache));
+ }
+
+ /**
+ * Delete the whole cart.
+ */
+ public Boolean deleteall(Service cache) {
+ return cache.delete(cartId);
+ }
+
+ /**
+ * Delete an item from the cart.
+ */
+ public Boolean delete(String id, Service cache) {
+ return true;
+ }
+
+ /**
+ * Return the price of an item.
+ */
+ Double price(Iterable<?> item) {
+ return Double.valueOf((String)cadr(assoc("'price", caddr(item))));
+ }
+
+ /**
+ * Sum the prices of a list of items.
+ */
+ Double sum(Iterable<?> items) {
+ if (isNil(items))
+ return 0.0;
+ return price((Iterable<?>)car(items)) + sum(cdr(items));
+ }
+
+ /**
+ * Return the total price of the items in the cart.
+ */
+ public Double gettotal(Service cache) {
+ Iterable<?> cart = getcart(cartId, cache);
+ return sum(cart);
+ }
+
+ /**
+ * TODO remove this JSON-RPC specific function.
+ */
+ public Iterable<?> listMethods(final CurrencyConverter converter) {
+ return list("Service.gettotal");
+ }
+
+}