169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.util.proxy; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.lang.reflect.Method; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.BufferedOutputStream; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.ByteArrayOutputStream; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.DataOutputStream; 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.File; 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.FileOutputStream; 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException; 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.security.ProtectionDomain; 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException; 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.ClassFile; 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A helper class for implementing <code>ProxyFactory</code>. 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The users of <code>ProxyFactory</code> do not have to see this class. 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see ProxyFactory 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class FactoryHelper { 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static java.lang.reflect.Method defineClass1, defineClass2; 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal static { 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class cl = Class.forName("java.lang.ClassLoader"); 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal defineClass1 = SecurityActions.getDeclaredMethod( 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cl, 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "defineClass", 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Class[] { String.class, byte[].class, 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int.class, int.class }); 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal defineClass2 = SecurityActions.getDeclaredMethod( 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cl, 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "defineClass", 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Class[] { String.class, byte[].class, 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int.class, int.class, ProtectionDomain.class }); 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception e) { 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("cannot initialize"); 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Returns an index for accessing arrays in this class. 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @throws RuntimeException if a given type is not a primitive type. 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int typeIndex(Class type) { 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class[] list = primitiveTypes; 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = list.length; 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; i++) 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (list[i] == type) 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return i; 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("bad type:" + type.getName()); 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>Class</code> objects representing primitive types. 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final Class[] primitiveTypes = { 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Boolean.TYPE, Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE, 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal }; 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The fully-qualified names of wrapper classes for primitive types. 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String[] wrapperTypes = { 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "java.lang.Boolean", "java.lang.Byte", "java.lang.Character", 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "java.lang.Short", "java.lang.Integer", "java.lang.Long", 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "java.lang.Float", "java.lang.Double", "java.lang.Void" 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal }; 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The descriptors of the constructors of wrapper classes. 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String[] wrapperDesc = { 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "(Z)V", "(B)V", "(C)V", "(S)V", "(I)V", "(J)V", 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "(F)V", "(D)V" 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal }; 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The names of methods for obtaining a primitive value 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * from a wrapper object. For example, <code>intValue()</code> 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is such a method for obtaining an integer value from a 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>java.lang.Integer</code> object. 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String[] unwarpMethods = { 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "booleanValue", "byteValue", "charValue", "shortValue", 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "intValue", "longValue", "floatValue", "doubleValue" 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal }; 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The descriptors of the unwrapping methods contained 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * in <code>unwrapMethods</code>. 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String[] unwrapDesc = { 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "()Z", "()B", "()C", "()S", "()I", "()J", "()F", "()D" 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal }; 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The data size of primitive types. <code>long</code> 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * and <code>double</code> are 2; the others are 1. 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final int[] dataSize = { 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1, 1, 1, 1, 1, 2, 1, 2 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal }; 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Loads a class file by a given class loader. 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method uses a default protection domain for the class 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * but it may not work with a security manager or a sigend jar file. 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @see #toClass(ClassFile,ClassLoader,ProtectionDomain) 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static Class toClass(ClassFile cf, ClassLoader loader) 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return toClass(cf, loader, null); 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Loads a class file by a given class loader. 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param domain if it is null, a default domain is used. 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @since 3.3 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static Class toClass(ClassFile cf, ClassLoader loader, ProtectionDomain domain) 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal byte[] b = toBytecode(cf); 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Method method; 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object[] args; 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (domain == null) { 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal method = defineClass1; 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args = new Object[] { cf.getName(), b, new Integer(0), 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Integer(b.length) }; 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal method = defineClass2; 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args = new Object[] { cf.getName(), b, new Integer(0), 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new Integer(b.length), domain }; 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return toClass2(method, loader, args); 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (RuntimeException e) { 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw e; 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (java.lang.reflect.InvocationTargetException e) { 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException(e.getTargetException()); 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (Exception e) { 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException(e); 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static synchronized Class toClass2(Method method, 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ClassLoader loader, Object[] args) 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws Exception 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SecurityActions.setAccessible(method, true); 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class clazz = (Class)method.invoke(loader, args); 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SecurityActions.setAccessible(method, false); 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return clazz; 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static byte[] toBytecode(ClassFile cf) throws IOException { 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ByteArrayOutputStream barray = new ByteArrayOutputStream(); 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal DataOutputStream out = new DataOutputStream(barray); 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cf.write(out); 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal finally { 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.close(); 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return barray.toByteArray(); 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Writes a class file. 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static void writeFile(ClassFile cf, String directoryName) 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException { 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal writeFile0(cf, directoryName); 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IOException e) { 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CannotCompileException(e); 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void writeFile0(ClassFile cf, String directoryName) 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CannotCompileException, IOException { 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String classname = cf.getName(); 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String filename = directoryName + File.separatorChar 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + classname.replace('.', File.separatorChar) + ".class"; 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int pos = filename.lastIndexOf(File.separatorChar); 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (pos > 0) { 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String dir = filename.substring(0, pos); 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!dir.equals(".")) 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new File(dir).mkdirs(); 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal DataOutputStream out = new DataOutputStream(new BufferedOutputStream( 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new FileOutputStream(filename))); 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cf.write(out); 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (IOException e) { 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw e; 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal finally { 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal out.close(); 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 237