|
|
@ -18,8 +18,8 @@ |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
package jode.bytecode; |
|
|
|
package jode.bytecode; |
|
|
|
|
|
|
|
import jode.Decompiler; |
|
|
|
import jode.type.Type; |
|
|
|
import jode.type.Type; |
|
|
|
import jode.type.MethodType; |
|
|
|
|
|
|
|
import java.io.*; |
|
|
|
import java.io.*; |
|
|
|
import java.util.*; |
|
|
|
import java.util.*; |
|
|
|
///#ifdef JDK12
|
|
|
|
///#ifdef JDK12
|
|
|
@ -53,12 +53,13 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
|
|
|
|
|
|
|
|
private int status = 0; |
|
|
|
private int status = 0; |
|
|
|
|
|
|
|
|
|
|
|
private ConstantPool constantPool; |
|
|
|
|
|
|
|
private int modifiers = -1; |
|
|
|
private int modifiers = -1; |
|
|
|
private ClassInfo superclass; |
|
|
|
private ClassInfo superclass; |
|
|
|
private ClassInfo[] interfaces; |
|
|
|
private ClassInfo[] interfaces; |
|
|
|
private FieldInfo[] fields; |
|
|
|
private FieldInfo[] fields; |
|
|
|
private MethodInfo[] methods; |
|
|
|
private MethodInfo[] methods; |
|
|
|
|
|
|
|
private InnerClassInfo[] innerClasses; |
|
|
|
|
|
|
|
private String sourceFile; |
|
|
|
|
|
|
|
|
|
|
|
public final static ClassInfo javaLangObject = forName("java.lang.Object"); |
|
|
|
public final static ClassInfo javaLangObject = forName("java.lang.Object"); |
|
|
|
|
|
|
|
|
|
|
@ -86,7 +87,7 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
ci.fields = null; |
|
|
|
ci.fields = null; |
|
|
|
ci.interfaces = null; |
|
|
|
ci.interfaces = null; |
|
|
|
ci.methods = null; |
|
|
|
ci.methods = null; |
|
|
|
ci.attributes = null; |
|
|
|
ci.unknownAttributes = null; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -194,7 +195,7 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
fields = new FieldInfo[count]; |
|
|
|
fields = new FieldInfo[count]; |
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
fields[i] = new FieldInfo(); |
|
|
|
fields[i] = new FieldInfo(this); |
|
|
|
fields[i].read(cpool, input, howMuch); |
|
|
|
fields[i].read(cpool, input, howMuch); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -215,7 +216,7 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
methods = new MethodInfo[count]; |
|
|
|
methods = new MethodInfo[count]; |
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
methods[i] = new MethodInfo(); |
|
|
|
methods[i] = new MethodInfo(this); |
|
|
|
methods[i].read(cpool, input, howMuch); |
|
|
|
methods[i].read(cpool, input, howMuch); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -229,10 +230,209 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void loadInfoReflection(Class clazz, int howMuch) { |
|
|
|
protected void readAttribute(String name, int length, |
|
|
|
try { |
|
|
|
ConstantPool cp, |
|
|
|
modifiers = clazz.getModifiers(); |
|
|
|
DataInputStream input, |
|
|
|
|
|
|
|
int howMuch) throws IOException { |
|
|
|
|
|
|
|
if (name.equals("SourceFile")) { |
|
|
|
|
|
|
|
if (length != 2) |
|
|
|
|
|
|
|
throw new ClassFormatException("SourceFile attribute" |
|
|
|
|
|
|
|
+ " has wrong length"); |
|
|
|
|
|
|
|
sourceFile = cp.getUTF8(input.readUnsignedShort()); |
|
|
|
|
|
|
|
} else if (name.equals("InnerClasses")) { |
|
|
|
|
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
|
|
|
|
innerClasses = new InnerClassInfo[count]; |
|
|
|
|
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
|
|
|
|
int innerIndex = input.readUnsignedShort(); |
|
|
|
|
|
|
|
int outerIndex = input.readUnsignedShort(); |
|
|
|
|
|
|
|
int nameIndex = input.readUnsignedShort(); |
|
|
|
|
|
|
|
String inner = cp.getClassName(innerIndex); |
|
|
|
|
|
|
|
String outer = |
|
|
|
|
|
|
|
outerIndex != 0 ? cp.getClassName(outerIndex) : null; |
|
|
|
|
|
|
|
String innername = |
|
|
|
|
|
|
|
nameIndex != 0 ? cp.getUTF8(nameIndex) : null; |
|
|
|
|
|
|
|
int access = input.readUnsignedShort(); |
|
|
|
|
|
|
|
innerClasses[i] = new InnerClassInfo |
|
|
|
|
|
|
|
(inner, outer, innername, access); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (length != 2 + 8 * count) |
|
|
|
|
|
|
|
throw new ClassFormatException |
|
|
|
|
|
|
|
("InnerClasses attribute has wrong length"); |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
super.readAttribute(name, length, cp, input, howMuch); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void read(DataInputStream input, int howMuch) throws IOException { |
|
|
|
|
|
|
|
/* header */ |
|
|
|
|
|
|
|
if (input.readInt() != 0xcafebabe) |
|
|
|
|
|
|
|
throw new ClassFormatException("Wrong magic"); |
|
|
|
|
|
|
|
if (input.readUnsignedShort() > 3) |
|
|
|
|
|
|
|
throw new ClassFormatException("Wrong minor"); |
|
|
|
|
|
|
|
if (input.readUnsignedShort() != 45) |
|
|
|
|
|
|
|
throw new ClassFormatException("Wrong major"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* constant pool */ |
|
|
|
|
|
|
|
ConstantPool cpool = new ConstantPool(); |
|
|
|
|
|
|
|
cpool.read(input); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* always read modifiers, name, super, ifaces */ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
status |= HIERARCHY; |
|
|
|
|
|
|
|
modifiers = input.readUnsignedShort(); |
|
|
|
|
|
|
|
String className = cpool.getClassName(input.readUnsignedShort()); |
|
|
|
|
|
|
|
if (!name.equals(className)) |
|
|
|
|
|
|
|
throw new ClassFormatException("wrong name " + className); |
|
|
|
|
|
|
|
String superName = cpool.getClassName(input.readUnsignedShort()); |
|
|
|
|
|
|
|
superclass = superName != null ? ClassInfo.forName(superName) : null; |
|
|
|
|
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
|
|
|
|
interfaces = new ClassInfo[count]; |
|
|
|
|
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
|
|
|
|
interfaces[i] = ClassInfo.forName |
|
|
|
|
|
|
|
(cpool.getClassName(input.readUnsignedShort())); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* fields */ |
|
|
|
|
|
|
|
if ((howMuch & FIELDS) != 0) { |
|
|
|
|
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
|
|
|
|
fields = new FieldInfo[count]; |
|
|
|
|
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
|
|
|
|
fields[i] = new FieldInfo(this); |
|
|
|
|
|
|
|
fields[i].read(cpool, input, howMuch); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
byte[] skipBuf = new byte[6]; |
|
|
|
|
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
|
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
|
|
|
|
input.readFully(skipBuf); // modifier, name, type
|
|
|
|
|
|
|
|
skipAttributes(input); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* methods */ |
|
|
|
|
|
|
|
if ((howMuch & METHODS) != 0) { |
|
|
|
|
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
|
|
|
|
methods = new MethodInfo[count]; |
|
|
|
|
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
|
|
|
|
methods[i] = new MethodInfo(this); |
|
|
|
|
|
|
|
methods[i].read(cpool, input, howMuch); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
byte[] skipBuf = new byte[6]; |
|
|
|
|
|
|
|
int count = input.readUnsignedShort(); |
|
|
|
|
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
|
|
|
|
input.readFully(skipBuf); // modifier, name, type
|
|
|
|
|
|
|
|
skipAttributes(input); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* attributes */ |
|
|
|
|
|
|
|
readAttributes(cpool, input, howMuch); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void reserveSmallConstants(GrowableConstantPool gcp) { |
|
|
|
|
|
|
|
for (int i=0; i < fields.length; i++) |
|
|
|
|
|
|
|
fields[i].reserveSmallConstants(gcp); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i=0; i < methods.length; i++) |
|
|
|
|
|
|
|
methods[i].reserveSmallConstants(gcp); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void prepareWriting(GrowableConstantPool gcp) { |
|
|
|
|
|
|
|
gcp.putClassName(name); |
|
|
|
|
|
|
|
gcp.putClassName(superclass.getName()); |
|
|
|
|
|
|
|
for (int i=0; i < interfaces.length; i++) |
|
|
|
|
|
|
|
gcp.putClassName(interfaces[i].getName()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i=0; i < fields.length; i++) |
|
|
|
|
|
|
|
fields[i].prepareWriting(gcp); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i=0; i < methods.length; i++) |
|
|
|
|
|
|
|
methods[i].prepareWriting(gcp); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (sourceFile != null) { |
|
|
|
|
|
|
|
gcp.putUTF8("SourceFile"); |
|
|
|
|
|
|
|
gcp.putUTF8(sourceFile); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (innerClasses != null) { |
|
|
|
|
|
|
|
gcp.putUTF8("InnerClasses"); |
|
|
|
|
|
|
|
int count = innerClasses.length; |
|
|
|
|
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
|
|
|
|
gcp.putClassName(innerClasses[i].inner); |
|
|
|
|
|
|
|
if (innerClasses[i].outer != null) |
|
|
|
|
|
|
|
gcp.putClassName(innerClasses[i].outer); |
|
|
|
|
|
|
|
if (innerClasses[i].name != null) |
|
|
|
|
|
|
|
gcp.putUTF8(innerClasses[i].name); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
prepareAttributes(gcp); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected int getKnownAttributeCount() { |
|
|
|
|
|
|
|
int count = 0; |
|
|
|
|
|
|
|
if (sourceFile != null) |
|
|
|
|
|
|
|
count++; |
|
|
|
|
|
|
|
if (innerClasses != null) |
|
|
|
|
|
|
|
count++; |
|
|
|
|
|
|
|
return count; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void writeKnownAttributes(GrowableConstantPool gcp, |
|
|
|
|
|
|
|
DataOutputStream output) |
|
|
|
|
|
|
|
throws IOException { |
|
|
|
|
|
|
|
if (sourceFile != null) { |
|
|
|
|
|
|
|
output.writeShort(gcp.putUTF8("SourceFile")); |
|
|
|
|
|
|
|
output.writeInt(2); |
|
|
|
|
|
|
|
output.writeShort(gcp.putUTF8(sourceFile)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (innerClasses != null) { |
|
|
|
|
|
|
|
output.writeShort(gcp.putUTF8("InnerClasses")); |
|
|
|
|
|
|
|
int count = innerClasses.length; |
|
|
|
|
|
|
|
output.writeInt(2 + count * 8); |
|
|
|
|
|
|
|
output.writeShort(count); |
|
|
|
|
|
|
|
for (int i=0; i< count; i++) { |
|
|
|
|
|
|
|
output.writeShort(gcp.putClassName(innerClasses[i].inner)); |
|
|
|
|
|
|
|
output.writeShort(innerClasses[i].outer != null ? |
|
|
|
|
|
|
|
gcp.putClassName(innerClasses[i].outer) : 0); |
|
|
|
|
|
|
|
output.writeShort(innerClasses[i].name != null ? |
|
|
|
|
|
|
|
gcp.putUTF8(innerClasses[i].name) : 0); |
|
|
|
|
|
|
|
output.writeShort(innerClasses[i].modifiers); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void write(DataOutputStream out) throws IOException { |
|
|
|
|
|
|
|
GrowableConstantPool gcp = new GrowableConstantPool(); |
|
|
|
|
|
|
|
reserveSmallConstants(gcp); |
|
|
|
|
|
|
|
prepareWriting(gcp); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out.writeInt(0xcafebabe); |
|
|
|
|
|
|
|
out.writeShort(3); |
|
|
|
|
|
|
|
out.writeShort(45); |
|
|
|
|
|
|
|
gcp.write(out); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out.writeShort(modifiers); |
|
|
|
|
|
|
|
out.writeShort(gcp.putClassName(name)); |
|
|
|
|
|
|
|
out.writeShort(gcp.putClassName(superclass.getName())); |
|
|
|
|
|
|
|
out.writeShort(interfaces.length); |
|
|
|
|
|
|
|
for (int i=0; i < interfaces.length; i++) |
|
|
|
|
|
|
|
out.writeShort(gcp.putClassName(interfaces[i].getName())); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out.writeShort(fields.length); |
|
|
|
|
|
|
|
for (int i=0; i < fields.length; i++) |
|
|
|
|
|
|
|
fields[i].write(gcp, out); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out.writeShort(methods.length); |
|
|
|
|
|
|
|
for (int i=0; i < methods.length; i++) |
|
|
|
|
|
|
|
methods[i].write(gcp, out); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
writeAttributes(gcp, out); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void loadInfoReflection(Class clazz, int howMuch) |
|
|
|
|
|
|
|
throws SecurityException { |
|
|
|
if ((howMuch & HIERARCHY) != 0) { |
|
|
|
if ((howMuch & HIERARCHY) != 0) { |
|
|
|
|
|
|
|
modifiers = clazz.getModifiers(); |
|
|
|
if (clazz.getSuperclass() == null) |
|
|
|
if (clazz.getSuperclass() == null) |
|
|
|
superclass = null; |
|
|
|
superclass = null; |
|
|
|
else |
|
|
|
else |
|
|
@ -244,77 +444,60 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
interfaces[i] = ClassInfo.forName(ifaces[i].getName()); |
|
|
|
interfaces[i] = ClassInfo.forName(ifaces[i].getName()); |
|
|
|
status |= HIERARCHY; |
|
|
|
status |= HIERARCHY; |
|
|
|
} |
|
|
|
} |
|
|
|
if ((howMuch & FIELDS) != 0) { |
|
|
|
if ((howMuch & FIELDS) != 0 && fields == null) { |
|
|
|
Field[] fs; |
|
|
|
Field[] fs; |
|
|
|
try { |
|
|
|
try { |
|
|
|
fs = clazz.getDeclaredFields(); |
|
|
|
fs = clazz.getDeclaredFields(); |
|
|
|
} catch (SecurityException ex) { |
|
|
|
} catch (SecurityException ex) { |
|
|
|
fs = clazz.getFields(); |
|
|
|
fs = clazz.getFields(); |
|
|
|
jode.Decompiler.err.println |
|
|
|
Decompiler.err.println |
|
|
|
("Could only get public fields of class " |
|
|
|
("Could only get public fields of class " |
|
|
|
+ name + "."); |
|
|
|
+ name + "."); |
|
|
|
} |
|
|
|
} |
|
|
|
fields = new FieldInfo[fs.length]; |
|
|
|
fields = new FieldInfo[fs.length]; |
|
|
|
for (int i = fs.length; --i >= 0; ) { |
|
|
|
for (int i = fs.length; --i >= 0; ) { |
|
|
|
Type type = Type.tType(fs[i].getType()); |
|
|
|
String type = Type.getSignature(fs[i].getType()); |
|
|
|
fields[i] = new FieldInfo |
|
|
|
fields[i] = new FieldInfo |
|
|
|
(fs[i].getName(), type, fs[i].getModifiers()); |
|
|
|
(this, fs[i].getName(), type, fs[i].getModifiers()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if ((howMuch & METHODS) != 0) { |
|
|
|
if ((howMuch & METHODS) != 0 && methods == null) { |
|
|
|
Method[] ms; |
|
|
|
Method[] ms; |
|
|
|
try { |
|
|
|
try { |
|
|
|
ms = clazz.getDeclaredMethods(); |
|
|
|
ms = clazz.getDeclaredMethods(); |
|
|
|
} catch (SecurityException ex) { |
|
|
|
} catch (SecurityException ex) { |
|
|
|
ms = clazz.getMethods(); |
|
|
|
ms = clazz.getMethods(); |
|
|
|
jode.Decompiler.err.println |
|
|
|
Decompiler.err.println |
|
|
|
("Could only get public methods of class " |
|
|
|
("Could only get public methods of class " |
|
|
|
+ name + "."); |
|
|
|
+ name + "."); |
|
|
|
} |
|
|
|
} |
|
|
|
methods = new MethodInfo[ms.length]; |
|
|
|
methods = new MethodInfo[ms.length]; |
|
|
|
for (int i = ms.length; --i >= 0; ) { |
|
|
|
for (int i = ms.length; --i >= 0; ) { |
|
|
|
MethodType type = Type.tMethod |
|
|
|
String type = Type.getSignature |
|
|
|
(ms[i].getParameterTypes(), ms[i].getReturnType()); |
|
|
|
(ms[i].getParameterTypes(), ms[i].getReturnType()); |
|
|
|
methods[i] = new MethodInfo |
|
|
|
methods[i] = new MethodInfo |
|
|
|
(ms[i].getName(), type, ms[i].getModifiers()); |
|
|
|
(this, ms[i].getName(), type, ms[i].getModifiers()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if ((howMuch & ~(FIELDS|METHODS|HIERARCHY)) != 0) { |
|
|
|
|
|
|
|
jode.Decompiler.err.println |
|
|
|
|
|
|
|
("Can't find class " + name |
|
|
|
|
|
|
|
+ " in classpath, and couldn't load everything" |
|
|
|
|
|
|
|
+ " from reflection."); |
|
|
|
|
|
|
|
status |= howMuch; |
|
|
|
status |= howMuch; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} catch (SecurityException ex) { |
|
|
|
|
|
|
|
jode.Decompiler.err.println |
|
|
|
|
|
|
|
(ex+" while collecting info about class " + name + "."); |
|
|
|
|
|
|
|
jode.Decompiler.err.println("Bad things may happen?"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void loadInfo(int howMuch) { |
|
|
|
public void loadInfo(int howMuch) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
DataInputStream input = |
|
|
|
DataInputStream input = |
|
|
|
new DataInputStream(classpath.getFile(name.replace('.', '/') |
|
|
|
new DataInputStream(classpath.getFile(name.replace('.', '/') |
|
|
|
+ ".class")); |
|
|
|
+ ".class")); |
|
|
|
readHeader(input, howMuch); |
|
|
|
read(input, howMuch); |
|
|
|
|
|
|
|
|
|
|
|
ConstantPool cpool = readConstants(input, howMuch); |
|
|
|
|
|
|
|
if ((howMuch & CONSTANTS) != 0) |
|
|
|
|
|
|
|
this.constantPool = cpool; |
|
|
|
|
|
|
|
readNameAndSuper(cpool, input, howMuch); |
|
|
|
|
|
|
|
readInterfaces(cpool, input, howMuch); |
|
|
|
|
|
|
|
if ((howMuch & HIERARCHY) != 0) |
|
|
|
|
|
|
|
status |= HIERARCHY; |
|
|
|
|
|
|
|
readFields(cpool, input, howMuch); |
|
|
|
|
|
|
|
readMethods(cpool, input, howMuch); |
|
|
|
|
|
|
|
readAttributes(cpool, input, howMuch); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status |= howMuch; |
|
|
|
status |= howMuch; |
|
|
|
|
|
|
|
|
|
|
|
} catch (IOException ex) { |
|
|
|
} catch (IOException ex) { |
|
|
|
|
|
|
|
String message = ex.getMessage(); |
|
|
|
|
|
|
|
if ((howMuch & ~(FIELDS|METHODS|HIERARCHY)) != 0) { |
|
|
|
|
|
|
|
Decompiler.err.println |
|
|
|
|
|
|
|
("Can't read class " + name + "."); |
|
|
|
|
|
|
|
ex.printStackTrace(Decompiler.err); |
|
|
|
|
|
|
|
throw new NoClassDefFoundError(name); |
|
|
|
|
|
|
|
} |
|
|
|
// Try getting the info through the reflection interface
|
|
|
|
// Try getting the info through the reflection interface
|
|
|
|
// instead.
|
|
|
|
// instead.
|
|
|
|
Class clazz = null; |
|
|
|
Class clazz = null; |
|
|
@ -323,31 +506,38 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
} catch (ClassNotFoundException ex2) { |
|
|
|
} catch (ClassNotFoundException ex2) { |
|
|
|
} catch (NoClassDefFoundError ex2) { |
|
|
|
} catch (NoClassDefFoundError ex2) { |
|
|
|
} |
|
|
|
} |
|
|
|
if (clazz != null) |
|
|
|
try { |
|
|
|
loadInfoReflection(clazz, howMuch); |
|
|
|
loadInfoReflection(clazz, howMuch); |
|
|
|
else { |
|
|
|
return; |
|
|
|
// Nothing helped, ``guess'' the hierarchie
|
|
|
|
} catch (SecurityException ex2) { |
|
|
|
String message = ex.getMessage(); |
|
|
|
Decompiler.err.println |
|
|
|
if ((howMuch & ~(METHODS|HIERARCHY)) == 0) { |
|
|
|
(ex2+" while collecting info about class " + name + "."); |
|
|
|
jode.Decompiler.err.println |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Give a warning and ``guess'' the hierarchie, methods etc.
|
|
|
|
|
|
|
|
Decompiler.err.println |
|
|
|
("Can't read class " + name + ", types may be incorrect. (" |
|
|
|
("Can't read class " + name + ", types may be incorrect. (" |
|
|
|
+ ex.getClass().getName() |
|
|
|
+ ex.getClass().getName() |
|
|
|
+ (message != null ? ": " + message : "") + ")"); |
|
|
|
+ (message != null ? ": " + message : "") + ")"); |
|
|
|
} else |
|
|
|
|
|
|
|
jode.Decompiler.err.println |
|
|
|
|
|
|
|
("Can't read class " + name |
|
|
|
|
|
|
|
+ " (" + ex.getClass().getName() |
|
|
|
|
|
|
|
+ (message != null ? ": " + message : "") + ")"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((howMuch & HIERARCHY) != 0) { |
|
|
|
|
|
|
|
modifiers = Modifier.PUBLIC; |
|
|
|
if (name.equals("java.lang.Object")) |
|
|
|
if (name.equals("java.lang.Object")) |
|
|
|
superclass = null; |
|
|
|
superclass = null; |
|
|
|
else |
|
|
|
else |
|
|
|
superclass = ClassInfo.forName("java.lang.Object"); |
|
|
|
superclass = ClassInfo.forName("java.lang.Object"); |
|
|
|
interfaces = new ClassInfo[0]; |
|
|
|
interfaces = new ClassInfo[0]; |
|
|
|
modifiers = Modifier.PUBLIC; |
|
|
|
} |
|
|
|
status = FULLINFO; |
|
|
|
if ((howMuch & METHODS) != 0) |
|
|
|
|
|
|
|
methods = new MethodInfo[0]; |
|
|
|
|
|
|
|
if ((howMuch & FIELDS) != 0) |
|
|
|
|
|
|
|
fields = new FieldInfo[0]; |
|
|
|
|
|
|
|
status |= howMuch; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String getName() { |
|
|
|
|
|
|
|
return name; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public ClassInfo getSuperclass() { |
|
|
|
public ClassInfo getSuperclass() { |
|
|
@ -372,12 +562,60 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
return Modifier.isInterface(getModifiers()); |
|
|
|
return Modifier.isInterface(getModifiers()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public String toString() { |
|
|
|
public FieldInfo findField(String name, String typeSig) { |
|
|
|
return name; |
|
|
|
if ((status & FIELDS) == 0) |
|
|
|
|
|
|
|
loadInfo(FIELDS); |
|
|
|
|
|
|
|
for (int i=0; i< methods.length; i++) |
|
|
|
|
|
|
|
if (fields[i].getName().equals(name) |
|
|
|
|
|
|
|
&& fields[i].getType().equals(typeSig)) |
|
|
|
|
|
|
|
return fields[i]; |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public String getName() { |
|
|
|
public MethodInfo findMethod(String name, String typeSig) { |
|
|
|
return name; |
|
|
|
if ((status & METHODS) == 0) |
|
|
|
|
|
|
|
loadInfo(METHODS); |
|
|
|
|
|
|
|
for (int i=0; i< methods.length; i++) |
|
|
|
|
|
|
|
if (methods[i].getName().equals(name) |
|
|
|
|
|
|
|
&& methods[i].getType().equals(typeSig)) |
|
|
|
|
|
|
|
return methods[i]; |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public MethodInfo[] getMethods() { |
|
|
|
|
|
|
|
if ((status & METHODS) == 0) |
|
|
|
|
|
|
|
loadInfo(METHODS); |
|
|
|
|
|
|
|
return methods; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public FieldInfo[] getFields() { |
|
|
|
|
|
|
|
if ((status & FIELDS) == 0) |
|
|
|
|
|
|
|
loadInfo(FIELDS); |
|
|
|
|
|
|
|
return fields; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setName(String newName) { |
|
|
|
|
|
|
|
name = newName; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setSuperclass(ClassInfo newSuper) { |
|
|
|
|
|
|
|
superclass = newSuper; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setInterfaces(ClassInfo[] newIfaces) { |
|
|
|
|
|
|
|
interfaces = newIfaces; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setModifiers(int newModifiers) { |
|
|
|
|
|
|
|
modifiers = newModifiers; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setMethods(MethodInfo[] mi) { |
|
|
|
|
|
|
|
methods = mi; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setFields(FieldInfo[] fi) { |
|
|
|
|
|
|
|
fields = fi; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean superClassOf(ClassInfo son) { |
|
|
|
public boolean superClassOf(ClassInfo son) { |
|
|
@ -399,31 +637,7 @@ public class ClassInfo extends BinaryInfo { |
|
|
|
return clazz == this; |
|
|
|
return clazz == this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public ConstantPool getConstantPool() { |
|
|
|
public String toString() { |
|
|
|
if ((status & CONSTANTS) == 0) |
|
|
|
return name; |
|
|
|
loadInfo(CONSTANTS); |
|
|
|
|
|
|
|
return constantPool; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public MethodInfo findMethod(String name, MethodType type) { |
|
|
|
|
|
|
|
if ((status & METHODS) == 0) |
|
|
|
|
|
|
|
loadInfo(METHODS); |
|
|
|
|
|
|
|
for (int i=0; i< methods.length; i++) |
|
|
|
|
|
|
|
if (methods[i].getName().equals(name) |
|
|
|
|
|
|
|
&& methods[i].getType().equals(type)) |
|
|
|
|
|
|
|
return methods[i]; |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public MethodInfo[] getMethods() { |
|
|
|
|
|
|
|
if ((status & METHODS) == 0) |
|
|
|
|
|
|
|
loadInfo(METHODS); |
|
|
|
|
|
|
|
return methods; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public FieldInfo[] getFields() { |
|
|
|
|
|
|
|
if ((status & FIELDS) == 0) |
|
|
|
|
|
|
|
loadInfo(FIELDS); |
|
|
|
|
|
|
|
return fields; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|