00001 package de.fub.bytecode.classfile;
00002
00003 import de.fub.bytecode.Constants;
00004 import java.io.*;
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 public class ConstantPool implements Cloneable {
00016 private int constant_pool_count;
00017 private Constant[] constant_pool;
00018
00019
00020
00021
00022 public ConstantPool(Constant[] constant_pool)
00023 {
00024 setConstantPool(constant_pool);
00025 }
00026
00027
00028
00029
00030
00031
00032
00033 ConstantPool(DataInputStream file) throws IOException, ClassFormatError
00034 {
00035 byte tag;
00036
00037 constant_pool_count = file.readUnsignedShort();
00038 constant_pool = new Constant[constant_pool_count];
00039
00040
00041
00042
00043 for(int i=1; i < constant_pool_count; i++) {
00044 constant_pool[i] = Constant.readConstant(file);
00045
00046
00047
00048
00049
00050
00051
00052
00053 tag = constant_pool[i].getTag();
00054 if((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long))
00055 i++;
00056 }
00057 }
00058
00059
00060
00061
00062
00063
00064
00065 public void accept(Visitor v) {
00066 v.visitConstantPool(this);
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076 public String constantToString(int index, byte tag)
00077 throws ClassFormatError
00078 {
00079 Constant c = getConstant(index, tag);
00080 return constantToString(c);
00081 }
00082
00083
00084
00085
00086
00087
00088 public String constantToString(Constant c)
00089 throws ClassFormatError
00090 {
00091 String str;
00092 int i;
00093 byte tag = c.getTag();
00094
00095 switch(tag) {
00096 case Constants.CONSTANT_Class:
00097 i = ((ConstantClass)c).getNameIndex();
00098 c = getConstant(i, Constants.CONSTANT_Utf8);
00099 str = Utility.compactClassName(((ConstantUtf8)c).getBytes(), false);
00100 break;
00101
00102 case Constants.CONSTANT_String:
00103 i = ((ConstantString)c).getStringIndex();
00104 c = getConstant(i, Constants.CONSTANT_Utf8);
00105 str = "\"" + escape(((ConstantUtf8)c).getBytes()) + "\"";
00106 break;
00107
00108 case Constants.CONSTANT_Utf8: str = ((ConstantUtf8)c).getBytes(); break;
00109 case Constants.CONSTANT_Double: str = "" + ((ConstantDouble)c).getBytes(); break;
00110 case Constants.CONSTANT_Float: str = "" + ((ConstantFloat)c).getBytes(); break;
00111 case Constants.CONSTANT_Long: str = "" + ((ConstantLong)c).getBytes(); break;
00112 case Constants.CONSTANT_Integer: str = "" + ((ConstantInteger)c).getBytes(); break;
00113
00114 case Constants.CONSTANT_NameAndType:
00115 str = (constantToString(((ConstantNameAndType)c).getNameIndex(),
00116 Constants.CONSTANT_Utf8) + " " +
00117 constantToString(((ConstantNameAndType)c).getSignatureIndex(),
00118 Constants.CONSTANT_Utf8));
00119 break;
00120
00121 case Constants.CONSTANT_InterfaceMethodref: case Constants.CONSTANT_Methodref:
00122 case Constants.CONSTANT_Fieldref:
00123 str = (constantToString(((ConstantCP)c).getClassIndex(),
00124 Constants.CONSTANT_Class) + "." +
00125 constantToString(((ConstantCP)c).getNameAndTypeIndex(),
00126 Constants.CONSTANT_NameAndType));
00127 break;
00128
00129 default:
00130 throw new RuntimeException("Unknown constant type " + tag);
00131 }
00132
00133 return str;
00134 }
00135
00136
00137
00138 public ConstantPool copy() {
00139 ConstantPool c = null;
00140
00141 try {
00142 c = (ConstantPool)clone();
00143 } catch(CloneNotSupportedException e) {}
00144
00145 c.constant_pool = new Constant[constant_pool_count];
00146
00147 for(int i=1; i < constant_pool_count; i++) {
00148 if(constant_pool[i] != null)
00149 c.constant_pool[i] = constant_pool[i].copy();
00150 }
00151
00152 return c;
00153 }
00154
00155
00156
00157
00158
00159
00160 public void dump(DataOutputStream file) throws IOException
00161 {
00162 file.writeShort(constant_pool_count);
00163
00164 for(int i=1; i < constant_pool_count; i++)
00165 if(constant_pool[i] != null)
00166 constant_pool[i].dump(file);
00167 }
00168 private static final String escape(String str) {
00169 int len = str.length();
00170 StringBuffer buf = new StringBuffer(len + 5);
00171 char[] ch = str.toCharArray();
00172
00173 for(int i=0; i < len; i++) {
00174 switch(ch[i]) {
00175 case '\n' : buf.append("\\n"); break;
00176 case '\r' : buf.append("\\r"); break;
00177 case '\t' : buf.append("\\t"); break;
00178 case '\b' : buf.append("\\b"); break;
00179 case '"' : buf.append("\\\""); break;
00180 default: buf.append(ch[i]);
00181 }
00182 }
00183
00184 return buf.toString();
00185 }
00186
00187
00188
00189
00190
00191
00192
00193 public Constant getConstant(int index) {
00194 return constant_pool[index];
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 public Constant getConstant(int index, byte tag)
00207 throws ClassFormatError
00208 {
00209 Constant c;
00210
00211 c = constant_pool[index];
00212
00213 if(c == null)
00214 throw new ClassFormatError("Constant pool at index " + index + " is null.");
00215
00216 if(c.getTag() == tag)
00217 return c;
00218 else
00219 throw new ClassFormatError("Expected class `" + Constants.CONSTANT_NAMES[tag] +
00220 "' at index " + index + " and got " + c);
00221 }
00222
00223
00224
00225
00226 public Constant[] getConstantPool() { return constant_pool; }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 public String getConstantString(int index, byte tag)
00241 throws ClassFormatError
00242 {
00243 Constant c;
00244 int i;
00245 String s;
00246
00247 c = getConstant(index, tag);
00248
00249
00250
00251
00252
00253
00254
00255
00256 switch(tag) {
00257 case Constants.CONSTANT_Class: i = ((ConstantClass)c).getNameIndex(); break;
00258 case Constants.CONSTANT_String: i = ((ConstantString)c).getStringIndex(); break;
00259 default:
00260 throw new RuntimeException("getConstantString called with illegal tag " + tag);
00261 }
00262
00263
00264 c = getConstant(i, Constants.CONSTANT_Utf8);
00265 return ((ConstantUtf8)c).getBytes();
00266 }
00267
00268
00269
00270 public int getLength()
00271 {
00272 return constant_pool_count;
00273 }
00274
00275
00276
00277 public void setConstant(int index, Constant constant) {
00278 constant_pool[index] = constant;
00279 }
00280
00281
00282
00283 public void setConstantPool(Constant[] constant_pool) {
00284 this.constant_pool = constant_pool;
00285 constant_pool_count = (constant_pool == null)? 0 : constant_pool.length;
00286 }
00287
00288
00289
00290 public String toString() {
00291 StringBuffer buf = new StringBuffer();
00292
00293 for(int i=1; i < constant_pool_count; i++)
00294 buf.append(i + ")" + constant_pool[i] + "\n");
00295
00296 return buf.toString();
00297 }
00298 }