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