1 package sli.kim.classfile; 2 3 import java.io.*; 4 5 public final class ConstPoolEntry implements Cloneable { 6 public static final int UTF = 1; 7 public static final int UNICODE = 2; 8 public static final int INT = 3; 9 public static final int FLOAT = 4; 10 public static final int LONG = 5; 11 public static final int DOUBLE = 6; 12 public static final int CLASS = 7; 13 public static final int STRING = 8; 14 public static final int FIELDREF = 9; 15 public static final int METHODREF = 10; 16 public static final int INTERFACEMETHODREF = 11; 17 public static final int NAMEANDTYPE = 12; 18 19 private byte typecode = -1; 20 21 private String stringValue; 22 private int intValue; 23 private long longValue; 24 private float floatValue; 25 private double doubleValue; 26 private short index1, index2; 27 28 public boolean equals(Object o) { 29 ConstPoolEntry other; 30 try { 31 other = (ConstPoolEntry)o; 32 } catch (ClassCastException e) { 33 return false; 34 } 35 36 if (stringValue != null && other.stringValue != null) 40 return stringValue.equals(other.stringValue); 41 42 if (typecode != other.typecode) 43 return false; 44 45 return (other.intValue == intValue && 47 other.longValue == longValue && 48 other.index1 == index1 && 49 other.index2 == index2 && 50 other.floatValue == floatValue && 51 other.doubleValue == doubleValue); 52 } 53 public int hashCode() { 54 int result = typecode * 97; 55 if (stringValue != null) 56 result += stringValue.hashCode()*43; 57 result += intValue*37 + longValue*31 + index1*29 + index2*23; 58 return result; 59 } 60 public Object clone() { 61 ConstPoolEntry result = new ConstPoolEntry(); 62 result.typecode = typecode; 63 result.stringValue = stringValue; 64 result.intValue = intValue; 65 result.longValue = longValue; 66 result.index1 = index1; 67 result.index2 = index2; 68 result.floatValue = floatValue; 69 result.doubleValue = doubleValue; 70 return result; 71 } 72 public String toString() { 73 if (UTF == typecode) 74 return "UTF \"" + stringValue + "\""; 75 else if (UNICODE == typecode) 76 return "UNICODE \"" + stringValue + "\""; 77 else if (INT == typecode) 78 return "INT " + intValue; 79 else if (FLOAT == typecode) 80 return "FLOAT " + floatValue; 81 else if (LONG == typecode) 82 return "LONG " + longValue; 83 else if (DOUBLE == typecode) 84 return "DOUBLE " + doubleValue; 85 else if (CLASS == typecode) 86 return "CLASS " + index1; 87 else if (STRING == typecode) 88 return "STRING " + index1; 89 else if (FIELDREF == typecode) 90 return "FIELDREF " + index1 + " " + index2; 91 else if (METHODREF == typecode) 92 return "METHODREF " + index1 + " " + index2; 93 else if (INTERFACEMETHODREF == typecode) 94 return "INTERFACEMETHODREF " + index1 + " " + index2; 95 else if (NAMEANDTYPE == typecode) 96 return "NAMEANDTYPE " + index1 + " " + index2; 97 else 98 return "Unknown typecode " + typecode; 99 } 100 101 public byte typecode() { 102 return typecode; 103 } 104 105 106 private void clearType() { 108 typecode = -1; 109 stringValue = null; 110 index1 = 0; 111 index2 = 0; 112 intValue = 0; 113 longValue = 0; 114 floatValue = 0; 115 doubleValue = 0; 116 } 117 121 public ConstPoolEntry setUnused() { 122 typecode = -1; 123 return this; 124 } 125 public boolean isUnused() { 126 return (typecode == -1); 127 } 128 public ConstPoolEntry setUTF(String value) { 129 clearType(); 130 typecode = UTF; 131 stringValue = value; 132 if (null == stringValue) 133 throw new ConstPoolEntryError("ConstPoolEntry.setUTF called with null string"); 134 return this; 135 } 136 public ConstPoolEntry setUnicode(String value) { 137 clearType(); 138 typecode = UNICODE; 139 stringValue = value; 140 if (null == stringValue) 141 throw new ConstPoolEntryError("ConstPoolEntry.setUTF called with null string"); 142 return this; 143 } 144 public ConstPoolEntry setInt(int value) { 145 clearType(); 146 typecode = INT; 147 intValue = value; 148 return this; 149 } 150 public ConstPoolEntry setLong(long value) { 151 clearType(); 152 typecode = LONG; 153 longValue = value; 154 return this; 155 } 156 public ConstPoolEntry setFloat(float value) { 157 clearType(); 158 typecode = FLOAT; 159 floatValue = value; 160 return this; 161 } 162 public ConstPoolEntry setDouble(double value) { 163 clearType(); 164 typecode = DOUBLE; 165 doubleValue = value; 166 return this; 167 } 168 public ConstPoolEntry setString(short index) { 169 clearType(); 170 typecode = STRING; 171 index1 = index; 172 return this; 173 } 174 public ConstPoolEntry setClass(short index) { 175 clearType(); 176 typecode = CLASS; 177 index1 = index; 178 return this; 179 } 180 public ConstPoolEntry setFieldRef(short index1, short index2) { 181 clearType(); 182 typecode = FIELDREF; 183 this.index1 = index1; 184 this.index2 = index2; 185 return this; 186 } 187 public ConstPoolEntry setMethodRef(short index1, short index2) { 188 clearType(); 189 typecode = METHODREF; 190 this.index1 = index1; 191 this.index2 = index2; 192 return this; 193 } 194 public ConstPoolEntry setInterfaceMethodRef(short index1, short index2) { 195 clearType(); 196 typecode = INTERFACEMETHODREF; 197 this.index1 = index1; 198 this.index2 = index2; 199 return this; 200 } 201 public ConstPoolEntry setNameAndType(short index1, short index2) { 202 clearType(); 203 typecode = NAMEANDTYPE; 204 this.index1 = index1; 205 this.index2 = index2; 206 return this; 207 } 208 209 210 213 public String getString() { 214 if (UTF == typecode || UNICODE == typecode) 215 return stringValue; 216 throw getError("getString()"); 217 } 218 221 public short getStringIndex() { 222 if (STRING == typecode) 223 return index1; 224 throw getError("getStringIndex()"); 225 } 226 229 public int getInt() { 230 if (INT == typecode) 231 return intValue; 232 throw getError("getInt()"); 233 } 234 237 public long getLong() { 238 if (LONG == typecode) 239 return longValue; 240 throw getError("getLong()"); 241 } 242 245 public float getFloat() { 246 if (FLOAT == typecode) 247 return floatValue; 248 throw getError("getFloat()"); 249 } 250 253 public double getDouble() { 254 if (DOUBLE == typecode) 255 return doubleValue; 256 throw getError("getDouble()"); 257 } 258 262 public Object getPrimitiveTypeValue() { 263 if (UTF == typecode || UNICODE == typecode) 264 return stringValue; 265 if (INT == typecode) 266 return new Integer (intValue); 267 if (LONG == typecode) 268 return new Long (longValue); 269 if (FLOAT == typecode) 270 return new Float (floatValue); 271 if (DOUBLE == typecode) 272 return new Double (doubleValue); 273 throw getError("getPrimitiveTypeValue()"); 274 } 275 278 public short getClassNameIndex() { 279 if (CLASS == typecode) 280 return index1; 281 throw getError("getClassNameIndex()"); 282 } 283 286 public short getClassIndex() { 287 if (FIELDREF == typecode || METHODREF == typecode 288 || INTERFACEMETHODREF == typecode) 289 return index1; 290 throw getError("getClassIndex()"); 291 } 292 295 public short getNameAndTypeIndex() { 296 if (FIELDREF == typecode || METHODREF == typecode 297 || INTERFACEMETHODREF == typecode) 298 return index2; 299 throw getError("getNameAndTypeIndex()"); 300 } 301 304 public short getNameIndex() { 305 if (NAMEANDTYPE == typecode) 306 return index1; 307 throw getError("getNameIndex()"); 308 } 309 312 public short getTypeIndex() { 313 if (NAMEANDTYPE == typecode) 314 return index2; 315 throw getError("getTypeIndex()"); 316 } 317 318 private ConstPoolEntryError getError(String method) { 320 return new ConstPoolEntryError(method + " called on ConstPoolEntry with typecode " + 321 typecode()); 322 } 323 324 325 326 331 public void read(DataInput in, ConstPoolEntry entry) 332 throws IOException, ClassFileParseException 333 { 334 byte tag = in.readByte(); 335 switch (tag) { 336 case UTF: 337 entry.setUTF(in.readUTF()); 338 break; 339 case UNICODE: 340 { 341 int length = in.readShort(); 342 char[] chars = new char[length]; 343 for (int i = 0; i < length; i++) 344 chars[i] = in.readChar(); 345 String str = new String (chars); 346 entry.setUnicode(str); 347 break; 348 } 349 case INT: 350 entry.setInt(in.readInt()); 351 break; 352 case FLOAT: 353 entry.setFloat(in.readFloat()); 354 break; 355 case LONG: 356 entry.setLong(in.readLong()); 357 break; 358 case DOUBLE: 359 entry.setDouble(in.readDouble()); 360 break; 361 case CLASS: 362 entry.setClass(in.readShort()); 363 break; 364 case STRING: 365 entry.setString(in.readShort()); 366 break; 367 case FIELDREF: 368 entry.setFieldRef(in.readShort(), in.readShort()); 369 break; 370 case METHODREF: 371 entry.setMethodRef(in.readShort(), in.readShort()); 372 break; 373 case INTERFACEMETHODREF: 374 entry.setInterfaceMethodRef(in.readShort(), in.readShort()); 375 break; 376 case NAMEANDTYPE: 377 entry.setNameAndType(in.readShort(), in.readShort()); 378 break; 379 default: 380 throw new ClassFileParseException("Unknown constant pool tag: " + tag); 381 } 382 } 383 384 388 public void write(DataOutput out, ConstPoolEntry entry) throws IOException { 389 out.writeByte(entry.typecode()); 390 switch (entry.typecode()) { 391 case UTF: 392 out.writeUTF(entry.getString()); 393 break; 394 case UNICODE: 395 { 396 char[] chars = entry.getString().toCharArray(); 397 out.writeShort(chars.length); 398 for (int i = 0; i < chars.length; i++) 399 out.writeChar(chars[i]); 400 break; 401 } 402 case INT: 403 out.writeInt(entry.getInt()); 404 break; 405 case FLOAT: 406 out.writeFloat(entry.getFloat()); 407 break; 408 case LONG: 409 out.writeLong(entry.getLong()); 410 break; 411 case DOUBLE: 412 out.writeDouble(entry.getDouble()); 413 break; 414 case CLASS: 415 short idx = entry.getClassNameIndex(); 416 out.writeShort(entry.getClassNameIndex()); 417 break; 418 case STRING: 419 out.writeShort(entry.getStringIndex()); 420 break; 421 case FIELDREF: 422 case METHODREF: 423 case INTERFACEMETHODREF: 424 out.writeShort(entry.getClassIndex()); 425 out.writeShort(entry.getNameAndTypeIndex()); 426 break; 427 case NAMEANDTYPE: 428 out.writeShort(entry.getNameIndex()); 429 out.writeShort(entry.getTypeIndex()); 430 break; 431 default: 432 throw new ConstPoolEntryError("Internal error: Unknown constant pool typecode: " + 433 entry.typecode()); 434 } 435 } 436 } | Popular Tags |