KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jeantessier > classreader > Classfile


1 /*
2  * Copyright (c) 2001-2005, Jean Tessier
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of Jean Tessier nor the names of his contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */

32
33 package com.jeantessier.classreader;
34
35 import java.io.*;
36 import java.util.*;
37
38 import org.apache.log4j.*;
39
40 public class Classfile implements Deprecatable, Visitable {
41     public static final int ACC_PUBLIC = 0x0001;
42     public static final int ACC_FINAL = 0x0010;
43     public static final int ACC_SUPER = 0x0020;
44     public static final int ACC_INTERFACE = 0x0200;
45     public static final int ACC_ABSTRACT = 0x0400;
46
47     private ClassfileLoader loader;
48
49     private int magicNumber;
50     private int minorVersion;
51     private int majorVersion;
52     private ConstantPool constantPool;
53     private int accessFlag;
54     private int classIndex;
55     private int superclassIndex;
56     private Map interfaces = new TreeMap();
57     private Map fields = new TreeMap();
58     private Map methods = new TreeMap();
59     private Collection attributes = new LinkedList();
60
61     /**
62      * Parses the input stream and extracts the class description.
63      * You should only call this constructor from a ClassfileLoader.
64      */

65     public Classfile(ClassfileLoader loader, DataInputStream in) throws IOException {
66         this.loader = loader;
67
68         magicNumber = in.readInt();
69         Logger.getLogger(getClass()).debug("magic number = " + magicNumber);
70
71         if (magicNumber != 0xCAFEBABE) {
72             throw new IOException("Bad magic number");
73         }
74         
75         // Reading the file format's version number
76
minorVersion = in.readUnsignedShort();
77         Logger.getLogger(getClass()).debug("minor version = " + minorVersion);
78         majorVersion = in.readUnsignedShort();
79         Logger.getLogger(getClass()).debug("major version = " + majorVersion);
80
81         // Reading the constant pool
82
Logger.getLogger(getClass()).debug("Reading the constant pool ...");
83         constantPool = new ConstantPool(this, in);
84         Logger.getLogger(getClass()).debug(constantPool);
85
86         // Skipping the access flag
87
accessFlag = in.readUnsignedShort();
88         Logger.getLogger(getClass()).debug("accessFlag = " + accessFlag);
89
90         // Retrieving this class's name
91
classIndex = in.readUnsignedShort();
92         Logger.getLogger(getClass()).debug("thisClass = " + classIndex + " (" + getClassName() + ")");
93
94         // Retrieving this class's superclass
95
superclassIndex = in.readUnsignedShort();
96         Logger.getLogger(getClass()).debug("superclass = " + superclassIndex + " (" + getSuperclassName() + ")");
97
98         // Retrieving the inferfaces
99
int interfaceCount = in.readUnsignedShort();
100         Logger.getLogger(getClass()).debug("Reading " + interfaceCount + " interface(s)");
101         for (int i=0; i<interfaceCount; i++) {
102             Class_info interfaceInfo = (Class_info) constantPool.get(in.readUnsignedShort());
103             Logger.getLogger(getClass()).debug(" " + interfaceInfo.getName());
104             interfaces.put(interfaceInfo.getName(), interfaceInfo);
105         }
106
107         // Retrieving the fields
108
int fieldCount = in.readUnsignedShort();
109         Logger.getLogger(getClass()).debug("Reading " + fieldCount + " field(s)");
110         for (int i=0; i<fieldCount; i++) {
111             Logger.getLogger(getClass()).debug("Field " + i + ":");
112             Field_info fieldInfo = new Field_info(this, in);
113             fields.put(fieldInfo.getName(), fieldInfo);
114         }
115
116         // Retrieving the methods
117
int methodCount = in.readUnsignedShort();
118         Logger.getLogger(getClass()).debug("Reading " + methodCount + " method(s)");
119         for (int i=0; i<methodCount; i++) {
120             Logger.getLogger(getClass()).debug("Method " + i + ":");
121             Method_info methodInfo = new Method_info(this, in);
122             methods.put(methodInfo.getSignature(), methodInfo);
123         }
124
125         // Retrieving the attributes
126
int attributeCount = in.readUnsignedShort();
127         Logger.getLogger(getClass()).debug("Reading " + attributeCount + " class attribute(s)");
128         for (int i=0; i<attributeCount; i++) {
129             Logger.getLogger(getClass()).debug("Attribute " + i + ":");
130             attributes.add(AttributeFactory.create(this, this, in));
131         }
132     }
133
134     public ClassfileLoader getLoader() {
135         return loader;
136     }
137
138     public int getMagicNumber() {
139         return magicNumber;
140     }
141
142     public int getMinorVersion() {
143         return minorVersion;
144     }
145
146     public int getMajorVersion() {
147         return majorVersion;
148     }
149
150     public ConstantPool getConstantPool() {
151         return constantPool;
152     }
153
154     public int getAccessFlag() {
155         return accessFlag;
156     }
157
158     public int getClassIndex() {
159         return classIndex;
160     }
161
162     public Class_info getRawClass() {
163         return (Class_info) getConstantPool().get(getClassIndex());
164     }
165
166     public String JavaDoc getClassName() {
167         return getRawClass().toString();
168     }
169
170     public int getSuperclassIndex() {
171         return superclassIndex;
172     }
173
174     public Class_info getRawSuperclass() {
175         return (Class_info) getConstantPool().get(getSuperclassIndex());
176     }
177
178     public String JavaDoc getSuperclassName() {
179         String JavaDoc result = "";
180
181         if (getSuperclassIndex() != 0) {
182             result = getRawSuperclass().toString();
183         }
184         
185         return result;
186     }
187
188     public Class_info getInterface(String JavaDoc name) {
189         return (Class_info) interfaces.get(name);
190     }
191
192     public Collection getAllInterfaces() {
193         return interfaces.values();
194     }
195
196     public Collection getAllFields() {
197         return fields.values();
198     }
199
200     public Field_info getField(String JavaDoc name) {
201         return (Field_info) fields.get(name);
202     }
203
204     public Field_info locateField(String JavaDoc name) {
205         Field_info result = getField(name);
206
207         if (result == null) {
208             Classfile classfile = getLoader().getClassfile(getSuperclassName());
209             if (classfile != null) {
210                 Field_info attempt = classfile.locateField(name);
211                 if (attempt != null && (attempt.isPublic() || attempt.isProtected())) {
212                     result = attempt;
213                 }
214             }
215         }
216
217         Iterator i = getAllInterfaces().iterator();
218         while (result == null && i.hasNext()) {
219             Classfile classfile = getLoader().getClassfile(i.next().toString());
220             if (classfile != null) {
221                 Field_info attempt = classfile.locateField(name);
222                 if (attempt != null && (attempt.isPublic() || attempt.isProtected())) {
223                     result = attempt;
224                 }
225             }
226         }
227
228         return result;
229     }
230
231     public Collection getAllMethods() {
232         return methods.values();
233     }
234
235     public Method_info getMethod(String JavaDoc signature) {
236         return (Method_info) methods.get(signature);
237     }
238
239     public Method_info locateMethod(String JavaDoc signature) {
240         Method_info result = getMethod(signature);
241
242         if (result == null) {
243             Classfile classfile = getLoader().getClassfile(getSuperclassName());
244             if (classfile != null) {
245                 Method_info attempt = classfile.locateMethod(signature);
246                 if (attempt != null && (attempt.isPublic() || attempt.isProtected())) {
247                     result = attempt;
248                 }
249             }
250         }
251
252         Iterator i = getAllInterfaces().iterator();
253         while (result == null && i.hasNext()) {
254             Classfile classfile = getLoader().getClassfile(i.next().toString());
255             if (classfile != null) {
256                 Method_info attempt = classfile.locateMethod(signature);
257                 if (attempt != null && (attempt.isPublic() || attempt.isProtected())) {
258                     result = attempt;
259                 }
260             }
261         }
262
263         return result;
264     }
265
266     public Collection getAttributes() {
267         return attributes;
268     }
269
270     public boolean isPublic() {
271         return (getAccessFlag() & ACC_PUBLIC) != 0;
272     }
273
274     public boolean isPackage() {
275         return (getAccessFlag() & ACC_PUBLIC) == 0;
276     }
277
278     public boolean isFinal() {
279         return (getAccessFlag() & ACC_FINAL) != 0;
280     }
281
282     public boolean isSuper() {
283         return (getAccessFlag() & ACC_SUPER) != 0;
284     }
285
286     public boolean isInterface() {
287         return (getAccessFlag() & ACC_INTERFACE) != 0;
288     }
289
290     public boolean isAbstract() {
291         return (getAccessFlag() & ACC_ABSTRACT) != 0;
292     }
293
294     public boolean isSynthetic() {
295         boolean result = false;
296
297         Iterator i = getAttributes().iterator();
298         while (!result && i.hasNext()) {
299             result = i.next() instanceof Synthetic_attribute;
300         }
301     
302         return result;
303     }
304
305     public boolean isDeprecated() {
306         boolean result = false;
307
308         Iterator i = getAttributes().iterator();
309         while (!result && i.hasNext()) {
310             result = i.next() instanceof Deprecated_attribute;
311         }
312     
313         return result;
314     }
315
316     public String JavaDoc getDeclaration() {
317         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
318
319         if (isPublic()) result.append("public ");
320         if (isFinal()) result.append("final ");
321
322         if (isInterface()) {
323             result.append("interface ").append(getClassName());
324
325             if (getAllInterfaces().size() != 0) {
326                 result.append(" extends ");
327                 Iterator i = getAllInterfaces().iterator();
328                 while (i.hasNext()) {
329                     result.append(i.next());
330                     if (i.hasNext()) {
331                         result.append(", ");
332                     }
333                 }
334             }
335         } else {
336             if (isAbstract()) result.append("abstract ");
337             result.append("class ").append(getClassName());
338
339             if (getSuperclassIndex() != 0) {
340                 result.append(" extends ").append(getSuperclassName());
341             }
342             
343             if (getAllInterfaces().size() != 0) {
344                 result.append(" implements ");
345                 Iterator i = getAllInterfaces().iterator();
346                 while (i.hasNext()) {
347                     result.append(i.next());
348                     if (i.hasNext()) {
349                         result.append(", ");
350                     }
351                 }
352             }
353         }
354
355         return result.toString();
356     }
357
358     public void accept(Visitor visitor) {
359         visitor.visitClassfile(this);
360     }
361
362     public String JavaDoc toString() {
363         return getClassName();
364     }
365 }
366
Popular Tags