1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| |
16 |
| |
17 |
| |
18 |
| |
19 |
| |
20 |
| |
21 |
| |
22 |
| |
23 |
| |
24 |
| |
25 |
| |
26 |
| |
27 |
| |
28 |
| |
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
| package com.jeantessier.classreader.impl; |
34 |
| |
35 |
| import com.jeantessier.classreader.ClassfileLoader; |
36 |
| import com.jeantessier.classreader.Visitor; |
37 |
| import org.apache.log4j.Logger; |
38 |
| |
39 |
| import java.io.DataInput; |
40 |
| import java.io.IOException; |
41 |
| import java.util.Collection; |
42 |
| import java.util.Iterator; |
43 |
| import java.util.LinkedList; |
44 |
| |
45 |
| public class Classfile implements com.jeantessier.classreader.Classfile { |
46 |
| private static final int ACC_PUBLIC = 0x0001; |
47 |
| private static final int ACC_FINAL = 0x0010; |
48 |
| private static final int ACC_SUPER = 0x0020; |
49 |
| private static final int ACC_INTERFACE = 0x0200; |
50 |
| private static final int ACC_ABSTRACT = 0x0400; |
51 |
| private static final int ACC_SYNTHETIC = 0x1000; |
52 |
| private static final int ACC_ANNOTATION = 0x2000; |
53 |
| private static final int ACC_ENUM = 0x4000; |
54 |
| |
55 |
| private ClassfileLoader loader; |
56 |
| |
57 |
| private int magicNumber; |
58 |
| private int minorVersion; |
59 |
| private int majorVersion; |
60 |
| private ConstantPool constantPool; |
61 |
| private int accessFlag; |
62 |
| private int classIndex; |
63 |
| private int superclassIndex; |
64 |
| private Collection<Class_info> interfaces = new LinkedList<Class_info>(); |
65 |
| private Collection<Field_info> fields = new LinkedList<Field_info>(); |
66 |
| private Collection<Method_info> methods = new LinkedList<Method_info>(); |
67 |
| private Collection<Attribute_info> attributes = new LinkedList<Attribute_info>(); |
68 |
| |
69 |
| |
70 |
| |
71 |
| |
72 |
| |
73 |
1304
| public Classfile(ClassfileLoader loader, DataInput in) throws IOException {
|
74 |
1304
| this(loader, in, new AttributeFactory());
|
75 |
| } |
76 |
| |
77 |
1304
| public Classfile(ClassfileLoader loader, DataInput in, AttributeFactory attributeFactory) throws IOException {
|
78 |
1304
| this.loader = loader;
|
79 |
| |
80 |
1304
| magicNumber = in.readInt();
|
81 |
1304
| Logger.getLogger(getClass()).debug("magic number = 0x" + Integer.toHexString(magicNumber).toUpperCase());
|
82 |
| |
83 |
1304
| if (magicNumber != 0xCAFEBABE) {
|
84 |
0
| throw new IOException("Bad magic number");
|
85 |
| } |
86 |
| |
87 |
| |
88 |
1304
| minorVersion = in.readUnsignedShort();
|
89 |
1304
| Logger.getLogger(getClass()).debug("minor version = " + minorVersion);
|
90 |
1304
| majorVersion = in.readUnsignedShort();
|
91 |
1304
| Logger.getLogger(getClass()).debug("major version = " + majorVersion);
|
92 |
| |
93 |
| |
94 |
1304
| Logger.getLogger(getClass()).debug("Reading the constant pool ...");
|
95 |
1304
| constantPool = new ConstantPool(this, in);
|
96 |
1304
| Logger.getLogger(getClass()).debug(constantPool);
|
97 |
| |
98 |
| |
99 |
1304
| accessFlag = in.readUnsignedShort();
|
100 |
1304
| Logger.getLogger(getClass()).debug("accessFlag = " + accessFlag);
|
101 |
| |
102 |
| |
103 |
1304
| classIndex = in.readUnsignedShort();
|
104 |
1304
| Logger.getLogger(getClass()).debug("thisClass = " + classIndex + " (" + getClassName() + ")");
|
105 |
| |
106 |
| |
107 |
1304
| superclassIndex = in.readUnsignedShort();
|
108 |
1304
| Logger.getLogger(getClass()).debug("superclass = " + superclassIndex + " (" + getSuperclassName() + ")");
|
109 |
| |
110 |
| |
111 |
1304
| int interfaceCount = in.readUnsignedShort();
|
112 |
1304
| Logger.getLogger(getClass()).debug("Reading " + interfaceCount + " interface(s)");
|
113 |
1304
| for (int i=0; i<interfaceCount; i++) {
|
114 |
77
| Class_info interfaceInfo = (Class_info) constantPool.get(in.readUnsignedShort());
|
115 |
77
| Logger.getLogger(getClass()).debug(" " + interfaceInfo.getName());
|
116 |
77
| interfaces.add(interfaceInfo);
|
117 |
| } |
118 |
| |
119 |
| |
120 |
1304
| int fieldCount = in.readUnsignedShort();
|
121 |
1304
| Logger.getLogger(getClass()).debug("Reading " + fieldCount + " field(s)");
|
122 |
1304
| for (int i=0; i<fieldCount; i++) {
|
123 |
1974
| Logger.getLogger(getClass()).debug("Field " + i + ":");
|
124 |
1974
| fields.add(new Field_info(this, in));
|
125 |
| } |
126 |
| |
127 |
| |
128 |
1304
| int methodCount = in.readUnsignedShort();
|
129 |
1304
| Logger.getLogger(getClass()).debug("Reading " + methodCount + " method(s)");
|
130 |
1304
| for (int i=0; i<methodCount; i++) {
|
131 |
3045
| Logger.getLogger(getClass()).debug("Method " + i + ":");
|
132 |
3045
| methods.add(new Method_info(this, in));
|
133 |
| } |
134 |
| |
135 |
| |
136 |
1304
| int attributeCount = in.readUnsignedShort();
|
137 |
1304
| Logger.getLogger(getClass()).debug("Reading " + attributeCount + " class attribute(s)");
|
138 |
1304
| for (int i=0; i<attributeCount; i++) {
|
139 |
1034
| Logger.getLogger(getClass()).debug("Attribute " + i + ":");
|
140 |
1034
| attributes.add(attributeFactory.create(constantPool, this, in));
|
141 |
| } |
142 |
| } |
143 |
| |
144 |
| |
145 |
| |
146 |
| |
147 |
16
| Classfile(ClassfileLoader loader, ConstantPool constantPool, int accessFlag, int classIndex, int superclassIndex, Iterable<Class_info> interfaces, Iterable<Field_info> fields, Iterable<Method_info> methods, Iterable<Attribute_info> attributes) {
|
148 |
16
| this.loader = loader;
|
149 |
16
| this.constantPool = constantPool;
|
150 |
16
| this.accessFlag = accessFlag;
|
151 |
16
| this.classIndex = classIndex;
|
152 |
16
| this.superclassIndex = superclassIndex;
|
153 |
| |
154 |
16
| for (Class_info interfaceInfo : interfaces) {
|
155 |
0
| this.interfaces.add(interfaceInfo);
|
156 |
| } |
157 |
| |
158 |
16
| for (Field_info field : fields) {
|
159 |
1
| this.fields.add(field);
|
160 |
| } |
161 |
| |
162 |
16
| for (Method_info method : methods) {
|
163 |
1
| this.methods.add(method);
|
164 |
| } |
165 |
| |
166 |
16
| for (Attribute_info attribute : attributes) {
|
167 |
2
| this.attributes.add(attribute);
|
168 |
| } |
169 |
| } |
170 |
| |
171 |
914
| public ClassfileLoader getLoader() {
|
172 |
914
| return loader;
|
173 |
| } |
174 |
| |
175 |
16
| public int getMagicNumber() {
|
176 |
16
| return magicNumber;
|
177 |
| } |
178 |
| |
179 |
16
| public int getMinorVersion() {
|
180 |
16
| return minorVersion;
|
181 |
| } |
182 |
| |
183 |
16
| public int getMajorVersion() {
|
184 |
16
| return majorVersion;
|
185 |
| } |
186 |
| |
187 |
228624
| public ConstantPool getConstantPool() {
|
188 |
228624
| return constantPool;
|
189 |
| } |
190 |
| |
191 |
12227
| public int getAccessFlag() {
|
192 |
12227
| return accessFlag;
|
193 |
| } |
194 |
| |
195 |
28766
| public int getClassIndex() {
|
196 |
28766
| return classIndex;
|
197 |
| } |
198 |
| |
199 |
28766
| public Class_info getRawClass() {
|
200 |
28766
| return (Class_info) getConstantPool().get(getClassIndex());
|
201 |
| } |
202 |
| |
203 |
12384
| public String getClassName() {
|
204 |
12384
| return getRawClass().getName();
|
205 |
| } |
206 |
| |
207 |
172
| public String getPackageName() {
|
208 |
172
| return getRawClass().getPackageName();
|
209 |
| } |
210 |
| |
211 |
16194
| public String getSimpleName() {
|
212 |
16194
| return getRawClass().getSimpleName();
|
213 |
| } |
214 |
| |
215 |
10288
| public int getSuperclassIndex() {
|
216 |
10288
| return superclassIndex;
|
217 |
| } |
218 |
| |
219 |
4408
| public Class_info getRawSuperclass() {
|
220 |
4408
| return (Class_info) getConstantPool().get(getSuperclassIndex());
|
221 |
| } |
222 |
| |
223 |
4024
| public String getSuperclassName() {
|
224 |
4024
| String result = "";
|
225 |
| |
226 |
4024
| if (getSuperclassIndex() != 0) {
|
227 |
4024
| result = getRawSuperclass().getName();
|
228 |
| } |
229 |
| |
230 |
4024
| return result;
|
231 |
| } |
232 |
| |
233 |
0
| public Class_info getInterface(String name) {
|
234 |
0
| for (Class_info interfaceInfo : interfaces) {
|
235 |
0
| if (interfaceInfo.getName().equals(name)) {
|
236 |
0
| return interfaceInfo;
|
237 |
| } |
238 |
| } |
239 |
| |
240 |
0
| return null;
|
241 |
| } |
242 |
| |
243 |
3621
| public Collection<Class_info> getAllInterfaces() {
|
244 |
3621
| return interfaces;
|
245 |
| } |
246 |
| |
247 |
1464
| public Collection<Field_info> getAllFields() {
|
248 |
1464
| return fields;
|
249 |
| } |
250 |
| |
251 |
3884
| public Field_info getField(String name) {
|
252 |
3884
| for (Field_info field : fields) {
|
253 |
41216
| if (field.getName().equals(name)) {
|
254 |
2754
| return field;
|
255 |
| } |
256 |
| } |
257 |
| |
258 |
1130
| return null;
|
259 |
| } |
260 |
| |
261 |
351
| public com.jeantessier.classreader.Field_info locateField(String name) {
|
262 |
351
| com.jeantessier.classreader.Field_info localField = getField(name);
|
263 |
351
| if (localField != null) {
|
264 |
1
| return localField;
|
265 |
| } |
266 |
| |
267 |
350
| com.jeantessier.classreader.Classfile superclass = getLoader().getClassfile(getSuperclassName());
|
268 |
350
| if (superclass != null) {
|
269 |
5
| com.jeantessier.classreader.Field_info inheritedField = superclass.locateField(name);
|
270 |
5
| if (inheritedField != null && (inheritedField.isPublic() || inheritedField.isProtected() || (inheritedField.isPackage() && inheritedField.getClassfile().getPackageName().equals(superclass.getPackageName())))) {
|
271 |
3
| return inheritedField;
|
272 |
| } |
273 |
| } |
274 |
| |
275 |
| |
276 |
347
| for (com.jeantessier.classreader.Class_info interfaceInfo : getAllInterfaces()) {
|
277 |
0
| com.jeantessier.classreader.Classfile interfaceClassfile = getLoader().getClassfile(interfaceInfo.getName());
|
278 |
0
| if (interfaceClassfile != null) {
|
279 |
0
| com.jeantessier.classreader.Field_info interfaceField = interfaceClassfile.locateField(name);
|
280 |
0
| if (interfaceField != null && (interfaceField.isPublic() || interfaceField.isProtected())) {
|
281 |
0
| return interfaceField;
|
282 |
| } |
283 |
| } |
284 |
| } |
285 |
| |
286 |
347
| return null;
|
287 |
| } |
288 |
| |
289 |
1271
| public Collection<Method_info> getAllMethods() {
|
290 |
1271
| return methods;
|
291 |
| } |
292 |
| |
293 |
3100
| public Method_info getMethod(String signature) {
|
294 |
3100
| for (Method_info method : methods) {
|
295 |
20326
| if (method.getSignature().equals(signature)) {
|
296 |
2612
| return method;
|
297 |
| } |
298 |
| } |
299 |
| |
300 |
488
| return null;
|
301 |
| } |
302 |
| |
303 |
131
| public com.jeantessier.classreader.Method_info locateMethod(String signature) {
|
304 |
131
| com.jeantessier.classreader.Method_info localMethod = getMethod(signature);
|
305 |
131
| if (localMethod != null) {
|
306 |
1
| return localMethod;
|
307 |
| } |
308 |
| |
309 |
130
| com.jeantessier.classreader.Classfile superclass = getLoader().getClassfile(getSuperclassName());
|
310 |
130
| if (superclass != null) {
|
311 |
5
| com.jeantessier.classreader.Method_info inheritedMethod = superclass.locateMethod(signature);
|
312 |
5
| if (inheritedMethod != null && (inheritedMethod.isPublic() || inheritedMethod.isProtected() || (inheritedMethod.isPackage() && inheritedMethod.getClassfile().getPackageName().equals(superclass.getPackageName())))) {
|
313 |
3
| return inheritedMethod;
|
314 |
| } |
315 |
| } |
316 |
| |
317 |
127
| for (com.jeantessier.classreader.Class_info inferfaceInfo : getAllInterfaces()) {
|
318 |
0
| com.jeantessier.classreader.Classfile interfaceClassfile = getLoader().getClassfile(inferfaceInfo.getName());
|
319 |
0
| if (interfaceClassfile != null) {
|
320 |
0
| com.jeantessier.classreader.Method_info interfaceMethod = interfaceClassfile.locateMethod(signature);
|
321 |
0
| if (interfaceMethod != null && (interfaceMethod.isPublic() || interfaceMethod.isProtected())) {
|
322 |
0
| return interfaceMethod;
|
323 |
| } |
324 |
| } |
325 |
| } |
326 |
| |
327 |
127
| return null;
|
328 |
| } |
329 |
| |
330 |
3114
| public Collection<Attribute_info> getAttributes() {
|
331 |
3114
| return attributes;
|
332 |
| } |
333 |
| |
334 |
2885
| public boolean isPublic() {
|
335 |
2885
| return (getAccessFlag() & ACC_PUBLIC) != 0;
|
336 |
| } |
337 |
| |
338 |
12
| public boolean isPackage() {
|
339 |
12
| return (getAccessFlag() & ACC_PUBLIC) == 0;
|
340 |
| } |
341 |
| |
342 |
2872
| public boolean isFinal() {
|
343 |
2872
| return (getAccessFlag() & ACC_FINAL) != 0;
|
344 |
| } |
345 |
| |
346 |
378
| public boolean isSuper() {
|
347 |
378
| return (getAccessFlag() & ACC_SUPER) != 0;
|
348 |
| } |
349 |
| |
350 |
3481
| public boolean isInterface() {
|
351 |
3481
| return (getAccessFlag() & ACC_INTERFACE) != 0;
|
352 |
| } |
353 |
| |
354 |
1817
| public boolean isAbstract() {
|
355 |
1817
| return (getAccessFlag() & ACC_ABSTRACT) != 0;
|
356 |
| } |
357 |
| |
358 |
18
| public boolean isAnnotation() {
|
359 |
18
| return (getAccessFlag() & ACC_ANNOTATION) != 0;
|
360 |
| } |
361 |
| |
362 |
20
| public boolean isEnum() {
|
363 |
20
| return (getAccessFlag() & ACC_ENUM) != 0;
|
364 |
| } |
365 |
| |
366 |
728
| public boolean isSynthetic() {
|
367 |
728
| return isSyntheticFromAccessFlag() || isSyntheticFromAttribute();
|
368 |
| } |
369 |
| |
370 |
728
| private boolean isSyntheticFromAccessFlag() {
|
371 |
728
| return (getAccessFlag() & ACC_SYNTHETIC) != 0;
|
372 |
| } |
373 |
| |
374 |
728
| private boolean isSyntheticFromAttribute() {
|
375 |
728
| boolean result = false;
|
376 |
| |
377 |
728
| Iterator i = getAttributes().iterator();
|
378 |
728
| while (!result && i.hasNext()) {
|
379 |
1278
| result = i.next() instanceof Synthetic_attribute;
|
380 |
| } |
381 |
| |
382 |
728
| return result;
|
383 |
| } |
384 |
| |
385 |
1949
| public boolean isDeprecated() {
|
386 |
1949
| boolean result = false;
|
387 |
| |
388 |
1949
| Iterator i = getAttributes().iterator();
|
389 |
1949
| while (!result && i.hasNext()) {
|
390 |
571
| result = i.next() instanceof Deprecated_attribute;
|
391 |
| } |
392 |
| |
393 |
1949
| return result;
|
394 |
| } |
395 |
| |
396 |
2
| public boolean isGeneric() {
|
397 |
2
| boolean result = false;
|
398 |
| |
399 |
2
| Iterator i = getAttributes().iterator();
|
400 |
2
| while (!result && i.hasNext()) {
|
401 |
3
| result = i.next() instanceof Signature_attribute;
|
402 |
| } |
403 |
| |
404 |
2
| return result;
|
405 |
| } |
406 |
| |
407 |
2437
| public String getDeclaration() {
|
408 |
2437
| StringBuffer result = new StringBuffer();
|
409 |
| |
410 |
2437
| if (isPublic()) result.append("public ");
|
411 |
6
| if (isFinal()) result.append("final ");
|
412 |
| |
413 |
2437
| if (isInterface()) {
|
414 |
1049
| result.append("interface ").append(getClassName());
|
415 |
| |
416 |
1049
| if (getAllInterfaces().size() != 0) {
|
417 |
96
| result.append(" extends ");
|
418 |
96
| Iterator i = getAllInterfaces().iterator();
|
419 |
96
| while (i.hasNext()) {
|
420 |
96
| result.append(i.next());
|
421 |
96
| if (i.hasNext()) {
|
422 |
0
| result.append(", ");
|
423 |
| } |
424 |
| } |
425 |
| } |
426 |
| } else { |
427 |
0
| if (isAbstract()) result.append("abstract ");
|
428 |
1388
| result.append("class ").append(getClassName());
|
429 |
| |
430 |
1388
| if (getSuperclassIndex() != 0) {
|
431 |
1388
| result.append(" extends ").append(getSuperclassName());
|
432 |
| } |
433 |
| |
434 |
1388
| if (getAllInterfaces().size() != 0) {
|
435 |
96
| result.append(" implements ");
|
436 |
96
| Iterator i = getAllInterfaces().iterator();
|
437 |
96
| while (i.hasNext()) {
|
438 |
96
| result.append(i.next());
|
439 |
96
| if (i.hasNext()) {
|
440 |
0
| result.append(", ");
|
441 |
| } |
442 |
| } |
443 |
| } |
444 |
| } |
445 |
| |
446 |
2437
| return result.toString();
|
447 |
| } |
448 |
| |
449 |
423
| public void accept(Visitor visitor) {
|
450 |
423
| visitor.visitClassfile(this);
|
451 |
| } |
452 |
| |
453 |
29
| public String toString() {
|
454 |
29
| return getClassName();
|
455 |
| } |
456 |
| |
457 |
3
| public boolean isInnerClass() {
|
458 |
3
| return getMatchingInnerClass() != null;
|
459 |
| } |
460 |
| |
461 |
0
| public boolean isMemberClass() {
|
462 |
0
| boolean result = false;
|
463 |
| |
464 |
0
| InnerClass innerClass = getMatchingInnerClass();
|
465 |
0
| if (innerClass != null) {
|
466 |
0
| result = innerClass.isMemberClass();
|
467 |
| } |
468 |
| |
469 |
0
| return result;
|
470 |
| } |
471 |
| |
472 |
0
| public boolean isLocalClass() {
|
473 |
0
| boolean result = false;
|
474 |
| |
475 |
0
| InnerClass innerClass = getMatchingInnerClass();
|
476 |
0
| EnclosingMethod_attribute enclosingMethod = getEnclosingMethod();
|
477 |
0
| if (innerClass != null && enclosingMethod != null) {
|
478 |
0
| result = !innerClass.isAnonymousClass();
|
479 |
| } |
480 |
| |
481 |
0
| return result;
|
482 |
| } |
483 |
| |
484 |
0
| public boolean isAnonymousClass() {
|
485 |
0
| boolean result = false;
|
486 |
| |
487 |
0
| InnerClass innerClass = getMatchingInnerClass();
|
488 |
0
| if (innerClass != null) {
|
489 |
0
| result = innerClass.isAnonymousClass();
|
490 |
| } |
491 |
| |
492 |
0
| return result;
|
493 |
| } |
494 |
| |
495 |
3
| private InnerClass getMatchingInnerClass() {
|
496 |
3
| InnerClass result = null;
|
497 |
| |
498 |
3
| for (Attribute_info attribute : getAttributes()) {
|
499 |
2
| if (attribute instanceof InnerClasses_attribute) {
|
500 |
2
| for (InnerClass innerClass : ((InnerClasses_attribute) attribute).getInnerClasses()) {
|
501 |
2
| if (innerClass.getInnerClassInfo().equals(getClassName())) {
|
502 |
1
| result = innerClass;
|
503 |
| } |
504 |
| } |
505 |
| } |
506 |
| } |
507 |
| |
508 |
3
| return result;
|
509 |
| } |
510 |
| |
511 |
0
| private EnclosingMethod_attribute getEnclosingMethod() {
|
512 |
0
| EnclosingMethod_attribute result = null;
|
513 |
| |
514 |
0
| for (Attribute_info attribute : getAttributes()) {
|
515 |
0
| if (attribute instanceof EnclosingMethod_attribute) {
|
516 |
0
| result = (EnclosingMethod_attribute) attribute;
|
517 |
| } |
518 |
| } |
519 |
| |
520 |
0
| return result;
|
521 |
| } |
522 |
| } |