KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > bytecode > TypeSignature


1 /* TypeSignature Copyright (C) 1999-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: TypeSignature.java,v 4.5.2.1 2002/05/28 17:34:01 hoenicke Exp $
18  */

19
20 package jode.bytecode;
21 import jode.AssertError;
22
23 /**
24  * This class contains some static methods to handle type signatures.
25  */

26 public class TypeSignature {
27     /**
28      * This is a private method for generating the signature of a
29      * given type.
30      */

31     private static final StringBuffer JavaDoc appendSignature(StringBuffer JavaDoc sb,
32                               Class JavaDoc javaType) {
33     if (javaType.isPrimitive()) {
34         if (javaType == Boolean.TYPE)
35         return sb.append('Z');
36         else if (javaType == Byte.TYPE)
37         return sb.append('B');
38         else if (javaType == Character.TYPE)
39         return sb.append('C');
40         else if (javaType == Short.TYPE)
41         return sb.append('S');
42         else if (javaType == Integer.TYPE)
43         return sb.append('I');
44         else if (javaType == Long.TYPE)
45         return sb.append('J');
46         else if (javaType == Float.TYPE)
47         return sb.append('F');
48         else if (javaType == Double.TYPE)
49         return sb.append('D');
50         else if (javaType == Void.TYPE)
51         return sb.append('V');
52         else
53         throw new AssertError("Unknown primitive type: "+javaType);
54     } else if (javaType.isArray()) {
55         return appendSignature(sb.append('['),
56                    javaType.getComponentType());
57     } else {
58         return sb.append('L')
59         .append(javaType.getName().replace('.','/')).append(';');
60     }
61     }
62
63     /**
64      * Generate the signature for the given Class.
65      * @param clazz a java.lang.Class, this may also be a primitive or
66      * array type.
67      * @return the type signature (see section 4.3.2 Field Descriptors
68      * of the JVM specification)
69      */

70     public static String JavaDoc getSignature(Class JavaDoc clazz) {
71     return appendSignature(new StringBuffer JavaDoc(), clazz).toString();
72     }
73  
74     /**
75      * Generate a method signature.
76      * @param paramT the java.lang.Class of the parameter types of the method.
77      * @param returnT the java.lang.Class of the return type of the method.
78      * @return the method signature (see section 4.3.3 Method Descriptors
79      * of the JVM specification)
80      */

81     public static String JavaDoc getSignature(Class JavaDoc paramT[], Class JavaDoc returnT) {
82     StringBuffer JavaDoc sig = new StringBuffer JavaDoc("(");
83     for (int i=0; i< paramT.length; i++)
84         appendSignature(sig, paramT[i]);
85     return appendSignature(sig.append(')'), returnT).toString();
86     }
87
88     /**
89      * Generate a Class for a type signature. This is the pendant to
90      * getSignature.
91      * @param typeSig a single type signature
92      * @return the Class object representing that type.
93      */

94     public static Class JavaDoc getClass(String JavaDoc typeSig)
95     throws ClassNotFoundException JavaDoc
96     {
97         switch(typeSig.charAt(0)) {
98         case 'Z':
99             return Boolean.TYPE;
100         case 'B':
101             return Byte.TYPE;
102         case 'C':
103             return Character.TYPE;
104         case 'S':
105             return Short.TYPE;
106         case 'I':
107             return Integer.TYPE;
108         case 'F':
109             return Float.TYPE;
110         case 'J':
111             return Long.TYPE;
112         case 'D':
113             return Double.TYPE;
114         case 'V':
115             return Void.TYPE;
116         case 'L':
117         typeSig = typeSig.substring(1, typeSig.length()-1)
118         .replace('/','.');
119         /* fall through */
120         case '[':
121         return Class.forName(typeSig);
122         }
123         throw new IllegalArgumentException JavaDoc(typeSig);
124     }
125
126     /**
127      * Check if the given type is a two slot type. */

128     private static boolean usingTwoSlots(char type) {
129     return "JD".indexOf(type) >= 0;
130     }
131
132     /**
133      * Returns the number of words, an object of the given simple type
134      * signature takes.
135      */

136     public static int getTypeSize(String JavaDoc typeSig) {
137     return usingTwoSlots(typeSig.charAt(0)) ? 2 : 1;
138     }
139
140     public static String JavaDoc getElementType(String JavaDoc typeSig) {
141     if (typeSig.charAt(0) != '[')
142         throw new IllegalArgumentException JavaDoc();
143     return typeSig.substring(1);
144     }
145
146     public static ClassInfo getClassInfo(String JavaDoc typeSig) {
147     if (typeSig.charAt(0) != 'L')
148         throw new IllegalArgumentException JavaDoc();
149     return ClassInfo.forName
150         (typeSig.substring(1, typeSig.length()-1).replace('/', '.'));
151     }
152
153     public static int skipType(String JavaDoc methodTypeSig, int position) {
154     char c = methodTypeSig.charAt(position++);
155     while (c == '[')
156         c = methodTypeSig.charAt(position++);
157     if (c == 'L')
158         return methodTypeSig.indexOf(';', position) + 1;
159     return position;
160     }
161     
162     /**
163      * Returns the number of words, the arguments for the given method
164      * type signature takes.
165      */

166     public static int getArgumentSize(String JavaDoc methodTypeSig) {
167     int nargs = 0;
168     int i = 1;
169     for (;;) {
170         char c = methodTypeSig.charAt(i);
171         if (c == ')')
172         return nargs;
173         i = skipType(methodTypeSig, i);
174         if (usingTwoSlots(c))
175         nargs += 2;
176         else
177         nargs++;
178     }
179     }
180
181     /**
182      * Returns the number of words, an object of the given simple type
183      * signature takes.
184      */

185     public static int getReturnSize(String JavaDoc methodTypeSig) {
186     int length = methodTypeSig.length();
187     if (methodTypeSig.charAt(length - 2) == ')') {
188         // This is a single character return type.
189
char returnType = methodTypeSig.charAt(length - 1);
190         return returnType == 'V' ? 0
191         : usingTwoSlots(returnType) ? 2 : 1;
192     } else
193         // All multi character return types take one parameter
194
return 1;
195     }
196
197     /**
198      * Returns the number of words, an object of the given simple type
199      * signature takes.
200      */

201     public static String JavaDoc[] getParameterTypes(String JavaDoc methodTypeSig) {
202     int pos = 1;
203     int count = 0;
204     while (methodTypeSig.charAt(pos) != ')') {
205         pos = skipType(methodTypeSig, pos);
206         count++;
207     }
208     String JavaDoc[] params = new String JavaDoc[count];
209     pos = 1;
210     for (int i = 0; i < count; i++) {
211         int start = pos;
212         pos = skipType(methodTypeSig, pos);
213         params[i] = methodTypeSig.substring(start, pos);
214     }
215     return params;
216     }
217
218     /**
219      * Returns the number of words, an object of the given simple type
220      * signature takes.
221      */

222     public static String JavaDoc getReturnType(String JavaDoc methodTypeSig) {
223     return methodTypeSig.substring(methodTypeSig.lastIndexOf(')')+1);
224     }
225
226     /**
227      * Check if there is a valid class name starting at index
228      * in string typesig and ending with a semicolon.
229      * @return the index at which the class name ends.
230      * @exception IllegalArgumentException if there was an illegal character.
231      * @exception StringIndexOutOfBoundsException if the typesig ended early.
232      */

233     private static int checkClassName(String JavaDoc clName, int i)
234     throws IllegalArgumentException JavaDoc, StringIndexOutOfBoundsException JavaDoc
235     {
236     while (true) {
237         char c = clName.charAt(i++);
238         if (c == ';')
239         return i;
240         if (c != '/' && !Character.isJavaIdentifierPart(c))
241         throw new IllegalArgumentException JavaDoc("Illegal java class name: "
242                            + clName);
243     }
244     }
245
246     /**
247      * Check if there is a valid simple type signature starting at index
248      * in string typesig.
249      * @return the index at which the type signature ends.
250      * @exception IllegalArgumentException if there was an illegal character.
251      * @exception StringIndexOutOfBoundsException if the typesig ended early.
252      */

253     private static int checkTypeSig(String JavaDoc typesig, int index) {
254     char c = typesig.charAt(index++);
255     while (c == '[')
256         c = typesig.charAt(index++);
257     if (c == 'L') {
258         index = checkClassName(typesig, index);
259     } else {
260         if ("ZBSCIJFD".indexOf(c) == -1)
261         throw new IllegalArgumentException JavaDoc("Type sig error: "+typesig);
262     }
263     return index;
264     }
265
266     public static void checkTypeSig(String JavaDoc typesig)
267     throws IllegalArgumentException JavaDoc
268     {
269     try {
270         if (checkTypeSig(typesig, 0) != typesig.length())
271         throw new IllegalArgumentException JavaDoc
272             ("Type sig too long: "+typesig);
273     } catch (StringIndexOutOfBoundsException JavaDoc ex) {
274         throw new IllegalArgumentException JavaDoc
275         ("Incomplete type sig: "+typesig);
276     }
277     }
278
279     public static void checkMethodTypeSig(String JavaDoc typesig)
280     throws IllegalArgumentException JavaDoc
281     {
282     try {
283         if (typesig.charAt(0) != '(')
284         throw new IllegalArgumentException JavaDoc
285             ("No method signature: "+typesig);
286         int i = 1;
287         while (typesig.charAt(i) != ')')
288         i = checkTypeSig(typesig, i);
289         // skip closing parenthesis.
290
i++;
291         if (typesig.charAt(i) == 'V')
292         // accept void return type.
293
i++;
294         else
295         i = checkTypeSig(typesig, i);
296         if (i != typesig.length())
297         throw new IllegalArgumentException JavaDoc
298             ("Type sig too long: "+typesig);
299     } catch (StringIndexOutOfBoundsException JavaDoc ex) {
300         throw new IllegalArgumentException JavaDoc
301         ("Incomplete type sig: "+typesig);
302     }
303     }
304 }
305
306
Popular Tags