1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 package com.sun.org.apache.bcel.internal.classfile;
   6 
   7 /* ====================================================================
   8  * The Apache Software License, Version 1.1
   9  *
  10  * Copyright (c) 2001 The Apache Software Foundation.  All rights
  11  * reserved.
  12  *
  13  * Redistribution and use in source and binary forms, with or without
  14  * modification, are permitted provided that the following conditions
  15  * are met:
  16  *
  17  * 1. Redistributions of source code must retain the above copyright
  18  *    notice, this list of conditions and the following disclaimer.
  19  *
  20  * 2. Redistributions in binary form must reproduce the above copyright
  21  *    notice, this list of conditions and the following disclaimer in
  22  *    the documentation and/or other materials provided with the
  23  *    distribution.
  24  *
  25  * 3. The end-user documentation included with the redistribution,
  26  *    if any, must include the following acknowledgment:
  27  *       "This product includes software developed by the
  28  *        Apache Software Foundation (http://www.apache.org/)."
  29  *    Alternately, this acknowledgment may appear in the software itself,
  30  *    if and wherever such third-party acknowledgments normally appear.
  31  *
  32  * 4. The names "Apache" and "Apache Software Foundation" and
  33  *    "Apache BCEL" must not be used to endorse or promote products
  34  *    derived from this software without prior written permission. For
  35  *    written permission, please contact apache@apache.org.
  36  *
  37  * 5. Products derived from this software may not be called "Apache",
  38  *    "Apache BCEL", nor may "Apache" appear in their name, without
  39  *    prior written permission of the Apache Software Foundation.
  40  *
  41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  44  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  52  * SUCH DAMAGE.
  53  * ====================================================================
  54  *
  55  * This software consists of voluntary contributions made by many
  56  * individuals on behalf of the Apache Software Foundation.  For more
  57  * information on the Apache Software Foundation, please see
  58  * <http://www.apache.org/>.
  59  */
  60 
  61 import  com.sun.org.apache.bcel.internal.Constants;
  62 import  com.sun.org.apache.bcel.internal.util.SyntheticRepository;
  63 import  com.sun.org.apache.bcel.internal.util.ClassVector;
  64 import  com.sun.org.apache.bcel.internal.util.ClassQueue;
  65 import  com.sun.org.apache.bcel.internal.generic.Type;
  66 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
  67 
  68 import  java.io.*;
  69 import  java.util.StringTokenizer;
  70 
  71 /**
  72  * Represents a Java class, i.e., the data structures, constant pool,
  73  * fields, methods and commands contained in a Java .class file.
  74  * See <a href="ftp://java.sun.com/docs/specs/">JVM
  75  * specification</a> for details.
  76 
  77  * The intent of this class is to represent a parsed or otherwise existing
  78  * class file.  Those interested in programatically generating classes
  79  * should see the <a href="../generic/ClassGen.html">ClassGen</a> class.
  80 
  81  * @see com.sun.org.apache.bcel.internal.generic.ClassGen
  82  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  83  */
  84 public class JavaClass extends AccessFlags implements Cloneable, Node {
  85   private String       file_name;
  86   private String       package_name;
  87   private String       source_file_name = "<Unknown>";
  88   private int          class_name_index;
  89   private int          superclass_name_index;
  90   private String       class_name;
  91   private String       superclass_name;
  92   private int          major, minor;  // Compiler version
  93   private ConstantPool constant_pool; // Constant pool
  94   private int[]        interfaces;    // implemented interfaces
  95   private String[]     interface_names;
  96   private Field[]      fields;        // Fields, i.e., variables of class
  97   private Method[]     methods;       // methods defined in the class
  98   private Attribute[]  attributes;    // attributes defined in the class
  99   private byte         source = HEAP; // Generated in memory
 100 
 101   public static final byte HEAP = 1;
 102   public static final byte FILE = 2;
 103   public static final byte ZIP  = 3;
 104 
 105   static boolean debug = false; // Debugging on/off
 106   static char    sep   = '/';   // directory separator
 107 
 108   /**
 109    * In cases where we go ahead and create something,
 110    * use the default SyntheticRepository, because we
 111    * don't know any better.
 112    */
 113   private transient com.sun.org.apache.bcel.internal.util.Repository repository =
 114     SyntheticRepository.getInstance();
 115 
 116   /**
 117    * Constructor gets all contents as arguments.
 118    *
 119    * @param class_name_index Index into constant pool referencing a
 120    * ConstantClass that represents this class.
 121    * @param superclass_name_index Index into constant pool referencing a
 122    * ConstantClass that represents this class's superclass.
 123    * @param file_name File name
 124    * @param major Major compiler version
 125    * @param minor Minor compiler version
 126    * @param access_flags Access rights defined by bit flags
 127    * @param constant_pool Array of constants
 128    * @param interfaces Implemented interfaces
 129    * @param fields Class fields
 130    * @param methods Class methods
 131    * @param attributes Class attributes
 132    * @param source Read from file or generated in memory?
 133    */
 134   public JavaClass(int        class_name_index,
 135                    int        superclass_name_index,
 136                    String     file_name,
 137                    int        major,
 138                    int        minor,
 139                    int        access_flags,
 140                    ConstantPool constant_pool,
 141                    int[]      interfaces,
 142                    Field[]      fields,
 143                    Method[]     methods,
 144                    Attribute[]  attributes,
 145                    byte          source)
 146   {
 147     if(interfaces == null) // Allowed for backward compatibility
 148       interfaces = new int[0];
 149     if(attributes == null)
 150       this.attributes = new Attribute[0];
 151     if(fields == null)
 152       fields = new Field[0];
 153     if(methods == null)
 154       methods = new Method[0];
 155 
 156     this.class_name_index      = class_name_index;
 157     this.superclass_name_index = superclass_name_index;
 158     this.file_name             = file_name;
 159     this.major                 = major;
 160     this.minor                 = minor;
 161     this.access_flags          = access_flags;
 162     this.constant_pool         = constant_pool;
 163     this.interfaces            = interfaces;
 164     this.fields                = fields;
 165     this.methods               = methods;
 166     this.attributes            = attributes;
 167     this.source                = source;
 168 
 169     // Get source file name if available
 170     for(int i=0; i < attributes.length; i++) {
 171       if(attributes[i] instanceof SourceFile) {
 172         source_file_name = ((SourceFile)attributes[i]).getSourceFileName();
 173         break;
 174       }
 175     }
 176 
 177     /* According to the specification the following entries must be of type
 178      * `ConstantClass' but we check that anyway via the
 179      * `ConstPool.getConstant' method.
 180      */
 181     class_name = constant_pool.getConstantString(class_name_index,
 182                                                  Constants.CONSTANT_Class);
 183     class_name = Utility.compactClassName(class_name, false);
 184 
 185     int index = class_name.lastIndexOf('.');
 186     if(index < 0)
 187       package_name = "";
 188     else
 189       package_name = class_name.substring(0, index);
 190 
 191     if(superclass_name_index > 0) { // May be zero -> class is java.lang.Object
 192       superclass_name = constant_pool.getConstantString(superclass_name_index,
 193                                                         Constants.CONSTANT_Class);
 194       superclass_name = Utility.compactClassName(superclass_name, false);
 195     }
 196     else
 197       superclass_name = "java.lang.Object";
 198 
 199     interface_names = new String[interfaces.length];
 200     for(int i=0; i < interfaces.length; i++) {
 201       String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
 202       interface_names[i] = Utility.compactClassName(str, false);
 203     }
 204   }
 205 
 206   /**
 207    * Constructor gets all contents as arguments.
 208    *
 209    * @param class_name_index Class name
 210    * @param superclass_name_index Superclass name
 211    * @param file_name File name
 212    * @param major Major compiler version
 213    * @param minor Minor compiler version
 214    * @param access_flags Access rights defined by bit flags
 215    * @param constant_pool Array of constants
 216    * @param interfaces Implemented interfaces
 217    * @param fields Class fields
 218    * @param methods Class methods
 219    * @param attributes Class attributes
 220    */
 221   public JavaClass(int        class_name_index,
 222                    int        superclass_name_index,
 223                    String     file_name,
 224                    int        major,
 225                    int        minor,
 226                    int        access_flags,
 227                    ConstantPool constant_pool,
 228                    int[]      interfaces,
 229                    Field[]      fields,
 230                    Method[]     methods,
 231                    Attribute[]  attributes) {
 232     this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
 233          constant_pool, interfaces, fields, methods, attributes, HEAP);
 234   }
 235 
 236 
 237   /**
 238    * Called by objects that are traversing the nodes of the tree implicitely
 239    * defined by the contents of a Java class. I.e., the hierarchy of methods,
 240    * fields, attributes, etc. spawns a tree of objects.
 241    *
 242    * @param v Visitor object
 243    */
 244   public void accept(Visitor v) {
 245     v.visitJavaClass(this);
 246   }
 247 
 248   /* Print debug information depending on `JavaClass.debug'
 249    */
 250   static final void Debug(String str) {
 251     if(debug)
 252       System.out.println(str);
 253   }
 254 
 255   /**
 256    * Dump class to a file.
 257    *
 258    * @param file Output file
 259    * @throws IOException
 260    */
 261   public void dump(File file) throws IOException
 262   {
 263     String parent = file.getParent();
 264 
 265     if(parent != null) {
 266       File dir = new File(parent);
 267 
 268       if(dir != null)
 269         dir.mkdirs();
 270     }
 271 
 272     dump(new DataOutputStream(new FileOutputStream(file)));
 273   }
 274 
 275   /**
 276    * Dump class to a file named file_name.
 277    *
 278    * @param file_name Output file name
 279    * @exception IOException
 280    */
 281   public void dump(String file_name) throws IOException
 282   {
 283     dump(new File(file_name));
 284   }
 285 
 286   /**
 287    * @return class in binary format
 288    */
 289   public byte[] getBytes() {
 290     ByteArrayOutputStream s  = new ByteArrayOutputStream();
 291     DataOutputStream      ds = new DataOutputStream(s);
 292 
 293     try {
 294       dump(ds);
 295     } catch(IOException e) {
 296       e.printStackTrace();
 297     } finally {
 298       try { ds.close(); } catch(IOException e2) { e2.printStackTrace(); }
 299     }
 300 
 301     return s.toByteArray();
 302   }
 303 
 304   /**
 305    * Dump Java class to output stream in binary format.
 306    *
 307    * @param file Output stream
 308    * @exception IOException
 309    */
 310   public void dump(OutputStream file) throws IOException {
 311     dump(new DataOutputStream(file));
 312   }
 313 
 314   /**
 315    * Dump Java class to output stream in binary format.
 316    *
 317    * @param file Output stream
 318    * @exception IOException
 319    */
 320   public void dump(DataOutputStream file) throws IOException
 321   {
 322     file.writeInt(0xcafebabe);
 323     file.writeShort(minor);
 324     file.writeShort(major);
 325 
 326     constant_pool.dump(file);
 327 
 328     file.writeShort(access_flags);
 329     file.writeShort(class_name_index);
 330     file.writeShort(superclass_name_index);
 331 
 332     file.writeShort(interfaces.length);
 333     for(int i=0; i < interfaces.length; i++)
 334       file.writeShort(interfaces[i]);
 335 
 336     file.writeShort(fields.length);
 337     for(int i=0; i < fields.length; i++)
 338       fields[i].dump(file);
 339 
 340     file.writeShort(methods.length);
 341     for(int i=0; i < methods.length; i++)
 342       methods[i].dump(file);
 343 
 344     if(attributes != null) {
 345       file.writeShort(attributes.length);
 346       for(int i=0; i < attributes.length; i++)
 347         attributes[i].dump(file);
 348     }
 349     else
 350       file.writeShort(0);
 351 
 352     file.close();
 353   }
 354 
 355   /**
 356    * @return Attributes of the class.
 357    */
 358   public Attribute[] getAttributes() { return attributes; }
 359 
 360   /**
 361    * @return Class name.
 362    */
 363   public String getClassName()       { return class_name; }
 364 
 365   /**
 366    * @return Package name.
 367    */
 368   public String getPackageName()       { return package_name; }
 369 
 370   /**
 371    * @return Class name index.
 372    */
 373   public int getClassNameIndex()   { return class_name_index; }
 374 
 375   /**
 376    * @return Constant pool.
 377    */
 378   public ConstantPool getConstantPool() { return constant_pool; }
 379 
 380   /**
 381    * @return Fields, i.e., variables of the class. Like the JVM spec
 382    * mandates for the classfile format, these fields are those specific to
 383    * this class, and not those of the superclass or superinterfaces.
 384    */
 385   public Field[] getFields()         { return fields; }
 386 
 387   /**
 388    * @return File name of class, aka SourceFile attribute value
 389    */
 390   public String getFileName()        { return file_name; }
 391 
 392   /**
 393    * @return Names of implemented interfaces.
 394    */
 395   public String[] getInterfaceNames()  { return interface_names; }
 396 
 397   /**
 398    * @return Indices in constant pool of implemented interfaces.
 399    */
 400   public int[] getInterfaceIndices()     { return interfaces; }
 401 
 402   /**
 403    * @return Major number of class file version.
 404    */
 405   public int  getMajor()           { return major; }
 406 
 407   /**
 408    * @return Methods of the class.
 409    */
 410   public Method[] getMethods()       { return methods; }
 411 
 412   /**
 413    * @return A com.sun.org.apache.bcel.internal.classfile.Method corresponding to
 414    * java.lang.reflect.Method if any
 415    */
 416   public Method getMethod(java.lang.reflect.Method m) {
 417     for(int i = 0; i < methods.length; i++) {
 418       Method method = methods[i];
 419 
 420       if(m.getName().equals(method.getName()) &&
 421          (m.getModifiers() == method.getModifiers()) &&
 422          Type.getSignature(m).equals(method.getSignature())) {
 423         return method;
 424       }
 425     }
 426 
 427     return null;
 428   }
 429 
 430   /**
 431    * @return Minor number of class file version.
 432    */
 433   public int  getMinor()           { return minor; }
 434 
 435   /**
 436    * @return sbsolute path to file where this class was read from
 437    */
 438   public String getSourceFileName()  { return source_file_name; }
 439 
 440   /**
 441    * @return Superclass name.
 442    */
 443   public String getSuperclassName()  { return superclass_name; }
 444 
 445   /**
 446    * @return Class name index.
 447    */
 448   public int getSuperclassNameIndex() { return superclass_name_index; }
 449 
 450   static {
 451     // Debugging ... on/off
 452     String debug = null, sep = null;
 453 
 454     try {
 455       debug = SecuritySupport.getSystemProperty("JavaClass.debug");
 456       // Get path separator either / or \ usually
 457       sep = SecuritySupport.getSystemProperty("file.separator");
 458     }
 459     catch (SecurityException e) {
 460         // falls through
 461     }
 462 
 463     if(debug != null)
 464       JavaClass.debug = Boolean.parseBoolean(debug);
 465 
 466     if(sep != null)
 467       try {
 468         JavaClass.sep = sep.charAt(0);
 469       } catch(StringIndexOutOfBoundsException e) {} // Never reached
 470   }
 471 
 472   /**
 473    * @param attributes .
 474    */
 475   public void setAttributes(Attribute[] attributes) {
 476     this.attributes = attributes;
 477   }
 478 
 479   /**
 480    * @param class_name .
 481    */
 482   public void setClassName(String class_name) {
 483     this.class_name = class_name;
 484   }
 485 
 486   /**
 487    * @param class_name_index .
 488    */
 489   public void setClassNameIndex(int class_name_index) {
 490     this.class_name_index = class_name_index;
 491   }
 492 
 493   /**
 494    * @param constant_pool .
 495    */
 496   public void setConstantPool(ConstantPool constant_pool) {
 497     this.constant_pool = constant_pool;
 498   }
 499 
 500   /**
 501    * @param fields .
 502    */
 503   public void setFields(Field[] fields) {
 504     this.fields = fields;
 505   }
 506 
 507   /**
 508    * Set File name of class, aka SourceFile attribute value
 509    */
 510   public void setFileName(String file_name) {
 511     this.file_name = file_name;
 512   }
 513 
 514   /**
 515    * @param interface_names .
 516    */
 517   public void setInterfaceNames(String[] interface_names) {
 518     this.interface_names = interface_names;
 519   }
 520 
 521   /**
 522    * @param interfaces .
 523    */
 524   public void setInterfaces(int[] interfaces) {
 525     this.interfaces = interfaces;
 526   }
 527 
 528   /**
 529    * @param major .
 530    */
 531   public void setMajor(int major) {
 532     this.major = major;
 533   }
 534 
 535   /**
 536    * @param methods .
 537    */
 538   public void setMethods(Method[] methods) {
 539     this.methods = methods;
 540   }
 541 
 542   /**
 543    * @param minor .
 544    */
 545   public void setMinor(int minor) {
 546     this.minor = minor;
 547   }
 548 
 549   /**
 550    * Set absolute path to file this class was read from.
 551    */
 552   public void setSourceFileName(String source_file_name) {
 553     this.source_file_name = source_file_name;
 554   }
 555 
 556   /**
 557    * @param superclass_name .
 558    */
 559   public void setSuperclassName(String superclass_name) {
 560     this.superclass_name = superclass_name;
 561   }
 562 
 563   /**
 564    * @param superclass_name_index .
 565    */
 566   public void setSuperclassNameIndex(int superclass_name_index) {
 567     this.superclass_name_index = superclass_name_index;
 568   }
 569 
 570   /**
 571    * @return String representing class contents.
 572    */
 573   public String toString() {
 574     String access = Utility.accessToString(access_flags, true);
 575     access = access.equals("")? "" : (access + " ");
 576 
 577     StringBuffer buf = new StringBuffer(access +
 578                                         Utility.classOrInterface(access_flags) +
 579                                         " " +
 580                                         class_name + " extends " +
 581                                         Utility.compactClassName(superclass_name,
 582                                                                  false) + '\n');
 583     int size = interfaces.length;
 584 
 585     if(size > 0) {
 586       buf.append("implements\t\t");
 587 
 588       for(int i=0; i < size; i++) {
 589         buf.append(interface_names[i]);
 590         if(i < size - 1)
 591           buf.append(", ");
 592       }
 593 
 594       buf.append('\n');
 595     }
 596 
 597     buf.append("filename\t\t" + file_name + '\n');
 598     buf.append("compiled from\t\t" + source_file_name + '\n');
 599     buf.append("compiler version\t" + major + "." + minor + '\n');
 600     buf.append("access flags\t\t" + access_flags + '\n');
 601     buf.append("constant pool\t\t" + constant_pool.getLength() + " entries\n");
 602     buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n");
 603 
 604     if(attributes.length > 0) {
 605       buf.append("\nAttribute(s):\n");
 606       for(int i=0; i < attributes.length; i++)
 607         buf.append(indent(attributes[i]));
 608     }
 609 
 610     if(fields.length > 0) {
 611       buf.append("\n" + fields.length + " fields:\n");
 612       for(int i=0; i < fields.length; i++)
 613         buf.append("\t" + fields[i] + '\n');
 614     }
 615 
 616     if(methods.length > 0) {
 617       buf.append("\n" + methods.length + " methods:\n");
 618       for(int i=0; i < methods.length; i++)
 619         buf.append("\t" + methods[i] + '\n');
 620     }
 621 
 622     return buf.toString();
 623   }
 624 
 625   private static final String indent(Object obj) {
 626     StringTokenizer tok = new StringTokenizer(obj.toString(), "\n");
 627     StringBuffer buf = new StringBuffer();
 628 
 629     while(tok.hasMoreTokens())
 630       buf.append("\t" + tok.nextToken() + "\n");
 631 
 632     return buf.toString();
 633   }
 634 
 635   /**
 636    * @return deep copy of this class
 637    */
 638   public JavaClass copy() {
 639     JavaClass c = null;
 640 
 641     try {
 642       c = (JavaClass)clone();
 643     } catch(CloneNotSupportedException e) {}
 644 
 645     c.constant_pool   = constant_pool.copy();
 646     c.interfaces      = (int[])interfaces.clone();
 647     c.interface_names = (String[])interface_names.clone();
 648 
 649     c.fields = new Field[fields.length];
 650     for(int i=0; i < fields.length; i++)
 651       c.fields[i] = fields[i].copy(c.constant_pool);
 652 
 653     c.methods = new Method[methods.length];
 654     for(int i=0; i < methods.length; i++)
 655       c.methods[i] = methods[i].copy(c.constant_pool);
 656 
 657     c.attributes = new Attribute[attributes.length];
 658     for(int i=0; i < attributes.length; i++)
 659       c.attributes[i] = attributes[i].copy(c.constant_pool);
 660 
 661     return c;
 662   }
 663 
 664   public final boolean isSuper() {
 665     return (access_flags & Constants.ACC_SUPER) != 0;
 666   }
 667 
 668   public final boolean isClass() {
 669     return (access_flags & Constants.ACC_INTERFACE) == 0;
 670   }
 671 
 672   /** @return returns either HEAP (generated), FILE, or ZIP
 673    */
 674   public final byte getSource() {
 675     return source;
 676   }
 677 
 678   /********************* New repository functionality *********************/
 679 
 680   /**
 681    * Gets the ClassRepository which holds its definition. By default
 682    * this is the same as SyntheticRepository.getInstance();
 683    */
 684   public com.sun.org.apache.bcel.internal.util.Repository getRepository() {
 685     return repository;
 686   }
 687 
 688   /**
 689    * Sets the ClassRepository which loaded the JavaClass.
 690    * Should be called immediately after parsing is done.
 691    */
 692   public void setRepository(com.sun.org.apache.bcel.internal.util.Repository repository) {
 693     this.repository = repository;
 694   }
 695 
 696   /** Equivalent to runtime "instanceof" operator.
 697    *
 698    * @return true if this JavaClass is derived from teh super class
 699    */
 700   public final boolean instanceOf(JavaClass super_class) {
 701     if(this.equals(super_class))
 702       return true;
 703 
 704     JavaClass[] super_classes = getSuperClasses();
 705 
 706     for(int i=0; i < super_classes.length; i++) {
 707       if(super_classes[i].equals(super_class)) {
 708         return true;
 709       }
 710     }
 711 
 712     if(super_class.isInterface()) {
 713       return implementationOf(super_class);
 714     }
 715 
 716     return false;
 717   }
 718 
 719   /**
 720    * @return true, if clazz is an implementation of interface inter
 721    */
 722   public boolean implementationOf(JavaClass inter) {
 723     if(!inter.isInterface()) {
 724       throw new IllegalArgumentException(inter.getClassName() + " is no interface");
 725     }
 726 
 727     if(this.equals(inter)) {
 728       return true;
 729     }
 730 
 731     JavaClass[] super_interfaces = getAllInterfaces();
 732 
 733     for(int i=0; i < super_interfaces.length; i++) {
 734       if(super_interfaces[i].equals(inter)) {
 735         return true;
 736       }
 737     }
 738 
 739     return false;
 740   }
 741 
 742   /**
 743    * @return the superclass for this JavaClass object, or null if this
 744    * is java.lang.Object
 745    */
 746   public JavaClass getSuperClass() {
 747     if("java.lang.Object".equals(getClassName())) {
 748       return null;
 749     }
 750 
 751     try {
 752       return repository.loadClass(getSuperclassName());
 753     } catch(ClassNotFoundException e) {
 754       System.err.println(e);
 755       return null;
 756     }
 757   }
 758 
 759   /**
 760    * @return list of super classes of this class in ascending order, i.e.,
 761    * java.lang.Object is always the last element
 762    */
 763   public JavaClass[] getSuperClasses() {
 764     JavaClass   clazz = this;
 765     ClassVector vec   = new ClassVector();
 766 
 767     for(clazz = clazz.getSuperClass(); clazz != null;
 768         clazz = clazz.getSuperClass())
 769     {
 770       vec.addElement(clazz);
 771     }
 772 
 773     return vec.toArray();
 774   }
 775 
 776   /**
 777    * Get interfaces directly implemented by this JavaClass.
 778    */
 779   public JavaClass[] getInterfaces() {
 780     String[]    interfaces = getInterfaceNames();
 781     JavaClass[] classes    = new JavaClass[interfaces.length];
 782 
 783     try {
 784       for(int i = 0; i < interfaces.length; i++) {
 785         classes[i] = repository.loadClass(interfaces[i]);
 786       }
 787     } catch(ClassNotFoundException e) {
 788       System.err.println(e);
 789       return null;
 790     }
 791 
 792     return classes;
 793   }
 794 
 795   /**
 796    * Get all interfaces implemented by this JavaClass (transitively).
 797    */
 798   public JavaClass[] getAllInterfaces() {
 799     ClassQueue  queue = new ClassQueue();
 800     ClassVector vec   = new ClassVector();
 801 
 802     queue.enqueue(this);
 803 
 804     while(!queue.empty()) {
 805       JavaClass clazz = queue.dequeue();
 806 
 807       JavaClass   souper     = clazz.getSuperClass();
 808       JavaClass[] interfaces = clazz.getInterfaces();
 809 
 810       if(clazz.isInterface()) {
 811         vec.addElement(clazz);
 812       } else {
 813         if(souper != null) {
 814           queue.enqueue(souper);
 815         }
 816       }
 817 
 818       for(int i = 0; i < interfaces.length; i++) {
 819         queue.enqueue(interfaces[i]);
 820       }
 821     }
 822 
 823     return vec.toArray();
 824   }
 825 }