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 Constants, 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 == CONSTANT_Double) || (tag == 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 CONSTANT_Class:
00097 i = ((ConstantClass)c).getNameIndex();
00098 c = getConstant(i, CONSTANT_Utf8);
00099 str = Utility.compactClassName(((ConstantUtf8)c).getBytes(), false);
00100 break;
00101
00102 case CONSTANT_String:
00103 i = ((ConstantString)c).getStringIndex();
00104 c = getConstant(i, CONSTANT_Utf8);
00105 str = "\"" + escape(((ConstantUtf8)c).getBytes()) + "\"";
00106 break;
00107
00108 case CONSTANT_Utf8: str = ((ConstantUtf8)c).getBytes(); break;
00109 case CONSTANT_Double: str = "" + ((ConstantDouble)c).getBytes(); break;
00110 case CONSTANT_Float: str = "" + ((ConstantFloat)c).getBytes(); break;
00111 case CONSTANT_Long: str = "" + ((ConstantLong)c).getBytes(); break;
00112 case CONSTANT_Integer: str = "" + ((ConstantInteger)c).getBytes(); break;
00113
00114 case CONSTANT_NameAndType:
00115 str = (constantToString(((ConstantNameAndType)c).getNameIndex(),
00116 CONSTANT_Utf8) + " " +
00117 constantToString(((ConstantNameAndType)c).getSignatureIndex(),
00118 CONSTANT_Utf8));
00119 break;
00120
00121 case CONSTANT_InterfaceMethodref: case CONSTANT_Methodref: case CONSTANT_Fieldref:
00122 str = (constantToString(((ConstantCP)c).getClassIndex(),
00123 CONSTANT_Class) + "." +
00124 constantToString(((ConstantCP)c).getNameAndTypeIndex(),
00125 CONSTANT_NameAndType));
00126 break;
00127
00128 default:
00129 throw new RuntimeException("Unknown constant type " + tag);
00130 }
00131
00132 return str;
00133 }
00134
00135
00136
00137 public ConstantPool copy() {
00138 ConstantPool c = null;
00139
00140 try {
00141 c = (ConstantPool)clone();
00142 } catch(CloneNotSupportedException e) {}
00143
00144 c.constant_pool = new Constant[constant_pool_count];
00145
00146 for(int i=1; i < constant_pool_count; i++) {
00147 if(constant_pool[i] != null)
00148 c.constant_pool[i] = constant_pool[i].copy();
00149 }
00150
00151 return c;
00152 }
00153
00154
00155
00156
00157
00158
00159 public void dump(DataOutputStream file) throws IOException
00160 {
00161 file.writeShort(constant_pool_count);
00162
00163 for(int i=1; i < constant_pool_count; i++)
00164 if(constant_pool[i] != null)
00165 constant_pool[i].dump(file);
00166 }
00167 private static final String escape(String str) {
00168 int len = str.length();
00169 StringBuffer buf = new StringBuffer(len + 5);
00170 char[] ch = str.toCharArray();
00171
00172 for(int i=0; i < len; i++) {
00173 switch(ch[i]) {
00174 case '\n' : buf.append("\\n"); break;
00175 case '\r' : buf.append("\\r"); break;
00176 case '\t' : buf.append("\\t"); break;
00177 case '\b' : buf.append("\\b"); break;
00178 case '"' : buf.append("\\\""); break;
00179 default: buf.append(ch[i]);
00180 }
00181 }
00182
00183 return buf.toString();
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 public Constant getConstant(int index) {
00193 return constant_pool[index];
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 public Constant getConstant(int index, byte tag)
00206 throws ClassFormatError
00207 {
00208 Constant c;
00209
00210 c = constant_pool[index];
00211
00212 if(c == null)
00213 throw new ClassFormatError("Constant pool at index " + index + " is null.");
00214
00215 if(c.getTag() == tag)
00216 return c;
00217 else
00218 throw new ClassFormatError("Expected class `" + CONSTANT_NAMES[tag] +
00219 "' at index " + index + " and got " + c);
00220 }
00221
00222
00223
00224
00225 public Constant[] getConstantPool() { return constant_pool; }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 public String getConstantString(int index, byte tag)
00240 throws ClassFormatError
00241 {
00242 Constant c;
00243 int i;
00244 String s;
00245
00246 c = getConstant(index, tag);
00247
00248
00249
00250
00251
00252
00253
00254
00255 switch(tag) {
00256 case CONSTANT_Class: i = ((ConstantClass)c).getNameIndex(); break;
00257 case CONSTANT_String: i = ((ConstantString)c).getStringIndex(); break;
00258 default: throw new RuntimeException("getConstantString" +
00259 "called with illegal tag " +
00260 tag);
00261 }
00262
00263
00264 c = getConstant(i, 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 }