import java.io.*; public class PoolEntry { public final static int cUTF8 = 1; public final static int cInteger = 3; public final static int cFloat = 4; public final static int cLong = 5; public final static int cDouble = 6; public final static int cClassInfo = 7; public final static int cString = 8; public final static int cFieldRef = 9; public final static int cMethodRef = 10; public final static int cInterfaceMethodRef = 11; public final static int cNameAndType = 12; int tag; byte[] data; public PoolEntry(DataInputStream dis) throws IOException { tag = dis.readUnsignedByte(); int bytesToRead; switch (tag) { case cLong: case cDouble: bytesToRead = 8; break; case cInteger: case cFloat: case cFieldRef: case cMethodRef: case cNameAndType: case cInterfaceMethodRef: bytesToRead = 4; break; case cClassInfo: case cString: bytesToRead = 2; break; case cUTF8: bytesToRead = dis.readUnsignedShort(); break; default: throw new ClassFormatError("Unrecognized Constant Type " + tag); } data = new byte[bytesToRead]; int check = dis.read(data); if (check != data.length) { throw new ClassFormatError("Not enough data to fill array"); } } public String readUTF8() { if (tag != cUTF8) { throw new ClassFormatError ("This is not a UTF8 string "); } try { // first put length of string back in string int len = data.length; byte[] newdata = new byte[len+2]; newdata[0] = (byte) (len >>> 8); newdata[1] = (byte) len; System.arraycopy(data, 0, newdata, 2, data.length); ByteArrayInputStream bis = new ByteArrayInputStream(newdata); DataInputStream dis = new DataInputStream(bis); return dis.readUTF(); } catch (IOException e) { throw new ClassFormatError(e + " Bad UTF8 string"); } } public int readInteger() { if (tag != cInteger) { throw new ClassFormatError ("This is not an integer."); } return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; } public int readLong() { if (tag != cLong) { throw new ClassFormatError ("This is not a long."); } return data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; } public float readFloat() { if (tag != cFloat) { throw new ClassFormatError ("This is not a float"); } int bits = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; return Float.intBitsToFloat(bits); } public double readDouble() { if (tag != cDouble) { throw new ClassFormatError ("This is not a double"); } long bits = (long) data[0] << 56 | (long) data[1] << 48 | (long) data[2] << 40 | (long) data[3] << 32 | (long) data[4] << 24 | (long) data[5] << 16 | (long) data[6] << 8 | (long) data[7]; return Double.longBitsToDouble(bits); } public ClassInfo readClassInfo() { if (tag != cClassInfo) { throw new ClassFormatError ("This is not a ClassInfoStructure"); } return new ClassInfo(tag, data[0] << 8 | data[1]); } public RefInfo readFieldRef() { if (tag != cFieldRef) { throw new ClassFormatError ("This is not a FieldRefStructure"); } return new RefInfo(tag, data[0] << 8 | data[1], data[2] << 8 | data[3]); } public RefInfo readMethodRef() { if (tag != cMethodRef) { throw new ClassFormatError ("This is not a methodRef"); } return new RefInfo(tag, data[0] << 8 | data[1], data[2] << 8 | data[3]); } public RefInfo readInterfaceMethodRef() { if (tag != cInterfaceMethodRef) { throw new ClassFormatError ("This is not an InterfaceMethodRef"); } return new RefInfo(tag, data[0] << 8 | data[1], data[2] << 8 | data[3]); } public NameAndType readNameAndType() { if (tag != cNameAndType) { throw new ClassFormatError ("This is not a Name and Type structure"); } return new NameAndType(tag, data[0] << 8 | data[1], data[2] << 8 | data[3]); } public int readString() { if (tag != cString) { throw new ClassFormatError ("This is not a String"); } return data[0] << 8 | data[1]; } public int tag() { return tag; } public String toString() { switch (tag) { case cLong: return "long " + String.valueOf(readLong()); case cDouble: return "double " + String.valueOf(readDouble()); case cInteger: return "int " + String.valueOf(readInteger()); case cFloat: return "float " + String.valueOf(readFloat()); case cFieldRef: return "FieldRef " + String.valueOf(readFieldRef()); case cMethodRef: return "MethodRef " + String.valueOf(readMethodRef()); case cNameAndType: return "NameAndType " + String.valueOf(readNameAndType()); case cInterfaceMethodRef: return "InterfaceMethodRef " + String.valueOf(readInterfaceMethodRef()); case cClassInfo: return "ClassInfo " + String.valueOf(readClassInfo()); case cString: return "String " + String.valueOf(readString()); case cUTF8: return "UTF8 " + readUTF8(); default: throw new ClassFormatError("Unrecognized Constant Type"); } } }