KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > util > ClassFileReader


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.util;
12
13 /**
14  * Default implementation of IClassFileReader.
15  */

16 import org.eclipse.jdt.core.compiler.CharOperation;
17 import org.eclipse.jdt.core.util.ClassFormatException;
18 import org.eclipse.jdt.core.util.IAttributeNamesConstants;
19 import org.eclipse.jdt.core.util.IClassFileAttribute;
20 import org.eclipse.jdt.core.util.IClassFileReader;
21 import org.eclipse.jdt.core.util.IConstantPool;
22 import org.eclipse.jdt.core.util.IConstantPoolConstant;
23 import org.eclipse.jdt.core.util.IFieldInfo;
24 import org.eclipse.jdt.core.util.IInnerClassesAttribute;
25 import org.eclipse.jdt.core.util.IMethodInfo;
26 import org.eclipse.jdt.core.util.IModifierConstants;
27 import org.eclipse.jdt.core.util.ISourceAttribute;
28 import org.eclipse.jdt.internal.compiler.util.Util;
29
30 public class ClassFileReader extends ClassFileStruct implements IClassFileReader {
31     private static final IFieldInfo[] NO_FIELD_INFOS = new IFieldInfo[0];
32     private static final char[][] NO_INTERFACES_NAMES = CharOperation.NO_CHAR_CHAR;
33     private static final IMethodInfo[] NO_METHOD_INFOS = new IMethodInfo[0];
34     private int accessFlags;
35     private IClassFileAttribute[] attributes;
36     private int attributesCount;
37     private char[] className;
38     private int classNameIndex;
39
40     private IConstantPool constantPool;
41     private IFieldInfo[] fields;
42     private int fieldsCount;
43     private IInnerClassesAttribute innerClassesAttribute;
44     private int[] interfaceIndexes;
45     private char[][] interfaceNames;
46     private int interfacesCount;
47     private int magicNumber;
48     private int majorVersion;
49     private IMethodInfo[] methods;
50     private int methodsCount;
51     private int minorVersion;
52     private ISourceAttribute sourceFileAttribute;
53     private char[] superclassName;
54     private int superclassNameIndex;
55     
56     /**
57      * Constructor for ClassFileReader.
58      *
59      * @param classFileBytes the raw bytes of the .class file
60      * @param decodingFlags the decoding flags
61      *
62      * @see IClassFileReader#ALL
63      * @see IClassFileReader#CLASSFILE_ATTRIBUTES
64      * @see IClassFileReader#CONSTANT_POOL
65      * @see IClassFileReader#FIELD_INFOS
66      */

67     public ClassFileReader(byte[] classFileBytes, int decodingFlags) throws ClassFormatException {
68     
69         // This method looks ugly but is actually quite simple, the constantPool is constructed
70
// in 3 passes. All non-primitive constant pool members that usually refer to other members
71
// by index are tweaked to have their value in inst vars, this minor cost at read-time makes
72
// all subsequent uses of the constant pool element faster.
73
int constantPoolCount;
74         int[] constantPoolOffsets;
75         try {
76             this.magicNumber = (int) u4At(classFileBytes, 0, 0);
77             if (this.magicNumber != 0xCAFEBABE) {
78                 throw new ClassFormatException(ClassFormatException.INVALID_MAGIC_NUMBER);
79             }
80             
81             int readOffset = 10;
82             this.minorVersion = this.u2At(classFileBytes, 4, 0);
83             this.majorVersion = this.u2At(classFileBytes, 6, 0);
84             
85             if ((decodingFlags & IClassFileReader.CONSTANT_POOL) == 0) {
86                 // no need to go further
87
return;
88             }
89             
90             constantPoolCount = this.u2At(classFileBytes, 8, 0);
91             // Pass #1 - Fill in all primitive constants
92
constantPoolOffsets = new int[constantPoolCount];
93             for (int i = 1; i < constantPoolCount; i++) {
94                 int tag = this.u1At(classFileBytes, readOffset, 0);
95                 switch (tag) {
96                     case IConstantPoolConstant.CONSTANT_Utf8 :
97                         constantPoolOffsets[i] = readOffset;
98                         readOffset += u2At(classFileBytes, readOffset + 1, 0);
99                         readOffset += IConstantPoolConstant.CONSTANT_Utf8_SIZE;
100                         break;
101                     case IConstantPoolConstant.CONSTANT_Integer :
102                         constantPoolOffsets[i] = readOffset;
103                         readOffset += IConstantPoolConstant.CONSTANT_Integer_SIZE;
104                         break;
105                     case IConstantPoolConstant.CONSTANT_Float :
106                         constantPoolOffsets[i] = readOffset;
107                         readOffset += IConstantPoolConstant.CONSTANT_Float_SIZE;
108                         break;
109                     case IConstantPoolConstant.CONSTANT_Long :
110                         constantPoolOffsets[i] = readOffset;
111                         readOffset += IConstantPoolConstant.CONSTANT_Long_SIZE;
112                         i++;
113                         break;
114                     case IConstantPoolConstant.CONSTANT_Double :
115                         constantPoolOffsets[i] = readOffset;
116                         readOffset += IConstantPoolConstant.CONSTANT_Double_SIZE;
117                         i++;
118                         break;
119                     case IConstantPoolConstant.CONSTANT_Class :
120                         constantPoolOffsets[i] = readOffset;
121                         readOffset += IConstantPoolConstant.CONSTANT_Class_SIZE;
122                         break;
123                     case IConstantPoolConstant.CONSTANT_String :
124                         constantPoolOffsets[i] = readOffset;
125                         readOffset += IConstantPoolConstant.CONSTANT_String_SIZE;
126                         break;
127                     case IConstantPoolConstant.CONSTANT_Fieldref :
128                         constantPoolOffsets[i] = readOffset;
129                         readOffset += IConstantPoolConstant.CONSTANT_Fieldref_SIZE;
130                         break;
131                     case IConstantPoolConstant.CONSTANT_Methodref :
132                         constantPoolOffsets[i] = readOffset;
133                         readOffset += IConstantPoolConstant.CONSTANT_Methodref_SIZE;
134                         break;
135                     case IConstantPoolConstant.CONSTANT_InterfaceMethodref :
136                         constantPoolOffsets[i] = readOffset;
137                         readOffset += IConstantPoolConstant.CONSTANT_InterfaceMethodref_SIZE;
138                         break;
139                     case IConstantPoolConstant.CONSTANT_NameAndType :
140                         constantPoolOffsets[i] = readOffset;
141                         readOffset += IConstantPoolConstant.CONSTANT_NameAndType_SIZE;
142                         break;
143                     default:
144                         throw new ClassFormatException(ClassFormatException.INVALID_TAG_CONSTANT);
145                 }
146             }
147             
148             this.constantPool = new ConstantPool(classFileBytes, constantPoolOffsets);
149             // Read and validate access flags
150
this.accessFlags = u2At(classFileBytes, readOffset, 0);
151             readOffset += 2;
152     
153             // Read the classname, use exception handlers to catch bad format
154
this.classNameIndex = u2At(classFileBytes, readOffset, 0);
155             this.className = getConstantClassNameAt(classFileBytes, constantPoolOffsets, this.classNameIndex);
156             readOffset += 2;
157     
158             // Read the superclass name, can be zero for java.lang.Object
159
this.superclassNameIndex = u2At(classFileBytes, readOffset, 0);
160             readOffset += 2;
161             // if superclassNameIndex is equals to 0 there is no need to set a value for the
162
// field this.superclassName. null is fine.
163
if (superclassNameIndex != 0) {
164                 this.superclassName = getConstantClassNameAt(classFileBytes, constantPoolOffsets, this.superclassNameIndex);
165             }
166     
167             // Read the interfaces, use exception handlers to catch bad format
168
this.interfacesCount = u2At(classFileBytes, readOffset, 0);
169             readOffset += 2;
170             this.interfaceNames = NO_INTERFACES_NAMES;
171             this.interfaceIndexes = Util.EMPTY_INT_ARRAY;
172             if (this.interfacesCount != 0) {
173                 if ((decodingFlags & IClassFileReader.SUPER_INTERFACES) != IClassFileReader.CONSTANT_POOL) {
174                     this.interfaceNames = new char[this.interfacesCount][];
175                     this.interfaceIndexes = new int[this.interfacesCount];
176                     for (int i = 0; i < this.interfacesCount; i++) {
177                         this.interfaceIndexes[i] = u2At(classFileBytes, readOffset, 0);
178                         this.interfaceNames[i] = getConstantClassNameAt(classFileBytes, constantPoolOffsets, this.interfaceIndexes[i]);
179                         readOffset += 2;
180                     }
181                 } else {
182                     readOffset += (2 * this.interfacesCount);
183                 }
184             }
185             // Read the this.fields, use exception handlers to catch bad format
186
this.fieldsCount = u2At(classFileBytes, readOffset, 0);
187             readOffset += 2;
188             this.fields = NO_FIELD_INFOS;
189             if (this.fieldsCount != 0) {
190                 if ((decodingFlags & IClassFileReader.FIELD_INFOS) != IClassFileReader.CONSTANT_POOL) {
191                     FieldInfo field;
192                     this.fields = new FieldInfo[this.fieldsCount];
193                     for (int i = 0; i < this.fieldsCount; i++) {
194                         field = new FieldInfo(classFileBytes, this.constantPool, readOffset);
195                         this.fields[i] = field;
196                         readOffset += field.sizeInBytes();
197                     }
198                 } else {
199                     for (int i = 0; i < this.fieldsCount; i++) {
200                         int attributeCountForField = u2At(classFileBytes, 6, readOffset);
201                         readOffset += 8;
202                         if (attributeCountForField != 0) {
203                             for (int j = 0; j < attributeCountForField; j++) {
204                                 int attributeLength = (int) u4At(classFileBytes, 2, readOffset);
205                                 readOffset += (6 + attributeLength);
206                             }
207                         }
208                     }
209                 }
210             }
211             // Read the this.methods
212
this.methodsCount = u2At(classFileBytes, readOffset, 0);
213             readOffset += 2;
214             this.methods = NO_METHOD_INFOS;
215             if (this.methodsCount != 0) {
216                 if ((decodingFlags & IClassFileReader.METHOD_INFOS) != IClassFileReader.CONSTANT_POOL) {
217                     this.methods = new MethodInfo[this.methodsCount];
218                     MethodInfo method;
219                     for (int i = 0; i < this.methodsCount; i++) {
220                         method = new MethodInfo(classFileBytes, this.constantPool, readOffset, decodingFlags);
221                         this.methods[i] = method;
222                         readOffset += method.sizeInBytes();
223                     }
224                 } else {
225                     for (int i = 0; i < this.methodsCount; i++) {
226                         int attributeCountForMethod = u2At(classFileBytes, 6, readOffset);
227                         readOffset += 8;
228                         if (attributeCountForMethod != 0) {
229                             for (int j = 0; j < attributeCountForMethod; j++) {
230                                 int attributeLength = (int) u4At(classFileBytes, 2, readOffset);
231                                 readOffset += (6 + attributeLength);
232                             }
233                         }
234                     }
235                 }
236             }
237     
238             // Read the attributes
239
this.attributesCount = u2At(classFileBytes, readOffset, 0);
240             readOffset += 2;
241     
242             int attributesIndex = 0;
243             this.attributes = ClassFileAttribute.NO_ATTRIBUTES;
244             if (this.attributesCount != 0) {
245                 if ((decodingFlags & IClassFileReader.CLASSFILE_ATTRIBUTES) != IClassFileReader.CONSTANT_POOL) {
246                     this.attributes = new IClassFileAttribute[this.attributesCount];
247                     for (int i = 0; i < attributesCount; i++) {
248                         int utf8Offset = constantPoolOffsets[u2At(classFileBytes, readOffset, 0)];
249                         char[] attributeName = utf8At(classFileBytes, utf8Offset + 3, 0, u2At(classFileBytes, utf8Offset + 1, 0));
250                         if (equals(attributeName, IAttributeNamesConstants.INNER_CLASSES)) {
251                             this.innerClassesAttribute = new InnerClassesAttribute(classFileBytes, this.constantPool, readOffset);
252                             this.attributes[attributesIndex++] = this.innerClassesAttribute;
253                         } else if (equals(attributeName, IAttributeNamesConstants.SOURCE)) {
254                             this.sourceFileAttribute = new SourceFileAttribute(classFileBytes, this.constantPool, readOffset);
255                             this.attributes[attributesIndex++] = this.sourceFileAttribute;
256                         } else if (equals(attributeName, IAttributeNamesConstants.ENCLOSING_METHOD)) {
257                             this.attributes[attributesIndex++] = new EnclosingMethodAttribute(classFileBytes, this.constantPool, readOffset);
258                         } else if (equals(attributeName, IAttributeNamesConstants.SIGNATURE)) {
259                             this.attributes[attributesIndex++] = new SignatureAttribute(classFileBytes, this.constantPool, readOffset);
260                         } else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS)) {
261                             this.attributes[attributesIndex++] = new RuntimeVisibleAnnotationsAttribute(classFileBytes, this.constantPool, readOffset);
262                         } else if (equals(attributeName, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS)) {
263                             this.attributes[attributesIndex++] = new RuntimeInvisibleAnnotationsAttribute(classFileBytes, this.constantPool, readOffset);
264                         } else {
265                             this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset);
266                         }
267                         readOffset += (6 + u4At(classFileBytes, readOffset + 2, 0));
268                     }
269                 } else {
270                     for (int i = 0; i < attributesCount; i++) {
271                         readOffset += (6 + u4At(classFileBytes, readOffset + 2, 0));
272                     }
273                 }
274             }
275             if (readOffset != classFileBytes.length) {
276                 throw new ClassFormatException(ClassFormatException.TOO_MANY_BYTES);
277             }
278         } catch(ClassFormatException e) {
279             throw e;
280         } catch (Exception JavaDoc e) {
281             e.printStackTrace();
282             throw new ClassFormatException(ClassFormatException.ERROR_TRUNCATED_INPUT);
283         }
284     }
285
286     /**
287      * @see IClassFileReader#getAccessFlags()
288      */

289     public int getAccessFlags() {
290         return this.accessFlags;
291     }
292     /**
293      * @see IClassFileReader#getAttributeCount()
294      */

295     public int getAttributeCount() {
296         return this.attributesCount;
297     }
298
299     /**
300      * @see IClassFileReader#getAttributes()
301      */

302     public IClassFileAttribute[] getAttributes() {
303         return this.attributes;
304     }
305
306     /**
307      * @see IClassFileReader#getClassIndex()
308      */

309     public int getClassIndex() {
310         return this.classNameIndex;
311     }
312
313     /**
314      * @see IClassFileReader#getClassName()
315      */

316     public char[] getClassName() {
317         return this.className;
318     }
319
320     private char[] getConstantClassNameAt(byte[] classFileBytes, int[] constantPoolOffsets, int constantPoolIndex) {
321         int utf8Offset = constantPoolOffsets[u2At(classFileBytes, constantPoolOffsets[constantPoolIndex] + 1, 0)];
322         return utf8At(classFileBytes, utf8Offset + 3, 0, u2At(classFileBytes, utf8Offset + 1, 0));
323     }
324
325     /**
326      * @see IClassFileReader#getConstantPool()
327      */

328     public IConstantPool getConstantPool() {
329         return this.constantPool;
330     }
331     /**
332      * @see IClassFileReader#getFieldInfos()
333      */

334     public IFieldInfo[] getFieldInfos() {
335         return this.fields;
336     }
337
338     /**
339      * @see IClassFileReader#getFieldsCount()
340      */

341     public int getFieldsCount() {
342         return this.fieldsCount;
343     }
344
345     /**
346      * @see IClassFileReader#getInnerClassesAttribute()
347      */

348     public IInnerClassesAttribute getInnerClassesAttribute() {
349         return this.innerClassesAttribute;
350     }
351
352     /**
353      * @see IClassFileReader#getInterfaceIndexes()
354      */

355     public int[] getInterfaceIndexes() {
356         return this.interfaceIndexes;
357     }
358
359     /**
360      * @see IClassFileReader#getInterfaceNames()
361      */

362     public char[][] getInterfaceNames() {
363         return this.interfaceNames;
364     }
365
366     /**
367      * @see IClassFileReader#getMagic()
368      */

369     public int getMagic() {
370         return this.magicNumber;
371     }
372
373     /**
374      * @see IClassFileReader#getMajorVersion()
375      */

376     public int getMajorVersion() {
377         return this.majorVersion;
378     }
379
380     /**
381      * @see IClassFileReader#getMethodInfos()
382      */

383     public IMethodInfo[] getMethodInfos() {
384         return this.methods;
385     }
386
387     /**
388      * @see IClassFileReader#getMethodsCount()
389      */

390     public int getMethodsCount() {
391         return this.methodsCount;
392     }
393
394     /**
395      * @see IClassFileReader#getMinorVersion()
396      */

397     public int getMinorVersion() {
398         return this.minorVersion;
399     }
400
401     /**
402      * @see IClassFileReader#getSourceFileAttribute()
403      */

404     public ISourceAttribute getSourceFileAttribute() {
405         return this.sourceFileAttribute;
406     }
407
408     /**
409      * @see IClassFileReader#getSuperclassIndex()
410      */

411     public int getSuperclassIndex() {
412         return this.superclassNameIndex;
413     }
414
415     /**
416      * @see IClassFileReader#getSuperclassName()
417      */

418     public char[] getSuperclassName() {
419         return this.superclassName;
420     }
421     /**
422      * @see IClassFileReader#isClass()
423      */

424     public boolean isClass() {
425         return !isInterface();
426     }
427
428     /**
429      * @see IClassFileReader#isInterface()
430      */

431     public boolean isInterface() {
432         return (getAccessFlags() & IModifierConstants.ACC_INTERFACE) != 0;
433     }
434 }
435
Popular Tags