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 * Create empty constant pool. 093 */ 094 public ConstantPoolGen() { 095 size = DEFAULT_BUFFER_SIZE; 096 constants = new Constant[size]; 097 } 098 099 /** 100 * Initialize with 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 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 134 final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; 135 136 sb.append(u8.getBytes()); 137 sb.append(NAT_DELIM); 138 sb.append(u8_2.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 * Initialize with 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_(str.replace('.', '/')); 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 * Import constant from another ConstantPool and return new index. 271 */ 272 public int addConstant(final Constant c, final ConstantPoolGen cp) { 273 final Constant[] constants = cp.getConstantPool().getConstantPool(); 274 switch (c.getTag()) { 275 case Const.CONSTANT_String: { 276 final ConstantString s = (ConstantString) c; 277 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; 278 return addString(u8.getBytes()); 279 } 280 case Const.CONSTANT_Class: { 281 final ConstantClass s = (ConstantClass) c; 282 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; 283 return addClass(u8.getBytes()); 284 } 285 case Const.CONSTANT_NameAndType: { 286 final ConstantNameAndType n = (ConstantNameAndType) c; 287 final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 288 final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; 289 return addNameAndType(u8.getBytes(), u8_2.getBytes()); 290 } 291 case Const.CONSTANT_Utf8: 292 return addUtf8(((ConstantUtf8) c).getBytes()); 293 case Const.CONSTANT_Double: 294 return addDouble(((ConstantDouble) c).getBytes()); 295 case Const.CONSTANT_Float: 296 return addFloat(((ConstantFloat) c).getBytes()); 297 case Const.CONSTANT_Long: 298 return addLong(((ConstantLong) c).getBytes()); 299 case Const.CONSTANT_Integer: 300 return addInteger(((ConstantInteger) c).getBytes()); 301 case Const.CONSTANT_InterfaceMethodref: 302 case Const.CONSTANT_Methodref: 303 case Const.CONSTANT_Fieldref: { 304 final ConstantCP m = (ConstantCP) c; 305 final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; 306 final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; 307 ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; 308 final String className = Utility.pathToPackage(u8.getBytes()); 309 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 310 final String name = u8.getBytes(); 311 u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; 312 final String signature = u8.getBytes(); 313 switch (c.getTag()) { 314 case Const.CONSTANT_InterfaceMethodref: 315 return addInterfaceMethodref(className, name, signature); 316 case Const.CONSTANT_Methodref: 317 return addMethodref(className, name, signature); 318 case Const.CONSTANT_Fieldref: 319 return addFieldref(className, name, signature); 320 default: // Never reached 321 throw new IllegalArgumentException("Unknown constant type " + c); 322 } 323 } 324 default: // Never reached 325 throw new IllegalArgumentException("Unknown constant type " + c); 326 } 327 } 328 329 /** 330 * Add a new double constant to the ConstantPool, if it is not already in there. 331 * 332 * @param n Double number to add 333 * @return index of entry 334 */ 335 public int addDouble(final double n) { 336 int ret; 337 if ((ret = lookupDouble(n)) != -1) { 338 return ret; // Already in CP 339 } 340 adjustSize(); 341 ret = index; 342 constants[index] = new ConstantDouble(n); 343 index += 2; // Wastes one entry according to spec 344 return ret; 345 } 346 347 /** 348 * Add a new Fieldref constant to the ConstantPool, if it is not already in there. 349 * 350 * @param className class name string to add 351 * @param fieldName field name string to add 352 * @param signature signature string to add 353 * @return index of entry 354 */ 355 public int addFieldref(final String className, final String fieldName, final String signature) { 356 final int cpRet; 357 if ((cpRet = lookupFieldref(className, fieldName, signature)) != -1) { 358 return cpRet; // Already in CP 359 } 360 adjustSize(); 361 int classIndex = addClass(className); 362 int nameAndTypeIndex = addNameAndType(fieldName, signature); 363 final int ret = index; 364 constants[index++] = new ConstantFieldref(classIndex, nameAndTypeIndex); 365 return computeIfAbsent(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature, ret); 366 } 367 368 /** 369 * Add a new Float constant to the ConstantPool, if it is not already in there. 370 * 371 * @param n Float number to add 372 * @return index of entry 373 */ 374 public int addFloat(final float n) { 375 int ret; 376 if ((ret = lookupFloat(n)) != -1) { 377 return ret; // Already in CP 378 } 379 adjustSize(); 380 ret = index; 381 constants[index++] = new ConstantFloat(n); 382 return ret; 383 } 384 385 /** 386 * Add a new Integer constant to the ConstantPool, if it is not already in there. 387 * 388 * @param n integer number to add 389 * @return index of entry 390 */ 391 public int addInteger(final int n) { 392 int ret; 393 if ((ret = lookupInteger(n)) != -1) { 394 return ret; // Already in CP 395 } 396 adjustSize(); 397 ret = index; 398 constants[index++] = new ConstantInteger(n); 399 return ret; 400 } 401 402 public int addInterfaceMethodref(final MethodGen method) { 403 return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); 404 } 405 406 /** 407 * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already in there. 408 * 409 * @param className class name string to add 410 * @param methodName method name string to add 411 * @param signature signature string to add 412 * @return index of entry 413 */ 414 public int addInterfaceMethodref(final String className, final String methodName, final String signature) { 415 final int cpRet; 416 if ((cpRet = lookupInterfaceMethodref(className, methodName, signature)) != -1) { 417 return cpRet; // Already in CP 418 } 419 adjustSize(); 420 int classIndex = addClass(className); 421 int nameAndTypeIndex = addNameAndType(methodName, signature); 422 final int ret = index; 423 constants[index++] = new ConstantInterfaceMethodref(classIndex, nameAndTypeIndex); 424 return computeIfAbsent(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature, ret); 425 } 426 427 /** 428 * Add a new long constant to the ConstantPool, if it is not already in there. 429 * 430 * @param n Long number to add 431 * @return index of entry 432 */ 433 public int addLong(final long n) { 434 int ret; 435 if ((ret = lookupLong(n)) != -1) { 436 return ret; // Already in CP 437 } 438 adjustSize(); 439 ret = index; 440 constants[index] = new ConstantLong(n); 441 index += 2; // Wastes one entry according to spec 442 return ret; 443 } 444 public int addMethodref(final MethodGen method) { 445 return addMethodref(method.getClassName(), method.getName(), method.getSignature()); 446 } 447 448 /** 449 * Add a new Methodref constant to the ConstantPool, if it is not already in there. 450 * 451 * @param className class name string to add 452 * @param methodName method name string to add 453 * @param signature method signature string to add 454 * @return index of entry 455 */ 456 public int addMethodref(final String className, final String methodName, final String signature) { 457 final int cpRet; 458 if ((cpRet = lookupMethodref(className, methodName, signature)) != -1) { 459 return cpRet; // Already in CP 460 } 461 adjustSize(); 462 int nameAndTypeIndex = addNameAndType(methodName, signature); 463 int classIndex = addClass(className); 464 final int ret = index; 465 constants[index++] = new ConstantMethodref(classIndex, nameAndTypeIndex); 466 return computeIfAbsent(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature, ret); 467 } 468 469 /** 470 * Add a new NameAndType constant to the ConstantPool if it is not already in there. 471 * 472 * @param name Name string to add 473 * @param signature signature string to add 474 * @return index of entry 475 */ 476 public int addNameAndType(final String name, final String signature) { 477 int ret; 478 if ((ret = lookupNameAndType(name, signature)) != -1) { 479 return ret; // Already in CP 480 } 481 adjustSize(); 482 int nameIndex = addUtf8(name); 483 int signatureIndex = addUtf8(signature); 484 ret = index; 485 constants[index++] = new ConstantNameAndType(nameIndex, signatureIndex); 486 return computeIfAbsent(natTable, name + NAT_DELIM + signature, ret); 487 } 488 489 /** 490 * Add a new String constant to the ConstantPool, if it is not already in there. 491 * 492 * @param str String to add 493 * @return index of entry 494 */ 495 public int addString(final String str) { 496 int ret; 497 if ((ret = lookupString(str)) != -1) { 498 return ret; // Already in CP 499 } 500 final int utf8 = addUtf8(str); 501 adjustSize(); 502 final ConstantString s = new ConstantString(utf8); 503 ret = index; 504 constants[index++] = s; 505 return computeIfAbsent(stringTable, str, ret); 506 } 507 508 /** 509 * Add a new Utf8 constant to the ConstantPool, if it is not already in there. 510 * 511 * @param n Utf8 string to add 512 * @return index of entry 513 */ 514 public int addUtf8(final String n) { 515 int ret; 516 if ((ret = lookupUtf8(n)) != -1) { 517 return ret; // Already in CP 518 } 519 adjustSize(); 520 ret = index; 521 constants[index++] = new ConstantUtf8(n); 522 return computeIfAbsent(utf8Table, n, ret); 523 } 524 525 /** 526 * Resize internal array of constants. 527 */ 528 protected void adjustSize() { 529 // 3 extra spaces are needed as some entries may take 3 slots 530 if (index + 3 >= Const.MAX_CP_ENTRIES + 1) { 531 throw new IllegalStateException("The number of constants " + (index + 3) 532 + " is over the size of the constant pool: " 533 + Const.MAX_CP_ENTRIES); 534 } 535 536 if (index + 3 >= size) { 537 final Constant[] cs = constants; 538 size *= 2; 539 // the constant array shall not exceed the size of the constant pool 540 size = Math.min(size, Const.MAX_CP_ENTRIES + 1); 541 constants = new Constant[size]; 542 System.arraycopy(cs, 0, constants, 0, index); 543 } 544 } 545 546 private int computeIfAbsent(final Map<String, Integer> map, final String key, final int value) { 547 return map.computeIfAbsent(key, k -> Integer.valueOf(value)); 548 } 549 550 /** 551 * @param i index in constant pool 552 * @return constant pool entry at index i 553 */ 554 public Constant getConstant(final int i) { 555 return constants[i]; 556 } 557 558 /** 559 * @return intermediate constant pool 560 */ 561 public ConstantPool getConstantPool() { 562 return new ConstantPool(constants); 563 } 564 565 /** 566 * @return constant pool with proper length 567 */ 568 public ConstantPool getFinalConstantPool() { 569 return new ConstantPool(Arrays.copyOf(constants, index)); 570 } 571 572 private int getIndex(final Map<String, Integer> map, final String key) { 573 return toIndex(map.get(key)); 574 } 575 576 /** 577 * @return current size of constant pool 578 */ 579 public int getSize() { 580 return index; 581 } 582 583 /** 584 * Look for ConstantClass in ConstantPool named `str'. 585 * 586 * @param str String to search for 587 * @return index on success, -1 otherwise 588 */ 589 public int lookupClass(final String str) { 590 return getIndex(classTable, str.replace('.', '/')); 591 } 592 593 /** 594 * Look for ConstantDouble in ConstantPool. 595 * 596 * @param n Double number to look for 597 * @return index on success, -1 otherwise 598 */ 599 public int lookupDouble(final double n) { 600 final long bits = Double.doubleToLongBits(n); 601 for (int i = 1; i < index; i++) { 602 if (constants[i] instanceof ConstantDouble) { 603 final ConstantDouble c = (ConstantDouble) constants[i]; 604 if (Double.doubleToLongBits(c.getBytes()) == bits) { 605 return i; 606 } 607 } 608 } 609 return -1; 610 } 611 612 /** 613 * Look for ConstantFieldref in ConstantPool. 614 * 615 * @param className Where to find method 616 * @param fieldName Guess what 617 * @param signature return and argument types 618 * @return index on success, -1 otherwise 619 */ 620 public int lookupFieldref(final String className, final String fieldName, final String signature) { 621 return getIndex(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature); 622 } 623 624 /** 625 * Look for ConstantFloat in ConstantPool. 626 * 627 * @param n Float number to look for 628 * @return index on success, -1 otherwise 629 */ 630 public int lookupFloat(final float n) { 631 final int bits = Float.floatToIntBits(n); 632 for (int i = 1; i < index; i++) { 633 if (constants[i] instanceof ConstantFloat) { 634 final ConstantFloat c = (ConstantFloat) constants[i]; 635 if (Float.floatToIntBits(c.getBytes()) == bits) { 636 return i; 637 } 638 } 639 } 640 return -1; 641 } 642 643 /** 644 * Look for ConstantInteger in ConstantPool. 645 * 646 * @param n integer number to look for 647 * @return index on success, -1 otherwise 648 */ 649 public int lookupInteger(final int n) { 650 for (int i = 1; i < index; i++) { 651 if (constants[i] instanceof ConstantInteger) { 652 final ConstantInteger c = (ConstantInteger) constants[i]; 653 if (c.getBytes() == n) { 654 return i; 655 } 656 } 657 } 658 return -1; 659 } 660 661 public int lookupInterfaceMethodref(final MethodGen method) { 662 return lookupInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); 663 } 664 665 /** 666 * Look for ConstantInterfaceMethodref in ConstantPool. 667 * 668 * @param className Where to find method 669 * @param methodName Guess what 670 * @param signature return and argument types 671 * @return index on success, -1 otherwise 672 */ 673 public int lookupInterfaceMethodref(final String className, final String methodName, final String signature) { 674 return getIndex(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature); 675 } 676 677 /** 678 * Look for ConstantLong in ConstantPool. 679 * 680 * @param n Long number to look for 681 * @return index on success, -1 otherwise 682 */ 683 public int lookupLong(final long n) { 684 for (int i = 1; i < index; i++) { 685 if (constants[i] instanceof ConstantLong) { 686 final ConstantLong c = (ConstantLong) constants[i]; 687 if (c.getBytes() == n) { 688 return i; 689 } 690 } 691 } 692 return -1; 693 } 694 695 public int lookupMethodref(final MethodGen method) { 696 return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); 697 } 698 699 /** 700 * Look for ConstantMethodref in ConstantPool. 701 * 702 * @param className Where to find method 703 * @param methodName Guess what 704 * @param signature return and argument types 705 * @return index on success, -1 otherwise 706 */ 707 public int lookupMethodref(final String className, final String methodName, final String signature) { 708 return getIndex(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature); 709 } 710 711 /** 712 * Look for ConstantNameAndType in ConstantPool. 713 * 714 * @param name of variable/method 715 * @param signature of variable/method 716 * @return index on success, -1 otherwise 717 */ 718 public int lookupNameAndType(final String name, final String signature) { 719 return getIndex(natTable, name + NAT_DELIM + signature); 720 } 721 722 /** 723 * Look for ConstantString in ConstantPool containing String `str'. 724 * 725 * @param str String to search for 726 * @return index on success, -1 otherwise 727 */ 728 public int lookupString(final String str) { 729 return getIndex(stringTable, str); 730 } 731 732 /** 733 * Look for ConstantUtf8 in ConstantPool. 734 * 735 * @param n Utf8 string to look for 736 * @return index on success, -1 otherwise 737 */ 738 public int lookupUtf8(final String n) { 739 return getIndex(utf8Table, n); 740 } 741 742 /** 743 * Use with care! 744 * 745 * @param i index in constant pool 746 * @param c new constant pool entry at index i 747 */ 748 public void setConstant(final int i, final Constant c) { 749 constants[i] = c; 750 } 751 752 private int toIndex(final Integer index) { 753 return index != null ? index.intValue() : -1; 754 } 755 756 /** 757 * @return String representation. 758 */ 759 @Override 760 public String toString() { 761 final StringBuilder buf = new StringBuilder(); 762 for (int i = 1; i < index; i++) { 763 buf.append(i).append(")").append(constants[i]).append("\n"); 764 } 765 return buf.toString(); 766 } 767}