KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > bcel > internal > classfile > JavaClass


1 package com.sun.org.apache.bcel.internal.classfile;
2
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2001 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgment may appear in the software itself,
26  * if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation" and
29  * "Apache BCEL" must not be used to endorse or promote products
30  * derived from this software without prior written permission. For
31  * written permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache",
34  * "Apache BCEL", nor may "Apache" appear in their name, without
35  * prior written permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56
57 import com.sun.org.apache.bcel.internal.Constants;
58 import com.sun.org.apache.bcel.internal.Repository;
59 import java.io.*;
60 import java.util.StringTokenizer JavaDoc;
61
62 /**
63  * Represents a Java class, i.e., the data structures, constant pool,
64  * fields, methods and commands contained in a Java .class file.
65  * See <a HREF="ftp://java.sun.com/docs/specs/">JVM
66  * specification</a> for details.
67  *
68  * @version $Id: JavaClass.java,v 1.1 2003/12/12 08:57:41 rameshm Exp $
69  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
70  */

71 public class JavaClass extends AccessFlags implements Cloneable JavaDoc, Node {
72   private String JavaDoc file_name;
73   private String JavaDoc package_name;
74   private String JavaDoc source_file_name = "<Unknown>";
75   private int class_name_index;
76   private int superclass_name_index;
77   private String JavaDoc class_name;
78   private String JavaDoc superclass_name;
79   private int major, minor; // Compiler version
80
private ConstantPool constant_pool; // Constant pool
81
private int[] interfaces; // implemented interfaces
82
private String JavaDoc[] interface_names;
83   private Field[] fields; // Fields, i.e., variables of class
84
private Method[] methods; // methods defined in the class
85
private Attribute[] attributes; // attributes defined in the class
86
private byte source = HEAP; // Generated in memory
87

88   public static final byte HEAP = 1;
89   public static final byte FILE = 2;
90   public static final byte ZIP = 3;
91
92   static boolean debug = false; // Debugging on/off
93
static char sep = '/'; // directory separator
94

95   /**
96    * Constructor gets all contents as arguments.
97    *
98    * @param class_name Class name
99    * @param superclass_name Superclass name
100    * @param file_name File name
101    * @param major Major compiler version
102    * @param minor Minor compiler version
103    * @param access_flags Access rights defined by bit flags
104    * @param constant_pool Array of constants
105    * @param interfaces Implemented interfaces
106    * @param fields Class fields
107    * @param methods Class methods
108    * @param attributes Class attributes
109    * @param source Read from file or generated in memory?
110    */

111   public JavaClass(int class_name_index,
112            int superclass_name_index,
113            String JavaDoc file_name,
114            int major,
115            int minor,
116            int access_flags,
117            ConstantPool constant_pool,
118            int[] interfaces,
119            Field[] fields,
120            Method[] methods,
121            Attribute[] attributes,
122            byte source)
123   {
124     if(interfaces == null) // Allowed for backward compatibility
125
interfaces = new int[0];
126     if(attributes == null)
127       this.attributes = new Attribute[0];
128     if(fields == null)
129       fields = new Field[0];
130     if(methods == null)
131       methods = new Method[0];
132
133     this.class_name_index = class_name_index;
134     this.superclass_name_index = superclass_name_index;
135     this.file_name = file_name;
136     this.major = major;
137     this.minor = minor;
138     this.access_flags = access_flags;
139     this.constant_pool = constant_pool;
140     this.interfaces = interfaces;
141     this.fields = fields;
142     this.methods = methods;
143     this.attributes = attributes;
144     this.source = source;
145
146     // Get source file name if available
147
for(int i=0; i < attributes.length; i++) {
148       if(attributes[i] instanceof SourceFile) {
149     source_file_name = ((SourceFile)attributes[i]).getSourceFileName();
150     break;
151       }
152     }
153     
154     // Get class name and superclass name
155
ConstantUtf8 name;
156
157     /* According to the specification the following entries must be of type
158      * `ConstantClass' but we check that anyway via the
159      * `ConstPool.getConstant' method.
160      */

161     class_name = constant_pool.getConstantString(class_name_index,
162                          Constants.CONSTANT_Class);
163     class_name = Utility.compactClassName(class_name, false);
164
165     int index = class_name.lastIndexOf('.');
166     if(index < 0)
167       package_name = "";
168     else
169       package_name = class_name.substring(0, index);
170
171     if(superclass_name_index > 0) { // May be zero -> class is java.lang.Object
172
superclass_name = constant_pool.getConstantString(superclass_name_index,
173                             Constants.CONSTANT_Class);
174       superclass_name = Utility.compactClassName(superclass_name, false);
175     }
176     else
177       superclass_name = "java.lang.Object";
178
179     interface_names = new String JavaDoc[interfaces.length];
180     for(int i=0; i < interfaces.length; i++) {
181       String JavaDoc str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
182       interface_names[i] = Utility.compactClassName(str, false);
183     }
184   }
185
186   /**
187    * Constructor gets all contents as arguments.
188    *
189    * @param class_name Class name
190    * @param superclass_name Superclass name
191    * @param file_name File name
192    * @param major Major compiler version
193    * @param minor Minor compiler version
194    * @param access_flags Access rights defined by bit flags
195    * @param constant_pool Array of constants
196    * @param interfaces Implemented interfaces
197    * @param fields Class fields
198    * @param methods Class methods
199    * @param attributes Class attributes
200    */

201   public JavaClass(int class_name_index,
202            int superclass_name_index,
203            String JavaDoc file_name,
204            int major,
205            int minor,
206            int access_flags,
207            ConstantPool constant_pool,
208            int[] interfaces,
209            Field[] fields,
210            Method[] methods,
211            Attribute[] attributes) {
212     this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
213      constant_pool, interfaces, fields, methods, attributes, HEAP);
214   }
215
216       
217   /**
218    * Called by objects that are traversing the nodes of the tree implicitely
219    * defined by the contents of a Java class. I.e., the hierarchy of methods,
220    * fields, attributes, etc. spawns a tree of objects.
221    *
222    * @param v Visitor object
223    */

224   public void accept(Visitor v) {
225     v.visitJavaClass(this);
226   }
227
228   /* Print debug information depending on `JavaClass.debug'
229    */

230   static final void Debug(String JavaDoc str) {
231     if(debug)
232       System.out.println(str);
233   }
234
235   /**
236    * Dump class to a file.
237    *
238    * @param file Output file
239    * @throw IOException
240    */

241   public void dump(File file) throws IOException
242   {
243     String JavaDoc parent = file.getParent();
244
245     if(parent != null) {
246       File dir = new File(parent);
247       
248       if(dir != null)
249     dir.mkdirs();
250     }
251
252     dump(new DataOutputStream(new FileOutputStream(file)));
253   }
254
255   /**
256    * Dump class to a file named file_name.
257    *
258    * @param file_name Output file name
259    * @exception IOException
260    */

261   public void dump(String JavaDoc file_name) throws IOException
262   {
263     dump(new File(file_name));
264   }
265
266   /**
267    * @return class in binary format
268    */

269   public byte[] getBytes() {
270     ByteArrayOutputStream s = new ByteArrayOutputStream();
271     DataOutputStream ds = new DataOutputStream(s);
272
273     try {
274       dump(ds);
275       ds.close();
276     } catch(IOException e) { e.printStackTrace(); }
277
278     return s.toByteArray();
279   }
280
281   /**
282    * Dump Java class to output stream in binary format.
283    *
284    * @param file Output stream
285    * @exception IOException
286    */

287   public void dump(OutputStream file) throws IOException {
288     dump(new DataOutputStream(file));
289   }
290
291   /**
292    * Dump Java class to output stream in binary format.
293    *
294    * @param file Output stream
295    * @exception IOException
296    */

297   public void dump(DataOutputStream file) throws IOException
298   {
299     file.writeInt(0xcafebabe);
300     file.writeShort(minor);
301     file.writeShort(major);
302
303     constant_pool.dump(file);
304     
305     file.writeShort(access_flags);
306     file.writeShort(class_name_index);
307     file.writeShort(superclass_name_index);
308
309     file.writeShort(interfaces.length);
310     for(int i=0; i < interfaces.length; i++)
311       file.writeShort(interfaces[i]);
312
313     file.writeShort(fields.length);
314     for(int i=0; i < fields.length; i++)
315       fields[i].dump(file);
316
317     file.writeShort(methods.length);
318     for(int i=0; i < methods.length; i++)
319       methods[i].dump(file);
320
321     if(attributes != null) {
322       file.writeShort(attributes.length);
323       for(int i=0; i < attributes.length; i++)
324     attributes[i].dump(file);
325     }
326     else
327       file.writeShort(0);
328
329     file.close();
330   }
331
332   /**
333    * @return Attributes of the class.
334    */

335   public Attribute[] getAttributes() { return attributes; }
336
337   /**
338    * @return Class name.
339    */

340   public String JavaDoc getClassName() { return class_name; }
341
342   /**
343    * @return Package name.
344    */

345   public String JavaDoc getPackageName() { return package_name; }
346
347   /**
348    * @return Class name index.
349    */

350   public int getClassNameIndex() { return class_name_index; }
351
352   /**
353    * @return Constant pool.
354    */

355   public ConstantPool getConstantPool() { return constant_pool; }
356
357   /**
358    * @return Fields, i.e., variables of the class.
359    */

360   public Field[] getFields() { return fields; }
361   /**
362    * @return File name of class, aka SourceFile attribute value
363    */

364   public String JavaDoc getFileName() { return file_name; }
365   /**
366    * @return Names of implemented interfaces.
367    */

368   public String JavaDoc[] getInterfaceNames() { return interface_names; }
369   /**
370    * @return Implemented interfaces.
371    */

372   public int[] getInterfaces() { return interfaces; }
373   /**
374    * @return Major number of compiler version.
375    */

376   public int getMajor() { return major; }
377   /**
378    * @return Methods of the class.
379    */

380   public Method[] getMethods() { return methods; }
381   /**
382    * @return Minor number of compiler version.
383    */

384   public int getMinor() { return minor; }
385
386   /**
387    * @return sbsolute path to file where this class was read from
388    */

389   public String JavaDoc getSourceFileName() { return source_file_name; }
390
391   /**
392    * @return Superclass name.
393    */

394   public String JavaDoc getSuperclassName() { return superclass_name; }
395   /**
396    * @return Class name index.
397    */

398   public int getSuperclassNameIndex() { return superclass_name_index; }
399
400   static {
401     // Debugging ... on/off
402
//String debug = System.getProperty("JavaClass.debug");
403

404     //if(debug != null)
405
// JavaClass.debug = new Boolean(debug).booleanValue();
406

407     // Get path separator either / or \ usually
408
JavaClass.sep = java.io.File.separatorChar;
409   }
410
411   /**
412    * @param attributes.
413    */

414   public void setAttributes(Attribute[] attributes) {
415     this.attributes = attributes;
416   }
417   /**
418    * @param class_name.
419    */

420   public void setClassName(String JavaDoc class_name) {
421     this.class_name = class_name;
422   }
423   /**
424    * @param class_name_index.
425    */

426   public void setClassNameIndex(int class_name_index) {
427     this.class_name_index = class_name_index;
428   }
429   /**
430    * @param constant_pool.
431    */

432   public void setConstantPool(ConstantPool constant_pool) {
433     this.constant_pool = constant_pool;
434   }
435   /**
436    * @param fields.
437    */

438   public void setFields(Field[] fields) {
439     this.fields = fields;
440   }
441   /**
442    * Set File name of class, aka SourceFile attribute value
443    */

444   public void setFileName(String JavaDoc file_name) {
445     this.file_name = file_name;
446   }
447   /**
448    * @param interface_names.
449    */

450   public void setInterfaceNames(String JavaDoc[] interface_names) {
451     this.interface_names = interface_names;
452   }
453   /**
454    * @param interfaces.
455    */

456   public void setInterfaces(int[] interfaces) {
457     this.interfaces = interfaces;
458   }
459   /**
460    * @param major.
461    */

462   public void setMajor(int major) {
463     this.major = major;
464   }
465   /**
466    * @param methods.
467    */

468   public void setMethods(Method[] methods) {
469     this.methods = methods;
470   }
471   /**
472    * @param minor.
473    */

474   public void setMinor(int minor) {
475     this.minor = minor;
476   }
477   /**
478    * Set absolute path to file this class was read from.
479    */

480   public void setSourceFileName(String JavaDoc source_file_name) {
481     this.source_file_name = source_file_name;
482   }
483   /**
484    * @param superclass_name.
485    */

486   public void setSuperclassName(String JavaDoc superclass_name) {
487     this.superclass_name = superclass_name;
488   }
489   /**
490    * @param superclass_name_index.
491    */

492   public void setSuperclassNameIndex(int superclass_name_index) {
493     this.superclass_name_index = superclass_name_index;
494   }
495   /**
496    * @return String representing class contents.
497    */

498   public String JavaDoc toString() {
499     String JavaDoc access = Utility.accessToString(access_flags, true);
500     access = access.equals("")? "" : (access + " ");
501
502     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(access +
503                     Utility.classOrInterface(access_flags) +
504                     " " +
505                     class_name + " extends " +
506                     Utility.compactClassName(superclass_name,
507                                  false) + '\n');
508     int size = interfaces.length;
509
510     if(size > 0) {
511       buf.append("implements\t\t");
512
513       for(int i=0; i < size; i++) {
514     buf.append(interface_names[i]);
515     if(i < size - 1)
516       buf.append(", ");
517       }
518
519       buf.append('\n');
520     }
521
522     buf.append("filename\t\t" + file_name + '\n');
523     buf.append("compiled from\t\t" + source_file_name + '\n');
524     buf.append("compiler version\t" + major + "." + minor + '\n');
525     buf.append("access flags\t\t" + access_flags + '\n');
526     buf.append("constant pool\t\t" + constant_pool.getLength() + " entries\n");
527     buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n");
528
529     if(attributes.length > 0) {
530       buf.append("\nAttribute(s):\n");
531       for(int i=0; i < attributes.length; i++)
532     buf.append(indent(attributes[i]));
533     }
534
535     if(fields.length > 0) {
536       buf.append("\n" + fields.length + " fields:\n");
537       for(int i=0; i < fields.length; i++)
538     buf.append("\t" + fields[i] + '\n');
539     }
540
541     if(methods.length > 0) {
542       buf.append("\n" + methods.length + " methods:\n");
543       for(int i=0; i < methods.length; i++)
544     buf.append("\t" + methods[i] + '\n');
545     }
546
547     return buf.toString();
548   }
549
550   private static final String JavaDoc indent(Object JavaDoc obj) {
551     StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(obj.toString(), "\n");
552     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
553
554     while(tok.hasMoreTokens())
555       buf.append("\t" + tok.nextToken() + "\n");
556
557     return buf.toString();
558   }
559
560   /**
561    * @return deep copy of this class
562    */

563   public JavaClass copy() {
564     JavaClass c = null;
565
566     try {
567       c = (JavaClass)clone();
568     } catch(CloneNotSupportedException JavaDoc e) {}
569
570     c.constant_pool = constant_pool.copy();
571     c.interfaces = (int[])interfaces.clone();
572     c.interface_names = (String JavaDoc[])interface_names.clone();
573
574     c.fields = new Field[fields.length];
575     for(int i=0; i < fields.length; i++)
576       c.fields[i] = fields[i].copy(c.constant_pool);
577
578     c.methods = new Method[methods.length];
579     for(int i=0; i < methods.length; i++)
580       c.methods[i] = methods[i].copy(c.constant_pool);
581
582     c.attributes = new Attribute[attributes.length];
583     for(int i=0; i < attributes.length; i++)
584       c.attributes[i] = attributes[i].copy(c.constant_pool);
585
586     return c;
587   }
588
589   public final boolean instanceOf(JavaClass super_class) {
590     return Repository.instanceOf(this, super_class);
591   }
592
593   public final boolean isSuper() {
594     return (access_flags & Constants.ACC_SUPER) != 0;
595   }
596
597   public final boolean isClass() {
598     return (access_flags & Constants.ACC_INTERFACE) == 0;
599   }
600
601   /** @return returns either HEAP (generated), FILE, or ZIP
602    */

603   public final byte getSource() {
604     return source;
605   }
606 }
607
Popular Tags