KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.*;
59 import java.util.zip.*;
60
61 /**
62  * Wrapper class that parses a given Java .class file. The method
63  * <A href ="#parse">parse</A> returns a
64  * <A href ="com.sun.org.apache.bcel.internal.classfile.JavaClass.html">
65  * JavaClass</A> object on success. When an I/O error or an
66  * inconsistency occurs an appropiate exception is propagated back
67  * to the caller.
68  *
69  * The structure and the names comply, except for a few conveniences,
70  * exactly with the <A HREF="ftp://java.sun.com/docs/specs/vmspec.ps">
71  * JVM specification 1.0</a>. See this paper for
72  * further details about the structure of a bytecode file.
73  *
74  * @version $Id: ClassParser.java,v 1.1.1.1 2001/10/29 19:59:57 jvanzyl Exp $
75  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
76  */

77 public final class ClassParser {
78   private DataInputStream file;
79   private ZipFile zip;
80   private String JavaDoc file_name;
81   private int class_name_index, superclass_name_index;
82   private int major, minor; // Compiler version
83
private int access_flags; // Access rights of parsed class
84
private int[] interfaces; // Names of implemented interfaces
85
private ConstantPool constant_pool; // collection of constants
86
private Field[] fields; // class fields, i.e., its variables
87
private Method[] methods; // methods defined in the class
88
private Attribute[] attributes; // attributes defined in the class
89
private boolean is_zip; // Loaded from zip file
90

91   private static final int BUFSIZE = 8192;
92
93   /**
94    * Parse class from the given stream.
95    *
96    * @param file Input stream
97    * @param file_name File name
98    */

99   public ClassParser(InputStream file, String JavaDoc file_name) {
100     this.file_name = file_name;
101
102     String JavaDoc clazz = file.getClass().getName(); // Not a very clean solution ...
103
is_zip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar.");
104
105     if(file instanceof DataInputStream) // Is already a data stream
106
this.file = (DataInputStream)file;
107     else
108       this.file = new DataInputStream(new BufferedInputStream(file, BUFSIZE));
109   }
110
111   /** Parse class from given .class file.
112    *
113    * @param file_name file name
114    * @throw IOException
115    */

116   public ClassParser(String JavaDoc file_name) throws IOException
117   {
118     is_zip = false;
119     this.file_name = file_name;
120     file = new DataInputStream(new BufferedInputStream
121                    (new FileInputStream(file_name), BUFSIZE));
122   }
123
124   /** Parse class from given .class file in a ZIP-archive
125    *
126    * @param file_name file name
127    * @throw IOException
128    */

129   public ClassParser(String JavaDoc zip_file, String JavaDoc file_name) throws IOException
130   {
131     is_zip = true;
132     zip = new ZipFile(zip_file);
133     ZipEntry entry = zip.getEntry(file_name);
134            
135     this.file_name = file_name;
136
137     file = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry),
138                                BUFSIZE));
139   }
140
141   /**
142    * Parse the given Java class file and return an object that represents
143    * the contained data, i.e., constants, methods, fields and commands.
144    * A <em>ClassFormatError</em> is raised, if the file is not a valid
145    * .class file. (This does not include verification of the byte code as it
146    * is performed by the java interpreter).
147    *
148    * @return Class object representing the parsed class file
149    * @throw IOException
150    * @throw ClassFormatError
151    */

152   public JavaClass parse() throws IOException, ClassFormatError JavaDoc
153   {
154     /****************** Read headers ********************************/
155     // Check magic tag of class file
156
readID();
157
158     // Get compiler version
159
readVersion();
160
161     /****************** Read constant pool and related **************/
162     // Read constant pool entries
163
readConstantPool();
164     
165     // Get class information
166
readClassInfo();
167
168     // Get interface information, i.e., implemented interfaces
169
readInterfaces();
170
171     /****************** Read class fields and methods ***************/
172     // Read class fields, i.e., the variables of the class
173
readFields();
174
175     // Read class methods, i.e., the functions in the class
176
readMethods();
177
178     // Read class attributes
179
readAttributes();
180
181     // Check for unknown variables
182
//Unknown[] u = Unknown.getUnknownAttributes();
183
//for(int i=0; i < u.length; i++)
184
// System.err.println("WARNING: " + u[i]);
185

186     // Everything should have been read now
187
// if(file.available() > 0) {
188
// int bytes = file.available();
189
// byte[] buf = new byte[bytes];
190
// file.read(buf);
191

192     // if(!(is_zip && (buf.length == 1))) {
193
// System.err.println("WARNING: Trailing garbage at end of " + file_name);
194
// System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf));
195
// }
196
// }
197

198     // Read everything of interest, so close the file
199
file.close();
200     if(zip != null)
201       zip.close();
202
203     // Return the information we have gathered in a new object
204
return new JavaClass(class_name_index, superclass_name_index,
205              file_name, major, minor, access_flags,
206              constant_pool, interfaces, fields,
207              methods, attributes, is_zip? JavaClass.ZIP : JavaClass.FILE);
208   }
209
210   /**
211    * Read information about the attributes of the attributes of the class.
212    * @throw IOException
213    * @throw ClassFormatError
214    */

215   private final void readAttributes() throws IOException, ClassFormatError JavaDoc
216   {
217     int attributes_count;
218
219     attributes_count = file.readUnsignedShort();
220     attributes = new Attribute[attributes_count];
221
222     for(int i=0; i < attributes_count; i++)
223       attributes[i] = Attribute.readAttribute(file, constant_pool);
224   }
225
226   /**
227    * Read information about the class and its super class.
228    * @throw IOException
229    * @throw ClassFormatError
230    */

231   private final void readClassInfo() throws IOException, ClassFormatError JavaDoc
232   {
233     access_flags = file.readUnsignedShort();
234
235     /* Interfaces are implicitely abstract, the flag should be set
236      * according to the JVM specification.
237      */

238     if((access_flags & Constants.ACC_INTERFACE) != 0)
239       access_flags |= Constants.ACC_ABSTRACT;
240
241     if(((access_flags & Constants.ACC_ABSTRACT) != 0) &&
242        ((access_flags & Constants.ACC_FINAL) != 0 ))
243       throw new ClassFormatError JavaDoc("Class can't be both final and abstract");
244
245     class_name_index = file.readUnsignedShort();
246     superclass_name_index = file.readUnsignedShort();
247   }
248   /**
249    * Read constant pool entries.
250    * @throw IOException
251    * @throw ClassFormatError
252    */

253   private final void readConstantPool() throws IOException, ClassFormatError JavaDoc
254   {
255     constant_pool = new ConstantPool(file);
256   }
257
258   /**
259    * Read information about the fields of the class, i.e., its variables.
260    * @throw IOException
261    * @throw ClassFormatError
262    */

263   private final void readFields() throws IOException, ClassFormatError JavaDoc
264   {
265     int fields_count;
266
267     fields_count = file.readUnsignedShort();
268     fields = new Field[fields_count];
269
270     for(int i=0; i < fields_count; i++)
271       fields[i] = new Field(file, constant_pool);
272   }
273
274   /******************** Private utility methods **********************/
275
276   /**
277    * Check whether the header of the file is ok.
278    * Of course, this has to be the first action on successive file reads.
279    * @throw IOException
280    * @throw ClassFormatError
281    */

282   private final void readID() throws IOException, ClassFormatError JavaDoc
283   {
284     int magic = 0xCAFEBABE;
285
286     if(file.readInt() != magic)
287       throw new ClassFormatError JavaDoc(file_name + " is not a Java .class file");
288   }
289   /**
290    * Read information about the interfaces implemented by this class.
291    * @throw IOException
292    * @throw ClassFormatError
293    */

294   private final void readInterfaces() throws IOException, ClassFormatError JavaDoc
295   {
296     int interfaces_count;
297
298     interfaces_count = file.readUnsignedShort();
299     interfaces = new int[interfaces_count];
300
301     for(int i=0; i < interfaces_count; i++)
302       interfaces[i] = file.readUnsignedShort();
303   }
304   /**
305    * Read information about the methods of the class.
306    * @throw IOException
307    * @throw ClassFormatError
308    */

309   private final void readMethods() throws IOException, ClassFormatError JavaDoc
310   {
311     int methods_count;
312
313     methods_count = file.readUnsignedShort();
314     methods = new Method[methods_count];
315
316     for(int i=0; i < methods_count; i++)
317       methods[i] = new Method(file, constant_pool);
318   }
319   /**
320    * Read major and minor version of compiler which created the file.
321    * @throw IOException
322    * @throw ClassFormatError
323    */

324   private final void readVersion() throws IOException, ClassFormatError JavaDoc
325   {
326     minor = file.readUnsignedShort();
327     major = file.readUnsignedShort();
328   }
329 }
330
Popular Tags