1 17 package org.apache.bcel.classfile; 18 19 import java.io.ByteArrayOutputStream ; 20 import java.io.DataOutputStream ; 21 import java.io.File ; 22 import java.io.FileOutputStream ; 23 import java.io.IOException ; 24 import java.io.OutputStream ; 25 import java.util.ArrayList ; 26 import java.util.List ; 27 import java.util.Set ; 28 import java.util.StringTokenizer ; 29 import java.util.TreeSet ; 30 import org.apache.bcel.Constants; 31 import org.apache.bcel.generic.Type; 32 import org.apache.bcel.util.BCELComparator; 33 import org.apache.bcel.util.ClassQueue; 34 import org.apache.bcel.util.SyntheticRepository; 35 36 48 public class JavaClass extends AccessFlags implements Cloneable , Node, Comparable { 49 50 private String file_name; 51 private String package_name; 52 private String source_file_name = "<Unknown>"; 53 private int class_name_index; 54 private int superclass_name_index; 55 private String class_name; 56 private String superclass_name; 57 private int major, minor; private ConstantPool constant_pool; private int[] interfaces; private String [] interface_names; 61 private Field[] fields; private Method[] methods; private Attribute[] attributes; private byte source = HEAP; public static final byte HEAP = 1; 66 public static final byte FILE = 2; 67 public static final byte ZIP = 3; 68 static boolean debug = false; static char sep = '/'; private static BCELComparator _cmp = new BCELComparator() { 71 72 public boolean equals( Object o1, Object o2 ) { 73 JavaClass THIS = (JavaClass) o1; 74 JavaClass THAT = (JavaClass) o2; 75 return THIS.getClassName().equals(THAT.getClassName()); 76 } 77 78 79 public int hashCode( Object o ) { 80 JavaClass THIS = (JavaClass) o; 81 return THIS.getClassName().hashCode(); 82 } 83 }; 84 89 private transient org.apache.bcel.util.Repository repository = SyntheticRepository 90 .getInstance(); 91 92 93 111 public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major, 112 int minor, int access_flags, ConstantPool constant_pool, int[] interfaces, 113 Field[] fields, Method[] methods, Attribute[] attributes, byte source) { 114 if (interfaces == null) { 115 interfaces = new int[0]; 116 } 117 if (attributes == null) { 118 attributes = new Attribute[0]; 119 } 120 if (fields == null) { 121 fields = new Field[0]; 122 } 123 if (methods == null) { 124 methods = new Method[0]; 125 } 126 this.class_name_index = class_name_index; 127 this.superclass_name_index = superclass_name_index; 128 this.file_name = file_name; 129 this.major = major; 130 this.minor = minor; 131 this.access_flags = access_flags; 132 this.constant_pool = constant_pool; 133 this.interfaces = interfaces; 134 this.fields = fields; 135 this.methods = methods; 136 this.attributes = attributes; 137 this.source = source; 138 for (int i = 0; i < attributes.length; i++) { 140 if (attributes[i] instanceof SourceFile) { 141 source_file_name = ((SourceFile) attributes[i]).getSourceFileName(); 142 break; 143 } 144 } 145 149 class_name = constant_pool.getConstantString(class_name_index, Constants.CONSTANT_Class); 150 class_name = Utility.compactClassName(class_name, false); 151 int index = class_name.lastIndexOf('.'); 152 if (index < 0) { 153 package_name = ""; 154 } else { 155 package_name = class_name.substring(0, index); 156 } 157 if (superclass_name_index > 0) { 158 superclass_name = constant_pool.getConstantString(superclass_name_index, 160 Constants.CONSTANT_Class); 161 superclass_name = Utility.compactClassName(superclass_name, false); 162 } else { 163 superclass_name = "java.lang.Object"; 164 } 165 interface_names = new String [interfaces.length]; 166 for (int i = 0; i < interfaces.length; i++) { 167 String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class); 168 interface_names[i] = Utility.compactClassName(str, false); 169 } 170 } 171 172 173 188 public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major, 189 int minor, int access_flags, ConstantPool constant_pool, int[] interfaces, 190 Field[] fields, Method[] methods, Attribute[] attributes) { 191 this(class_name_index, superclass_name_index, file_name, major, minor, access_flags, 192 constant_pool, interfaces, fields, methods, attributes, HEAP); 193 } 194 195 196 203 public void accept( Visitor v ) { 204 v.visitJavaClass(this); 205 } 206 207 208 210 static final void Debug( String str ) { 211 if (debug) { 212 System.out.println(str); 213 } 214 } 215 216 217 223 public void dump( File file ) throws IOException { 224 String parent = file.getParent(); 225 if (parent != null) { 226 File dir = new File (parent); 227 dir.mkdirs(); 228 } 229 DataOutputStream dos = null; 230 try { 231 dos = new DataOutputStream (new FileOutputStream (file)); 232 dump(dos); 233 } finally { 234 if (dos != null) { 235 dos.close(); 236 } 237 } 238 } 239 240 241 247 public void dump( String _file_name ) throws IOException { 248 dump(new File (_file_name)); 249 } 250 251 252 255 public byte[] getBytes() { 256 ByteArrayOutputStream s = new ByteArrayOutputStream (); 257 DataOutputStream ds = new DataOutputStream (s); 258 try { 259 dump(ds); 260 } catch (IOException e) { 261 e.printStackTrace(); 262 } finally { 263 try { 264 ds.close(); 265 } catch (IOException e2) { 266 e2.printStackTrace(); 267 } 268 } 269 return s.toByteArray(); 270 } 271 272 273 279 public void dump( OutputStream file ) throws IOException { 280 dump(new DataOutputStream (file)); 281 } 282 283 284 290 public void dump( DataOutputStream file ) throws IOException { 291 file.writeInt(0xcafebabe); 292 file.writeShort(minor); 293 file.writeShort(major); 294 constant_pool.dump(file); 295 file.writeShort(access_flags); 296 file.writeShort(class_name_index); 297 file.writeShort(superclass_name_index); 298 file.writeShort(interfaces.length); 299 for (int i = 0; i < interfaces.length; i++) { 300 file.writeShort(interfaces[i]); 301 } 302 file.writeShort(fields.length); 303 for (int i = 0; i < fields.length; i++) { 304 fields[i].dump(file); 305 } 306 file.writeShort(methods.length); 307 for (int i = 0; i < methods.length; i++) { 308 methods[i].dump(file); 309 } 310 if (attributes != null) { 311 file.writeShort(attributes.length); 312 for (int i = 0; i < attributes.length; i++) { 313 attributes[i].dump(file); 314 } 315 } else { 316 file.writeShort(0); 317 } 318 file.flush(); 319 } 320 321 322 325 public Attribute[] getAttributes() { 326 return attributes; 327 } 328 329 330 333 public String getClassName() { 334 return class_name; 335 } 336 337 338 341 public String getPackageName() { 342 return package_name; 343 } 344 345 346 349 public int getClassNameIndex() { 350 return class_name_index; 351 } 352 353 354 357 public ConstantPool getConstantPool() { 358 return constant_pool; 359 } 360 361 362 367 public Field[] getFields() { 368 return fields; 369 } 370 371 372 375 public String getFileName() { 376 return file_name; 377 } 378 379 380 383 public String [] getInterfaceNames() { 384 return interface_names; 385 } 386 387 388 391 public int[] getInterfaceIndices() { 392 return interfaces; 393 } 394 395 396 399 public int getMajor() { 400 return major; 401 } 402 403 404 407 public Method[] getMethods() { 408 return methods; 409 } 410 411 412 416 public Method getMethod( java.lang.reflect.Method m ) { 417 for (int i = 0; i < methods.length; i++) { 418 Method method = methods[i]; 419 if (m.getName().equals(method.getName()) && (m.getModifiers() == method.getModifiers()) 420 && Type.getSignature(m).equals(method.getSignature())) { 421 return method; 422 } 423 } 424 return null; 425 } 426 427 428 431 public int getMinor() { 432 return minor; 433 } 434 435 436 439 public String getSourceFileName() { 440 return source_file_name; 441 } 442 443 444 447 public String getSuperclassName() { 448 return superclass_name; 449 } 450 451 452 455 public int getSuperclassNameIndex() { 456 return superclass_name_index; 457 } 458 459 static { 460 debug = Boolean.getBoolean("JavaClass.debug"); 462 String _sep = System.getProperty("file.separator"); 464 if (_sep != null) { 465 try { 466 JavaClass.sep = _sep.charAt(0); 467 } catch (StringIndexOutOfBoundsException e) { 468 } } 470 } 471 472 473 476 public void setAttributes( Attribute[] attributes ) { 477 this.attributes = attributes; 478 } 479 480 481 484 public void setClassName( String class_name ) { 485 this.class_name = class_name; 486 } 487 488 489 492 public void setClassNameIndex( int class_name_index ) { 493 this.class_name_index = class_name_index; 494 } 495 496 497 500 public void setConstantPool( ConstantPool constant_pool ) { 501 this.constant_pool = constant_pool; 502 } 503 504 505 508 public void setFields( Field[] fields ) { 509 this.fields = fields; 510 } 511 512 513 516 public void setFileName( String file_name ) { 517 this.file_name = file_name; 518 } 519 520 521 524 public void setInterfaceNames( String [] interface_names ) { 525 this.interface_names = interface_names; 526 } 527 528 529 532 public void setInterfaces( int[] interfaces ) { 533 this.interfaces = interfaces; 534 } 535 536 537 540 public void setMajor( int major ) { 541 this.major = major; 542 } 543 544 545 548 public void setMethods( Method[] methods ) { 549 this.methods = methods; 550 } 551 552 553 556 public void setMinor( int minor ) { 557 this.minor = minor; 558 } 559 560 561 564 public void setSourceFileName( String source_file_name ) { 565 this.source_file_name = source_file_name; 566 } 567 568 569 572 public void setSuperclassName( String superclass_name ) { 573 this.superclass_name = superclass_name; 574 } 575 576 577 580 public void setSuperclassNameIndex( int superclass_name_index ) { 581 this.superclass_name_index = superclass_name_index; 582 } 583 584 585 588 public String toString() { 589 String access = Utility.accessToString(access_flags, true); 590 access = access.equals("") ? "" : (access + " "); 591 StringBuffer buf = new StringBuffer (128); 592 buf.append(access).append(Utility.classOrInterface(access_flags)).append(" ").append( 593 class_name).append(" extends ").append( 594 Utility.compactClassName(superclass_name, false)).append('\n'); 595 int size = interfaces.length; 596 if (size > 0) { 597 buf.append("implements\t\t"); 598 for (int i = 0; i < size; i++) { 599 buf.append(interface_names[i]); 600 if (i < size - 1) { 601 buf.append(", "); 602 } 603 } 604 buf.append('\n'); 605 } 606 buf.append("filename\t\t").append(file_name).append('\n'); 607 buf.append("compiled from\t\t").append(source_file_name).append('\n'); 608 buf.append("compiler version\t").append(major).append(".").append(minor).append('\n'); 609 buf.append("access flags\t\t").append(access_flags).append('\n'); 610 buf.append("constant pool\t\t").append(constant_pool.getLength()).append(" entries\n"); 611 buf.append("ACC_SUPER flag\t\t").append(isSuper()).append("\n"); 612 if (attributes.length > 0) { 613 buf.append("\nAttribute(s):\n"); 614 for (int i = 0; i < attributes.length; i++) { 615 buf.append(indent(attributes[i])); 616 } 617 } 618 if (fields.length > 0) { 619 buf.append("\n").append(fields.length).append(" fields:\n"); 620 for (int i = 0; i < fields.length; i++) { 621 buf.append("\t").append(fields[i]).append('\n'); 622 } 623 } 624 if (methods.length > 0) { 625 buf.append("\n").append(methods.length).append(" methods:\n"); 626 for (int i = 0; i < methods.length; i++) { 627 buf.append("\t").append(methods[i]).append('\n'); 628 } 629 } 630 return buf.toString(); 631 } 632 633 634 private static final String indent( Object obj ) { 635 StringTokenizer tok = new StringTokenizer (obj.toString(), "\n"); 636 StringBuffer buf = new StringBuffer (); 637 while (tok.hasMoreTokens()) { 638 buf.append("\t").append(tok.nextToken()).append("\n"); 639 } 640 return buf.toString(); 641 } 642 643 644 647 public JavaClass copy() { 648 JavaClass c = null; 649 try { 650 c = (JavaClass) clone(); 651 c.constant_pool = constant_pool.copy(); 652 c.interfaces = (int[]) interfaces.clone(); 653 c.interface_names = (String []) interface_names.clone(); 654 c.fields = new Field[fields.length]; 655 for (int i = 0; i < fields.length; i++) { 656 c.fields[i] = fields[i].copy(c.constant_pool); 657 } 658 c.methods = new Method[methods.length]; 659 for (int i = 0; i < methods.length; i++) { 660 c.methods[i] = methods[i].copy(c.constant_pool); 661 } 662 c.attributes = new Attribute[attributes.length]; 663 for (int i = 0; i < attributes.length; i++) { 664 c.attributes[i] = attributes[i].copy(c.constant_pool); 665 } 666 } catch (CloneNotSupportedException e) { 667 } 668 return c; 669 } 670 671 672 public final boolean isSuper() { 673 return (access_flags & Constants.ACC_SUPER) != 0; 674 } 675 676 677 public final boolean isClass() { 678 return (access_flags & Constants.ACC_INTERFACE) == 0; 679 } 680 681 682 684 public final byte getSource() { 685 return source; 686 } 687 688 689 690 694 public org.apache.bcel.util.Repository getRepository() { 695 return repository; 696 } 697 698 699 703 public void setRepository( org.apache.bcel.util.Repository repository ) { 704 this.repository = repository; 705 } 706 707 708 714 public final boolean instanceOf( JavaClass super_class ) throws ClassNotFoundException { 715 if (this.equals(super_class)) { 716 return true; 717 } 718 JavaClass[] super_classes = getSuperClasses(); 719 for (int i = 0; i < super_classes.length; i++) { 720 if (super_classes[i].equals(super_class)) { 721 return true; 722 } 723 } 724 if (super_class.isInterface()) { 725 return implementationOf(super_class); 726 } 727 return false; 728 } 729 730 731 736 public boolean implementationOf( JavaClass inter ) throws ClassNotFoundException { 737 if (!inter.isInterface()) { 738 throw new IllegalArgumentException (inter.getClassName() + " is no interface"); 739 } 740 if (this.equals(inter)) { 741 return true; 742 } 743 JavaClass[] super_interfaces = getAllInterfaces(); 744 for (int i = 0; i < super_interfaces.length; i++) { 745 if (super_interfaces[i].equals(inter)) { 746 return true; 747 } 748 } 749 return false; 750 } 751 752 753 758 public JavaClass getSuperClass() throws ClassNotFoundException { 759 if ("java.lang.Object".equals(getClassName())) { 760 return null; 761 } 762 return repository.loadClass(getSuperclassName()); 763 } 764 765 766 771 public JavaClass[] getSuperClasses() throws ClassNotFoundException { 772 JavaClass clazz = this; 773 List allSuperClasses = new ArrayList (); 774 for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) { 775 allSuperClasses.add(clazz); 776 } 777 return (JavaClass[]) allSuperClasses.toArray(new JavaClass[allSuperClasses.size()]); 778 } 779 780 781 784 public JavaClass[] getInterfaces() throws ClassNotFoundException { 785 String [] _interfaces = getInterfaceNames(); 786 JavaClass[] classes = new JavaClass[_interfaces.length]; 787 for (int i = 0; i < _interfaces.length; i++) { 788 classes[i] = repository.loadClass(_interfaces[i]); 789 } 790 return classes; 791 } 792 793 794 797 public JavaClass[] getAllInterfaces() throws ClassNotFoundException { 798 ClassQueue queue = new ClassQueue(); 799 Set allInterfaces = new TreeSet (); 800 queue.enqueue(this); 801 while (!queue.empty()) { 802 JavaClass clazz = queue.dequeue(); 803 JavaClass souper = clazz.getSuperClass(); 804 JavaClass[] _interfaces = clazz.getInterfaces(); 805 if (clazz.isInterface()) { 806 allInterfaces.add(clazz); 807 } else { 808 if (souper != null) { 809 queue.enqueue(souper); 810 } 811 } 812 for (int i = 0; i < _interfaces.length; i++) { 813 queue.enqueue(_interfaces[i]); 814 } 815 } 816 return (JavaClass[]) allInterfaces.toArray(new JavaClass[allInterfaces.size()]); 817 } 818 819 820 823 public static BCELComparator getComparator() { 824 return _cmp; 825 } 826 827 828 831 public static void setComparator( BCELComparator comparator ) { 832 _cmp = comparator; 833 } 834 835 836 843 public boolean equals( Object obj ) { 844 return _cmp.equals(this, obj); 845 } 846 847 848 852 public int compareTo( Object obj ) { 853 return getClassName().compareTo(((JavaClass) obj).getClassName()); 854 } 855 856 857 863 public int hashCode() { 864 return _cmp.hashCode(this); 865 } 866 } 867 | Popular Tags |