summaryrefslogtreecommitdiffstats
path: root/sca-cpp/branches/lightweight-sca/modules/java
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/branches/lightweight-sca/modules/java')
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/Makefile.am70
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/client-test.cpp39
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/domain-test.composite41
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/driver.hpp61
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/eval.hpp566
-rwxr-xr-xsca-cpp/branches/lightweight-sca/modules/java/java-conf38
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/java-shell.cpp40
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/java-test.cpp138
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/jni-test.cpp80
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/mod-java.cpp83
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/mod-java.hpp77
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/ClassLoader.java76
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/InvocationHandler.java59
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/IterableUtil.java398
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/Service.java53
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/UUIDUtil.java32
-rwxr-xr-xsca-cpp/branches/lightweight-sca/modules/java/server-test42
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/test/Adder.java26
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/test/AdderImpl.java28
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/test/CalcImpl.java52
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/test/Client.java34
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/test/ClientImpl.java44
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/test/Server.java34
-rw-r--r--sca-cpp/branches/lightweight-sca/modules/java/test/ServerImpl.java55
-rwxr-xr-xsca-cpp/branches/lightweight-sca/modules/java/wiring-test81
25 files changed, 2247 insertions, 0 deletions
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/Makefile.am b/sca-cpp/branches/lightweight-sca/modules/java/Makefile.am
new file mode 100644
index 0000000000..8b80276d15
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/Makefile.am
@@ -0,0 +1,70 @@
+# 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.
+
+JAVAROOT = $(top_builddir)/modules/java
+
+if WANT_JAVA
+
+INCLUDES = -I${JAVA_INCLUDE}
+
+incl_HEADERS = *.hpp
+incldir = $(prefix)/include/modules/java
+
+dist_mod_SCRIPTS = java-conf
+moddir = $(prefix)/modules/java
+
+prefix_DATA = java.prefix
+prefixdir = $(prefix)/modules/java
+java.prefix: $(top_builddir)/config.status
+ echo ${JAVA_PREFIX} >java.prefix
+
+EXTRA_DIST = domain-test.composite
+
+mod_LTLIBRARIES = libmod_tuscany_java.la
+libmod_tuscany_java_la_SOURCES = mod-java.cpp
+libmod_tuscany_java_la_LDFLAGS = -lxml2 -lcurl -lmozjs ${JAVA_LDFLAGS}
+noinst_DATA = libmod_tuscany_java${libsuffix}
+libmod_tuscany_java${libsuffix}:
+ ln -s .libs/libmod_tuscany_java${libsuffix}
+
+jni_test_SOURCES = jni-test.cpp
+jni_test_LDFLAGS = ${JAVA_LDFLAGS}
+
+java_test_SOURCES = java-test.cpp
+java_test_LDFLAGS = ${JAVA_LDFLAGS}
+
+java_shell_SOURCES = java-shell.cpp
+java_shell_LDFLAGS = ${JAVA_LDFLAGS}
+
+dist_mod_JAVA = org/apache/tuscany/*.java test/*.java
+jardir = ${prefix}/modules/java
+jarfile = libmod-tuscany-java-${PACKAGE_VERSION}.jar
+jar_DATA = ${jarfile}
+${jarfile}: ${dist_mod_JAVA}
+ ${JAR} cf $@ org/apache/tuscany/*.class
+
+CLEANFILES = *.stamp ${jarfile} org/apache/tuscany/*.class test/*.class
+
+client_test_SOURCES = client-test.cpp
+client_test_LDFLAGS = -lxml2 -lcurl -lmozjs
+
+dist_noinst_SCRIPTS = server-test wiring-test
+noinst_PROGRAMS = jni-test java-test client-test
+mod_PROGRAMS = java-shell
+TESTS = jni-test java-test server-test
+
+endif
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/client-test.cpp b/sca-cpp/branches/lightweight-sca/modules/java/client-test.cpp
new file mode 100644
index 0000000000..d06c57721e
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/client-test.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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 HTTP client functions.
+ */
+
+#include "stream.hpp"
+#include "string.hpp"
+#include "../server/client-test.hpp"
+
+int main() {
+ tuscany::cout << "Testing..." << tuscany::endl;
+ tuscany::server::testURI = "http://localhost:8090/java";
+
+ tuscany::server::testServer();
+
+ tuscany::cout << "OK" << tuscany::endl;
+
+ return 0;
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/domain-test.composite b/sca-cpp/branches/lightweight-sca/modules/java/domain-test.composite
new file mode 100644
index 0000000000..a4c696c38d
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/domain-test.composite
@@ -0,0 +1,41 @@
+<?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/200912"
+ targetNamespace="http://domain/test"
+ name="domain-test">
+
+ <component name="java-test">
+ <implementation.java class="test.ServerImpl"/>
+ <service name="test">
+ <binding.http uri="java"/>
+ </service>
+ </component>
+
+ <component name="client-test">
+ <implementation.java class="test.ClientImpl"/>
+ <service name="client">
+ <binding.http uri="client"/>
+ </service>
+ <reference name="ref" target="java-test">
+ <binding.http/>
+ </reference>
+ </component>
+
+</composite>
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/driver.hpp b/sca-cpp/branches/lightweight-sca/modules/java/driver.hpp
new file mode 100644
index 0000000000..ddfc057940
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/driver.hpp
@@ -0,0 +1,61 @@
+/*
+ * 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_java_driver_hpp
+#define tuscany_java_driver_hpp
+
+/**
+ * Java evaluator main driver loop.
+ */
+
+#include "string.hpp"
+#include "stream.hpp"
+#include "monad.hpp"
+#include "../scheme/driver.hpp"
+#include "eval.hpp"
+
+namespace tuscany {
+namespace java {
+
+const value evalDriverLoop(const JavaRuntime& jr, const JavaClass jc, istream& in, ostream& out) {
+ scheme::promptForInput(scheme::evalInputPrompt, out);
+ value input = scheme::readValue(in);
+ if (isNil(input))
+ return input;
+ const failable<value> output = evalClass(jr, input, jc);
+ scheme::announceOutput(scheme::evalOutputPrompt, out);
+ scheme::userPrint(content(output), out);
+ return evalDriverLoop(jr, jc, in, out);
+}
+
+const bool evalDriverRun(const char* name, istream& in, ostream& out) {
+ scheme::setupDisplay(out);
+ JavaRuntime javaRuntime;
+ const failable<JavaClass> jc = readClass(javaRuntime, ".", name);
+ if (!hasContent(jc))
+ return true;
+ evalDriverLoop(javaRuntime, content(jc), in, out);
+ return true;
+}
+
+}
+}
+#endif /* tuscany_java_driver_hpp */
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/eval.hpp b/sca-cpp/branches/lightweight-sca/modules/java/eval.hpp
new file mode 100644
index 0000000000..31fb09f741
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/eval.hpp
@@ -0,0 +1,566 @@
+/*
+ * 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_java_eval_hpp
+#define tuscany_java_eval_hpp
+
+/**
+ * Java component implementation evaluation logic.
+ */
+#include <jni.h>
+
+#include "list.hpp"
+#include "value.hpp"
+
+namespace tuscany {
+namespace java {
+
+/**
+ * Handle differences between various JNI APIs.
+ */
+#ifdef JAVA_HARMONY_VM
+#define JNI_VERSION JNI_VERSION_1_4
+#else
+#define JNI_VERSION JNI_VERSION_1_6
+#endif
+
+/**
+ * Represent a Java VM runtime.
+ */
+jobject JNICALL nativeInvoke(JNIEnv *env, jobject self, jobject proxy, jobject method, jobjectArray args);
+jobject JNICALL nativeUUID(JNIEnv *env);
+
+class JavaRuntime {
+public:
+ JavaRuntime() {
+ debug("java::javaruntime");
+
+ // Get existing JVM
+ jsize nvms = 0;
+ JNI_GetCreatedJavaVMs(&jvm, 1, &nvms);
+ if (nvms == 0) {
+
+ // Create a new JVM
+ JavaVMInitArgs args;
+ args.version = JNI_VERSION;
+ args.ignoreUnrecognized = JNI_FALSE;
+ JavaVMOption options[3];
+ args.options = options;
+ 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));
+ options[args.nOptions++].extraInfo = NULL;
+
+#ifdef WANT_MAINTAINER_ASSERT
+ // 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);
+ options[args.nOptions++].extraInfo = NULL;
+ } 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));
+ options[args.nOptions++].extraInfo = NULL;
+ }
+ }
+
+ // Create the JVM
+#ifdef JAVA_HARMONY_VM
+ JNI_CreateJavaVM(&jvm, &env, &args);
+#else
+ JNI_CreateJavaVM(&jvm, (void**)&env, &args);
+#endif
+
+ } else {
+
+ // Just point to existing JVM
+ jvm->GetEnv((void**)&env, JNI_VERSION);
+ }
+
+ // Lookup System classes and methods
+ classClass = env->FindClass("java/lang/Class");
+ methodClass = env->FindClass("java/lang/reflect/Method");
+ objectClass = env->FindClass("java/lang/Object");
+ doubleClass = env->FindClass("java/lang/Double");
+ booleanClass = env->FindClass("java/lang/Boolean");
+ stringClass = env->FindClass("java/lang/String");
+ objectArrayClass = env->FindClass("[Ljava/lang/Object;");
+ iterableClass = env->FindClass("java/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;");
+ booleanValue = env->GetMethodID(booleanClass, "booleanValue", "()Z");
+ 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;");
+ invokerStackTrace = env->GetStaticMethodID(invokerClass, "stackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;");
+ 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;");
+ uuidClass = env->FindClass("org/apache/tuscany/UUIDUtil");
+
+ // Register our native invocation handler function
+ JNINativeMethod invokenm;
+ invokenm.name = const_cast<char*>("invoke");
+ invokenm.signature = const_cast<char*>("(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
+ invokenm.fnPtr = (void*)nativeInvoke;
+ env->RegisterNatives(invokerClass, &invokenm, 1);
+
+ // Register our native UUID function
+ JNINativeMethod uuidnm;
+ uuidnm.name = const_cast<char*>("uuid");
+ uuidnm.signature = const_cast<char*>("()Ljava/lang/String;");
+ uuidnm.fnPtr = (void*)nativeUUID;
+ env->RegisterNatives(uuidClass, &uuidnm, 1);
+ }
+
+ ~JavaRuntime() {
+ }
+
+ JavaVM* jvm;
+ JNIEnv* env;
+
+ jclass classClass;
+ jclass methodClass;
+ jclass objectClass;
+ jclass doubleClass;
+ jclass booleanClass;
+ jclass stringClass;
+ jclass objectArrayClass;
+ jclass iterableClass;
+ jmethodID doubleValueOf;
+ jmethodID doubleValue;
+ jmethodID booleanValueOf;
+ jmethodID booleanValue;
+ jmethodID declaredMethods;
+ jmethodID methodName;
+ jmethodID parameterTypes;
+ jmethodID classForName;
+ jclass loaderClass;
+ jmethodID loaderValueOf;
+ jmethodID loaderForName;
+ jclass invokerClass;
+ jmethodID invokerValueOf;
+ jmethodID invokerStackTrace;
+ jfieldID invokerLambda;
+ jclass iterableUtilClass;
+ jmethodID iterableValueOf;
+ jmethodID iterableCar;
+ jmethodID iterableCdr;
+ jmethodID iterableIsNil;
+ jclass uuidClass;
+};
+
+/**
+ * Return the last exception that occurred in a JVM.
+ */
+string lastException(const JavaRuntime& jr) {
+ if (!jr.env->ExceptionCheck())
+ return "No Exception";
+ const jthrowable ex = jr.env->ExceptionOccurred();
+ const jstring trace = (jstring)jr.env->CallStaticObjectMethod(jr.invokerClass, jr.invokerStackTrace, ex);
+ const char* c = jr.env->GetStringUTFChars(trace, NULL);
+ const string msg(c);
+ jr.env->ReleaseStringUTFChars(trace, c);
+ jr.env->ExceptionClear();
+ return msg;
+}
+
+/**
+ * Declare conversion functions.
+ */
+const jobject valueToJobject(const JavaRuntime& jr, const value& jtype, const value& v);
+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.
+ */
+const bool jniClassNameHelper(char* to, const char* from) {
+ if (*from == '\0') {
+ *to = '\0';
+ return true;
+ }
+ *to = *from == '.'? '/' : *from;
+ return jniClassNameHelper(to + 1, from + 1);
+}
+
+const string jniClassName(const string& from) {
+ char buf[length(from) + 1];
+ jniClassNameHelper(buf, c_str(from));
+ return string(buf);
+}
+
+/**
+ * Create a new Java object representing a lambda expression.
+ */
+class javaLambda {
+public:
+ javaLambda(const JavaRuntime& jr, const value& iface, const lambda<value(const list<value>&)>& func) : jr(jr), iface(iface), func(func) {
+ }
+
+ const value operator()(const list<value>& expr) const {
+ if (isNil(expr))
+ return func(expr);
+ const value& op(car(expr));
+ if (op == "equals")
+ return value(cadr(expr) == this);
+ if (op == "hashCode")
+ return value((double)(long)this);
+ if (op == "toString") {
+ ostringstream os;
+ os << this;
+ return value(string("org.apache.tuscany.InvocationHandler@") + (c_str(str(os)) + 2));
+ }
+ return func(expr);
+ }
+
+ const JavaRuntime& jr;
+ const value iface;
+ const lambda<value(const list<value>&)> func;
+};
+
+/**
+ * Native implementation of the InvocationHandler.invoke Java method.
+ * Dispatches the call to the lambda function wrapped in the invocation handler.
+ */
+jobject JNICALL nativeInvoke(JNIEnv* env, jobject self, unused jobject proxy, jobject method, jobjectArray args) {
+
+ // Retrieve the lambda function from the invocation handler
+ jclass clazz = env->GetObjectClass(self);
+ jfieldID f = env->GetFieldID(clazz, "lambda", "J");
+ const javaLambda& jl = *(javaLambda*)(long)env->GetLongField(self, f);
+
+ // Retrieve the function name
+ const jstring s = (jstring)env->CallObjectMethod(method, jl.jr.methodName);
+ const char* c = env->GetStringUTFChars(s, NULL);
+ const value func(c);
+ env->ReleaseStringUTFChars(s, c);
+
+ // Build the expression to evaluate, either (func, args[0], args[1], args[2]...)
+ // or just args[0] for the special eval(...) function
+ const list<value> expr = func == "eval"? (list<value>)car<value>(jarrayToValues(jl.jr, args)) : 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);
+}
+
+/**
+ * Native implementation of IterableUtil.uuid. We are providing a native implementation
+ * of this function as java.util.UUID seems to behave differently with different JDKs.
+ */
+jobject JNICALL nativeUUID(JNIEnv* env) {
+ const value uuid = mkuuid();
+ return env->NewStringUTF(c_str(uuid));
+}
+
+/**
+ * Convert a lambda function to Java proxy.
+ */
+const jobject mkJavaLambda(const JavaRuntime& jr, unused const value& iface, const lambda<value(const list<value>&)>& l) {
+ const gc_ptr<javaLambda> jl = new (gc_new<javaLambda>()) javaLambda(jr, iface, l);
+ jclass jc = (jclass)(long)(double)iface;
+ const jobject obj = jr.env->CallStaticObjectMethod(jr.invokerClass, jr.invokerValueOf, jc, (long)(javaLambda*)jl);
+ return obj;
+}
+
+/**
+ * Convert a list of values to a Java jobjectArray.
+ */
+const jobjectArray valuesToJarrayHelper(const JavaRuntime& jr, jobjectArray a, const list<value>& v, const int i) {
+ if (isNil(v))
+ return a;
+ jr.env->SetObjectArrayElement(a, i, valueToJobject(jr, value(), car(v)));
+ return valuesToJarrayHelper(jr, a, cdr(v), i + 1);
+}
+
+const jobjectArray valuesToJarray(const JavaRuntime& jr, const list<value>& v) {
+ jobjectArray a = jr.env->NewObjectArray((jsize)length(v), jr.objectClass, NULL);
+ return valuesToJarrayHelper(jr, a, v, 0);
+}
+
+/**
+ * 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 jarrayToJiterable(jr, valuesToJarray(jr, v));
+ case value::Lambda:
+ return mkJavaLambda(jr, jtype, v);
+ case value::Symbol:
+ return jr.env->NewStringUTF(c_str(string("'") + v));
+ case value::String:
+ return jr.env->NewStringUTF(c_str(v));
+ case value::Number:
+ return jr.env->CallStaticObjectMethod(jr.doubleClass, jr.doubleValueOf, (double)v);
+ case value::Bool:
+ return jr.env->CallStaticObjectMethod(jr.booleanClass, jr.booleanValueOf, (bool)v);
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Convert a list of values to an array of jvalues.
+ */
+const jvalue* valuesToJvaluesHelper(const JavaRuntime& jr, jvalue* a, const list<value>& types, const list<value>& v) {
+ if (isNil(v))
+ return a;
+ a->l = valueToJobject(jr, car(types), car(v));
+ return valuesToJvaluesHelper(jr, a + 1, cdr(types), cdr(v));
+}
+
+const jvalue* valuesToJvalues(const JavaRuntime& jr, const list<value>& types, const list<value>& v) {
+ const size_t n = length(v);
+ jvalue* a = new (gc_anew<jvalue>(n)) jvalue[n];
+ valuesToJvaluesHelper(jr, a, types, v);
+ return a;
+}
+
+/**
+ * Convert a Java jobjectArray to a list of values.
+ */
+const list<value> jarrayToValuesHelper(const JavaRuntime& jr, jobjectArray a, const int i, const int size) {
+ if (i == size)
+ return list<value>();
+ return cons(jobjectToValue(jr, jr.env->GetObjectArrayElement(a, i)), jarrayToValuesHelper(jr, a, i + 1, size));
+}
+
+const list<value> jarrayToValues(const JavaRuntime& jr, jobjectArray o) {
+ if (o == NULL)
+ return list<value>();
+ return jarrayToValuesHelper(jr, o, 0, jr.env->GetArrayLength(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 {
+ const JavaRuntime& jr;
+ const jobject obj;
+
+ javaCallable(const JavaRuntime& jr, const jobject obj) : jr(jr), obj(obj) {
+ }
+
+ const value operator()(const list<value>& args) const {
+ jobjectArray jargs = valuesToJarray(jr, args);
+ jobject result = jargs; //CallObject(func, jargs);
+ return jobjectToValue(jr, result);
+ }
+};
+
+/**
+ * Convert a Java jobject to a value.
+ */
+const value jobjectToValue(const JavaRuntime& jr, const jobject o) {
+ if (o == NULL)
+ return value();
+ const jclass clazz = jr.env->GetObjectClass(o);
+ if ((jr.env->IsSameObject(clazz, jr.stringClass))) {
+ const char* s = jr.env->GetStringUTFChars((jstring)o, NULL);
+ if (*s == '\'') {
+ const value v(s + 1);
+ jr.env->ReleaseStringUTFChars((jstring)o, s);
+ return v;
+ }
+ const value v = string(s);
+ jr.env->ReleaseStringUTFChars((jstring)o, s);
+ return v;
+ }
+ if (jr.env->IsSameObject(clazz, jr.booleanClass))
+ 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->IsAssignableFrom(clazz, jr.iterableClass))
+ return jiterableToValues(jr, o);
+ if (jr.env->IsAssignableFrom(clazz, jr.objectArrayClass))
+ return jarrayToValues(jr, (jobjectArray)o);
+ return lambda<value(const list<value>&)>(javaCallable(jr, o));
+}
+
+/**
+ * Returns a balanced tree of the methods of a class.
+ */
+const value parameterTypeToValue(const jobject t) {
+ return value((double)(long)t);
+}
+
+const list<value> parameterTypesToValues(const JavaRuntime& jr, const jobjectArray t, const int i) {
+ if (i == 0)
+ return list<value>();
+ return cons<value>(parameterTypeToValue(jr.env->GetObjectArrayElement(t, i - 1)), parameterTypesToValues(jr, t, i - 1));
+}
+
+const value methodToValue(const JavaRuntime& jr, const jobject m) {
+ const jobject s = jr.env->CallObjectMethod(m, jr.methodName);
+ const char* c = jr.env->GetStringUTFChars((jstring)s, NULL);
+ const string& name = string(c);
+ jr.env->ReleaseStringUTFChars((jstring)s, c);
+
+ const jmethodID mid = jr.env->FromReflectedMethod(m);
+
+ const jobjectArray t = (jobjectArray)jr.env->CallObjectMethod(m, jr.parameterTypes);
+ const list<value> types = reverse(parameterTypesToValues(jr, t, jr.env->GetArrayLength(t)));
+
+ return cons<value>(c_str(name), cons<value>((double)(long)mid, types));
+}
+
+const list<value> methodsToValues(const JavaRuntime& jr, const jobjectArray m, const int i) {
+ if (i == 0)
+ return list<value>();
+ return cons<value>(methodToValue(jr, jr.env->GetObjectArrayElement(m, i - 1)), methodsToValues(jr, m, i - 1));
+}
+
+const list<value> methodsToValues(const JavaRuntime& jr, const jclass clazz) {
+ const jobjectArray m = (jobjectArray)jr.env->CallObjectMethod(clazz, jr.declaredMethods);
+ return methodsToValues(jr, m, jr.env->GetArrayLength(m));
+}
+
+/**
+ * Represents a Java Class.
+ */
+class JavaClass {
+public:
+ JavaClass() : loader(NULL), clazz(NULL), obj(NULL) {
+ }
+ 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;
+};
+
+/**
+ * Read a class.
+ */
+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(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);
+ if (isNil(func)) {
+
+ // The start, stop, and restart functions are optional
+ const value fn = car<value>(expr);
+ if (fn == "start" || fn == "stop")
+ return value(lambda<value(const list<value>&)>());
+
+ return mkfailure<value>(string("Couldn't find function: ") + car<value>(expr) + " : " + lastException(jr));
+ }
+ const jmethodID fid = (jmethodID)(long)(double)cadr(func);
+
+ // Convert args to Java jvalues
+ const jvalue* args = valuesToJvalues(jr, cddr(func), cdr<value>(expr));
+
+ // Call the Java function
+ const jobject result = jr.env->CallObjectMethodA(jc.obj, fid, const_cast<jvalue*>(args));
+ if (result == NULL)
+ return mkfailure<value>(string("Function call failed: ") + car<value>(expr) + " : " + lastException(jr));
+
+ // Convert Java result to a value
+ const value v = jobjectToValue(jr, result);
+ debug(v, "java::evalClass::result");
+ return v;
+}
+
+}
+}
+#endif /* tuscany_java_eval_hpp */
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/java-conf b/sca-cpp/branches/lightweight-sca/modules/java/java-conf
new file mode 100755
index 0000000000..baa5c059c2
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/java-conf
@@ -0,0 +1,38 @@
+#!/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.
+
+# Generate a Java server conf
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+mkdir -p $1
+root=`echo "import os; print os.path.realpath('$1')" | python`
+
+uname=`uname -s`
+if [ $uname = "Darwin" ]; then
+ libsuffix=".dylib"
+else
+ libsuffix=".so"
+fi
+
+cat >>$root/conf/modules.conf <<EOF
+# Generated by: java-conf $*
+# Support for Java SCA components
+LoadModule mod_tuscany_eval $here/libmod_tuscany_java${libsuffix}
+
+EOF
+
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/java-shell.cpp b/sca-cpp/branches/lightweight-sca/modules/java/java-shell.cpp
new file mode 100644
index 0000000000..51df513990
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/java-shell.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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$ */
+
+/**
+ * Java evaluator shell, used for interactive testing of Java classes.
+ */
+
+#include <assert.h>
+#include "gc.hpp"
+#include "stream.hpp"
+#include "string.hpp"
+#include "driver.hpp"
+
+int main(const int argc, char** argv) {
+ tuscany::gc_scoped_pool pool;
+ if (argc != 2) {
+ tuscany::cerr << "Usage: java-shell <class name>" << tuscany::endl;
+ return 1;
+ }
+ tuscany::java::evalDriverRun(argv[1], tuscany::cin, tuscany::cout);
+ return 0;
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/java-test.cpp b/sca-cpp/branches/lightweight-sca/modules/java/java-test.cpp
new file mode 100644
index 0000000000..f811a4f58d
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/java-test.cpp
@@ -0,0 +1,138 @@
+/*
+ * 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 Java evaluator.
+ */
+
+#include <assert.h>
+#include "stream.hpp"
+#include "string.hpp"
+#include "driver.hpp"
+
+namespace tuscany {
+namespace java {
+
+bool testEvalExpr() {
+ gc_scoped_pool pool;
+ JavaRuntime javaRuntime;
+ {
+ 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));
+ assert(hasContent(r));
+ assert(content(r) == value(6));
+ }
+ {
+ 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;
+}
+
+const value add(const list<value>& args) {
+ assert(car(args) == "add");
+ const double x = cadr(args);
+ const double y = caddr(args);
+ return x + y;
+}
+
+bool testEvalLambda() {
+ gc_scoped_pool pool;
+ JavaRuntime javaRuntime;
+ {
+ 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));
+ assert(hasContent(r));
+ assert(content(r) == value(7));
+ }
+ {
+ const failable<JavaClass> obj = readClass(javaRuntime, ".", "test.CalcImpl");
+ assert(hasContent(obj));
+ const value tcel = mklist<value>("addEval", 3, 4, lambda<value(const list<value>&)>(add));
+ const failable<value> r = evalClass(javaRuntime, tcel, content(obj));
+ assert(hasContent(r));
+ assert(content(r) == value(7));
+ }
+ return true;
+}
+
+bool testClassLoader() {
+ gc_scoped_pool pool;
+ JavaRuntime javaRuntime;
+ 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;
+ JavaRuntime javaRuntime;
+ 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::testEvalLambda();
+ tuscany::java::testClassLoader();
+ tuscany::java::testIterableUtil();
+
+ tuscany::cout << "OK" << tuscany::endl;
+ return 0;
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/jni-test.cpp b/sca-cpp/branches/lightweight-sca/modules/java/jni-test.cpp
new file mode 100644
index 0000000000..727af13dc6
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/jni-test.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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$ */
+
+/**
+ * Basic JNI test.
+ */
+
+#include <assert.h>
+#include <jni.h>
+#include "stream.hpp"
+#include "string.hpp"
+#include "fstream.hpp"
+#include "eval.hpp"
+
+namespace tuscany {
+namespace java {
+
+#ifdef JAVA_HARMONY_VM
+#define JNI_VERSION JNI_VERSION_1_4
+#else
+#define JNI_VERSION JNI_VERSION_1_6
+#endif
+
+bool testJNI() {
+ gc_scoped_pool pool;
+ JavaVM* jvm;
+ JNIEnv* env;
+
+ JavaVMInitArgs args;
+ args.version = JNI_VERSION;
+ args.ignoreUnrecognized = JNI_FALSE;
+ JavaVMOption options[3];
+ args.options = options;
+ args.nOptions = 0;
+ 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));
+ options[args.nOptions++].extraInfo = NULL;
+#ifdef JAVA_HARMONY_VM
+ JNI_CreateJavaVM(&jvm, &env, &args);
+#else
+ JNI_CreateJavaVM(&jvm, (void**)&env, &args);
+#endif
+
+ jclass classClass = env->FindClass("java/lang/Class");
+ assert(classClass != NULL);
+ jclass loaderClass = env->FindClass("org/apache/tuscany/ClassLoader");
+ assert(loaderClass != NULL);
+ return true;
+}
+
+}
+}
+
+int main() {
+ tuscany::cout << "Testing..." << tuscany::endl;
+
+ tuscany::java::testJNI();
+
+ tuscany::cout << "OK" << tuscany::endl;
+ return 0;
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/mod-java.cpp b/sca-cpp/branches/lightweight-sca/modules/java/mod-java.cpp
new file mode 100644
index 0000000000..d96861cc6d
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/mod-java.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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$ */
+
+/**
+ * HTTPD module used to eval Java component implementations.
+ */
+
+#define WANT_HTTPD_LOG 1
+#include "string.hpp"
+#include "function.hpp"
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "../server/mod-cpp.hpp"
+#include "../server/mod-eval.hpp"
+#include "mod-java.hpp"
+
+namespace tuscany {
+namespace server {
+namespace modeval {
+
+/**
+ * Apply a lifecycle start or restart event.
+ */
+struct javaLifecycle {
+ javaLifecycle(java::JavaRuntime& jr) : jr(jr) {
+ }
+ const value operator()(const list<value>& params) const {
+ const value func = car(params);
+ if (func == "javaRuntime")
+ return (gc_ptr<value>)(value*)(void*)&jr;
+ return lambda<value(const list<value>&)>();
+ }
+ java::JavaRuntime& jr;
+};
+
+const value applyLifecycle(unused const list<value>& params) {
+
+ // Create a Java runtime
+ java::JavaRuntime& jr = *(new (gc_new<java::JavaRuntime>()) java::JavaRuntime());
+
+ // Return the function to invoke on subsequent events
+ return failable<value>(lambda<value(const list<value>&)>(javaLifecycle(jr)));
+}
+
+/**
+ * Evaluate a Java component implementation and convert it to an applicable
+ * lambda function.
+ */
+const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle) {
+ const string itype(elementName(impl));
+ if (contains(itype, ".java")) {
+ const void* p = (gc_ptr<value>)lifecycle(mklist<value>("javaRuntime"));
+ return modjava::evalImplementation(path, impl, px, *(java::JavaRuntime*)p);
+ }
+ if (contains(itype, ".cpp"))
+ return modcpp::evalImplementation(path, impl, px);
+ if (contains(itype, ".widget"))
+ return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype, -1, false);
+ return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype);
+}
+
+}
+}
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/mod-java.hpp b/sca-cpp/branches/lightweight-sca/modules/java/mod-java.hpp
new file mode 100644
index 0000000000..b68f17aa3f
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/mod-java.hpp
@@ -0,0 +1,77 @@
+/*
+ * 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_modjava_hpp
+#define tuscany_modjava_hpp
+
+/**
+ * Evaluation functions used by mod-eval to evaluate Java
+ * component implementations.
+ */
+
+#include "string.hpp"
+#include "stream.hpp"
+#include "function.hpp"
+#include "list.hpp"
+#include "value.hpp"
+#include "monad.hpp"
+#include "eval.hpp"
+
+namespace tuscany {
+namespace server {
+namespace modjava {
+
+/**
+ * Apply a Java component implementation function.
+ */
+struct applyImplementation {
+ java::JavaClass impl;
+ const list<value> px;
+ java::JavaRuntime& jr;
+ applyImplementation(const java::JavaClass& impl, const list<value>& px, java::JavaRuntime& jr) : impl(impl), px(px), jr(jr) {
+ }
+ const value operator()(const list<value>& params) const {
+ const value expr = append<value>(params, px);
+ debug(expr, "modeval::java::applyImplementation::input");
+ const failable<value> res = java::evalClass(jr, expr, impl);
+ const value val = !hasContent(res)? mklist<value>(value(), reason(res), rcode(res)) : mklist<value>(content(res));
+ debug(val, "modeval::java::applyImplementation::result");
+ return val;
+ }
+};
+
+/**
+ * Evaluate a Java component implementation and convert it to an applicable
+ * lambda function.
+ */
+const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, java::JavaRuntime& jr) {
+ const string cn(attributeValue("class", impl));
+ const failable<java::JavaClass> jc = java::readClass(jr, path, cn);
+ if (!hasContent(jc))
+ return mkfailure<lambda<value(const list<value>&)> >(jc);
+ return lambda<value(const list<value>&)>(applyImplementation(content(jc), px, jr));
+}
+
+}
+}
+}
+
+#endif /* tuscany_modjava_hpp */
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/ClassLoader.java b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/ClassLoader.java
new file mode 100644
index 0000000000..ef7b2316fb
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/ClassLoader.java
@@ -0,0 +1,76 @@
+/*
+ * 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 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/branches/lightweight-sca/modules/java/org/apache/tuscany/InvocationHandler.java b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/InvocationHandler.java
new file mode 100644
index 0000000000..06466fe9fc
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/InvocationHandler.java
@@ -0,0 +1,59 @@
+/*
+ * 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 java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * 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;
+ }
+
+ /**
+ * 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));
+ }
+
+ /**
+ * Proxy invocation of a C++ function.
+ */
+ public native Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable;
+
+ /**
+ * Return the stack trace of an exception.
+ */
+ static String stackTrace(final Throwable e) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ return sw.toString();
+ }
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/IterableUtil.java b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/IterableUtil.java
new file mode 100644
index 0000000000..2366d79af6
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/IterableUtil.java
@@ -0,0 +1,398 @@
+/*
+ * 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 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>() {
+ 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 cdr of the cdr of the cdr of a list.
+ */
+ public static <T> Iterable<T> cdddr(final Object l) {
+ return cdr(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 car of the cdr of the cdr of the cdr of a list.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T cadddr(final Object l) {
+ return (T)car(cdddr(l));
+ }
+
+ /**
+ * Appends a list and another list.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterable<T> append(final Object a, final Object b) {
+ if (isNil(a))
+ return (Iterable<T>)b;
+ return cons(car(a), append(cdr(a), b));
+ }
+
+ /**
+ * 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() {
+ return this.isNil()? 0 : 1 + ((List<T>)this.cdr()).size();
+ }
+
+ @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;
+
+ public boolean hasNext() {
+ return this.i < ArrayIterable.this.a.length;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T next() {
+ return (T)ArrayIterable.this.a[this.i++];
+ }
+
+ 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;
+
+ public boolean hasNext() {
+ return this.i < ListIterable.this.l.size();
+ }
+
+ @SuppressWarnings("unchecked")
+ public T next() {
+ return (T)ListIterable.this.l.get(this.i++);
+ }
+
+ 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();
+
+ public boolean hasNext() {
+ if(this.carIterator)
+ return true;
+ return this.cdrIterator.hasNext();
+ }
+
+ @SuppressWarnings("unchecked")
+ public T next() {
+ if(this.carIterator) {
+ this.carIterator = false;
+ return (T)PairIterable.this.car;
+ }
+ return (T)this.cdrIterator.next();
+ }
+
+ 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);
+
+ final Iterable<Object> a = list(0, 1, 2);
+ final Iterable<Object> b = list(3, 4);
+ final Iterable<Object> ab = append(a, b);
+ assert ab.toString().equals("[0, 1, 2, 3, 4]");
+ 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/branches/lightweight-sca/modules/java/org/apache/tuscany/Service.java b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/Service.java
new file mode 100644
index 0000000000..a00d5b1b53
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/Service.java
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+/**
+ * Interface used to represent SCA component references providing both REST
+ * access to a resource and function application.
+ */
+public interface Service {
+
+ /**
+ * Post a new item to a collection of items.
+ */
+ Iterable<String> post(Iterable<String> collection, Iterable<?> item);
+
+ /**
+ * Return an item.
+ */
+ Iterable<?> get(Iterable<String> id);
+
+ /**
+ * Update an item.
+ */
+ boolean put(Iterable<String> id, Iterable<?> item);
+
+ /**
+ * Delete an item.
+ */
+ boolean delete(Iterable<String> id);
+
+ /**
+ * Evaluate an expression.
+ */
+ <T> T eval(Object... params);
+
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/UUIDUtil.java b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/UUIDUtil.java
new file mode 100644
index 0000000000..60076c62ca
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/org/apache/tuscany/UUIDUtil.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+/**
+ * A fast and portable UUID generator function.
+ */
+public class UUIDUtil {
+
+ /**
+ * Return a UUID.
+ */
+ public static native String uuid();
+
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/server-test b/sca-cpp/branches/lightweight-sca/modules/java/server-test
new file mode 100755
index 0000000000..0b45649ace
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/server-test
@@ -0,0 +1,42 @@
+#!/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
+rm -rf tmp
+../http/httpd-conf tmp localhost 8090 ../server/htdocs
+../server/server-conf tmp
+./java-conf tmp
+cat >>tmp/conf/httpd.conf <<EOF
+SCAContribution `pwd`/
+SCAComposite domain-test.composite
+EOF
+
+export CLASSPATH="`pwd`/libmod-tuscany-java-1.0.jar:`pwd`"
+
+../http/httpd-start tmp
+sleep 2
+
+# Test
+./client-test 2>/dev/null
+rc=$?
+
+# Cleanup
+../http/httpd-stop tmp
+sleep 2
+exit $rc
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/test/Adder.java b/sca-cpp/branches/lightweight-sca/modules/java/test/Adder.java
new file mode 100644
index 0000000000..7236548c41
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/test/Adder.java
@@ -0,0 +1,26 @@
+/*
+ * 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 test;
+
+public interface Adder {
+
+ Double add(Double x, Double y);
+
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/test/AdderImpl.java b/sca-cpp/branches/lightweight-sca/modules/java/test/AdderImpl.java
new file mode 100644
index 0000000000..e607012b78
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/test/AdderImpl.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 test;
+
+public class AdderImpl {
+
+ public Double add(Double x, Double y) {
+ return x + y;
+ }
+
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/test/CalcImpl.java b/sca-cpp/branches/lightweight-sca/modules/java/test/CalcImpl.java
new file mode 100644
index 0000000000..5bea01a43f
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/test/CalcImpl.java
@@ -0,0 +1,52 @@
+/*
+ * 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 test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.Service;
+
+public class CalcImpl {
+
+ public Double add(final Double x, final Double y, final Adder adder) {
+ return adder.add(x, y);
+ }
+
+ public Double addEval(final Double x, final Double y, final Service adder) {
+ return adder.eval("add", x, y);
+ }
+
+ public Double mult(final Double x, final Double y) {
+ return x * y;
+ }
+
+ public Boolean even(final Double x) {
+ return (double)((int)(double)x / 2 * 2) == (double)x;
+ }
+
+ public Iterable<Double> square(final Iterable<Double> l) {
+ final List<Double> r = new ArrayList<Double>();
+ for(final Double x : l)
+ r.add(x * x);
+ return r;
+ }
+
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/test/Client.java b/sca-cpp/branches/lightweight-sca/modules/java/test/Client.java
new file mode 100644
index 0000000000..c3bd875fcc
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/test/Client.java
@@ -0,0 +1,34 @@
+/*
+ * 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 test;
+
+public interface Client {
+
+ String echo(String x);
+
+ Iterable<?> get(Iterable<String> id);
+
+ Iterable<String> post(Iterable<String> collection, Iterable<?> item);
+
+ Boolean put(Iterable<String> id, Iterable<?> item);
+
+ Boolean delete(Iterable<String> id);
+
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/test/ClientImpl.java b/sca-cpp/branches/lightweight-sca/modules/java/test/ClientImpl.java
new file mode 100644
index 0000000000..ade2ba302e
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/test/ClientImpl.java
@@ -0,0 +1,44 @@
+/*
+ * 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 test;
+
+public class ClientImpl {
+
+ public String echo(String x, Server server) {
+ return server.echo(x);
+ }
+
+ public Iterable<?> get(Iterable<String> id, Server server) {
+ return server.get(id);
+ }
+
+ public Iterable<String> post(Iterable<String> collection, Iterable<?> item, Server server) {
+ return server.post(collection, item);
+ }
+
+ public Boolean put(Iterable<String> id, Iterable<?> item, Server server) {
+ return server.put(id, item);
+ }
+
+ public Boolean delete(Iterable<String> id, Server server) {
+ return server.delete(id);
+ }
+
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/test/Server.java b/sca-cpp/branches/lightweight-sca/modules/java/test/Server.java
new file mode 100644
index 0000000000..3dfe3c84ef
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/test/Server.java
@@ -0,0 +1,34 @@
+/*
+ * 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 test;
+
+public interface Server {
+
+ String echo(String x);
+
+ Iterable<?> get(Iterable<String> id);
+
+ Iterable<String> post(Iterable<String> collection, Iterable<?> item);
+
+ Boolean put(Iterable<String> id, Iterable<?> item);
+
+ Boolean delete(Iterable<String> id);
+
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/test/ServerImpl.java b/sca-cpp/branches/lightweight-sca/modules/java/test/ServerImpl.java
new file mode 100644
index 0000000000..ee25cf7bf8
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/test/ServerImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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 test;
+
+import static org.apache.tuscany.IterableUtil.*;
+
+public class ServerImpl {
+
+ public String echo(final String x) {
+ return x;
+ }
+
+ public Iterable<?> get(final Iterable<String> id) {
+ if (isNil(id))
+ return list(list("'feed", list("'title", "Sample Feed"), list("'id", "123456789"), list("'entry", list(
+ list(list("'title", "Item"), list("'id", "111"),
+ list("'content", list("'item", list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99)))),
+ list(list("'title", "Item"), list("'id", "222"),
+ list("'content", list("'item", list("'name", "Orange"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 3.55)))),
+ list(list("'title", "Item"), list("'id", "333"),
+ list("'content", list("'item", list("'name", "Pear"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 1.55))))))));
+
+ final Iterable<?> content = list("'content", list("'item", list("'name", "Apple"), list("'currencyCode", "USD"), list("'currencySymbol", "$"), list("'price", 2.99)));
+ return list(list("'entry", list("'title", "Item"), list("'id", car(id)), content));
+ }
+
+ public Iterable<String> post(final Iterable<String> collection, final Iterable<?> item) {
+ return list("123456789");
+ }
+
+ public Boolean put(final Iterable<String> id, final Iterable<?> item) {
+ return true;
+ }
+
+ public Boolean delete(final Iterable<String> id) {
+ return true;
+ }
+}
diff --git a/sca-cpp/branches/lightweight-sca/modules/java/wiring-test b/sca-cpp/branches/lightweight-sca/modules/java/wiring-test
new file mode 100755
index 0000000000..dd865c4c66
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/modules/java/wiring-test
@@ -0,0 +1,81 @@
+#!/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.
+
+echo "Testing..."
+here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
+curl_prefix=`cat $here/../http/curl.prefix`
+
+# Setup
+rm -rf tmp
+../http/httpd-conf tmp localhost 8090 ../server/htdocs
+../server/server-conf tmp
+./java-conf tmp
+cat >>tmp/conf/httpd.conf <<EOF
+SCAContribution `pwd`/
+SCAComposite domain-test.composite
+EOF
+
+export CLASSPATH="`pwd`/libmod-tuscany-java-1.0.jar:`pwd`"
+
+../http/httpd-start tmp
+sleep 2
+
+# Test HTTP GET
+$curl_prefix/bin/curl http://localhost:8090/index.html 2>/dev/null >tmp/index.html
+diff tmp/index.html ../server/htdocs/index.html
+rc=$?
+
+# Test ATOMPub
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl http://localhost:8090/client/ >tmp/feed.xml 2>/dev/null
+ diff tmp/feed.xml ../server/htdocs/test/feed.xml
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl http://localhost:8090/client/111 >tmp/entry.xml 2>/dev/null
+ diff tmp/entry.xml ../server/htdocs/test/entry.xml
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl http://localhost:8090/client/ -X POST -H "Content-type: application/atom+xml" --data @../server/htdocs/test/entry.xml 2>/dev/null
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl http://localhost:8090/client/111 -X PUT -H "Content-type: application/atom+xml" --data @../server/htdocs/test/entry.xml 2>/dev/null
+ rc=$?
+fi
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl http://localhost:8090/client/111 -X DELETE 2>/dev/null
+ rc=$?
+fi
+
+# Test JSON-RPC
+if [ "$rc" = "0" ]; then
+ $curl_prefix/bin/curl http://localhost:8090/client/ -X POST -H "Content-type: application/json-rpc" --data @../server/htdocs/test/json-request.txt >tmp/json-result.txt 2>/dev/null
+ diff tmp/json-result.txt ../server/htdocs/test/json-result.txt
+ rc=$?
+fi
+
+# Cleanup
+../http/httpd-stop tmp
+sleep 2
+if [ "$rc" = "0" ]; then
+ echo "OK"
+fi
+exit $rc