• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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