001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.bcel.generic; 018 019import java.util.Arrays; 020import java.util.HashMap; 021import java.util.Map; 022 023import org.apache.bcel.Const; 024import org.apache.bcel.classfile.Constant; 025import org.apache.bcel.classfile.ConstantCP; 026import org.apache.bcel.classfile.ConstantClass; 027import org.apache.bcel.classfile.ConstantDouble; 028import org.apache.bcel.classfile.ConstantDynamic; 029import org.apache.bcel.classfile.ConstantFieldref; 030import org.apache.bcel.classfile.ConstantFloat; 031import org.apache.bcel.classfile.ConstantInteger; 032import org.apache.bcel.classfile.ConstantInterfaceMethodref; 033import org.apache.bcel.classfile.ConstantInvokeDynamic; 034import org.apache.bcel.classfile.ConstantLong; 035import org.apache.bcel.classfile.ConstantMethodref; 036import org.apache.bcel.classfile.ConstantNameAndType; 037import org.apache.bcel.classfile.ConstantPool; 038import org.apache.bcel.classfile.ConstantString; 039import org.apache.bcel.classfile.ConstantUtf8; 040import org.apache.bcel.classfile.Utility; 041 042/** 043 * This class is used to build up a constant pool. The user adds constants via 'addXXX' methods, 'addString', 044 * 'addClass', etc.. These methods return an index into the constant pool. Finally, 'getFinalConstantPool()' returns the 045 * constant pool built up. Intermediate versions of the constant pool can be obtained with 'getConstantPool()'. A 046 * constant pool has capacity for Constants.MAX_SHORT entries. Note that the first (0) is used by the JVM and that 047 * Double and Long constants need two slots. 048 * 049 * @see Constant 050 */ 051public class ConstantPoolGen { 052 053 private static final int DEFAULT_BUFFER_SIZE = 256; 054 055 private static final String METHODREF_DELIM = ":"; 056 057 private static final String IMETHODREF_DELIM = "#"; 058 059 private static final String FIELDREF_DELIM = "&"; 060 061 private static final String NAT_DELIM = "%"; // Name and Type 062 063 /** 064 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 065 */ 066 @Deprecated 067 protected int size; 068 069 /** 070 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 071 */ 072 @Deprecated 073 protected Constant[] constants; 074 075 /** 076 * @deprecated (since 6.0) will be made private; do not access directly, use getSize() 077 */ 078 @Deprecated 079 protected int index = 1; // First entry (0) used by JVM 080 081 private final Map<String, Integer> stringTable = new HashMap<>(); 082 083 private final Map<String, Integer> classTable = new HashMap<>(); 084 085 private final Map<String, Integer> utf8Table = new HashMap<>(); 086 087 private final Map<String, Integer> natTable = new HashMap<>(); 088 089 private final Map<String, Integer> cpTable = new HashMap<>(); 090 091 /** 092 * Constructs a new empty constant pool. 093 */ 094 public ConstantPoolGen() { 095 size = DEFAULT_BUFFER_SIZE; 096 constants = new Constant[size]; 097 } 098 099 /** 100 * Constructs a new instance with the given array of constants. 101 * 102 * @param cs array of given constants, new ones will be appended 103 */ 104 public ConstantPoolGen(final Constant[] cs) { 105 final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE); 106 107 size = Math.min(Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64), Const.MAX_CP_ENTRIES + 1); 108 constants = Arrays.copyOf(cs, size); 109 110 if (cs.length > 0) { 111 index = cs.length; 112 } 113 114 for (int i = 1; i < index; i++) { 115 final Constant c = constants[i]; 116 if (c instanceof ConstantString) { 117 final ConstantString s = (ConstantString) c; 118 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; 119 final String key = u8.getBytes(); 120 if (!stringTable.containsKey(key)) { 121 stringTable.put(key, Integer.valueOf(i)); 122 } 123 } else if (c instanceof ConstantClass) { 124 final ConstantClass s = (ConstantClass) c; 125 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; 126 final String key = u8.getBytes(); 127 if (!classTable.containsKey(key)) { 128 classTable.put(key, Integer.valueOf(i)); 129 } 130 } else if (c instanceof ConstantNameAndType) { 131 final ConstantNameAndType n = (ConstantNameAndType) c; 132 final ConstantUtf8 u8NameIdx = (ConstantUtf8) constants[n.getNameIndex()]; 133 final ConstantUtf8 u8SigIdx = (ConstantUtf8) constants[n.getSignatureIndex()]; 134 135 sb.append(u8NameIdx.getBytes()); 136 sb.append(NAT_DELIM); 137 sb.append(u8SigIdx.getBytes()); 138 final String key = sb.toString(); 139 sb.delete(0, sb.length()); 140 141 if (!natTable.containsKey(key)) { 142 natTable.put(key, Integer.valueOf(i)); 143 } 144 } else if (c instanceof ConstantUtf8) { 145 final ConstantUtf8 u = (ConstantUtf8) c; 146 final String key = u.getBytes(); 147 if (!utf8Table.containsKey(key)) { 148 utf8Table.put(key, Integer.valueOf(i)); 149 } 150 } else if (c instanceof ConstantCP) { 151 final ConstantCP m = (ConstantCP) c; 152 String className; 153 ConstantUtf8 u8; 154 155 if (c instanceof ConstantInvokeDynamic) { 156 className = Integer.toString(((ConstantInvokeDynamic) m).getBootstrapMethodAttrIndex()); 157 } else if (c instanceof ConstantDynamic) { 158 className = Integer.toString(((ConstantDynamic) m).getBootstrapMethodAttrIndex()); 159 } else { 160 final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; 161 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; 162 className = Utility.pathToPackage(u8.getBytes()); 163 } 164 165 final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; 166 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 167 final String methodName = u8.getBytes(); 168 u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; 169 final String signature = u8.getBytes(); 170 171 // Since name cannot begin with digit, we can use METHODREF_DELIM without fear of duplicates 172 String delim = METHODREF_DELIM; 173 if (c instanceof ConstantInterfaceMethodref) { 174 delim = IMETHODREF_DELIM; 175 } else if (c instanceof ConstantFieldref) { 176 delim = FIELDREF_DELIM; 177 } 178 179 sb.append(className); 180 sb.append(delim); 181 sb.append(methodName); 182 sb.append(delim); 183 sb.append(signature); 184 final String key = sb.toString(); 185 sb.delete(0, sb.length()); 186 187 if (!cpTable.containsKey(key)) { 188 cpTable.put(key, Integer.valueOf(i)); 189 } 190 } 191// else if (c == null) { // entries may be null 192// // nothing to do 193// } else if (c instanceof ConstantInteger) { 194// // nothing to do 195// } else if (c instanceof ConstantLong) { 196// // nothing to do 197// } else if (c instanceof ConstantFloat) { 198// // nothing to do 199// } else if (c instanceof ConstantDouble) { 200// // nothing to do 201// } else if (c instanceof org.apache.bcel.classfile.ConstantMethodType) { 202// // TODO should this be handled somehow? 203// } else if (c instanceof org.apache.bcel.classfile.ConstantMethodHandle) { 204// // TODO should this be handled somehow? 205// } else if (c instanceof org.apache.bcel.classfile.ConstantModule) { 206// // TODO should this be handled somehow? 207// } else if (c instanceof org.apache.bcel.classfile.ConstantPackage) { 208// // TODO should this be handled somehow? 209// } else { 210// // Not helpful, should throw an exception. 211// assert false : "Unexpected constant type: " + c.getClass().getName(); 212// } 213 } 214 } 215 216 /** 217 * Constructs a new instance with the given constant pool. 218 * 219 * @param cp the constant pool. 220 */ 221 public ConstantPoolGen(final ConstantPool cp) { 222 this(cp.getConstantPool()); 223 } 224 225 /** 226 * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY instruction, e.g. to the 227 * ConstantPool. 228 * 229 * @param type type of array class 230 * @return index of entry 231 */ 232 public int addArrayClass(final ArrayType type) { 233 return addClass_(type.getSignature()); 234 } 235 236 /** 237 * Add a new Class reference to the ConstantPool for a given type. 238 * 239 * @param type Class to add 240 * @return index of entry 241 */ 242 public int addClass(final ObjectType type) { 243 return addClass(type.getClassName()); 244 } 245 246 /** 247 * Add a new Class reference to the ConstantPool, if it is not already in there. 248 * 249 * @param str Class to add 250 * @return index of entry 251 */ 252 public int addClass(final String str) { 253 return addClass_(Utility.packageToPath(str)); 254 } 255 256 private int addClass_(final String clazz) { 257 final int cpRet; 258 if ((cpRet = lookupClass(clazz)) != -1) { 259 return cpRet; // Already in CP 260 } 261 adjustSize(); 262 final ConstantClass c = new ConstantClass(addUtf8(clazz)); 263 final int ret = index; 264 constants[index++] = c; 265 return computeIfAbsent(classTable, clazz, ret); 266 } 267 268 /** 269 * Adds a constant from another ConstantPool and returns the new index. 270 * 271 * @param constant The constant to add. 272 * @param cpGen Source pool. 273 * @return index of entry 274 */ 275 public int addConstant(final Constant constant, final ConstantPoolGen cpGen) { 276 final Constant[] constants = cpGen.getConstantPool().getConstantPool(); 277 switch (constant.getTag()) { 278 case Const.CONSTANT_String: { 279 final ConstantString s = (ConstantString) constant; 280 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; 281 return addString(u8.getBytes()); 282 } 283 case Const.CONSTANT_Class: { 284 final ConstantClass s = (ConstantClass) constant; 285 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; 286 return addClass(u8.getBytes()); 287 } 288 case Const.CONSTANT_NameAndType: { 289 final ConstantNameAndType n = (ConstantNameAndType) constant; 290 final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 291 final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; 292 return addNameAndType(u8.getBytes(), u8_2.getBytes()); 293 } 294 case Const.CONSTANT_Utf8: 295 return addUtf8(((ConstantUtf8) constant).getBytes()); 296 case Const.CONSTANT_Double: 297 return addDouble(((ConstantDouble) constant).getBytes()); 298 case Const.CONSTANT_Float: 299 return addFloat(((ConstantFloat) constant).getBytes()); 300 case Const.CONSTANT_Long: 301 return addLong(((ConstantLong) constant).getBytes()); 302 case Const.CONSTANT_Integer: 303 return addInteger(((ConstantInteger) constant).getBytes()); 304 case Const.CONSTANT_InterfaceMethodref: 305 case Const.CONSTANT_Methodref: 306 case Const.CONSTANT_Fieldref: { 307 final ConstantCP m = (ConstantCP) constant; 308 final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; 309 final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; 310 ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; 311 final String className = Utility.pathToPackage(u8.getBytes()); 312 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 313 final String name = u8.getBytes(); 314 u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; 315 final String signature = u8.getBytes(); 316 switch (constant.getTag()) { 317 case Const.CONSTANT_InterfaceMethodref: 318 return addInterfaceMethodref(className, name, signature); 319 case Const.CONSTANT_Methodref: 320 return addMethodref(className, name, signature); 321 case Const.CONSTANT_Fieldref: 322 return addFieldref(className, name, signature); 323 default: // Never reached 324 throw new IllegalArgumentException("Unknown constant type " + constant); 325 } 326 } 327 default: // Never reached 328 throw new IllegalArgumentException("Unknown constant type " + constant); 329 } 330 } 331 332 /** 333 * Add a new double constant to the ConstantPool, if it is not already in there. 334 * 335 * @param n Double number to add 336 * @return index of entry 337 */ 338 public int addDouble(final double n) { 339 int ret; 340 if ((ret = lookupDouble(n)) != -1) { 341 return ret; // Already in CP 342 } 343 adjustSize(); 344 ret = index; 345 constants[index] = new ConstantDouble(n); 346 index += 2; // Wastes one entry according to spec 347 return ret; 348 } 349 350 /** 351 * Add a new Fieldref constant to the ConstantPool, if it is not already in there. 352 * 353 * @param className class name string to add 354 * @param fieldName field name string to add 355 * @param signature signature string to add 356 * @return index of entry 357 */ 358 public int addFieldref(final String className, final String fieldName, final String signature) { 359 final int cpRet; 360 if ((cpRet = lookupFieldref(className, fieldName, signature)) != -1) { 361 return cpRet; // Already in CP 362 } 363 adjustSize(); 364 final int classIndex = addClass(className); 365 final int nameAndTypeIndex = addNameAndType(fieldName, signature); 366 final int ret = index; 367 constants[index++] = new ConstantFieldref(classIndex, nameAndTypeIndex); 368 return computeIfAbsent(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature, ret); 369 } 370 371 /** 372 * Add a new Float constant to the ConstantPool, if it is not already in there. 373 * 374 * @param n Float number to add 375 * @return index of entry 376 */ 377 public int addFloat(final float n) { 378 int ret; 379 if ((ret = lookupFloat(n)) != -1) { 380 return ret; // Already in CP 381 } 382 adjustSize(); 383 ret = index; 384 constants[index++] = new ConstantFloat(n); 385 return ret; 386 } 387 388 /** 389 * Add a new Integer constant to the ConstantPool, if it is not already in there. 390 * 391 * @param n integer number to add 392 * @return index of entry 393 */ 394 public int addInteger(final int n) { 395 int ret; 396 if ((ret = lookupInteger(n)) != -1) { 397 return ret; // Already in CP 398 } 399 adjustSize(); 400 ret = index; 401 constants[index++] = new ConstantInteger(n); 402 return ret; 403 } 404 405 public int addInterfaceMethodref(final MethodGen method) { 406 return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); 407 } 408 409 /** 410 * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already in there. 411 * 412 * @param className class name string to add 413 * @param methodName method name string to add 414 * @param signature signature string to add 415 * @return index of entry 416 */ 417 public int addInterfaceMethodref(final String className, final String methodName, final String signature) { 418 final int cpRet; 419 if ((cpRet = lookupInterfaceMethodref(className, methodName, signature)) != -1) { 420 return cpRet; // Already in CP 421 } 422 adjustSize(); 423 final int classIndex = addClass(className); 424 final int nameAndTypeIndex = addNameAndType(methodName, signature); 425 final int ret = index; 426 constants[index++] = new ConstantInterfaceMethodref(classIndex, nameAndTypeIndex); 427 return computeIfAbsent(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature, ret); 428 } 429 430 /** 431 * Add a new long constant to the ConstantPool, if it is not already in there. 432 * 433 * @param n Long number to add 434 * @return index of entry 435 */ 436 public int addLong(final long n) { 437 int ret; 438 if ((ret = lookupLong(n)) != -1) { 439 return ret; // Already in CP 440 } 441 adjustSize(); 442 ret = index; 443 constants[index] = new ConstantLong(n); 444 index += 2; // Wastes one entry according to spec 445 return ret; 446 } 447 public int addMethodref(final MethodGen method) { 448 return addMethodref(method.getClassName(), method.getName(), method.getSignature()); 449 } 450 451 /** 452 * Add a new Methodref constant to the ConstantPool, if it is not already in there. 453 * 454 * @param className class name string to add 455 * @param methodName method name string to add 456 * @param signature method signature string to add 457 * @return index of entry 458 */ 459 public int addMethodref(final String className, final String methodName, final String signature) { 460 final int cpRet; 461 if ((cpRet = lookupMethodref(className, methodName, signature)) != -1) { 462 return cpRet; // Already in CP 463 } 464 adjustSize(); 465 final int nameAndTypeIndex = addNameAndType(methodName, signature); 466 final int classIndex = addClass(className); 467 final int ret = index; 468 constants[index++] = new ConstantMethodref(classIndex, nameAndTypeIndex); 469 return computeIfAbsent(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature, ret); 470 } 471 472 /** 473 * Add a new NameAndType constant to the ConstantPool if it is not already in there. 474 * 475 * @param name Name string to add 476 * @param signature signature string to add 477 * @return index of entry 478 */ 479 public int addNameAndType(final String name, final String signature) { 480 int ret; 481 if ((ret = lookupNameAndType(name, signature)) != -1) { 482 return ret; // Already in CP 483 } 484 adjustSize(); 485 final int nameIndex = addUtf8(name); 486 final int signatureIndex = addUtf8(signature); 487 ret = index; 488 constants[index++] = new ConstantNameAndType(nameIndex, signatureIndex); 489 return computeIfAbsent(natTable, name + NAT_DELIM + signature, ret); 490 } 491 492 /** 493 * Add a new String constant to the ConstantPool, if it is not already in there. 494 * 495 * @param str String to add 496 * @return index of entry 497 */ 498 public int addString(final String str) { 499 int ret; 500 if ((ret = lookupString(str)) != -1) { 501 return ret; // Already in CP 502 } 503 final int utf8 = addUtf8(str); 504 adjustSize(); 505 final ConstantString s = new ConstantString(utf8); 506 ret = index; 507 constants[index++] = s; 508 return computeIfAbsent(stringTable, str, ret); 509 } 510 511 /** 512 * Add a new Utf8 constant to the ConstantPool, if it is not already in there. 513 * 514 * @param n Utf8 string to add 515 * @return index of entry 516 */ 517 public int addUtf8(final String n) { 518 int ret; 519 if ((ret = lookupUtf8(n)) != -1) { 520 return ret; // Already in CP 521 } 522 adjustSize(); 523 ret = index; 524 constants[index++] = new ConstantUtf8(n); 525 return computeIfAbsent(utf8Table, n, ret); 526 } 527 528 /** 529 * Resize internal array of constants. 530 */ 531 protected void adjustSize() { 532 // 3 extra spaces are needed as some entries may take 3 slots 533 if (index + 3 >= Const.MAX_CP_ENTRIES + 1) { 534 throw new IllegalStateException("The number of constants " + (index + 3) 535 + " is over the size of the constant pool: " 536 + Const.MAX_CP_ENTRIES); 537 } 538 539 if (index + 3 >= size) { 540 final Constant[] tmp = constants; 541 size *= 2; 542 // the constant array shall not exceed the size of the constant pool 543 size = Math.min(size, Const.MAX_CP_ENTRIES + 1); 544 constants = new Constant[size]; 545 System.arraycopy(tmp, 0, constants, 0, index); 546 } 547 } 548 549 private int computeIfAbsent(final Map<String, Integer> map, final String key, final int value) { 550 return map.computeIfAbsent(key, k -> Integer.valueOf(value)); 551 } 552 553 /** 554 * @param i index in constant pool 555 * @return constant pool entry at index i 556 */ 557 public Constant getConstant(final int i) { 558 return constants[i]; 559 } 560 561 /** 562 * @return intermediate constant pool 563 */ 564 public ConstantPool getConstantPool() { 565 return new ConstantPool(constants); 566 } 567 568 /** 569 * @return constant pool with proper length 570 */ 571 public ConstantPool getFinalConstantPool() { 572 return new ConstantPool(Arrays.copyOf(constants, index)); 573 } 574 575 private int getIndex(final Map<String, Integer> map, final String key) { 576 return toIndex(map.get(key)); 577 } 578 579 /** 580 * @return current size of constant pool 581 */ 582 public int getSize() { 583 return index; 584 } 585 586 /** 587 * Look for ConstantClass in ConstantPool named 'str'. 588 * 589 * @param str String to search for 590 * @return index on success, -1 otherwise 591 */ 592 public int lookupClass(final String str) { 593 return getIndex(classTable, Utility.packageToPath(str)); 594 } 595 596 /** 597 * Look for ConstantDouble in ConstantPool. 598 * 599 * @param n Double number to look for 600 * @return index on success, -1 otherwise 601 */ 602 public int lookupDouble(final double n) { 603 final long bits = Double.doubleToLongBits(n); 604 for (int i = 1; i < index; i++) { 605 if (constants[i] instanceof ConstantDouble) { 606 final ConstantDouble c = (ConstantDouble) constants[i]; 607 if (Double.doubleToLongBits(c.getBytes()) == bits) { 608 return i; 609 } 610 } 611 } 612 return -1; 613 } 614 615 /** 616 * Look for ConstantFieldref in ConstantPool. 617 * 618 * @param className Where to find method 619 * @param fieldName Guess what 620 * @param signature return and argument types 621 * @return index on success, -1 otherwise 622 */ 623 public int lookupFieldref(final String className, final String fieldName, final String signature) { 624 return getIndex(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature); 625 } 626 627 /** 628 * Look for ConstantFloat in ConstantPool. 629 * 630 * @param n Float number to look for 631 * @return index on success, -1 otherwise 632 */ 633 public int lookupFloat(final float n) { 634 final int bits = Float.floatToIntBits(n); 635 for (int i = 1; i < index; i++) { 636 if (constants[i] instanceof ConstantFloat) { 637 final ConstantFloat c = (ConstantFloat) constants[i]; 638 if (Float.floatToIntBits(c.getBytes()) == bits) { 639 return i; 640 } 641 } 642 } 643 return -1; 644 } 645 646 /** 647 * Look for ConstantInteger in ConstantPool. 648 * 649 * @param n integer number to look for 650 * @return index on success, -1 otherwise 651 */ 652 public int lookupInteger(final int n) { 653 for (int i = 1; i < index; i++) { 654 if (constants[i] instanceof ConstantInteger) { 655 final ConstantInteger c = (ConstantInteger) constants[i]; 656 if (c.getBytes() == n) { 657 return i; 658 } 659 } 660 } 661 return -1; 662 } 663 664 public int lookupInterfaceMethodref(final MethodGen method) { 665 return lookupInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); 666 } 667 668 /** 669 * Look for ConstantInterfaceMethodref in ConstantPool. 670 * 671 * @param className Where to find method 672 * @param methodName Guess what 673 * @param signature return and argument types 674 * @return index on success, -1 otherwise 675 */ 676 public int lookupInterfaceMethodref(final String className, final String methodName, final String signature) { 677 return getIndex(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature); 678 } 679 680 /** 681 * Look for ConstantLong in ConstantPool. 682 * 683 * @param n Long number to look for 684 * @return index on success, -1 otherwise 685 */ 686 public int lookupLong(final long n) { 687 for (int i = 1; i < index; i++) { 688 if (constants[i] instanceof ConstantLong) { 689 final ConstantLong c = (ConstantLong) constants[i]; 690 if (c.getBytes() == n) { 691 return i; 692 } 693 } 694 } 695 return -1; 696 } 697 698 public int lookupMethodref(final MethodGen method) { 699 return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); 700 } 701 702 /** 703 * Look for ConstantMethodref in ConstantPool. 704 * 705 * @param className Where to find method 706 * @param methodName Guess what 707 * @param signature return and argument types 708 * @return index on success, -1 otherwise 709 */ 710 public int lookupMethodref(final String className, final String methodName, final String signature) { 711 return getIndex(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature); 712 } 713 714 /** 715 * Look for ConstantNameAndType in ConstantPool. 716 * 717 * @param name of variable/method 718 * @param signature of variable/method 719 * @return index on success, -1 otherwise 720 */ 721 public int lookupNameAndType(final String name, final String signature) { 722 return getIndex(natTable, name + NAT_DELIM + signature); 723 } 724 725 /** 726 * Look for ConstantString in ConstantPool containing String 'str'. 727 * 728 * @param str String to search for 729 * @return index on success, -1 otherwise 730 */ 731 public int lookupString(final String str) { 732 return getIndex(stringTable, str); 733 } 734 735 /** 736 * Look for ConstantUtf8 in ConstantPool. 737 * 738 * @param n Utf8 string to look for 739 * @return index on success, -1 otherwise 740 */ 741 public int lookupUtf8(final String n) { 742 return getIndex(utf8Table, n); 743 } 744 745 /** 746 * Use with care! 747 * 748 * @param i index in constant pool 749 * @param c new constant pool entry at index i 750 */ 751 public void setConstant(final int i, final Constant c) { 752 constants[i] = c; 753 } 754 755 private int toIndex(final Integer index) { 756 return index != null ? index.intValue() : -1; 757 } 758 759 /** 760 * @return String representation. 761 */ 762 @Override 763 public String toString() { 764 final StringBuilder buf = new StringBuilder(); 765 for (int i = 1; i < index; i++) { 766 buf.append(i).append(")").append(constants[i]).append("\n"); 767 } 768 return buf.toString(); 769 } 770}