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