1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.bcel.generic; 19 20 import java.util.HashMap; 21 import java.util.Map; 22 23 import org.apache.bcel.Const; 24 import org.apache.bcel.classfile.Constant; 25 import org.apache.bcel.classfile.ConstantCP; 26 import org.apache.bcel.classfile.ConstantClass; 27 import org.apache.bcel.classfile.ConstantDouble; 28 import org.apache.bcel.classfile.ConstantFieldref; 29 import org.apache.bcel.classfile.ConstantFloat; 30 import org.apache.bcel.classfile.ConstantInteger; 31 import org.apache.bcel.classfile.ConstantInterfaceMethodref; 32 import org.apache.bcel.classfile.ConstantInvokeDynamic; 33 import org.apache.bcel.classfile.ConstantLong; 34 import org.apache.bcel.classfile.ConstantMethodref; 35 import org.apache.bcel.classfile.ConstantNameAndType; 36 import org.apache.bcel.classfile.ConstantPool; 37 import org.apache.bcel.classfile.ConstantString; 38 import org.apache.bcel.classfile.ConstantUtf8; 39 40 /** 41 * This class is used to build up a constant pool. The user adds 42 * constants via `addXXX' methods, `addString', `addClass', 43 * etc.. These methods return an index into the constant 44 * pool. Finally, `getFinalConstantPool()' returns the constant pool 45 * built up. Intermediate versions of the constant pool can be 46 * obtained with `getConstantPool()'. A constant pool has capacity for 47 * Constants.MAX_SHORT entries. Note that the first (0) is used by the 48 * JVM and that Double and Long constants need two slots. 49 * 50 * @version $Id$ 51 * @see Constant 52 */ 53 public class ConstantPoolGen { 54 55 private static final int DEFAULT_BUFFER_SIZE = 256; 56 57 /** 58 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 59 */ 60 @Deprecated 61 protected int size; 62 63 /** 64 * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter 65 */ 66 @Deprecated 67 protected Constant[] constants; 68 69 /** 70 * @deprecated (since 6.0) will be made private; do not access directly, use getSize() 71 */ 72 @Deprecated 73 protected int index = 1; // First entry (0) used by JVM 74 75 private static final String METHODREF_DELIM = ":"; 76 private static final String IMETHODREF_DELIM = "#"; 77 private static final String FIELDREF_DELIM = "&"; 78 private static final String NAT_DELIM = "%"; // Name and Type 79 80 private static class Index { 81 82 final int index; 83 84 Index(final int i)85 Index(final int i) { 86 index = i; 87 } 88 } 89 90 91 /** 92 * Initialize with given array of constants. 93 * 94 * @param cs array of given constants, new ones will be appended 95 */ ConstantPoolGen(final Constant[] cs)96 public ConstantPoolGen(final Constant[] cs) { 97 final StringBuilder sb = new StringBuilder(DEFAULT_BUFFER_SIZE); 98 99 size = Math.max(DEFAULT_BUFFER_SIZE, cs.length + 64); 100 constants = new Constant[size]; 101 102 System.arraycopy(cs, 0, constants, 0, cs.length); 103 if (cs.length > 0) { 104 index = cs.length; 105 } 106 107 108 for (int i = 1; i < index; i++) { 109 final Constant c = constants[i]; 110 if (c instanceof ConstantString) { 111 final ConstantString s = (ConstantString) c; 112 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; 113 final String key = u8.getBytes(); 114 if (!string_table.containsKey(key)) { 115 string_table.put(key, new Index(i)); 116 } 117 } else if (c instanceof ConstantClass) { 118 final ConstantClass s = (ConstantClass) c; 119 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; 120 final String key = u8.getBytes(); 121 if (!class_table.containsKey(key)) { 122 class_table.put(key, new Index(i)); 123 } 124 } else if (c instanceof ConstantNameAndType) { 125 final ConstantNameAndType n = (ConstantNameAndType) c; 126 final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 127 final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; 128 129 sb.append(u8.getBytes()); 130 sb.append(NAT_DELIM); 131 sb.append(u8_2.getBytes()); 132 final String key = sb.toString(); 133 sb.delete(0, sb.length()); 134 135 if (!n_a_t_table.containsKey(key)) { 136 n_a_t_table.put(key, new Index(i)); 137 } 138 } else if (c instanceof ConstantUtf8) { 139 final ConstantUtf8 u = (ConstantUtf8) c; 140 final String key = u.getBytes(); 141 if (!utf8_table.containsKey(key)) { 142 utf8_table.put(key, new Index(i)); 143 } 144 } else if (c instanceof ConstantCP) { 145 final ConstantCP m = (ConstantCP) c; 146 String class_name; 147 ConstantUtf8 u8; 148 149 if (c instanceof ConstantInvokeDynamic) { 150 class_name = Integer.toString(((ConstantInvokeDynamic) m).getBootstrapMethodAttrIndex()); 151 // since name can't begin with digit, can use 152 // METHODREF_DELIM with out fear of duplicates. 153 } else { 154 final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; 155 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; 156 class_name = u8.getBytes().replace('/', '.'); 157 } 158 159 final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; 160 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 161 final String method_name = u8.getBytes(); 162 u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; 163 final String signature = u8.getBytes(); 164 165 String delim = METHODREF_DELIM; 166 if (c instanceof ConstantInterfaceMethodref) { 167 delim = IMETHODREF_DELIM; 168 } else if (c instanceof ConstantFieldref) { 169 delim = FIELDREF_DELIM; 170 } 171 172 sb.append(class_name); 173 sb.append(delim); 174 sb.append(method_name); 175 sb.append(delim); 176 sb.append(signature); 177 final String key = sb.toString(); 178 sb.delete(0, sb.length()); 179 180 if (!cp_table.containsKey(key)) { 181 cp_table.put(key, new Index(i)); 182 } 183 } else if (c == null) { // entries may be null 184 // nothing to do 185 } else if (c instanceof ConstantInteger) { 186 // nothing to do 187 } else if (c instanceof ConstantLong) { 188 // nothing to do 189 } else if (c instanceof ConstantFloat) { 190 // nothing to do 191 } else if (c instanceof ConstantDouble) { 192 // nothing to do 193 } else if (c instanceof org.apache.bcel.classfile.ConstantMethodType) { 194 // TODO should this be handled somehow? 195 } else if (c instanceof org.apache.bcel.classfile.ConstantMethodHandle) { 196 // TODO should this be handled somehow? 197 } else { 198 assert false : "Unexpected constant type: " + c.getClass().getName(); 199 } 200 } 201 } 202 203 204 /** 205 * Initialize with given constant pool. 206 */ ConstantPoolGen(final ConstantPool cp)207 public ConstantPoolGen(final ConstantPool cp) { 208 this(cp.getConstantPool()); 209 } 210 211 212 /** 213 * Create empty constant pool. 214 */ ConstantPoolGen()215 public ConstantPoolGen() { 216 size = DEFAULT_BUFFER_SIZE; 217 constants = new Constant[size]; 218 } 219 220 221 /** Resize internal array of constants. 222 */ adjustSize()223 protected void adjustSize() { 224 if (index + 3 >= size) { 225 final Constant[] cs = constants; 226 size *= 2; 227 constants = new Constant[size]; 228 System.arraycopy(cs, 0, constants, 0, index); 229 } 230 } 231 232 private final Map<String, Index> string_table = new HashMap<>(); 233 234 235 /** 236 * Look for ConstantString in ConstantPool containing String `str'. 237 * 238 * @param str String to search for 239 * @return index on success, -1 otherwise 240 */ lookupString( final String str )241 public int lookupString( final String str ) { 242 final Index index = string_table.get(str); 243 return (index != null) ? index.index : -1; 244 } 245 246 247 /** 248 * Add a new String constant to the ConstantPool, if it is not already in there. 249 * 250 * @param str String to add 251 * @return index of entry 252 */ addString( final String str )253 public int addString( final String str ) { 254 int ret; 255 if ((ret = lookupString(str)) != -1) { 256 return ret; // Already in CP 257 } 258 final int utf8 = addUtf8(str); 259 adjustSize(); 260 final ConstantString s = new ConstantString(utf8); 261 ret = index; 262 constants[index++] = s; 263 if (!string_table.containsKey(str)) { 264 string_table.put(str, new Index(ret)); 265 } 266 return ret; 267 } 268 269 private final Map<String, Index> class_table = new HashMap<>(); 270 271 272 /** 273 * Look for ConstantClass in ConstantPool named `str'. 274 * 275 * @param str String to search for 276 * @return index on success, -1 otherwise 277 */ lookupClass( final String str )278 public int lookupClass( final String str ) { 279 final Index index = class_table.get(str.replace('.', '/')); 280 return (index != null) ? index.index : -1; 281 } 282 283 addClass_( final String clazz )284 private int addClass_( final String clazz ) { 285 int ret; 286 if ((ret = lookupClass(clazz)) != -1) { 287 return ret; // Already in CP 288 } 289 adjustSize(); 290 final ConstantClass c = new ConstantClass(addUtf8(clazz)); 291 ret = index; 292 constants[index++] = c; 293 if (!class_table.containsKey(clazz)) { 294 class_table.put(clazz, new Index(ret)); 295 } 296 return ret; 297 } 298 299 300 /** 301 * Add a new Class reference to the ConstantPool, if it is not already in there. 302 * 303 * @param str Class to add 304 * @return index of entry 305 */ addClass( final String str )306 public int addClass( final String str ) { 307 return addClass_(str.replace('.', '/')); 308 } 309 310 311 /** 312 * Add a new Class reference to the ConstantPool for a given type. 313 * 314 * @param type Class to add 315 * @return index of entry 316 */ addClass( final ObjectType type )317 public int addClass( final ObjectType type ) { 318 return addClass(type.getClassName()); 319 } 320 321 322 /** 323 * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY 324 * instruction, e.g. to the ConstantPool. 325 * 326 * @param type type of array class 327 * @return index of entry 328 */ addArrayClass( final ArrayType type )329 public int addArrayClass( final ArrayType type ) { 330 return addClass_(type.getSignature()); 331 } 332 333 334 /** 335 * Look for ConstantInteger in ConstantPool. 336 * 337 * @param n integer number to look for 338 * @return index on success, -1 otherwise 339 */ lookupInteger( final int n )340 public int lookupInteger( final int n ) { 341 for (int i = 1; i < index; i++) { 342 if (constants[i] instanceof ConstantInteger) { 343 final ConstantInteger c = (ConstantInteger) constants[i]; 344 if (c.getBytes() == n) { 345 return i; 346 } 347 } 348 } 349 return -1; 350 } 351 352 353 /** 354 * Add a new Integer constant to the ConstantPool, if it is not already in there. 355 * 356 * @param n integer number to add 357 * @return index of entry 358 */ addInteger( final int n )359 public int addInteger( final int n ) { 360 int ret; 361 if ((ret = lookupInteger(n)) != -1) { 362 return ret; // Already in CP 363 } 364 adjustSize(); 365 ret = index; 366 constants[index++] = new ConstantInteger(n); 367 return ret; 368 } 369 370 371 /** 372 * Look for ConstantFloat in ConstantPool. 373 * 374 * @param n Float number to look for 375 * @return index on success, -1 otherwise 376 */ lookupFloat( final float n )377 public int lookupFloat( final float n ) { 378 final int bits = Float.floatToIntBits(n); 379 for (int i = 1; i < index; i++) { 380 if (constants[i] instanceof ConstantFloat) { 381 final ConstantFloat c = (ConstantFloat) constants[i]; 382 if (Float.floatToIntBits(c.getBytes()) == bits) { 383 return i; 384 } 385 } 386 } 387 return -1; 388 } 389 390 391 /** 392 * Add a new Float constant to the ConstantPool, if it is not already in there. 393 * 394 * @param n Float number to add 395 * @return index of entry 396 */ addFloat( final float n )397 public int addFloat( final float n ) { 398 int ret; 399 if ((ret = lookupFloat(n)) != -1) { 400 return ret; // Already in CP 401 } 402 adjustSize(); 403 ret = index; 404 constants[index++] = new ConstantFloat(n); 405 return ret; 406 } 407 408 private final Map<String, Index> utf8_table = new HashMap<>(); 409 410 411 /** 412 * Look for ConstantUtf8 in ConstantPool. 413 * 414 * @param n Utf8 string to look for 415 * @return index on success, -1 otherwise 416 */ lookupUtf8( final String n )417 public int lookupUtf8( final String n ) { 418 final Index index = utf8_table.get(n); 419 return (index != null) ? index.index : -1; 420 } 421 422 423 /** 424 * Add a new Utf8 constant to the ConstantPool, if it is not already in there. 425 * 426 * @param n Utf8 string to add 427 * @return index of entry 428 */ addUtf8( final String n )429 public int addUtf8( final String n ) { 430 int ret; 431 if ((ret = lookupUtf8(n)) != -1) { 432 return ret; // Already in CP 433 } 434 adjustSize(); 435 ret = index; 436 constants[index++] = new ConstantUtf8(n); 437 if (!utf8_table.containsKey(n)) { 438 utf8_table.put(n, new Index(ret)); 439 } 440 return ret; 441 } 442 443 444 /** 445 * Look for ConstantLong in ConstantPool. 446 * 447 * @param n Long number to look for 448 * @return index on success, -1 otherwise 449 */ lookupLong( final long n )450 public int lookupLong( final long n ) { 451 for (int i = 1; i < index; i++) { 452 if (constants[i] instanceof ConstantLong) { 453 final ConstantLong c = (ConstantLong) constants[i]; 454 if (c.getBytes() == n) { 455 return i; 456 } 457 } 458 } 459 return -1; 460 } 461 462 463 /** 464 * Add a new long constant to the ConstantPool, if it is not already in there. 465 * 466 * @param n Long number to add 467 * @return index of entry 468 */ addLong( final long n )469 public int addLong( final long n ) { 470 int ret; 471 if ((ret = lookupLong(n)) != -1) { 472 return ret; // Already in CP 473 } 474 adjustSize(); 475 ret = index; 476 constants[index] = new ConstantLong(n); 477 index += 2; // Wastes one entry according to spec 478 return ret; 479 } 480 481 482 /** 483 * Look for ConstantDouble in ConstantPool. 484 * 485 * @param n Double number to look for 486 * @return index on success, -1 otherwise 487 */ lookupDouble( final double n )488 public int lookupDouble( final double n ) { 489 final long bits = Double.doubleToLongBits(n); 490 for (int i = 1; i < index; i++) { 491 if (constants[i] instanceof ConstantDouble) { 492 final ConstantDouble c = (ConstantDouble) constants[i]; 493 if (Double.doubleToLongBits(c.getBytes()) == bits) { 494 return i; 495 } 496 } 497 } 498 return -1; 499 } 500 501 502 /** 503 * Add a new double constant to the ConstantPool, if it is not already in there. 504 * 505 * @param n Double number to add 506 * @return index of entry 507 */ addDouble( final double n )508 public int addDouble( final double n ) { 509 int ret; 510 if ((ret = lookupDouble(n)) != -1) { 511 return ret; // Already in CP 512 } 513 adjustSize(); 514 ret = index; 515 constants[index] = new ConstantDouble(n); 516 index += 2; // Wastes one entry according to spec 517 return ret; 518 } 519 520 private final Map<String, Index> n_a_t_table = new HashMap<>(); 521 522 523 /** 524 * Look for ConstantNameAndType in ConstantPool. 525 * 526 * @param name of variable/method 527 * @param signature of variable/method 528 * @return index on success, -1 otherwise 529 */ lookupNameAndType( final String name, final String signature )530 public int lookupNameAndType( final String name, final String signature ) { 531 final Index _index = n_a_t_table.get(name + NAT_DELIM + signature); 532 return (_index != null) ? _index.index : -1; 533 } 534 535 536 /** 537 * Add a new NameAndType constant to the ConstantPool if it is not already 538 * in there. 539 * 540 * @param name Name string to add 541 * @param signature signature string to add 542 * @return index of entry 543 */ addNameAndType( final String name, final String signature )544 public int addNameAndType( final String name, final String signature ) { 545 int ret; 546 int name_index; 547 int signature_index; 548 if ((ret = lookupNameAndType(name, signature)) != -1) { 549 return ret; // Already in CP 550 } 551 adjustSize(); 552 name_index = addUtf8(name); 553 signature_index = addUtf8(signature); 554 ret = index; 555 constants[index++] = new ConstantNameAndType(name_index, signature_index); 556 final String key = name + NAT_DELIM + signature; 557 if (!n_a_t_table.containsKey(key)) { 558 n_a_t_table.put(key, new Index(ret)); 559 } 560 return ret; 561 } 562 563 private final Map<String, Index> cp_table = new HashMap<>(); 564 565 566 /** 567 * Look for ConstantMethodref in ConstantPool. 568 * 569 * @param class_name Where to find method 570 * @param method_name Guess what 571 * @param signature return and argument types 572 * @return index on success, -1 otherwise 573 */ lookupMethodref( final String class_name, final String method_name, final String signature )574 public int lookupMethodref( final String class_name, final String method_name, final String signature ) { 575 final Index index = cp_table.get(class_name + METHODREF_DELIM + method_name 576 + METHODREF_DELIM + signature); 577 return (index != null) ? index.index : -1; 578 } 579 580 lookupMethodref( final MethodGen method )581 public int lookupMethodref( final MethodGen method ) { 582 return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); 583 } 584 585 586 /** 587 * Add a new Methodref constant to the ConstantPool, if it is not already 588 * in there. 589 * 590 * @param class_name class name string to add 591 * @param method_name method name string to add 592 * @param signature method signature string to add 593 * @return index of entry 594 */ addMethodref( final String class_name, final String method_name, final String signature )595 public int addMethodref( final String class_name, final String method_name, final String signature ) { 596 int ret; 597 int class_index; 598 int name_and_type_index; 599 if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) { 600 return ret; // Already in CP 601 } 602 adjustSize(); 603 name_and_type_index = addNameAndType(method_name, signature); 604 class_index = addClass(class_name); 605 ret = index; 606 constants[index++] = new ConstantMethodref(class_index, name_and_type_index); 607 final String key = class_name + METHODREF_DELIM + method_name + METHODREF_DELIM + signature; 608 if (!cp_table.containsKey(key)) { 609 cp_table.put(key, new Index(ret)); 610 } 611 return ret; 612 } 613 614 addMethodref( final MethodGen method )615 public int addMethodref( final MethodGen method ) { 616 return addMethodref(method.getClassName(), method.getName(), method.getSignature()); 617 } 618 619 620 /** 621 * Look for ConstantInterfaceMethodref in ConstantPool. 622 * 623 * @param class_name Where to find method 624 * @param method_name Guess what 625 * @param signature return and argument types 626 * @return index on success, -1 otherwise 627 */ lookupInterfaceMethodref( final String class_name, final String method_name, final String signature )628 public int lookupInterfaceMethodref( final String class_name, final String method_name, final String signature ) { 629 final Index index = cp_table.get(class_name + IMETHODREF_DELIM + method_name 630 + IMETHODREF_DELIM + signature); 631 return (index != null) ? index.index : -1; 632 } 633 634 lookupInterfaceMethodref( final MethodGen method )635 public int lookupInterfaceMethodref( final MethodGen method ) { 636 return lookupInterfaceMethodref(method.getClassName(), method.getName(), method 637 .getSignature()); 638 } 639 640 641 /** 642 * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already 643 * in there. 644 * 645 * @param class_name class name string to add 646 * @param method_name method name string to add 647 * @param signature signature string to add 648 * @return index of entry 649 */ addInterfaceMethodref( final String class_name, final String method_name, final String signature )650 public int addInterfaceMethodref( final String class_name, final String method_name, final String signature ) { 651 int ret; 652 int class_index; 653 int name_and_type_index; 654 if ((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1) { 655 return ret; // Already in CP 656 } 657 adjustSize(); 658 class_index = addClass(class_name); 659 name_and_type_index = addNameAndType(method_name, signature); 660 ret = index; 661 constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index); 662 final String key = class_name + IMETHODREF_DELIM + method_name + IMETHODREF_DELIM + signature; 663 if (!cp_table.containsKey(key)) { 664 cp_table.put(key, new Index(ret)); 665 } 666 return ret; 667 } 668 669 addInterfaceMethodref( final MethodGen method )670 public int addInterfaceMethodref( final MethodGen method ) { 671 return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); 672 } 673 674 675 /** 676 * Look for ConstantFieldref in ConstantPool. 677 * 678 * @param class_name Where to find method 679 * @param field_name Guess what 680 * @param signature return and argument types 681 * @return index on success, -1 otherwise 682 */ lookupFieldref( final String class_name, final String field_name, final String signature )683 public int lookupFieldref( final String class_name, final String field_name, final String signature ) { 684 final Index index = cp_table.get(class_name + FIELDREF_DELIM + field_name 685 + FIELDREF_DELIM + signature); 686 return (index != null) ? index.index : -1; 687 } 688 689 690 /** 691 * Add a new Fieldref constant to the ConstantPool, if it is not already 692 * in there. 693 * 694 * @param class_name class name string to add 695 * @param field_name field name string to add 696 * @param signature signature string to add 697 * @return index of entry 698 */ addFieldref( final String class_name, final String field_name, final String signature )699 public int addFieldref( final String class_name, final String field_name, final String signature ) { 700 int ret; 701 int class_index; 702 int name_and_type_index; 703 if ((ret = lookupFieldref(class_name, field_name, signature)) != -1) { 704 return ret; // Already in CP 705 } 706 adjustSize(); 707 class_index = addClass(class_name); 708 name_and_type_index = addNameAndType(field_name, signature); 709 ret = index; 710 constants[index++] = new ConstantFieldref(class_index, name_and_type_index); 711 final String key = class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature; 712 if (!cp_table.containsKey(key)) { 713 cp_table.put(key, new Index(ret)); 714 } 715 return ret; 716 } 717 718 719 /** 720 * @param i index in constant pool 721 * @return constant pool entry at index i 722 */ getConstant( final int i )723 public Constant getConstant( final int i ) { 724 return constants[i]; 725 } 726 727 728 /** 729 * Use with care! 730 * 731 * @param i index in constant pool 732 * @param c new constant pool entry at index i 733 */ setConstant( final int i, final Constant c )734 public void setConstant( final int i, final Constant c ) { 735 constants[i] = c; 736 } 737 738 739 /** 740 * @return intermediate constant pool 741 */ getConstantPool()742 public ConstantPool getConstantPool() { 743 return new ConstantPool(constants); 744 } 745 746 747 /** 748 * @return current size of constant pool 749 */ getSize()750 public int getSize() { 751 return index; 752 } 753 754 755 /** 756 * @return constant pool with proper length 757 */ getFinalConstantPool()758 public ConstantPool getFinalConstantPool() { 759 final Constant[] cs = new Constant[index]; 760 System.arraycopy(constants, 0, cs, 0, index); 761 return new ConstantPool(cs); 762 } 763 764 765 /** 766 * @return String representation. 767 */ 768 @Override toString()769 public String toString() { 770 final StringBuilder buf = new StringBuilder(); 771 for (int i = 1; i < index; i++) { 772 buf.append(i).append(")").append(constants[i]).append("\n"); 773 } 774 return buf.toString(); 775 } 776 777 778 /** Import constant from another ConstantPool and return new index. 779 */ addConstant( final Constant c, final ConstantPoolGen cp )780 public int addConstant( final Constant c, final ConstantPoolGen cp ) { 781 final Constant[] constants = cp.getConstantPool().getConstantPool(); 782 switch (c.getTag()) { 783 case Const.CONSTANT_String: { 784 final ConstantString s = (ConstantString) c; 785 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; 786 return addString(u8.getBytes()); 787 } 788 case Const.CONSTANT_Class: { 789 final ConstantClass s = (ConstantClass) c; 790 final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; 791 return addClass(u8.getBytes()); 792 } 793 case Const.CONSTANT_NameAndType: { 794 final ConstantNameAndType n = (ConstantNameAndType) c; 795 final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 796 final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; 797 return addNameAndType(u8.getBytes(), u8_2.getBytes()); 798 } 799 case Const.CONSTANT_Utf8: 800 return addUtf8(((ConstantUtf8) c).getBytes()); 801 case Const.CONSTANT_Double: 802 return addDouble(((ConstantDouble) c).getBytes()); 803 case Const.CONSTANT_Float: 804 return addFloat(((ConstantFloat) c).getBytes()); 805 case Const.CONSTANT_Long: 806 return addLong(((ConstantLong) c).getBytes()); 807 case Const.CONSTANT_Integer: 808 return addInteger(((ConstantInteger) c).getBytes()); 809 case Const.CONSTANT_InterfaceMethodref: 810 case Const.CONSTANT_Methodref: 811 case Const.CONSTANT_Fieldref: { 812 final ConstantCP m = (ConstantCP) c; 813 final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; 814 final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; 815 ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; 816 final String class_name = u8.getBytes().replace('/', '.'); 817 u8 = (ConstantUtf8) constants[n.getNameIndex()]; 818 final String name = u8.getBytes(); 819 u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; 820 final String signature = u8.getBytes(); 821 switch (c.getTag()) { 822 case Const.CONSTANT_InterfaceMethodref: 823 return addInterfaceMethodref(class_name, name, signature); 824 case Const.CONSTANT_Methodref: 825 return addMethodref(class_name, name, signature); 826 case Const.CONSTANT_Fieldref: 827 return addFieldref(class_name, name, signature); 828 default: // Never reached 829 throw new RuntimeException("Unknown constant type " + c); 830 } 831 } 832 default: // Never reached 833 throw new RuntimeException("Unknown constant type " + c); 834 } 835 } 836 } 837