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