/* * @(#)IxcClassLoader.java 1.29 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package com.sun.xlet.ixc; import java.rmi.Remote; import java.rmi.RemoteException; import javax.microedition.xlet.XletContext; import javax.microedition.xlet.ixc.StubException; import java.net.URL; import java.lang.reflect.Method; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Hashtable; import java.util.HashSet; import java.util.Iterator; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; /** * Class loader for Xlets. This is needed to automatically generate stub * classes for IXC. * <p> * Suppose, for example, that a user class implemens a remote interface UserIF, * and that interface contains two methods, void frob(Something), and * int glorp(float). This classloader will automatically generate * a remote stub. The stub will be equivalent to the following class: * <pre> * * package com.sun.xlet; * * import java.lang.reflect.Method; * * public final class StubClass$$42 extends com.sun.xlet.WrappedRemote * implements UserIF { * * private static Method com_sun_xlet_method0; * private static Method com_sun_xlet_method1; * * * public static void com_sun_xlet_init(Method findMethodMethod) * throws Exception { * // findMethodMethod is Utils.findMethod for the ClassLoader * // where the *target* Remote object lives. * * if (com_sun_xlet_method0 != null) { * return; * } * com_sun_xlet_method0 = (Method) findMethodMethod.invoke(null, * new Object[] { "UserIF", "frob", new Object[] { "Something" }}); * com_sun_xlet_method1 = (Method) findMethodMethod.invoke(null, * new Object[] { "UserIF", "glorp", * new Object[] { java.lang.Float.TYPE }}); * } * * public static void com_sun_xlet_destroy() { * com_sun_xlet_method0 = null; * com_sun_xlet_method1 = null; * } * * public StubClass$$42(Remote target, ImportRegistryImpl registry, * RegistryKey key) { * super(target, registry, key); * } * * public void frob(Something arg1) throws org.dvb.ixc.RemoteException { * com_sun_xlet_execute(com_sun_xlet_method0, * new Object[] { arg1 }); * } * * public int glorp(float arg1) throws org.dvb.ixc.RemoteException { * Object r = com_sun_xlet_execute(com_sun_xlet_method1, * new Object[] { new Float(arg1) }); * return ((Integer) r).intValue(); * } * } * * </pre> * <p> * @@ Add the synthetic attribute * @@ Do this with a security manager installed * @@ Make exception handling consistent with 1.2 behavior. Specifically, * RemoteExceptions should be cloned and wrapped, RuntimeExceptions * should be cloned and re-thrown, checked exception that appear in the * interface method's signature should be cloned and re-thrown (probably * with our deprecated friend, Thread.stop(Throwable)), and unexpected * checked exceptions should be cloned and wrapped (there's some exception * under java.rmi specifically for this). */ /* * This classloader is deligated from an Xlet's class loader and generates * a stub class to be used for inter-xlet communication */ class IxcClassLoader extends ClassLoader { private static Class theRemoteIF = Remote.class; private Hashtable generated = new Hashtable(11); // Key is remote class, value is stub we generate. private static // for debugging int nextStubNumber = 1; // ImportRegistryImpl.copyObject needs to // deserialize objects in the context of this classloader. To do this, // it defines a class called com.sun.xlet.DeserializeUtility, with // a single static method, deserialize(byte[]). The source for this // class, and a little utility for converting the .class to a // byte[], can be found in ~/misc/com/sun/xlet. private Method deserializeMethod = null; private Method findMethodMethod = null; private Class utilsClass = null; private static byte[] utilsClassBody = { // The .class file (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x2e, (byte) 0x00, (byte) 0x3d, (byte) 0x0a, (byte) 0x00, (byte) 0x11, (byte) 0x00, (byte) 0x1f, (byte) 0x07, (byte) 0x00, (byte) 0x20, (byte) 0x07, (byte) 0x00, (byte) 0x21, (byte) 0x0a, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x22, (byte) 0x0a, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x23, (byte) 0x0a, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x24, (byte) 0x07, (byte) 0x00, (byte) 0x25, (byte) 0x07, (byte) 0x00, (byte) 0x26, (byte) 0x07, (byte) 0x00, (byte) 0x27, (byte) 0x0a, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x28, (byte) 0x0a, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x29, (byte) 0x07, (byte) 0x00, (byte) 0x2a, (byte) 0x07, (byte) 0x00, (byte) 0x2b, (byte) 0x0a, (byte) 0x00, (byte) 0x0c, (byte) 0x00, (byte) 0x2c, (byte) 0x0a, (byte) 0x00, (byte) 0x0d, (byte) 0x00, (byte) 0x2d, (byte) 0x07, (byte) 0x00, (byte) 0x2e, (byte) 0x07, (byte) 0x00, (byte) 0x2f, (byte) 0x01, (byte) 0x00, (byte) 0x06, (byte) 0x3c, (byte) 0x69, (byte) 0x6e, (byte) 0x69, (byte) 0x74, (byte) 0x3e, (byte) 0x01, (byte) 0x00, (byte) 0x03, (byte) 0x28, (byte) 0x29, (byte) 0x56, (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x43, (byte) 0x6f, (byte) 0x64, (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0f, (byte) 0x4c, (byte) 0x69, (byte) 0x6e, (byte) 0x65, (byte) 0x4e, (byte) 0x75, (byte) 0x6d, (byte) 0x62, (byte) 0x65, (byte) 0x72, (byte) 0x54, (byte) 0x61, (byte) 0x62, (byte) 0x6c, (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0b, (byte) 0x64, (byte) 0x65, (byte) 0x73, (byte) 0x65, (byte) 0x72, (byte) 0x69, (byte) 0x61, (byte) 0x6c, (byte) 0x69, (byte) 0x7a, (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x1a, (byte) 0x28, (byte) 0x5b, (byte) 0x42, (byte) 0x29, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x69, (byte) 0x6f, (byte) 0x2f, (byte) 0x53, (byte) 0x65, (byte) 0x72, (byte) 0x69, (byte) 0x61, (byte) 0x6c, (byte) 0x69, (byte) 0x7a, (byte) 0x61, (byte) 0x62, (byte) 0x6c, (byte) 0x65, (byte) 0x3b, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x45, (byte) 0x78, (byte) 0x63, (byte) 0x65, (byte) 0x70, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, (byte) 0x73, (byte) 0x07, (byte) 0x00, (byte) 0x30, (byte) 0x07, (byte) 0x00, (byte) 0x31, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x66, (byte) 0x69, (byte) 0x6e, (byte) 0x64, (byte) 0x4d, (byte) 0x65, (byte) 0x74, (byte) 0x68, (byte) 0x6f, (byte) 0x64, (byte) 0x01, (byte) 0x00, (byte) 0x4b, (byte) 0x28, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x3b, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x3b, (byte) 0x5b, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x3b, (byte) 0x29, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x3b, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x75, (byte) 0x72, (byte) 0x63, (byte) 0x65, (byte) 0x46, (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x55, (byte) 0x74, (byte) 0x69, (byte) 0x6c, (byte) 0x73, (byte) 0x2e, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x0c, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x13, (byte) 0x01, (byte) 0x00, (byte) 0x19, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x69, (byte) 0x6f, (byte) 0x2f, (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x49, (byte) 0x6e, (byte) 0x70, (byte) 0x75, (byte) 0x74, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x6d, (byte) 0x01, (byte) 0x00, (byte) 0x1c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x69, (byte) 0x6f, (byte) 0x2f, (byte) 0x42, (byte) 0x79, (byte) 0x74, (byte) 0x65, (byte) 0x41, (byte) 0x72, (byte) 0x72, (byte) 0x61, (byte) 0x79, (byte) 0x49, (byte) 0x6e, (byte) 0x70, (byte) 0x75, (byte) 0x74, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x6d, (byte) 0x0c, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x32, (byte) 0x0c, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x33, (byte) 0x0c, (byte) 0x00, (byte) 0x34, (byte) 0x00, (byte) 0x35, (byte) 0x01, (byte) 0x00, (byte) 0x14, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x69, (byte) 0x6f, (byte) 0x2f, (byte) 0x53, (byte) 0x65, (byte) 0x72, (byte) 0x69, (byte) 0x61, (byte) 0x6c, (byte) 0x69, (byte) 0x7a, (byte) 0x61, (byte) 0x62, (byte) 0x6c, (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x0f, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x43, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x01, (byte) 0x00, (byte) 0x10, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x0c, (byte) 0x00, (byte) 0x36, (byte) 0x00, (byte) 0x37, (byte) 0x0c, (byte) 0x00, (byte) 0x38, (byte) 0x00, (byte) 0x39, (byte) 0x01, (byte) 0x00, (byte) 0x13, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x45, (byte) 0x78, (byte) 0x63, (byte) 0x65, (byte) 0x70, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, (byte) 0x01, (byte) 0x00, (byte) 0x1a, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x52, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x69, (byte) 0x6d, (byte) 0x65, (byte) 0x45, (byte) 0x78, (byte) 0x63, (byte) 0x65, (byte) 0x70, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, (byte) 0x0c, (byte) 0x00, (byte) 0x3a, (byte) 0x00, (byte) 0x3b, (byte) 0x0c, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x3c, (byte) 0x01, (byte) 0x00, (byte) 0x12, (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x2f, (byte) 0x73, (byte) 0x75, (byte) 0x6e, (byte) 0x2f, (byte) 0x78, (byte) 0x6c, (byte) 0x65, (byte) 0x74, (byte) 0x2f, (byte) 0x55, (byte) 0x74, (byte) 0x69, (byte) 0x6c, (byte) 0x73, (byte) 0x01, (byte) 0x00, (byte) 0x10, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x01, (byte) 0x00, (byte) 0x13, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x69, (byte) 0x6f, (byte) 0x2f, (byte) 0x49, (byte) 0x4f, (byte) 0x45, (byte) 0x78, (byte) 0x63, (byte) 0x65, (byte) 0x70, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, (byte) 0x01, (byte) 0x00, (byte) 0x20, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x43, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x4e, (byte) 0x6f, (byte) 0x74, (byte) 0x46, (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x64, (byte) 0x45, (byte) 0x78, (byte) 0x63, (byte) 0x65, (byte) 0x70, (byte) 0x74, (byte) 0x69, (byte) 0x6f, (byte) 0x6e, (byte) 0x01, (byte) 0x00, (byte) 0x05, (byte) 0x28, (byte) 0x5b, (byte) 0x42, (byte) 0x29, (byte) 0x56, (byte) 0x01, (byte) 0x00, (byte) 0x18, (byte) 0x28, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x69, (byte) 0x6f, (byte) 0x2f, (byte) 0x49, (byte) 0x6e, (byte) 0x70, (byte) 0x75, (byte) 0x74, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x6d, (byte) 0x3b, (byte) 0x29, (byte) 0x56, (byte) 0x01, (byte) 0x00, (byte) 0x0a, (byte) 0x72, (byte) 0x65, (byte) 0x61, (byte) 0x64, (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x01, (byte) 0x00, (byte) 0x14, (byte) 0x28, (byte) 0x29, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x3b, (byte) 0x01, (byte) 0x00, (byte) 0x07, (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x4e, (byte) 0x61, (byte) 0x6d, (byte) 0x65, (byte) 0x01, (byte) 0x00, (byte) 0x25, (byte) 0x28, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x3b, (byte) 0x29, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x43, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x3b, (byte) 0x01, (byte) 0x00, (byte) 0x09, (byte) 0x67, (byte) 0x65, (byte) 0x74, (byte) 0x4d, (byte) 0x65, (byte) 0x74, (byte) 0x68, (byte) 0x6f, (byte) 0x64, (byte) 0x01, (byte) 0x00, (byte) 0x40, (byte) 0x28, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x3b, (byte) 0x5b, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x43, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x3b, (byte) 0x29, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x72, (byte) 0x65, (byte) 0x66, (byte) 0x6c, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x2f, (byte) 0x4d, (byte) 0x65, (byte) 0x74, (byte) 0x68, (byte) 0x6f, (byte) 0x64, (byte) 0x3b, (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x74, (byte) 0x6f, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x01, (byte) 0x00, (byte) 0x14, (byte) 0x28, (byte) 0x29, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x3b, (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x28, (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53, (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x3b, (byte) 0x29, (byte) 0x56, (byte) 0x00, (byte) 0x21, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x11, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x12, (byte) 0x00, (byte) 0x13, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1d, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x2a, (byte) 0xb7, (byte) 0x00, (byte) 0x01, (byte) 0xb1, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x16, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x34, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x18, (byte) 0xbb, (byte) 0x00, (byte) 0x02, (byte) 0x59, (byte) 0xbb, (byte) 0x00, (byte) 0x03, (byte) 0x59, (byte) 0x2a, (byte) 0xb7, (byte) 0x00, (byte) 0x04, (byte) 0xb7, (byte) 0x00, (byte) 0x05, (byte) 0x4c, (byte) 0x2b, (byte) 0xb6, (byte) 0x00, (byte) 0x06, (byte) 0xc0, (byte) 0x00, (byte) 0x07, (byte) 0xb0, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0a, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x0d, (byte) 0x00, (byte) 0x18, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x19, (byte) 0x00, (byte) 0x1a, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x1b, (byte) 0x00, (byte) 0x1c, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x93, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x53, (byte) 0x2c, (byte) 0xbe, (byte) 0xbd, (byte) 0x00, (byte) 0x08, (byte) 0x4e, (byte) 0x03, (byte) 0x36, (byte) 0x04, (byte) 0x15, (byte) 0x04, (byte) 0x2c, (byte) 0xbe, (byte) 0xa2, (byte) 0x00, (byte) 0x2f, (byte) 0x2c, (byte) 0x15, (byte) 0x04, (byte) 0x32, (byte) 0xc1, (byte) 0x00, (byte) 0x08, (byte) 0x99, (byte) 0x00, (byte) 0x11, (byte) 0x2d, (byte) 0x15, (byte) 0x04, (byte) 0x2c, (byte) 0x15, (byte) 0x04, (byte) 0x32, (byte) 0xc0, (byte) 0x00, (byte) 0x08, (byte) 0x53, (byte) 0xa7, (byte) 0x00, (byte) 0x11, (byte) 0x2d, (byte) 0x15, (byte) 0x04, (byte) 0x2c, (byte) 0x15, (byte) 0x04, (byte) 0x32, (byte) 0xc0, (byte) 0x00, (byte) 0x09, (byte) 0xb8, (byte) 0x00, (byte) 0x0a, (byte) 0x53, (byte) 0x84, (byte) 0x04, (byte) 0x01, (byte) 0xa7, (byte) 0xff, (byte) 0xd0, (byte) 0x2a, (byte) 0xb8, (byte) 0x00, (byte) 0x0a, (byte) 0x2b, (byte) 0x2d, (byte) 0xb6, (byte) 0x00, (byte) 0x0b, (byte) 0xb0, (byte) 0x4e, (byte) 0xbb, (byte) 0x00, (byte) 0x0d, (byte) 0x59, (byte) 0x2d, (byte) 0xb6, (byte) 0x00, (byte) 0x0e, (byte) 0xb7, (byte) 0x00, (byte) 0x0f, (byte) 0xbf, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x45, (byte) 0x00, (byte) 0x46, (byte) 0x00, (byte) 0x0c, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x15, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x26, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x13, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x15, (byte) 0x00, (byte) 0x1a, (byte) 0x00, (byte) 0x16, (byte) 0x00, (byte) 0x28, (byte) 0x00, (byte) 0x18, (byte) 0x00, (byte) 0x36, (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x3c, (byte) 0x00, (byte) 0x1b, (byte) 0x00, (byte) 0x46, (byte) 0x00, (byte) 0x1c, (byte) 0x00, (byte) 0x47, (byte) 0x00, (byte) 0x1d, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x1d, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x1e }; IxcClassLoader(ClassLoader l) { super(l); } private void addMethodsFor(Class clazz, Hashtable methods) { if (theRemoteIF.isAssignableFrom(clazz)) { if (clazz.isInterface()) { Method[] m = clazz.getMethods(); for (int i = 0; i < m.length; i++) { methods.put(m[i], m[i]); } } else { Class[] ifs = clazz.getInterfaces(); for (int i = 0; i < ifs.length; i++) { addMethodsFor(ifs[i], methods); } Class sup = clazz.getSuperclass(); if (sup != null) { addMethodsFor(sup, methods); } } } } private Method[] getMethodsFor(Class remote) { Hashtable methods = new Hashtable(11); // Set of methods we have to generate. Both key and value are // (the same instance of) Method. This eliminates duplicates. addMethodsFor(remote, methods); Method[] result = new Method[methods.size()]; int i = 0; for (Enumeration e = methods.elements(); e.hasMoreElements();) { result[i++] = (Method) e.nextElement(); } return result; } private void addInterfacesFor(Class clazz, Hashtable interfaces, boolean addAll) { // If addAll = true, then add any interface to the list. // Else add interfaces that extend java.rmi.Remote to the list. if (clazz.isInterface()) { if (addAll) { interfaces.put(clazz, clazz); } else { if (theRemoteIF.isAssignableFrom(clazz)) { interfaces.put(clazz, clazz); addAll = true; } } } Class[] ifs = clazz.getInterfaces(); for (int i = 0; i < ifs.length; i++) { addInterfacesFor(ifs[i], interfaces, addAll); } Class sup = clazz.getSuperclass(); if (sup != null) { addInterfacesFor(sup, interfaces, addAll); } } private Class[] getInterfacesFor(Class remote) { // Returns a set of interfaces we have to add to a ConstantPool. Hashtable interfaces = new Hashtable(11); addInterfacesFor(remote, interfaces, false); Class[] result = new Class[interfaces.size()]; int i = 0; for (Enumeration e = interfaces.elements(); e.hasMoreElements();) { result[i++] = (Class) e.nextElement(); } return result; } // // Get the set of remote interfaces that are // implemented by the class cl. This includes // remote interfaces implemented by // the superclasses of cl. // private Class[] getRemoteInterfaces(Class cl) { HashSet interfaces = new HashSet(); getRemoteInterfacesFor(cl, interfaces); Class[] result = new Class[interfaces.size()]; Iterator it = interfaces.iterator(); for (int i = 0; it.hasNext(); i++){ result[i] = (Class) it.next(); } return result; } private void getRemoteInterfacesFor(Class cl, HashSet interfaces) { while (cl != null) { Class[] ifs = cl.getInterfaces(); for (int i = 0; i < ifs.length; i++) { if (theRemoteIF.isAssignableFrom(ifs[i])) { interfaces.add(ifs[i]); } } cl = cl.getSuperclass(); } } private String nextStubName(String className) { // We expect to be called with this's lock held // fix for 4977190 return new String(className + "_stub" + (nextStubNumber++)); } private String descriptorFor(Method m) { String descriptor = "("; Class[] params = m.getParameterTypes(); for (int j = 0; j < params.length; j++) { descriptor += TypeInfo.descriptorFor(params[j]); } descriptor += ")"; descriptor += TypeInfo.descriptorFor(m.getReturnType()); return descriptor; } synchronized Class getStubClass(IxcClassLoader target, Class remote) throws RemoteException { loadUtilsClass(); Class result = (Class) generated.get(remote); if (result != null) { return result; } if (!theRemoteIF.isAssignableFrom(remote)) { throw new StubException("Remote class must implement Remote"); } try { String stubName = nextStubName(remote.getName()); // fix for 4977190 byte[] classBytes = generateStubClass(stubName.replace('.','/'), remote); // workaround to invoke defineClass() of a ClassLoader // that loaded an xlet.. ClassLoader loader = getParent(); final java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { String.class, classBytes.getClass(), int.class, int.class }); AccessController.doPrivileged(new PrivilegedAction() { public Object run() { m.setAccessible(new java.lang.reflect.AccessibleObject[]{m}, true); return null; } }); result = (Class) m.invoke(loader, new Object[] { stubName, classBytes, new Integer(0), new Integer(classBytes.length) } ); Method initialize = result.getMethod("com_sun_xlet_init", new Class[] { Method.class } ); Method findMethod = target.getFindMethodMethod(); initialize.invoke(null, new Object[] { findMethod } ); generated.put(remote, result); return result; } catch (StubException r) { throw r; } catch (Exception ex) { throw new StubException("getStub() failed", ex); } catch (NoClassDefFoundError err) { throw new StubException("Cannot find a class definition for " + err.getMessage(), err); } } synchronized void forgetStubsFor(ClassLoader other) { Class[] keys = new Class[generated.size()]; int i = 0; for (Enumeration e = generated.keys(); e.hasMoreElements();) { keys[i++] = (Class) e.nextElement(); } for (i = 0; i < keys.length; i++) { Class stub = (Class) generated.get(keys[i]); // Now, we invoke com_sun_xlet_destroy on the stub. This // is important, because our stub maintains references to // methods of the ClassLoader that is being destroyed. If // we maintained them, that ClassLoader would still be reachable // through our stub class, so the victim ClassLoader would never // become collectible. try { Method destroy = stub.getMethod("com_sun_xlet_destroy", new Class[0]); destroy.invoke(null, new Object[0]); } catch (Exception ex) { ex.printStackTrace(); // Should never happen } generated.remove(keys[i]); } } private synchronized byte[] generateStubClass(String stubName, Class remote) throws IOException, RemoteException { Method[] methods = getMethodsFor(remote); // The stub would include methods defined in 'remote interface', // which is an interface that directly or indirectly extends // java.rmi.Remote. In other words, // interface BaseInterface extends java.rmi.Remote // interface ExtendedInterface extends java.rmi.Remote, Xlet // class TestXlet implements ExtendedInterface // then, ExtendedInterface is a 'remote interface' for TestXlet // and methods declared in BaseInterface, ExtendedInterface // and Xlet interface are treated as remote methods. // Class[] allInterfaces = getInterfacesFor(remote); Class[] toplevelInterfaces = getRemoteInterfaces(remote); // time to check if all method declarations are valid.. verifyRemoteMethods(methods); ConstantPool cp = new ConstantPool(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); cp.addString("Code"); // For the code attribute cp.addString("Exceptions"); // For the exceptoins attribute String wrappedRemote = "com/sun/xlet/ixc/WrappedRemote"; String constructorDescriptor = "(Ljava/rmi/Remote;Lcom/sun/xlet/ixc/ImportRegistry;Lcom/sun/xlet/ixc/RegistryKey;)V"; String executeDescriptor = "(Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"; String invokeDescriptor = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"; // Add constant pool entries for names derived from the stuff // we're implementing. cp.addClass(wrappedRemote); cp.addClass(stubName); cp.addClass("com/sun/xlet/Utils"); cp.addClass("java/lang/Object"); cp.addClass("java/lang/Exception"); cp.addClass("java/lang/reflect/Method"); cp.addClass("java/rmi/RemoteException"); for (int i = 0; i < allInterfaces.length; i++) { cp.addClass(allInterfaces[i].getName().replace('.', '/')); } Hashtable primArgsDone = new Hashtable(11); Hashtable primRetsDone = new Hashtable(11); for (int i = 0; i < methods.length; i++) { cp.addField(stubName, "com_sun_xlet_method" + i, "Ljava/lang/reflect/Method;"); // For class init method cp.addStringConstant(methods[i].getName()); cp.addIfMethodReference(methods[i].getDeclaringClass().getName().replace('.', '/'), methods[i].getName(), descriptorFor(methods[i])); cp.addStringConstant(methods[i].getDeclaringClass().getName()); Class rt = methods[i].getReturnType(); if (Void.TYPE.equals(rt)) {} else if (rt.isPrimitive()) { TypeInfo info = TypeInfo.get(rt); String rtNm = info.primitiveWrapper.getName().replace('.', '/'); cp.addClass(rtNm); cp.addMethodReference(rtNm, info.valueMethod, "()" + info.typeDescriptor); } else { cp.addClass(rt.getName().replace('.', '/')); } Class[] params = methods[i].getParameterTypes(); for (int j = 0; j < params.length; j++) { if (params[j].isPrimitive()) { // Don't need to worry about void here TypeInfo info = TypeInfo.get(params[j]); Class p = info.primitiveWrapper; String nm = p.getName().replace('.', '/'); if (primArgsDone.get(nm) == null) { primArgsDone.put(nm, nm); cp.addClass(nm); // The constructor for the wrapper class: cp.addMethodReference(nm, "<init>", "(" + TypeInfo.descriptorFor(params[j]) + ")V"); // The TYPE field cp.addField(nm, "TYPE", "Ljava/lang/Class;"); } } else { cp.addStringConstant(params[j].getName()); } } //for exceptions //Class[] exceptions = methods[i].getExceptionTypes(); //for (int j = 0; j < exceptions.length; j++) { // cp.addClass(exceptions[j].getName().replace('.', '/')); //} cp.addClass("java/rmi/RemoteException"); } cp.addString("com_sun_xlet_init"); cp.addString("(Ljava/lang/reflect/Method;)V"); cp.addString("com_sun_xlet_destroy"); cp.addString("()V"); // Add constructor constants... cp.addString("<init>"); cp.addMethodReference(wrappedRemote, "<init>", constructorDescriptor); cp.addMethodReference(wrappedRemote, "com_sun_xlet_execute", executeDescriptor); cp.addMethodReference("java/lang/reflect/Method", "invoke", invokeDescriptor); // Now write out the .class! dos.writeInt(0xcafebabe); dos.writeShort(0x3a); // Minor version, JDK 1.1.3 dos.writeShort(0x2d); // Major version, JDK 1.1.3 // It's what I observed in 1.1.3, which was handy. Nothing magic // about 1.1.3. cp.write(dos); // Constant pool dos.writeShort(0x31); // ACC_SUPER | ACC_PUBLIC | ACC_FINAL // this_class: dos.writeShort(cp.lookupClass(stubName)); // super_class: dos.writeShort(cp.lookupClass(wrappedRemote)); // Interfaces: dos.writeShort(toplevelInterfaces.length); for (int i = 0; i < toplevelInterfaces.length; i++) { dos.writeShort(cp.lookupClass(toplevelInterfaces[i].getName().replace('.', '/'))); } // Fields: dos.writeShort(methods.length); int methodClassType = cp.lookupString("Ljava/lang/reflect/Method;"); for (int i = 0; i < methods.length; i++) { dos.writeShort(0x8 | 0x2); // STATIC, PRIVATE dos.writeShort(cp.lookupString("com_sun_xlet_method" + i)); dos.writeShort(methodClassType); dos.writeShort(0); // attributes_count } // Methods: dos.writeShort(methods.length + 3); // First, the constructor: { dos.writeShort(0x1); // PUBLIC dos.writeShort(cp.lookupString("<init>")); dos.writeShort(cp.lookupString(constructorDescriptor)); dos.writeShort(1); // 1 attribute, the Code attribute dos.writeShort(cp.lookupString("Code")); int codeLen = 8; dos.writeInt(12 + codeLen); // attribute_length dos.writeShort(10); // max_stack; be conservative dos.writeShort(10); // max_locals; be conservative dos.writeInt(codeLen); // The code: dos.write(0x2a); // aload_0 dos.write(0x2b); // aload_1 dos.write(0x2c); // aload_2 dos.write(0x2d); // aload_3 dos.write(0xb7); // invokespecial dos.writeShort( cp.lookupMethod(wrappedRemote, "<init>", constructorDescriptor)); dos.write(0xb1); // return // The rest of the code attribute: dos.writeShort(0); // exception_table_length dos.writeShort(0); // attribute_count } // Next, the com_sun_xlet_init static initialization method: int invokeMethod = cp.lookupMethod("java/lang/reflect/Method", "invoke", invokeDescriptor); { dos.writeShort(0x1 | 0x8); // PUBLIC | STATIC dos.writeShort(cp.lookupString("com_sun_xlet_init")); dos.writeShort(cp.lookupString("(Ljava/lang/reflect/Method;)V")); dos.writeShort(2); // 2 attributes, Code and Exceptions dos.writeShort(cp.lookupString("Code")); int codeLen = 7; for (int i = 0; i < methods.length; i++) { Class[] params = methods[i].getParameterTypes(); codeLen += 25 + (7 * params.length) + 10; } codeLen += 1; dos.writeInt(12 + codeLen); // attribute_length dos.writeShort(20); // max_stack; be conservative dos.writeShort(20); // max_locals; be conservative dos.writeInt(codeLen); // The code: dos.write(0xb2); // getstatic dos.writeShort(cp.lookupField(stubName, "com_sun_xlet_method0", "Ljava/lang/reflect/Method;")); dos.write(0xc6); // ifnull dos.writeShort(4); dos.write(0xb1); // return for (int i = 0; i < methods.length; i++) { Method m = methods[i]; Class[] params = m.getParameterTypes(); String from = m.getDeclaringClass().getName(); dos.write(0x2a); // aload_0 dos.write(0x1); // aconst_null dos.write(0x6); // iconst_3 dos.write(0xbd); // anewarray dos.writeShort(cp.lookupClass("java/lang/Object")); dos.write(0x59); // dup dos.write(0x3); // iconst_0 dos.write(0x13); // ldc_2 dos.writeShort(cp.lookupStringConstant(from)); dos.write(0x53); // aastore dos.write(0x59); // dup dos.write(0x4); // iconst_1 dos.write(0x13); // ldc_w dos.writeShort(cp.lookupStringConstant(m.getName())); dos.write(0x53); // aastore dos.write(0x59); // dup dos.write(0x5); // iconst_2 dos.write(0x10); // bipush dos.write(params.length); dos.write(0xbd); // anewarray dos.writeShort(cp.lookupClass("java/lang/Object")); for (int j = 0; j < params.length; j++) { Class p = params[j]; dos.write(0x59); // dup dos.write(0x10); // bipush dos.write(j); if (p.isPrimitive()) { p = TypeInfo.get(p).primitiveWrapper; String nm = p.getName().replace('.', '/'); dos.write(0xb2); // getstatic dos.writeShort(cp.lookupField(nm, "TYPE", "Ljava/lang/Class;")); } else { dos.write(0x13); // ldc_w dos.writeShort(cp.lookupStringConstant(p.getName())); } dos.write(0x53); // aastore } dos.write(0x53); // aastore dos.write(0xb6); // invokevirtual dos.writeShort(invokeMethod); dos.write(0xc0); // checkcast dos.writeShort(cp.lookupClass("java/lang/reflect/Method")); dos.write(0xb3); // putstatic dos.writeShort(cp.lookupField(stubName, "com_sun_xlet_method" + i, "Ljava/lang/reflect/Method;")); } dos.write(0xb1); // return // The rest of the code attribute: dos.writeShort(0); // exception_table_length dos.writeShort(0); // attribute_count // Now the second attribute of the method dos.writeShort(cp.lookupString("Exceptions")); dos.writeInt(4); dos.writeShort(1); dos.writeShort(cp.lookupClass("java/lang/Exception")); } // Next, the com_sun_xlet_destroy static method. cf. // forgetStubsFor(XletClassLoader l). { dos.writeShort(0x1 | 0x8); // PUBLIC | STATIC dos.writeShort(cp.lookupString("com_sun_xlet_destroy")); dos.writeShort(cp.lookupString("()V")); dos.writeShort(1); // 1 attribute, Code dos.writeShort(cp.lookupString("Code")); int codeLen = (4 * methods.length) + 1; dos.writeInt(12 + codeLen); // attribute_length dos.writeShort(5); // max_stack; be conservative dos.writeShort(5); // max_locals; be conservative dos.writeInt(codeLen); // The code: for (int i = 0; i < methods.length; i++) { Method m = methods[i]; dos.write(0x1); // aconst_null dos.write(0xb3); // putstatic dos.writeShort(cp.lookupField(stubName, "com_sun_xlet_method" + i, "Ljava/lang/reflect/Method;")); } dos.write(0xb1); // return // The rest of the code attribute: dos.writeShort(0); // exception_table_length dos.writeShort(0); // attribute_count } int executeMethod = cp.lookupMethod(wrappedRemote, "com_sun_xlet_execute", executeDescriptor); // Now the stub methods: for (int i = 0; i < methods.length; i++) { Method m = methods[i]; Class[] args = m.getParameterTypes(); int maxLocals = 1; // 1 for "this" parameter for (int j = 0; j < args.length; j++) { maxLocals += TypeInfo.localSlotsFor(args[j]); } int codeLen = 9; for (int j = 0; j < args.length; j++) { if (args[j].isPrimitive()) { codeLen += 9 + 4; } else { codeLen += 2 + 4; } } codeLen += 3; if (Void.TYPE.equals(m.getReturnType())) { codeLen += 2; } else if (m.getReturnType().isPrimitive()) { codeLen += 7; } else { codeLen += 4; } dos.writeShort(0x1 | 0x10); // PUBLIC | FINAL dos.writeShort(cp.lookupString(m.getName())); dos.writeShort(cp.lookupString(descriptorFor(methods[i]))); dos.writeShort(2); // attributes_count dos.writeShort(cp.lookupString("Code")); dos.writeInt(12 + codeLen); dos.writeShort(10); // max_stack; be conservative dos.writeShort(maxLocals); dos.writeInt(codeLen); // Now the code dos.write(0x2a); // aload_0 dos.write(0xb2); // getstatic dos.writeShort(cp.lookupField(stubName, "com_sun_xlet_method" + i, "Ljava/lang/reflect/Method;")); dos.write(0x10); // bipush dos.write(args.length); dos.write(0xbd); // anewarray java.lang.Object dos.writeShort(cp.lookupClass("java/lang/Object")); int slot = 1; for (int j = 0; j < args.length; j++) { dos.write(0x59); // dup dos.write(0x10); // bipush dos.write(j); if (args[j].isPrimitive()) { TypeInfo info = TypeInfo.get(args[j]); Class p = info.primitiveWrapper; String pName = p.getName().replace('.', '/'); dos.write(0xbb); // new dos.writeShort(cp.lookupClass(pName)); dos.write(0x59); // dup dos.write(info.loadInstruction); dos.write(slot); // Invoke constructor of primitive wrapper type: dos.write(0xb7); // invokespecial String d = "(" + info.typeDescriptor + ")V"; dos.writeShort(cp.lookupMethod(pName, "<init>", d)); slot += info.localSlots; } else { dos.write(0x19); dos.write(slot); slot++; } dos.write(0x53); // aastore } dos.write(0xb6); // invokevirtual dos.writeShort(executeMethod); Class ret = m.getReturnType(); if (Void.TYPE.equals(ret)) { dos.write(0x57); // pop dos.write(0xb1); // return } else if (ret.isPrimitive()) { TypeInfo info = TypeInfo.get(ret); Class wr = info.primitiveWrapper; String wrNm = wr.getName().replace('.', '/'); dos.write(0xc0); // checkcast dos.writeShort(cp.lookupClass(wrNm)); dos.write(0xb6); // invokevirtual dos.writeShort(cp.lookupMethod(wrNm, info.valueMethod, "()" + info.typeDescriptor)); dos.write(info.returnInstruction); } else { dos.write(0xc0); // checkcast dos.writeShort(cp.lookupClass(ret.getName().replace('.', '/'))); dos.write(0xb0); // areturn } // The rest of the code attribute: dos.writeShort(0); // exception_table_length dos.writeShort(0); // attribute_count // Now the second attribute of the method dos.writeShort(cp.lookupString("Exceptions")); dos.writeInt(4); dos.writeShort(1); dos.writeShort(cp.lookupClass("java/rmi/RemoteException")); // Class[] exceptions = m.getExceptionTypes(); // number of description (2) + exception index table //dos.writeInt(2 + exceptions.length*2); //dos.writeShort(exceptions.length); // assume RemoteException is already declared in the method //dos.writeShort(cp.lookupClass("java/rmi/RemoteException")); //for (int j = 0; j < exceptions.length; j++) { // dos.writeShort(cp.lookupClass(exceptions[j].getName().replace('.', '/'))); //} } // Attributes (of ClassFile): dos.writeShort(0); // And we're done! dos.close(); // debug //System.out.println("@@ dumping class " + stubName // + " to .class file for debug"); /** ** uncomment this part to dump the stub object in the current dir ** try { ** // dumping the stub class to the current dir. ** dos = new DataOutputStream(new java.io.FileOutputStream(stubName + ".class")); ** dos.write(bos.toByteArray()); ** dos.close(); ** } catch (Exception e) { ** // The output is for debugging - if it can't be done, ** // just notify the user and move on. ** System.out.println("@@ cannot write " + stubName ** + " to .class file to this file system: " + e); ** } **/ return bos.toByteArray(); } private synchronized void loadUtilsClass() throws RemoteException { if (utilsClass == null) { try { // fix for 4977190 utilsClass = defineClass("com.sun.xlet.Utils", utilsClassBody, 0, utilsClassBody.length); } catch (Exception ex) { //throw new RemoteException("Failed to load a util class", ex); throw new StubException("Failed to load a util class", ex); } } } synchronized Method getDeserializeMethod() throws RemoteException { if (deserializeMethod == null) { loadUtilsClass(); try { Class byteA = (Array.newInstance(Byte.TYPE, 0)).getClass(); deserializeMethod = utilsClass.getMethod("deserialize", new Class[] { byteA } ); } catch (Exception ex) { //throw new RemoteException("Can't deserialize", ex); throw new StubException("Can't deserialize", ex); } } return deserializeMethod; } synchronized Method getFindMethodMethod() throws RemoteException { if (findMethodMethod == null) { loadUtilsClass(); try { Class sc = String.class; Class oa = (Array.newInstance(Object.class, 0)).getClass(); findMethodMethod = utilsClass.getMethod("findMethod", new Class[] { sc, sc, oa } ); } catch (Exception ex) { //throw new RemoteException("Can't find the method", ex); throw new StubException("Can't find the method", ex); } } return findMethodMethod; } private void verifyRemoteMethods(Method[] methods) throws RemoteException { // To check if the methods declared in Remote Interfaces are valid. // From the PBP spec: // --- // Methods declared in a remote interface must be defined as follows: // 1. Each method must declare java.rmi.RemoteException in its throws // clause, in addition to any application-specific exceptions. // 2. A remote object passed by remote reference as an argument or // return value must be declared as an interface that extends // java.rmi.Remote , and not as an application class that // implements this remote interface. // 3. The type of each method argument must either be a remote // interface, a class or interface that implements // java.io.Serializable, or a primitive type. // 4. Each return value must either be a remote interface, a class or // interface that implements java.io.Serializable, a primitive type, // or void. boolean doesExceptionThrown; int count; String errorMsg = ""; int i = 0; next: for (; i < methods.length; i++) { doesExceptionThrown = false; Class[] exceptions = methods[i].getExceptionTypes(); for (count = 0; count < exceptions.length; count++) { if (exceptions[count].equals(RemoteException.class)) { doesExceptionThrown = true; break; } } if (doesExceptionThrown == false) { errorMsg += "Method does not declare java.rmi.RemoteException " + "in it's throws clause : " + methods[i].toString() + "\n"; continue next; } Class[] parameters = methods[i].getParameterTypes(); for (count = 0; count < parameters.length; count++) { Class param = parameters[count]; if ( (param.isPrimitive()) || ((java.io.Serializable.class).isAssignableFrom(param)) || (param.isInterface() && theRemoteIF.isAssignableFrom(param))) {; } else { errorMsg += "Method parameter type is not primitive, " + "remote interface, or Serializable : \n" + methods[i].toString() + "\n"; continue next; } } Class rt = methods[i].getReturnType(); if ((rt.isPrimitive()) || (Void.TYPE.equals(rt)) || ((java.io.Serializable.class).isAssignableFrom(rt)) || (rt.isInterface() && theRemoteIF.isAssignableFrom(rt))) {; } else { errorMsg += "Method return type is not primitive, " + "remote interface, Serializable, or void : \n" + methods[i].toString() + "\n"; } } if (!errorMsg.equals("")) { throw new StubException(errorMsg); } } private void log(String s) { System.err.println("IxcClassLoader: " + s); } }