1 34 35 package org.logicalcobwebs.asm; 36 37 44 45 public class ClassWriter implements ClassVisitor { 46 47 50 51 final static int CLASS = 7; 52 53 56 57 final static int FIELD = 9; 58 59 62 63 final static int METH = 10; 64 65 68 69 final static int IMETH = 11; 70 71 74 75 final static int STR = 8; 76 77 80 81 final static int INT = 3; 82 83 86 87 final static int FLOAT = 4; 88 89 92 93 final static int LONG = 5; 94 95 98 99 final static int DOUBLE = 6; 100 101 104 105 final static int NAME_TYPE = 12; 106 107 110 111 final static int UTF8 = 1; 112 113 116 117 private short index; 118 119 122 123 private ByteVector pool; 124 125 128 129 private Item[] table; 130 131 134 135 private int threshold; 136 137 140 141 private int access; 142 143 146 147 private int name; 148 149 153 154 private int superName; 155 156 159 160 private int interfaceCount; 161 162 167 168 private int[] interfaces; 169 170 174 175 private int sourceFile; 176 177 180 181 private int fieldCount; 182 183 186 187 private ByteVector fields; 188 189 193 194 private boolean computeMaxs; 195 196 201 202 CodeWriter firstMethod; 203 204 209 210 CodeWriter lastMethod; 211 212 215 216 private int innerClassesCount; 217 218 221 222 private ByteVector innerClasses; 223 224 227 228 private Attribute attrs; 229 230 233 234 Item key; 235 236 239 240 Item key2; 241 242 245 246 Item key3; 247 248 251 252 final static int NOARG_INSN = 0; 253 254 257 258 final static int SBYTE_INSN = 1; 259 260 263 264 final static int SHORT_INSN = 2; 265 266 269 270 final static int VAR_INSN = 3; 271 272 275 276 final static int IMPLVAR_INSN = 4; 277 278 281 282 final static int TYPE_INSN = 5; 283 284 287 288 final static int FIELDORMETH_INSN = 6; 289 290 293 294 final static int ITFMETH_INSN = 7; 295 296 299 300 final static int LABEL_INSN = 8; 301 302 305 306 final static int LABELW_INSN = 9; 307 308 311 312 final static int LDC_INSN = 10; 313 314 317 318 final static int LDCW_INSN = 11; 319 320 323 324 final static int IINC_INSN = 12; 325 326 329 330 final static int TABL_INSN = 13; 331 332 335 336 final static int LOOK_INSN = 14; 337 338 341 342 final static int MANA_INSN = 15; 343 344 347 348 final static int WIDE_INSN = 16; 349 350 353 354 static byte[] TYPE; 355 356 360 363 364 static { 365 int i; 366 byte[] b = new byte[220]; 367 String s = 368 "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADDDDDEEEEEEEEE" + 369 "EEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA" + 370 "AAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAAAAAAGGGGGGGHAFBFAAFFAAQPIIJJII" + 371 "IIIIIIIIIIIIIIII"; 372 for (i = 0; i < b.length; ++i) { 373 b[i] = (byte)(s.charAt(i) - 'A'); 374 } 375 TYPE = b; 376 377 443 } 444 445 449 460 461 public ClassWriter (final boolean computeMaxs) { 462 index = 1; 463 pool = new ByteVector(); 464 table = new Item[64]; 465 threshold = (int)(0.75d*table.length); 466 key = new Item(); 467 key2 = new Item(); 468 key3 = new Item(); 469 this.computeMaxs = computeMaxs; 470 } 471 472 476 public void visit ( 477 final int access, 478 final String name, 479 final String superName, 480 final String [] interfaces, 481 final String sourceFile) 482 { 483 this.access = access; 484 this.name = newClass(name); 485 this.superName = superName == null ? 0 : newClass(superName); 486 if (interfaces != null && interfaces.length > 0) { 487 interfaceCount = interfaces.length; 488 this.interfaces = new int[interfaceCount]; 489 for (int i = 0; i < interfaceCount; ++i) { 490 this.interfaces[i] = newClass(interfaces[i]); 491 } 492 } 493 if (sourceFile != null) { 494 newUTF8("SourceFile"); 495 this.sourceFile = newUTF8(sourceFile); 496 } 497 if ((access & Constants.ACC_DEPRECATED) != 0) { 498 newUTF8("Deprecated"); 499 } 500 } 501 502 public void visitInnerClass ( 503 final String name, 504 final String outerName, 505 final String innerName, 506 final int access) 507 { 508 if (innerClasses == null) { 509 newUTF8("InnerClasses"); 510 innerClasses = new ByteVector(); 511 } 512 ++innerClassesCount; 513 innerClasses.put2(name == null ? 0 : newClass(name)); 514 innerClasses.put2(outerName == null ? 0 : newClass(outerName)); 515 innerClasses.put2(innerName == null ? 0 : newUTF8(innerName)); 516 innerClasses.put2(access); 517 } 518 519 public void visitField ( 520 final int access, 521 final String name, 522 final String desc, 523 final Object value, 524 final Attribute attrs) 525 { 526 ++fieldCount; 527 if (fields == null) { 528 fields = new ByteVector(); 529 } 530 fields.put2(access).put2(newUTF8(name)).put2(newUTF8(desc)); 531 int attributeCount = 0; 532 if (value != null) { 533 ++attributeCount; 534 } 535 if ((access & Constants.ACC_SYNTHETIC) != 0) { 536 ++attributeCount; 537 } 538 if ((access & Constants.ACC_DEPRECATED) != 0) { 539 ++attributeCount; 540 } 541 if (attrs != null) { 542 attributeCount += attrs.getCount(); 543 } 544 fields.put2(attributeCount); 545 if (value != null) { 546 fields.put2(newUTF8("ConstantValue")); 547 fields.put4(2).put2(newConst(value).index); 548 } 549 if ((access & Constants.ACC_SYNTHETIC) != 0) { 550 fields.put2(newUTF8("Synthetic")).put4(0); 551 } 552 if ((access & Constants.ACC_DEPRECATED) != 0) { 553 fields.put2(newUTF8("Deprecated")).put4(0); 554 } 555 if (attrs != null) { 556 attrs.getSize(this); 557 attrs.put(this, fields); 558 } 559 } 560 561 public CodeVisitor visitMethod ( 562 final int access, 563 final String name, 564 final String desc, 565 final String [] exceptions, 566 final Attribute attrs) 567 { 568 CodeWriter cw = new CodeWriter(this, computeMaxs); 569 cw.init(access, name, desc, exceptions, attrs); 570 return cw; 571 } 572 573 public void visitAttribute (final Attribute attr) { 574 attr.next = attrs; 575 attrs = attr; 576 } 577 578 public void visitEnd () { 579 } 580 581 585 590 591 public byte[] toByteArray () { 592 int size = 24 + 2*interfaceCount; 594 if (fields != null) { 595 size += fields.length; 596 } 597 int nbMethods = 0; 598 CodeWriter cb = firstMethod; 599 while (cb != null) { 600 ++nbMethods; 601 size += cb.getSize(); 602 cb = cb.next; 603 } 604 int attributeCount = 0; 605 if (sourceFile != 0) { 606 ++attributeCount; 607 size += 8; 608 } 609 if ((access & Constants.ACC_DEPRECATED) != 0) { 610 ++attributeCount; 611 size += 6; 612 } 613 if (innerClasses != null) { 614 ++attributeCount; 615 size += 8 + innerClasses.length; 616 } 617 if (attrs != null) { 618 attributeCount += attrs.getCount(); 619 size += attrs.getSize(this); 620 } 621 size += pool.length; 622 ByteVector out = new ByteVector(size); 625 out.put4(0xCAFEBABE).put2(3).put2(45); 626 out.put2(index).putByteArray(pool.data, 0, pool.length); 627 out.put2(access).put2(name).put2(superName); 628 out.put2(interfaceCount); 629 for (int i = 0; i < interfaceCount; ++i) { 630 out.put2(interfaces[i]); 631 } 632 out.put2(fieldCount); 633 if (fields != null) { 634 out.putByteArray(fields.data, 0, fields.length); 635 } 636 out.put2(nbMethods); 637 cb = firstMethod; 638 while (cb != null) { 639 cb.put(out); 640 cb = cb.next; 641 } 642 out.put2(attributeCount); 643 if (sourceFile != 0) { 644 out.put2(newUTF8("SourceFile")).put4(2).put2(sourceFile); 645 } 646 if ((access & Constants.ACC_DEPRECATED) != 0) { 647 out.put2(newUTF8("Deprecated")).put4(0); 648 } 649 if (innerClasses != null) { 650 out.put2(newUTF8("InnerClasses")); 651 out.put4(innerClasses.length + 2).put2(innerClassesCount); 652 out.putByteArray(innerClasses.data, 0, innerClasses.length); 653 } 654 if (attrs != null) { 655 attrs.put(this, out); 656 } 657 return out.data; 658 } 659 660 664 674 675 Item newConst (final Object cst) { 676 if (cst instanceof Integer ) { 677 int val = ((Integer )cst).intValue(); 678 return newInteger(val); 679 } else if (cst instanceof Float ) { 680 float val = ((Float )cst).floatValue(); 681 return newFloat(val); 682 } else if (cst instanceof Long ) { 683 long val = ((Long )cst).longValue(); 684 return newLong(val); 685 } else if (cst instanceof Double ) { 686 double val = ((Double )cst).doubleValue(); 687 return newDouble(val); 688 } else if (cst instanceof String ) { 689 return newString((String )cst); 690 } else { 691 throw new IllegalArgumentException ("value " + cst); 692 } 693 } 694 695 706 707 protected int newCst (final Object cst) { 708 return newConst(cst).index; 709 } 710 711 718 719 protected int newUTF8 (final String value) { 720 key.set(UTF8, value, null, null); 721 Item result = get(key); 722 if (result == null) { 723 pool.put1(UTF8).putUTF(value); 724 result = new Item(index++, key); 725 put(result); 726 } 727 return result.index; 728 } 729 730 737 738 protected int newClass (final String value) { 739 key2.set(CLASS, value, null, null); 740 Item result = get(key2); 741 if (result == null) { 742 pool.put12(CLASS, newUTF8(value)); 743 result = new Item(index++, key2); 744 put(result); 745 } 746 return result.index; 747 } 748 749 758 759 protected int newField ( 760 final String owner, 761 final String name, 762 final String desc) 763 { 764 key3.set(FIELD, owner, name, desc); 765 Item result = get(key3); 766 if (result == null) { 767 put122(FIELD, newClass(owner), newNameType(name, desc)); 768 result = new Item(index++, key3); 769 put(result); 770 } 771 return result.index; 772 } 773 774 784 785 Item newMethodItem ( 786 final String owner, 787 final String name, 788 final String desc, 789 final boolean itf) 790 { 791 key3.set(itf ? IMETH : METH, owner, name, desc); 792 Item result = get(key3); 793 if (result == null) { 794 put122(itf ? IMETH : METH, newClass(owner), newNameType(name, desc)); 795 result = new Item(index++, key3); 796 put(result); 797 } 798 return result; 799 } 800 801 811 812 protected int newMethod ( 813 final String owner, 814 final String name, 815 final String desc, 816 final boolean itf) 817 { 818 return newMethodItem(owner, name, desc, itf).index; 819 } 820 821 828 829 private Item newInteger (final int value) { 830 key.set(value); 831 Item result = get(key); 832 if (result == null) { 833 pool.put1(INT).put4(value); 834 result = new Item(index++, key); 835 put(result); 836 } 837 return result; 838 } 839 840 847 848 private Item newFloat (final float value) { 849 key.set(value); 850 Item result = get(key); 851 if (result == null) { 852 pool.put1(FLOAT).put4(Float.floatToIntBits(value)); 853 result = new Item(index++, key); 854 put(result); 855 } 856 return result; 857 } 858 859 866 867 private Item newLong (final long value) { 868 key.set(value); 869 Item result = get(key); 870 if (result == null) { 871 pool.put1(LONG).put8(value); 872 result = new Item(index, key); 873 put(result); 874 index += 2; 875 } 876 return result; 877 } 878 879 886 887 private Item newDouble (final double value) { 888 key.set(value); 889 Item result = get(key); 890 if (result == null) { 891 pool.put1(DOUBLE).put8(Double.doubleToLongBits(value)); 892 result = new Item(index, key); 893 put(result); 894 index += 2; 895 } 896 return result; 897 } 898 899 906 907 private Item newString (final String value) { 908 key2.set(STR, value, null, null); 909 Item result = get(key2); 910 if (result == null) { 911 pool.put12(STR, newUTF8(value)); 912 result = new Item(index++, key2); 913 put(result); 914 } 915 return result; 916 } 917 918 926 927 protected int newNameType (final String name, final String desc) { 928 key2.set(NAME_TYPE, name, desc, null); 929 Item result = get(key2); 930 if (result == null) { 931 put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); 932 result = new Item(index++, key2); 933 put(result); 934 } 935 return result.index; 936 } 937 938 946 947 private Item get (final Item key) { 948 Item tab[] = table; 949 int hashCode = key.hashCode; 950 int index = (hashCode & 0x7FFFFFFF) % tab.length; 951 for (Item i = tab[index]; i != null; i = i.next) { 952 if (i.hashCode == hashCode && key.isEqualTo(i)) { 953 return i; 954 } 955 } 956 return null; 957 } 958 959 965 966 private void put (final Item i) { 967 if (index > threshold) { 968 int oldCapacity = table.length; 969 Item oldMap[] = table; 970 int newCapacity = oldCapacity * 2 + 1; 971 Item newMap[] = new Item[newCapacity]; 972 threshold = (int)(newCapacity * 0.75); 973 table = newMap; 974 for (int j = oldCapacity; j-- > 0; ) { 975 for (Item old = oldMap[j]; old != null; ) { 976 Item e = old; 977 old = old.next; 978 int index = (e.hashCode & 0x7FFFFFFF) % newCapacity; 979 e.next = newMap[index]; 980 newMap[index] = e; 981 } 982 } 983 } 984 int index = (i.hashCode & 0x7FFFFFFF) % table.length; 985 i.next = table[index]; 986 table[index] = i; 987 } 988 989 996 997 private void put122 (final int b, final int s1, final int s2) { 998 pool.put12(b, s1).put2(s2); 999 } 1000 1001 1005 1013 1014 protected byte[] writeAttribute (final Attribute attr) { 1015 if (attr.b == null) { 1016 throw new IllegalArgumentException ( 1017 "Unsupported attribute type: " + attr.type); 1018 } else { 1019 byte[] b = new byte[attr.len]; 1020 System.arraycopy(attr.b, attr.off, b, 0, attr.len); 1021 return b; 1022 } 1023 } 1024} 1025 | Popular Tags |