git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@140 379699f6-c40d-0410-875b-85095c16579estable
parent
cec18ee2e9
commit
8a2a399945
@ -0,0 +1,84 @@ |
||||
/* jode.bytecode.AttributeInfo Copyright (C) 1997-1998 Jochen Hoenicke. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2, or (at your option) |
||||
* any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; see the file COPYING. If not, write to |
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
* |
||||
* $Id$ |
||||
*/ |
||||
package jode.bytecode; |
||||
import jode.TabbedPrintWriter; |
||||
import java.io.*; |
||||
import java.lang.reflect.Modifier; |
||||
|
||||
public class AttributeInfo { |
||||
ClassInfo classinfo; |
||||
|
||||
String name; |
||||
byte[] data; |
||||
|
||||
public AttributeInfo() { |
||||
} |
||||
|
||||
public void read(ConstantPool constantPool, |
||||
DataInputStream input, int howMuch) throws IOException { |
||||
String attrName = constantPool.getUTF8(input.readUnsignedShort()); |
||||
int length = input.readInt(); |
||||
if ((howMuch & ClassInfo.ALL_ATTRIBUTES) != 0) { |
||||
name = attrName; |
||||
data = new byte[length]; |
||||
input.read(data); |
||||
} else |
||||
input.skip(length); |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public byte[] getContents() { |
||||
return data; |
||||
} |
||||
|
||||
static final char hex[] = { '0','1','2','3','4','5','6','7', |
||||
'8','9','a','b','c','d','e','f' }; |
||||
|
||||
public void dumpSource(TabbedPrintWriter writer) throws IOException{ |
||||
if (data != null) { |
||||
writer.println("/* Attribute "+name+" ["+data.length+"]"); |
||||
writer.tab(); |
||||
StringBuffer sb = new StringBuffer(); |
||||
for (int i=0; i< data.length; i++) { |
||||
byte b = data[i]; |
||||
int h = (b<0)?b+256:b; |
||||
writer.print(" " + hex[h/16] + hex[h%16]); |
||||
if (b >=32 && b < 127) { |
||||
sb.append((char)b); |
||||
} else { |
||||
sb.append("."); |
||||
} |
||||
if (i % 16 == 15) { |
||||
writer.println(" "+sb.toString()); |
||||
sb.setLength(0); |
||||
} |
||||
} |
||||
if ((data.length % 16) != 0) { |
||||
for (int i=data.length % 16; i<16; i++) |
||||
writer.print(" "); |
||||
writer.println(" "+sb.toString()); |
||||
} |
||||
writer.untab(); |
||||
writer.println("*/"); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
/* jode.bytecode.BinaryInfo Copyright (C) 1997-1998 Jochen Hoenicke. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2, or (at your option) |
||||
* any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; see the file COPYING. If not, write to |
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
* |
||||
* $Id$ |
||||
*/ |
||||
|
||||
package jode.bytecode; |
||||
import java.io.*; |
||||
|
||||
/** |
||||
* |
||||
* @author Jochen Hoenicke |
||||
*/ |
||||
public class BinaryInfo { |
||||
public static final int HIERARCHY = 0x01; |
||||
public static final int FIELDS = 0x02; |
||||
public static final int METHODS = 0x04; |
||||
public static final int CONSTANTS = 0x08; |
||||
public static final int ALL_ATTRIBUTES = 0x10; |
||||
public static final int FULLINFO = 0xff; |
||||
|
||||
private int status = 0; |
||||
|
||||
private AttributeInfo[] attributes; |
||||
|
||||
public AttributeInfo findAttribute(String name) { |
||||
for (int i=0; i< attributes.length; i++) |
||||
if (attributes[i].getName().equals(name)) |
||||
return attributes[i]; |
||||
return null; |
||||
} |
||||
|
||||
protected void skipAttributes(DataInputStream input) throws IOException { |
||||
int count = input.readUnsignedShort(); |
||||
for (int i=0; i< count; i++) { |
||||
input.readUnsignedShort(); // the name index
|
||||
int length = input.readInt(); |
||||
input.skip(length); |
||||
} |
||||
} |
||||
|
||||
protected void readAttributes(ConstantPool constantPool, |
||||
DataInputStream input, |
||||
int howMuch) throws IOException { |
||||
if ((howMuch & ALL_ATTRIBUTES) != 0) { |
||||
int count = input.readUnsignedShort(); |
||||
attributes = new AttributeInfo[count]; |
||||
for (int i=0; i< count; i++) { |
||||
attributes[i] = new AttributeInfo(); |
||||
attributes[i].read(constantPool, input, howMuch); |
||||
} |
||||
} else |
||||
skipAttributes(input); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,277 @@ |
||||
/* jode.bytecode.ClassInfo Copyright (C) 1997-1998 Jochen Hoenicke. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2, or (at your option) |
||||
* any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; see the file COPYING. If not, write to |
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
* |
||||
* $Id$ |
||||
*/ |
||||
package jode.bytecode; |
||||
import jode.SearchPath; |
||||
import jode.MethodType; |
||||
import java.io.*; |
||||
import java.util.Hashtable; |
||||
|
||||
/** |
||||
* This class does represent a class similar to java.lang.Class. You |
||||
* can get the super class and the interfaces. |
||||
* |
||||
* The main difference to java.lang.Class is, that the objects are builded |
||||
* from a stream containing the .class file, and that it uses the |
||||
* <code>jode.Type</code> to represent types instead of Class itself. |
||||
* |
||||
* @author Jochen Hoenicke |
||||
*/ |
||||
public class ClassInfo extends BinaryInfo { |
||||
private String name; |
||||
|
||||
private static SearchPath classpath; |
||||
private static Hashtable classes = new Hashtable(); // XXX - weak map
|
||||
|
||||
private int status = 0; |
||||
|
||||
private ConstantPool constantPool; |
||||
private int modifiers = -1; |
||||
private ClassInfo superclass; |
||||
private ClassInfo[] interfaces; |
||||
private FieldInfo[] fields; |
||||
private MethodInfo[] methods; |
||||
private AttributeInfo[] attributes; |
||||
|
||||
public final static ClassInfo javaLangObject = |
||||
ClassInfo.forName("java.lang.Object"); |
||||
|
||||
public static void setClassPath(SearchPath path) { |
||||
classpath = path; |
||||
} |
||||
|
||||
|
||||
public static ClassInfo forName(String name) { |
||||
if (name == null) |
||||
return null; |
||||
name = name.replace('/', '.'); |
||||
ClassInfo clazz = (ClassInfo) classes.get(name); |
||||
if (clazz == null) { |
||||
clazz = new ClassInfo(name); |
||||
classes.put(name, clazz); |
||||
} |
||||
return clazz; |
||||
} |
||||
|
||||
public ClassInfo(String name) { |
||||
this.name = name; |
||||
} |
||||
|
||||
private void readHeader(DataInputStream input, int howMuch) |
||||
throws IOException { |
||||
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"); |
||||
} |
||||
|
||||
private ConstantPool readConstants(DataInputStream input, int howMuch) |
||||
throws IOException { |
||||
ConstantPool cpool = new ConstantPool(); |
||||
cpool.read(input); |
||||
return cpool; |
||||
} |
||||
|
||||
private void readNameAndSuper(ConstantPool cpool, |
||||
DataInputStream input, int howMuch) |
||||
throws IOException { |
||||
modifiers = input.readUnsignedShort(); |
||||
String name = cpool.getClassName(input.readUnsignedShort()); |
||||
if (!this.name.equals(name)) |
||||
new ClassFormatException("Class has wrong name: "+name); |
||||
superclass = ClassInfo.forName |
||||
(cpool.getClassName(input.readUnsignedShort())); |
||||
} |
||||
|
||||
private void readInterfaces(ConstantPool cpool, |
||||
DataInputStream input, int howMuch) |
||||
throws IOException { |
||||
int count = input.readUnsignedShort(); |
||||
interfaces = new ClassInfo[count]; |
||||
for (int i=0; i< count; i++) { |
||||
interfaces[i] = ClassInfo.forName |
||||
(cpool.getClassName(input.readUnsignedShort())); |
||||
} |
||||
} |
||||
|
||||
private void readFields(ConstantPool cpool, |
||||
DataInputStream input, int howMuch) |
||||
throws IOException { |
||||
if ((howMuch & FIELDS) != 0) { |
||||
int count = input.readUnsignedShort(); |
||||
fields = new FieldInfo[count]; |
||||
for (int i=0; i< count; i++) { |
||||
fields[i] = new FieldInfo(); |
||||
fields[i].read(cpool, input, howMuch); |
||||
} |
||||
} else { |
||||
int count = input.readUnsignedShort(); |
||||
fields = new FieldInfo[count]; |
||||
for (int i=0; i< count; i++) { |
||||
input.readUnsignedShort(); // modifier
|
||||
input.readUnsignedShort(); // name
|
||||
input.readUnsignedShort(); // type
|
||||
skipAttributes(input); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void readMethods(ConstantPool cpool, |
||||
DataInputStream input, int howMuch) |
||||
throws IOException { |
||||
if ((howMuch & METHODS) != 0) { |
||||
int count = input.readUnsignedShort(); |
||||
methods = new MethodInfo[count]; |
||||
for (int i=0; i< count; i++) { |
||||
methods[i] = new MethodInfo(); |
||||
methods[i].read(cpool, input, howMuch); |
||||
} |
||||
} else { |
||||
int count = input.readUnsignedShort(); |
||||
fields = new FieldInfo[count]; |
||||
for (int i=0; i< count; i++) { |
||||
input.readUnsignedShort(); // modifier
|
||||
input.readUnsignedShort(); // name
|
||||
input.readUnsignedShort(); // type
|
||||
skipAttributes(input); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void loadInfo(int howMuch) { |
||||
try { |
||||
DataInputStream input = |
||||
new DataInputStream(classpath.getFile(name.replace('.', '/') |
||||
+ ".class")); |
||||
readHeader(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; |
||||
|
||||
} catch (IOException ex) { |
||||
String message = ex.getLocalizedMessage(); |
||||
if ((howMuch & ~(METHODS|HIERARCHY)) == 0) |
||||
System.err.println("Can't read class " + name |
||||
+ ", types may be incorrect. (" |
||||
+ ex.getClass().getName() |
||||
+ (message != null ? ": " + message : "") |
||||
+ ")"); |
||||
else |
||||
System.err.println("Can't read class " + name + "(" |
||||
+ ex.getClass().getName() |
||||
+ (message != null ? ": " + message : "") |
||||
+ ")"); |
||||
|
||||
if (name.equals("java.lang.Object")) |
||||
superclass = null; |
||||
else |
||||
superclass = ClassInfo.forName("java.lang.Object"); |
||||
interfaces = new ClassInfo[0]; |
||||
status = FULLINFO; |
||||
} |
||||
} |
||||
|
||||
public ClassInfo getSuperclass() { |
||||
if ((status & HIERARCHY) == 0) |
||||
loadInfo(HIERARCHY); |
||||
return superclass; |
||||
} |
||||
|
||||
public ClassInfo[] getInterfaces() { |
||||
if ((status & HIERARCHY) == 0) |
||||
loadInfo(HIERARCHY); |
||||
return interfaces; |
||||
} |
||||
|
||||
public int getModifiers() { |
||||
if ((status & HIERARCHY) == 0) |
||||
loadInfo(HIERARCHY); |
||||
return modifiers; |
||||
} |
||||
|
||||
public boolean isInterface() { |
||||
return java.lang.reflect.Modifier.isInterface(getModifiers()); |
||||
} |
||||
|
||||
public String toString() { |
||||
return name; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public boolean superClassOf(ClassInfo son) { |
||||
while (son != this && son != null) { |
||||
son = son.getSuperclass(); |
||||
} |
||||
return son == this; |
||||
} |
||||
|
||||
public boolean implementedBy(ClassInfo clazz) { |
||||
while (clazz != this && clazz != null) { |
||||
ClassInfo[] ifaces = clazz.getInterfaces(); |
||||
for (int i=0; i< ifaces.length; i++) { |
||||
if (implementedBy(ifaces[i])) |
||||
return true; |
||||
} |
||||
clazz = clazz.getSuperclass(); |
||||
} |
||||
return clazz == this; |
||||
} |
||||
|
||||
public ConstantPool getConstantPool() { |
||||
if ((status & CONSTANTS) == 0) |
||||
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; |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
/* jode.bytecode.CodeInfo Copyright (C) 1997-1998 Jochen Hoenicke. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2, or (at your option) |
||||
* any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; see the file COPYING. If not, write to |
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
* |
||||
* $Id$ |
||||
*/ |
||||
package jode.bytecode; |
||||
import java.io.*; |
||||
import java.lang.reflect.Modifier; |
||||
|
||||
public class CodeInfo extends BinaryInfo { |
||||
|
||||
int maxStack, maxLocals; |
||||
byte[] code; |
||||
int[] exceptionTable; |
||||
|
||||
public int getMaxStack() { |
||||
return maxStack; |
||||
} |
||||
|
||||
public int getMaxLocals() { |
||||
return maxLocals; |
||||
} |
||||
|
||||
public byte[] getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public int[] getExceptionHandlers() { |
||||
return exceptionTable; |
||||
} |
||||
|
||||
public void read(ConstantPool constantPool, |
||||
DataInputStream input) throws IOException { |
||||
maxStack = input.readUnsignedShort(); |
||||
maxLocals = input.readUnsignedShort(); |
||||
int codeLength = input.readInt(); |
||||
code = new byte[codeLength]; |
||||
input.read(code); |
||||
int count = 4*input.readUnsignedShort(); |
||||
exceptionTable = new int[count]; |
||||
for (int i = 0; i< count; i+=4) { |
||||
exceptionTable[i+0] = input.readUnsignedShort(); |
||||
exceptionTable[i+1] = input.readUnsignedShort(); |
||||
exceptionTable[i+2] = input.readUnsignedShort(); |
||||
exceptionTable[i+3] = input.readUnsignedShort(); |
||||
} |
||||
readAttributes(constantPool, input, FULLINFO); |
||||
} |
||||
} |
@ -0,0 +1,54 @@ |
||||
/* jode.bytecode.FieldInfo Copyright (C) 1997-1998 Jochen Hoenicke. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2, or (at your option) |
||||
* any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; see the file COPYING. If not, write to |
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
* |
||||
* $Id$ |
||||
*/ |
||||
package jode.bytecode; |
||||
import jode.Type; |
||||
import java.io.*; |
||||
import java.lang.reflect.Modifier; |
||||
|
||||
public class FieldInfo extends BinaryInfo { |
||||
int modifier; |
||||
String name; |
||||
Type type; |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public Type getType() { |
||||
return type; |
||||
} |
||||
|
||||
public int getModifiers() { |
||||
return modifier; |
||||
} |
||||
|
||||
public void read(ConstantPool constantPool, |
||||
DataInputStream input, int howMuch) throws IOException { |
||||
modifier = input.readUnsignedShort(); |
||||
name = constantPool.getUTF8(input.readUnsignedShort()); |
||||
type = Type.tType(constantPool.getUTF8(input.readUnsignedShort())); |
||||
|
||||
readAttributes(constantPool, input, howMuch); |
||||
} |
||||
|
||||
public String toString() { |
||||
return "Field "+Modifier.toString(modifier)+" "+ |
||||
type.toString()+" "+name; |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
/* jode.bytecode.MethodInfo Copyright (C) 1997-1998 Jochen Hoenicke. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2, or (at your option) |
||||
* any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; see the file COPYING. If not, write to |
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
* |
||||
* $Id$ |
||||
*/ |
||||
package jode.bytecode; |
||||
import jode.MethodType; |
||||
import java.io.*; |
||||
import java.lang.reflect.Modifier; |
||||
|
||||
public class MethodInfo extends BinaryInfo { |
||||
|
||||
int modifier; |
||||
String name; |
||||
MethodType type; |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public MethodType getType() { |
||||
return type; |
||||
} |
||||
|
||||
public int getModifiers() { |
||||
return modifier; |
||||
} |
||||
|
||||
public void read(ConstantPool constantPool, |
||||
DataInputStream input, int howMuch) throws IOException { |
||||
modifier = input.readUnsignedShort(); |
||||
name = constantPool.getUTF8(input.readUnsignedShort()); |
||||
type = new MethodType(Modifier.isStatic(modifier), |
||||
constantPool.getUTF8(input.readUnsignedShort())); |
||||
readAttributes(constantPool, input, howMuch); |
||||
} |
||||
|
||||
public String toString() { |
||||
return "Method "+Modifier.toString(modifier)+" "+ |
||||
type.toString()+" "+name; |
||||
} |
||||
} |
Loading…
Reference in new issue