/* * @(#)ConstantPoolInfo.java 1.5 95/08/16 Chuck McManis * * Copyright (c) 1996 Chuck McManis, All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes and without * fee is hereby granted provided that this copyright notice * appears in all copies. * * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ package util; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; /** * This class defines an entry in the constant pool for a Java class. * The class file is primarily composed of ConstantPool entries and * manipulation is done by modifying those entries. * * @version 1.5, 16 Aug 1995 * @author Chuck McManis * @see ClassFile */ public class ConstantPoolInfo{ int type; // type of this item String name; // String for the type ConstantPoolInfo arg1; // index to first argument ConstantPoolInfo arg2; // index to second argument short index1, index2; String strValue; // ASCIZ String value int intValue; long longValue; float floatValue; double doubleValue; public static final int CLASS = 7; public static final int FIELDREF = 9; public static final int METHODREF = 10; public static final int STRING = 8; public static final int INTEGER = 3; public static final int FLOAT = 4; public static final int LONG = 5; public static final int DOUBLE = 6; public static final int INTERFACE = 11; public static final int NAMEANDTYPE = 12; public static final int ASCIZ = 1; public static final int UNICODE = 2; /** * Construct a new ConstantPoolInfo object that is of type ASCIZ */ public ConstantPoolInfo(String value) { index1 = -1; index2 = -1; arg1 = null; arg2 = null; type = ASCIZ; strValue = value; } /** * Construct a new ConstantPoolInfo object that is of type INTEGER */ public ConstantPoolInfo(int value) { index1 = -1; index2 = -1; arg1 = null; arg2 = null; type = INTEGER; intValue = value; } /** * Construct a new ConstantPoolInfo object that is of type FLOAT */ public ConstantPoolInfo(float value) { index1 = -1; index2 = -1; arg1 = null; arg2 = null; type = FLOAT; floatValue = value; } /** * Construct a new ConstantPoolInfo object that is of type LONG */ public ConstantPoolInfo(long value) { index1 = -1; index2 = -1; arg1 = null; arg2 = null; type = LONG; longValue = value; } /** * Construct a new ConstantPoolInfo object that is of type DOUBLE */ public ConstantPoolInfo(double value) { index1 = -1; index2 = -1; arg1 = null; arg2 = null; type = DOUBLE; doubleValue = value; } /** * Generic constructor */ public ConstantPoolInfo() { index1 = -1; index2 = -1; arg1 = null; arg2 = null; type = -1; } /** * return the type of this constant pool item. */ public int isType() { return (type); } public boolean read(DataInputStream dis) throws IOException { int len; char c; type = dis.readByte(); switch (type) { case CLASS: name = "Class"; index1 = dis.readShort(); index2 = -1; break; case FIELDREF: name = "Field Reference"; index1 = dis.readShort(); index2 = dis.readShort(); break; case METHODREF: name = "Method Reference"; index1 = dis.readShort(); index2 = dis.readShort(); break; case INTERFACE: name = "Interface Method Reference"; index1 = dis.readShort(); index2 = dis.readShort(); break; case NAMEANDTYPE: name = "Name and Type"; index1 = dis.readShort(); index2 = dis.readShort(); break; case STRING: name = "String"; index1 = dis.readShort(); index2 = -1; break; case INTEGER: name = "Integer"; intValue = dis.readInt(); break; case FLOAT: name = "Float"; floatValue = dis.readFloat(); break; case LONG: name = "Long"; longValue = dis.readLong(); break; case DOUBLE: name = "Double"; doubleValue = dis.readDouble(); break; case ASCIZ: case UNICODE: if (type == ASCIZ) name = "ASCIZ"; else name = "UNICODE"; StringBuffer xxBuf = new StringBuffer(); len = dis.readShort(); while (len > 0) { c = (char) (dis.readByte()); xxBuf.append(c); len--; } strValue = xxBuf.toString(); break; default: System.out.println("Warning bad type."); } return (true); } public void write(DataOutputStream dos, ConstantPoolInfo pool[]) throws IOException, Exception { dos.write(type); switch (type) { case CLASS: case STRING: dos.writeShort(indexOf(arg1, pool)); break; case FIELDREF: case METHODREF: case INTERFACE: case NAMEANDTYPE: dos.writeShort(indexOf(arg1, pool)); dos.writeShort(indexOf(arg2, pool)); break; case INTEGER: dos.writeInt(intValue); break; case FLOAT: dos.writeFloat(floatValue); break; case LONG: dos.writeLong(longValue); break; case DOUBLE: dos.writeDouble(doubleValue); break; case ASCIZ: case UNICODE: dos.writeShort(strValue.length()); dos.writeBytes(strValue); break; default: throw new Exception("ConstantPoolInfo::write() - bad type."); } } public String toString() { StringBuffer s; if (type == ASCIZ) { return(strValue); } if (type == INTEGER) { return("= "+intValue); } if (type == LONG) { return("= "+longValue); } if (type == FLOAT) { return("= "+floatValue); } if (type == DOUBLE) { return("= "+doubleValue); } s = new StringBuffer(); s.append(name); s.append(":"); if (arg1 != null) s.append(arg1.toString()); else if (index1 != -1) s.append("I1["+index1+"], "); if (arg2 != null) s.append(arg2.toString()); else if (index2 != -1) s.append("I2["+index2+"], "); return (s.toString()); } public static short indexOf(ConstantPoolInfo item, ConstantPoolInfo pool[]) throws Exception { for (int i = 0; i < pool.length; i++) { if (item == pool[i]) return (short) i; } throw new Exception("ConstantPoolInfo:: indexOf() - item not in pool."); } /** * Returns true if these constant pool items are identical. */ public boolean isEqual(ConstantPoolInfo cp) { if (cp == null) return false; if (cp.type != type) return (false); switch (cp.type) { case CLASS: case STRING: return (arg1 == cp.arg1); case FIELDREF: case METHODREF: case INTERFACE: case NAMEANDTYPE: return ((arg1 == cp.arg1) && (arg2 == cp.arg2)); case INTEGER: return (cp.intValue == intValue); case FLOAT: return (cp.floatValue == floatValue); case LONG: return (cp.longValue == longValue); case DOUBLE: return (cp.doubleValue == doubleValue); case ASCIZ: case UNICODE: return (cp.strValue.compareTo(strValue) == 0); } return (false); } /** * Returns the reference to the constant pool item that is * already in pool, that matches this one. */ public ConstantPoolInfo inPool(ConstantPoolInfo pool[]) { for (int i = 1; i < pool.length; i++) { if (isEqual(pool[i])) return (pool[i]); } return null; } }