1 package org.apache.bcel.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 org.apache.bcel.Constants;
58 import java.io.*;
59 import java.util.zip.*;
60
61 /***
62 * Wrapper class that parses a given Java .class file. The method <A
63 * href ="#parse">parse</A> returns a <A href ="JavaClass.html">
64 * JavaClass</A> object on success. When an I/O error or an
65 * inconsistency occurs an appropiate exception is propagated back to
66 * the caller.
67 *
68 * The structure and the names comply, except for a few conveniences,
69 * exactly with the <A href="ftp://java.sun.com/docs/specs/vmspec.ps">
70 * JVM specification 1.0</a>. See this paper for
71 * further details about the structure of a bytecode file.
72 *
73 * @version $Id: ClassParser.java,v 1.5 2002/08/09 13:09:31 mdahm Exp $
74 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
75 */
76 public final class ClassParser {
77 private DataInputStream file;
78 private ZipFile zip;
79 private String file_name;
80 private int class_name_index, superclass_name_index;
81 private int major, minor; // Compiler version
82 private int access_flags; // Access rights of parsed class
83 private int[] interfaces; // Names of implemented interfaces
84 private ConstantPool constant_pool; // collection of constants
85 private Field[] fields; // class fields, i.e., its variables
86 private Method[] methods; // methods defined in the class
87 private Attribute[] attributes; // attributes defined in the class
88 private boolean is_zip; // Loaded from zip file
89
90 private static final int BUFSIZE = 8192;
91
92 /***
93 * Parse class from the given stream.
94 *
95 * @param file Input stream
96 * @param file_name File name
97 */
98 public ClassParser(InputStream file, String file_name) {
99 this.file_name = file_name;
100
101 String clazz = file.getClass().getName(); // Not a very clean solution ...
102 is_zip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar.");
103
104 if(file instanceof DataInputStream) // Is already a data stream
105 this.file = (DataInputStream)file;
106 else
107 this.file = new DataInputStream(new BufferedInputStream(file, BUFSIZE));
108 }
109
110 /*** Parse class from given .class file.
111 *
112 * @param file_name file name
113 * @throws IOException
114 */
115 public ClassParser(String file_name) throws IOException
116 {
117 is_zip = false;
118 this.file_name = file_name;
119 file = new DataInputStream(new BufferedInputStream
120 (new FileInputStream(file_name), BUFSIZE));
121 }
122
123 /*** Parse class from given .class file in a ZIP-archive
124 *
125 * @param file_name file name
126 * @throws IOException
127 */
128 public ClassParser(String zip_file, String file_name) throws IOException
129 {
130 is_zip = true;
131 zip = new ZipFile(zip_file);
132 ZipEntry entry = zip.getEntry(file_name);
133
134 this.file_name = file_name;
135
136 file = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry),
137 BUFSIZE));
138 }
139
140 /***
141 * Parse the given Java class file and return an object that represents
142 * the contained data, i.e., constants, methods, fields and commands.
143 * A <em>ClassFormatException</em> is raised, if the file is not a valid
144 * .class file. (This does not include verification of the byte code as it
145 * is performed by the java interpreter).
146 *
147 * @return Class object representing the parsed class file
148 * @throws IOException
149 * @throws ClassFormatException
150 */
151 public JavaClass parse() throws IOException, ClassFormatException
152 {
153 /******************* Read headers ********************************/
154 // Check magic tag of class file
155 readID();
156
157 // Get compiler version
158 readVersion();
159
160 /******************* Read constant pool and related **************/
161 // Read constant pool entries
162 readConstantPool();
163
164 // Get class information
165 readClassInfo();
166
167 // Get interface information, i.e., implemented interfaces
168 readInterfaces();
169
170 /******************* Read class fields and methods ***************/
171 // Read class fields, i.e., the variables of the class
172 readFields();
173
174 // Read class methods, i.e., the functions in the class
175 readMethods();
176
177 // Read class attributes
178 readAttributes();
179
180 // Check for unknown variables
181 //Unknown[] u = Unknown.getUnknownAttributes();
182 //for(int i=0; i < u.length; i++)
183 // System.err.println("WARNING: " + u[i]);
184
185 // Everything should have been read now
186 // if(file.available() > 0) {
187 // int bytes = file.available();
188 // byte[] buf = new byte[bytes];
189 // file.read(buf);
190
191 // if(!(is_zip && (buf.length == 1))) {
192 // System.err.println("WARNING: Trailing garbage at end of " + file_name);
193 // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf));
194 // }
195 // }
196
197 // Read everything of interest, so close the file
198 file.close();
199 if(zip != null)
200 zip.close();
201
202 // Return the information we have gathered in a new object
203 return new JavaClass(class_name_index, superclass_name_index,
204 file_name, major, minor, access_flags,
205 constant_pool, interfaces, fields,
206 methods, attributes, is_zip? JavaClass.ZIP : JavaClass.FILE);
207 }
208
209 /***
210 * Read information about the attributes of the class.
211 * @throws IOException
212 * @throws ClassFormatException
213 */
214 private final void readAttributes() throws IOException, ClassFormatException
215 {
216 int attributes_count;
217
218 attributes_count = file.readUnsignedShort();
219 attributes = new Attribute[attributes_count];
220
221 for(int i=0; i < attributes_count; i++)
222 attributes[i] = Attribute.readAttribute(file, constant_pool);
223 }
224
225 /***
226 * Read information about the class and its super class.
227 * @throws IOException
228 * @throws ClassFormatException
229 */
230 private final void readClassInfo() throws IOException, ClassFormatException
231 {
232 access_flags = file.readUnsignedShort();
233
234 /* Interfaces are implicitely abstract, the flag should be set
235 * according to the JVM specification.
236 */
237 if((access_flags & Constants.ACC_INTERFACE) != 0)
238 access_flags |= Constants.ACC_ABSTRACT;
239
240 if(((access_flags & Constants.ACC_ABSTRACT) != 0) &&
241 ((access_flags & Constants.ACC_FINAL) != 0 ))
242 throw new ClassFormatException("Class can't be both final and abstract");
243
244 class_name_index = file.readUnsignedShort();
245 superclass_name_index = file.readUnsignedShort();
246 }
247 /***
248 * Read constant pool entries.
249 * @throws IOException
250 * @throws ClassFormatException
251 */
252 private final void readConstantPool() throws IOException, ClassFormatException
253 {
254 constant_pool = new ConstantPool(file);
255 }
256
257 /***
258 * Read information about the fields of the class, i.e., its variables.
259 * @throws IOException
260 * @throws ClassFormatException
261 */
262 private final void readFields() throws IOException, ClassFormatException
263 {
264 int fields_count;
265
266 fields_count = file.readUnsignedShort();
267 fields = new Field[fields_count];
268
269 for(int i=0; i < fields_count; i++)
270 fields[i] = new Field(file, constant_pool);
271 }
272
273 /********************* Private utility methods **********************/
274
275 /***
276 * Check whether the header of the file is ok.
277 * Of course, this has to be the first action on successive file reads.
278 * @throws IOException
279 * @throws ClassFormatException
280 */
281 private final void readID() throws IOException, ClassFormatException
282 {
283 int magic = 0xCAFEBABE;
284
285 if(file.readInt() != magic)
286 throw new ClassFormatException(file_name + " is not a Java .class file");
287 }
288 /***
289 * Read information about the interfaces implemented by this class.
290 * @throws IOException
291 * @throws ClassFormatException
292 */
293 private final void readInterfaces() throws IOException, ClassFormatException
294 {
295 int interfaces_count;
296
297 interfaces_count = file.readUnsignedShort();
298 interfaces = new int[interfaces_count];
299
300 for(int i=0; i < interfaces_count; i++)
301 interfaces[i] = file.readUnsignedShort();
302 }
303 /***
304 * Read information about the methods of the class.
305 * @throws IOException
306 * @throws ClassFormatException
307 */
308 private final void readMethods() throws IOException, ClassFormatException
309 {
310 int methods_count;
311
312 methods_count = file.readUnsignedShort();
313 methods = new Method[methods_count];
314
315 for(int i=0; i < methods_count; i++)
316 methods[i] = new Method(file, constant_pool);
317 }
318 /***
319 * Read major and minor version of compiler which created the file.
320 * @throws IOException
321 * @throws ClassFormatException
322 */
323 private final void readVersion() throws IOException, ClassFormatException
324 {
325 minor = file.readUnsignedShort();
326 major = file.readUnsignedShort();
327 }
328 }
This page was automatically generated by Maven