|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package sun.rmi.server; |
|
|
|
import java.io.ByteArrayOutputStream; |
|
import java.io.IOException; |
|
import java.io.DataOutputStream; |
|
import java.lang.reflect.Constructor; |
|
import java.lang.reflect.InvocationHandler; |
|
import java.lang.reflect.InvocationTargetException; |
|
import java.lang.reflect.Proxy; |
|
import java.lang.reflect.Method; |
|
import java.rmi.Remote; |
|
import java.rmi.RemoteException; |
|
import java.rmi.StubNotFoundException; |
|
import java.rmi.registry.Registry; |
|
import java.rmi.server.LogStream; |
|
import java.rmi.server.ObjID; |
|
import java.rmi.server.RMIClientSocketFactory; |
|
import java.rmi.server.RemoteObjectInvocationHandler; |
|
import java.rmi.server.RemoteRef; |
|
import java.rmi.server.RemoteStub; |
|
import java.rmi.server.Skeleton; |
|
import java.rmi.server.SkeletonNotFoundException; |
|
import java.security.AccessController; |
|
import java.security.MessageDigest; |
|
import java.security.DigestOutputStream; |
|
import java.security.NoSuchAlgorithmException; |
|
import java.security.PrivilegedAction; |
|
import java.util.ArrayList; |
|
import java.util.Collections; |
|
import java.util.Map; |
|
import java.util.WeakHashMap; |
|
import sun.rmi.registry.RegistryImpl; |
|
import sun.rmi.runtime.Log; |
|
import sun.rmi.transport.LiveRef; |
|
import sun.rmi.transport.tcp.TCPEndpoint; |
|
import sun.security.action.GetBooleanAction; |
|
import sun.security.action.GetPropertyAction; |
|
|
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("deprecation") |
|
public final class Util { |
|
|
|
|
|
static final int logLevel = LogStream.parseLevel( |
|
AccessController.doPrivileged( |
|
new GetPropertyAction("sun.rmi.server.logLevel"))); |
|
|
|
|
|
public static final Log serverRefLog = |
|
Log.getLog("sun.rmi.server.ref", "transport", Util.logLevel); |
|
|
|
|
|
private static final boolean ignoreStubClasses = |
|
AccessController.doPrivileged( |
|
new GetBooleanAction("java.rmi.server.ignoreStubClasses")). |
|
booleanValue(); |
|
|
|
|
|
private static final Map<Class<?>, Void> withoutStubs = |
|
Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>(11)); |
|
|
|
|
|
private static final Class<?>[] stubConsParamTypes = { RemoteRef.class }; |
|
|
|
private Util() { |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public static Remote createProxy(Class<?> implClass, |
|
RemoteRef clientRef, |
|
boolean forceStubUse) |
|
throws StubNotFoundException |
|
{ |
|
Class<?> remoteClass; |
|
|
|
try { |
|
remoteClass = getRemoteClass(implClass); |
|
} catch (ClassNotFoundException ex ) { |
|
throw new StubNotFoundException( |
|
"object does not implement a remote interface: " + |
|
implClass.getName()); |
|
} |
|
|
|
if (forceStubUse || |
|
!(ignoreStubClasses || !stubClassExists(remoteClass))) |
|
{ |
|
return createStub(remoteClass, clientRef); |
|
} |
|
|
|
final ClassLoader loader = implClass.getClassLoader(); |
|
final Class<?>[] interfaces = getRemoteInterfaces(implClass); |
|
final InvocationHandler handler = |
|
new RemoteObjectInvocationHandler(clientRef); |
|
|
|
/* REMIND: private remote interfaces? */ |
|
|
|
try { |
|
return AccessController.doPrivileged(new PrivilegedAction<Remote>() { |
|
public Remote run() { |
|
return (Remote) Proxy.newProxyInstance(loader, |
|
interfaces, |
|
handler); |
|
}}); |
|
} catch (IllegalArgumentException e) { |
|
throw new StubNotFoundException("unable to create proxy", e); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static boolean stubClassExists(Class<?> remoteClass) { |
|
if (!withoutStubs.containsKey(remoteClass)) { |
|
try { |
|
Class.forName(remoteClass.getName() + "_Stub", |
|
false, |
|
remoteClass.getClassLoader()); |
|
return true; |
|
|
|
} catch (ClassNotFoundException cnfe) { |
|
withoutStubs.put(remoteClass, null); |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static Class<?> getRemoteClass(Class<?> cl) |
|
throws ClassNotFoundException |
|
{ |
|
while (cl != null) { |
|
Class<?>[] interfaces = cl.getInterfaces(); |
|
for (int i = interfaces.length -1; i >= 0; i--) { |
|
if (Remote.class.isAssignableFrom(interfaces[i])) |
|
return cl; |
|
} |
|
cl = cl.getSuperclass(); |
|
} |
|
throw new ClassNotFoundException( |
|
"class does not implement java.rmi.Remote"); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static Class<?>[] getRemoteInterfaces(Class<?> remoteClass) { |
|
ArrayList<Class<?>> list = new ArrayList<>(); |
|
getRemoteInterfaces(list, remoteClass); |
|
return list.toArray(new Class<?>[list.size()]); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static void getRemoteInterfaces(ArrayList<Class<?>> list, Class<?> cl) { |
|
Class<?> superclass = cl.getSuperclass(); |
|
if (superclass != null) { |
|
getRemoteInterfaces(list, superclass); |
|
} |
|
|
|
Class<?>[] interfaces = cl.getInterfaces(); |
|
for (int i = 0; i < interfaces.length; i++) { |
|
Class<?> intf = interfaces[i]; |
|
|
|
|
|
|
|
|
|
*/ |
|
if (Remote.class.isAssignableFrom(intf)) { |
|
if (!(list.contains(intf))) { |
|
Method[] methods = intf.getMethods(); |
|
for (int j = 0; j < methods.length; j++) { |
|
checkMethod(methods[j]); |
|
} |
|
list.add(intf); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static void checkMethod(Method m) { |
|
Class<?>[] ex = m.getExceptionTypes(); |
|
for (int i = 0; i < ex.length; i++) { |
|
if (ex[i].isAssignableFrom(RemoteException.class)) |
|
return; |
|
} |
|
throw new IllegalArgumentException( |
|
"illegal remote method encountered: " + m); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
private static RemoteStub createStub(Class<?> remoteClass, RemoteRef ref) |
|
throws StubNotFoundException |
|
{ |
|
String stubname = remoteClass.getName() + "_Stub"; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
try { |
|
Class<?> stubcl = |
|
Class.forName(stubname, false, remoteClass.getClassLoader()); |
|
Constructor<?> cons = stubcl.getConstructor(stubConsParamTypes); |
|
return (RemoteStub) cons.newInstance(new Object[] { ref }); |
|
|
|
} catch (ClassNotFoundException e) { |
|
throw new StubNotFoundException( |
|
"Stub class not found: " + stubname, e); |
|
} catch (NoSuchMethodException e) { |
|
throw new StubNotFoundException( |
|
"Stub class missing constructor: " + stubname, e); |
|
} catch (InstantiationException e) { |
|
throw new StubNotFoundException( |
|
"Can't create instance of stub class: " + stubname, e); |
|
} catch (IllegalAccessException e) { |
|
throw new StubNotFoundException( |
|
"Stub class constructor not public: " + stubname, e); |
|
} catch (InvocationTargetException e) { |
|
throw new StubNotFoundException( |
|
"Exception creating instance of stub class: " + stubname, e); |
|
} catch (ClassCastException e) { |
|
throw new StubNotFoundException( |
|
"Stub class not instance of RemoteStub: " + stubname, e); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
static Skeleton createSkeleton(Remote object) |
|
throws SkeletonNotFoundException |
|
{ |
|
Class<?> cl; |
|
try { |
|
cl = getRemoteClass(object.getClass()); |
|
} catch (ClassNotFoundException ex ) { |
|
throw new SkeletonNotFoundException( |
|
"object does not implement a remote interface: " + |
|
object.getClass().getName()); |
|
} |
|
|
|
|
|
String skelname = cl.getName() + "_Skel"; |
|
try { |
|
Class<?> skelcl = Class.forName(skelname, false, cl.getClassLoader()); |
|
|
|
return (Skeleton)skelcl.newInstance(); |
|
} catch (ClassNotFoundException ex) { |
|
throw new SkeletonNotFoundException("Skeleton class not found: " + |
|
skelname, ex); |
|
} catch (InstantiationException ex) { |
|
throw new SkeletonNotFoundException("Can't create skeleton: " + |
|
skelname, ex); |
|
} catch (IllegalAccessException ex) { |
|
throw new SkeletonNotFoundException("No public constructor: " + |
|
skelname, ex); |
|
} catch (ClassCastException ex) { |
|
throw new SkeletonNotFoundException( |
|
"Skeleton not of correct class: " + skelname, ex); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static long computeMethodHash(Method m) { |
|
long hash = 0; |
|
ByteArrayOutputStream sink = new ByteArrayOutputStream(127); |
|
try { |
|
MessageDigest md = MessageDigest.getInstance("SHA"); |
|
DataOutputStream out = new DataOutputStream( |
|
new DigestOutputStream(sink, md)); |
|
|
|
String s = getMethodNameAndDescriptor(m); |
|
if (serverRefLog.isLoggable(Log.VERBOSE)) { |
|
serverRefLog.log(Log.VERBOSE, |
|
"string used for method hash: \"" + s + "\""); |
|
} |
|
out.writeUTF(s); |
|
|
|
|
|
out.flush(); |
|
byte hasharray[] = md.digest(); |
|
for (int i = 0; i < Math.min(8, hasharray.length); i++) { |
|
hash += ((long) (hasharray[i] & 0xFF)) << (i * 8); |
|
} |
|
} catch (IOException ignore) { |
|
|
|
hash = -1; |
|
} catch (NoSuchAlgorithmException complain) { |
|
throw new SecurityException(complain.getMessage()); |
|
} |
|
return hash; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static String getMethodNameAndDescriptor(Method m) { |
|
StringBuffer desc = new StringBuffer(m.getName()); |
|
desc.append('('); |
|
Class<?>[] paramTypes = m.getParameterTypes(); |
|
for (int i = 0; i < paramTypes.length; i++) { |
|
desc.append(getTypeDescriptor(paramTypes[i])); |
|
} |
|
desc.append(')'); |
|
Class<?> returnType = m.getReturnType(); |
|
if (returnType == void.class) { |
|
desc.append('V'); |
|
} else { |
|
desc.append(getTypeDescriptor(returnType)); |
|
} |
|
return desc.toString(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private static String getTypeDescriptor(Class<?> type) { |
|
if (type.isPrimitive()) { |
|
if (type == int.class) { |
|
return "I"; |
|
} else if (type == boolean.class) { |
|
return "Z"; |
|
} else if (type == byte.class) { |
|
return "B"; |
|
} else if (type == char.class) { |
|
return "C"; |
|
} else if (type == short.class) { |
|
return "S"; |
|
} else if (type == long.class) { |
|
return "J"; |
|
} else if (type == float.class) { |
|
return "F"; |
|
} else if (type == double.class) { |
|
return "D"; |
|
} else if (type == void.class) { |
|
return "V"; |
|
} else { |
|
throw new Error("unrecognized primitive type: " + type); |
|
} |
|
} else if (type.isArray()) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
return type.getName().replace('.', '/'); |
|
} else { |
|
return "L" + type.getName().replace('.', '/') + ";"; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public static String getUnqualifiedName(Class<?> c) { |
|
String binaryName = c.getName(); |
|
return binaryName.substring(binaryName.lastIndexOf('.') + 1); |
|
} |
|
} |