summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src')
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java144
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingProviderFactory.java60
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java81
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java169
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RemoteInterfaceGenerator.java102
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.BindingProviderFactory20
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java60
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java42
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java50
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java31
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java31
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java80
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/HelloWorldImpl.componentType23
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType28
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.composite41
15 files changed, 962 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java
new file mode 100644
index 0000000000..1bbcb49840
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java
@@ -0,0 +1,144 @@
+/*
+ * 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.sca.binding.rmi.provider;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.rmi.ConnectException;
+import java.rmi.Remote;
+import java.rmi.UnexpectedException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.tuscany.sca.host.rmi.RMIHost;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+
+/**
+ * Invoker for RMI References.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RMIBindingInvoker implements Invoker {
+
+ private RMIHost rmiHost;
+ private String uri;
+ private Method remoteMethod;
+ private Remote proxy;
+
+ public RMIBindingInvoker(RMIHost rmiHost, String uri, Method remoteMethod) {
+ this.rmiHost = rmiHost;
+ this.remoteMethod = remoteMethod;
+ this.uri = uri;
+ }
+
+ public Message invoke(Message msg) {
+ try {
+
+ Object[] args = msg.getBody();
+ Object resp = invokeTarget(args);
+ msg.setBody(resp);
+
+ } catch (InvocationTargetException e) {
+ msg.setFaultBody(e.getCause());
+ } catch (Throwable e) {
+ msg.setFaultBody(e);
+ }
+
+ return msg;
+ }
+
+ public Object invokeTarget(final Object payload) throws InvocationTargetException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException {
+
+ if (proxy == null) {
+ initProxy();
+ }
+
+ Object invocationResult = null;
+ InvocationTargetException rethrow = null;
+ try {
+ invocationResult = doInvokeTarget(payload);
+ } catch (InvocationTargetException e) {
+ // rethrow this exception from finally block unless it can be
+ // handled
+ rethrow = e;
+ // try to diagnose the error condition: proxy may be out-of-date
+ // (cf. TUSCANY-3850)
+ Throwable cause = e.getCause();
+ if (cause instanceof UndeclaredThrowableException) {
+ cause = cause.getCause();
+ if (cause instanceof UnexpectedException) {
+ cause = cause.getCause();
+ if (cause instanceof ConnectException) {
+ // retry invoke with a fresh proxy
+ rethrow = null;
+ proxy = rmiHost.findService(uri);
+ invocationResult = doInvokeTarget(payload);
+ }
+ }
+ }
+ } finally {
+ if (rethrow != null) {
+ throw rethrow;
+ }
+ }
+
+ return invocationResult;
+ }
+
+ private synchronized void initProxy() {
+ if (proxy == null) {
+ final Class<?> remote = remoteMethod.getDeclaringClass();
+ final ClassLoader stubClassLoader = remote.getClassLoader();
+ // The generated remote interface is not available for the service
+ // lookup
+ final ClassLoader tccl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(stubClassLoader);
+ return tccl;
+ }
+ });
+ try {
+ // The proxy cannot be cached as the remote services can be rebound
+ proxy = rmiHost.findService(uri);
+ } finally {
+ AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ ClassLoader current = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(tccl);
+ return current;
+ }
+ });
+ }
+ }
+ }
+
+ private Object doInvokeTarget(final Object payload) throws InvocationTargetException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException {
+
+ remoteMethod = proxy.getClass().getMethod(remoteMethod.getName(), remoteMethod.getParameterTypes());
+
+ if (payload != null && !payload.getClass().isArray()) {
+ return remoteMethod.invoke(proxy, payload);
+ } else {
+ return remoteMethod.invoke(proxy, (Object[])payload);
+ }
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingProviderFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingProviderFactory.java
new file mode 100644
index 0000000000..3b903cc846
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingProviderFactory.java
@@ -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.
+ */
+
+package org.apache.tuscany.sca.binding.rmi.provider;
+
+import org.apache.tuscany.sca.binding.rmi.RMIBinding;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.host.rmi.ExtensibleRMIHost;
+import org.apache.tuscany.sca.host.rmi.RMIHost;
+import org.apache.tuscany.sca.host.rmi.RMIHostExtensionPoint;
+import org.apache.tuscany.sca.provider.BindingProviderFactory;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
+
+/**
+ * RMI Binding Provider Factory
+ *
+ * @version $Rev$ $Date$
+ */
+public class RMIBindingProviderFactory implements BindingProviderFactory<RMIBinding> {
+
+ private RMIHost rmiHost;
+
+ public RMIBindingProviderFactory(ExtensionPointRegistry extensionPoints) {
+ RMIHostExtensionPoint rmiHosts = extensionPoints.getExtensionPoint(RMIHostExtensionPoint.class);
+ this.rmiHost = new ExtensibleRMIHost(rmiHosts);
+ }
+
+ public ReferenceBindingProvider createReferenceBindingProvider(RuntimeEndpointReference endpointReference) {
+
+ return new RMIReferenceBindingProvider(endpointReference, rmiHost);
+ }
+
+ public ServiceBindingProvider createServiceBindingProvider(RuntimeEndpoint endpoint) {
+ return new RMIServiceBindingProvider(endpoint, rmiHost);
+ }
+
+ public Class<RMIBinding> getModelType() {
+ return RMIBinding.class;
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java
new file mode 100644
index 0000000000..52ce74f3d5
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java
@@ -0,0 +1,81 @@
+/*
+ * 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.sca.binding.rmi.provider;
+
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.assembly.EndpointReference;
+import org.apache.tuscany.sca.binding.rmi.RMIBinding;
+import org.apache.tuscany.sca.host.rmi.RMIHost;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+
+/**
+ * Implementation of the RMI Binding Provider for References
+ *
+ * @version $Rev$ $Date$
+ */
+public class RMIReferenceBindingProvider implements ReferenceBindingProvider {
+
+ private RuntimeComponentReference reference;
+ private EndpointReference endpointReference;
+ private RMIBinding binding;
+ private RMIHost rmiHost;
+
+ public RMIReferenceBindingProvider(EndpointReference endpointReference,
+ RMIHost rmiHost) {
+ this.endpointReference = endpointReference;
+ this.reference = (RuntimeComponentReference)endpointReference.getReference();
+ this.binding = (RMIBinding)endpointReference.getBinding();
+ this.rmiHost = rmiHost;
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ return reference.getInterfaceContract();
+ }
+
+ public Invoker createInvoker(Operation operation) {
+ Class<?> iface = ((JavaInterface)reference.getInterfaceContract().getInterface()).getJavaClass();
+ Method remoteMethod;
+ try {
+ remoteMethod = JavaInterfaceUtil.findMethod(iface, operation);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ return new RMIBindingInvoker(rmiHost, endpointReference.getDeployedURI(), remoteMethod);
+ }
+
+ public void start() {
+ }
+
+ public void stop() {
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return false;
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java
new file mode 100644
index 0000000000..e555485085
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java
@@ -0,0 +1,169 @@
+/*
+ * 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.sca.binding.rmi.provider;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.server.UnicastRemoteObject;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+
+import org.apache.tuscany.sca.binding.rmi.RMIBinding;
+import org.apache.tuscany.sca.common.java.classloader.ClassLoaderDelegate;
+import org.apache.tuscany.sca.host.rmi.RMIHost;
+import org.apache.tuscany.sca.host.rmi.RMIHostException;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
+import org.oasisopen.sca.ServiceRuntimeException;
+
+/**
+ * Implementation of a Service for the RMIBinding.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RMIServiceBindingProvider implements ServiceBindingProvider {
+
+ private RuntimeComponent component;
+ private RuntimeComponentService service;
+ private RMIBinding binding;
+ private RMIHost rmiHost;
+ private RuntimeEndpoint endpoint;
+ private Remote rmiProxy;
+
+ public RMIServiceBindingProvider(RuntimeEndpoint endpoint, RMIHost rmiHost) {
+ this.endpoint = endpoint;
+ this.component = (RuntimeComponent)endpoint.getComponent();
+ this.service = (RuntimeComponentService)endpoint.getService();
+ this.binding = (RMIBinding)endpoint.getBinding();
+ this.rmiHost = rmiHost;
+ }
+
+ public void start() {
+
+ Interface serviceInterface = service.getInterfaceContract().getInterface();
+
+ rmiProxy = createRmiService(serviceInterface);
+
+ try {
+
+ String uri = rmiHost.registerService(binding.getURI(), rmiProxy);
+ // Update the binding with the physical URI
+ binding.setURI(uri);
+ endpoint.setDeployedURI(uri);
+
+ } catch (RMIHostException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public void stop() {
+ rmiHost.unregisterService(binding.getURI());
+ try {
+ UnicastRemoteObject.unexportObject(rmiProxy, false);
+ } catch (NoSuchObjectException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ private int getPort(String port) {
+ int portNumber = RMIHost.RMI_DEFAULT_PORT;
+ if (port != null && port.length() > 0) {
+ portNumber = Integer.decode(port);
+ }
+ return portNumber;
+ }
+
+ private Remote createRmiService(final Interface serviceInterface) {
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(UnicastRemoteObject.class);
+ enhancer.setCallback(new MethodInterceptor() {
+ public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
+ try {
+ return invokeTarget(JavaInterfaceUtil.findOperation(method, serviceInterface.getOperations()), args);
+ } catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ for (Class<?> declaredType : method.getExceptionTypes()) {
+ if (declaredType.isInstance(cause)) {
+ throw e;
+ }
+ }
+
+ if (cause.getCause() != null) {
+ // TUSCANY-2545: don't inlcude nested cause object
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ public Object run() throws Exception {
+ Field field = Throwable.class.getDeclaredField("cause");
+ field.setAccessible(true);
+ field.set(cause, null);
+ field.setAccessible(false);
+ return null;
+ }
+ });
+ }
+
+ throw cause;
+ }
+ }
+ });
+ Class<?> targetJavaInterface = getTargetJavaClass(serviceInterface);
+ targetJavaInterface = RemoteInterfaceGenerator.generate(targetJavaInterface);
+ /*
+ * In OSGi, the classloader for the interface cannot access the classes for the CGLIB
+ */
+ enhancer.setClassLoader(new ClassLoaderDelegate(targetJavaInterface.getClassLoader(), getClass().getClassLoader()));
+ enhancer.setInterfaces(new Class[] {targetJavaInterface});
+ return (Remote)enhancer.create();
+ }
+
+ private Object invokeTarget(Operation op, Object[] args) throws InvocationTargetException {
+ return endpoint.invoke(op, args);
+ }
+
+ private Class<?> getTargetJavaClass(Interface targetInterface) {
+ // TODO: right now assume that the target is always a Java
+ // Implementation. Need to figure out
+ // how to generate Java Interface in cases where the target is not a
+ // Java Implementation
+ return ((JavaInterface)targetInterface).getJavaClass();
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ return service.getInterfaceContract();
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return false;
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RemoteInterfaceGenerator.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RemoteInterfaceGenerator.java
new file mode 100644
index 0000000000..b351bfacc7
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RemoteInterfaceGenerator.java
@@ -0,0 +1,102 @@
+/*
+ * 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.sca.binding.rmi.provider;
+
+import java.lang.reflect.Method;
+import java.rmi.Remote;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import net.sf.cglib.core.Constants;
+
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Type;
+
+/**
+ *
+ */
+public class RemoteInterfaceGenerator {
+ private final static Map<Class<?>, Class<? extends Remote>> remoteInterfaces =
+ Collections.synchronizedMap(new WeakHashMap<Class<?>, Class<? extends Remote>>());
+
+ static class RemoteInterfaceClassLoader extends ClassLoader {
+ public RemoteInterfaceClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ public Class<?> defineClass(String name, byte[] byteArray) {
+ return defineClass(name, byteArray, 0, byteArray.length);
+ }
+ }
+
+ /**
+ * if the interface of the component whose serviceBindings must be exposed as RMI Service, does not
+ * implement java.rmi.Remote, then generate such an interface. This method will stop with just
+ * generating the bytecode. Defining the class from the byte code must be the responsibility of the
+ * caller of this method, since it requires a ClassLoader to be created to define and load this interface.
+ */
+ private static byte[] generateRemoteInterface(Class<?> serviceInterface) {
+ String interfazeName = serviceInterface.getName();
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+
+ cw.visit(Constants.V1_5, Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT + Constants.ACC_INTERFACE, interfazeName
+ .replace('.', '/'), null, "java/lang/Object", new String[] {"java/rmi/Remote"});
+
+ StringBuffer argsAndReturn = null;
+ Method[] methods = serviceInterface.getMethods();
+ for (Method method : methods) {
+ argsAndReturn = new StringBuffer("(");
+ Class<?>[] paramTypes = method.getParameterTypes();
+ Class<?> returnType = method.getReturnType();
+
+ for (Class<?> paramType : paramTypes) {
+ argsAndReturn.append(Type.getType(paramType));
+ }
+ argsAndReturn.append(")");
+ argsAndReturn.append(Type.getType(returnType));
+
+ cw.visitMethod(Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT,
+ method.getName(),
+ argsAndReturn.toString(),
+ null,
+ new String[] {"java/rmi/RemoteException"});
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ public static Class<? extends Remote> generate(Class<?> javaInterface) {
+ if (!Remote.class.isAssignableFrom(javaInterface)) {
+ Class<? extends Remote> remote = remoteInterfaces.get(javaInterface);
+ if (remote == null) {
+ RemoteInterfaceClassLoader classloader = new RemoteInterfaceClassLoader(javaInterface.getClassLoader());
+ final byte[] byteCode = generateRemoteInterface(javaInterface);
+ javaInterface = classloader.defineClass(javaInterface.getName(), byteCode);
+ remote = (Class<? extends Remote>)javaInterface;
+ remoteInterfaces.put(javaInterface, remote);
+ }
+ return remote;
+ } else {
+ return (Class<? extends Remote>)javaInterface;
+ }
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.BindingProviderFactory b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.BindingProviderFactory
new file mode 100644
index 0000000000..679543e0f2
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.BindingProviderFactory
@@ -0,0 +1,20 @@
+# 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.
+
+# Implementation class for the binding extension
+org.apache.tuscany.sca.binding.rmi.provider.RMIBindingProviderFactory;model=org.apache.tuscany.sca.binding.rmi.RMIBinding
+
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java
new file mode 100644
index 0000000000..cbc860ecc6
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java
@@ -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.
+ */
+
+package helloworld;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class HelloException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2570611055132507470L;
+
+ /**
+ *
+ */
+ public HelloException() {
+ }
+
+ /**
+ * @param message
+ */
+ public HelloException(String message) {
+ super(message);
+ }
+
+ /**
+ * @param cause
+ */
+ public HelloException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public HelloException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java
new file mode 100644
index 0000000000..cd7a0fd625
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java
@@ -0,0 +1,42 @@
+/*
+ * 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 helloworld;
+
+import org.oasisopen.sca.annotation.Service;
+
+
+/**
+ * This class implements the HelloWorld service.
+ *
+ * @version $Rev$ $Date$
+ */
+@Service(HelloWorldService.class)
+public class HelloWorldImpl implements HelloWorldService {
+
+ public String sayHello(String name) {
+ return "Hello from the RMI Service to - " + name;
+ }
+
+ public String sayHi(String name, String greeter) throws HelloException {
+ if (name == null || greeter == null) {
+ throw new HelloException("Invalid name or greeter: name=" + name + " greeter=" + greeter);
+ }
+ return "Hi from " + greeter + " in RMI Service to - " + name;
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java
new file mode 100644
index 0000000000..89ea795529
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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 helloworld;
+
+import org.oasisopen.sca.annotation.Reference;
+import org.oasisopen.sca.annotation.Service;
+
+/**
+ * This class implements the HelloWorld service.
+ *
+ * @version $Rev$ $Date$
+ */
+@Service(HelloWorldRmiService.class)
+public class HelloWorldRmiImpl implements HelloWorldRmiService {
+ private HelloWorldService extService;
+
+ public HelloWorldService getExtService() {
+ return extService;
+ }
+
+ @Reference
+ public void setExtService(HelloWorldService extService) {
+ this.extService = extService;
+ }
+
+ public String sayRmiHello(String name) {
+ return extService.sayHello(name) + " thro the RMI Reference";
+ }
+
+ public String sayRmiHi(String name, String greeter) throws HelloException {
+ return extService.sayHi(name, greeter) + " thro the RMI Reference";
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java
new file mode 100644
index 0000000000..461c176e1e
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java
@@ -0,0 +1,31 @@
+/*
+ * 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 helloworld;
+
+/**
+ * This is the business interface of the HelloWorld greetings service.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface HelloWorldRmiService {
+
+ String sayRmiHello(String name);
+ String sayRmiHi(String name, String greeter) throws HelloException;
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java
new file mode 100644
index 0000000000..3b705d2c97
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java
@@ -0,0 +1,31 @@
+/*
+ * 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 helloworld;
+
+/**
+ * This is the business interface of the HelloWorld greetings service.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface HelloWorldService {
+
+ String sayHello(String name);
+ String sayHi(String name, String greeter) throws HelloException;
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java
new file mode 100644
index 0000000000..c3cd710f1d
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java
@@ -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.
+ */
+package org.apache.tuscany.sca.binding.rmi;
+
+import helloworld.HelloException;
+import helloworld.HelloWorldRmiService;
+import junit.framework.Assert;
+
+import org.apache.tuscany.sca.node.Contribution;
+import org.apache.tuscany.sca.node.ContributionLocationHelper;
+import org.apache.tuscany.sca.node.Node;
+import org.apache.tuscany.sca.node.NodeFactory;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests for the RMIBinding.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BindingTestCase {
+ private static HelloWorldRmiService helloWorldRmiService;
+ private static Node node;
+
+ @Test
+ public void testRmiService() {
+ String msg = helloWorldRmiService.sayRmiHello("Tuscany World!");
+ System.out.println(msg);
+ Assert.assertEquals("Hello from the RMI Service to - Tuscany World! thro the RMI Reference", msg);
+
+ try {
+ msg = helloWorldRmiService.sayRmiHi("Tuscany World!", "Apache World");
+ System.out.println(msg);
+ Assert.assertEquals("Hi from Apache World in RMI Service to - Tuscany World! thro the RMI Reference", msg);
+ } catch (HelloException e) {
+ Assert.fail(e.getMessage());
+ }
+ try {
+ msg = helloWorldRmiService.sayRmiHi(null, "Apache World");
+ Assert.fail("HelloException should have been thrown");
+ } catch (HelloException e) {
+ System.out.println("Expected exception :" + e.getClass().getName());
+ }
+ }
+
+ @BeforeClass
+ public static void init() throws Exception {
+ try {
+ String contribution = ContributionLocationHelper.getContributionLocation(BindingTestCase.class);
+ node = NodeFactory.newInstance().createNode("RMIBindingTest.composite", new Contribution("test", contribution));
+ node.start();
+ helloWorldRmiService = node.getService(HelloWorldRmiService.class, "HelloWorldRmiServiceComponent");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ node.stop();
+ }
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/HelloWorldImpl.componentType b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/HelloWorldImpl.componentType
new file mode 100644
index 0000000000..59e7606bbb
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/HelloWorldImpl.componentType
@@ -0,0 +1,23 @@
+<!--
+ * 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.
+-->
+<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <service name="HelloWorldService">
+ <interface.java interface="helloworld.HelloWorldService"/>
+ </service>
+</componentType>
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType
new file mode 100644
index 0000000000..819a00f978
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType
@@ -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.
+-->
+<componentType xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+ <service name="HelloWorldRmiService">
+ <interface.java interface="helloworld.HelloWorldRmiService"/>
+ </service>
+
+ <reference name="extService">
+ <interface.java interface="helloworld.HelloWorldService"/>
+ </reference>
+</componentType>
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.composite b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.composite
new file mode 100644
index 0000000000..9d526b7f11
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.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"
+ xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://tuscany.apache.org/xmlns/sca/1.1"
+ name="HelloWorldRmiComposite">
+
+ <component name="HelloWorldServiceComponent">
+ <implementation.java class="helloworld.HelloWorldImpl"/>
+ <service name="HelloWorldService" >
+ <interface.java interface="helloworld.HelloWorldService"/>
+ <tuscany:binding.rmi uri="rmi://localhost:8099/HelloWorldRemoteService"/>
+ </service>
+ </component>
+
+ <component name="HelloWorldRmiServiceComponent">
+ <implementation.java class="helloworld.HelloWorldRmiImpl"/>
+ <reference name="extService">
+ <interface.java interface="helloworld.HelloWorldService"/>
+ <tuscany:binding.rmi uri="rmi://localhost:8099/HelloWorldRemoteService" />
+ </reference>
+ </component>
+
+</composite>