KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sli > kim > classfile > ClassFileReader


1
2 package sli.kim.classfile;
3
4 import java.io.*;
5
6 /**
7 * This class parses java class files and stores the information in a ClassInfo object.
8 *
9 * @see ClassInfo
10 */

11 public class ClassFileReader implements AccessFlags {
12     /**
13     * Read in and parse a java class file.
14     *
15     * @param in a DataInput stream to read in the class file.
16     * @param classInfo a ClassInfo to consume the class information.
17     * @throws ClassFileParseException if the class file is corrupt.
18     * @throws IOException if the InputStream throws an IOException.
19     */

20     public void read(InputStream in, ClassInfo classInfo)
21         throws ClassFileParseException, IOException
22     {
23         readClass(new DataInputStream(new BufferedInputStream(in)), classInfo);
24     }
25
26     private void readClass(DataInput in, ClassInfo classInfo)
27         throws ClassFileParseException, IOException
28     {
29         short count;
30
31         // Magic And Version Numbers
32
{
33             int magic = in.readInt();
34             if (magic != 0xCAFEBABE)
35                 throw new ClassFileParseException("Invalid classfile magic number" +
36                     ": expected 0xCAFEBABE, found 0x" + Integer.toHexString(magic));
37             short major = in.readShort(), minor = in.readShort();
38             // assume we can handle changes to the minor version number
39
if (major != 0x003)
40                 throw new ClassFileParseException("Unrecognized classfile version " +
41                     major + "." + minor);
42         }
43
44         // Constant Pool
45
ConstPool cp = new ConstPool();
46         cp.read(in);
47         classInfo.setConstPool(cp);
48
49         // General Class Info
50
{
51             short flags = in.readShort();
52             short classIndex = in.readShort();
53             short superClassIndex = in.readShort();
54             short classNameIndex = cp.getEntryAtIndex(classIndex).getClassNameIndex();
55             short superClassNameIndex = cp.getEntryAtIndex(superClassIndex).getClassNameIndex();
56             String JavaDoc className = cp.getEntryAtIndex(classNameIndex).getString();
57             String JavaDoc superClassName = cp.getEntryAtIndex(superClassNameIndex).getString();
58
59             if (Debug.readClass != null) Debug.println(Debug.readClass,
60                 "flags=" + flags +
61                 "; class index=" + classIndex +
62                 "; super class index=" + superClassIndex);
63
64             classInfo.setAccessFlags(flags);
65             classInfo.setName(className);
66             classInfo.setSuperClassName(superClassName);
67         }
68
69         // Interfaces
70
count = in.readShort();
71         if (Debug.readClass != null) Debug.println(Debug.readClass,
72             "#interfaces=" + count);
73         Debug.indent();
74         for (int i = 0; i < count; i++)
75             classInfo.addInterface(readInterface(cp, in));
76         Debug.outdent();
77
78         // Fields
79
count = in.readShort();
80         if (Debug.readClass != null) Debug.println(Debug.readClass,
81             "#fields=" + count);
82         Debug.indent();
83         for (int i = 0; i < count; i++)
84             classInfo.addField(readField(cp, in));
85         Debug.outdent();
86
87         // Methods
88
count = in.readShort();
89         if (Debug.readClass != null) Debug.println(Debug.readClass,
90             "#methods=" + count);
91         Debug.indent();
92         for (int i = 0; i < count; i++)
93             classInfo.addMethod(readMethod(cp, in));
94         Debug.outdent();
95
96         // Attributes
97
count = in.readShort();
98         if (Debug.readClass != null) Debug.println(Debug.readClass,
99             "#attributes=" + count);
100         Debug.indent();
101         for (int i = 0; i < count; i++)
102             readClassAttribute(classInfo, cp, in);
103         Debug.outdent();
104     }
105
106     private String JavaDoc readInterface(ConstPool cp, DataInput in)
107         throws IOException
108     {
109         short classIndex = in.readShort();
110         if (Debug.readInterface != null) Debug.println(Debug.readInterface,
111             "class index=" + classIndex);
112         short nameIndex = cp.getEntryAtIndex(classIndex).getClassNameIndex();
113         return cp.getEntryAtIndex(nameIndex).getString();
114     }
115
116     private FieldInfo readField(ConstPool cp, DataInput in)
117         throws ClassFileParseException, IOException
118     {
119         FieldInfo result;
120
121         // General Field Info
122
{
123             short flags = in.readShort();
124             short nameIndex = in.readShort();
125             short signatureIndex = in.readShort();
126
127             if (Debug.readField != null) Debug.println(Debug.readField,
128                 "flags=" + flags +
129                 "; name index=" + nameIndex +
130                 "; signature index=" + signatureIndex);
131
132             result = new FieldInfo(flags, cp.getEntryAtIndex(nameIndex).getString(),
133                 cp.getEntryAtIndex(signatureIndex).getString());
134         }
135     
136         // Field Attributes
137
short numAttributes = in.readShort();
138         if (Debug.readField != null) Debug.println(Debug.readField,
139             "#attributes=" + numAttributes);
140         Debug.indent();
141         for (int i = 0; i < numAttributes; i++)
142             readFieldAttribute(result, cp, in);
143         Debug.outdent();
144
145         return result;
146     }
147
148     private MethodInfo readMethod(ConstPool cp, DataInput in)
149         throws ClassFileParseException, IOException
150     {
151         MethodInfo result;
152
153         // General Method Info
154
{
155             short flags = in.readShort();
156             short nameIndex = in.readShort();
157             short signatureIndex = in.readShort();
158             String JavaDoc methodName = cp.getEntryAtIndex(nameIndex).getString();
159             String JavaDoc methodSignature = cp.getEntryAtIndex(signatureIndex).getString();
160
161             if (Debug.readMethod != null) Debug.println(Debug.readMethod,
162                 "flags=" + flags +
163                 "; name index=" + nameIndex +
164                 "; signature index=" + signatureIndex);
165
166             result = new MethodInfo(flags, methodName, methodSignature);
167         }
168
169         // Method Attributes
170
short methodAttrCount = in.readShort();
171         if (Debug.readMethod != null) Debug.println(Debug.readMethod,
172             "#attributes=" + methodAttrCount);
173         Debug.indent();
174
175         for (int iMethodAttr = 0; iMethodAttr < methodAttrCount; iMethodAttr++)
176             readMethodAttribute(result, cp, in);
177
178         Debug.outdent();
179
180         return result;
181     }
182
183     private void readClassAttribute(ClassInfo classInfo, ConstPool cp,
184         DataInput in) throws IOException
185     {
186         short nameIndex = in.readShort();
187         int length = in.readInt();
188
189         // make sure we read the entire attribute -- if it has bad data,
190
// an exception might get thrown before we've read it all
191
byte[] bytes = new byte[length];
192         in.readFully(bytes);
193         in = new DataInputStream(new ByteArrayInputStream(bytes));
194
195         if (Debug.readClass != null) Debug.println(Debug.readClass,
196             "attribute name index=" + nameIndex +
197             "; length=" + length);
198         Debug.indent();
199
200         try {
201
202             String JavaDoc name = cp.getEntryAtIndex(nameIndex).getString();
203
204             // SourceFile Attribute
205
if (name.equals("SourceFile")) {
206                 short filenameIndex = in.readShort();
207                 if (Debug.readClass != null) Debug.println(Debug.readClass,
208                     "filename index=" + filenameIndex);
209                 classInfo.setSourceFile(cp.getEntryAtIndex(filenameIndex).getString());
210             }
211
212             else if (name.equals("InnerClasses"))
213                 classInfo.setInnerClasses(readInnerClasses(cp, in));
214
215             else
216                 classInfo.addAttribute(readUnknownAttribute(name, length, in));
217
218         } catch (ConstPoolEntryError e) {
219             if (Debug.readBadData != null) Debug.println(Debug.readBadData,
220                 "class attribute name index=" + nameIndex);
221         }
222
223         Debug.outdent();
224     }
225
226     private void readFieldAttribute(FieldInfo fieldInfo, ConstPool cp,
227         DataInput in) throws IOException
228     {
229         short nameIndex = in.readShort();
230         String JavaDoc name = cp.getEntryAtIndex(nameIndex).getString();
231         int length = in.readInt();
232
233         // make sure we read the entire attribute -- if it has bad data,
234
// an exception might get thrown before we've read it all
235
byte[] bytes = new byte[length];
236         in.readFully(bytes);
237         in = new DataInputStream(new ByteArrayInputStream(bytes));
238
239         if (Debug.readField != null) Debug.println(Debug.readField,
240             "attribute name index=" + nameIndex +
241             "; length=" + length);
242         Debug.indent();
243
244         try {
245
246             // ConstantValue Attribute
247
if (name.equals("ConstantValue")) {
248                 short cvIndex = in.readShort();
249                 if (Debug.readField != null) Debug.println(Debug.readField,
250                     "constant value index=" + cvIndex);
251                 fieldInfo.setConstantValue(cp.getEntryAtIndex(cvIndex).getPrimitiveTypeValue());
252             }
253
254             else if (name.equals("Synthetic")) {
255                 if (Debug.readField != null) Debug.println(Debug.readField,
256                     "synthetic");
257                 fieldInfo.setSynthetic(true);
258             }
259
260             else
261                 fieldInfo.addAttribute(readUnknownAttribute(name, length, in));
262
263         } catch (ConstPoolEntryError e) {
264             if (Debug.readBadData != null) Debug.println(Debug.readBadData,
265                 "field attribute name index=" + nameIndex);
266         }
267
268         Debug.outdent();
269     }
270
271     private void readMethodAttribute(MethodInfo methodInfo, ConstPool cp,
272         DataInput in) throws IOException
273     {
274         short nameIndex = in.readShort();
275         int length = in.readInt();
276
277         // make sure we read the entire attribute -- if it has bad data,
278
// an exception might get thrown before we've read it all
279
byte[] bytes = new byte[length];
280         in.readFully(bytes);
281         in = new DataInputStream(new ByteArrayInputStream(bytes));
282
283         if (Debug.readMethod != null) Debug.println(Debug.readMethod,
284             "attribute name index=" + nameIndex +
285             "; length=" + length);
286         Debug.indent();
287
288         try {
289
290             String JavaDoc name = cp.getEntryAtIndex(nameIndex).getString();
291             if (name.equals("Exceptions")) {
292                 int count = in.readShort();
293                 for (int i = 0; i < count; i++) {
294                     short exceptionClassIndex = in.readShort();
295                     short exceptionClassNameIndex = cp.getEntryAtIndex(exceptionClassIndex).getClassNameIndex();
296                     String JavaDoc exceptionName = cp.getEntryAtIndex(exceptionClassNameIndex). getString();
297                     methodInfo.addException(exceptionName);
298                 }
299             }
300
301             else if (name.equals("Code"))
302                 methodInfo.setCodeInfo(readCode(cp, in));
303
304             else if (name.equals("Deprecated")) {
305                 if (Debug.readMethod != null) Debug.println(Debug.readMethod,
306                     "deprecated");
307                 methodInfo.setDeprecated(true);
308             }
309
310             else
311                 methodInfo.addAttribute(readUnknownAttribute(name, length, in));
312
313         } catch (ConstPoolEntryError e) {
314             if (Debug.readBadData != null) Debug.println(Debug.readBadData,
315                 "method attribute name index=" + nameIndex);
316         }
317         
318         Debug.outdent();
319     }
320
321     private CodeInfo readCode(ConstPool cp, DataInput in)
322         throws IOException
323     {
324         // General Code Info
325
short maxStack = in.readShort();
326         short maxLocals = in.readShort();
327         byte[] bytecode = new byte[in.readInt()];
328
329         if (Debug.readCode != null) Debug.println(Debug.readCode,
330             "maxStack=" + maxStack +
331             "; maxLocals=" + maxLocals +
332             "; bytecode length=" + bytecode.length);
333         
334         in.readFully(bytecode);
335
336         // Exception Table
337
ExceptionInfo[] exceptionTable = new ExceptionInfo[in.readShort()];
338         if (Debug.readCode != null) Debug.println(Debug.readCode,
339             "exception table length=" + exceptionTable.length);
340         Debug.indent();
341         for (int i = 0; i < exceptionTable.length; i++) {
342             short startPC = in.readShort();
343             short endPC = in.readShort();
344             short handlerPC = in.readShort();
345             short catchTypeIndex = in.readShort();
346
347             if (Debug.readCode != null) Debug.println(Debug.readCode,
348                 "startPC=" + startPC +
349                 "; endPC=" + endPC +
350                 "; handlerPC=" + handlerPC +
351                 "; catchTypeIndex=" + catchTypeIndex);
352
353             String JavaDoc catchType = null;
354             if (catchTypeIndex != 0) { // index is null for finally blocks
355
short catchTypeNameIndex =
356                     cp.getEntryAtIndex(catchTypeIndex).getClassNameIndex();
357                 catchType = cp.getEntryAtIndex(catchTypeNameIndex).getString();
358             }
359             exceptionTable[i] =
360                 new ExceptionInfo(startPC, endPC, handlerPC, catchType);
361         }
362         Debug.outdent();
363
364         CodeInfo codeInfo =
365             new CodeInfo(maxStack, maxLocals, bytecode, exceptionTable);
366
367         // Code Attributes
368
short codeAttrCount = in.readShort();
369         if (Debug.readCode != null) Debug.println(Debug.readCode,
370             "#attributes=" + codeAttrCount);
371         Debug.indent();
372         for (int iCodeAttr = 0; iCodeAttr < codeAttrCount; iCodeAttr++)
373             readCodeAttribute(codeInfo, cp, in);
374         Debug.outdent();
375
376         return codeInfo;
377     }
378
379     private void readCodeAttribute(CodeInfo codeInfo, ConstPool cp,
380         DataInput in) throws IOException
381     {
382         short nameIndex = in.readShort();
383         int length = in.readInt();
384
385         // make sure we read the entire attribute -- if it has bad data,
386
// an exception might get thrown before we've read it all
387
byte[] bytes = new byte[length];
388         in.readFully(bytes);
389         in = new DataInputStream(new ByteArrayInputStream(bytes));
390
391         if (Debug.readCode != null) Debug.println(Debug.readCode,
392             "code attribute name index=" + nameIndex +
393             "; length=" + length);
394         Debug.indent();
395
396         try {
397
398             String JavaDoc name = cp.getEntryAtIndex(nameIndex).getString();
399             if (name.equals("LineNumberTable"))
400                 codeInfo.setLineNumberTable(readLineNumberTable(in));
401             else if (name.equals("LocalVariableTable"))
402                 codeInfo.setLocalVariableTable(readLocalVariableTable(cp, in));
403             else
404                 codeInfo.addAttribute(readUnknownAttribute(name, length, in));
405
406         } catch (ConstPoolEntryError e) {
407             if (Debug.readBadData != null) Debug.println(Debug.readBadData,
408                 "code attribute name index=" + nameIndex);
409         }
410
411         Debug.outdent();
412     }
413
414     private InnerClassInfo[] readInnerClasses(ConstPool cp, DataInput in)
415         throws IOException
416     {
417         short rows = in.readShort();
418         if (Debug.readInnerClasses != null) Debug.println(Debug.readInnerClasses,
419             "#inner classes=" + rows);
420         InnerClassInfo[] classes = new InnerClassInfo[rows];
421         for (int i = 0; i < rows; i++) {
422             short innerClassIndex = in.readShort();
423             short outerClassIndex = in.readShort();
424             short simpleNameIndex = in.readShort();
425             short flags = in.readShort();
426
427             if (Debug.readInnerClasses != null) Debug.println(Debug.readInnerClasses,
428                 "inner class index=" + innerClassIndex +
429                 "; outer class index=" + outerClassIndex +
430                 "; simple name index=" + simpleNameIndex +
431                 "; flags=" + flags);
432
433             short innerClassNameIndex = cp.getEntryAtIndex(innerClassIndex).getClassNameIndex();
434             String JavaDoc innerClassName = cp.getEntryAtIndex(innerClassNameIndex).getString();
435             String JavaDoc outerClassName = null;
436             if (outerClassIndex != 0) {
437                 short outerClassNameIndex = cp.getEntryAtIndex(outerClassIndex).getClassNameIndex();
438                 outerClassName = cp.getEntryAtIndex(outerClassNameIndex).getString();
439             }
440             String JavaDoc simpleName = null;
441             if (simpleNameIndex != 0)
442                 simpleName = cp.getEntryAtIndex(simpleNameIndex).getString();
443
444             classes[i] = new InnerClassInfo(innerClassName, outerClassName, simpleName, flags);
445         }
446         return classes;
447     }
448
449     private LocalVariableInfo[] readLocalVariableTable(ConstPool cp, DataInput in)
450         throws IOException
451     {
452         LocalVariableInfo[] table = new LocalVariableInfo[in.readShort()];
453         if (Debug.readLocalVariables != null) Debug.println(Debug.readLocalVariables,
454             "#local variables=" + table.length);
455         for (int i = 0; i < table.length; i++) {
456             short startPC = in.readShort();
457             short length = in.readShort();
458             short nameIndex = in.readShort();
459             short signatureIndex = in.readShort();
460             short slot= in.readShort();
461             if (Debug.readLocalVariables != null) Debug.println(Debug.readLocalVariables,
462                 "start PC=" + startPC +
463                 "; length=" + length +
464                 "; name index=" + nameIndex +
465                 "; signature index=" + signatureIndex +
466                 "; slot=" + slot);
467
468             String JavaDoc name = cp.getEntryAtIndex(nameIndex).getString();
469             String JavaDoc signature = cp.getEntryAtIndex(signatureIndex).getString();
470             table[i] = new LocalVariableInfo(startPC, length, name, signature, slot);
471         }
472         return table;
473     }
474
475     private LineNumberInfo[] readLineNumberTable(DataInput in)
476         throws IOException
477     {
478         LineNumberInfo[] table = new LineNumberInfo[in.readShort()];
479         if (Debug.readLineNumbers != null) Debug.println(Debug.readLineNumbers,
480             "#line numbers=" + table.length);
481         for (int i = 0; i < table.length; i++) {
482             short startPC = in.readShort();
483             short lineNumber = in.readShort();
484
485             if (Debug.readLineNumbers != null) Debug.println(Debug.readLineNumbers,
486                 "start PC=" + startPC +
487                 "; line number=" + lineNumber);
488
489             table[i] = new LineNumberInfo(startPC, lineNumber);
490         }
491         return table;
492     }
493
494     private AttributeInfo readUnknownAttribute(String JavaDoc name, int length, DataInput in)
495         throws IOException
496     {
497         if (Debug.readUnknownAttribute != null) Debug.println(Debug.readUnknownAttribute,
498             "attribute name=\"" + name + "\"");
499         byte[] data = new byte[length];
500         in.readFully(data);
501         return new AttributeInfo(name, data);
502     }
503 }
504 
Popular Tags