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