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.runtime; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/** 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * A support class for implementing <code>$sig</code> and 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>$type</code>. 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This support class is required at runtime 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * only if <code>$sig</code> or <code>$type</code> is used. 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Desc { 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Specifies how a <code>java.lang.Class</code> object is loaded. 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If true, it is loaded by: 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>Thread.currentThread().getContextClassLoader().loadClass()</pre></ul> 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If false, it is loaded by <code>Class.forName()</code>. 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The default value is false. 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static boolean useContextClassLoader = false; 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static Class getClassObject(String name) 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws ClassNotFoundException 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (useContextClassLoader) 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Thread.currentThread().getContextClassLoader() 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal .loadClass(name); 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return Class.forName(name); 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Interprets the given class name. 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It is used for implementing <code>$class</code>. 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static Class getClazz(String name) { 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return getClassObject(name); 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (ClassNotFoundException e) { 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException( 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "$class: internal error, could not find class '" + name 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + "' (Desc.useContextClassLoader: " 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal + Boolean.toString(useContextClassLoader) + ")", e); 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Interprets the given type descriptor representing a method 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * signature. It is used for implementing <code>$sig</code>. 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static Class[] getParams(String desc) { 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (desc.charAt(0) != '(') 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("$sig: internal error"); 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return getType(desc, desc.length(), 1, 0); 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Interprets the given type descriptor. 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It is used for implementing <code>$type</code>. 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static Class getType(String desc) { 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class[] result = getType(desc, desc.length(), 0, 0); 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (result == null || result.length != 1) 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException("$type: internal error"); 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return result[0]; 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static Class[] getType(String desc, int descLen, 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int start, int num) { 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class clazz; 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (start >= descLen) 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Class[num]; 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c = desc.charAt(start); 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (c) { 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'Z' : 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Boolean.TYPE; 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'C' : 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Character.TYPE; 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'B' : 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Byte.TYPE; 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'S' : 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Short.TYPE; 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'I' : 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Integer.TYPE; 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'J' : 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Long.TYPE; 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'F' : 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Float.TYPE; 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'D' : 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Double.TYPE; 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'V' : 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal clazz = Void.TYPE; 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 'L' : 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case '[' : 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return getClassType(desc, descLen, start, num); 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default : 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return new Class[num]; 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class[] result = getType(desc, descLen, start + 1, num + 1); 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal result[num] = clazz; 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return result; 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static Class[] getClassType(String desc, int descLen, 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int start, int num) { 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int end = start; 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (desc.charAt(end) == '[') 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++end; 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (desc.charAt(end) == 'L') { 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal end = desc.indexOf(';', end); 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (end < 0) 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new IndexOutOfBoundsException("bad descriptor"); 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String cname; 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (desc.charAt(start) == 'L') 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = desc.substring(start + 1, end); 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = desc.substring(start, end + 1); 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Class[] result = getType(desc, descLen, end + 1, num + 1); 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal result[num] = getClassObject(cname.replace('/', '.')); 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (ClassNotFoundException e) { 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // "new RuntimeException(e)" is not available in JDK 1.3. 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new RuntimeException(e.getMessage()); 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return result; 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 162