1 52 53 package com.go.trove.classfile; 54 55 import java.util.*; 56 import java.io.*; 57 58 75 public class ConstantPool { 76 private Map mConstants = new HashMap(); 78 private Vector mIndexedConstants; 80 private int mEntries; 81 82 private boolean mPreserveOrder; 84 85 ConstantPool() { 86 } 87 88 private ConstantPool(Vector indexedConstants) { 89 mIndexedConstants = indexedConstants; 90 91 int size = indexedConstants.size(); 92 for (int i=1; i<size; i++) { 93 ConstantInfo ci = (ConstantInfo)indexedConstants.get(i); 94 if (ci != null) { 95 mConstants.put(ci, ci); 96 mEntries += ci.getEntryCount(); 97 } 98 } 99 100 mPreserveOrder = true; 101 } 102 103 110 public ConstantInfo getConstant(int index) { 111 if (mIndexedConstants == null) { 112 throw new ArrayIndexOutOfBoundsException 113 ("Constant pool indexes have not been assigned"); 114 } 115 116 return (ConstantInfo)mIndexedConstants.get(index); 117 } 118 119 122 public Set getAllConstants() { 123 return Collections.unmodifiableSet(mConstants.keySet()); 124 } 125 126 129 public int getSize() { 130 return mEntries; 131 } 132 133 136 public ConstantClassInfo addConstantClass(String className) { 137 return ConstantClassInfo.make(this, className); 138 } 139 140 146 public ConstantClassInfo addConstantClass(String className, int dim) { 147 return ConstantClassInfo.make(this, className, dim); 148 } 149 150 153 public ConstantClassInfo addConstantClass(TypeDescriptor type) { 154 return ConstantClassInfo.make(this, type); 155 } 156 157 161 public ConstantFieldInfo addConstantField(String className, 162 String fieldName, 163 TypeDescriptor type) { 164 return ConstantFieldInfo.make 165 (this, 166 ConstantClassInfo.make(this, className), 167 ConstantNameAndTypeInfo.make(this, fieldName, type)); 168 } 169 170 174 public ConstantMethodInfo addConstantMethod(String className, 175 String methodName, 176 TypeDescriptor ret, 177 TypeDescriptor[] params) { 178 179 MethodDescriptor md = new MethodDescriptor(ret, params); 180 181 return ConstantMethodInfo.make 182 (this, 183 ConstantClassInfo.make(this, className), 184 ConstantNameAndTypeInfo.make(this, methodName, md)); 185 } 186 187 191 public ConstantInterfaceMethodInfo addConstantInterfaceMethod 192 (String className, 193 String methodName, 194 TypeDescriptor ret, 195 TypeDescriptor[] params) { 196 197 MethodDescriptor md = new MethodDescriptor(ret, params); 198 199 return ConstantInterfaceMethodInfo.make 200 (this, 201 ConstantClassInfo.make(this, className), 202 ConstantNameAndTypeInfo.make(this, methodName, md)); 203 } 204 205 209 public ConstantMethodInfo addConstantConstructor(String className, 210 TypeDescriptor[] params) { 211 return addConstantMethod(className, "<init>", null, params); 212 } 213 214 217 public ConstantIntegerInfo addConstantInteger(int value) { 218 return ConstantIntegerInfo.make(this, value); 219 } 220 221 224 public ConstantLongInfo addConstantLong(long value) { 225 return ConstantLongInfo.make(this, value); 226 } 227 228 231 public ConstantFloatInfo addConstantFloat(float value) { 232 return ConstantFloatInfo.make(this, value); 233 } 234 235 238 public ConstantDoubleInfo addConstantDouble(double value) { 239 return ConstantDoubleInfo.make(this, value); 240 } 241 242 245 public ConstantStringInfo addConstantString(String str) { 246 return ConstantStringInfo.make(this, str); 247 } 248 249 252 public ConstantUTFInfo addConstantUTF(String str) { 253 return ConstantUTFInfo.make(this, str); 254 } 255 256 259 public ConstantNameAndTypeInfo addConstantNameAndType(String name, 260 Descriptor type) { 261 return ConstantNameAndTypeInfo.make(this, name, type); 262 } 263 264 270 public ConstantInfo addConstant(ConstantInfo constant) { 271 ConstantInfo info = (ConstantInfo)mConstants.get(constant); 272 if (info != null) { 273 return info; 274 } 275 276 int entryCount = constant.getEntryCount(); 277 278 if (mIndexedConstants != null && mPreserveOrder) { 279 int size = mIndexedConstants.size(); 280 mIndexedConstants.setSize(size + entryCount); 281 mIndexedConstants.set(size, constant); 282 } 283 284 mConstants.put(constant, constant); 285 mEntries += entryCount; 286 287 return constant; 288 } 289 290 public void writeTo(DataOutput dout) throws IOException { 291 293 int size = getSize() + 1; if (size >= 65535) { 295 throw new RuntimeException 296 ("Constant pool entry count cannot exceed 65535: " + size); 297 } 298 dout.writeShort(size); 299 300 if (mIndexedConstants == null || !mPreserveOrder) { 301 mIndexedConstants = new Vector(size); 302 mIndexedConstants.setSize(size); 303 int index = 1; 305 311 Iterator it = mConstants.keySet().iterator(); 312 while (it.hasNext()) { 313 ConstantInfo constant = (ConstantInfo)it.next(); 314 if (constant.hasPriority()) { 315 constant.mIndex = index; 316 mIndexedConstants.set(index, constant); 317 index += constant.getEntryCount(); 318 } 319 } 320 321 323 it = mConstants.keySet().iterator(); 324 while (it.hasNext()) { 325 ConstantInfo constant = (ConstantInfo)it.next(); 326 if (!constant.hasPriority()) { 327 constant.mIndex = index; 328 mIndexedConstants.set(index, constant); 329 index += constant.getEntryCount(); 330 } 331 } 332 } 333 334 337 for (int i=1; i<size; i++) { 338 Object obj = mIndexedConstants.get(i); 339 if (obj != null) { 340 ((ConstantInfo)obj).writeTo(dout); 341 } 342 } 343 } 344 345 public static ConstantPool readFrom(DataInput din) throws IOException { 346 int size = din.readUnsignedShort(); 347 Vector constants = new Vector(size); 348 constants.setSize(size); 349 350 int index = 1; 351 while (index < size) { 352 int tag = din.readByte(); 353 int entryCount = 1; 354 Object constant; 355 356 switch (tag) { 357 case ConstantInfo.TAG_UTF8: 358 constant = new ConstantUTFInfo(din.readUTF()); 359 break; 360 case ConstantInfo.TAG_INTEGER: 361 constant = new ConstantIntegerInfo(din.readInt()); 362 break; 363 case ConstantInfo.TAG_FLOAT: 364 constant = new ConstantFloatInfo(din.readFloat()); 365 break; 366 case ConstantInfo.TAG_LONG: 367 constant = new ConstantLongInfo(din.readLong()); 368 entryCount++; 369 break; 370 case ConstantInfo.TAG_DOUBLE: 371 constant = new ConstantDoubleInfo(din.readDouble()); 372 entryCount++; 373 break; 374 375 case ConstantInfo.TAG_CLASS: 376 case ConstantInfo.TAG_STRING: 377 constant = new TempEntry(tag, din.readUnsignedShort()); 378 break; 379 380 case ConstantInfo.TAG_FIELD: 381 case ConstantInfo.TAG_METHOD: 382 case ConstantInfo.TAG_INTERFACE_METHOD: 383 case ConstantInfo.TAG_NAME_AND_TYPE: 384 constant = new TempEntry 385 (tag, (din.readShort() << 16) | (din.readUnsignedShort())); 386 break; 387 388 default: 389 throw new IOException("Invalid constant pool tag: " + tag); 390 } 391 392 if (constant instanceof ConstantInfo) { 393 ((ConstantInfo)constant).mIndex = index; 394 } 395 396 constants.set(index, constant); 397 index += entryCount; 398 } 399 400 for (index = 1; index < size; index++) { 401 resolve(constants, index); 402 } 403 404 return new ConstantPool(constants); 405 } 406 407 private static ConstantInfo resolve(List constants, int index) { 408 Object constant = constants.get(index); 409 if (constant == null) { 410 return null; 411 } 412 413 if (constant instanceof ConstantInfo) { 414 return (ConstantInfo)constant; 415 } 416 417 TempEntry entry = (TempEntry)constant; 418 int data = entry.mData; 419 int index1 = data & 0xffff; 420 421 ConstantInfo ci1; 422 Object constant1 = constants.get(index1); 423 424 if (constant1 instanceof ConstantInfo) { 425 ci1 = (ConstantInfo)constant1; 426 } 427 else { 428 ci1 = resolve(constants, index1); 429 } 430 431 ConstantInfo ci = null; 432 433 switch (entry.mTag) { 434 case ConstantInfo.TAG_CLASS: 435 ci = new ConstantClassInfo((ConstantUTFInfo)ci1); 436 break; 437 case ConstantInfo.TAG_STRING: 438 ci = new ConstantStringInfo((ConstantUTFInfo)ci1); 439 break; 440 441 case ConstantInfo.TAG_FIELD: 442 case ConstantInfo.TAG_METHOD: 443 case ConstantInfo.TAG_INTERFACE_METHOD: 444 case ConstantInfo.TAG_NAME_AND_TYPE: 445 int index2 = data >> 16; 446 447 ConstantInfo ci2; 448 Object constant2 = constants.get(index2); 449 450 if (constant2 instanceof ConstantInfo) { 451 ci2 = (ConstantInfo)constant2; 452 } 453 else { 454 ci2 = resolve(constants, index2); 455 } 456 457 switch (entry.mTag) { 458 case ConstantInfo.TAG_FIELD: 459 ci = new ConstantFieldInfo 460 ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); 461 break; 462 case ConstantInfo.TAG_METHOD: 463 ci = new ConstantMethodInfo 464 ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); 465 break; 466 case ConstantInfo.TAG_INTERFACE_METHOD: 467 ci = new ConstantInterfaceMethodInfo 468 ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); 469 break; 470 case ConstantInfo.TAG_NAME_AND_TYPE: 471 ci = new ConstantNameAndTypeInfo 472 ((ConstantUTFInfo)ci2, (ConstantUTFInfo)ci1); 473 break; 474 } 475 476 break; 477 } 478 479 ci.mIndex = index; 480 constants.set(index, ci); 481 482 return ci; 483 } 484 485 private static class TempEntry { 486 public int mTag; 487 public int mData; 488 489 public TempEntry(int tag, int data) { 490 mTag = tag; 491 mData = data; 492 } 493 } 494 } 495 | Popular Tags |