KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > classfile > util > ClassUtil


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */

21 package proguard.classfile.util;
22
23 import proguard.classfile.*;
24
25 import java.util.*;
26
27 /**
28  * Utility methods for converting between internal and external representations
29  * of names and descriptions.
30  *
31  * @author Eric Lafortune
32  */

33 public class ClassUtil
34 {
35     private static final String JavaDoc EMPTY_STRING = "";
36
37     private static final InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration();
38     private static final ExternalTypeEnumeration externalTypeEnumeration = new ExternalTypeEnumeration();
39
40
41     /**
42      * Checks whether the given class magic number is correct.
43      * @param magicNumber the magic number.
44      * @throws UnsupportedOperationException when the magic number is incorrect.
45      */

46     public static void checkMagicNumber(int magicNumber) throws UnsupportedOperationException JavaDoc
47     {
48         if (magicNumber != ClassConstants.MAGIC)
49         {
50             throw new UnsupportedOperationException JavaDoc("Invalid magic number ["+Integer.toHexString(magicNumber)+"] in class");
51         }
52     }
53
54
55     /**
56      * Returns the combined class version number.
57      * @param majorVersion the major part of the class version number.
58      * @param minorVersion the minor part of the class version number.
59      * @return the combined class version number.
60      */

61     public static int internalClassVersion(int majorVersion, int minorVersion)
62     {
63         return (majorVersion << 16) | minorVersion;
64     }
65
66
67     /**
68      * Returns the major part of the given class version number.
69      * @param classVersion the combined class version number.
70      * @return the major part of the class version number.
71      */

72     public static int internalMajorClassVersion(int classVersion)
73     {
74         return classVersion >>> 16;
75     }
76
77
78     /**
79      * Returns the internal class version number.
80      * @param classVersion the external class version number.
81      * @return the internal class version number.
82      */

83     public static int internalMinorClassVersion(int classVersion)
84     {
85         return classVersion & 0xffff;
86     }
87
88
89     /**
90      * Returns the internal class version number.
91      * @param classVersion the external class version number.
92      * @return the internal class version number.
93      */

94     public static int internalClassVersion(String JavaDoc classVersion)
95     {
96         return
97             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_0) ||
98             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_1) ? ClassConstants.INTERNAL_CLASS_VERSION_1_0 :
99             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_2) ? ClassConstants.INTERNAL_CLASS_VERSION_1_2 :
100             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_3) ? ClassConstants.INTERNAL_CLASS_VERSION_1_3 :
101             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_4) ? ClassConstants.INTERNAL_CLASS_VERSION_1_4 :
102             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_5_ALIAS) ||
103             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_5) ? ClassConstants.INTERNAL_CLASS_VERSION_1_5 :
104             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_6_ALIAS) ||
105             classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_6) ? ClassConstants.INTERNAL_CLASS_VERSION_1_6 :
106                                                                              0;
107     }
108
109
110     /**
111      * Returns the minor part of the given class version number.
112      * @param classVersion the combined class version number.
113      * @return the minor part of the class version number.
114      */

115     public static String JavaDoc externalClassVersion(int classVersion)
116     {
117         switch (classVersion)
118         {
119             case ClassConstants.INTERNAL_CLASS_VERSION_1_0: return ClassConstants.EXTERNAL_CLASS_VERSION_1_0;
120             case ClassConstants.INTERNAL_CLASS_VERSION_1_2: return ClassConstants.EXTERNAL_CLASS_VERSION_1_2;
121             case ClassConstants.INTERNAL_CLASS_VERSION_1_3: return ClassConstants.EXTERNAL_CLASS_VERSION_1_3;
122             case ClassConstants.INTERNAL_CLASS_VERSION_1_4: return ClassConstants.EXTERNAL_CLASS_VERSION_1_4;
123             case ClassConstants.INTERNAL_CLASS_VERSION_1_5: return ClassConstants.EXTERNAL_CLASS_VERSION_1_5;
124             case ClassConstants.INTERNAL_CLASS_VERSION_1_6: return ClassConstants.EXTERNAL_CLASS_VERSION_1_6;
125             default: return null;
126         }
127     }
128
129
130     /**
131      * Checks whether the given class version number is supported.
132      * @param classVersion the combined class version number.
133      * @throws UnsupportedOperationException when the version is not supported.
134      */

135     public static void checkVersionNumbers(int classVersion) throws UnsupportedOperationException JavaDoc
136     {
137         if (classVersion < ClassConstants.INTERNAL_CLASS_VERSION_1_0 ||
138             classVersion > ClassConstants.INTERNAL_CLASS_VERSION_1_6)
139         {
140             throw new UnsupportedOperationException JavaDoc("Unsupported version number ["+
141                                                     internalMajorClassVersion(classVersion)+"."+
142                                                     internalMinorClassVersion(classVersion)+"] for class format");
143         }
144     }
145
146
147     /**
148      * Converts an external class name into an internal class name.
149      * @param externalClassName the external class name,
150      * e.g. "<code>java.lang.Object</code>"
151      * @return the internal class name,
152      * e.g. "<code>java/lang/Object</code>".
153      */

154     public static String JavaDoc internalClassName(String JavaDoc externalClassName)
155     {
156         return externalClassName.replace(ClassConstants.EXTERNAL_PACKAGE_SEPARATOR,
157                                          ClassConstants.INTERNAL_PACKAGE_SEPARATOR);
158     }
159
160
161     /**
162      * Converts an internal class description into an external class description.
163      * @param accessFlags the access flags of the class.
164      * @param internalClassName the internal class name,
165      * e.g. "<code>java/lang/Object</code>".
166      * @return the external class description,
167      * e.g. "<code>public java.lang.Object</code>".
168      */

169     public static String JavaDoc externalFullClassDescription(int accessFlags,
170                                                       String JavaDoc internalClassName)
171     {
172         return externalClassAccessFlags(accessFlags) +
173                externalClassName(internalClassName);
174     }
175
176
177     /**
178      * Converts an internal class name into an external class name.
179      * @param internalClassName the internal class name,
180      * e.g. "<code>java/lang/Object</code>".
181      * @return the external class name,
182      * e.g. "<code>java.lang.Object</code>".
183      */

184     public static String JavaDoc externalClassName(String JavaDoc internalClassName)
185     {
186         return //internalClassName.startsWith(ClassConstants.INTERNAL_PACKAGE_JAVA_LANG) &&
187
//internalClassName.indexOf(ClassConstants.INTERNAL_PACKAGE_SEPARATOR, ClassConstants.INTERNAL_PACKAGE_JAVA_LANG.length() + 1) < 0 ?
188
//internalClassName.substring(ClassConstants.INTERNAL_PACKAGE_JAVA_LANG.length()) :
189
internalClassName.replace(ClassConstants.INTERNAL_PACKAGE_SEPARATOR,
190                                          ClassConstants.EXTERNAL_PACKAGE_SEPARATOR);
191     }
192
193
194     /**
195      * Converts an internal class name into an external short class name, without
196      * package specification.
197      * @param externalClassName the external class name,
198      * e.g. "<code>java.lang.Object</code>"
199      * @return the external short class name,
200      * e.g. "<code>Object</code>".
201      */

202     public static String JavaDoc externalShortClassName(String JavaDoc externalClassName)
203     {
204         int index = externalClassName.lastIndexOf(ClassConstants.EXTERNAL_PACKAGE_SEPARATOR);
205         return externalClassName.substring(index+1);
206     }
207
208
209     /**
210      * Returns whether the given internal type is an array type.
211      * @param internalType the internal type,
212      * e.g. "<code>[[Ljava/lang/Object;</code>".
213      * @return <code>true</code> if the given type is an array type,
214      * <code>false</code> otherwise.
215      */

216     public static boolean isInternalArrayType(String JavaDoc internalType)
217     {
218         return internalType.length() > 1 &&
219                internalType.charAt(0) == ClassConstants.INTERNAL_TYPE_ARRAY;
220     }
221
222
223     /**
224      * Returns the number of dimensions of the given internal type.
225      * @param internalType the internal type,
226      * e.g. "<code>[[Ljava/lang/Object;</code>".
227      * @return the number of dimensions, e.g. 2.
228      */

229     public static int internalArrayTypeDimensionCount(String JavaDoc internalType)
230     {
231         int dimensions = 0;
232         while (internalType.charAt(dimensions) == ClassConstants.INTERNAL_TYPE_ARRAY)
233         {
234             dimensions++;
235         }
236
237         return dimensions;
238     }
239
240
241     /**
242      * Returns whether the given internal class name is one of the interfaces
243      * that is implemented by all array types. These class names are
244      * "<code>java/lang/Object</code>", "<code>java/lang/Cloneable</code>", and
245      * "<code>java/io/Serializable</code>"
246      * @param internalClassName the internal class name,
247      * e.g. "<code>java/lang/Object</code>".
248      * @return <code>true</code> if the given type is an array interface name,
249      * <code>false</code> otherwise.
250      */

251     public static boolean isInternalArrayInterfaceName(String JavaDoc internalClassName)
252     {
253         return ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT.equals(internalClassName) ||
254                ClassConstants.INTERNAL_NAME_JAVA_LANG_CLONEABLE.equals(internalClassName) ||
255                ClassConstants.INTERNAL_NAME_JAVA_IO_SERIALIZABLE.equals(internalClassName);
256     }
257
258
259     /**
260      * Returns whether the given internal type is a plain primitive type
261      * (not void).
262      * @param internalType the internal type,
263      * e.g. "<code>I</code>".
264      * @return <code>true</code> if the given type is a class type,
265      * <code>false</code> otherwise.
266      */

267     public static boolean isInternalPrimitiveType(char internalType)
268     {
269         return internalType == ClassConstants.INTERNAL_TYPE_BOOLEAN ||
270                internalType == ClassConstants.INTERNAL_TYPE_BYTE ||
271                internalType == ClassConstants.INTERNAL_TYPE_CHAR ||
272                internalType == ClassConstants.INTERNAL_TYPE_SHORT ||
273                internalType == ClassConstants.INTERNAL_TYPE_INT ||
274                internalType == ClassConstants.INTERNAL_TYPE_FLOAT ||
275                internalType == ClassConstants.INTERNAL_TYPE_LONG ||
276                internalType == ClassConstants.INTERNAL_TYPE_DOUBLE;
277     }
278
279
280     /**
281      * Returns whether the given internal type is a primitive Category 2 type.
282      * @param internalType the internal type,
283      * e.g. "<code>L</code>".
284      * @return <code>true</code> if the given type is a Category 2 type,
285      * <code>false</code> otherwise.
286      */

287     public static boolean isInternalCategory2Type(String JavaDoc internalType)
288     {
289         return internalType.length() == 1 &&
290                (internalType.charAt(0) == ClassConstants.INTERNAL_TYPE_LONG ||
291                 internalType.charAt(0) == ClassConstants.INTERNAL_TYPE_DOUBLE);
292     }
293
294
295     /**
296      * Returns whether the given internal type is a plain class type
297      * (including an array type of a plain class type).
298      * @param internalType the internal type,
299      * e.g. "<code>Ljava/lang/Object;</code>".
300      * @return <code>true</code> if the given type is a class type,
301      * <code>false</code> otherwise.
302      */

303     public static boolean isInternalClassType(String JavaDoc internalType)
304     {
305         int length = internalType.length();
306         return length > 1 &&
307 // internalType.charAt(0) == ClassConstants.INTERNAL_TYPE_CLASS_START &&
308
internalType.charAt(length-1) == ClassConstants.INTERNAL_TYPE_CLASS_END;
309     }
310
311
312     /**
313      * Returns the internal type of a given class name.
314      * @param internalClassName the internal class name,
315      * e.g. "<code>java/lang/Object</code>".
316      * @return the internal type,
317      * e.g. "<code>Ljava/lang/Object;</code>".
318      */

319     public static String JavaDoc internalTypeFromClassName(String JavaDoc internalClassName)
320     {
321         return internalArrayTypeFromClassName(internalClassName, 0);
322     }
323
324
325     /**
326      * Returns the internal array type of a given class name with a given number
327      * of dimensions. If the number of dimensions is 0, the class name itself is
328      * returned.
329      * @param internalClassName the internal class name,
330      * e.g. "<code>java/lang/Object</code>".
331      * @param dimensionCount the number of array dimensions.
332      * @return the internal array type of the array elements,
333      * e.g. "<code>Ljava/lang/Object;</code>".
334      */

335     public static String JavaDoc internalArrayTypeFromClassName(String JavaDoc internalClassName,
336                                                         int dimensionCount)
337     {
338         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(internalClassName.length() + dimensionCount + 2);
339
340         for (int dimension = 0; dimension < dimensionCount; dimension++)
341         {
342             buffer.append(ClassConstants.INTERNAL_TYPE_ARRAY);
343         }
344
345         return buffer.append(ClassConstants.INTERNAL_TYPE_CLASS_START)
346                      .append(internalClassName)
347                      .append(ClassConstants.INTERNAL_TYPE_CLASS_END)
348                      .toString();
349     }
350
351
352     /**
353      * Returns the internal element type of a given internal array type.
354      * @param internalArrayType the internal array type,
355      * e.g. "<code>[[Ljava/lang/Object;</code>" or
356      * "<code>[I</code>".
357      * @return the internal type of the array elements,
358      * e.g. "<code>Ljava/lang/Object;</code>" or
359      * "<code>I</code>".
360      */

361     public static String JavaDoc internalTypeFromArrayType(String JavaDoc internalArrayType)
362     {
363         int index = internalArrayType.lastIndexOf(ClassConstants.INTERNAL_TYPE_ARRAY);
364         return internalArrayType.substring(index+1);
365     }
366
367
368     /**
369      * Returns the internal class name of a given internal class type
370      * (including an array type). Types involving primitive types are returned
371      * unchanged.
372      * @param internalClassType the internal class type,
373      * e.g. "<code>[Ljava/lang/Object;</code>",
374      * "<code>Ljava/lang/Object;</code>", or
375      * "<code>java/lang/Object</code>".
376      * @return the internal class name,
377      * e.g. "<code>java/lang/Object</code>".
378      */

379     public static String JavaDoc internalClassNameFromClassType(String JavaDoc internalClassType)
380     {
381         return isInternalClassType(internalClassType) ?
382             internalClassType.substring(internalClassType.indexOf(ClassConstants.INTERNAL_TYPE_CLASS_START)+1,
383                                         internalClassType.length()-1) :
384             internalClassType;
385     }
386
387
388     /**
389      * Returns the internal class name of any given internal descriptor type,
390      * disregarding array prefixes.
391      * @param internalClassType the internal class type,
392      * e.g. "<code>Ljava/lang/Object;</code>" or
393      * "<code>[[I</code>".
394      * @return the internal class name,
395      * e.g. "<code>java/lang/Object</code>" or
396      * <code>null</code>.
397      */

398     public static String JavaDoc internalClassNameFromType(String JavaDoc internalClassType)
399     {
400         if (!isInternalClassType(internalClassType))
401         {
402             return null;
403         }
404
405         // Is it an array type?
406
if (isInternalArrayType(internalClassType))
407         {
408             internalClassType = internalTypeFromArrayType(internalClassType);
409         }
410
411         return internalClassNameFromClassType(internalClassType);
412     }
413
414
415     /**
416      * Returns the internal type of the given internal method descriptor.
417      * @param internalMethodDescriptor the internal method descriptor,
418      * e.g. "<code>(II)Z</code>".
419      * @return the internal return type,
420      * e.g. "<code>Z</code>".
421      */

422     public static String JavaDoc internalMethodReturnType(String JavaDoc internalMethodDescriptor)
423     {
424         int index = internalMethodDescriptor.indexOf(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE);
425         return internalMethodDescriptor.substring(index + 1);
426     }
427
428
429     /**
430      * Returns the number of parameters of the given internal method descriptor.
431      * @param internalMethodDescriptor the internal method descriptor,
432      * e.g. "<code>(ID)Z</code>".
433      * @return the number of parameters,
434      * e.g. 2.
435      */

436     public static int internalMethodParameterCount(String JavaDoc internalMethodDescriptor)
437     {
438         internalTypeEnumeration.setDescriptor(internalMethodDescriptor);
439
440         int counter = 0;
441         while (internalTypeEnumeration.hasMoreTypes())
442         {
443             internalTypeEnumeration.nextType();
444
445             counter++;
446         }
447
448         return counter;
449     }
450
451
452     /**
453      * Returns the size taken up on the stack by the parameters of the given
454      * internal method descriptor. This accounts for long and double parameters
455      * taking up two spaces.
456      * @param internalMethodDescriptor the internal method descriptor,
457      * e.g. "<code>(ID)Z</code>".
458      * @return the size taken up on the stack,
459      * e.g. 3.
460      */

461     public static int internalMethodParameterSize(String JavaDoc internalMethodDescriptor)
462     {
463         internalTypeEnumeration.setDescriptor(internalMethodDescriptor);
464
465         int size = 0;
466         while (internalTypeEnumeration.hasMoreTypes())
467         {
468             String JavaDoc internalType = internalTypeEnumeration.nextType();
469
470             size += internalTypeSize(internalType);
471         }
472
473         return size;
474     }
475
476
477     /**
478      * Returns the size taken up on the stack by the given internal type.
479      * The size is 1, except for long and double types, for which it is 2,
480      * and for the void type, for which 0 is returned
481      * @param internalType the internal type,
482      * e.g. "<code>I</code>".
483      * @return the size taken up on the stack,
484      * e.g. 1.
485      */

486     public static int internalTypeSize(String JavaDoc internalType)
487     {
488         if (internalType.length() == 1)
489         {
490             char internalPrimitiveType = internalType.charAt(0);
491             if (internalPrimitiveType == ClassConstants.INTERNAL_TYPE_LONG ||
492                      internalPrimitiveType == ClassConstants.INTERNAL_TYPE_DOUBLE)
493             {
494                 return 2;
495             }
496             else if (internalPrimitiveType == ClassConstants.INTERNAL_TYPE_VOID)
497             {
498                 return 0;
499             }
500         }
501
502         return 1;
503     }
504
505
506     /**
507      * Converts an external type into an internal type.
508      * @param externalType the external type,
509      * e.g. "<code>java.lang.Object[][]</code>" or
510      * "<code>int[]</code>".
511      * @return the internal type,
512      * e.g. "<code>[[Ljava/lang/Object;</code>" or
513      * "<code>[I</code>".
514      */

515     public static String JavaDoc internalType(String JavaDoc externalType)
516     {
517         // Strip the array part, if any.
518
int dimensionCount = externalArrayTypeDimensionCount(externalType);
519         if (dimensionCount > 0)
520         {
521             externalType = externalType.substring(0, externalType.length() - dimensionCount * ClassConstants.EXTERNAL_TYPE_ARRAY.length());
522         }
523
524         // Analyze the actual type part.
525
char internalTypeChar =
526             externalType.equals(ClassConstants.EXTERNAL_TYPE_VOID ) ?
527                                 ClassConstants.INTERNAL_TYPE_VOID :
528             externalType.equals(ClassConstants.EXTERNAL_TYPE_BOOLEAN) ?
529                                 ClassConstants.INTERNAL_TYPE_BOOLEAN :
530             externalType.equals(ClassConstants.EXTERNAL_TYPE_BYTE ) ?
531                                 ClassConstants.INTERNAL_TYPE_BYTE :
532             externalType.equals(ClassConstants.EXTERNAL_TYPE_CHAR ) ?
533                                 ClassConstants.INTERNAL_TYPE_CHAR :
534             externalType.equals(ClassConstants.EXTERNAL_TYPE_SHORT ) ?
535                                 ClassConstants.INTERNAL_TYPE_SHORT :
536             externalType.equals(ClassConstants.EXTERNAL_TYPE_INT ) ?
537                                 ClassConstants.INTERNAL_TYPE_INT :
538             externalType.equals(ClassConstants.EXTERNAL_TYPE_FLOAT ) ?
539                                 ClassConstants.INTERNAL_TYPE_FLOAT :
540             externalType.equals(ClassConstants.EXTERNAL_TYPE_LONG ) ?
541                                 ClassConstants.INTERNAL_TYPE_LONG :
542             externalType.equals(ClassConstants.EXTERNAL_TYPE_DOUBLE ) ?
543                                 ClassConstants.INTERNAL_TYPE_DOUBLE :
544             externalType.equals("%" ) ?
545                                 '%' :
546                                 (char)0;
547
548         String JavaDoc internalType =
549             internalTypeChar != 0 ? ("" + internalTypeChar) :
550                                     (ClassConstants.INTERNAL_TYPE_CLASS_START +
551                                      internalClassName(externalType) +
552                                      ClassConstants.INTERNAL_TYPE_CLASS_END);
553
554         // Prepend the array part, if any.
555
for (int count = 0; count < dimensionCount; count++)
556         {
557             internalType = ClassConstants.INTERNAL_TYPE_ARRAY + internalType;
558         }
559
560         return internalType;
561     }
562
563
564     /**
565      * Returns the number of dimensions of the given external type.
566      * @param externalType the external type,
567      * e.g. "<code>[[Ljava/lang/Object;</code>".
568      * @return the number of dimensions, e.g. 2.
569      */

570     public static int externalArrayTypeDimensionCount(String JavaDoc externalType)
571     {
572         int dimensions = 0;
573         int length = ClassConstants.EXTERNAL_TYPE_ARRAY.length();
574         int offset = externalType.length() - length;
575         while (externalType.regionMatches(offset,
576                                           ClassConstants.EXTERNAL_TYPE_ARRAY,
577                                           0,
578                                           length))
579         {
580             dimensions++;
581             offset -= length;
582         }
583
584         return dimensions;
585     }
586
587
588     /**
589      * Converts an internal type into an external type.
590      * @param internalType the internal type,
591      * e.g. "<code>[[Ljava/lang/Object;</code>" or
592      * "<code>[I</code>".
593      * @return the external type,
594      * e.g. "<code>java.lang.Object[][]</code>" or
595      * "<code>int[]</code>".
596      */

597     public static String JavaDoc externalType(String JavaDoc internalType)
598     {
599         // Strip the array part, if any.
600
int dimensionCount = internalArrayTypeDimensionCount(internalType);
601         if (dimensionCount > 0)
602         {
603             internalType = internalType.substring(dimensionCount);
604         }
605
606         // Analyze the actual type part.
607
char internalTypeChar = internalType.charAt(0);
608
609         String JavaDoc externalType =
610             internalTypeChar == ClassConstants.INTERNAL_TYPE_VOID ?
611                                 ClassConstants.EXTERNAL_TYPE_VOID :
612             internalTypeChar == ClassConstants.INTERNAL_TYPE_BOOLEAN ?
613                                 ClassConstants.EXTERNAL_TYPE_BOOLEAN :
614             internalTypeChar == ClassConstants.INTERNAL_TYPE_BYTE ?
615                                 ClassConstants.EXTERNAL_TYPE_BYTE :
616             internalTypeChar == ClassConstants.INTERNAL_TYPE_CHAR ?
617                                 ClassConstants.EXTERNAL_TYPE_CHAR :
618             internalTypeChar == ClassConstants.INTERNAL_TYPE_SHORT ?
619                                 ClassConstants.EXTERNAL_TYPE_SHORT :
620             internalTypeChar == ClassConstants.INTERNAL_TYPE_INT ?
621                                 ClassConstants.EXTERNAL_TYPE_INT :
622             internalTypeChar == ClassConstants.INTERNAL_TYPE_FLOAT ?
623                                 ClassConstants.EXTERNAL_TYPE_FLOAT :
624             internalTypeChar == ClassConstants.INTERNAL_TYPE_LONG ?
625                                 ClassConstants.EXTERNAL_TYPE_LONG :
626             internalTypeChar == ClassConstants.INTERNAL_TYPE_DOUBLE ?
627                                 ClassConstants.EXTERNAL_TYPE_DOUBLE :
628             internalTypeChar == '%' ?
629                                 "%" :
630             internalTypeChar == ClassConstants.INTERNAL_TYPE_CLASS_START ?
631                                 externalClassName(internalType.substring(1, internalType.indexOf(ClassConstants.INTERNAL_TYPE_CLASS_END))) :
632                                 null;
633
634         if (externalType == null)
635         {
636             throw new IllegalArgumentException JavaDoc("Unknown type ["+internalType+"]");
637         }
638
639         // Append the array part, if any.
640
for (int count = 0; count < dimensionCount; count++)
641         {
642             externalType = externalType + ClassConstants.EXTERNAL_TYPE_ARRAY;
643         }
644
645         return externalType;
646     }
647
648
649     /**
650      * Returns whether the given internal descriptor String represents a method
651      * descriptor.
652      * @param internalDescriptor the internal descriptor String,
653      * e.g. "<code>(II)Z</code>".
654      * @return <code>true</code> if the given String is a method descriptor,
655      * <code>false</code> otherwise.
656      */

657     public static boolean isInternalMethodDescriptor(String JavaDoc internalDescriptor)
658     {
659         return internalDescriptor.charAt(0) == ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN;
660     }
661
662
663     /**
664      * Returns whether the given member String represents an external method
665      * name with arguments.
666      * @param externalMemberNameAndArguments the external member String,
667      * e.g. "<code>myField</code>" or
668      * e.g. "<code>myMethod(int,int)</code>".
669      * @return <code>true</code> if the given String refers to a method,
670      * <code>false</code> otherwise.
671      */

672     public static boolean isExternalMethodNameAndArguments(String JavaDoc externalMemberNameAndArguments)
673     {
674         return externalMemberNameAndArguments.indexOf(ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN) > 0;
675     }
676
677
678     /**
679      * Returns the name part of the given external method name and arguments.
680      * @param externalMethodNameAndArguments the external method name and arguments,
681      * e.g. "<code>myMethod(int,int)</code>".
682      * @return the name part of the String, e.g. "<code>myMethod</code>".
683      */

684     public static String JavaDoc externalMethodName(String JavaDoc externalMethodNameAndArguments)
685     {
686         externalTypeEnumeration.setDescriptor(externalMethodNameAndArguments);
687         return externalTypeEnumeration.methodName();
688     }
689
690
691     /**
692      * Converts the given external method return type and name and arguments to
693      * an internal method descriptor.
694      * @param externalReturnType the external method return type,
695      * e.g. "<code>boolean</code>".
696      * @param externalMethodNameAndArguments the external method name and arguments,
697      * e.g. "<code>myMethod(int,int)</code>".
698      * @return the internal method descriptor,
699      * e.g. "<code>(II)Z</code>".
700      */

701     public static String JavaDoc internalMethodDescriptor(String JavaDoc externalReturnType,
702                                                   String JavaDoc externalMethodNameAndArguments)
703     {
704         StringBuffer JavaDoc internalMethodDescriptor = new StringBuffer JavaDoc();
705         internalMethodDescriptor.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN);
706
707         externalTypeEnumeration.setDescriptor(externalMethodNameAndArguments);
708         while (externalTypeEnumeration.hasMoreTypes())
709         {
710             internalMethodDescriptor.append(internalType(externalTypeEnumeration.nextType()));
711         }
712
713         internalMethodDescriptor.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE);
714         internalMethodDescriptor.append(internalType(externalReturnType));
715
716         return internalMethodDescriptor.toString();
717     }
718
719
720     /**
721      * Converts the given external method return type and List of arguments to
722      * an internal method descriptor.
723      * @param externalReturnType the external method return type,
724      * e.g. "<code>boolean</code>".
725      * @param externalArguments the external method arguments,
726      * e.g. <code>{ "int", "int" }</code>.
727      * @return the internal method descriptor,
728      * e.g. "<code>(II)Z</code>".
729      */

730     public static String JavaDoc internalMethodDescriptor(String JavaDoc externalReturnType,
731                                                   List externalArguments)
732     {
733         StringBuffer JavaDoc internalMethodDescriptor = new StringBuffer JavaDoc();
734         internalMethodDescriptor.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN);
735
736         for (int index = 0; index < externalArguments.size(); index++)
737         {
738             internalMethodDescriptor.append(internalType((String JavaDoc)externalArguments.get(index)));
739         }
740
741         internalMethodDescriptor.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE);
742         internalMethodDescriptor.append(internalType(externalReturnType));
743
744         return internalMethodDescriptor.toString();
745     }
746
747
748     /**
749      * Converts an internal field description into an external full field description.
750      * @param accessFlags the access flags of the field.
751      * @param fieldName the field name,
752      * e.g. "<code>myField</code>".
753      * @param internalFieldDescriptor the internal field descriptor,
754      * e.g. "<code>Z</code>".
755      * @return the external full field description,
756      * e.g. "<code>public boolean myField</code>".
757      */

758     public static String JavaDoc externalFullFieldDescription(int accessFlags,
759                                                       String JavaDoc fieldName,
760                                                       String JavaDoc internalFieldDescriptor)
761     {
762         return externalFieldAccessFlags(accessFlags) +
763                externalType(internalFieldDescriptor) +
764                " " +
765                fieldName;
766     }
767
768
769     /**
770      * Converts an internal method description into an external full method description.
771      * @param internalClassName the internal name of the class of the method,
772      * e.g. "<code>mypackage/MyClass</code>".
773      * @param accessFlags the access flags of the method.
774      * @param internalMethodName the internal method name,
775      * e.g. "<code>myMethod</code>" or
776      * "<code>&lt;init&gt;</code>".
777      * @param internalMethodDescriptor the internal method descriptor,
778      * e.g. "<code>(II)Z</code>".
779      * @return the external full method description,
780      * e.g. "<code>public boolean myMethod(int,int)</code>" or
781      * "<code>public MyClass(int,int)</code>".
782      */

783     public static String JavaDoc externalFullMethodDescription(String JavaDoc internalClassName,
784                                                        int accessFlags,
785                                                        String JavaDoc internalMethodName,
786                                                        String JavaDoc internalMethodDescriptor)
787     {
788         return externalMethodAccessFlags(accessFlags) +
789                externalMethodReturnTypeAndName(internalClassName,
790                                                internalMethodName,
791                                                internalMethodDescriptor) +
792                ClassConstants.EXTERNAL_METHOD_ARGUMENTS_OPEN +
793                externalMethodArguments(internalMethodDescriptor) +
794                ClassConstants.EXTERNAL_METHOD_ARGUMENTS_CLOSE;
795     }
796
797
798     /**
799      * Converts internal class access flags into an external access description.
800      * @param accessFlags the class access flags.
801      * @return the external class access description,
802      * e.g. "<code>public final </code>".
803      */

804     public static String JavaDoc externalClassAccessFlags(int accessFlags)
805     {
806         return externalClassAccessFlags(accessFlags, "");
807     }
808
809
810     /**
811      * Converts internal class access flags into an external access description.
812      * @param accessFlags the class access flags.
813      * @param prefix a prefix that is added to each access modifier.
814      * @return the external class access description,
815      * e.g. "<code>public final </code>".
816      */

817     public static String JavaDoc externalClassAccessFlags(int accessFlags, String JavaDoc prefix)
818     {
819         if (accessFlags == 0)
820         {
821             return EMPTY_STRING;
822         }
823
824         StringBuffer JavaDoc string = new StringBuffer JavaDoc(50);
825
826         if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) != 0)
827         {
828             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(" ");
829         }
830         if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0)
831         {
832             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(" ");
833         }
834         if ((accessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) != 0)
835         {
836             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_INTERFACE).append(" ");
837         }
838         else if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0)
839         {
840             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ABSTRACT).append(" ");
841         }
842
843         return string.toString();
844     }
845
846
847     /**
848      * Converts internal field access flags into an external access description.
849      * @param accessFlags the field access flags.
850      * @return the external field access description,
851      * e.g. "<code>public volatile </code>".
852      */

853     public static String JavaDoc externalFieldAccessFlags(int accessFlags)
854     {
855         return externalFieldAccessFlags(accessFlags, "");
856     }
857
858
859     /**
860      * Converts internal field access flags into an external access description.
861      * @param accessFlags the field access flags.
862      * @param prefix a prefix that is added to each access modifier.
863      * @return the external field access description,
864      * e.g. "<code>public volatile </code>".
865      */

866     public static String JavaDoc externalFieldAccessFlags(int accessFlags, String JavaDoc prefix)
867     {
868         if (accessFlags == 0)
869         {
870             return EMPTY_STRING;
871         }
872
873         StringBuffer JavaDoc string = new StringBuffer JavaDoc(50);
874
875         if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) != 0)
876         {
877             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(" ");
878         }
879         if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0)
880         {
881             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PRIVATE).append(" ");
882         }
883         if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0)
884         {
885             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PROTECTED).append(" ");
886         }
887         if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0)
888         {
889             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STATIC).append(" ");
890         }
891         if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0)
892         {
893             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(" ");
894         }
895         if ((accessFlags & ClassConstants.INTERNAL_ACC_VOLATILE) != 0)
896         {
897             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_VOLATILE).append(" ");
898         }
899         if ((accessFlags & ClassConstants.INTERNAL_ACC_TRANSIENT) != 0)
900         {
901             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_TRANSIENT).append(" ");
902         }
903
904         return string.toString();
905     }
906
907
908     /**
909      * Converts internal method access flags into an external access description.
910      * @param accessFlags the method access flags.
911      * @return the external method access description,
912      * e.g. "<code>public synchronized </code>".
913      */

914     public static String JavaDoc externalMethodAccessFlags(int accessFlags)
915     {
916         return externalMethodAccessFlags(accessFlags, "");
917     }
918
919
920     /**
921      * Converts internal method access flags into an external access description.
922      * @param accessFlags the method access flags.
923      * @param prefix a prefix that is added to each access modifier.
924      * @return the external method access description,
925      * e.g. "public synchronized ".
926      */

927     public static String JavaDoc externalMethodAccessFlags(int accessFlags, String JavaDoc prefix)
928     {
929         if (accessFlags == 0)
930         {
931             return EMPTY_STRING;
932         }
933
934         StringBuffer JavaDoc string = new StringBuffer JavaDoc(50);
935
936         if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) != 0)
937         {
938             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(" ");
939         }
940         if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0)
941         {
942             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PRIVATE).append(" ");
943         }
944         if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0)
945         {
946             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PROTECTED).append(" ");
947         }
948         if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0)
949         {
950             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STATIC).append(" ");
951         }
952         if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0)
953         {
954             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(" ");
955         }
956         if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNCHRONIZED) != 0)
957         {
958             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED).append(" ");
959         }
960         if ((accessFlags & ClassConstants.INTERNAL_ACC_NATIVE) != 0)
961         {
962             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_NATIVE).append(" ");
963         }
964         if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0)
965         {
966             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ABSTRACT).append(" ");
967         }
968         if ((accessFlags & ClassConstants.INTERNAL_ACC_STRICT) != 0)
969         {
970             string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STRICT).append(" ");
971         }
972
973         return string.toString();
974     }
975
976
977     /**
978      * Converts an internal method descriptor into an external method return type.
979      * @param internalMethodDescriptor the internal method descriptor,
980      * e.g. "<code>(II)Z</code>".
981      * @return the external method return type,
982      * e.g. "<code>boolean</code>".
983      */

984     public static String JavaDoc externalMethodReturnType(String JavaDoc internalMethodDescriptor)
985     {
986         return externalType(internalMethodReturnType(internalMethodDescriptor));
987     }
988
989
990     /**
991      * Converts an internal class name, method name, and method descriptor to
992      * an external method return type and name.
993      * @param internalClassName the internal name of the class of the method,
994      * e.g. "<code>mypackage/MyClass</code>".
995      * @param internalMethodName the internal method name,
996      * e.g. "<code>myMethod</code>" or
997      * "<code>&lt;init&gt;</code>".
998      * @param internalMethodDescriptor the internal method descriptor,
999      * e.g. "<code>(II)Z</code>".
1000     * @return the external method return type and name,
1001     * e.g. "<code>boolean myMethod</code>" or
1002     * "<code>MyClass</code>".
1003     */

1004    private static String JavaDoc externalMethodReturnTypeAndName(String JavaDoc internalClassName,
1005                                                          String JavaDoc internalMethodName,
1006                                                          String JavaDoc internalMethodDescriptor)
1007    {
1008        return internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ?
1009            externalShortClassName(externalClassName(internalClassName)) :
1010            (externalMethodReturnType(internalMethodDescriptor) +
1011             " " +
1012             internalMethodName);
1013    }
1014
1015
1016    /**
1017     * Converts an internal method descriptor into an external method argument
1018     * description.
1019     * @param internalMethodDescriptor the internal method descriptor,
1020     * e.g. "<code>(II)Z</code>".
1021     * @return the external method argument description,
1022     * e.g. "<code>int,int</code>".
1023     */

1024    public static String JavaDoc externalMethodArguments(String JavaDoc internalMethodDescriptor)
1025    {
1026        StringBuffer JavaDoc externalMethodNameAndArguments = new StringBuffer JavaDoc();
1027
1028        internalTypeEnumeration.setDescriptor(internalMethodDescriptor);
1029        while (internalTypeEnumeration.hasMoreTypes())
1030        {
1031            externalMethodNameAndArguments.append(externalType(internalTypeEnumeration.nextType()));
1032            if (internalTypeEnumeration.hasMoreTypes())
1033            {
1034                externalMethodNameAndArguments.append(ClassConstants.EXTERNAL_METHOD_ARGUMENTS_SEPARATOR);
1035            }
1036        }
1037
1038        return externalMethodNameAndArguments.toString();
1039    }
1040
1041
1042    /**
1043     * Returns the internal package name of the given internal class name.
1044     * @param internalClassName the internal class name,
1045     * e.g. "<code>java/lang/Object</code>".
1046     * @return the internal package name,
1047     * e.g. "<code>java/lang</code>".
1048     */

1049    public static String JavaDoc internalPackageName(String JavaDoc internalClassName)
1050    {
1051        String JavaDoc internalPackagePrefix = internalPackagePrefix(internalClassName);
1052        int length = internalPackagePrefix.length();
1053        return length > 0 ?
1054            internalPackagePrefix.substring(0, length - 1) :
1055            "";
1056    }
1057
1058
1059    /**
1060     * Returns the internal package prefix of the given internal class name.
1061     * @param internalClassName the internal class name,
1062     * e.g. "<code>java/lang/Object</code>".
1063     * @return the internal package prefix,
1064     * e.g. "<code>java/lang/</code>".
1065     */

1066    public static String JavaDoc internalPackagePrefix(String JavaDoc internalClassName)
1067    {
1068        return internalClassName.substring(0, internalClassName.lastIndexOf(ClassConstants.INTERNAL_PACKAGE_SEPARATOR,
1069                                                                            internalClassName.length() - 2) + 1);
1070    }
1071
1072
1073    /**
1074     * Returns the external package name of the given external class name.
1075     * @param externalClassName the external class name,
1076     * e.g. "<code>java.lang.Object</code>".
1077     * @return the external package name,
1078     * e.g. "<code>java.lang</code>".
1079     */

1080    public static String JavaDoc externalPackageName(String JavaDoc externalClassName)
1081    {
1082        String JavaDoc externalPackagePrefix = externalPackagePrefix(externalClassName);
1083        int length = externalPackagePrefix.length();
1084        return length > 0 ?
1085            externalPackagePrefix.substring(0, length - 1) :
1086            "";
1087    }
1088
1089
1090    /**
1091     * Returns the external package prefix of the given external class name.
1092     * @param externalClassName the external class name,
1093     * e.g. "<code>java.lang.Object</code>".
1094     * @return the external package prefix,
1095     * e.g. "<code>java.lang.</code>".
1096     */

1097    public static String JavaDoc externalPackagePrefix(String JavaDoc externalClassName)
1098    {
1099        return externalClassName.substring(0, externalClassName.lastIndexOf(ClassConstants.EXTERNAL_PACKAGE_SEPARATOR,
1100                                                                            externalClassName.length() - 2) + 1);
1101    }
1102}
1103
Popular Tags