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