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