/Users/lyon/j4p/src/javassist/runtime/Desc.java

1    /* 
2     * Javassist, a Java-bytecode translator toolkit. 
3     * Copyright (C) 1999-2003 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    
36       private static Class getClassObject(String name) 
37               throws ClassNotFoundException { 
38           if (useContextClassLoader) 
39               return Thread.currentThread().getContextClassLoader() 
40                       .loadClass(name); 
41           else 
42               return Class.forName(name); 
43       } 
44    
45       /** 
46        * Interprets the given class name. 
47        * It is used for implementing <code>$class</code>. 
48        */ 
49       public static Class getClazz(String name) { 
50           try { 
51               return getClassObject(name); 
52           } catch (ClassNotFoundException e) { 
53               throw new RuntimeException("$class: internal error"); 
54           } 
55       } 
56    
57       /** 
58        * Interprets the given type descriptor representing a method 
59        * signature.  It is used for implementing <code>$sig</code>. 
60        */ 
61       public static Class[] getParams(String desc) { 
62           if (desc.charAt(0) != '(') 
63               throw new RuntimeException("$sig: internal error"); 
64    
65           return getType(desc, desc.length(), 1, 0); 
66       } 
67    
68       /** 
69        * Interprets the given type descriptor. 
70        * It is used for implementing <code>$type</code>. 
71        */ 
72       public static Class getType(String desc) { 
73           Class[] result = getType(desc, desc.length(), 0, 0); 
74           if (result == null || result.length != 1) 
75               throw new RuntimeException("$type: internal error"); 
76    
77           return result[0]; 
78       } 
79    
80       private static Class[] getType(String desc, int descLen, 
81                                      int start, int num) { 
82           Class clazz; 
83           if (start >= descLen) 
84               return new Class[num]; 
85    
86           char c = desc.charAt(start); 
87           switch (c) { 
88               case 'Z': 
89                   clazz = Boolean.TYPE; 
90                   break; 
91               case 'C': 
92                   clazz = Character.TYPE; 
93                   break; 
94               case 'B': 
95                   clazz = Byte.TYPE; 
96                   break; 
97               case 'S': 
98                   clazz = Short.TYPE; 
99                   break; 
100              case 'I': 
101                  clazz = Integer.TYPE; 
102                  break; 
103              case 'J': 
104                  clazz = Long.TYPE; 
105                  break; 
106              case 'F': 
107                  clazz = Float.TYPE; 
108                  break; 
109              case 'D': 
110                  clazz = Double.TYPE; 
111                  break; 
112              case 'V': 
113                  clazz = Void.TYPE; 
114                  break; 
115              case 'L': 
116              case '[': 
117                  return getClassType(desc, descLen, start, num); 
118              default : 
119                  return new Class[num]; 
120          } 
121   
122          Class[] result = getType(desc, descLen, start + 1, num + 1); 
123          result[num] = clazz; 
124          return result; 
125      } 
126   
127      private static Class[] getClassType(String desc, int descLen, 
128                                          int start, int num) { 
129          int end = start; 
130          while (desc.charAt(end) == '[') 
131              ++end; 
132   
133          if (desc.charAt(end) == 'L') { 
134              end = desc.indexOf(';', end); 
135              if (end < 0) 
136                  throw new IndexOutOfBoundsException("bad descriptor"); 
137          } 
138   
139          String cname; 
140          if (desc.charAt(start) == 'L') 
141              cname = desc.substring(start + 1, end); 
142          else 
143              cname = desc.substring(start, end + 1); 
144   
145          Class[] result = getType(desc, descLen, end + 1, num + 1); 
146          try { 
147              result[num] = getClassObject(cname.replace('/', '.')); 
148          } catch (ClassNotFoundException e) { 
149              // "new RuntimeException(e)" is not available in JDK 1.3. 
150              throw new RuntimeException(e.getMessage()); 
151          } 
152   
153          return result; 
154      } 
155  } 
156