package me.test.spring.rmi.pojo;
import java.io.Serializable;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.rmi.RmiBasedExporter;
import org.springframework.remoting.rmi.RmiInvocationHandler;
import org.springframework.remoting.support.DefaultRemoteInvocationFactory;
import org.springframework.remoting.support.RemoteInvocation;
import org.springframework.remoting.support.RemoteInvocationFactory;
public class RMIUtil {
private static Map<Object, Remote> staticRefMap = new HashMap<Object, Remote>();
@SuppressWarnings("unchecked")
public static <E> E registerAndExport(Object target, Class<E> clazz) {
AnonymousRmiServiceExporter a = new AnonymousRmiServiceExporter();
a.setService(target);
a.setServiceInterface(clazz);
Remote remoteProxy = a.getObjectToExport();
staticRefMap.put(target, remoteProxy);
RmiInvocationHandler stub = null;
try {
stub = (RmiInvocationHandler) UnicastRemoteObject.exportObject(
remoteProxy, 0);
System.out.println(stub);
} catch (RemoteException e1) {
throw new RuntimeException(e1);
}
MethodInterceptor mi = new TargetInterfaceWrapper(stub);
ProxyFactory pf = new ProxyFactory(clazz, mi);
pf.addInterface(Serializable.class);
return (E) pf.getProxy();
}
public static void unregister(Object target) {
Remote remoteProxy = staticRefMap.remove(target);
try {
UnicastRemoteObject.unexportObject(remoteProxy, true);
} catch (NoSuchObjectException e) {
// do nothing.
}
}
public static class AnonymousRmiServiceExporter extends RmiBasedExporter {
public Remote getObjectToExport() {
return super.getObjectToExport();
}
}
public static class TargetInterfaceWrapper implements MethodInterceptor,
Serializable {
private static final long serialVersionUID = 1L;
private static RemoteInvocationFactory remoteInvocationFactory = new DefaultRemoteInvocationFactory();
private RmiInvocationHandler stub = null;
public TargetInterfaceWrapper(RmiInvocationHandler stub) {
this.stub = stub;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object invoke(MethodInvocation invocation) throws Throwable {
RemoteInvocation remoteInvocation = remoteInvocationFactory
.createRemoteInvocation(invocation);
try {
return stub.invoke(remoteInvocation);
} catch (Exception e) {
Class<?>[] declaredExceptions = invocation.getMethod()
.getExceptionTypes();
for (Class exceptionClass : declaredExceptions) {
if (exceptionClass.isAssignableFrom(e.getClass())) {
throw e;
}
}
throw new RemoteAccessException(e.getMessage(), e);
}
}
}
}