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 private static final String NAT_DELIM = "%"; // Name and Type 063 064 /** 065 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 066 */ 067 @Deprecated 068 protected int size; 069 070 /** 071 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 072 */ 073 @Deprecated 074 protected Constant[] constants; 075 076 /** 077 * @deprecated (since 6.0) will be made private; do not access directly, use getSize() 078 */ 079 @Deprecated 080 protected int index = 1; // First entry (0) used by JVM 081 082 private final Map<String, Integer> stringTable = new HashMap<>(); 083 084 private final Map<String, Integer> classTable = new HashMap<>(); 085 086 private final Map<String, Integer> utf8Table = new HashMap<>(); 087 088 private final Map<String, Integer> natTable = new HashMap<>(); 089 090 private final Map<String, Integer> cpTable = new HashMap<>(); 091 092 /** 093 * Constructs a new empty constant pool. 094 */ 095 public ConstantPoolGen() { 096 size = DEFAULT_BUFFER_SIZE; 097 constants = new Constant[size]; 098 } 099 100 /** 101 * Constructs a new instance with the given array of constants. 102 * 103 * @param cs array of given constants, new ones will be appended. 104 */ 105 public ConstantPoolGen(final Constant[] cs) { 106 final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE); 107 108 size = Math.min(Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64), Const.MAX_CP_ENTRIES + 1); 109 constants = Arrays.copyOf(cs, size); 110 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 final 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 (for example, String[][]) as needed by MULTIANEWARRAY instruction, for example, to the 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 /** 406 * Adds a new InterfaceMethodref constant to the ConstantPool. 407 * 408 * @param method the method to add. 409 * @return index of entry. 410 */ 411 public int addInterfaceMethodref(final MethodGen method) { 412 return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); 413 } 414 415 /** 416 * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already in there. 417 * 418 * @param className class name string to add. 419 * @param methodName method name string to add. 420 * @param signature signature string to add. 421 * @return index of entry. 422 */ 423 public int addInterfaceMethodref(final String className, final String methodName, final String signature) { 424 final int cpRet; 425 if ((cpRet = lookupInterfaceMethodref(className, methodName, signature)) != -1) { 426 return cpRet; // Already in CP 427 } 428 adjustSize(); 429 final int classIndex = addClass(className); 430 final int nameAndTypeIndex = addNameAndType(methodName, signature); 431 final int ret = index; 432 constants[index++] = new ConstantInterfaceMethodref(classIndex, nameAndTypeIndex); 433 return computeIfAbsent(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature, ret); 434 } 435 436 /** 437 * Add a new long constant to the ConstantPool, if it is not already in there. 438 * 439 * @param n Long number to add. 440 * @return index of entry. 441 */ 442 public int addLong(final long n) { 443 int ret; 444 if ((ret = lookupLong(n)) != -1) { 445 return ret; // Already in CP 446 } 447 adjustSize(); 448 ret = index; 449 constants[index] = new ConstantLong(n); 450 index += 2; // Wastes one entry according to spec 451 return ret; 452 } 453 454 /** 455 * Adds a new Methodref constant to the ConstantPool. 456 * 457 * @param method the method to add. 458 * @return index of entry. 459 */ 460 public int addMethodref(final MethodGen method) { 461 return addMethodref(method.getClassName(), method.getName(), method.getSignature()); 462 } 463 464 /** 465 * Add a new Methodref constant to the ConstantPool, if it is not already in there. 466 * 467 * @param className class name string to add. 468 * @param methodName method name string to add. 469 * @param signature method signature string to add. 470 * @return index of entry. 471 */ 472 public int addMethodref(final String className, final String methodName, final String signature) { 473 final int cpRet; 474 if ((cpRet = lookupMethodref(className, methodName, signature)) != -1) { 475 return cpRet; // Already in CP 476 } 477 adjustSize(); 478 final int nameAndTypeIndex = addNameAndType(methodName, signature); 479 final int classIndex = addClass(className); 480 final int ret = index; 481 constants[index++] = new ConstantMethodref(classIndex, nameAndTypeIndex); 482 return computeIfAbsent(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature, ret); 483 } 484 485 /** 486 * Add a new NameAndType constant to the ConstantPool if it is not already in there. 487 * 488 * @param name Name string to add. 489 * @param signature signature string to add. 490 * @return index of entry. 491 */ 492 public int addNameAndType(final String name, final String signature) { 493 int ret; 494 if ((ret = lookupNameAndType(name, signature)) != -1) { 495 return ret; // Already in CP 496 } 497 adjustSize(); 498 final int nameIndex = addUtf8(name); 499 final int signatureIndex = addUtf8(signature); 500 ret = index; 501 constants[index++] = new ConstantNameAndType(nameIndex, signatureIndex); 502 return computeIfAbsent(natTable, name + NAT_DELIM + signature, ret); 503 } 504 505 /** 506 * Add a new String constant to the ConstantPool, if it is not already in there. 507 * 508 * @param str String to add. 509 * @return index of entry. 510 */ 511 public int addString(final String str) { 512 int ret; 513 if ((ret = lookupString(str)) != -1) { 514 return ret; // Already in CP 515 } 516 final int utf8 = addUtf8(str); 517 adjustSize(); 518 final ConstantString s = new ConstantString(utf8); 519 ret = index; 520 constants[index++] = s; 521 return computeIfAbsent(stringTable, str, ret); 522 } 523 524 /** 525 * Add a new Utf8 constant to the ConstantPool, if it is not already in there. 526 * 527 * @param n Utf8 string to add. 528 * @return index of entry. 529 */ 530 public int addUtf8(final String n) { 531 int ret; 532 if ((ret = lookupUtf8(n)) != -1) { 533 return ret; // Already in CP 534 } 535 adjustSize(); 536 ret = index; 537 constants[index++] = new ConstantUtf8(n); 538 return computeIfAbsent(utf8Table, n, ret); 539 } 540 541 /** 542 * Resize internal array of constants. 543 */ 544 protected void adjustSize() { 545 // 3 extra spaces are needed as some entries may take 3 slots 546 if (index + 3 >= Const.MAX_CP_ENTRIES + 1) { 547 throw new IllegalStateException("The number of constants " + (index + 3) 548 + " is over the size of the constant pool: " 549 + Const.MAX_CP_ENTRIES); 550 } 551 552 if (index + 3 >= size) { 553 final Constant[] tmp = constants; 554 size *= 2; 555 // the constant array shall not exceed the size of the constant pool 556 size = Math.min(size, Const.MAX_CP_ENTRIES + 1); 557 constants = new Constant[size]; 558 System.arraycopy(tmp, 0, constants, 0, index); 559 } 560 } 561 562 private int computeIfAbsent(final Map<String, Integer> map, final String key, final int value) { 563 return map.computeIfAbsent(key, k -> Integer.valueOf(value)); 564 } 565 566 /** 567 * Gets a constant pool entry at the specified index. 568 * 569 * @param i index in constant pool. 570 * @return constant pool entry at index i. 571 */ 572 public Constant getConstant(final int i) { 573 return constants[i]; 574 } 575 576 /** 577 * Gets the intermediate constant pool. 578 * 579 * @return intermediate constant pool. 580 */ 581 public ConstantPool getConstantPool() { 582 return new ConstantPool(constants); 583 } 584 585 /** 586 * Gets the constant pool with proper length. 587 * 588 * @return constant pool with proper length. 589 */ 590 public ConstantPool getFinalConstantPool() { 591 return new ConstantPool(Arrays.copyOf(constants, index)); 592 } 593 594 private int getIndex(final Map<String, Integer> map, final String key) { 595 return toIndex(map.get(key)); 596 } 597 598 /** 599 * Gets the current size of constant pool. 600 * 601 * @return current size of constant pool. 602 */ 603 public int getSize() { 604 return index; 605 } 606 607 /** 608 * Look for ConstantClass in ConstantPool named 'str'. 609 * 610 * @param str String to search for. 611 * @return index on success, -1 otherwise. 612 */ 613 public int lookupClass(final String str) { 614 return getIndex(classTable, Utility.packageToPath(str)); 615 } 616 617 /** 618 * Look for ConstantDouble in ConstantPool. 619 * 620 * @param n Double number to look for. 621 * @return index on success, -1 otherwise. 622 */ 623 public int lookupDouble(final double n) { 624 final long bits = Double.doubleToLongBits(n); 625 for (int i = 1; i < index; i++) { 626 if (constants[i] instanceof ConstantDouble) { 627 final ConstantDouble c = (ConstantDouble) constants[i]; 628 if (Double.doubleToLongBits(c.getBytes()) == bits) { 629 return i; 630 } 631 } 632 } 633 return -1; 634 } 635 636 /** 637 * Look for ConstantFieldref in ConstantPool. 638 * 639 * @param className Where to find method. 640 * @param fieldName Guess what. 641 * @param signature return and argument types. 642 * @return index on success, -1 otherwise. 643 */ 644 public int lookupFieldref(final String className, final String fieldName, final String signature) { 645 return getIndex(cpTable, className + FIELDREF_DELIM + fieldName + FIELDREF_DELIM + signature); 646 } 647 648 /** 649 * Look for ConstantFloat in ConstantPool. 650 * 651 * @param n Float number to look for. 652 * @return index on success, -1 otherwise. 653 */ 654 public int lookupFloat(final float n) { 655 final int bits = Float.floatToIntBits(n); 656 for (int i = 1; i < index; i++) { 657 if (constants[i] instanceof ConstantFloat) { 658 final ConstantFloat c = (ConstantFloat) constants[i]; 659 if (Float.floatToIntBits(c.getBytes()) == bits) { 660 return i; 661 } 662 } 663 } 664 return -1; 665 } 666 667 /** 668 * Look for ConstantInteger in ConstantPool. 669 * 670 * @param n integer number to look for. 671 * @return index on success, -1 otherwise. 672 */ 673 public int lookupInteger(final int n) { 674 for (int i = 1; i < index; i++) { 675 if (constants[i] instanceof ConstantInteger) { 676 final ConstantInteger c = (ConstantInteger) constants[i]; 677 if (c.getBytes() == n) { 678 return i; 679 } 680 } 681 } 682 return -1; 683 } 684 685 /** 686 * Looks up an InterfaceMethodref in the ConstantPool. 687 * 688 * @param method the method to look for. 689 * @return index on success, -1 otherwise. 690 */ 691 public int lookupInterfaceMethodref(final MethodGen method) { 692 return lookupInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); 693 } 694 695 /** 696 * Look for ConstantInterfaceMethodref in ConstantPool. 697 * 698 * @param className Where to find method. 699 * @param methodName Guess what. 700 * @param signature return and argument types. 701 * @return index on success, -1 otherwise. 702 */ 703 public int lookupInterfaceMethodref(final String className, final String methodName, final String signature) { 704 return getIndex(cpTable, className + IMETHODREF_DELIM + methodName + IMETHODREF_DELIM + signature); 705 } 706 707 /** 708 * Look for ConstantLong in ConstantPool. 709 * 710 * @param n Long number to look for. 711 * @return index on success, -1 otherwise. 712 */ 713 public int lookupLong(final long n) { 714 for (int i = 1; i < index; i++) { 715 if (constants[i] instanceof ConstantLong) { 716 final ConstantLong c = (ConstantLong) constants[i]; 717 if (c.getBytes() == n) { 718 return i; 719 } 720 } 721 } 722 return -1; 723 } 724 725 /** 726 * Looks up a Methodref in the ConstantPool. 727 * 728 * @param method the method to look for. 729 * @return index on success, -1 otherwise. 730 */ 731 public int lookupMethodref(final MethodGen method) { 732 return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); 733 } 734 735 /** 736 * Look for ConstantMethodref in ConstantPool. 737 * 738 * @param className Where to find method. 739 * @param methodName Guess what. 740 * @param signature return and argument types. 741 * @return index on success, -1 otherwise. 742 */ 743 public int lookupMethodref(final String className, final String methodName, final String signature) { 744 return getIndex(cpTable, className + METHODREF_DELIM + methodName + METHODREF_DELIM + signature); 745 } 746 747 /** 748 * Look for ConstantNameAndType in ConstantPool. 749 * 750 * @param name of variable/method. 751 * @param signature of variable/method. 752 * @return index on success, -1 otherwise. 753 */ 754 public int lookupNameAndType(final String name, final String signature) { 755 return getIndex(natTable, name + NAT_DELIM + signature); 756 } 757 758 /** 759 * Look for ConstantString in ConstantPool containing String 'str'. 760 * 761 * @param str String to search for. 762 * @return index on success, -1 otherwise. 763 */ 764 public int lookupString(final String str) { 765 return getIndex(stringTable, str); 766 } 767 768 /** 769 * Look for ConstantUtf8 in ConstantPool. 770 * 771 * @param n Utf8 string to look for. 772 * @return index on success, -1 otherwise. 773 */ 774 public int lookupUtf8(final String n) { 775 return getIndex(utf8Table, n); 776 } 777 778 /** 779 * Use with care! 780 * 781 * @param i index in constant pool. 782 * @param c new constant pool entry at index i. 783 */ 784 public void setConstant(final int i, final Constant c) { 785 constants[i] = c; 786 } 787 788 private int toIndex(final Integer index) { 789 return index != null ? index.intValue() : -1; 790 } 791 792 /** 793 * @return String representation. 794 */ 795 @Override 796 public String toString() { 797 final StringBuilder buf = new StringBuilder(); 798 for (int i = 1; i < index; i++) { 799 buf.append(i).append(")").append(constants[i]).append("\n"); 800 } 801 return buf.toString(); 802 } 803}