1 30 31 package oracle.toplink.libraries.asm; 32 33 42 43 public class ClassWriter implements ClassVisitor { 44 45 48 49 final static int CLASS = 7; 50 51 54 55 final static int FIELD = 9; 56 57 60 61 final static int METH = 10; 62 63 66 67 final static int IMETH = 11; 68 69 72 73 final static int STR = 8; 74 75 78 79 final static int INT = 3; 80 81 84 85 final static int FLOAT = 4; 86 87 90 91 final static int LONG = 5; 92 93 96 97 final static int DOUBLE = 6; 98 99 102 103 final static int NAME_TYPE = 12; 104 105 108 109 final static int UTF8 = 1; 110 111 114 115 private int version; 116 117 120 121 private short index; 122 123 126 127 private ByteVector pool; 128 129 132 133 private Item[] items; 134 135 138 139 private int threshold; 140 141 144 145 private int access; 146 147 150 151 private int name; 152 153 157 158 private int superName; 159 160 163 164 private int interfaceCount; 165 166 171 172 private int[] interfaces; 173 174 178 179 private int sourceFile; 180 181 184 185 private int fieldCount; 186 187 190 191 private ByteVector fields; 192 193 197 198 private boolean computeMaxs; 199 200 203 204 boolean checkAttributes; 205 206 211 212 CodeWriter firstMethod; 213 214 219 220 CodeWriter lastMethod; 221 222 225 226 private int innerClassesCount; 227 228 231 232 private ByteVector innerClasses; 233 234 237 238 private Attribute attrs; 239 240 243 244 Item key; 245 246 249 250 Item key2; 251 252 255 256 Item key3; 257 258 261 262 final static int NOARG_INSN = 0; 263 264 267 268 final static int SBYTE_INSN = 1; 269 270 273 274 final static int SHORT_INSN = 2; 275 276 279 280 final static int VAR_INSN = 3; 281 282 285 286 final static int IMPLVAR_INSN = 4; 287 288 291 292 final static int TYPE_INSN = 5; 293 294 297 298 final static int FIELDORMETH_INSN = 6; 299 300 303 304 final static int ITFMETH_INSN = 7; 305 306 309 310 final static int LABEL_INSN = 8; 311 312 315 316 final static int LABELW_INSN = 9; 317 318 321 322 final static int LDC_INSN = 10; 323 324 327 328 final static int LDCW_INSN = 11; 329 330 333 334 final static int IINC_INSN = 12; 335 336 339 340 final static int TABL_INSN = 13; 341 342 345 346 final static int LOOK_INSN = 14; 347 348 351 352 final static int MANA_INSN = 15; 353 354 357 358 final static int WIDE_INSN = 16; 359 360 363 364 static byte[] TYPE; 365 366 370 373 374 static { 375 int i; 376 byte[] b = new byte[220]; 377 String s = 378 "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADDDDDEEEEEEEEE" + 379 "EEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA" + 380 "AAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAAAAAAGGGGGGGHAFBFAAFFAAQPIIJJII" + 381 "IIIIIIIIIIIIIIII"; 382 for (i = 0; i < b.length; ++i) { 383 b[i] = (byte)(s.charAt(i) - 'A'); 384 } 385 TYPE = b; 386 387 453 } 454 455 459 470 471 public ClassWriter (final boolean computeMaxs) { 472 this(computeMaxs, false); 473 } 474 475 489 490 public ClassWriter ( 491 final boolean computeMaxs, 492 final boolean skipUnknownAttributes) 493 { 494 index = 1; 495 pool = new ByteVector(); 496 items = new Item[64]; 497 threshold = (int)(0.75d*items.length); 498 key = new Item(); 499 key2 = new Item(); 500 key3 = new Item(); 501 this.computeMaxs = computeMaxs; 502 this.checkAttributes = !skipUnknownAttributes; 503 } 504 505 509 public void visit ( 510 final int version, 511 final int access, 512 final String name, 513 final String superName, 514 final String [] interfaces, 515 final String sourceFile) 516 { 517 this.version = version; 518 this.access = access; 519 this.name = newClass(name); 520 this.superName = superName == null ? 0 : newClass(superName); 521 if (interfaces != null && interfaces.length > 0) { 522 interfaceCount = interfaces.length; 523 this.interfaces = new int[interfaceCount]; 524 for (int i = 0; i < interfaceCount; ++i) { 525 this.interfaces[i] = newClass(interfaces[i]); 526 } 527 } 528 if (sourceFile != null) { 529 newUTF8("SourceFile"); 530 this.sourceFile = newUTF8(sourceFile); 531 } 532 if ((access & Constants.ACC_DEPRECATED) != 0) { 533 newUTF8("Deprecated"); 534 } 535 if ((access & Constants.ACC_SYNTHETIC) != 0) { 536 newUTF8("Synthetic"); 537 } 538 } 539 540 public void visitInnerClass ( 541 final String name, 542 final String outerName, 543 final String innerName, 544 final int access) 545 { 546 if (innerClasses == null) { 547 newUTF8("InnerClasses"); 548 innerClasses = new ByteVector(); 549 } 550 ++innerClassesCount; 551 innerClasses.putShort(name == null ? 0 : newClass(name)); 552 innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); 553 innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); 554 innerClasses.putShort(access); 555 } 556 557 public void visitField ( 558 final int access, 559 final String name, 560 final String desc, 561 final Object value, 562 final Attribute attrs) 563 { 564 ++fieldCount; 565 if (fields == null) { 566 fields = new ByteVector(); 567 } 568 fields.putShort(access).putShort(newUTF8(name)).putShort(newUTF8(desc)); 569 int attributeCount = 0; 570 if (value != null) { 571 ++attributeCount; 572 } 573 if ((access & Constants.ACC_SYNTHETIC) != 0) { 574 ++attributeCount; 575 } 576 if ((access & Constants.ACC_DEPRECATED) != 0) { 577 ++attributeCount; 578 } 579 if (attrs != null) { 580 attributeCount += attrs.getCount(); 581 } 582 fields.putShort(attributeCount); 583 if (value != null) { 584 fields.putShort(newUTF8("ConstantValue")); 585 fields.putInt(2).putShort(newConstItem(value).index); 586 } 587 if ((access & Constants.ACC_SYNTHETIC) != 0) { 588 fields.putShort(newUTF8("Synthetic")).putInt(0); 589 } 590 if ((access & Constants.ACC_DEPRECATED) != 0) { 591 fields.putShort(newUTF8("Deprecated")).putInt(0); 592 } 593 if (attrs != null) { 594 attrs.put(this, null, 0, -1, -1, fields); 595 } 596 } 597 598 public CodeVisitor visitMethod ( 599 final int access, 600 final String name, 601 final String desc, 602 final String [] exceptions, 603 final Attribute attrs) 604 { 605 CodeWriter cw = new CodeWriter(this, computeMaxs); 606 cw.init(access, name, desc, exceptions, attrs); 607 return cw; 608 } 609 610 public void visitAttribute (final Attribute attr) { 611 attr.next = attrs; 612 attrs = attr; 613 } 614 615 public void visitEnd () { 616 } 617 618 622 627 628 public byte[] toByteArray () { 629 int size = 24 + 2*interfaceCount; 631 if (fields != null) { 632 size += fields.length; 633 } 634 int nbMethods = 0; 635 CodeWriter cb = firstMethod; 636 while (cb != null) { 637 ++nbMethods; 638 size += cb.getSize(); 639 cb = cb.next; 640 } 641 int attributeCount = 0; 642 if (sourceFile != 0) { 643 ++attributeCount; 644 size += 8; 645 } 646 if ((access & Constants.ACC_DEPRECATED) != 0) { 647 ++attributeCount; 648 size += 6; 649 } 650 if ((access & Constants.ACC_SYNTHETIC) != 0) { 651 ++attributeCount; 652 size += 6; 653 } 654 if (innerClasses != null) { 655 ++attributeCount; 656 size += 8 + innerClasses.length; 657 } 658 if (attrs != null) { 659 attributeCount += attrs.getCount(); 660 size += attrs.getSize(this, null, 0, -1, -1); 661 } 662 size += pool.length; 663 ByteVector out = new ByteVector(size); 666 out.putInt(0xCAFEBABE).putInt(version); 667 out.putShort(index).putByteArray(pool.data, 0, pool.length); 668 out.putShort(access).putShort(name).putShort(superName); 669 out.putShort(interfaceCount); 670 for (int i = 0; i < interfaceCount; ++i) { 671 out.putShort(interfaces[i]); 672 } 673 out.putShort(fieldCount); 674 if (fields != null) { 675 out.putByteArray(fields.data, 0, fields.length); 676 } 677 out.putShort(nbMethods); 678 cb = firstMethod; 679 while (cb != null) { 680 cb.put(out); 681 cb = cb.next; 682 } 683 out.putShort(attributeCount); 684 if (sourceFile != 0) { 685 out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile); 686 } 687 if ((access & Constants.ACC_DEPRECATED) != 0) { 688 out.putShort(newUTF8("Deprecated")).putInt(0); 689 } 690 if ((access & Constants.ACC_SYNTHETIC) != 0) { 691 out.putShort(newUTF8("Synthetic")).putInt(0); 692 } 693 if (innerClasses != null) { 694 out.putShort(newUTF8("InnerClasses")); 695 out.putInt(innerClasses.length + 2).putShort(innerClassesCount); 696 out.putByteArray(innerClasses.data, 0, innerClasses.length); 697 } 698 if (attrs != null) { 699 attrs.put(this, null, 0, -1, -1, out); 700 } 701 return out.data; 702 } 703 704 708 718 719 Item newConstItem (final Object cst) { 720 if (cst instanceof Integer ) { 721 int val = ((Integer )cst).intValue(); 722 return newInteger(val); 723 } else if (cst instanceof Byte ) { 724 int val = ((Byte )cst).intValue(); 725 return newInteger(val); 726 } else if (cst instanceof Character ) { 727 int val = ((Character )cst).charValue(); 728 return newInteger(val); 729 } else if (cst instanceof Short ) { 730 int val = ((Short )cst).intValue(); 731 return newInteger(val); 732 } else if (cst instanceof Boolean ) { 733 int val = ((Boolean )cst).booleanValue() ? 1 : 0; 734 return newInteger(val); 735 } else if (cst instanceof Float ) { 736 float val = ((Float )cst).floatValue(); 737 return newFloat(val); 738 } else if (cst instanceof Long ) { 739 long val = ((Long )cst).longValue(); 740 return newLong(val); 741 } else if (cst instanceof Double ) { 742 double val = ((Double )cst).doubleValue(); 743 return newDouble(val); 744 } else if (cst instanceof String ) { 745 return newString((String )cst); 746 } else if (cst instanceof Type) { 747 Type t = (Type)cst; 748 return newClassItem( 749 t.getSort() == Type.OBJECT ? t.getInternalName() : t.getDescriptor()); 750 } else { 751 throw new IllegalArgumentException ("value " + cst); 752 } 753 } 754 755 768 769 public int newConst (final Object cst) { 770 return newConstItem(cst).index; 771 } 772 773 public int newConstInt (final int i) { 774 return newInteger(i).index; 775 } 776 777 public int newConstLong (final long l) { 778 return newLong(l).index; 779 } 780 781 public int newConstFloat (final float f) { 782 return newFloat(f).index; 783 } 784 785 public int newConstDouble (final double d) { 786 return newDouble(d).index; 787 } 788 789 798 799 public int newUTF8 (final String value) { 800 key.set(UTF8, value, null, null); 801 Item result = get(key); 802 if (result == null) { 803 pool.putByte(UTF8).putUTF8(value); 804 result = new Item(index++, key); 805 put(result); 806 } 807 return result.index; 808 } 809 810 819 820 public int newClass (final String value) { 821 return newClassItem(value).index; 822 } 823 824 833 834 private Item newClassItem (final String value) { 835 key2.set(CLASS, value, null, null); 836 Item result = get(key2); 837 if (result == null) { 838 pool.put12(CLASS, newUTF8(value)); 839 result = new Item(index++, key2); 840 put(result); 841 } 842 return result; 843 } 844 845 856 857 public int newField ( 858 final String owner, 859 final String name, 860 final String desc) 861 { 862 key3.set(FIELD, owner, name, desc); 863 Item result = get(key3); 864 if (result == null) { 865 put122(FIELD, newClass(owner), newNameType(name, desc)); 866 result = new Item(index++, key3); 867 put(result); 868 } 869 return result.index; 870 } 871 872 882 883 Item newMethodItem ( 884 final String owner, 885 final String name, 886 final String desc, 887 final boolean itf) 888 { 889 key3.set(itf ? IMETH : METH, owner, name, desc); 890 Item result = get(key3); 891 if (result == null) { 892 put122(itf ? IMETH : METH, newClass(owner), newNameType(name, desc)); 893 result = new Item(index++, key3); 894 put(result); 895 } 896 return result; 897 } 898 899 911 912 public int newMethod ( 913 final String owner, 914 final String name, 915 final String desc, 916 final boolean itf) 917 { 918 return newMethodItem(owner, name, desc, itf).index; 919 } 920 921 928 929 private Item newInteger (final int value) { 930 key.set(value); 931 Item result = get(key); 932 if (result == null) { 933 pool.putByte(INT).putInt(value); 934 result = new Item(index++, key); 935 put(result); 936 } 937 return result; 938 } 939 940 947 948 private Item newFloat (final float value) { 949 key.set(value); 950 Item result = get(key); 951 if (result == null) { 952 pool.putByte(FLOAT).putInt(Float.floatToIntBits(value)); 953 result = new Item(index++, key); 954 put(result); 955 } 956 return result; 957 } 958 959 966 967 private Item newLong (final long value) { 968 key.set(value); 969 Item result = get(key); 970 if (result == null) { 971 pool.putByte(LONG).putLong(value); 972 result = new Item(index, key); 973 put(result); 974 index += 2; 975 } 976 return result; 977 } 978 979 986 987 private Item newDouble (final double value) { 988 key.set(value); 989 Item result = get(key); 990 if (result == null) { 991 pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value)); 992 result = new Item(index, key); 993 put(result); 994 index += 2; 995 } 996 return result; 997 } 998 999 1006 1007 private Item newString (final String value) { 1008 key2.set(STR, value, null, null); 1009 Item result = get(key2); 1010 if (result == null) { 1011 pool.put12(STR, newUTF8(value)); 1012 result = new Item(index++, key2); 1013 put(result); 1014 } 1015 return result; 1016 } 1017 1018 1028 1029 public int newNameType (final String name, final String desc) { 1030 key2.set(NAME_TYPE, name, desc, null); 1031 Item result = get(key2); 1032 if (result == null) { 1033 put122(NAME_TYPE, newUTF8(name), newUTF8(desc)); 1034 result = new Item(index++, key2); 1035 put(result); 1036 } 1037 return result.index; 1038 } 1039 1040 1048 1049 private Item get (final Item key) { 1050 int h = key.hashCode; 1051 Item i = items[h % items.length]; 1052 while (i != null) { 1053 if (i.hashCode == h && key.isEqualTo(i)) { 1054 return i; 1055 } 1056 i = i.next; 1057 } 1058 return null; 1059 } 1060 1061 1067 1068 private void put (final Item i) { 1069 if (index > threshold) { 1070 Item[] newItems = new Item[items.length * 2 + 1]; 1071 for (int l = items.length - 1; l >= 0; --l) { 1072 Item j = items[l]; 1073 while (j != null) { 1074 int index = j.hashCode % newItems.length; 1075 Item k = j.next; 1076 j.next = newItems[index]; 1077 newItems[index] = j; 1078 j = k; 1079 } 1080 } 1081 items = newItems; 1082 threshold = (int)(items.length * 0.75); 1083 } 1084 int index = i.hashCode % items.length; 1085 i.next = items[index]; 1086 items[index] = i; 1087 } 1088 1089 1096 1097 private void put122 (final int b, final int s1, final int s2) { 1098 pool.put12(b, s1).putShort(s2); 1099 } 1100} 1101 | Popular Tags |