123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- package org.aspectj.apache.bcel.classfile;
-
- /* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (https://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" and
- * "Apache BCEL" must not be used to endorse or promote products
- * derived from this software without prior written permission. For
- * written permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * "Apache BCEL", nor may "Apache" appear in their name, without
- * prior written permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <https://www.apache.org/>.
- */
-
- import java.io.BufferedInputStream;
- import java.io.ByteArrayInputStream;
- import java.io.DataInputStream;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
-
- import org.aspectj.apache.bcel.Constants;
-
- /**
- * Wrapper class that parses a given Java .class file. The method <A
- * href ="#parse">parse</A> returns a <A href ="JavaClass.html">
- * JavaClass</A> object on success. When an I/O error or an
- * inconsistency occurs an appropiate exception is propagated back to
- * the caller.
- *
- * The structure and the names comply, except for a few conveniences,
- * exactly with the <A href="ftp://java.sun.com/docs/specs/vmspec.ps">
- * JVM specification 1.0</a>. See this paper for
- * further details about the structure of a bytecode file.
- *
- * @version $Id: ClassParser.java,v 1.6 2008/05/30 17:29:14 aclement Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
- */
- public final class ClassParser {
- private DataInputStream file;
- private String filename;
- private int classnameIndex;
- private int superclassnameIndex;
- private int major, minor;
- private int accessflags;
- private int[] interfaceIndices;
- private ConstantPool cpool;
- private Field[] fields;
- private Method[] methods;
- private Attribute[] attributes;
-
- private static final int BUFSIZE = 8192;
-
- /** Parse class from the given stream */
- public ClassParser(InputStream file, String filename) {
- this.filename = filename;
- if (file instanceof DataInputStream) this.file = (DataInputStream)file;
- else this.file = new DataInputStream(new BufferedInputStream(file,BUFSIZE));
- }
-
- public ClassParser(ByteArrayInputStream baos, String filename) {
- this.filename = filename;
- this.file = new DataInputStream(baos);
- }
-
- /** Parse class from given .class file */
- public ClassParser(String file_name) throws IOException {
- this.filename = file_name;
- file = new DataInputStream(new BufferedInputStream(new FileInputStream(file_name),BUFSIZE));
- }
-
- /**
- * Parse the given Java class file and return an object that represents
- * the contained data, i.e., constants, methods, fields and commands.
- * A <em>ClassFormatException</em> is raised, if the file is not a valid
- * .class file. (This does not include verification of the byte code as it
- * is performed by the java interpreter).
- */
- public JavaClass parse() throws IOException, ClassFormatException {
- /****************** Read headers ********************************/
- // Check magic tag of class file
- readID();
-
- // Get compiler version
- readVersion();
-
- /****************** Read constant pool and related **************/
- // Read constant pool entries
- readConstantPool();
-
- // Get class information
- readClassInfo();
-
- // Get interface information, i.e., implemented interfaces
- readInterfaces();
-
- /****************** Read class fields and methods ***************/
- // Read class fields, i.e., the variables of the class
- readFields();
-
- // Read class methods, i.e., the functions in the class
- readMethods();
-
- // Read class attributes
- readAttributes();
-
- // Read everything of interest, so close the file
- file.close();
-
- // Return the information we have gathered in a new object
- JavaClass jc= new JavaClass(classnameIndex, superclassnameIndex,
- filename, major, minor, accessflags,
- cpool, interfaceIndices, fields,
- methods, attributes);
- return jc;
- }
-
- /** Read information about the attributes of the class */
- private final void readAttributes() {
- attributes = AttributeUtils.readAttributes(file,cpool);
- }
-
- /** Read information about the class and its super class */
- private final void readClassInfo() throws IOException {
- accessflags = file.readUnsignedShort();
-
- /* Interfaces are implicitely abstract, the flag should be set
- * according to the JVM specification */
- if((accessflags & Constants.ACC_INTERFACE) != 0)
- accessflags |= Constants.ACC_ABSTRACT;
-
- // don't police it like this... leave higher level verification code to check it.
- // if(((access_flags & Constants.ACC_ABSTRACT) != 0) &&
- // ((access_flags & Constants.ACC_FINAL) != 0 ))
- // throw new ClassFormatException("Class can't be both final and abstract");
-
- classnameIndex = file.readUnsignedShort();
- superclassnameIndex = file.readUnsignedShort();
- }
-
- private final void readConstantPool() throws IOException {
- try {
- cpool = new ConstantPool(file);
- } catch (ClassFormatException cfe) {
- // add some context if we can
- cfe.printStackTrace();
- if (filename!=null) {
- String newmessage = "File: '"+filename+"': "+cfe.getMessage();
- throw new ClassFormatException(newmessage); // this loses the old stack trace but I dont think that matters!
- }
- throw cfe;
- }
- }
-
- /** Read information about the fields of the class */
- private final void readFields() throws IOException, ClassFormatException {
- int fieldCount = file.readUnsignedShort();
- if (fieldCount == 0) {
- fields = Field.NoFields;
- } else {
- fields = new Field[fieldCount];
- for(int i=0; i < fieldCount; i++)
- fields[i] = new Field(file, cpool);
- }
- }
-
- /** Check whether the header of the file is ok. Of course, this has
- * to be the first action on successive file reads */
- private final void readID() throws IOException {
- int magic = 0xCAFEBABE;
- if (file.readInt() != magic)
- throw new ClassFormatException(filename + " is not a Java .class file");
- }
-
- private static final int[] NO_INTERFACES = new int[0];
-
- /** Read information about the interfaces implemented by this class */
- private final void readInterfaces() throws IOException {
- int interfacesCount = file.readUnsignedShort();
- if (interfacesCount==0) {
- interfaceIndices = NO_INTERFACES;
- } else {
- interfaceIndices = new int[interfacesCount];
- for(int i=0; i < interfacesCount; i++)
- interfaceIndices[i] = file.readUnsignedShort();
- }
- }
-
- /** Read information about the methods of the class */
- private final void readMethods() throws IOException {
- int methodsCount = file.readUnsignedShort();
- if (methodsCount==0) {
- methods = Method.NoMethods;
- } else {
- methods = new Method[methodsCount];
- for(int i=0; i < methodsCount; i++)
- methods[i] = new Method(file, cpool);
- }
- }
-
- /** Read major and minor version of compiler which created the file */
- private final void readVersion() throws IOException {
- minor = file.readUnsignedShort();
- major = file.readUnsignedShort();
- }
-
- }
|