View Javadoc
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