diff --git a/dubbo-rpc-rmi/pom.xml b/dubbo-rpc-rmi/pom.xml
index 63dd687050..0b060f4951 100644
--- a/dubbo-rpc-rmi/pom.xml
+++ b/dubbo-rpc-rmi/pom.xml
@@ -31,5 +31,10 @@
dubbo-rpc
${project.parent.version}
+
+ org.springframework
+ spring
+ provided
+
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/AbstractRmiInvocationHandler.java b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/AbstractRmiInvocationHandler.java
new file mode 100644
index 0000000000..0832cf99b1
--- /dev/null
+++ b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/AbstractRmiInvocationHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.lang.reflect.InvocationTargetException;
+import java.rmi.RemoteException;
+
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.RpcInvocation;
+import com.alibaba.dubbo.rpc.RpcResult;
+
+/**
+ * AbstratcRmiInvocationHandler
+ *
+ * @author william.liangf
+ */
+public abstract class AbstractRmiInvocationHandler implements RmiInvocationHandler {
+
+ public RpcResult invoke(RpcInvocation invocation) throws RemoteException, NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ return (RpcResult) invoke((Invocation) invocation);
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteObject2RmiInvocationHandler.java b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteObject2RmiInvocationHandler.java
new file mode 100644
index 0000000000..df937dbdda
--- /dev/null
+++ b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteObject2RmiInvocationHandler.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.lang.reflect.InvocationTargetException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import com.alibaba.dubbo.common.bytecode.Wrapper;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Result;
+import com.alibaba.dubbo.rpc.RpcResult;
+
+/**
+ * Generic Remote object adapter to rmi invocation handler.
+ *
+ * @serial
+ * @author qian.lei
+ */
+class RemoteObject2RmiInvocationHandler extends AbstractRmiInvocationHandler
+{
+ private Remote mRemote;
+
+ private Wrapper mWrapper;
+
+ RemoteObject2RmiInvocationHandler(Remote remote, Class> type)
+ {
+ // check remote object and interface.
+ if( type.isInterface() == false )
+ throw new IllegalArgumentException("Service type must be interface. " + type.getName());
+
+ if( type.isInstance(remote) == false )
+ throw new IllegalArgumentException("Remote object must implement interface: " + type.getName());
+
+ mRemote = remote;
+ mWrapper = Wrapper.getWrapper(type);
+ }
+
+ public Result invoke(Invocation inv)
+ throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException
+ {
+ RpcResult result = new RpcResult();
+ try
+ {
+ result.setResult(mWrapper.invokeMethod(mRemote, inv.getMethodName(), inv.getParameterTypes(), inv.getArguments()));
+ }
+ catch(InvocationTargetException e)
+ {
+ Throwable rmiInvocationEx = e.getTargetException();
+ if(null == rmiInvocationEx) throw e;
+
+ if(rmiInvocationEx.getClass().getName().startsWith("java.rmi.")
+ || rmiInvocationEx.getClass().getName().startsWith("javax.rmi.")) {
+ throw new RemoteException("", rmiInvocationEx);
+ }
+ result.setException(rmiInvocationEx);
+ }
+
+ return result;
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiExporter.java b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiExporter.java
new file mode 100644
index 0000000000..80952bb142
--- /dev/null
+++ b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiExporter.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.rmi.Remote;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+
+import com.alibaba.dubbo.common.logger.Logger;
+import com.alibaba.dubbo.common.logger.LoggerFactory;
+import com.alibaba.dubbo.rpc.Invoker;
+import com.alibaba.dubbo.rpc.protocol.AbstractExporter;
+
+/**
+ * Rmi exporter.
+ *
+ * @author qian.lei
+ */
+public class RmiExporter extends AbstractExporter
+{
+ private static final Logger Log = LoggerFactory.getLogger(RmiExporter.class);
+
+ private Remote mRemote;
+
+ private Registry mRmiRegistry;
+
+ RmiExporter(Invoker invoker) {
+ super(invoker);
+ }
+
+ public void unexport()
+ {
+ super.unexport();
+
+ if( mRmiRegistry != null )
+ {
+ try
+ {
+ // unbind.
+ mRmiRegistry.unbind(getInvoker().getUrl().getPath());
+ // unexport.
+ if( mRemote != null )
+ UnicastRemoteObject.unexportObject(mRemote, true);
+ }
+ catch(Exception e)
+ {
+ Log.warn("Unexport rmi object error.", e); //ignore it.
+ }
+ mRemote = null;
+ mRmiRegistry = null;
+ }
+ }
+
+ void setRmiRegistry(Registry reg)
+ {
+ mRmiRegistry = reg;
+ }
+
+ void setRemoteObject(Remote remote)
+ {
+ mRemote = remote;
+ }
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiInvocationHandler.java b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiInvocationHandler.java
new file mode 100644
index 0000000000..709f73b717
--- /dev/null
+++ b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiInvocationHandler.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 1999-2011 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.lang.reflect.InvocationTargetException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Result;
+
+/**
+ * rmi invocation handler.
+ *
+ * @serial Don't change the class name.
+ * @author qianlei
+ */
+public interface RmiInvocationHandler extends Remote {
+
+ /**
+ * invoke.
+ *
+ * @param invocation invocation.
+ * @return result.
+ * @throws RemoteException.
+ * @throws NoSuchMethodException.
+ * @throws IllegalAccessException.
+ * @throws InvocationTargetException.
+ */
+ public Result invoke(Invocation invocation) throws RemoteException, NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException;
+
+}
diff --git a/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiInvoker.java b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiInvoker.java
new file mode 100644
index 0000000000..b89b5b27c6
--- /dev/null
+++ b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiInvoker.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Result;
+import com.alibaba.dubbo.rpc.RpcException;
+import com.alibaba.dubbo.rpc.RpcInvocation;
+import com.alibaba.dubbo.rpc.protocol.AbstractInvoker;
+
+/**
+ * rmi rpc invoker.
+ *
+ * @author qian.lei
+ */
+public class RmiInvoker extends AbstractInvoker {
+
+ private RmiInvocationHandler proxy;
+
+ static boolean isInstance(Object obj, String interfaceClazzName) {
+ for(Class> clazz = obj.getClass(); clazz != null && !clazz.equals(Object.class);
+ clazz = clazz.getSuperclass()) {
+ Class>[] interfaces = clazz.getInterfaces();
+ for(Class> itf : interfaces) {
+ if(itf.getName().equals(interfaceClazzName)) return true;
+ }
+ }
+
+ return false;
+ }
+
+ public RmiInvoker(Class serviceType, URL url)
+ {
+ super(serviceType, url);
+ try
+ {
+ Registry reg = LocateRegistry.getRegistry(url.getHost(), url.getPort());
+ String path = url.getPath();
+ if (path == null || path.length() == 0) {
+ path = serviceType.getName();
+ }
+ Remote rmt = reg.lookup(path);
+
+ if( rmt instanceof RmiInvocationHandler ) {
+ // is the Remote wrap type in Dubbo2
+ proxy = (RmiInvocationHandler)rmt;
+ }
+ else if(isInstance(rmt, "org.springframework.remoting.rmi.RmiInvocationHandler")) {
+ // is the Remote wrap type in spring? (spring rmi is used in Dubbo1)
+ proxy = new SpringHandler2RmiInvocationHandler((org.springframework.remoting.rmi.RmiInvocationHandler)rmt, serviceType);
+ }
+ else
+ proxy = new RemoteObject2RmiInvocationHandler(rmt, serviceType);
+ }
+ catch(RemoteException e)
+ {
+ Throwable cause = e.getCause();
+ boolean isExportedBySpringButNoSpringClass = ClassNotFoundException.class.isInstance(cause)
+ && cause.getMessage().contains("org.springframework.remoting.rmi.RmiInvocationHandler");
+
+ String msg = String.format("Can not create remote object%s. url = %s",
+ isExportedBySpringButNoSpringClass ? "(Rmi object is exported by spring rmi but NO spring class org.springframework.remoting.rmi.RmiInvocationHandler at consumer side)" : "",
+ url);
+ throw new RpcException(msg, e);
+ }
+ catch(NotBoundException e)
+ {
+ throw new RpcException("Rmi service not found. url = " + url, e);
+ }
+ }
+
+ @Override
+ protected Object doInvoke(Invocation invocation) throws Throwable {
+ Result result;
+ try
+ {
+ result = proxy.invoke((RpcInvocation) invocation);
+ }
+ catch(Throwable e) // here is non-biz exception, wrap it.
+ {
+ throw new RpcException(e);
+ }
+ return result.recreate();
+ }
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiProtocol.java b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiProtocol.java
new file mode 100644
index 0000000000..37e01003b3
--- /dev/null
+++ b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiProtocol.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 1999-2011 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.rmi.AlreadyBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RemoteServer;
+import java.rmi.server.ServerNotActiveException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.springframework.remoting.support.RemoteInvocation;
+
+import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.Extension;
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.bytecode.Proxy;
+import com.alibaba.dubbo.common.utils.StringUtils;
+import com.alibaba.dubbo.rpc.Exporter;
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Invoker;
+import com.alibaba.dubbo.rpc.Result;
+import com.alibaba.dubbo.rpc.RpcException;
+import com.alibaba.dubbo.rpc.RpcInvocation;
+import com.alibaba.dubbo.rpc.protocol.AbstractProtocol;
+
+/**
+ * RmiProtocolSupport.
+ *
+ * @author qian.lei
+ */
+@Extension("rmi")
+public class RmiProtocol extends AbstractProtocol {
+
+ public static final int DEFAULT_PORT = 1099;
+
+ private final Map registryMap = new ConcurrentHashMap();
+
+ private final Map> exporterMap = new ConcurrentHashMap>(); // rpcExporter, boolean isSpringCodec, final String host,
+ final int port, final Class> serviceType) {
+ boolean isRemoteType = Remote.class.isAssignableFrom(serviceType);
+ Remote exportedObj;
+ if (isRemoteType) {
+ Proxy proxy = Proxy.getProxy(new Class>[] { serviceType });
+ Object proxyService = proxy.newInstance(new InvocationHandler() {
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ String client = null;
+ try {
+ client = RemoteServer.getClientHost();
+ } catch (ServerNotActiveException e) {
+ // Ignore it.
+ }
+ Invocation inv = new RpcInvocation(method, args);
+ try {
+ return rpcExporter.invoke(inv, client, 0).recreate();
+ } catch (RpcException e) {
+ throw new RemoteException(StringUtils.toString(e));
+ }
+ }
+ });
+ exportedObj = (Remote) proxyService;
+ } else if (isSpringCodec) {
+ try {
+ Class.forName("org.springframework.remoting.rmi.RmiInvocationHandler");
+ } catch (ClassNotFoundException e1) {
+ throw new RpcException(
+ "set codec spring for protocol rmi,"
+ + " but NO spring class org.springframework.remoting.rmi.RmiInvocationHandler at provider side!");
+ }
+ exportedObj = new org.springframework.remoting.rmi.RmiInvocationHandler() {
+
+ public Object invoke(RemoteInvocation invocation) throws RemoteException, NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ String client = null;
+ try {
+ client = RemoteServer.getClientHost();
+ } catch (ServerNotActiveException e) {
+ // Ignore it.
+ }
+
+ Invocation inv = new RpcInvocation(invocation.getMethodName(),
+ invocation.getParameterTypes(),
+ invocation.getArguments());
+ try {
+ return rpcExporter.invoke(inv, client, 0).recreate();
+ } catch (RpcException e) {
+ throw new RemoteException(StringUtils.toString(e));
+ } catch (Throwable t) {
+ throw new InvocationTargetException(t);
+ }
+ }
+
+ public String getTargetInterfaceName() throws RemoteException {
+ return serviceType.getName();
+ }
+ };
+ } else {
+ exportedObj = new AbstractRmiInvocationHandler() {
+
+ public Result invoke(Invocation inv) throws RemoteException, NoSuchMethodException,
+ IllegalAccessException, InvocationTargetException {
+ String client = null;
+ try {
+ client = RemoteServer.getClientHost();
+ } catch (ServerNotActiveException e) {
+ // Ignore it.
+ }
+
+ return rpcExporter.invoke(inv, client, 0);
+ }
+ };
+ }
+ return exportedObj;
+ }
+
+ public Exporter export(Invoker invoker) throws RpcException {
+ Class serviceType = invoker.getInterface();
+ URL url = invoker.getUrl();
+
+ String codec = url.getParameter(Constants.CODEC_KEY, "spring");
+ boolean isSpringCodec;
+ if ("spring".equals(codec)) {
+ isSpringCodec = true;
+ } else if ("dubbo".equals(codec)) {
+ isSpringCodec = false;
+ } else {
+ throw new IllegalArgumentException("Unsupported protocol codec " + codec
+ + " for protocol RMI, Only support \"dubbo\", \"spring\" codec.");
+ }
+
+ final RmiExporter ret = new RmiExporter(invoker);
+ Remote exportedObj = getObjectToExport(ret, isSpringCodec, url.getHost(), url.getPort(), serviceType);
+
+ // export.
+ try {
+ // UnicastRemoteObject.exportObject(exportedObj, 0, new InternalClientSocketFactory(), new
+ // InternalServerSocketFactory());
+ UnicastRemoteObject.exportObject(exportedObj, 0);
+ ret.setRemoteObject(exportedObj);
+ } catch (RemoteException e) {
+ if ("object already exported".equalsIgnoreCase(e.getMessage())) logger.warn("Ignore 'object already exported' exception.",
+ e);
+ else throw new RpcException("Export rmi service error.", e);
+ }
+
+ // register.
+ Registry reg = getOrCreateRegistry(url.getPort());
+ try {
+ // bind service.
+ reg.bind(url.getPath(), exportedObj);
+ ret.setRmiRegistry(reg);
+ } catch (RemoteException e) {
+ throw new RpcException("Bind rmi service [" + url.getPath() + "] error.", e);
+ } catch (AlreadyBoundException e) {
+ throw new RpcException("Bind rmi service error. Service name [" + url.getPath() + "] already bound.", e);
+ }
+
+ exporterMap.put(serviceKey(url), ret);
+ return ret;
+ }
+
+ public Invoker refer(Class serviceType, URL url) throws RpcException {
+ Invoker invoker = new RmiInvoker(serviceType, url);
+ invokers.add(invoker);
+ return invoker ;
+ }
+
+ protected Registry getOrCreateRegistry(int port) {
+ Registry reg = registryMap.get(port);
+ if (reg == null) {
+ try {
+ // reg = LocateRegistry.createRegistry(port, new InternalClientSocketFactory(), new
+ // InternalServerSocketFactory());
+ reg = LocateRegistry.createRegistry(port);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to create rmi registry on port " + port + ", cause: " + e.getMessage(), e);
+ }
+ registryMap.put(port, reg);
+ }
+ return reg;
+ }
+
+ public void destroy() {
+ super.destroy();
+ for (Integer key : new ArrayList(registryMap.keySet())) {
+ Registry registry = registryMap.remove(key);
+ if (registry != null) {
+ try {
+ String[] services = registry.list();
+ if (services != null && services.length > 0) {
+ for (String service : services) {
+ if (logger.isInfoEnabled()) {
+ logger.info("Unbind rmi service: " + service);
+ }
+ registry.unbind(service);
+ }
+ }
+ } catch (Throwable t) {
+ logger.warn(t.getMessage(), t);
+ }
+ }
+ }
+ }
+
+ /**
+ * 自定义的RMIClientSocketFactory类,用于控制Rmi Client端连接的控制,如连接池、监控等。 这个类会序列化传到Rmi Client(Client可能没有这个类),考虑到与Native
+ * Rmi的目前不使用这个类 。
+ *
+ * @author qian.lei
+ */
+ @SuppressWarnings("unused")
+ private static class InternalClientSocketFactory implements RMIClientSocketFactory, Serializable {
+
+ private static final long serialVersionUID = 8412843862275448994L;
+
+ public Socket createSocket(String host, int port) throws IOException {
+ Socket socket = new Socket();
+ socket.connect(new InetSocketAddress(host, port));
+ return socket;
+ }
+ }
+
+ /**
+ * @author qian.lei
+ */
+ @SuppressWarnings("unused")
+ private static class InternalServerSocketFactory implements RMIServerSocketFactory {
+
+ public ServerSocket createServerSocket(int port) throws IOException {
+ return new InternalServerSocket(port);
+ }
+ }
+
+ private static class InternalServerSocket extends ServerSocket {
+
+ public InternalServerSocket(int port) throws IOException{
+ super(port);
+ }
+
+ public Socket accept() throws IOException {
+ Socket socket = super.accept();
+ return socket;
+ }
+ }
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/SpringHandler2RmiInvocationHandler.java b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/SpringHandler2RmiInvocationHandler.java
new file mode 100644
index 0000000000..649086e148
--- /dev/null
+++ b/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/SpringHandler2RmiInvocationHandler.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.lang.reflect.InvocationTargetException;
+import java.rmi.RemoteException;
+
+import org.springframework.remoting.support.RemoteInvocation;
+
+import com.alibaba.dubbo.rpc.Invocation;
+import com.alibaba.dubbo.rpc.Result;
+import com.alibaba.dubbo.rpc.RpcResult;
+
+/**
+ *
+ * @serial
+ * @author ding.lid
+ */
+class SpringHandler2RmiInvocationHandler extends AbstractRmiInvocationHandler {
+
+ private org.springframework.remoting.rmi.RmiInvocationHandler springHandler;
+
+ SpringHandler2RmiInvocationHandler(org.springframework.remoting.rmi.RmiInvocationHandler springHandler, Class> type)
+ {
+ // check remote object and interface.
+ if( type.isInterface() == false )
+ throw new IllegalArgumentException("Service type must be interface. " + type.getName());
+
+ this.springHandler = springHandler;
+ }
+
+ public Result invoke(Invocation inv)
+ throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException
+ {
+ RpcResult result = new RpcResult();
+ try
+ {
+ RemoteInvocation i = new RemoteInvocation();
+ i.setMethodName(inv.getMethodName());
+ i.setParameterTypes(inv.getParameterTypes());
+ i.setArguments(inv.getArguments());
+
+ result.setResult(springHandler.invoke(i));
+ }
+ catch(InvocationTargetException e)
+ {
+ result.setException(e.getTargetException());
+ }
+
+ return result;
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/DemoService.java b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/DemoService.java
new file mode 100644
index 0000000000..ee69bc616f
--- /dev/null
+++ b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/DemoService.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+/**
+ * TestService
+ */
+
+public interface DemoService
+{
+ void sayHello(String name);
+
+ String echo(String text);
+
+ long timestamp();
+
+ String getThreadName();
+
+ int getSize(String[] strs);
+
+ int getSize(Object[] os);
+
+ Object invoke(String service, String method) throws Exception;
+
+ int stringLength(String str);
+
+ Type enumlength(Type... types);
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/DemoServiceImpl.java b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/DemoServiceImpl.java
new file mode 100644
index 0000000000..b0aae31af6
--- /dev/null
+++ b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/DemoServiceImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import com.alibaba.dubbo.rpc.RpcContext;
+
+/**
+ * DemoServiceImpl
+ */
+
+public class DemoServiceImpl implements DemoService
+{
+ public DemoServiceImpl()
+ {
+ super();
+ }
+
+ public void sayHello(String name) {
+ System.out.println("hello "+name);
+ }
+
+ public String echo(String text)
+ {
+ return text;
+ }
+
+ public long timestamp() {
+ return System.currentTimeMillis();
+ }
+
+ public String getThreadName()
+ {
+ return Thread.currentThread().getName();
+ }
+
+ public int getSize(String[] strs)
+ {
+ if( strs == null )
+ return -1;
+ return strs.length;
+ }
+
+ public int getSize(Object[] os)
+ {
+ if( os == null )
+ return -1;
+ return os.length;
+ }
+
+ public Object invoke(String service, String method) throws Exception
+ {
+ System.out.println("RpcContext.getContext().getRemoteHost()="+RpcContext.getContext().getRemoteHost());
+ return service + ":" + method;
+ }
+
+ public Type enumlength(Type... types)
+ {
+ if( types.length == 0 )
+ return Type.Lower;
+ return types[0];
+ }
+
+ public int stringLength(String str)
+ {
+ return str.length();
+ }
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/ProtocolsTest.java b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/ProtocolsTest.java
new file mode 100644
index 0000000000..9f71af82b4
--- /dev/null
+++ b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/ProtocolsTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+
+import static junit.framework.Assert.assertEquals;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.alibaba.dubbo.common.ExtensionLoader;
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.rpc.Exporter;
+import com.alibaba.dubbo.rpc.Protocol;
+import com.alibaba.dubbo.rpc.ProxyFactory;
+import com.alibaba.dubbo.rpc.service.EchoService;
+
+/**
+ * ProxiesTest
+ */
+
+public class ProtocolsTest
+{
+ private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+ private ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+
+ @Test
+ public void testRmiProtocol() throws Exception
+ {
+ {
+ DemoService service = new DemoServiceImpl();
+ Exporter> rpcExporter = protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("rmi://127.0.0.1:9001/TestService")));
+
+ service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("rmi://127.0.0.1:9001/TestService")));
+ assertEquals(service.getSize(null), -1);
+ assertEquals(service.getSize(new String[]{"", "", ""}), 3);
+ Object result = service.invoke("rmi://127.0.0.1:9001/TestService", "invoke");
+ assertEquals("rmi://127.0.0.1:9001/TestService:invoke", result);
+
+ rpcExporter.unexport();
+ }
+
+ {
+ RemoteService remoteService = new RemoteServiceImpl();
+ Exporter> rpcExporter = protocol.export(proxy.getInvoker(remoteService, RemoteService.class, URL.valueOf("rmi://127.0.0.1:9001/remoteService")));
+
+ remoteService = proxy.getProxy(protocol.refer(RemoteService.class, URL.valueOf("rmi://127.0.0.1:9001/remoteService")));
+ remoteService.getThreadName();
+ for(int i=0;i<100;i++) {
+ String say = remoteService.sayHello("abcd");
+ assertEquals("hello abcd@com.alibaba.dubbo.rpc.proxy.RemoteServiceImpl", say);
+ }
+ rpcExporter.unexport();
+ }
+ }
+
+ // FIXME RMI协议目前的实现不支持转型成 EchoService
+ @Ignore
+ @Test
+ public void testRmiProtocol_echoService() throws Exception
+ {
+ DemoService service = new DemoServiceImpl();
+ Exporter> rpcExporter = protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("rmi://127.0.0.1:9002/TestService")));
+
+ // cast to EchoService
+ EchoService echo = proxy.getProxy(protocol.refer(EchoService.class, URL.valueOf("rmi://127.0.0.1:9002/TestService")));
+ assertEquals(echo.$echo("test"), "test");
+ assertEquals(echo.$echo("abcdefg"), "abcdefg");
+ assertEquals(echo.$echo(1234), 1234);
+
+ rpcExporter.unexport();
+
+ RemoteService remoteService = new RemoteServiceImpl();
+ rpcExporter = protocol.export(proxy.getInvoker(remoteService, RemoteService.class, URL.valueOf("rmi://127.0.0.1:9002/remoteService")));
+
+ // cast to EchoService
+ echo = proxy.getProxy(protocol.refer(EchoService.class, URL.valueOf("rmi://127.0.0.1:9002/remoteService")));
+ assertEquals(echo.$echo("test"), "test");
+ assertEquals(echo.$echo("abcdefg"), "abcdefg");
+ assertEquals(echo.$echo(1234), 1234);
+
+ rpcExporter.unexport();
+ }
+
+ /*@Test
+ public void testRpcInvokerGroup() throws Exception
+ {
+ DemoService service = new DemoServiceImpl();
+ RpcUtils.export("demo://127.0.0.1:9030/com.alibaba.dubbo.rpc.TestService",DemoService.class,service);
+ RpcUtils.export("dubbo://127.0.0.1:9031/TestService",DemoService.class,service);
+ RpcUtils.export("rmi://127.0.0.1:9032/com.alibaba.dubbo.rpc.TestService",DemoService.class,service);
+ RpcUtils.export("rmi://127.0.0.1:9033/com.alibaba.dubbo.rpc.TestService",DemoService.class,service);
+
+ service = RpcUtils.createProxy(DemoService.class,
+ new String[]{
+ "demo://127.0.0.1:9030/com.alibaba.dubbo.rpc.TestService?weight=20",
+ "dubbo://127.0.0.1:9031/TestService?weight=20",
+ "rmi://127.0.0.1:9032/com.alibaba.dubbo.rpc.TestService",
+ });
+ assertEquals(service.getSize(null), -1);
+ assertEquals(service.getSize(new String[]{"","",""}), 3);
+
+ // cast to EchoService
+ EchoService echo = RpcUtils.createProxy(EchoService.class,
+ new String[]{
+ "demo://127.0.0.1:9030/com.alibaba.dubbo.rpc.TestService?weight=20",
+ "dubbo://127.0.0.1:9031/TestService?weight=20",
+ "rmi://127.0.0.1:9032/com.alibaba.dubbo.rpc.TestService",
+ });
+ assertEquals(echo.$echo("test"), "test");
+ assertEquals(echo.$echo("abcdefg"), "abcdefg");
+ assertEquals(echo.$echo(1234), 1234);
+ }*/
+
+ /*public void testForkInvoke() throws Exception
+ {
+ DemoService service = new DemoServiceImpl();
+ protocol.export(proxy.createInvoker("dubbo://127.0.0.1:9040/TestService", DemoService.class, service);
+ protocol.export(proxy.createInvoker("dubbo://127.0.0.1:9041/TestService", DemoService.class, service);
+ protocol.export(proxy.createInvoker("rmi://127.0.0.1:9042/com.alibaba.dubbo.rpc.TestService", DemoService.class, service);
+ protocol.export(proxy.createInvoker("rmi://127.0.0.1:9043/com.alibaba.dubbo.rpc.TestService", DemoService.class, service);
+
+ RpcInvokerGroup group = Proxies.createInvoker(DemoService.class, new String[]{
+ "dubbo://127.0.0.1:9040/TestService",
+ "dubbo://127.0.0.1:9041/TestService",
+ "rmi://127.0.0.1:9042/com.alibaba.dubbo.rpc.TestService",
+ "rmi://127.0.0.1:9043/com.alibaba.dubbo.rpc.TestService",
+ });
+ group.getMethodSettings("echo").setFork(true);
+ group.getMethodSettings("echo").setForkInvokeCallback(new ForkInvokeCallback(){
+ public Object merge(RpcInvocation invocation, RpcResult[] results) throws Throwable
+ {
+ System.out.println("merge result begin:");
+ for( RpcResult result : results )
+ {
+ if( result.hasException() )
+ System.out.println("exception:"+result.getException().getMessage());
+ else
+ System.out.println("result:"+result.getResult());
+ }
+ System.out.println("merge result end:");
+ return "aaaa";
+ }
+ });
+
+ service = proxy.createProxy(protocol.refer(DemoService.class, group);
+ service.echo("test");
+
+ // cast to EchoService
+ EchoService echo = proxy.createProxy(protocol.refer(EchoService.class, group);
+ assertEquals(echo.$echo("test"), "test");
+ assertEquals(echo.$echo("abcdefg"), "abcdefg");
+ assertEquals(echo.$echo(1234), 1234);
+ }*/
+
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteService.java b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteService.java
new file mode 100644
index 0000000000..24169b1e3c
--- /dev/null
+++ b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteService.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface RemoteService extends Remote
+{
+ String sayHello(String name) throws RemoteException;
+
+ String getThreadName() throws RemoteException;
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteServiceImpl.java b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteServiceImpl.java
new file mode 100644
index 0000000000..08358a4425
--- /dev/null
+++ b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/RemoteServiceImpl.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+import java.rmi.RemoteException;
+
+import com.alibaba.dubbo.rpc.RpcContext;
+
+public class RemoteServiceImpl implements RemoteService
+{
+ public String getThreadName() throws RemoteException
+ {
+ System.out.println("RpcContext.getContext().getRemoteHost()="+RpcContext.getContext().getRemoteHost());
+ return Thread.currentThread().getName();
+ }
+
+ public String sayHello(String name) throws RemoteException
+ {
+ return "hello " + name + "@" + RemoteServiceImpl.class.getName();
+ }
+}
\ No newline at end of file
diff --git a/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/Type.java b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/Type.java
new file mode 100644
index 0000000000..b38da0fdb7
--- /dev/null
+++ b/dubbo-rpc-rmi/src/test/java/com/alibaba/dubbo/rpc/protocol/rmi/Type.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 1999-2101 Alibaba Group.
+ *
+ * Licensed 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 com.alibaba.dubbo.rpc.protocol.rmi;
+
+public enum Type
+{
+ High, Normal, Lower
+}
\ No newline at end of file