001 package serp.bytecode.lowlevel; 002 003 import java.io.*; 004 import java.util.*; 005 006 import serp.bytecode.visitor.*; 007 008 /** 009 * Base type for all constant pool entries. Entries should generally be 010 * considered immutable; modifying an entry directly can have dire 011 * consequences, and often renders the resulting class file invalid. 012 * 013 * <p>Entries cannot be shared among constant pools.</p> 014 * 015 * @author Abe White 016 */ 017 public abstract class Entry implements VisitAcceptor { 018 public static final int UTF8 = 1; 019 public static final int INT = 3; 020 public static final int FLOAT = 4; 021 public static final int LONG = 5; 022 public static final int DOUBLE = 6; 023 public static final int CLASS = 7; 024 public static final int STRING = 8; 025 public static final int FIELD = 9; 026 public static final int METHOD = 10; 027 public static final int INTERFACEMETHOD = 11; 028 public static final int NAMEANDTYPE = 12; 029 private ConstantPool _pool = null; 030 private int _index = 0; 031 032 /** 033 * Read a single entry from the given bytecode stream and returns it. 034 */ 035 public static Entry read(DataInput in) throws IOException { 036 Entry entry = create(in.readUnsignedByte()); 037 entry.readData(in); 038 return entry; 039 } 040 041 /** 042 * Write the given entry to the given bytecode stream. 043 */ 044 public static void write(Entry entry, DataOutput out) 045 throws IOException { 046 out.writeByte(entry.getType()); 047 entry.writeData(out); 048 } 049 050 /** 051 * Create an entry based on its type code. 052 */ 053 public static Entry create(int type) { 054 switch (type) { 055 case CLASS: 056 return new ClassEntry(); 057 case FIELD: 058 return new FieldEntry(); 059 case METHOD: 060 return new MethodEntry(); 061 case INTERFACEMETHOD: 062 return new InterfaceMethodEntry(); 063 case STRING: 064 return new StringEntry(); 065 case INT: 066 return new IntEntry(); 067 case FLOAT: 068 return new FloatEntry(); 069 case LONG: 070 return new LongEntry(); 071 case DOUBLE: 072 return new DoubleEntry(); 073 case NAMEANDTYPE: 074 return new NameAndTypeEntry(); 075 case UTF8: 076 return new UTF8Entry(); 077 default: 078 throw new IllegalArgumentException("type = " + type); 079 } 080 } 081 082 /** 083 * Return the type code for this entry type. 084 */ 085 public abstract int getType(); 086 087 /** 088 * Return true if this is a wide entry -- i.e. if it takes up two 089 * places in the constant pool. Returns false by default. 090 */ 091 public boolean isWide() { 092 return false; 093 } 094 095 /** 096 * Returns the constant pool containing this entry, or null if none. 097 */ 098 public ConstantPool getPool() { 099 return _pool; 100 } 101 102 /** 103 * Returns the index of the entry in the owning constant pool, or 0. 104 */ 105 public int getIndex() { 106 return _index; 107 } 108 109 /** 110 * This method is called after reading the entry type from bytecode. 111 * It should read all the data for this entry from the given stream. 112 */ 113 abstract void readData(DataInput in) throws IOException; 114 115 /** 116 * This method is called after writing the entry type to bytecode. 117 * It should write all data for this entry to the given stream. 118 */ 119 abstract void writeData(DataOutput out) throws IOException; 120 121 /** 122 * Subclasses must call this method before their state is mutated. 123 */ 124 Object beforeModify() { 125 if (_pool == null) 126 return null; 127 return _pool.getKey(this); 128 } 129 130 /** 131 * Subclasses must call this method when their state is mutated. 132 */ 133 void afterModify(Object key) { 134 if (_pool != null) 135 _pool.modifyEntry(key, this); 136 } 137 138 /** 139 * Sets the owning pool of the entry. 140 */ 141 void setPool(ConstantPool pool) { 142 // attempting to overwrite current pool? 143 if (_pool != null && pool != null && _pool != pool) 144 throw new IllegalStateException("Entry already belongs to a pool"); 145 _pool = pool; 146 } 147 148 /** 149 * Set the index of this entry within the pool. 150 */ 151 void setIndex(int index) { 152 _index = index; 153 } 154 }