1 16 17 package org.cojen.classfile; 18 19 import java.lang.reflect.Method ; 20 import java.lang.reflect.Modifier ; 21 import java.util.Set ; 22 import java.util.HashSet ; 23 import java.util.List ; 24 import java.util.ArrayList ; 25 import java.util.Map ; 26 import java.util.HashMap ; 27 import java.io.DataInput ; 28 import java.io.DataInputStream ; 29 import java.io.DataOutput ; 30 import java.io.DataOutputStream ; 31 import java.io.InputStream ; 32 import java.io.IOException ; 33 import java.io.OutputStream ; 34 import org.cojen.classfile.attribute.Annotation; 35 import org.cojen.classfile.attribute.AnnotationsAttr; 36 import org.cojen.classfile.attribute.DeprecatedAttr; 37 import org.cojen.classfile.attribute.InnerClassesAttr; 38 import org.cojen.classfile.attribute.RuntimeInvisibleAnnotationsAttr; 39 import org.cojen.classfile.attribute.RuntimeVisibleAnnotationsAttr; 40 import org.cojen.classfile.attribute.SignatureAttr; 41 import org.cojen.classfile.attribute.SourceFileAttr; 42 import org.cojen.classfile.attribute.SyntheticAttr; 43 import org.cojen.classfile.constant.ConstantClassInfo; 44 45 55 public class ClassFile { 56 private static final int MAGIC = 0xCAFEBABE; 57 58 69 public static ClassFile readFrom(InputStream in) throws IOException { 70 return readFrom(in, null, null); 71 } 72 73 84 public static ClassFile readFrom(DataInput din) throws IOException { 85 return readFrom(din, null, null); 86 } 87 88 104 public static ClassFile readFrom(InputStream in, 105 ClassFileDataLoader loader, 106 AttributeFactory attrFactory) 107 throws IOException 108 { 109 if (!(in instanceof DataInput )) { 110 in = new DataInputStream (in); 111 } 112 return readFrom((DataInput )in, loader, attrFactory); 113 } 114 115 131 public static ClassFile readFrom(DataInput din, 132 ClassFileDataLoader loader, 133 AttributeFactory attrFactory) 134 throws IOException 135 { 136 return readFrom(din, loader, attrFactory, new HashMap (11), null); 137 } 138 139 143 private static ClassFile readFrom(DataInput din, 144 ClassFileDataLoader loader, 145 AttributeFactory attrFactory, 146 Map loadedClassFiles, 147 ClassFile outerClass) 148 throws IOException 149 { 150 int magic = din.readInt(); 151 if (magic != MAGIC) { 152 throw new IOException ("Incorrect magic number: 0x" + 153 Integer.toHexString(magic)); 154 } 155 156 short minor = din.readShort(); 157 short major = din.readShort(); 158 159 ConstantPool cp = ConstantPool.readFrom(din); 160 Modifiers modifiers = Modifiers.getInstance(din.readUnsignedShort()) 161 .toSynchronized(false); 162 163 int index = din.readUnsignedShort(); 164 ConstantClassInfo thisClass = (ConstantClassInfo)cp.getConstant(index); 165 166 index = din.readUnsignedShort(); 167 ConstantClassInfo superClass = null; 168 if (index > 0) { 169 superClass = (ConstantClassInfo)cp.getConstant(index); 170 } 171 172 ClassFile cf = new ClassFile(cp, modifiers, thisClass, superClass, outerClass); 173 cf.setVersion(major, minor); 174 loadedClassFiles.put(cf.getClassName(), cf); 175 176 int size = din.readUnsignedShort(); 178 for (int i=0; i<size; i++) { 179 index = din.readUnsignedShort(); 180 ConstantClassInfo info = (ConstantClassInfo)cp.getConstant(index); 181 cf.addInterface(info.getType().getRootName()); 182 } 183 184 size = din.readUnsignedShort(); 186 for (int i=0; i<size; i++) { 187 cf.mFields.add(FieldInfo.readFrom(cf, din, attrFactory)); 188 } 189 190 size = din.readUnsignedShort(); 192 for (int i=0; i<size; i++) { 193 cf.mMethods.add(MethodInfo.readFrom(cf, din, attrFactory)); 194 } 195 196 size = din.readUnsignedShort(); 198 for (int i=0; i<size; i++) { 199 Attribute attr = Attribute.readFrom(cp, din, attrFactory); 200 cf.addAttribute(attr); 201 if (attr instanceof InnerClassesAttr) { 202 cf.mInnerClassesAttr = (InnerClassesAttr)attr; 203 } 204 } 205 206 if (cf.mInnerClassesAttr != null && loader != null) { 208 InnerClassesAttr.Info[] infos = cf.mInnerClassesAttr.getInnerClassesInfo(); 209 for (int i=0; i<infos.length; i++) { 210 InnerClassesAttr.Info info = infos[i]; 211 212 if (thisClass.equals(info.getInnerClass())) { 213 if (info.getInnerClassName() != null) { 215 cf.mInnerClassName = info.getInnerClassName().getValue(); 216 } 217 ConstantClassInfo outer = info.getOuterClass(); 218 if (cf.mOuterClass == null && outer != null) { 219 cf.mOuterClass = readOuterClass 220 (outer, loader, attrFactory, loadedClassFiles); 221 } 222 Modifiers innerFlags = info.getModifiers(); 223 cf.mModifiers = cf.mModifiers 224 .toStatic(innerFlags.isStatic()) 225 .toPrivate(innerFlags.isPrivate()) 226 .toProtected(innerFlags.isProtected()) 227 .toPublic(innerFlags.isPublic()); 228 } else if (info.getOuterClass() == null || 229 thisClass.equals(info.getOuterClass())) { 230 231 ConstantClassInfo inner = info.getInnerClass(); 233 if (inner != null) { 234 ClassFile innerClass = readInnerClass 235 (inner, loader, attrFactory, loadedClassFiles, cf); 236 237 if (innerClass != null) { 238 if (innerClass.getInnerClassName() != null) { 239 innerClass.mInnerClassName = info.getInnerClassName().getValue(); 240 } 241 if (cf.mInnerClasses == null) { 242 cf.mInnerClasses = new ArrayList (); 243 } 244 cf.mInnerClasses.add(innerClass); 245 } 246 } 247 } 248 } 249 } 250 251 return cf; 252 } 253 254 private static ClassFile readOuterClass(ConstantClassInfo outer, 255 ClassFileDataLoader loader, 256 AttributeFactory attrFactory, 257 Map loadedClassFiles) 258 throws IOException 259 { 260 String name = outer.getType().getRootName(); 261 262 ClassFile outerClass = (ClassFile)loadedClassFiles.get(name); 263 if (outerClass != null) { 264 return outerClass; 265 } 266 267 InputStream in = loader.getClassData(name); 268 if (in == null) { 269 return null; 270 } 271 272 if (!(in instanceof DataInput )) { 273 in = new DataInputStream (in); 274 } 275 276 return readFrom((DataInput )in, loader, attrFactory, loadedClassFiles, null); 277 } 278 279 private static ClassFile readInnerClass(ConstantClassInfo inner, 280 ClassFileDataLoader loader, 281 AttributeFactory attrFactory, 282 Map loadedClassFiles, 283 ClassFile outerClass) 284 throws IOException 285 { 286 String name = inner.getType().getRootName(); 287 288 for (ClassFile outer = outerClass; outer != null; outer = outer.getOuterClass()) { 290 if (name.equals(outer.getClassName())) { 291 return null; 293 } 294 } 295 296 ClassFile innerClass = (ClassFile)loadedClassFiles.get(name); 298 if (innerClass != null) { 299 return innerClass; 300 } 301 302 InputStream in = loader.getClassData(name); 303 if (in == null) { 304 return null; 305 } 306 307 if (!(in instanceof DataInput )) { 308 in = new DataInputStream (in); 309 } 310 311 return readFrom((DataInput )in, loader, attrFactory, loadedClassFiles, outerClass); 312 } 313 314 private int mVersion; 315 private String mTarget; 316 { 317 setTarget(null); 318 } 319 320 private final String mClassName; 321 private final String mSuperClassName; 322 private String mInnerClassName; 323 private TypeDesc mType; 324 325 private ConstantPool mCp; 326 327 private Modifiers mModifiers; 328 329 private ConstantClassInfo mThisClass; 330 private ConstantClassInfo mSuperClass; 331 332 private List mInterfaces = new ArrayList (2); 334 private Set mInterfaceSet = new HashSet (7); 335 336 private List mFields = new ArrayList (); 338 private List mMethods = new ArrayList (); 339 private List mAttributes = new ArrayList (); 340 341 private SourceFileAttr mSource; 342 343 private List mInnerClasses; 344 private int mAnonymousInnerClassCount = 0; 345 private InnerClassesAttr mInnerClassesAttr; 346 347 private ClassFile mOuterClass; 349 350 360 public ClassFile(String className) { 361 this(className, (String )null); 362 } 363 364 373 public ClassFile(String className, Class superClass) { 374 this(className, superClass.isInterface() ? null : superClass.getName()); 375 if (superClass.isInterface()) { 376 addInterface(superClass); 377 } 378 } 379 380 389 public ClassFile(String className, String superClassName) { 390 if (superClassName == null) { 391 if (!className.equals(Object .class.getName())) { 392 superClassName = Object .class.getName(); 393 } 394 } 395 396 mCp = new ConstantPool(); 397 398 mModifiers = Modifiers.PUBLIC; 400 401 mThisClass = mCp.addConstantClass(className); 402 mSuperClass = mCp.addConstantClass(superClassName); 403 404 mClassName = className; 405 mSuperClassName = superClassName; 406 } 407 408 411 private ClassFile(ConstantPool cp, Modifiers modifiers, 412 ConstantClassInfo thisClass, 413 ConstantClassInfo superClass, 414 ClassFile outerClass) { 415 416 mCp = cp; 417 418 mModifiers = modifiers; 419 420 mThisClass = thisClass; 421 mSuperClass = superClass; 422 423 mClassName = thisClass.getType().getRootName(); 424 if (superClass == null) { 425 mSuperClassName = null; 426 } else { 427 mSuperClassName = superClass.getType().getRootName(); 428 } 429 430 mOuterClass = outerClass; 431 } 432 433 public String getClassName() { 434 return mClassName; 435 } 436 437 public String getSuperClassName() { 438 return mSuperClassName; 439 } 440 441 444 public TypeDesc getType() { 445 if (mType == null) { 446 mType = TypeDesc.forClass(mClassName); 447 } 448 return mType; 449 } 450 451 public Modifiers getModifiers() { 452 return mModifiers; 453 } 454 455 458 public String [] getInterfaces() { 459 int size = mInterfaces.size(); 460 String [] names = new String [size]; 461 462 for (int i=0; i<size; i++) { 463 names[i] = ((ConstantClassInfo)mInterfaces.get(i)) 464 .getType().getRootName(); 465 } 466 467 return names; 468 } 469 470 473 public FieldInfo[] getFields() { 474 FieldInfo[] fields = new FieldInfo[mFields.size()]; 475 return (FieldInfo[])mFields.toArray(fields); 476 } 477 478 482 public MethodInfo[] getMethods() { 483 int size = mMethods.size(); 484 List methodsOnly = new ArrayList (size); 485 486 for (int i=0; i<size; i++) { 487 MethodInfo method = (MethodInfo)mMethods.get(i); 488 String name = method.getName(); 489 if (!"<init>".equals(name) && !"<clinit>".equals(name)) { 490 methodsOnly.add(method); 491 } 492 } 493 494 MethodInfo[] methodsArray = new MethodInfo[methodsOnly.size()]; 495 return (MethodInfo[])methodsOnly.toArray(methodsArray); 496 } 497 498 501 public MethodInfo[] getConstructors() { 502 int size = mMethods.size(); 503 List ctorsOnly = new ArrayList (size); 504 505 for (int i=0; i<size; i++) { 506 MethodInfo method = (MethodInfo)mMethods.get(i); 507 if ("<init>".equals(method.getName())) { 508 ctorsOnly.add(method); 509 } 510 } 511 512 MethodInfo[] ctorsArray = new MethodInfo[ctorsOnly.size()]; 513 return (MethodInfo[])ctorsOnly.toArray(ctorsArray); 514 } 515 516 520 public MethodInfo getInitializer() { 521 int size = mMethods.size(); 522 523 for (int i=0; i<size; i++) { 524 MethodInfo method = (MethodInfo)mMethods.get(i); 525 if ("<clinit>".equals(method.getName())) { 526 return method; 527 } 528 } 529 530 return null; 531 } 532 533 537 public ClassFile[] getInnerClasses() { 538 if (mInnerClasses == null) { 539 return new ClassFile[0]; 540 } 541 542 ClassFile[] innerClasses = new ClassFile[mInnerClasses.size()]; 543 return (ClassFile[])mInnerClasses.toArray(innerClasses); 544 } 545 546 549 public boolean isInnerClass() { 550 return mOuterClass != null; 551 } 552 553 557 public String getInnerClassName() { 558 return mInnerClassName; 559 } 560 561 566 public ClassFile getOuterClass() { 567 return mOuterClass; 568 } 569 570 575 public int getClassDepth() { 576 int depth = 0; 577 578 ClassFile outer = mOuterClass; 579 while (outer != null) { 580 depth++; 581 outer = outer.mOuterClass; 582 } 583 584 return depth; 585 } 586 587 590 public String getSourceFile() { 591 if (mSource == null) { 592 return null; 593 } else { 594 return mSource.getFileName().getValue(); 595 } 596 } 597 598 public boolean isSynthetic() { 599 for (int i = mAttributes.size(); --i >= 0; ) { 600 Object obj = mAttributes.get(i); 601 if (obj instanceof SyntheticAttr) { 602 return true; 603 } 604 } 605 return false; 606 } 607 608 public boolean isDeprecated() { 609 for (int i = mAttributes.size(); --i >= 0; ) { 610 Object obj = mAttributes.get(i); 611 if (obj instanceof DeprecatedAttr) { 612 return true; 613 } 614 } 615 return false; 616 } 617 618 622 public Annotation[] getRuntimeInvisibleAnnotations() { 623 for (int i = mAttributes.size(); --i >= 0; ) { 624 Object obj = mAttributes.get(i); 625 if (obj instanceof RuntimeInvisibleAnnotationsAttr) { 626 return ((AnnotationsAttr) obj).getAnnotations(); 627 } 628 } 629 return new Annotation[0]; 630 } 631 632 636 public Annotation[] getRuntimeVisibleAnnotations() { 637 for (int i = mAttributes.size(); --i >= 0; ) { 638 Object obj = mAttributes.get(i); 639 if (obj instanceof RuntimeVisibleAnnotationsAttr) { 640 return ((AnnotationsAttr) obj).getAnnotations(); 641 } 642 } 643 return new Annotation[0]; 644 } 645 646 649 public Annotation addRuntimeInvisibleAnnotation(TypeDesc type) { 650 AnnotationsAttr attr = null; 651 for (int i = mAttributes.size(); --i >= 0; ) { 652 Object obj = mAttributes.get(i); 653 if (obj instanceof RuntimeInvisibleAnnotationsAttr) { 654 attr = (AnnotationsAttr) obj; 655 } 656 } 657 if (attr == null) { 658 attr = new RuntimeInvisibleAnnotationsAttr(mCp); 659 addAttribute(attr); 660 } 661 Annotation ann = new Annotation(mCp); 662 ann.setType(type); 663 attr.addAnnotation(ann); 664 return ann; 665 } 666 667 670 public Annotation addRuntimeVisibleAnnotation(TypeDesc type) { 671 AnnotationsAttr attr = null; 672 for (int i = mAttributes.size(); --i >= 0; ) { 673 Object obj = mAttributes.get(i); 674 if (obj instanceof RuntimeVisibleAnnotationsAttr) { 675 attr = (AnnotationsAttr) obj; 676 } 677 } 678 if (attr == null) { 679 attr = new RuntimeVisibleAnnotationsAttr(mCp); 680 addAttribute(attr); 681 } 682 Annotation ann = new Annotation(mCp); 683 ann.setType(type); 684 attr.addAnnotation(ann); 685 return ann; 686 } 687 688 692 public SignatureAttr getSignatureAttr() { 694 for (int i = mAttributes.size(); --i >= 0; ) { 695 Object obj = mAttributes.get(i); 696 if (obj instanceof SignatureAttr) { 697 return (SignatureAttr) obj; 698 } 699 } 700 return null; 701 } 702 703 708 public ConstantPool getConstantPool() { 709 return mCp; 710 } 711 712 public void setModifiers(Modifiers modifiers) { 713 mModifiers = modifiers; 714 } 715 716 721 public void addInterface(String interfaceName) { 722 if (!mInterfaceSet.contains(interfaceName)) { 723 mInterfaces.add(mCp.addConstantClass(interfaceName)); 724 mInterfaceSet.add(interfaceName); 725 } 726 } 727 728 731 public void addInterface(Class i) { 732 addInterface(i.getName()); 733 } 734 735 738 public FieldInfo addField(Modifiers modifiers, 739 String fieldName, 740 TypeDesc type) { 741 FieldInfo fi = new FieldInfo(this, modifiers, fieldName, type); 742 mFields.add(fi); 743 return fi; 744 } 745 746 752 public MethodInfo addMethod(Modifiers modifiers, 753 String methodName, 754 TypeDesc ret, 755 TypeDesc[] params) { 756 MethodDesc md = MethodDesc.forArguments(ret, params); 757 return addMethod(modifiers, methodName, md); 758 } 759 760 763 public MethodInfo addMethod(Modifiers modifiers, 764 String methodName, 765 MethodDesc md) { 766 MethodInfo mi = new MethodInfo(this, modifiers, methodName, md); 767 mMethods.add(mi); 768 return mi; 769 } 770 771 775 public MethodInfo addMethod(Method method) { 776 Modifiers modifiers = Modifiers.getInstance(method.getModifiers()).toAbstract(false); 777 MethodInfo mi = addMethod(modifiers, method.getName(), MethodDesc.forMethod(method)); 778 779 Class [] exceptions = method.getExceptionTypes(); 781 for (int i=0; i<exceptions.length; i++) { 782 mi.addException(TypeDesc.forClass(exceptions[i])); 783 } 784 785 return mi; 786 } 787 788 794 public MethodInfo addMethod(String declaration) { 795 MethodDeclarationParser p = new MethodDeclarationParser(declaration); 796 return addMethod(p.getModifiers(), p.getMethodName(), 797 p.getReturnType(), p.getParameters()); 798 } 799 800 805 public MethodInfo addConstructor(Modifiers modifiers, 806 TypeDesc[] params) { 807 MethodDesc md = MethodDesc.forArguments(null, params); 808 MethodInfo mi = new MethodInfo(this, modifiers, "<init>", md); 809 mMethods.add(mi); 810 return mi; 811 } 812 813 816 public MethodInfo addDefaultConstructor() { 817 MethodInfo mi = addConstructor(Modifiers.PUBLIC, null); 818 CodeBuilder builder = new CodeBuilder(mi); 819 builder.loadThis(); 820 builder.invokeSuperConstructor(null); 821 builder.returnVoid(); 822 return mi; 823 } 824 825 828 public MethodInfo addInitializer() { 829 MethodDesc md = MethodDesc.forArguments(null, null); 830 Modifiers af = Modifiers.NONE.toStatic(true); 831 MethodInfo mi = new MethodInfo(this, af, "<clinit>", md); 832 mMethods.add(mi); 833 return mi; 834 } 835 836 843 public ClassFile addInnerClass(String fullInnerClassName, String innerClassName) { 844 return addInnerClass(fullInnerClassName, innerClassName, (String )null); 845 } 846 847 855 public ClassFile addInnerClass(String fullInnerClassName, String innerClassName, 856 Class superClass) { 857 return addInnerClass(innerClassName, superClass.getName()); 858 } 859 860 868 public ClassFile addInnerClass(String fullInnerClassName, String innerClassName, 869 String superClassName) { 870 if (fullInnerClassName == null) { 871 if (innerClassName == null) { 872 fullInnerClassName = mClassName + '$' + (++mAnonymousInnerClassCount); 873 } else { 874 fullInnerClassName = mClassName + '$' + innerClassName; 875 } 876 } 877 878 ClassFile inner = new ClassFile(fullInnerClassName, superClassName); 879 Modifiers modifiers = inner.getModifiers().toPrivate(true).toStatic(true); 880 inner.setModifiers(modifiers); 881 inner.mInnerClassName = innerClassName; 882 inner.mOuterClass = this; 883 884 if (mInnerClasses == null) { 885 mInnerClasses = new ArrayList (); 886 } 887 888 mInnerClasses.add(inner); 889 890 if (mInnerClassesAttr == null) { 892 addAttribute(new InnerClassesAttr(mCp)); 893 } 894 895 898 mInnerClassesAttr.addInnerClass(fullInnerClassName, mClassName, 899 innerClassName, modifiers); 900 901 inner.addAttribute(new InnerClassesAttr(inner.getConstantPool())); 903 inner.mInnerClassesAttr.addInnerClass(fullInnerClassName, mClassName, 904 innerClassName, modifiers); 905 906 return inner; 907 } 908 909 914 public void setSourceFile(String fileName) { 915 addAttribute(new SourceFileAttr(mCp, fileName)); 916 } 917 918 921 public void markSynthetic() { 922 addAttribute(new SyntheticAttr(mCp)); 923 } 924 925 928 public void markDeprecated() { 929 addAttribute(new DeprecatedAttr(mCp)); 930 } 931 932 935 public void addAttribute(Attribute attr) { 936 if (attr instanceof SourceFileAttr) { 937 if (mSource != null) { 938 mAttributes.remove(mSource); 939 } 940 mSource = (SourceFileAttr)attr; 941 } else if (attr instanceof InnerClassesAttr) { 942 if (mInnerClassesAttr != null) { 943 mAttributes.remove(mInnerClassesAttr); 944 } 945 mInnerClassesAttr = (InnerClassesAttr)attr; 946 } 947 948 mAttributes.add(attr); 949 } 950 951 public Attribute[] getAttributes() { 952 Attribute[] attrs = new Attribute[mAttributes.size()]; 953 return (Attribute[])mAttributes.toArray(attrs); 954 } 955 956 964 public void setTarget(String target) throws IllegalArgumentException { 965 int major, minor; 966 967 if (target == null || "1.0".equals(target) || "1.1".equals(target)) { 968 major = 45; minor = 3; 969 if (target == null) { 970 target = "1.0"; 971 } 972 } else if ("1.2".equals(target)) { 973 major = 46; minor = 0; 974 } else if ("1.3".equals(target)) { 975 major = 47; minor = 0; 976 } else if ("1.4".equals(target)) { 977 major = 48; minor = 0; 978 } else if ("1.5".equals(target)) { 979 major = 49; minor = 0; 980 } else if ("1.6".equals(target)) { 981 major = 50; minor = 0; 982 } else { 983 throw new IllegalArgumentException 984 ("Unsupported target version: " + target); 985 } 986 987 mVersion = (minor << 16) | (major & 0xffff); 988 mTarget = target.intern(); 989 } 990 991 994 public String getTarget() { 995 return mTarget; 996 } 997 998 1002 public void setVersion(int major, int minor) { 1003 if (major > 65535 || minor > 65535) { 1004 throw new IllegalArgumentException 1005 ("Version number element cannot exceed 65535"); 1006 } 1007 1008 mVersion = (minor << 16) | (major & 0xffff); 1009 1010 String target; 1011 switch (major) { 1012 default: 1013 target = null; 1014 break; 1015 case 45: 1016 target = minor == 3 ? "1.0" : null; 1017 break; 1018 case 46: 1019 target = minor == 0 ? "1.2" : null; 1020 break; 1021 case 47: 1022 target = minor == 0 ? "1.3" : null; 1023 break; 1024 case 48: 1025 target = minor == 0 ? "1.4" : null; 1026 break; 1027 case 49: 1028 target = minor == 0 ? "1.5" : null; 1029 break; 1030 case 50: 1031 target = minor == 0 ? "1.6" : null; 1032 break; 1033 } 1034 1035 mTarget = target; 1036 } 1037 1038 1041 public int getMajorVersion() { 1042 return mVersion & 0xffff; 1043 } 1044 1045 1048 public int getMinorVersion() { 1049 return (mVersion >> 16) & 0xffff; 1050 } 1051 1052 1055 public void writeTo(OutputStream out) throws IOException { 1056 if (!(out instanceof DataOutput )) { 1057 out = new DataOutputStream (out); 1058 } 1059 writeTo((DataOutput )out); 1060 } 1061 1062 1065 public void writeTo(DataOutput dout) throws IOException { 1066 dout.writeInt(MAGIC); 1067 dout.writeInt(mVersion); 1068 1069 mCp.writeTo(dout); 1070 1071 { 1072 int flags = mModifiers.getBitmask(); 1073 if (!mModifiers.isInterface()) { 1074 flags |= Modifier.SYNCHRONIZED; 1076 } 1077 dout.writeShort(flags); 1078 } 1079 1080 dout.writeShort(mThisClass.getIndex()); 1081 if (mSuperClass != null) { 1082 dout.writeShort(mSuperClass.getIndex()); 1083 } else { 1084 dout.writeShort(0); 1085 } 1086 1087 int size = mInterfaces.size(); 1088 if (size > 65535) { 1089 throw new IllegalStateException 1090 ("Interfaces count cannot exceed 65535: " + size); 1091 } 1092 dout.writeShort(size); 1093 for (int i=0; i<size; i++) { 1094 int index = ((ConstantInfo)mInterfaces.get(i)).getIndex(); 1095 dout.writeShort(index); 1096 } 1097 1098 size = mFields.size(); 1099 if (size > 65535) { 1100 throw new IllegalStateException 1101 ("Field count cannot exceed 65535: " + size); 1102 } 1103 dout.writeShort(size); 1104 for (int i=0; i<size; i++) { 1105 FieldInfo field = (FieldInfo)mFields.get(i); 1106 field.writeTo(dout); 1107 } 1108 1109 size = mMethods.size(); 1110 if (size > 65535) { 1111 throw new IllegalStateException 1112 ("Method count cannot exceed 65535: " + size); 1113 } 1114 dout.writeShort(size); 1115 for (int i=0; i<size; i++) { 1116 MethodInfo method = (MethodInfo)mMethods.get(i); 1117 method.writeTo(dout); 1118 } 1119 1120 size = mAttributes.size(); 1121 if (size > 65535) { 1122 throw new IllegalStateException 1123 ("Attribute count cannot exceed 65535: " + size); 1124 } 1125 dout.writeShort(size); 1126 for (int i=0; i<size; i++) { 1127 Attribute attr = (Attribute)mAttributes.get(i); 1128 attr.writeTo(dout); 1129 } 1130 } 1131 1132 public String toString() { 1133 StringBuffer buf = new StringBuffer (); 1134 String modStr = mModifiers.toString(); 1135 if (modStr.length() > 0) { 1136 buf.append(modStr); 1137 buf.append(' '); 1138 } 1139 if (getModifiers().isInterface()) { 1140 buf.append("interface"); 1141 } else { 1142 buf.append("class"); 1143 } 1144 buf.append(' '); 1145 buf.append(getClassName()); 1146 1147 return buf.toString(); 1148 } 1149} 1150 | Popular Tags |