1 30 31 package jbet; 32 import java.io.*; 33 import java.util.*; 34 35 63 64 public final class ClassInfo { 65 66 public static String JbetLogFacility = "class"; 67 68 private int sourceFileIndex; private Vector attributes; private Vector attrHints; private int [] interfaceInts; 72 private int thisClassIndex, superClassIndex; 73 74 75 String filename = null; 76 public ClassPathElement classPathElement = null; 77 public boolean dirty = false; 78 79 80 int magic; 81 int minorVersion; 82 int majorVersion; 83 public ConstantPool constantPool; 84 public int accessFlags; 85 public String thisClass; 86 public String superClass; 87 public Vector interfaces; public Vector fields; public Vector methods; 91 96 Vector innerClasses; public boolean synthetic, deprecated; 99 public String sourceFile; 100 101 105 106 114 public ClassInfo(ClassPathElement cpElement, String thisClass) { 115 init(cpElement, thisClass); 116 } 117 118 public void setOutdir (ClassPathElement cpe) { 119 if (classPathElement == null) 120 classPathElement = cpe; 121 } 122 123 136 public ClassInfo(InputStream in) throws ClassFileException, IOException { 137 this(in,null,null); 138 } 139 public ClassInfo(InputStream in, ClassPathElement cpElement) 140 throws ClassFileException, IOException { 141 this(in,cpElement,null); 142 } 143 public ClassInfo(InputStream in, ClassPathElement cpElement, 144 String filename) 145 throws ClassFileException, IOException { 146 this.classPathElement = cpElement; 147 this.filename = filename; 148 DataInputStream dataIn = in instanceof DataInputStream ? 149 (DataInputStream) in : new DataInputStream(in); 150 readFile(dataIn); 151 } 152 153 161 public ClassInfo(ClassInfo cr) { 162 magic = cr.magic; 163 minorVersion = cr.minorVersion; 164 majorVersion = cr.majorVersion; 165 constantPool = null; 166 accessFlags = cr.accessFlags; 167 thisClass = cr.thisClass; 168 superClass = cr.superClass; 169 170 interfaces = new Vector( cr.interfaces.size() ); 171 for (int i = 0; i < cr.interfaces.size(); i++) 172 interfaces.addElement( cr.interfaces.elementAt(i) ); 173 174 fields = new Vector( cr.fields.size() ); 175 for (int i = 0; i < cr.fields.size(); i++) 176 addField (new FieldInfo ((FieldInfo)cr.fields.elementAt(i))); 177 178 methods = new Vector( cr.methods.size() ); 179 for (int i = 0; i < cr.methods.size(); i++) 180 addMethod 181 ((new MethodInfo ((MethodInfo)cr.methods.elementAt(i)))); 182 183 innerClasses = new Vector( cr.innerClasses.size() ); 184 for (int i = 0; i < cr.innerClasses.size(); i++) 185 innerClasses.addElement 186 (((InnerClassInfo)cr.innerClasses.elementAt(i)).dup()); 187 188 attrHints = new Vector(); 189 190 synthetic = cr.synthetic; 191 deprecated = cr.deprecated; 192 sourceFile = cr.sourceFile; 193 194 newPool(); 195 } 196 197 198 public FieldInfo getField(String name) throws ElementNotFoundException { 199 FieldInfo ret = null; 200 for (int i = 0; i < fields.size(); i++) { 201 FieldInfo mi = (FieldInfo) fields.elementAt(i); 202 if (mi.name.equals(name)) 203 if (ret == null) 204 ret = mi; 205 else 206 throw new ElementNotFoundException 207 (name(), name, null, "Can not disambiguate"); 208 } 209 if (ret == null) { 210 throw new ElementNotFoundException (name(), name, null); 211 } 212 return ret; 213 } 214 215 216 226 public ClassInfo(ClassPathElement cpElement, Lexer lexer) throws ClassFileException { 227 lexer.push(Lexer.ST_ASM); 228 if (!lexer.match(Token.TAG).text.equals(".class")) { 229 lexer.unexpected(lexer.justread()); 230 } 231 int af = lexer.parse_flags(ACC_ALL_CFLAGS | ACC_ALL_INNER_CFLAGS); 232 String name = lexer.match(Token.TAG).text; 233 init(cpElement, name); 234 accessFlags = af; 235 lexer.match('{'); 236 while (true) { 237 lexer.state = Lexer.ST_ASM; 238 while (lexer.peek().type == ';') { 239 lexer.read(); 240 } 241 Token tok = lexer.peek(); 242 lexer.state = Lexer.ST_ASM_ARG; 243 if (tok.type == Token.TAG) { 244 if (tok.text.equals(".inner")) { 245 InnerClassInfo ici = new InnerClassInfo(lexer); 246 innerClasses.addElement(ici); 247 continue; 248 } 249 255 if (tok.text.equals(".field")) { 256 FieldInfo fi = new FieldInfo(lexer); 257 addField(fi); 258 continue; 259 } 260 if (tok.text.equals(".method")) { 261 MethodInfo mi = new MethodInfo(lexer); 262 addMethod(mi); 263 continue; 264 } 265 lexer.read(); 266 if (tok.text.equals(".synthetic")) { 267 lexer.term(); 268 synthetic = true; 269 continue; 270 } 271 if (tok.text.equals(".deprecated")) { 272 lexer.term(); 273 deprecated = true; 274 continue; 275 } 276 if (tok.text.equals(".flags")) { 277 int flags = lexer.parse_flags(ACC_ALL_CFLAGS); 278 lexer.term(); 279 accessFlags = flags; 280 continue; 281 } 282 if (tok.text.equals(".extends")) { 283 superClass = lexer.parse_name(); 284 lexer.term(); 285 continue; 286 } 287 if (tok.text.equals(".implements")) { 288 interfaces.addElement( lexer.parse_name() ); 289 lexer.term(); 290 continue; 291 } 292 if (tok.text.equals(".sourcefile")) { 293 sourceFile = lexer.parse_string(); 294 lexer.term(); 295 continue; 296 } 297 lexer.unexpected(tok); 298 } 299 if (tok.type == '}') { 300 break; 301 } 302 lexer.unexpected(tok); 303 } 304 lexer.match('}'); 305 lexer.pop(); 306 } 308 309 317 private void init(ClassPathElement cpElement, String thisClass) { 318 constantPool = new ConstantPool(); 319 classPathElement = cpElement; 320 dirty = true; 321 magic = 0xCAFEBABE; 322 minorVersion = 3; 323 majorVersion = 45; 324 accessFlags = ACC_PUBLIC & ACC_FINAL; 325 this.thisClass = thisClass; 326 superClass = "java/lang/Object"; 327 interfaces = new Vector(); 328 fields = new Vector(); 329 methods = new Vector(); 330 innerClasses = new Vector(); 331 synthetic = true; 332 deprecated = false; 333 sourceFile = null; 334 attrHints = new Vector(); 337 } 338 339 342 343 362 private void readFile(DataInputStream dataIn) 363 throws IOException, ClassFileException { 364 365 synthetic = deprecated = false; 366 sourceFile = null; 367 innerClasses = new Vector(); 368 369 magic = dataIn.readInt(); 370 minorVersion = dataIn.readUnsignedShort(); 371 majorVersion = dataIn.readUnsignedShort(); 372 373 constantPool = new ConstantPool(dataIn); 374 375 accessFlags = dataIn.readUnsignedShort(); 376 377 thisClassIndex = dataIn.readUnsignedShort(); 378 thisClass = constantPool.cpClassAt(thisClassIndex).string(); 379 380 superClassIndex = dataIn.readUnsignedShort(); 381 superClass = (superClassIndex == 0) ? null : 382 constantPool.cpClassAt(superClassIndex).string(); 383 384 int interfacesCount = dataIn.readUnsignedShort(); 385 interfaces = new Vector (interfacesCount); 386 interfaceInts = new int [ interfacesCount ]; 387 for (int i = 0; i < interfacesCount; i++) { 388 int index = dataIn.readUnsignedShort(); 389 interfaceInts[i] = index; 390 interfaces.addElement 391 ( constantPool.cpClassAt(index).string() ); 392 } 393 394 int fieldsCount = dataIn.readUnsignedShort(); 395 fields = new Vector (fieldsCount); 396 for (int i = 0; i < fieldsCount; i++) { 397 FieldInfo f = new FieldInfo(dataIn, constantPool); 398 addField(f); 399 } 400 401 int methodsCount = dataIn.readUnsignedShort(); 402 methods = new Vector (methodsCount); 403 for (int i = 0; i < methodsCount; i++) { 404 MethodInfo m = new MethodInfo(dataIn, constantPool); 405 addMethod(m); 406 } 407 408 419 int attributesCount = dataIn.readUnsignedShort(); 420 attrHints = new Vector (attributesCount); 421 for (int i = 0; i < attributesCount; i++) { 422 int nameindex = dataIn.readUnsignedShort(); 423 String attrname = constantPool.utf8At(nameindex); 424 int length = dataIn.readInt(); 425 426 GenericAttribute item = new GenericAttribute (attrname, nameindex); 427 428 if (attrname.equals("InnerClasses")) { 429 int numClasses = dataIn.readUnsignedShort(); 430 innerClasses.ensureCapacity(numClasses); 431 for (int j = 0; j < numClasses; j++) { 432 InnerClassInfo ic = new InnerClassInfo(dataIn, 433 constantPool); 434 if (ic.inner.equals(thisClass)) 435 accessFlags |= ic.accessFlags; 436 innerClasses.addElement(ic); 437 } 438 item.writer = innerClassesWriter(); 439 } else if (attrname.equals("Synthetic")) { 440 synthetic = true; 441 item.nodata(); 442 } else if (attrname.equals("Deprecated")) { 443 deprecated = true; 444 item.nodata(); 445 } else if (attrname.equals("SourceFile")) { 446 sourceFileIndex = dataIn.readUnsignedShort(); 447 sourceFile = constantPool.utf8At(sourceFileIndex); 448 item.writer = sourceFileWriter(); 449 } else { 450 Jbet.warn.println("Warning: unrecognised class attribute " + 451 attrname); 452 item.read(length, dataIn); 453 } 454 attrHints.addElement(item); 455 } 456 attributes = attrHints; 457 458 } 459 460 465 public void write() throws Exception { 466 resolveConstants(); 467 468 String filename = this.filename; 469 if (filename == null) filename = name() + ".class"; 470 ClassPathElement cpe = classPathElement; 471 if (cpe == null) cpe = new ClassInfoLoader.DirectoryCPE(Jbet.outputdir); 472 OutputStream out = cpe.put(filename); 473 Jbet.info.println("wrote " + name() + " TO " + filename + " IN " + 474 cpe); 475 DataOutputStream dataOut = new DataOutputStream (out); 476 477 writeFile(dataOut); 478 dirty = false; 479 } 480 481 492 void writeFile(String filename) throws IOException { 493 FileOutputStream fout = new FileOutputStream(filename); 494 DataOutputStream dataOut = new DataOutputStream(fout); 495 writeFile(dataOut); 496 } 497 public void writeFile(OutputStream out) throws IOException { 498 DataOutputStream dataOut = new DataOutputStream(out); 499 writeFile(dataOut); 500 } 501 public void writeFile (DataOutputStream dataOut) throws IOException { 502 dataOut.writeInt( magic ); 503 dataOut.writeShort( minorVersion ); 504 dataOut.writeShort( majorVersion ); 505 506 constantPool.writeFile (dataOut); 507 508 dataOut.writeShort( accessFlags & ACC_ALL_CFLAGS ); 510 dataOut.writeShort( thisClassIndex ); 511 dataOut.writeShort( superClassIndex ); 512 513 dataOut.writeShort( interfaceInts.length ) ; 514 for (int i = 0; i < interfaceInts.length; i++) 515 dataOut.writeShort( interfaceInts[i] ); 516 517 dataOut.writeShort( fields.size() ); 518 for (int i = 0; i < fields.size(); i++) 519 ((FieldInfo)fields.elementAt(i)).writeFile( dataOut ); 520 521 dataOut.writeShort( methods.size() ); 522 for (int i = 0; i < methods.size(); i++) 523 ((MethodInfo)methods.elementAt(i)).writeFile( dataOut ); 524 525 dataOut.writeShort( attributes.size() ); 526 for (int i = 0; i < attributes.size(); i++) 527 ((GenericAttribute)attributes.elementAt(i)).writeAll( dataOut ); 528 } 529 530 537 private AttributeWriter innerClassesWriter() { 538 final int icsize = innerClasses.size(); 539 return new AttributeWriter() { 540 public void write (DataOutputStream dataOut) 541 throws IOException, RuntimeException { 542 dataOut.writeShort( icsize ); 543 for (int i = 0; i < icsize; i++) 544 ((InnerClassInfo) 545 innerClasses.elementAt(i)).writeFile(dataOut); 546 } 547 public int size() { return 2 + 8*icsize; } 548 }; 549 } 550 private AttributeWriter sourceFileWriter() { 551 return new AttributeWriter() { 552 public void write(DataOutputStream dataOut) 553 throws IOException, RuntimeException { 554 dataOut.writeShort( sourceFileIndex ); 555 } 556 public int size() { return 2; } 557 }; 558 } 559 560 577 public void relocate (Hashtable subs) { 578 thisClass = Util.relocate(thisClass, subs); 579 superClass = Util.relocate(superClass, subs); 580 for (int i = 0; i < interfaces.size(); i++) { 581 String cp = interfaceAt(i); 582 cp = Util.relocate(cp, subs); 583 interfaces.setElementAt(cp, i); 584 } 585 for (int i = 0; i < fields.size(); i++) 586 fieldAt(i).relocate(subs); 587 for (int i = 0; i < methods.size(); i++) 588 methodAt(i).relocate(subs); 589 for (int i = 0; i < innerClasses.size(); i++) 590 innerClassAt(i).relocate(subs); 591 } 592 593 596 public String toString() { 597 return thisClass; 598 } 599 600 public String name() { 601 return thisClass; 602 } 603 604 public ClassPathElement getPathElement () { 605 return classPathElement; 606 } 607 608 614 public boolean isAnon() { 615 return Util.isAnon(thisClass); 616 } 617 618 624 private void newPool() { 625 constantPool = new ConstantPool(); 626 } 627 628 635 public void disassemble(LineWriter out, String prefix) { 636 out.println (prefix + ".class " + 637 Util.flags2str(accessFlags, true) + " " + 638 thisClass + " {"); 639 String p = prefix + " "; 640 if (!superClass.equals("java/lang/Object")) 641 out.println(p + ".extends " + superClass); 642 for (int i = 0; i < interfaces.size(); i++) 643 out.println(p + ".implements " + interfaceAt(i)); 644 if (sourceFile != null) 645 out.println(p + ".sourcefile \"" + 646 Util.quoteString(sourceFile) + "\""); 647 if (synthetic) 648 out.println(p + ".synthetic"); 649 if (deprecated) 650 out.println(p + ".deprecated"); 651 out.println(prefix); 652 for (int i = 0; i < fields.size(); i++) 653 fieldAt(i).disassemble(out, p); 654 out.println(prefix); 655 for (int i = 0; i < methods.size(); i++) { 656 methodAt(i).disassemble(out, p); 657 out.println(prefix); 658 } 659 for (int i = 0; i < innerClasses.size(); i++) 660 innerClassAt(i).disassemble(out, p); 661 out.println(prefix); 662 out.println (prefix + "}"); 663 } 664 665 677 public void resolveConstants() { 678 679 thisClassIndex = constantPool.internClass(thisClass); 680 superClassIndex = constantPool.internClass(superClass); 681 682 interfaceInts = new int [ interfaces.size() ]; 683 for (int i = 0; i < interfaces.size(); i++) 684 interfaceInts[i] = constantPool.internClass(interfaceAt(i)); 685 686 for (int i = 0; i < fields.size(); i++) 687 ((FieldInfo)fields.elementAt(i)).resolveConstants(constantPool); 688 689 for (int i = 0; i < methods.size(); i++) 690 ((MethodInfo)methods.elementAt(i)).resolveConstants(constantPool); 691 692 Vector outAttrs = new Vector(); 693 694 for (int i = 0; i < innerClasses.size(); i++) 695 innerClassAt(i).resolveConstants(constantPool); 696 697 if (innerClasses.size() != 0) { 698 GenericAttribute attr = new GenericAttribute("InnerClasses", 699 constantPool); 700 attr.writer = innerClassesWriter(); 701 outAttrs.addElement( attr ); 702 } 703 704 if (synthetic) 705 outAttrs.addElement(new GenericAttribute("Synthetic", 706 constantPool).nodata()); 707 708 if (deprecated) 709 outAttrs.addElement(new GenericAttribute("Deprecated", 710 constantPool).nodata()); 711 712 if (sourceFile != null) { 713 GenericAttribute attr = new GenericAttribute("SourceFile", 714 constantPool); 715 sourceFileIndex = constantPool.internUtf8 ( sourceFile ); 716 attr.writer = sourceFileWriter(); 717 outAttrs.addElement( attr ); 718 } 719 attributes = new Vector(); 720 GenericAttribute.permute (attrHints, outAttrs, attributes); 721 } 722 723 726 public String getSuperName() { 727 return superClass; 728 } 729 730 public ConstantPool constantPool () { 731 return constantPool; 732 } 733 734 public int numMethods () { 735 return methods.size(); 736 } 737 public int numFields () { 738 return fields.size(); 739 } 740 public int numInterfaces () { 741 return interfaces.size(); 742 } 743 744 public String interfaceAt(int i) { 745 return (String ) interfaces.elementAt(i); 746 } 747 public FieldInfo fieldAt(int i) { 748 return (FieldInfo) fields.elementAt(i); 749 } 750 public MethodInfo methodAt(int i) { 751 return (MethodInfo) methods.elementAt(i); 752 } 753 public void addMethod(MethodInfo mi) { 754 mi.cr = this; 755 methods.addElement(mi); 756 } 757 public void addField(FieldInfo fi) { 758 fi.cr = this; 759 fields.addElement(fi); 760 } 761 public void removeField (FieldInfo fi) { 762 fields.remove (fi); 763 } 764 public void removeMethod (MethodInfo fi) { 765 methods.remove (fi); 766 } 767 768 public InnerClassInfo innerClassAt(int i) { 769 return (InnerClassInfo) innerClasses.elementAt(i); 770 } 771 772 774 public MethodInfo findMethod (String name, String type) { 775 MethodInfo ret = null; 776 for (int i = 0; i < methods.size(); i++) { 777 MethodInfo mi = (MethodInfo) methods.elementAt(i); 778 if (mi.name.equals(name) && 779 (type==null || type.equals(mi.descriptor.toString()))) 780 if (ret == null) 781 ret = mi; 782 else 783 return null; 784 } 785 return ret; 786 } 787 public MethodInfo findMethod(String name) { 788 return findMethod(name, (Descriptor) null); 789 } 790 public MethodInfo findMethod (String name, Descriptor type) { 791 MethodInfo ret = null; 792 for (int i = 0; i < methods.size(); i++) { 793 MethodInfo mi = (MethodInfo) methods.elementAt(i); 794 if (mi.name.equals(name) && 795 (type==null || type.equals(mi.descriptor))) 796 if (ret == null) 797 ret = mi; 798 else 799 return null; 800 } 801 return ret; 802 } 803 public FieldInfo findField (String name) { 804 for (int i = 0; i < fields.size(); i++) { 805 FieldInfo fi = (FieldInfo) fields.elementAt(i); 806 if (fi.name.equals(name)) 807 return fi; 808 } 809 return null; 810 } 811 812 public int findMethodIndex (String name, Descriptor type) { 813 int ret = -1; 814 for (int i = 0; i < methods.size(); i++) { 815 MethodInfo mi = (MethodInfo) methods.elementAt(i); 816 if (mi.name.equals(name) && 817 (type==null || type.equals(mi.descriptor))) 818 if (ret == -1) 819 ret = i; 820 else 821 return -1; 822 } 823 return ret; 824 } 825 826 829 public void printout(LineWriter out, int v) { 830 if (v == 1) 831 out.println("CLASS"); 832 if (v == 2) 833 out.println("CLASS " + thisClass ); 834 out.println( "Magic: " + Integer.toHexString(magic)); 835 out.println( "Version: " + majorVersion + "." + minorVersion); 836 out.println( "Pool Count: " + constantPool.poolCount() ); 837 out.println( "Flags: " + Util.flags2str(accessFlags, true) + 838 (synthetic?" synthetic":"") + 839 (deprecated?" deprecated":"") ); 840 out.println( "This Class: " + thisClass ); 841 out.println( "Super Class: " + superClass ); 842 out.print ( "Interfaces: " ); 843 for (int i = 0; i < interfaces.size(); i++) 844 out.print( (interfaceAt(i)) + " " ); 845 out.println(); 846 out.println( "Fields Count: " + fields.size() ); 847 out.println( "Methods Count: " + methods.size() ); 848 if (attributes != null) { 849 out.print ( "Attributes: " ); 850 for (int i = 0; i < attributes.size(); i++) 851 out.print( ((GenericAttribute)attributes.elementAt(i)).name + 852 " " ); 853 out.println(); 854 } 855 if (sourceFile != null) 856 out.println("SourceFile: " + sourceFile); 857 for (int i = 0; i < innerClasses.size(); i++) 858 out.println("InnerClass: " + 859 ((InnerClassInfo) 860 innerClasses.elementAt(i)).recString()); 861 862 out.println(); 863 864 if (v > 0) 865 out.println(); 866 } 867 public void printFields(LineWriter out, int v) { 868 if (v == 1) 869 out.println("FIELDS"); 870 if (v == 2) 871 out.println("FIELDS " + thisClass ); 872 for (int i = 0; i < fields.size(); i++) 873 out.println ( ((FieldInfo)fields.elementAt(i)).recString() ); 874 if (v > 0) 875 out.println(); 876 } 877 public void printFields(LineWriter out, boolean header) { 878 if (header) 879 out.println("FIELDS"); 880 for (int i = 0; i < fields.size(); i++) 881 out.println ( ((FieldInfo)fields.elementAt(i)).recString() ); 882 } 883 public void printMethodNames (LineWriter out) { 884 for (int i = 0; i < methods.size(); i++) 885 out.println(methodAt(i).name + " " + 886 methodAt(i).descriptor); 887 } 888 public void printMethods(LineWriter out, int v) { 889 if (v == 1) 890 out.println("METHODS"); 891 if (v == 2) 892 out.println("METHODS " + thisClass); 893 for (int i = 0; i < methods.size(); i++) { 894 ((MethodInfo)methods.elementAt(i)).printout(out, false); 895 out.println(); 896 } 897 if (v > 0) 898 out.println(); 899 } 900 public void printcp(LineWriter out, int v) { 901 if (v == 1) 902 out.println("CONSTANT POOL"); 903 if (v == 2) 904 out.println("CONSTANT POOL " + thisClass); 905 constantPool.printout(out); 906 if (v > 0) 907 out.println(); 908 } 909 public void printAll(LineWriter out) { 910 printout(out, 1); 911 printFields(out, 1); 912 printMethods(out, 1); 913 } 914 915 static public final int ACC_PUBLIC = Util.ACC_PUBLIC; 916 static public final int ACC_FINAL = Util.ACC_FINAL; 917 static public final int ACC_SUPER = Util.ACC_SUPER; 918 static public final int ACC_INTERFACE = Util.ACC_INTERFACE; 919 static public final int ACC_ABSTRACT = Util.ACC_ABSTRACT; 920 921 static private final int ACC_PRIVATE = Util.ACC_PRIVATE; 923 static private final int ACC_PROTECTED = Util.ACC_PROTECTED; 924 static private final int ACC_STATIC = Util.ACC_STATIC; 925 static private final int ACC_ALL_CFLAGS = ACC_PUBLIC |ACC_FINAL | 926 ACC_SUPER | ACC_INTERFACE | ACC_ABSTRACT; 927 928 static public final int ACC_ALL_INNER_CFLAGS = ACC_PUBLIC | 929 ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT | ACC_PRIVATE 930 | ACC_PROTECTED | ACC_STATIC; 931 932 933 public boolean isInterface () { 934 return (accessFlags & ACC_INTERFACE) != 0; 935 } 936 937 public boolean isFinal () { 938 return (accessFlags & ACC_FINAL) != 0; 939 } 940 941 942 948 static private Vector lineage (String cname) throws ClassFileException { 949 ClassInfo cr = Jbet.loader.getClass(cname); 950 Vector ret = (cr.superClass == null) ? 951 new Vector() : lineage(cr.superClass); 952 ret.addElement(cname); 953 return ret; 954 } 955 956 960 961 private static class InhInfo 962 { 963 String cname; 964 int depth; 965 966 InhInfo (String cn, int i) { cname = cn; depth = i; } 967 968 public boolean equals (Object o) { 969 if (!(o instanceof InhInfo)) 970 return false; 971 InhInfo oo = (InhInfo) o; 972 return oo.cname.equals (cname); 973 } 974 975 public int hashCode () { 976 return cname.hashCode(); 977 } 978 979 public String toString () { 980 return cname; 981 } 982 }; 983 984 static private Vector lineage2 (String cname) throws ClassFileException { 985 ClassInfo cr = Jbet.loader.getClass(cname); 986 987 Vector out = new Vector(); 988 989 if (cr.superClass == null) { 990 out.addElement (cname); 991 return out; 992 } 993 994 for (int i = 0; i < cr.numInterfaces(); i++) 995 out.addAll (lineage2 (cr.interfaceAt (i))); 996 997 out.addAll (lineage2 (cr.superClass)); 998 999 out.addElement(cname); 1000 return out; 1001 } 1002 1003 1012 public static boolean isAncestor (String child, String parent) throws ClassFileException { 1013 if (child.equals(parent)) 1014 return true; 1015 ClassInfo cr = Jbet.loader.getClass(child); 1016 1017 for (int i = 0; i < cr.interfaces.size(); i++) 1018 if ( isAncestor(cr.interfaceAt(i), parent) ) 1019 return true; 1020 if (cr.superClass == null) 1021 return false; 1022 if (cr.superClass.equals(parent)) 1023 return true; 1024 return isAncestor(cr.superClass, parent); 1025 } 1026 1027 1039 public static String common_ancestor(String classA, String classB) throws ClassFileException { 1040 1041 1053 1054 Vector al = lineage2(classA); 1055 Vector bl = lineage2(classB); 1056 1057 String ca = "java/lang/Object"; 1058 1059 loop: for (int i = al.size() - 1; i >= 0; i--) 1060 for (int j = bl.size() - 1; j >= 0; j--) 1061 if (al.elementAt (i).equals (bl.elementAt (j))) { 1062 ca = al.elementAt (i).toString(); 1063 break loop; 1064 } 1065 1066 if (!isAncestor (classA, ca)) 1067 throw new IllegalStateException ("common_ancestor failed! " + ca + " is not an ancestor of " + classA); 1068 if (!isAncestor (classB, ca)) 1069 throw new IllegalStateException ("common_ancestor failed! " + ca + " is not an ancestor of " + classB); 1070 Jbet.output.println ("CA " + classA + " and " + classB + " is " + ca); 1071 return ca; 1072 } 1073 1074 1075 1076 public static boolean hasAncestors (String child, Vector parents) throws ClassFileException { 1077 for (Iterator i = parents.iterator(); i.hasNext(); ) { 1078 if (!isAncestor (child, i.next().toString())) 1079 return false; 1080 } 1081 return true; 1082 } 1083 1084 private static boolean checkDerived (Vector ca, String newclass) throws ClassFileException 1085 { 1086 for (Iterator i = ca.iterator(); i.hasNext(); ) { 1087 String cname = i.next().toString(); 1088 1089 if (isAncestor (cname, newclass)) 1090 return false; 1091 } 1092 return true; 1093 } 1094 1095 1104 1105 public static String allCommonAncestors (String classA, String classB) throws ClassFileException 1106 { 1107 Vector al = lineage2(classA); 1108 Vector bl = lineage2(classB); 1109 1110 Vector ca = new Vector(); 1111 1112 for (int i = al.size() - 1; i >= 0; i--) 1113 for (int j = bl.size() - 1; j >= 0; j--) 1114 if (al.elementAt (i).equals (bl.elementAt (j)) && checkDerived (ca, al.elementAt (i).toString())) 1115 ca.addElement (al.elementAt (i).toString()); 1116 1117 if (ca.size() == 0) 1118 ca.addElement ("java/lang/Object"); 1119 1120 if (!hasAncestors (classA, ca)) 1121 throw new IllegalStateException ("common_ancestor failed! " + ca + " is not an ancestor of " + classA); 1122 if (!hasAncestors (classB, ca)) 1123 throw new IllegalStateException ("common_ancestor failed! " + ca + " is not an ancestor of " + classB); 1124 1125 String caname; 1126 if (ca.size() == 1) 1127 caname = ca.elementAt (0).toString(); 1128 else { 1129 StringBuffer canb = new StringBuffer ("-/"); 1130 for (Iterator i = ca.iterator(); i.hasNext(); ) { 1131 canb.append ("$"); 1132 canb.append (i.next().toString()); 1133 } 1134 caname = canb.toString(); 1135 1136 ClassInfo cacr = new ClassInfo (null, caname); 1137 cacr.superClass = null; 1138 1139 for (Iterator i = ca.iterator(); i.hasNext(); ) { 1140 ClassInfo cr = Jbet.loader.getClass (i.next().toString()); 1141 if (cr.isInterface()) 1142 cacr.interfaces.addElement (cr.name()); 1143 else if (cacr.superClass != null) 1144 throw new IllegalStateException ("can't have two common non-interface superclasses (" 1145 + cacr.superClass + " and " + cr.name() +")"); 1146 else 1147 cacr.superClass = cr.name(); 1148 } 1149 1150 cacr.dirty = false; Jbet.loader.putClass (cacr); 1152 } 1153 1154 return caname; 1155 } 1156 1157 public boolean isDirty() { 1158 return dirty; 1159 } 1160 1161 public void setDirty () { 1162 dirty = true; 1163 } 1164 1165 public boolean inPackage(String packname) { 1166 return name().startsWith(packname + "/"); 1167 } 1168 1169 public String getPackageName () { 1170 int li = name().lastIndexOf ('/'); 1171 if (li == -1) 1172 return ""; 1173 return name().substring (0, li); 1174 } 1175 1176 public boolean checkAccess (String fromPackage) { 1177 if ((accessFlags & ACC_PUBLIC) != 0) 1178 return true; 1179 if ((accessFlags & ACC_PRIVATE) != 0) 1180 return false; 1181 if ((accessFlags & ACC_PROTECTED) != 0) 1182 return false; 1183 return fromPackage.equals (getPackageName()); 1184 } 1185} 1186 | Popular Tags |