KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > usages > ClassFileUtil


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.java.source.usages;
21
22 import com.sun.tools.javac.code.Symbol;
23 import com.sun.tools.javac.util.Convert;
24 import com.sun.tools.javac.util.Name;
25 import java.util.Collection JavaDoc;
26 import java.util.EnumSet JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.Set JavaDoc;
30 import javax.lang.model.element.Element;
31 import javax.lang.model.element.ElementKind;
32 import javax.lang.model.element.ExecutableElement;
33 import javax.lang.model.element.TypeElement;
34 import javax.lang.model.element.VariableElement;
35 import javax.lang.model.type.ArrayType;
36 import javax.lang.model.type.DeclaredType;
37 import javax.lang.model.type.ErrorType;
38 import javax.lang.model.type.TypeKind;
39 import javax.lang.model.type.TypeMirror;
40 import javax.lang.model.type.TypeVariable;
41 import org.netbeans.modules.classfile.ByteCodes;
42 import org.netbeans.modules.classfile.CPClassInfo;
43 import org.netbeans.modules.classfile.CPFieldInfo;
44 import org.netbeans.modules.classfile.CPMethodInfo;
45 import org.netbeans.modules.classfile.ClassName;
46 import org.netbeans.modules.classfile.Code;
47 import org.netbeans.modules.classfile.ConstantPool;
48 import org.netbeans.modules.classfile.Method;
49
50 /**
51  *
52  * @author Tomas Zezula
53  */

54 public class ClassFileUtil {
55     
56     private static final Set JavaDoc<ElementKind> TYPE_DECLS = EnumSet.of(ElementKind.CLASS, ElementKind.INTERFACE, ElementKind.ENUM, ElementKind.ANNOTATION_TYPE);
57     
58     /** Creates a new instance of ClassFileUtil */
59     private ClassFileUtil() {
60     }
61     
62     
63     public static boolean accessesFiledOrMethod (final String JavaDoc[] fieldInfo, final String JavaDoc[] methodInfo, final Code c, final ConstantPool cp) {
64         BytecodeDecoder bd = new BytecodeDecoder (c.getByteCodes());
65         for (byte[] iw : bd) {
66             switch (((int)iw[0]&0xff)) {
67                 case ByteCodes.bc_putstatic:
68                 case ByteCodes.bc_getstatic:
69                 case ByteCodes.bc_putfield:
70                 case ByteCodes.bc_getfield:
71                     if (fieldInfo != null) {
72                         int cpIndex = BytecodeDecoder.toInt(iw[1],iw[2]);
73                         CPFieldInfo cpFieldInfo = (CPFieldInfo) cp.get(cpIndex);
74                         String JavaDoc className = cpFieldInfo.getClassName().getInternalName();
75                         String JavaDoc fieldName = cpFieldInfo.getFieldName();
76                         String JavaDoc signature = cpFieldInfo.getDescriptor();
77                         if (fieldInfo[0].equals(className) &&
78                             (fieldInfo[1] == null || (fieldInfo[1].equals(fieldName) && fieldInfo[2].equals(signature)))) {
79                             return true;
80                         }
81                     }
82                     break;
83                 case ByteCodes.bc_invokevirtual:
84                 case ByteCodes.bc_invokestatic:
85                 case ByteCodes.bc_invokeinterface:
86                 case ByteCodes.bc_invokespecial:
87                     if (methodInfo != null) {
88                         int cpIndex = BytecodeDecoder.toInt(iw[1],iw[2]);
89                         CPMethodInfo cpMethodInfo = (CPMethodInfo) cp.get(cpIndex);
90                         String JavaDoc className = cpMethodInfo.getClassName().getInternalName();
91                         String JavaDoc methodName = cpMethodInfo.getMethodName();
92                         String JavaDoc signature = cpMethodInfo.getDescriptor();
93                         if (methodInfo[0].equals(className) &&
94                             (methodInfo[1] == null || (methodInfo[1].equals(methodName) && methodInfo[2].equals(signature)))) {
95                             return true;
96                         }
97                     }
98                     break;
99             }
100         }
101         return false;
102     }
103     
104     public static boolean accessesFiledOrMethod (final String JavaDoc[] fieldInfo, final String JavaDoc[] methodInfo, final Method m) {
105         Code c = m.getCode();
106         if (c != null) {
107             ConstantPool cp = m.getClassFile().getConstantPool();
108             return accessesFiledOrMethod(fieldInfo,methodInfo, c, cp);
109         }
110         else {
111             return false;
112         }
113     }
114     
115     public static <T extends Method> Collection JavaDoc<T> accessesFiled (final String JavaDoc[] fieldInfo, final Collection JavaDoc<T> methods) {
116         Collection JavaDoc<T> result = new LinkedList JavaDoc<T> ();
117         for (T m : methods) {
118             if (accessesFiledOrMethod(fieldInfo,null,m)) {
119                 result.add(m);
120             }
121         }
122         return result;
123     }
124     
125     public static <T extends Method> Collection JavaDoc<T> callsMethod (final String JavaDoc[] methodInfo, final Collection JavaDoc<T> methods) {
126         Collection JavaDoc<T> result = new LinkedList JavaDoc<T> ();
127         for (T m : methods) {
128             if (accessesFiledOrMethod(null,methodInfo,m)) {
129                 result.add(m);
130             }
131         }
132         return result;
133     }
134     
135     
136     public static String JavaDoc[] createFieldDescriptor (final VariableElement ve) {
137     assert ve != null;
138         String JavaDoc[] result = new String JavaDoc[3];
139     Element enclosingElement = ve.getEnclosingElement();
140     assert enclosingElement instanceof TypeElement;
141         result[0] = encodeClassNameOrArray ((TypeElement) enclosingElement);
142         result[1] = ve.getSimpleName().toString();
143         StringBuilder JavaDoc sb = new StringBuilder JavaDoc ();
144         encodeType(ve.asType(),sb);
145         result[2] = sb.toString();
146         return result;
147     }
148     
149     public static String JavaDoc[] createExecutableDescriptor (final ExecutableElement ee) {
150         assert ee != null;
151         final String JavaDoc[] result = new String JavaDoc[3];
152         final Element enclosingType = ee.getEnclosingElement();
153     assert enclosingType instanceof TypeElement;
154         result[0] = encodeClassNameOrArray ((TypeElement)enclosingType);
155         final ElementKind kind = ee.getKind();
156         if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
157             final StringBuilder JavaDoc retType = new StringBuilder JavaDoc ();
158             if (kind == ElementKind.METHOD) {
159                 result[1] = ee.getSimpleName().toString();
160                 encodeType(ee.getReturnType(), retType);
161             }
162             else {
163                 result[1] = "<init>"; // NOI18N
164
retType.append('V'); // NOI18N
165
}
166             StringBuilder JavaDoc sb = new StringBuilder JavaDoc ();
167             sb.append('('); // NOI18N
168
for (VariableElement pd : ee.getParameters()) {
169                 encodeType(pd.asType(),sb);
170             }
171             sb.append(')'); // NOI18N
172
sb.append(retType);
173             result[2] = sb.toString();
174         }
175         else if (kind == ElementKind.INSTANCE_INIT) {
176             result[1] = "<init>"; // NOI18N
177
}
178         else if (kind == ElementKind.STATIC_INIT) {
179             result[1] = "<cinit>"; // NOI18N
180
}
181         else {
182             throw new IllegalArgumentException JavaDoc ();
183         }
184         return result;
185     }
186     
187     public static String JavaDoc encodeClassNameOrArray (TypeElement td) {
188         assert td != null;
189         CharSequence JavaDoc qname = td.getQualifiedName();
190         if (qname != null && "Array".contentEquals(qname) && td.getEnclosingElement().asType().getKind() == TypeKind.NONE) { //NOI18N
191
return "["; //NOI18N
192
}
193         else {
194             return encodeClassName(td);
195         }
196     }
197     
198     public static String JavaDoc encodeClassName (TypeElement td) {
199         assert td != null;
200         StringBuilder JavaDoc sb = new StringBuilder JavaDoc ();
201         encodeClassName(td, sb,'.'); // NOI18N
202
return sb.toString();
203     }
204     
205     private static void encodeType (final TypeMirror type, final StringBuilder JavaDoc sb) {
206     switch (type.getKind()) {
207         case VOID:
208         sb.append('V'); // NOI18N
209
break;
210         case BOOLEAN:
211         sb.append('Z'); // NOI18N
212
break;
213         case BYTE:
214         sb.append('B'); // NOI18N
215
break;
216         case SHORT:
217         sb.append('S'); // NOI18N
218
break;
219         case INT:
220         sb.append('I'); // NOI18N
221
break;
222         case LONG:
223         sb.append('J'); // NOI18N
224
break;
225         case CHAR:
226         sb.append('C'); // NOI18N
227
break;
228         case FLOAT:
229         sb.append('F'); // NOI18N
230
break;
231         case DOUBLE:
232         sb.append('D'); // NOI18N
233
break;
234         case ARRAY:
235         sb.append('['); // NOI18N
236
assert type instanceof ArrayType;
237         encodeType(((ArrayType)type).getComponentType(),sb);
238         break;
239         case DECLARED:
240             {
241         sb.append('L'); // NOI18N
242
TypeElement te = (TypeElement) ((DeclaredType)type).asElement();
243         encodeClassName(te, sb,'/');
244         sb.append(';'); // NOI18N
245
break;
246             }
247         case TYPEVAR:
248             {
249         assert type instanceof TypeVariable;
250         TypeVariable tr = (TypeVariable) type;
251         TypeMirror upperBound = tr.getUpperBound();
252         if (upperBound.getKind() == TypeKind.NULL) {
253             sb.append ("Ljava/lang/Object;"); // NOI18N
254
}
255         else {
256             encodeType(upperBound, sb);
257         }
258         break;
259             }
260             case ERROR:
261             {
262                 TypeElement te = (TypeElement) ((ErrorType)type).asElement();
263                 if (te != null) {
264                     sb.append('L');
265                     encodeClassName(te, sb,'/');
266                     sb.append(';'); // NOI18N
267
break;
268                 }
269             }
270         default:
271         throw new IllegalArgumentException JavaDoc ();
272     }
273     }
274     
275     static char[] nameChars = new char[512]; //Initial storage
276

277     
278     public static void encodeClassName (TypeElement te, final StringBuilder JavaDoc sb, final char separator) {
279         Name name = ((Symbol.ClassSymbol)te).flatname;
280         assert name != null;
281         int nameLength = name.len;
282         if (nameChars.length < nameLength) {
283             nameChars = new char[nameLength];
284         }
285         Convert.utf2chars(name.table.names, name.index, nameChars, 0, nameLength);
286         if (separator != '.') { //NOI18N
287
for (int i=0; i<nameLength; i++) {
288                 if (nameChars[i] == '.') { //NOI18N
289
nameChars[i] = separator;
290                 }
291             }
292         }
293         sb.append(nameChars,0,nameLength);
294     }
295     
296     /**
297      * Returns ClassName for jvmType which represents a classref
298      * otherwise it returns null;
299      */

300     public static ClassName getType (final String JavaDoc jvmTypeId) {
301         //Both L... (classref) and [L... (array of classref) are important
302
if (jvmTypeId.length()<2) {
303             return null; // no classref - simple types
304
}
305         else if (jvmTypeId.charAt(0) == 'L') {
306             //classref
307
return ClassName.getClassName(jvmTypeId);
308         }
309         else if (jvmTypeId.charAt(0) == '[') {
310             //Array of classref
311
return getType (jvmTypeId.substring(1));
312         }
313         //No classref - array of simple types
314
return null;
315     }
316     
317     public static ClassName getType (final CPClassInfo ci) {
318         String JavaDoc type = ci.getName();
319         if (type.charAt(0)=='[') { //NOI18N
320
return getType(type);
321         }
322         else {
323             return ci.getClassName();
324         }
325     }
326     
327     public static ClassName[] getTypesFromMethodTypeSignature (final String JavaDoc jvmTypeId) {
328         Set JavaDoc<ClassName> result = new HashSet JavaDoc<ClassName> ();
329         methodTypeSignature (jvmTypeId, new int[] {0}, result);
330         return result.toArray(new ClassName[result.size()]);
331     }
332     
333     public static ClassName[] getTypesFromFiledTypeSignature (final String JavaDoc jvmTypeId) {
334         Set JavaDoc<ClassName> result = new HashSet JavaDoc<ClassName> ();
335         typeSignatureType (jvmTypeId, new int[] {0}, result, false);
336         return result.toArray(new ClassName[result.size()]);
337     }
338     
339     public static ClassName[] getTypesFromClassTypeSignature (final String JavaDoc jvmTypeId) {
340         Set JavaDoc<ClassName> result = new HashSet JavaDoc<ClassName> ();
341         classTypeSignature (jvmTypeId, new int[] {0}, result);
342         return result.toArray(new ClassName[result.size()]);
343     }
344     
345     private static char getChar (final String JavaDoc buffer, final int pos) {
346         if (pos>=buffer.length()) {
347             throw new IllegalStateException JavaDoc ();
348         }
349         return buffer.charAt(pos);
350     }
351     
352     private static void classTypeSignature (final String JavaDoc jvmTypeId, final int[] pos, final Set JavaDoc<ClassName> s) {
353         char c = getChar (jvmTypeId, pos[0]);
354         if (c == '<') {
355             formalTypeParameters (jvmTypeId, pos, s);
356             c = getChar (jvmTypeId, pos[0]);
357         }
358         typeSignatureType (jvmTypeId, pos, s, false);
359         while (pos[0]<jvmTypeId.length()) {
360             typeSignatureType (jvmTypeId, pos, s, false);
361         }
362     }
363     
364     private static void methodTypeSignature (final String JavaDoc jvmTypeId, final int[] pos, final Set JavaDoc<ClassName> s) {
365         char c = getChar (jvmTypeId, pos[0]);
366         if (c == '<') {
367             formalTypeParameters (jvmTypeId, pos, s);
368             c = getChar (jvmTypeId, pos[0]);
369         }
370         if (c!='(') {
371             throw new IllegalStateException JavaDoc (jvmTypeId);
372         }
373         pos[0]++;
374         c = getChar (jvmTypeId, pos[0]);
375         while (c != ')') {
376             typeSignatureType (jvmTypeId, pos, s, false);
377             c = getChar (jvmTypeId, pos[0]);
378         }
379         pos[0]++;
380         typeSignatureType (jvmTypeId, pos, s, false); //returnType
381
//Todo: Exceptions
382
}
383     
384     
385     private static void formalTypeParam (final String JavaDoc jvmTypeId, final int[] pos, final Set JavaDoc<ClassName> s) {
386         //Identifier:[className][:ifaceName]*
387
char c;
388         do {
389             c = getChar(jvmTypeId, pos[0]++);
390         } while (c!=':');
391         c = getChar(jvmTypeId, pos[0]);
392         if (c !=':') {
393             typeSignatureType(jvmTypeId, pos, s, true);
394             c = getChar (jvmTypeId, pos[0]);
395         }
396         while (c == ':') {
397             pos[0]++;
398             typeSignatureType(jvmTypeId, pos, s, true);
399             c = getChar (jvmTypeId, pos[0]);
400         }
401     }
402     
403     
404     
405     private static void formalTypeParameters (final String JavaDoc jvmTypeId, final int[] pos, final Set JavaDoc<ClassName> s) {
406         char c = getChar(jvmTypeId, pos[0]++);
407         if (c != '<') {
408             throw new IllegalArgumentException JavaDoc (jvmTypeId);
409         }
410         c = getChar (jvmTypeId, pos[0]);
411         while (c !='>') {
412             formalTypeParam (jvmTypeId, pos, s);
413             c = getChar (jvmTypeId, pos[0]);
414         }
415         pos[0]++;
416     }
417     
418     private static void typeArgument (final String JavaDoc jvmTypeId, final int[] pos, final Set JavaDoc<ClassName> s) {
419         char c = getChar (jvmTypeId, pos[0]);
420         if (c == '*') {
421             pos[0]++;
422             return;
423         }
424         else if (c == '+' || c == '-') {
425             pos[0]++;
426             typeSignatureType (jvmTypeId, pos, s, true);
427         }
428         else {
429             typeSignatureType (jvmTypeId, pos, s, true);
430         }
431     }
432     
433     
434     private static void typeArgumentsList (final String JavaDoc jvmTypeId, final int[] pos, final Set JavaDoc<ClassName> s) {
435         char c = getChar (jvmTypeId, pos[0]++);
436         if (c != '<') {
437             throw new IllegalStateException JavaDoc (jvmTypeId);
438         }
439         c = getChar (jvmTypeId, pos[0]);
440         while (c !='>') {
441             typeArgument (jvmTypeId, pos, s);
442             c = getChar (jvmTypeId, pos[0]);
443         }
444         pos[0]++;
445     }
446
447     private static void typeSignatureType (final String JavaDoc jvmTypeId, final int[] pos, final Set JavaDoc<ClassName> s, boolean add) {
448         char c = getChar(jvmTypeId, pos[0]++);
449         switch (c) {
450             case 'B':
451             case 'C':
452             case 'D':
453             case 'F':
454             case 'I':
455             case 'J':
456             case 'S':
457             case 'V':
458             case 'Z':
459                 //Do nothing
460
break;
461             case 'L':
462                 StringBuilder JavaDoc builder = new StringBuilder JavaDoc ();
463                 do {
464                     builder.append (c);
465                     c = getChar(jvmTypeId, pos[0]);
466                     if (c=='<') {
467                         typeArgumentsList (jvmTypeId,pos, s);
468                         c = getChar(jvmTypeId, pos[0]++); //;
469
}
470                     else {
471                         pos[0]++;
472                     }
473                 } while (c != ';');
474                 builder.append (c);
475                 if (add) {
476                     s.add(ClassName.getClassName(builder.toString()));
477                 }
478                 break;
479             case 'T':
480                 do {
481                     c = getChar(jvmTypeId, pos[0]++);
482                 } while (c != ';');
483                 break;
484             case '[':
485                 typeSignatureType (jvmTypeId, pos, s, add);
486                 break;
487         }
488     }
489     
490 }
491
Popular Tags