| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
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); | 
 | 
    }  | 
 | 
}  |