1 4 package gnu.bytecode; 5 import java.io.*; 6 import java.util.Vector ; 7 8 public class ClassType extends ObjectType 9 implements AttrContainer, Externalizable 10 { 11 int classfileFormatVersion = 45 * 0x10000 + 3; 13 14 public short getClassfileMajorVersion () 15 { 16 return (short) (classfileFormatVersion >> 16); 17 } 18 public short getClassfileMinorVersion () 19 { 20 return (short) (classfileFormatVersion & 0xFFFF); 21 } 22 public void setClassfileVersion (int major, int minor) 23 { 24 classfileFormatVersion = (major & 0xFFFF) * 0x10000 + (minor * 0xFFFF); 25 } 26 public void setClassfileVersionJava5 () 27 { 28 setClassfileVersion(49, 0); 29 } 30 31 36 public static ClassType make(String name) 37 { 38 return (ClassType) Type.getType(name); 39 } 40 41 public static ClassType make (String name, ClassType superClass) 42 { 43 ClassType type = make(name); 44 if (type.superClass == null) 45 type.setSuper(superClass); 46 return type; 47 } 48 49 int thisClassIndex; 50 51 54 ClassType superClass; 55 56 int superClassIndex = -1; 57 58 ClassType[] interfaces; 59 int[] interfaceIndexes; 60 public int access_flags; 61 62 Attribute attributes; 63 public final Attribute getAttributes () { return attributes; } 64 public final void setAttributes (Attribute attributes) 65 { this.attributes = attributes; } 66 67 public static final ClassType[] noClasses = { }; 68 69 boolean emitDebugInfo = true; 70 71 ConstantPool constants; 72 73 public final ConstantPool getConstants () { return constants; } 74 75 public final CpoolEntry getConstant(int i) 76 { 77 if (constants == null || constants.pool == null 78 || i > constants.count) 79 return null; 80 return constants.pool[i]; 81 } 82 83 84 public final int getModifiers() 85 { 86 if (access_flags == 0 87 && (flags & EXISTING_CLASS) != 0 && getReflectClass() != null) 88 access_flags = reflectClass.getModifiers(); 89 return access_flags; 90 } 91 92 93 public final void setModifiers(int flags) { access_flags = flags; } 94 95 public final boolean hasOuterLink () 96 { 97 getFields(); 98 return (flags & HAS_OUTER_LINK) != 0; 99 } 100 101 public ClassType getOuterLinkType () 102 { 103 return ! hasOuterLink() ? null 104 : (ClassType) getDeclaredField("this$0").getType(); 105 } 106 107 113 public final Field setOuterLink (ClassType outer) 114 { 115 if ((flags & EXISTING_CLASS) != 0) 116 throw new Error ("setOuterLink called for existing class "+getName()); 117 Field field = getDeclaredField("this$0"); 118 if (field == null) 119 { 120 field = addField("this$0", outer); 121 flags |= HAS_OUTER_LINK; 122 for (Method meth = methods; meth != null; meth = meth.getNext()) 123 { 124 if ("<init>".equals(meth.getName())) 125 { 126 if (meth.code != null) 127 throw new Error ("setOuterLink called when "+meth+" has code"); 128 Type[] arg_types = meth.arg_types; 129 Type[] new_types = new Type[arg_types.length+1]; 130 System.arraycopy(arg_types, 0, new_types, 1, arg_types.length); 131 new_types[0] = outer; 132 meth.arg_types = new_types; 133 meth.signature = null; 134 } 135 } 136 } 137 else if (! outer.equals(field.getType())) 138 throw new Error ("inconsistent setOuterLink call for "+getName()); 139 return field; 140 } 141 142 148 public boolean isAccessible (ClassType declaring, int modifiers) 149 { 150 int cmods = declaring.getModifiers(); 151 if ((modifiers & Access.PUBLIC) != 0 && (cmods & Access.PUBLIC) != 0) 152 return true; 153 String callerName = getName(); 154 String className = declaring.getName(); 155 if (callerName.equals(className)) 156 return true; 157 if ((modifiers & Access.PRIVATE) != 0) 158 return false; 159 int dot = callerName.lastIndexOf('.'); 160 String callerPackage = dot >= 0 ? callerName.substring(0, dot) : ""; 161 dot = className.lastIndexOf('.'); 162 String classPackage = dot >= 0 ? className.substring(0, dot) : ""; 163 if (callerPackage.equals(classPackage)) 164 return true; 165 if ((modifiers & Access.PROTECTED) != 0 166 && this.isSubclass(declaring)) 167 return true; 168 return false; 169 } 170 171 174 public void setName (String name) 175 { 176 this_name = name; 177 setSignature("L"+name.replace('.', '/')+";"); 178 } 179 180 SourceDebugExtAttr sourceDbgExt; 181 182 185 public void setStratum (String stratum) 186 { 187 if (sourceDbgExt == null) 188 sourceDbgExt = new SourceDebugExtAttr(this); 189 sourceDbgExt.addStratum(stratum); 190 } 191 192 193 public void setSourceFile (String name) 194 { 195 if (sourceDbgExt != null) 196 { 197 sourceDbgExt.addFile(name); 198 if (sourceDbgExt.fileCount > 1) 199 return; 200 } 201 202 name = SourceFileAttr.fixSourceFile(name); 203 int slash = name.lastIndexOf('/'); 204 if (slash >= 0) 205 name = name.substring(slash+1); 206 SourceFileAttr.setSourceFile(this, name); 207 } 208 209 213 public void setSuper (String name) 214 { 215 setSuper(name == null ? Type.pointer_type : ClassType.make(name)); 216 } 217 218 public void setSuper (ClassType superClass) 219 { 220 this.superClass = superClass; 221 } 222 223 public ClassType getSuperclass () 224 { 225 if (superClass == null 226 && ! isInterface() 227 && ! ("java.lang.Object".equals(getName())) 228 && (flags & EXISTING_CLASS) != 0 && getReflectClass() != null) 229 { 230 superClass = (ClassType) make(reflectClass.getSuperclass()); 231 } 232 return superClass; 233 } 234 235 public String getPackageName() 236 { 237 String name = getName(); 238 int index = name.lastIndexOf('.'); 239 return index < 0 ? "" : name.substring(0, index); 240 } 241 242 246 public synchronized ClassType[] getInterfaces() 247 { 248 if (interfaces == null 249 && (flags & EXISTING_CLASS) != 0 && getReflectClass() != null) 250 { 251 Class [] reflectInterfaces = reflectClass.getInterfaces(); 252 int numInterfaces = reflectInterfaces.length; 253 interfaces 254 = numInterfaces == 0 ? noClasses : new ClassType[numInterfaces]; 255 256 for (int i = 0; i < numInterfaces; i++) 257 interfaces[i] = (ClassType) Type.make(reflectInterfaces[i]); 258 } 259 return interfaces; 260 } 261 262 public void setInterfaces (ClassType[] interfaces) 263 { this.interfaces = interfaces; } 264 265 266 public void addInterface (ClassType newInterface) 267 { 268 int oldCount; 269 if (interfaces == null || interfaces.length == 0) 270 { 271 oldCount = 0; 272 interfaces = new ClassType[1]; 273 } 274 else 275 { 276 oldCount = interfaces.length; 277 for (int i = oldCount; --i >= 0; ) 278 if (interfaces[i] == newInterface) 279 return; 280 ClassType[] newInterfaces = new ClassType[oldCount+1]; 281 System.arraycopy(interfaces, 0, newInterfaces, 0, oldCount); 282 interfaces = newInterfaces; 283 } 284 interfaces[oldCount] = newInterface; 285 } 286 287 public final boolean isInterface() 288 { return (getModifiers() & Access.INTERFACE) != 0; } 289 290 public final void setInterface(boolean val) 291 { 292 if (val) access_flags |= Access.INTERFACE|Access.ABSTRACT; 293 else access_flags &= ~Access.INTERFACE|Access.ABSTRACT; 294 } 295 296 public ClassType () { } 297 298 public ClassType (String class_name) 299 { 300 super(); 301 setName(class_name); 302 } 303 304 Field fields; 305 int fields_count; 306 Field last_field; 307 308 int ConstantValue_name_index; 309 310 311 int Code_name_index; 312 313 314 int LocalVariableTable_name_index; 315 316 317 int LineNumberTable_name_index; 318 319 320 public final synchronized Field getFields() 321 { 322 if ((flags & (ADD_FIELDS_DONE|EXISTING_CLASS)) == EXISTING_CLASS) 323 addFields(); 324 return fields; 325 } 326 327 public final int getFieldCount() 328 { 329 return fields_count; 330 } 331 332 335 public Field getDeclaredField(String name) 336 { 337 for (Field field = getFields(); field != null; field = field.next) 338 { 339 if (name.equals(field.name)) 340 return field; 341 } 342 return null; 343 } 344 345 351 public Field getField(String name, int mask) 352 { 353 ClassType cl = this; 354 for (;;) 355 { 356 Field field = cl.getDeclaredField(name); 357 if (field != null 358 && (mask == -1 || (field.getModifiers() & mask) != 0)) 359 return field; 360 ClassType[] interfaces = cl.getInterfaces(); 361 if (interfaces != null) 362 { 363 for (int i = 0; i < interfaces.length; i++) 364 { 365 field = interfaces[i].getField(name, mask); 366 if (field != null) 367 return field; 368 } 369 } 370 cl = cl.getSuperclass(); 371 if (cl == null) 372 return null; 373 } 374 } 375 376 379 public Field getField(String name) 380 { 381 return getField(name, Access.PUBLIC); 382 } 383 384 387 public Field addField () { return new Field (this); } 388 389 393 public Field addField (String name) { 394 Field field = new Field (this); 395 field.setName(name); 396 return field; 397 } 398 399 public final Field addField (String name, Type type) { 400 Field field = new Field (this); 401 field.setName(name); 402 field.setType(type); 403 return field; 404 } 405 406 public final Field addField (String name, Type type, int flags) 407 { 408 Field field = addField (name, type); 409 field.flags = flags; 410 return field; 411 } 412 413 417 public void addFields() 418 { 419 Class clas = getReflectClass(); 420 java.lang.reflect.Field [] fields; 421 try 422 { 423 fields = clas.getDeclaredFields(); 424 } 425 catch (SecurityException ex) 426 { 427 fields = clas.getFields(); 428 } 429 int count = fields.length; 430 for (int i = 0; i < count; i++) 431 { 432 java.lang.reflect.Field field = fields[i]; 433 if ("this$0".equals(field.getName())) 434 flags |= HAS_OUTER_LINK; 435 addField(field.getName(), Type.make(field.getType()), 436 field.getModifiers()); 437 } 438 flags |= ADD_FIELDS_DONE; 439 } 440 441 Method methods; 442 int methods_count; 443 Method last_method; 444 public Method constructor; 445 446 447 public final Method getMethods() 448 { 449 return methods; 450 } 451 452 public final int getMethodCount() { 453 return methods_count; 454 } 455 456 Method addMethod () { 457 return new Method (this, 0); 458 } 459 460 public Method addMethod (String name) { 461 return addMethod(name, 0); 462 } 463 464 public Method addMethod (String name, int flags) { 465 Method method = new Method (this, flags); 466 method.setName(name); 467 return method; 468 } 469 470 public Method addMethod (String name, 472 Type[] arg_types, Type return_type, 473 int flags) { 474 return addMethod(name, flags, arg_types, return_type); 475 } 476 477 481 public Method addMethod (String name, int flags, 482 Type[] arg_types, Type return_type) 483 { 484 Method method = getDeclaredMethod(name, arg_types); 485 if (method != null 486 && return_type.equals(method.getReturnType()) 487 && (flags & method.access_flags) == flags) 488 return method; 489 method = addMethod(name, flags); 490 method.arg_types = arg_types; 491 method.return_type = return_type; 492 return method; 493 } 494 495 public Method addMethod (String name, String signature, int flags) 496 { 497 Method meth = addMethod(name, flags); 498 meth.setSignature(signature); 499 return meth; 500 } 501 502 505 public Method getMethod (java.lang.reflect.Method method) 506 { 507 String name = method.getName(); 508 Class [] parameterClasses = method.getParameterTypes(); 509 Type[] parameterTypes = new Type[parameterClasses.length]; 510 for (int i = parameterClasses.length; --i >= 0; ) 511 parameterTypes[i] = Type.make(parameterClasses[i]); 512 return addMethod(name, method.getModifiers(), 513 parameterTypes, Type.make(method.getReturnType())); 514 } 515 516 public final synchronized Method getDeclaredMethods() 517 { 518 if ((flags & (ADD_METHODS_DONE|EXISTING_CLASS)) == EXISTING_CLASS) 519 addMethods(getReflectClass()); 520 return methods; 521 } 522 523 530 public final int countMethods (Filter filter, int searchSupers) 531 { 532 return getMethods(filter, searchSupers, null, 0); 533 } 534 535 public Method[] getMethods (Filter filter, boolean searchSupers) 536 { 537 return getMethods(filter, searchSupers ? 1 : 0); 538 } 539 540 547 public Method[] getMethods (Filter filter, int searchSupers) 548 { 549 int count = getMethods(filter, searchSupers, null, 0); 550 Method[] result = new Method[count]; 551 getMethods(filter, searchSupers, result, 0); 552 return result; 553 } 554 555 565 public int getMethods (Filter filter, int searchSupers, 566 Method[] result, int offset) 567 { 568 int count = 0; 569 for (ClassType ctype = this; ctype != null; 570 ctype = ctype.getSuperclass()) 571 { 572 for (Method meth = ctype.getDeclaredMethods(); 573 meth != null; meth = meth.getNext()) 574 if (filter.select(meth)) 575 { 576 if (result != null) 577 result[offset + count] = meth; 578 count++; 579 } 580 if (searchSupers == 0) 581 break; 582 583 if (searchSupers > 1) 584 { 585 ClassType[] interfaces = ctype.getInterfaces(); 586 if (interfaces != null) 587 { 588 for (int i = 0; i < interfaces.length; i++) 589 count += interfaces[i].getMethods(filter, searchSupers, 590 result, offset+count); 591 } 592 } 593 } 594 return count; 595 } 596 597 606 public int getMethods (Filter filter, int searchSupers, Vector result, 607 String context) 608 { 609 int count = 0; 610 for (ClassType ctype = this; ctype != null; 611 ctype = ctype.getSuperclass()) 612 { 613 if (context == null 614 || (ctype.getModifiers() & Access.PUBLIC) != 0 615 || context.equals(ctype.getPackageName())) 616 { 617 for (Method meth = ctype.getDeclaredMethods(); 618 meth != null; meth = meth.getNext()) 619 if (filter.select(meth)) 620 { 621 if (result != null) 622 result.addElement(meth); 623 count++; 624 } 625 } 626 if (searchSupers == 0) 627 break; 628 629 if (searchSupers > 1) 630 { 631 ClassType[] interfaces = ctype.getInterfaces(); 632 if (interfaces != null) 633 { 634 for (int i = 0; i < interfaces.length; i++) 635 count += interfaces[i].getMethods(filter, searchSupers, 636 result, context); 637 } 638 } 639 } 640 return count; 641 } 642 643 650 public Method getDeclaredMethod(String name, Type[] arg_types) 651 { 652 int needOuterLinkArg = "<init>".equals(name) && hasOuterLink() ? 1 : 0; 653 for (Method method = getDeclaredMethods(); 654 method != null; method = method.next) 655 { 656 if (! name.equals(method.getName())) 657 continue; 658 Type[] method_args = method.getParameterTypes(); 659 if (arg_types == null 660 || (arg_types == method_args && needOuterLinkArg==0)) 661 return method; 662 int i = arg_types.length; 663 if (i != method_args.length-needOuterLinkArg) 664 continue; 665 while (-- i >= 0) 666 { 667 Type meth_type = method_args[i+needOuterLinkArg]; 668 Type need_type = arg_types[i]; 669 if (meth_type == need_type || need_type == null) 670 continue; 671 String meth_sig = meth_type.getSignature(); 672 String need_sig = need_type.getSignature(); 673 if (! meth_sig.equals(need_sig)) 674 break; 675 } 676 if (i < 0) 677 return method; 678 } 679 return null; 680 } 681 682 683 public Method getDeclaredMethod(String name, int argCount) 684 { 685 Method result = null; 686 int needOuterLinkArg = "<init>".equals(name) && hasOuterLink() ? 1 : 0; 687 for (Method method = getDeclaredMethods(); 688 method != null; method = method.next) 689 { 690 if (name.equals(method.getName()) 691 && argCount + needOuterLinkArg == method.getParameterTypes().length) 692 { 693 if (result != null) 694 throw new Error ("ambiguous call to getDeclaredMethod(\"" 695 + name + "\", " + argCount+ 696 ")\n - " + result + "\n - " + method); 697 result = method; 698 } 699 } 700 return result; 701 } 702 703 public Method getMethod(String name, Type[] arg_types) 704 { 705 ClassType cl = this; 706 for (;;) 707 { 708 Method method = cl.getDeclaredMethod(name, arg_types); 709 if (method != null) 710 return method; 711 cl = cl.getSuperclass(); 712 if (cl == null) 713 break; 714 } 715 cl = this; 716 for (;;) 717 { 718 ClassType[] interfaces = cl.getInterfaces(); 719 if (interfaces != null) 720 { 721 for (int i = 0; i < interfaces.length; i++) 722 { 723 Method method 724 = interfaces[i].getDeclaredMethod(name, arg_types); 725 if (method != null) 726 return method; 727 } 728 } 729 cl = cl.getSuperclass(); 730 if (cl == null) 731 break; 732 } 733 return null; 734 } 735 736 740 public void addMethods(Class clas) 741 { 742 flags |= ADD_METHODS_DONE; 747 748 java.lang.reflect.Method [] methods; 749 try 750 { 751 methods = clas.getDeclaredMethods(); 752 } 753 catch (SecurityException ex) 754 { 755 methods = clas.getMethods(); 756 } 757 int count = methods.length; 758 for (int i = 0; i < count; i++) 759 { 760 java.lang.reflect.Method method = methods[i]; 761 if (! method.getDeclaringClass().equals(clas)) 762 continue; 763 int modifiers = method.getModifiers(); 764 Class [] paramTypes = method.getParameterTypes(); 765 int j = paramTypes.length; 766 Type[] args = new Type[j]; 767 while (--j >= 0) 768 args[j] = Type.make(paramTypes[j]); 769 Method meth = addMethod(method.getName(), modifiers); 770 meth.arg_types = args; 771 meth.return_type = Type.make(method.getReturnType()); 772 } 773 774 java.lang.reflect.Constructor [] cmethods; 775 try 776 { 777 cmethods = clas.getDeclaredConstructors(); 778 } 779 catch (SecurityException ex) 780 { 781 cmethods = clas.getConstructors(); 782 } 783 count = cmethods.length; 784 for (int i = 0; i < count; i++) 785 { 786 java.lang.reflect.Constructor method = cmethods[i]; 787 if (! method.getDeclaringClass().equals(clas)) 788 continue; 789 int modifiers = method.getModifiers(); 790 if ((modifiers & (Access.PUBLIC|Access.PROTECTED)) == 0) 791 continue; 792 Class [] paramTypes = method.getParameterTypes(); 793 int j = paramTypes.length; 794 Type[] args = new Type[j]; 795 while (--j >= 0) 796 args[j] = Type.make(paramTypes[j]); 797 Method meth = addMethod("<init>", modifiers); 798 meth.arg_types = args; 799 meth.return_type = Type.void_type; 800 } 801 } 802 803 public Method[] getMatchingMethods(String name, Type[] paramTypes, int flags) 804 { 805 int nMatches = 0; 806 java.util.Vector matches = new java.util.Vector (10); 807 for (Method method = methods; method != null; method = method.getNext()) 808 { 809 if (! name.equals(method.getName())) 810 continue; 811 if ((flags & Access.STATIC) != (method.access_flags & Access.STATIC)) 812 continue; 813 if ((flags & Access.PUBLIC) > (method.access_flags & Access.PUBLIC)) 814 continue; 815 Type[] mtypes = method.arg_types; 816 if (mtypes.length != paramTypes.length) 817 continue; 818 nMatches++; 819 matches.addElement(method); 820 } 821 Method[] result = new Method[nMatches]; 822 matches.copyInto(result); 823 return result; 824 } 825 826 829 public void doFixups () 830 { 831 if (constants == null) 832 constants = new ConstantPool(); 833 if (thisClassIndex == 0) 834 thisClassIndex = constants.addClass(this).index; 835 if (superClass == this) 836 setSuper((ClassType) null); 837 if (superClassIndex < 0) 838 superClassIndex = superClass == null ? 0 839 : constants.addClass(superClass).index; 840 if (interfaces != null && interfaceIndexes == null) 841 { 842 int n = interfaces.length; 843 interfaceIndexes = new int [n]; 844 for (int i = 0; i < n; i++) 845 interfaceIndexes[i] = constants.addClass(interfaces[i]).index; 846 } 847 for (Field field = fields; field != null; field = field.next) { 848 field.assign_constants (this); 849 } 850 for (Method method = methods; method != null; method = method.next) 851 method.assignConstants(); 852 Attribute.assignConstants(this, this); 853 } 854 855 public void writeToStream (OutputStream stream) 856 throws java.io.IOException 857 { 858 java.io.DataOutputStream dstr = new java.io.DataOutputStream (stream); 859 int i; 860 861 doFixups (); 862 863 dstr.writeInt (0xcafebabe); dstr.writeShort(getClassfileMinorVersion()); 865 dstr.writeShort(getClassfileMajorVersion()); 866 867 if (constants == null) 869 dstr.writeShort (1); 870 else 871 constants.write(dstr); 872 873 dstr.writeShort (access_flags); 874 dstr.writeShort (thisClassIndex); 875 dstr.writeShort (superClassIndex); 876 if (interfaceIndexes == null) 877 dstr.writeShort (0); else 879 { 880 int interfaces_count = interfaceIndexes.length; 881 dstr.writeShort (interfaces_count); 882 for (i = 0; i < interfaces_count; i++) 883 dstr.writeShort (interfaceIndexes[i]); 884 } 885 886 dstr.writeShort (fields_count); 887 for (Field field = fields; field != null; field = field.next) 888 field.write (dstr, this); 889 890 dstr.writeShort (methods_count); 891 for (Method method = methods; method != null; method = method.next) 892 method.write (dstr, this); 893 894 Attribute.writeAll (this, dstr); 895 896 flags |= ADD_FIELDS_DONE | ADD_METHODS_DONE; 897 } 898 899 public void writeToFile (String filename) 900 throws java.io.IOException 901 { 902 OutputStream stream 903 = new BufferedOutputStream(new FileOutputStream (filename)); 904 writeToStream (stream); 905 stream.close (); 906 } 907 908 public void writeToFile () 909 throws java.io.IOException 910 { 911 writeToFile (this_name.replace ('.', File.separatorChar) + ".class"); 912 } 913 914 public byte[] writeToArray () 915 { 916 ByteArrayOutputStream stream = new ByteArrayOutputStream (500); 917 try 918 { 919 writeToStream(stream); 920 } 921 catch (java.io.IOException ex) 922 { 923 throw new InternalError (ex.toString()); 924 } 925 return stream.toByteArray (); 926 } 927 928 933 public static byte[] to_utf8 (String str) 934 { 935 if (str == null) 936 return null; 937 int str_len = str.length (); 938 int utf_len = 0; 939 for (int i = 0; i < str_len; i++) { 940 int c = str.charAt(i); 941 if ((c > 0) && (c <= 0x7F)) 942 utf_len++; 943 else if (c <= 0x7FF) 944 utf_len += 2; 945 else 946 utf_len += 3; 947 } 948 byte[] buffer = new byte[utf_len]; 949 int j = 0; 950 for (int i = 0; i < str_len; i++) { 951 int c = str.charAt(i); 952 if ((c > 0) && (c <= 0x7F)) 953 buffer[j++] = (byte) c; 954 else if (c <= 0x7FF) { 955 buffer[j++] = (byte) (0xC0 | ((c >> 6) & 0x1F)); 956 buffer[j++] = (byte) (0x80 | ((c >> 0) & 0x3F)); 957 } else { 958 buffer[j++] = (byte) (0xE0 | ((c >> 12) & 0x0F)); 959 buffer[j++] = (byte) (0x80 | ((c >> 6) & 0x3F)); 960 buffer[j++] = (byte) (0x80 | ((c >> 0) & 0x3F)); 961 } 962 } 963 return buffer; 964 } 965 966 967 public final boolean implementsInterface(ClassType iface) 968 { 969 if (this == iface) 970 return true; 971 ClassType baseClass = this.getSuperclass(); 972 if (baseClass != null && baseClass.implementsInterface(iface)) 973 return true; 974 ClassType[] interfaces = getInterfaces(); 975 if (interfaces != null) 976 { 977 for (int i = interfaces.length; --i >= 0; ) 978 { 979 if (interfaces[i].implementsInterface(iface)) 980 return true; 981 } 982 } 983 return false; 984 } 985 986 990 public final boolean isSubclass (String cname) 991 { 992 ClassType ctype = this; 993 for (;;) 994 { 995 if (cname.equals(ctype.getName())) 996 return true; 997 ctype = ctype.getSuperclass(); 998 if (ctype == null) 999 return false; 1000 } 1001 } 1002 1003 public final boolean isSubclass(ClassType other) 1004 { 1005 if (other.isInterface()) 1006 return implementsInterface(other); 1007 if ((this == tostring_type && other == string_type) 1008 || (this == string_type && other == tostring_type)) 1009 return true; 1010 ClassType baseClass = this; 1011 while (baseClass != null) 1012 { 1013 if (baseClass == other) 1014 return true; 1015 baseClass = baseClass.getSuperclass(); 1016 } 1017 return false; 1018 } 1019 1020 public int compare(Type other) 1021 { 1022 if (other == nullType) 1023 return 1; 1024 if (! (other instanceof ClassType)) 1025 return swappedCompareResult(other.compare(this)); 1026 String name = getName(); 1027 if (name != null && name.equals(other.getName())) 1028 return 0; 1029 ClassType cother = (ClassType) other; 1030 if (isSubclass(cother)) 1031 return -1; 1032 if (cother.isSubclass(this)) 1033 return 1; 1034 if (this == tostring_type) 1035 return cother == Type.pointer_type ? -1 : 1; 1036 if (cother == tostring_type) 1037 return this == Type.pointer_type ? 1 : -1; 1038 if (this.isInterface() || cother.isInterface()) 1039 return -2; 1040 return -3; 1041 } 1042 1043 public String toString() 1044 { 1045 return "ClassType " + getName(); 1046 } 1047 1048 1051 public void writeExternal(ObjectOutput out) throws IOException 1052 { 1053 out.writeUTF(getName()); 1054 } 1055 1056 public void readExternal(ObjectInput in) 1057 throws IOException, ClassNotFoundException 1058 { 1059 setName(in.readUTF()); 1060 flags |= ClassType.EXISTING_CLASS; 1061 } 1062 1063 public Object readResolve() throws ObjectStreamException 1064 { 1065 String name = getName(); 1066 1067 1069 java.util.Hashtable map = mapNameToType; 1070 1071 synchronized (map) 1072 { 1073 Type found = (Type) map.get(name); 1074 if (found != null) 1075 return found; 1076 map.put(name, this); 1077 } 1078 return this; 1079 } 1080 1081 1082 public void cleanupAfterCompilation () 1083 { 1084 for (Method meth = methods; meth != null; meth = meth.getNext()) 1085 meth.cleanupAfterCompilation(); 1086 1087 constants = null; 1088 attributes = null; 1089 sourceDbgExt = null; 1090 } 1091} 1092 | Popular Tags |