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