KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > classfile > io > LibraryClassReader


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 library 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 library 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 library; 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.io;
22
23 import proguard.classfile.*;
24 import proguard.classfile.constant.*;
25 import proguard.classfile.constant.visitor.ConstantVisitor;
26 import proguard.classfile.util.*;
27 import proguard.classfile.visitor.*;
28
29 import java.io.DataInput JavaDoc;
30
31 /**
32  * This ClassVisitor fills out the LibraryClass objects that it visits with data
33  * from the given DataInput object.
34  *
35  * @author Eric Lafortune
36  */

37 public class LibraryClassReader
38 extends SimplifiedVisitor
39 implements ClassVisitor,
40              MemberVisitor,
41              ConstantVisitor
42 {
43     private static final LibraryField[] EMPTY_LIBRARY_FIELDS = new LibraryField[0];
44     private static final LibraryMethod[] EMPTY_LIBRARY_METHODS = new LibraryMethod[0];
45
46
47     private RuntimeDataInput dataInput;
48     private boolean skipNonPublicClasses;
49     private boolean skipNonPublicClassMembers;
50
51     // A global array that acts as a parameter for the visitor methods.
52
private Constant[] constantPool;
53
54
55     /**
56      * Creates a new ProgramClassReader for reading from the given DataInput.
57      */

58     public LibraryClassReader(DataInput JavaDoc dataInput,
59                               boolean skipNonPublicClasses,
60                               boolean skipNonPublicClassMembers)
61     {
62         this.dataInput = new RuntimeDataInput(dataInput);
63         this.skipNonPublicClasses = skipNonPublicClasses;
64         this.skipNonPublicClassMembers = skipNonPublicClassMembers;
65     }
66
67
68     // Implementations for ClassVisitor.
69

70     public void visitProgramClass(ProgramClass libraryClass)
71     {
72     }
73
74
75     public void visitLibraryClass(LibraryClass libraryClass)
76     {
77         // Read and check the magic number.
78
int u4magic = dataInput.readInt();
79
80         ClassUtil.checkMagicNumber(u4magic);
81
82         // Read and check the version numbers.
83
int u2minorVersion = dataInput.readUnsignedShort();
84         int u2majorVersion = dataInput.readUnsignedShort();
85
86         int u4version = ClassUtil.internalClassVersion(u2majorVersion,
87                                                        u2minorVersion);
88
89         ClassUtil.checkVersionNumbers(u4version);
90
91         // Read the constant pool. Note that the first entry is not used.
92
int u2constantPoolCount = dataInput.readUnsignedShort();
93
94         // Create the constant pool array.
95
constantPool = new Constant[u2constantPoolCount];
96
97         for (int index = 1; index < u2constantPoolCount; index++)
98         {
99             Constant constant = createConstant();
100             constant.accept(libraryClass, this);
101
102             int tag = constant.getTag();
103             if (tag == ClassConstants.CONSTANT_Class ||
104                 tag == ClassConstants.CONSTANT_Utf8)
105             {
106                 constantPool[index] = constant;
107             }
108
109             // Long constants and double constants take up two entries in the
110
// constant pool.
111
if (tag == ClassConstants.CONSTANT_Long ||
112                 tag == ClassConstants.CONSTANT_Double)
113             {
114                 index++;
115             }
116         }
117
118         // Read the general class information.
119
libraryClass.u2accessFlags = dataInput.readUnsignedShort();
120
121         // We may stop parsing this library class if it's not public anyway.
122
// E.g. only about 60% of all rt.jar classes need to be parsed.
123
if (skipNonPublicClasses &&
124             AccessUtil.accessLevel(libraryClass.getAccessFlags()) < AccessUtil.PUBLIC)
125         {
126             return;
127         }
128
129         // Read the class and super class indices.
130
int u2thisClass = dataInput.readUnsignedShort();
131         int u2superClass = dataInput.readUnsignedShort();
132
133         // Store their actual names.
134
libraryClass.thisClassName = getClassName(u2thisClass);
135         libraryClass.superClassName = (u2superClass == 0) ? null :
136                                       getClassName(u2superClass);
137
138         // Read the interfaces
139
int u2interfacesCount = dataInput.readUnsignedShort();
140
141         libraryClass.interfaceNames = new String JavaDoc[u2interfacesCount];
142         for (int index = 0; index < u2interfacesCount; index++)
143         {
144             // Store the actual interface name.
145
int u2interface = dataInput.readUnsignedShort();
146             libraryClass.interfaceNames[index] = getClassName(u2interface);
147         }
148
149         // Read the fields.
150
int u2fieldsCount = dataInput.readUnsignedShort();
151
152         // Create the fields array.
153
LibraryField[] reusableFields = new LibraryField[u2fieldsCount];
154
155         int visibleFieldsCount = 0;
156         for (int index = 0; index < u2fieldsCount; index++)
157         {
158             LibraryField field = new LibraryField();
159             this.visitLibraryMember(libraryClass, field);
160
161             // Only store fields that are visible.
162
if (AccessUtil.accessLevel(field.getAccessFlags()) >=
163                 (skipNonPublicClassMembers ? AccessUtil.PROTECTED :
164                                              AccessUtil.PACKAGE_VISIBLE))
165             {
166                 reusableFields[visibleFieldsCount++] = field;
167             }
168         }
169
170         // Copy the visible fields (if any) into a fields array of the right size.
171
if (visibleFieldsCount == 0)
172         {
173             libraryClass.fields = EMPTY_LIBRARY_FIELDS;
174         }
175         else
176         {
177             libraryClass.fields = new LibraryField[visibleFieldsCount];
178             System.arraycopy(reusableFields, 0, libraryClass.fields, 0, visibleFieldsCount);
179         }
180
181         // Read the methods.
182
int u2methodsCount = dataInput.readUnsignedShort();
183
184         // Create the methods array.
185
LibraryMethod[] reusableMethods = new LibraryMethod[u2methodsCount];
186
187         int visibleMethodsCount = 0;
188         for (int index = 0; index < u2methodsCount; index++)
189         {
190             LibraryMethod method = new LibraryMethod();
191             this.visitLibraryMember(libraryClass, method);
192
193             // Only store methods that are visible.
194
if (AccessUtil.accessLevel(method.getAccessFlags()) >=
195                 (skipNonPublicClassMembers ? AccessUtil.PROTECTED :
196                                              AccessUtil.PACKAGE_VISIBLE))
197             {
198                 reusableMethods[visibleMethodsCount++] = method;
199             }
200         }
201
202         // Copy the visible methods (if any) into a methods array of the right size.
203
if (visibleMethodsCount == 0)
204         {
205             libraryClass.methods = EMPTY_LIBRARY_METHODS;
206         }
207         else
208         {
209             libraryClass.methods = new LibraryMethod[visibleMethodsCount];
210             System.arraycopy(reusableMethods, 0, libraryClass.methods, 0, visibleMethodsCount);
211         }
212
213         // Skip the class attributes.
214
skipAttributes();
215     }
216
217
218     // Implementations for MemberVisitor.
219

220     public void visitProgramMember(ProgramClass libraryClass, ProgramMember libraryMember)
221     {
222     }
223
224
225     public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
226     {
227         // Read the general field information.
228
libraryMember.u2accessFlags = dataInput.readUnsignedShort();
229         libraryMember.name = getString(dataInput.readUnsignedShort());
230         libraryMember.descriptor = getString(dataInput.readUnsignedShort());
231
232         // Skip the field attributes.
233
skipAttributes();
234     }
235
236
237     // Implementations for ConstantVisitor.
238

239     public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
240     {
241         dataInput.skipBytes(4);
242     }
243
244
245     public void visitLongConstant(Clazz clazz, LongConstant longConstant)
246     {
247         dataInput.skipBytes(8);
248     }
249
250
251     public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
252     {
253         dataInput.skipBytes(4);
254     }
255
256
257     public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
258     {
259         dataInput.skipBytes(8);
260     }
261
262
263     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
264     {
265         dataInput.skipBytes(2);
266     }
267
268
269     public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
270     {
271         int u2length = dataInput.readUnsignedShort();
272
273         // Read the UTF-8 bytes.
274
byte[] bytes = new byte[u2length];
275         dataInput.readFully(bytes);
276         utf8Constant.setBytes(bytes);
277     }
278
279
280     public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
281     {
282         dataInput.skipBytes(4);
283     }
284
285
286     public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
287     {
288         classConstant.u2nameIndex = dataInput.readUnsignedShort();
289     }
290
291
292     public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
293     {
294         dataInput.skipBytes(4);
295     }
296
297
298     // Small utility methods.
299

300     /**
301      * Returns the class name of the ClassConstant at the specified index in the
302      * reusable constant pool.
303      */

304     private String JavaDoc getClassName(int constantIndex)
305     {
306         ClassConstant classEntry = (ClassConstant)constantPool[constantIndex];
307
308         return getString(classEntry.u2nameIndex);
309     }
310
311
312     /**
313      * Returns the string of the Utf8Constant at the specified index in the
314      * reusable constant pool.
315      */

316     private String JavaDoc getString(int constantIndex)
317     {
318         return ((Utf8Constant)constantPool[constantIndex]).getString();
319     }
320
321
322     private Constant createConstant()
323     {
324         int u1tag = dataInput.readUnsignedByte();
325
326         switch (u1tag)
327         {
328             case ClassConstants.CONSTANT_Utf8: return new Utf8Constant();
329             case ClassConstants.CONSTANT_Integer: return new IntegerConstant();
330             case ClassConstants.CONSTANT_Float: return new FloatConstant();
331             case ClassConstants.CONSTANT_Long: return new LongConstant();
332             case ClassConstants.CONSTANT_Double: return new DoubleConstant();
333             case ClassConstants.CONSTANT_String: return new StringConstant();
334             case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant();
335             case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant();
336             case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant();
337             case ClassConstants.CONSTANT_Class: return new ClassConstant();
338             case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant();
339
340             default: throw new RuntimeException JavaDoc("Unknown constant type ["+u1tag+"] in constant pool");
341         }
342     }
343
344
345     private void skipAttributes()
346     {
347         int u2attributesCount = dataInput.readUnsignedShort();
348
349         for (int index = 0; index < u2attributesCount; index++)
350         {
351             skipAttribute();
352         }
353     }
354
355
356     private void skipAttribute()
357     {
358         dataInput.skipBytes(2);
359         int u4attributeLength = dataInput.readInt();
360         dataInput.skipBytes(u4attributeLength);
361     }
362 }
363
Popular Tags