1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later. 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 */ 15 16 package javassist.runtime; 17 18 /** 19 * A support class for implementing <code>$sig</code> and 20 * <code>$type</code>. 21 * This support class is required at runtime 22 * only if <code>$sig</code> or <code>$type</code> is used. 23 */ 24 public class Desc { 25 26 /** 27 * Specifies how a <code>java.lang.Class</code> object is loaded. 28 * 29 * <p>If true, it is loaded by: 30 * <ul><pre>Thread.currentThread().getContextClassLoader().loadClass()</pre></ul> 31 * <p>If false, it is loaded by <code>Class.forName()</code>. 32 * The default value is false. 33 */ 34 public static boolean useContextClassLoader = false; 35 getClassObject(String name)36 private static Class getClassObject(String name) 37 throws ClassNotFoundException 38 { 39 if (useContextClassLoader) 40 return Thread.currentThread().getContextClassLoader() 41 .loadClass(name); 42 else 43 return Class.forName(name); 44 } 45 46 /** 47 * Interprets the given class name. 48 * It is used for implementing <code>$class</code>. 49 */ getClazz(String name)50 public static Class getClazz(String name) { 51 try { 52 return getClassObject(name); 53 } 54 catch (ClassNotFoundException e) { 55 throw new RuntimeException( 56 "$class: internal error, could not find class '" + name 57 + "' (Desc.useContextClassLoader: " 58 + Boolean.toString(useContextClassLoader) + ")", e); 59 } 60 } 61 62 /** 63 * Interprets the given type descriptor representing a method 64 * signature. It is used for implementing <code>$sig</code>. 65 */ getParams(String desc)66 public static Class[] getParams(String desc) { 67 if (desc.charAt(0) != '(') 68 throw new RuntimeException("$sig: internal error"); 69 70 return getType(desc, desc.length(), 1, 0); 71 } 72 73 /** 74 * Interprets the given type descriptor. 75 * It is used for implementing <code>$type</code>. 76 */ getType(String desc)77 public static Class getType(String desc) { 78 Class[] result = getType(desc, desc.length(), 0, 0); 79 if (result == null || result.length != 1) 80 throw new RuntimeException("$type: internal error"); 81 82 return result[0]; 83 } 84 getType(String desc, int descLen, int start, int num)85 private static Class[] getType(String desc, int descLen, 86 int start, int num) { 87 Class clazz; 88 if (start >= descLen) 89 return new Class[num]; 90 91 char c = desc.charAt(start); 92 switch (c) { 93 case 'Z' : 94 clazz = Boolean.TYPE; 95 break; 96 case 'C' : 97 clazz = Character.TYPE; 98 break; 99 case 'B' : 100 clazz = Byte.TYPE; 101 break; 102 case 'S' : 103 clazz = Short.TYPE; 104 break; 105 case 'I' : 106 clazz = Integer.TYPE; 107 break; 108 case 'J' : 109 clazz = Long.TYPE; 110 break; 111 case 'F' : 112 clazz = Float.TYPE; 113 break; 114 case 'D' : 115 clazz = Double.TYPE; 116 break; 117 case 'V' : 118 clazz = Void.TYPE; 119 break; 120 case 'L' : 121 case '[' : 122 return getClassType(desc, descLen, start, num); 123 default : 124 return new Class[num]; 125 } 126 127 Class[] result = getType(desc, descLen, start + 1, num + 1); 128 result[num] = clazz; 129 return result; 130 } 131 getClassType(String desc, int descLen, int start, int num)132 private static Class[] getClassType(String desc, int descLen, 133 int start, int num) { 134 int end = start; 135 while (desc.charAt(end) == '[') 136 ++end; 137 138 if (desc.charAt(end) == 'L') { 139 end = desc.indexOf(';', end); 140 if (end < 0) 141 throw new IndexOutOfBoundsException("bad descriptor"); 142 } 143 144 String cname; 145 if (desc.charAt(start) == 'L') 146 cname = desc.substring(start + 1, end); 147 else 148 cname = desc.substring(start, end + 1); 149 150 Class[] result = getType(desc, descLen, end + 1, num + 1); 151 try { 152 result[num] = getClassObject(cname.replace('/', '.')); 153 } 154 catch (ClassNotFoundException e) { 155 // "new RuntimeException(e)" is not available in JDK 1.3. 156 throw new RuntimeException(e.getMessage()); 157 } 158 159 return result; 160 } 161 } 162