1 16 17 package org.cojen.classfile; 18 19 import java.util.Collections ; 20 import java.util.HashMap ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.Map ; 24 import java.util.Set ; 25 import java.util.Vector ; 26 import java.io.DataInput ; 27 import java.io.DataOutput ; 28 import java.io.IOException ; 29 import org.cojen.classfile.constant.ConstantClassInfo; 30 import org.cojen.classfile.constant.ConstantDoubleInfo; 31 import org.cojen.classfile.constant.ConstantFieldInfo; 32 import org.cojen.classfile.constant.ConstantFloatInfo; 33 import org.cojen.classfile.constant.ConstantIntegerInfo; 34 import org.cojen.classfile.constant.ConstantInterfaceMethodInfo; 35 import org.cojen.classfile.constant.ConstantLongInfo; 36 import org.cojen.classfile.constant.ConstantMethodInfo; 37 import org.cojen.classfile.constant.ConstantNameAndTypeInfo; 38 import org.cojen.classfile.constant.ConstantStringInfo; 39 import org.cojen.classfile.constant.ConstantUTFInfo; 40 41 55 public class ConstantPool { 56 private Map mConstants = new HashMap (); 58 private Vector mIndexedConstants; 60 private int mEntries; 61 62 private boolean mPreserveOrder; 64 65 ConstantPool() { 66 } 67 68 private ConstantPool(Vector indexedConstants) { 69 mIndexedConstants = indexedConstants; 70 71 int size = indexedConstants.size(); 72 for (int i=1; i<size; i++) { 73 ConstantInfo ci = (ConstantInfo)indexedConstants.get(i); 74 if (ci != null) { 75 mConstants.put(ci, ci); 76 mEntries += ci.getEntryCount(); 77 } 78 } 79 80 mPreserveOrder = true; 81 } 82 83 92 public ConstantInfo getConstant(int index) { 93 if (mIndexedConstants == null) { 94 throw new IllegalStateException 95 ("Constant pool indexes have not been assigned"); 96 } 97 98 return (ConstantInfo)mIndexedConstants.get(index); 99 } 100 101 104 public Set getAllConstants() { 105 return Collections.unmodifiableSet(mConstants.keySet()); 106 } 107 108 111 public int getSize() { 112 return mEntries; 113 } 114 115 118 public ConstantClassInfo addConstantClass(String className) { 119 return (ConstantClassInfo)addConstant(new ConstantClassInfo(this, className)); 120 } 121 122 128 public ConstantClassInfo addConstantClass(String className, int dim) { 129 return (ConstantClassInfo)addConstant(new ConstantClassInfo(this, className, dim)); 130 } 131 132 135 public ConstantClassInfo addConstantClass(TypeDesc type) { 136 return (ConstantClassInfo)addConstant(new ConstantClassInfo(this, type)); 137 } 138 139 143 public ConstantFieldInfo addConstantField(String className, 144 String fieldName, 145 TypeDesc type) { 146 ConstantInfo ci = new ConstantFieldInfo 147 (addConstantClass(className), addConstantNameAndType(fieldName, type)); 148 return (ConstantFieldInfo)addConstant(ci); 149 } 150 151 155 public ConstantMethodInfo addConstantMethod(String className, 156 String methodName, 157 TypeDesc ret, 158 TypeDesc[] params) { 159 160 MethodDesc md = MethodDesc.forArguments(ret, params); 161 ConstantInfo ci = new ConstantMethodInfo 162 (addConstantClass(className), addConstantNameAndType(methodName, md)); 163 return (ConstantMethodInfo)addConstant(ci); 164 } 165 166 170 public ConstantInterfaceMethodInfo addConstantInterfaceMethod(String className, 171 String methodName, 172 TypeDesc ret, 173 TypeDesc[] params) { 174 175 MethodDesc md = MethodDesc.forArguments(ret, params); 176 ConstantInfo ci = new ConstantInterfaceMethodInfo 177 (addConstantClass(className), addConstantNameAndType(methodName, md)); 178 return (ConstantInterfaceMethodInfo)addConstant(ci); 179 } 180 181 185 public ConstantMethodInfo addConstantConstructor(String className, 186 TypeDesc[] params) { 187 return addConstantMethod(className, "<init>", null, params); 188 } 189 190 193 public ConstantIntegerInfo addConstantInteger(int value) { 194 return (ConstantIntegerInfo)addConstant(new ConstantIntegerInfo(value)); 195 } 196 197 200 public ConstantLongInfo addConstantLong(long value) { 201 return (ConstantLongInfo)addConstant(new ConstantLongInfo(value)); 202 } 203 204 207 public ConstantFloatInfo addConstantFloat(float value) { 208 return (ConstantFloatInfo)addConstant(new ConstantFloatInfo(value)); 209 } 210 211 214 public ConstantDoubleInfo addConstantDouble(double value) { 215 return (ConstantDoubleInfo)addConstant(new ConstantDoubleInfo(value)); 216 } 217 218 221 public ConstantStringInfo addConstantString(String str) { 222 return (ConstantStringInfo)addConstant(new ConstantStringInfo(this, str)); 223 } 224 225 228 public ConstantUTFInfo addConstantUTF(String str) { 229 return (ConstantUTFInfo)addConstant(new ConstantUTFInfo(str)); 230 } 231 232 235 public ConstantNameAndTypeInfo addConstantNameAndType(String name, 236 Descriptor type) { 237 return (ConstantNameAndTypeInfo)addConstant(new ConstantNameAndTypeInfo(this, name, type)); 238 } 239 240 243 public ConstantNameAndTypeInfo addConstantNameAndType(ConstantUTFInfo nameConstant, 244 ConstantUTFInfo descConstant) { 245 return (ConstantNameAndTypeInfo)addConstant 246 (new ConstantNameAndTypeInfo(nameConstant, descConstant)); 247 } 248 249 250 256 public ConstantInfo addConstant(ConstantInfo constant) { 257 ConstantInfo info = (ConstantInfo)mConstants.get(constant); 258 if (info != null) { 259 return info; 260 } 261 262 int entryCount = constant.getEntryCount(); 263 264 if (mIndexedConstants != null && mPreserveOrder) { 265 int size = mIndexedConstants.size(); 266 mIndexedConstants.setSize(size + entryCount); 267 mIndexedConstants.set(size, constant); 268 constant.mIndex = size; 269 } 270 271 mConstants.put(constant, constant); 272 mEntries += entryCount; 273 274 return constant; 275 } 276 277 public void writeTo(DataOutput dout) throws IOException { 278 280 int size = getSize() + 1; if (size >= 65535) { 282 throw new IllegalStateException 283 ("Constant pool entry count cannot exceed 65535: " + size); 284 } 285 dout.writeShort(size); 286 287 if (mIndexedConstants == null || !mPreserveOrder) { 288 mIndexedConstants = new Vector (size); 289 mIndexedConstants.setSize(size); 290 int index = 1; 292 298 Iterator it = mConstants.keySet().iterator(); 299 while (it.hasNext()) { 300 ConstantInfo constant = (ConstantInfo)it.next(); 301 if (constant.hasPriority()) { 302 constant.mIndex = index; 303 mIndexedConstants.set(index, constant); 304 index += constant.getEntryCount(); 305 } 306 } 307 308 310 it = mConstants.keySet().iterator(); 311 while (it.hasNext()) { 312 ConstantInfo constant = (ConstantInfo)it.next(); 313 if (!constant.hasPriority()) { 314 constant.mIndex = index; 315 mIndexedConstants.set(index, constant); 316 index += constant.getEntryCount(); 317 } 318 } 319 } 320 321 324 for (int i=1; i<size; i++) { 325 Object obj = mIndexedConstants.get(i); 326 if (obj != null) { 327 ((ConstantInfo)obj).writeTo(dout); 328 } 329 } 330 } 331 332 public static ConstantPool readFrom(DataInput din) throws IOException { 333 int size = din.readUnsignedShort(); 334 Vector constants = new Vector (size); 335 constants.setSize(size); 336 337 int index = 1; 338 while (index < size) { 339 int tag = din.readByte(); 340 int entryCount = 1; 341 Object constant; 342 343 switch (tag) { 344 case ConstantInfo.TAG_UTF8: 345 constant = new ConstantUTFInfo(din.readUTF()); 346 break; 347 case ConstantInfo.TAG_INTEGER: 348 constant = new ConstantIntegerInfo(din.readInt()); 349 break; 350 case ConstantInfo.TAG_FLOAT: 351 constant = new ConstantFloatInfo(din.readFloat()); 352 break; 353 case ConstantInfo.TAG_LONG: 354 constant = new ConstantLongInfo(din.readLong()); 355 entryCount++; 356 break; 357 case ConstantInfo.TAG_DOUBLE: 358 constant = new ConstantDoubleInfo(din.readDouble()); 359 entryCount++; 360 break; 361 362 case ConstantInfo.TAG_CLASS: 363 case ConstantInfo.TAG_STRING: 364 constant = new TempEntry(tag, din.readUnsignedShort()); 365 break; 366 367 case ConstantInfo.TAG_FIELD: 368 case ConstantInfo.TAG_METHOD: 369 case ConstantInfo.TAG_INTERFACE_METHOD: 370 case ConstantInfo.TAG_NAME_AND_TYPE: 371 constant = new TempEntry 372 (tag, (din.readShort() << 16) | (din.readUnsignedShort())); 373 break; 374 375 default: 376 throw new IOException ("Invalid constant pool tag: " + tag); 377 } 378 379 if (constant instanceof ConstantInfo) { 380 ((ConstantInfo)constant).mIndex = index; 381 } 382 383 constants.set(index, constant); 384 index += entryCount; 385 } 386 387 for (index = 1; index < size; index++) { 388 resolve(constants, index); 389 } 390 391 return new ConstantPool(constants); 392 } 393 394 private static ConstantInfo resolve(List constants, int index) { 395 Object constant = constants.get(index); 396 if (constant == null) { 397 return null; 398 } 399 400 if (constant instanceof ConstantInfo) { 401 return (ConstantInfo)constant; 402 } 403 404 TempEntry entry = (TempEntry)constant; 405 int data = entry.mData; 406 int index1 = data & 0xffff; 407 408 ConstantInfo ci1; 409 Object constant1 = constants.get(index1); 410 411 if (constant1 instanceof ConstantInfo) { 412 ci1 = (ConstantInfo)constant1; 413 } else { 414 ci1 = resolve(constants, index1); 415 } 416 417 ConstantInfo ci = null; 418 419 switch (entry.mTag) { 420 case ConstantInfo.TAG_CLASS: 421 ci = new ConstantClassInfo((ConstantUTFInfo)ci1); 422 break; 423 case ConstantInfo.TAG_STRING: 424 ci = new ConstantStringInfo((ConstantUTFInfo)ci1); 425 break; 426 427 case ConstantInfo.TAG_FIELD: 428 case ConstantInfo.TAG_METHOD: 429 case ConstantInfo.TAG_INTERFACE_METHOD: 430 case ConstantInfo.TAG_NAME_AND_TYPE: 431 int index2 = data >> 16; 432 433 ConstantInfo ci2; 434 Object constant2 = constants.get(index2); 435 436 if (constant2 instanceof ConstantInfo) { 437 ci2 = (ConstantInfo)constant2; 438 } else { 439 ci2 = resolve(constants, index2); 440 } 441 442 switch (entry.mTag) { 443 case ConstantInfo.TAG_FIELD: 444 ci = new ConstantFieldInfo 445 ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); 446 break; 447 case ConstantInfo.TAG_METHOD: 448 ci = new ConstantMethodInfo 449 ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); 450 break; 451 case ConstantInfo.TAG_INTERFACE_METHOD: 452 ci = new ConstantInterfaceMethodInfo 453 ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); 454 break; 455 case ConstantInfo.TAG_NAME_AND_TYPE: 456 ci = new ConstantNameAndTypeInfo 457 ((ConstantUTFInfo)ci2, (ConstantUTFInfo)ci1); 458 break; 459 } 460 461 break; 462 } 463 464 ci.mIndex = index; 465 constants.set(index, ci); 466 467 return ci; 468 } 469 470 private static class TempEntry { 471 public int mTag; 472 public int mData; 473 474 public TempEntry(int tag, int data) { 475 mTag = tag; 476 mData = data; 477 } 478 } 479 } 480 | Popular Tags |