/* --- Copyright (c) Chris Rathman 1999. All rights reserved. -----------------
> File: jasper/Pool_Collection.java
> Purpose: Constant pool collection - symbol table
> Author: Chris Rathman, 12 June 1999
> Version: 1.00
*/
package jasper;
import java.io.*;
import java.lang.reflect.*;
/*=======================================================================
= Class: Pool_Collection =
= =
= Desc: Constant Table Pool =
=======================================================================*/
class Pool_Collection {
private short count; // number of entries in the constant pool table (no zero entry)
private int[] poolType; // type of pool constant
private Pool[] pool; // constant pool table
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read constants from the input stream -
-----------------------------------------------------------------------*/
Pool_Collection(DataInputStream ios) throws IOException {
// read in the number of entries in the table
count = ios.readShort();
// allocate the arrays to hold the pool constants
poolType = new int[count];
pool = new Pool[count];
// read in the pool constants from the input stream
for (int i = 1; i < count; i++) {
// get the type of constant
poolType[i] = ios.read();
try {
Constructor myConstructor;
// get subclass that handles the constant
Class newClass = (Class)dispatch[poolType[i]][2];
try {
// for some reason this technique is not working in JDK1.2?
myConstructor = newClass.getConstructor(new Class[] {ios.getClass(), Pool_Collection.class});
} catch (NoSuchMethodException e) {
// since there is only one constructor, we can use this technique if above fails
myConstructor = newClass.getDeclaredConstructors()[0];
}
// read in the constant
pool[i] = (Pool)myConstructor.newInstance(new Object[] {ios, this});
// skip over entries for types long and double (they occupy two indexes in constant pool)
for (int n = 1; n < Integer.parseInt((String)dispatch[poolType[i]][1]); n++) {
pool[i+1] = pool[i];
i = i + 1;
}
} catch (InstantiationException e) {
throw new IOException("InstantiationException");
} catch (IllegalAccessException e) {
throw new IOException("IllegalAccessException");
} catch (InvocationTargetException e) {
throw new IOException("InvocationTargetException");
}
}
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
String toString(int cptIndex) {
if ((cptIndex == 0) || (cptIndex >= count)) {
System.out.println("Index error for constant pool table: " + cptIndex);
return "";
}
return pool[cptIndex].toString();
}
/*-----------------------------------------------------------------------
- Method: isFieldref -
- -
- Desc: test if a class field is being referenced -
-----------------------------------------------------------------------*/
boolean isFieldref(int cptIndex) {
return pool[cptIndex].isFieldref();
}
/*-----------------------------------------------------------------------
- Method: isMethodref -
- -
- Desc: test if a class method is being referenced -
-----------------------------------------------------------------------*/
boolean isMethodref(int cptIndex) {
return pool[cptIndex].isMethodref();
}
/*-----------------------------------------------------------------------
- Method: isInterfaceMethodref -
- -
- Desc: test if an interface method is being referenced -
-----------------------------------------------------------------------*/
boolean isInterfaceMethodref(int cptIndex) {
return pool[cptIndex].isInterfaceMethodref();
}
/*-----------------------------------------------------------------------
- Method: browseString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
String browseString(int cptIndex) {
return pool[cptIndex].browseString();
}
/*-----------------------------------------------------------------------
- Method: browseDescriptor -
- -
- Desc: return string representation of type descriptor -
-----------------------------------------------------------------------*/
String browseDescriptor(int cptIndex) {
return pool[cptIndex].browseDescriptor();
}
/*-----------------------------------------------------------------------
- Field: dispatch -
- -
- Desc: array used to dispatch for object instantiation -
- element[i][0] = constant type -
- element[i][1] = entries occupied constant -
- element[i][2] = class name that handles attribute -
-----------------------------------------------------------------------*/
private static Object[][] dispatch = {
{"0", "1", null},
{"1", "1", Pool_Utf8.class},
{"2", "1", Pool_Unicode.class},
{"3", "1", Pool_Integer.class},
{"4", "1", Pool_Float.class},
{"5", "2", Pool_Long.class},
{"6", "2", Pool_Double.class},
{"7", "1", Pool_Class.class},
{"8", "1", Pool_String.class},
{"9", "1", Pool_Fieldref.class},
{"10", "1", Pool_Methodref.class},
{"11", "1", Pool_InterfaceMethodref.class},
{"12", "1", Pool_NamedType.class}
};
}
/*=======================================================================
= Class: Pool =
= =
= Desc: abstract class for constant entries =
=======================================================================*/
abstract class Pool {
protected Pool_Collection pool; // store of constant pool table for use by cross-ref'd constants
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read constant from the input stream -
-----------------------------------------------------------------------*/
Pool(Pool_Collection pool) {
this.pool = pool;
}
/*-----------------------------------------------------------------------
- Method: escapeString -
- -
- Desc: replace unprintable chars with octal constant (\xxx) -
-----------------------------------------------------------------------*/
static String escapeString(String raw) {
String retVal = raw;
for (int i = 0; i < retVal.length(); i++) {
if ((retVal.charAt(i) < ' ') || (retVal.charAt(i) > '~') || (retVal.charAt(i) == '\"')) {
String s = Integer.toOctalString(retVal.charAt(i));
while (s.length() < 3) s = '0' + s;
s = '\\' + s;
if (i > 0) {
retVal = retVal.substring(0, i) + s + retVal.substring(i+1);
} else {
retVal = s + retVal.substring(i+1);
}
}
}
return retVal;
}
/*-----------------------------------------------------------------------
- Method: browseDescriptor -
- -
- Desc: convert the descriptor to resemble java code -
-----------------------------------------------------------------------*/
String browseDescriptor(String s) {
String funstring = ""; // function or field name
String typestring = ""; // type of the function or field
String arraystring = ""; // array indexes of the type descriptor
int i = 0; // index used to traverse the string
// pull off the function parameters
if (s.charAt(0) == '(') {
funstring = " (" + browseDescriptor(s.substring(1)) + ")";
s = s.substring(s.indexOf(')') + 1);
}
// pull off the array indexes
while (s.charAt(i) == '[') {
i++;
arraystring = arraystring + "[]";
}
// get the types
switch (s.charAt(i++)) {
case 'Z': typestring = "boolean"; break;
case 'B': typestring = "byte"; break;
case 'C': typestring = "char"; break;
case 'S': typestring = "short"; break;
case 'I': typestring = "int"; break;
case 'J': typestring = "long"; break;
case 'F': typestring = "float"; break;
case 'D': typestring = "double"; break;
case 'V': typestring = "void"; break;
case 'L':
// object type
int j = s.indexOf(';');
typestring = s.substring(i, j).replace('/', '.');
i = j;
break;
case ')':
// end of the function parameters
i = i - 1;
break;
}
// go past semicolons
while ((s.length() > i) && (s.charAt(i) == ';')) i++;
// if end of string then return
if (s.length() <= i) return typestring + arraystring + funstring;
// if end of function parameters then return
if (s.charAt(i) == ')') return typestring + arraystring + funstring;
// return the results
return typestring + arraystring + ", " + browseDescriptor(s.substring(i)) + funstring;
}
/*-----------------------------------------------------------------------
- Method: browseDescriptor -
- -
- Desc: overload the function to allow external calls -
-----------------------------------------------------------------------*/
String browseDescriptor() {
return browseDescriptor(this.browseString());
}
/*-----------------------------------------------------------------------
- Method: browseString -
- -
- Desc: default browse string to same as toString method -
-----------------------------------------------------------------------*/
String browseString() {
return toString();
}
/*-----------------------------------------------------------------------
- Method: isFieldref -
- -
- Desc: default to class field not being referenced -
-----------------------------------------------------------------------*/
boolean isFieldref() {
return false;
}
/*-----------------------------------------------------------------------
- Method: isMethodref -
- -
- Desc: default to class method not being referenced -
-----------------------------------------------------------------------*/
boolean isMethodref() {
return false;
}
/*-----------------------------------------------------------------------
- Method: isInterfaceMethodref -
- -
- Desc: default to interface method not being referenced -
-----------------------------------------------------------------------*/
boolean isInterfaceMethodref() {
return false;
}
}
/*=======================================================================
= Class: Pool_Utf8 =
= =
= Desc: UTF-8 encoded string constant =
=======================================================================*/
class Pool_Utf8 extends Pool {
private String value = ""; // value of UTF-8 string constant
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read UTF-8 constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Utf8(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
short length = ios.readShort();
for (int i = 0; i < length; i++) {
int a = ios.read();
if ((a & 0x80) == 0) {
value = value + (char)a;
} else if ((a & 0x20) == 0) {
int b = ios.read();
value = value + (char)(((a & 0x1f) << 6) + (b & 0x3f));
i++;
} else {
int b = ios.read();
int c = ios.read();
value = value + (char)(((a & 0xf) << 12) + ((b & 0x3f) << 6) + (c & 0x3f));
i += 2;
}
}
value = escapeString(value);
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return value;
}
}
/*=======================================================================
= Class: Pool_Unicode =
= =
= Desc: Unicode string constant =
=======================================================================*/
class Pool_Unicode extends Pool {
private String value = ""; // value of unicode string constant
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read unicode constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Unicode(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
short length = ios.readShort();
for (int i = 0; i < length; i++) {
value = value + ios.readChar();
}
value = escapeString(value);
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return value;
}
}
/*=======================================================================
= Class: Pool_Integer =
= =
= Desc: Integer constant =
=======================================================================*/
class Pool_Integer extends Pool {
private int value; // value of int constant
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read integer constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Integer(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
value = ios.readInt();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return Integer.toString(value);
}
}
/*=======================================================================
= Class: Pool_Float =
= =
= Desc: Float constant =
=======================================================================*/
class Pool_Float extends Pool {
private float value; // value of float constant
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read float constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Float(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
value = ios.readFloat();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return Float.toString(value);
}
}
/*=======================================================================
= Class: Pool_Long =
= =
= Desc: Long constant =
=======================================================================*/
class Pool_Long extends Pool {
private long value; // value of long constant
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read long constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Long(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
value = ios.readLong();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return Long.toString(value);
}
}
/*=======================================================================
= Class: Pool_Double =
= =
= Desc: Double constant =
=======================================================================*/
class Pool_Double extends Pool {
private double value; // value of double constant
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read double constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Double(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
value = ios.readDouble();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return Double.toString(value);
}
}
/*=======================================================================
= Class: Pool_Class =
= =
= Desc: Class constant =
=======================================================================*/
class Pool_Class extends Pool {
private short index; // class constant (index into constant pool table)
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read class constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Class(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
index = ios.readShort();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return pool.toString(index);
}
/*-----------------------------------------------------------------------
- Method: browseString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
String browseString() {
return toString().replace('/', '.');
}
}
/*=======================================================================
= Class: Pool_String =
= =
= Desc: String constant =
=======================================================================*/
class Pool_String extends Pool {
private short index; // constant string (index into constant pool table)
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read string constant from the input stream -
-----------------------------------------------------------------------*/
Pool_String(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
index = ios.readShort();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return "\"" + pool.toString(index) + "\"";
}
}
/*=======================================================================
= Class: Pool_Fieldref =
= =
= Desc: Class field reference constant =
=======================================================================*/
class Pool_Fieldref extends Pool {
private short classIndex; // class name (index into the constant pool table)
private short namedtypeIndex; // return type and parameters (index into the constant pool table)
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read fieldref constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Fieldref(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
classIndex = ios.readShort();
namedtypeIndex = ios.readShort();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return pool.toString(classIndex) + "/" + pool.toString(namedtypeIndex);
}
/*-----------------------------------------------------------------------
- Method: browseString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
String browseString() {
int i;
String s;
String fieldType;
String fieldName;
String className;
s = pool.browseString(namedtypeIndex);
i = s.indexOf(' ');
fieldType = s.substring(0, i);
fieldName = s.substring(i+1);
className = pool.browseString(classIndex);
return fieldType + " " + className + "." + fieldName;
}
/*-----------------------------------------------------------------------
- Method: isFieldref -
- -
- Desc: flag that a class field is referenced -
-----------------------------------------------------------------------*/
boolean isFieldref() {
return true;
}
}
/*=======================================================================
= Class: Pool_Methodref =
= =
= Desc: Class method reference constant =
=======================================================================*/
class Pool_Methodref extends Pool {
private short classIndex; // class name (index into the constant pool table)
private short namedtypeIndex; // return type and parameters (index into the constant pool table)
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read methodref constant from the input stream -
-----------------------------------------------------------------------*/
Pool_Methodref(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
classIndex = ios.readShort();
namedtypeIndex = ios.readShort();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return pool.toString(classIndex) + "/" + pool.toString(namedtypeIndex);
}
/*-----------------------------------------------------------------------
- Method: browseString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
String browseString() {
String s = pool.browseString(namedtypeIndex);
int i = s.indexOf(' ');
int j = s.indexOf('(');
String returnType = s.substring(0, i);
String functionName = s.substring(i+1, j);
String functionParams = s.substring(j);
String className = pool.browseString(classIndex);
if (functionName.equals("<init>")) {
return "new " + className + functionParams;
} else {
return returnType + " " + className + "." + functionName + functionParams;
}
}
/*-----------------------------------------------------------------------
- Method: isMethodref -
- -
- Desc: flag that a class method is referenced -
-----------------------------------------------------------------------*/
boolean isMethodref() {
return true;
}
}
/*=======================================================================
= Class: Pool_InterfaceMethodref =
= =
= Desc: Interface method reference constant =
=======================================================================*/
class Pool_InterfaceMethodref extends Pool {
private short classIndex; // class name (index into the constant pool table)
private short namedtypeIndex; // return type and parameters (index into the constant pool table)
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read interfacemethodref constant from input stream -
-----------------------------------------------------------------------*/
Pool_InterfaceMethodref(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
classIndex = ios.readShort();
namedtypeIndex = ios.readShort();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
return pool.toString(classIndex) + "/" + pool.toString(namedtypeIndex);
}
/*-----------------------------------------------------------------------
- Method: browseString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
String browseString() {
String s = pool.browseString(namedtypeIndex);
int i = s.indexOf(' ');
int j = s.indexOf('(');
String returnType = s.substring(0, i);
String functionName = s.substring(i+1, j);
String functionParams = s.substring(j);
String className = pool.browseString(classIndex);
if (functionName.equals("<init>")) {
return "new " + className + functionParams;
} else {
return returnType + " " + className + "." + functionName + functionParams;
}
}
/*-----------------------------------------------------------------------
- Method: isFieldref -
- -
- Desc: flag that an interface method is referenced -
-----------------------------------------------------------------------*/
boolean isInterfaceMethodref() {
return true;
}
}
/*=======================================================================
= Class: Pool_NamedType =
= =
= Desc: Class name and type constant =
=======================================================================*/
class Pool_NamedType extends Pool {
private short nameIndex; // field or class name (index into the constant pool table)
private short descriptorIndex; // return type and parameters (index into the constant pool table)
/*-----------------------------------------------------------------------
- Method: Class Constructor -
- -
- Desc: read namedtype constant from the input stream -
-----------------------------------------------------------------------*/
Pool_NamedType(DataInputStream ios, Pool_Collection pool) throws IOException {
super(pool);
nameIndex = ios.readShort();
descriptorIndex = ios.readShort();
}
/*-----------------------------------------------------------------------
- Method: toString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
public String toString() {
String s = pool.toString(descriptorIndex);
if (s.charAt(0) != '(') s = " " + s;
return pool.toString(nameIndex) + s;
}
/*-----------------------------------------------------------------------
- Method: browseString -
- -
- Desc: return string representation of constant -
-----------------------------------------------------------------------*/
String browseString() {
String s = pool.browseDescriptor(descriptorIndex);
int i = s.indexOf('(');
if (i > 0) {
// this is a method
return s.substring(0, i) + pool.browseString(nameIndex) + s.substring(i);
} else {
// this is a field
return s + " " + pool.browseString(nameIndex);
}
}
}