diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-11 08:29:39 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-11 08:29:39 +0000 |
commit | 81678737cc3682dd811660ca794851b72e2b1fbe (patch) | |
tree | 62d0ffd191130ed443c777fdad7a24eea157b157 /sca-cpp/trunk | |
parent | f5202e9e875e5e6c797e97c4db53f1f4d7364c65 (diff) |
Added utility functions to help call Java code using JNI and wrap Axis2/java in a component.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@897789 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r-- | sca-cpp/trunk/modules/java/Makefile.am | 39 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/driver.hpp | 60 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/eval.hpp | 398 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/io.hpp | 43 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/java-shell.cpp | 40 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/java-test.cpp | 87 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java | 39 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/test/Adder.java | 26 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/test/AdderImpl.java | 28 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/test/CalcImpl.java | 32 |
10 files changed, 792 insertions, 0 deletions
diff --git a/sca-cpp/trunk/modules/java/Makefile.am b/sca-cpp/trunk/modules/java/Makefile.am new file mode 100644 index 0000000000..790277104b --- /dev/null +++ b/sca-cpp/trunk/modules/java/Makefile.am @@ -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. + +datadir=$(prefix)/modules/java +JAVAROOT = $(top_builddir)/modules/java + +if WANT_JAVA + +noinst_PROGRAMS = java-test java-shell + +INCLUDES = -I${JAVA_INCLUDE} + +java_test_SOURCES = java-test.cpp +java_test_LDADD = -L${JAVA_LIB} -ljava +java_test_LDFLAGS = -rpath ${JAVA_LIB} -rpath ${JAVA_LIB}/server + +java_shell_SOURCES = java-shell.cpp +java_shell_LDADD = -L${JAVA_LIB} -ljava +java_shell_LDFLAGS = -rpath ${JAVA_LIB} -rpath ${JAVA_LIB}/server + +noinst_JAVA = org/apache/tuscany/*.java test/*.java + +TESTS = java-test + +endif
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/java/driver.hpp b/sca-cpp/trunk/modules/java/driver.hpp new file mode 100644 index 0000000000..9bc55915c5 --- /dev/null +++ b/sca-cpp/trunk/modules/java/driver.hpp @@ -0,0 +1,60 @@ +/* + * 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); + 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/trunk/modules/java/eval.hpp b/sca-cpp/trunk/modules/java/eval.hpp new file mode 100644 index 0000000000..b51a57337e --- /dev/null +++ b/sca-cpp/trunk/modules/java/eval.hpp @@ -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. + */ + +/* $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" +#include "io.hpp" + +namespace tuscany { +namespace java { + +/** + * Initialize a JVM. + */ +jobject JNICALL nativeInvoke(JNIEnv *env, jobject self, jobject proxy, jobject method, jobjectArray args); + +class JavaRuntime { +public: + JavaRuntime() { + + // Create a JVM + JavaVMInitArgs args; + args.version = JNI_VERSION_1_6; + args.ignoreUnrecognized = JNI_FALSE; + JavaVMOption options[1]; + options[0].optionString = const_cast<char*>("-Djava.class.path=."); + args.options = options; + args.nOptions = 1; + JNI_CreateJavaVM(&jvm, (void**)&env, &args); + + // Capture JVM standard IO + setupIO(); + + // Lookup the system classes and methods we need + 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;"); + 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;"); + + // Register our native invocation handler native + 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"); + 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); + } + + ~JavaRuntime() { + if (jvm == NULL) + return; + jvm->DestroyJavaVM(); + } + + JavaVM* jvm; + JNIEnv* env; + + jclass classClass; + jclass methodClass; + jclass objectClass; + jclass doubleClass; + jclass booleanClass; + jclass stringClass; + jclass objectArrayClass; + jmethodID doubleValueOf; + jmethodID doubleValue; + jmethodID booleanValueOf; + jmethodID booleanValue; + jmethodID declaredMethods; + jmethodID methodName; + + jclass invokerClass; + jmethodID invokerValueOf; + jfieldID invokerLambda; + +} javaRuntime; + +/** + * Return the last exception that occurred in a JVM. + */ +string lastException(const JavaRuntime& jr) { + if (!jr.env->ExceptionCheck()) + return "No Exception"; + jr.env->ExceptionDescribe(); + jr.env->ExceptionClear(); + return "UnknownException"; +} + +/** + * Declare conversion functions. + */ +const jobject valueToJobject(const JavaRuntime& jr, 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); + +/** + * 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 JavaRuntime& jr; + const value iface; + const lambda<value(const list<value>&)> func; +}; + +/** + * Invocation handler invoke method, dispatches 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 + const list<value> expr = cons<value>(func, jarrayToValues(jl.jr, args)); + + // Invoke the lambda function + value result = jl.func(expr); + + // Convert result to a jobject + return valueToJobject(jl.jr, result); +} + +const jobject mkJavaLambda(const JavaRuntime& jr, const lambda<value(const list<value>&)>& l) { + + // The lambda function is given the opportunity to give us a + // Java interface name that it implements, and which will be + // used as the type of the Java proxy representing it. If the + // lambda function doesn't specify an interface, then the + // proxy implements javax.script.Invocable. + const value iface = l(mklist<value>("interface")); + const gc_ptr<javaLambda> jl = new (gc_new<javaLambda>()) javaLambda(jr, iface, l); + + jclass jc = jr.env->FindClass(c_str(jniClassName(string(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, 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(length(v), jr.objectClass, NULL); + return valuesToJarrayHelper(jr, a, v, 0); +} + +/** + * Convert a value to a Java jobject. + */ +const jobject valueToJobject(const JavaRuntime& jr, const value& v) { + switch (type(v)) { + case value::List: + return valuesToJarray(jr, v); + case value::Lambda: + return mkJavaLambda(jr, 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, (double)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>& v) { + if (isNil(v)) + return a; + a->l = valueToJobject(jr, car(v)); + return valuesToJvaluesHelper(jr, a + 1, cdr(v)); +} + +const jvalue* valuesToJvalues(const JavaRuntime& jr, const list<value>& v) { + const int n = length(v); + jvalue* a = new (gc_anew<jvalue>(n)) jvalue[n]; + valuesToJvaluesHelper(jr, a, 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) { + return jarrayToValuesHelper(jr, o, 0, jr.env->GetArrayLength(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->IsSameObject(clazz, jr.objectArrayClass))) + return jarrayToValues(jr, (jobjectArray)o); + return lambda<value(const list<value>&)>(javaCallable(jr, o)); +} + +/** + * Returns a balanced tree of a class' methods. + */ +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); + return mklist<value>(c_str(name), (double)(long)mid); +} + +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() : clazz(NULL), obj(NULL) { + } + + JavaClass(const jclass clazz, const jobject obj, const list<value> m) : clazz(clazz), obj(obj), m(m) { + } + + const jclass clazz; + const jobject obj; + const list<value> m; +}; + +/** + * 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)); + if (clazz == NULL) + return mkfailure<JavaClass>(string("Couldn't load class: ") + name + " : " + lastException(jr)); + 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)); +} + +/** + * Evaluate an expression against a Java class. + */ +const failable<value> evalClass(const JavaRuntime& jr, const value& expr, const JavaClass jc) { + + // Lookup the Java function named as the expression operand + const list<value> func = assoc<value>(car<value>(expr), jc.m); + if (isNil(func)) + 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, cdr<value>(expr)); + + // Call the Java function + const jobject result = jr.env->CallObjectMethodA(jc.obj, fid, args); + if (result == NULL) + return mkfailure<value>(string("Function call failed: ") + car<value>(expr) + " : " + lastException(jr)); + + // Convert Java result to a value + return jobjectToValue(jr, result); +} + +} +} +#endif /* tuscany_java_eval_hpp */ diff --git a/sca-cpp/trunk/modules/java/io.hpp b/sca-cpp/trunk/modules/java/io.hpp new file mode 100644 index 0000000000..58ca58f0b2 --- /dev/null +++ b/sca-cpp/trunk/modules/java/io.hpp @@ -0,0 +1,43 @@ +/* + * 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_io_hpp +#define tuscany_java_io_hpp + +/** + * Java IO functions. + */ +#include "stream.hpp" +#include "../scheme/io.hpp" + +namespace tuscany { +namespace java { + +/** + * Setup the display and log hooks. + */ +bool setupIO() { + return true; +} + +} +} +#endif /* tuscany_python_pyio_hpp */ diff --git a/sca-cpp/trunk/modules/java/java-shell.cpp b/sca-cpp/trunk/modules/java/java-shell.cpp new file mode 100644 index 0000000000..51df513990 --- /dev/null +++ b/sca-cpp/trunk/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/trunk/modules/java/java-test.cpp b/sca-cpp/trunk/modules/java/java-test.cpp new file mode 100644 index 0000000000..e50cfe5671 --- /dev/null +++ b/sca-cpp/trunk/modules/java/java-test.cpp @@ -0,0 +1,87 @@ +/* + * 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; + { + 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.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)); + } + return true; +} + +const value add(const list<value>& args) { + if (car(args) == "interface") + return "test.Adder"; + + assert(car(args) == "add"); + const double x = cadr(args); + const double y = caddr(args); + return x + y; +} + +bool testEvalLambda() { + gc_scoped_pool pool; + 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)); + return true; +} + +} +} + +int main() { + tuscany::cout << "Testing..." << tuscany::endl; + + //tuscany::java::testEvalExpr(); + tuscany::java::testEvalLambda(); + + tuscany::cout << "OK" << tuscany::endl; + return 0; +} diff --git a/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java b/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java new file mode 100644 index 0000000000..423fe6248d --- /dev/null +++ b/sca-cpp/trunk/modules/java/org/apache/tuscany/InvocationHandler.java @@ -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. + */ + +package org.apache.tuscany; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +public class InvocationHandler implements java.lang.reflect.InvocationHandler { + final long lambda; + + InvocationHandler(final long lambda) { + this.lambda = lambda; + } + + public static Object valueOf(final Class<?> clazz, final long lambda) { + return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler(lambda)); + } + + @Override + public native Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable; + +} diff --git a/sca-cpp/trunk/modules/java/test/Adder.java b/sca-cpp/trunk/modules/java/test/Adder.java new file mode 100644 index 0000000000..7236548c41 --- /dev/null +++ b/sca-cpp/trunk/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/trunk/modules/java/test/AdderImpl.java b/sca-cpp/trunk/modules/java/test/AdderImpl.java new file mode 100644 index 0000000000..e607012b78 --- /dev/null +++ b/sca-cpp/trunk/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/trunk/modules/java/test/CalcImpl.java b/sca-cpp/trunk/modules/java/test/CalcImpl.java new file mode 100644 index 0000000000..51753785e4 --- /dev/null +++ b/sca-cpp/trunk/modules/java/test/CalcImpl.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 test; + +public class CalcImpl { + + public Double add(Double x, Double y, Adder adder) { + return adder.add(x, y); + } + + public Double mult(Double x, Double y) { + return x * y; + } + +} |