- package com.sun.org.apache.bcel.internal.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 (http://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
- * <http://www.apache.org/>.
- */
-
- import com.sun.org.apache.bcel.internal.Constants;
- import com.sun.org.apache.bcel.internal.Repository;
- import java.io.*;
- import java.util.StringTokenizer;
-
- /**
- * Represents a Java class, i.e., the data structures, constant pool,
- * fields, methods and commands contained in a Java .class file.
- * See <a href="ftp://java.sun.com/docs/specs/">JVM
- * specification</a> for details.
- *
- * @version $Id: JavaClass.java,v 1.1 2003/12/12 08:57:41 rameshm Exp $
- * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
- */
- public class JavaClass extends AccessFlags implements Cloneable, Node {
- private String file_name;
- private String package_name;
- private String source_file_name = "<Unknown>";
- private int class_name_index;
- private int superclass_name_index;
- private String class_name;
- private String superclass_name;
- private int major, minor; // Compiler version
- private ConstantPool constant_pool; // Constant pool
- private int[] interfaces; // implemented interfaces
- private String[] interface_names;
- private Field[] fields; // Fields, i.e., variables of class
- private Method[] methods; // methods defined in the class
- private Attribute[] attributes; // attributes defined in the class
- private byte source = HEAP; // Generated in memory
-
- public static final byte HEAP = 1;
- public static final byte FILE = 2;
- public static final byte ZIP = 3;
-
- static boolean debug = false; // Debugging on/off
- static char sep = '/'; // directory separator
-
- /**
- * Constructor gets all contents as arguments.
- *
- * @param class_name Class name
- * @param superclass_name Superclass name
- * @param file_name File name
- * @param major Major compiler version
- * @param minor Minor compiler version
- * @param access_flags Access rights defined by bit flags
- * @param constant_pool Array of constants
- * @param interfaces Implemented interfaces
- * @param fields Class fields
- * @param methods Class methods
- * @param attributes Class attributes
- * @param source Read from file or generated in memory?
- */
- public JavaClass(int class_name_index,
- int superclass_name_index,
- String file_name,
- int major,
- int minor,
- int access_flags,
- ConstantPool constant_pool,
- int[] interfaces,
- Field[] fields,
- Method[] methods,
- Attribute[] attributes,
- byte source)
- {
- if(interfaces == null) // Allowed for backward compatibility
- interfaces = new int[0];
- if(attributes == null)
- this.attributes = new Attribute[0];
- if(fields == null)
- fields = new Field[0];
- if(methods == null)
- methods = new Method[0];
-
- this.class_name_index = class_name_index;
- this.superclass_name_index = superclass_name_index;
- this.file_name = file_name;
- this.major = major;
- this.minor = minor;
- this.access_flags = access_flags;
- this.constant_pool = constant_pool;
- this.interfaces = interfaces;
- this.fields = fields;
- this.methods = methods;
- this.attributes = attributes;
- this.source = source;
-
- // Get source file name if available
- for(int i=0; i < attributes.length; i++) {
- if(attributes[i] instanceof SourceFile) {
- source_file_name = ((SourceFile)attributes[i]).getSourceFileName();
- break;
- }
- }
-
- // Get class name and superclass name
- ConstantUtf8 name;
-
- /* According to the specification the following entries must be of type
- * `ConstantClass' but we check that anyway via the
- * `ConstPool.getConstant' method.
- */
- class_name = constant_pool.getConstantString(class_name_index,
- Constants.CONSTANT_Class);
- class_name = Utility.compactClassName(class_name, false);
-
- int index = class_name.lastIndexOf('.');
- if(index < 0)
- package_name = "";
- else
- package_name = class_name.substring(0, index);
-
- if(superclass_name_index > 0) { // May be zero -> class is java.lang.Object
- superclass_name = constant_pool.getConstantString(superclass_name_index,
- Constants.CONSTANT_Class);
- superclass_name = Utility.compactClassName(superclass_name, false);
- }
- else
- superclass_name = "java.lang.Object";
-
- interface_names = new String[interfaces.length];
- for(int i=0; i < interfaces.length; i++) {
- String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
- interface_names[i] = Utility.compactClassName(str, false);
- }
- }
-
- /**
- * Constructor gets all contents as arguments.
- *
- * @param class_name Class name
- * @param superclass_name Superclass name
- * @param file_name File name
- * @param major Major compiler version
- * @param minor Minor compiler version
- * @param access_flags Access rights defined by bit flags
- * @param constant_pool Array of constants
- * @param interfaces Implemented interfaces
- * @param fields Class fields
- * @param methods Class methods
- * @param attributes Class attributes
- */
- public JavaClass(int class_name_index,
- int superclass_name_index,
- String file_name,
- int major,
- int minor,
- int access_flags,
- ConstantPool constant_pool,
- int[] interfaces,
- Field[] fields,
- Method[] methods,
- Attribute[] attributes) {
- this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
- constant_pool, interfaces, fields, methods, attributes, HEAP);
- }
-
-
- /**
- * Called by objects that are traversing the nodes of the tree implicitely
- * defined by the contents of a Java class. I.e., the hierarchy of methods,
- * fields, attributes, etc. spawns a tree of objects.
- *
- * @param v Visitor object
- */
- public void accept(Visitor v) {
- v.visitJavaClass(this);
- }
-
- /* Print debug information depending on `JavaClass.debug'
- */
- static final void Debug(String str) {
- if(debug)
- System.out.println(str);
- }
-
- /**
- * Dump class to a file.
- *
- * @param file Output file
- * @throw IOException
- */
- public void dump(File file) throws IOException
- {
- String parent = file.getParent();
-
- if(parent != null) {
- File dir = new File(parent);
-
- if(dir != null)
- dir.mkdirs();
- }
-
- dump(new DataOutputStream(new FileOutputStream(file)));
- }
-
- /**
- * Dump class to a file named file_name.
- *
- * @param file_name Output file name
- * @exception IOException
- */
- public void dump(String file_name) throws IOException
- {
- dump(new File(file_name));
- }
-
- /**
- * @return class in binary format
- */
- public byte[] getBytes() {
- ByteArrayOutputStream s = new ByteArrayOutputStream();
- DataOutputStream ds = new DataOutputStream(s);
-
- try {
- dump(ds);
- ds.close();
- } catch(IOException e) { e.printStackTrace(); }
-
- return s.toByteArray();
- }
-
- /**
- * Dump Java class to output stream in binary format.
- *
- * @param file Output stream
- * @exception IOException
- */
- public void dump(OutputStream file) throws IOException {
- dump(new DataOutputStream(file));
- }
-
- /**
- * Dump Java class to output stream in binary format.
- *
- * @param file Output stream
- * @exception IOException
- */
- public void dump(DataOutputStream file) throws IOException
- {
- file.writeInt(0xcafebabe);
- file.writeShort(minor);
- file.writeShort(major);
-
- constant_pool.dump(file);
-
- file.writeShort(access_flags);
- file.writeShort(class_name_index);
- file.writeShort(superclass_name_index);
-
- file.writeShort(interfaces.length);
- for(int i=0; i < interfaces.length; i++)
- file.writeShort(interfaces[i]);
-
- file.writeShort(fields.length);
- for(int i=0; i < fields.length; i++)
- fields[i].dump(file);
-
- file.writeShort(methods.length);
- for(int i=0; i < methods.length; i++)
- methods[i].dump(file);
-
- if(attributes != null) {
- file.writeShort(attributes.length);
- for(int i=0; i < attributes.length; i++)
- attributes[i].dump(file);
- }
- else
- file.writeShort(0);
-
- file.close();
- }
-
- /**
- * @return Attributes of the class.
- */
- public Attribute[] getAttributes() { return attributes; }
-
- /**
- * @return Class name.
- */
- public String getClassName() { return class_name; }
-
- /**
- * @return Package name.
- */
- public String getPackageName() { return package_name; }
-
- /**
- * @return Class name index.
- */
- public int getClassNameIndex() { return class_name_index; }
-
- /**
- * @return Constant pool.
- */
- public ConstantPool getConstantPool() { return constant_pool; }
-
- /**
- * @return Fields, i.e., variables of the class.
- */
- public Field[] getFields() { return fields; }
- /**
- * @return File name of class, aka SourceFile attribute value
- */
- public String getFileName() { return file_name; }
- /**
- * @return Names of implemented interfaces.
- */
- public String[] getInterfaceNames() { return interface_names; }
- /**
- * @return Implemented interfaces.
- */
- public int[] getInterfaces() { return interfaces; }
- /**
- * @return Major number of compiler version.
- */
- public int getMajor() { return major; }
- /**
- * @return Methods of the class.
- */
- public Method[] getMethods() { return methods; }
- /**
- * @return Minor number of compiler version.
- */
- public int getMinor() { return minor; }
-
- /**
- * @return sbsolute path to file where this class was read from
- */
- public String getSourceFileName() { return source_file_name; }
-
- /**
- * @return Superclass name.
- */
- public String getSuperclassName() { return superclass_name; }
- /**
- * @return Class name index.
- */
- public int getSuperclassNameIndex() { return superclass_name_index; }
-
- static {
- // Debugging ... on/off
- //String debug = System.getProperty("JavaClass.debug");
-
- //if(debug != null)
- // JavaClass.debug = new Boolean(debug).booleanValue();
-
- // Get path separator either / or \ usually
- JavaClass.sep = java.io.File.separatorChar;
- }
-
- /**
- * @param attributes.
- */
- public void setAttributes(Attribute[] attributes) {
- this.attributes = attributes;
- }
- /**
- * @param class_name.
- */
- public void setClassName(String class_name) {
- this.class_name = class_name;
- }
- /**
- * @param class_name_index.
- */
- public void setClassNameIndex(int class_name_index) {
- this.class_name_index = class_name_index;
- }
- /**
- * @param constant_pool.
- */
- public void setConstantPool(ConstantPool constant_pool) {
- this.constant_pool = constant_pool;
- }
- /**
- * @param fields.
- */
- public void setFields(Field[] fields) {
- this.fields = fields;
- }
- /**
- * Set File name of class, aka SourceFile attribute value
- */
- public void setFileName(String file_name) {
- this.file_name = file_name;
- }
- /**
- * @param interface_names.
- */
- public void setInterfaceNames(String[] interface_names) {
- this.interface_names = interface_names;
- }
- /**
- * @param interfaces.
- */
- public void setInterfaces(int[] interfaces) {
- this.interfaces = interfaces;
- }
- /**
- * @param major.
- */
- public void setMajor(int major) {
- this.major = major;
- }
- /**
- * @param methods.
- */
- public void setMethods(Method[] methods) {
- this.methods = methods;
- }
- /**
- * @param minor.
- */
- public void setMinor(int minor) {
- this.minor = minor;
- }
- /**
- * Set absolute path to file this class was read from.
- */
- public void setSourceFileName(String source_file_name) {
- this.source_file_name = source_file_name;
- }
- /**
- * @param superclass_name.
- */
- public void setSuperclassName(String superclass_name) {
- this.superclass_name = superclass_name;
- }
- /**
- * @param superclass_name_index.
- */
- public void setSuperclassNameIndex(int superclass_name_index) {
- this.superclass_name_index = superclass_name_index;
- }
- /**
- * @return String representing class contents.
- */
- public String toString() {
- String access = Utility.accessToString(access_flags, true);
- access = access.equals("")? "" : (access + " ");
-
- StringBuffer buf = new StringBuffer(access +
- Utility.classOrInterface(access_flags) +
- " " +
- class_name + " extends " +
- Utility.compactClassName(superclass_name,
- false) + '\n');
- int size = interfaces.length;
-
- if(size > 0) {
- buf.append("implements\t\t");
-
- for(int i=0; i < size; i++) {
- buf.append(interface_names[i]);
- if(i < size - 1)
- buf.append(", ");
- }
-
- buf.append('\n');
- }
-
- buf.append("filename\t\t" + file_name + '\n');
- buf.append("compiled from\t\t" + source_file_name + '\n');
- buf.append("compiler version\t" + major + "." + minor + '\n');
- buf.append("access flags\t\t" + access_flags + '\n');
- buf.append("constant pool\t\t" + constant_pool.getLength() + " entries\n");
- buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n");
-
- if(attributes.length > 0) {
- buf.append("\nAttribute(s):\n");
- for(int i=0; i < attributes.length; i++)
- buf.append(indent(attributes[i]));
- }
-
- if(fields.length > 0) {
- buf.append("\n" + fields.length + " fields:\n");
- for(int i=0; i < fields.length; i++)
- buf.append("\t" + fields[i] + '\n');
- }
-
- if(methods.length > 0) {
- buf.append("\n" + methods.length + " methods:\n");
- for(int i=0; i < methods.length; i++)
- buf.append("\t" + methods[i] + '\n');
- }
-
- return buf.toString();
- }
-
- private static final String indent(Object obj) {
- StringTokenizer tok = new StringTokenizer(obj.toString(), "\n");
- StringBuffer buf = new StringBuffer();
-
- while(tok.hasMoreTokens())
- buf.append("\t" + tok.nextToken() + "\n");
-
- return buf.toString();
- }
-
- /**
- * @return deep copy of this class
- */
- public JavaClass copy() {
- JavaClass c = null;
-
- try {
- c = (JavaClass)clone();
- } catch(CloneNotSupportedException e) {}
-
- c.constant_pool = constant_pool.copy();
- c.interfaces = (int[])interfaces.clone();
- c.interface_names = (String[])interface_names.clone();
-
- c.fields = new Field[fields.length];
- for(int i=0; i < fields.length; i++)
- c.fields[i] = fields[i].copy(c.constant_pool);
-
- c.methods = new Method[methods.length];
- for(int i=0; i < methods.length; i++)
- c.methods[i] = methods[i].copy(c.constant_pool);
-
- c.attributes = new Attribute[attributes.length];
- for(int i=0; i < attributes.length; i++)
- c.attributes[i] = attributes[i].copy(c.constant_pool);
-
- return c;
- }
-
- public final boolean instanceOf(JavaClass super_class) {
- return Repository.instanceOf(this, super_class);
- }
-
- public final boolean isSuper() {
- return (access_flags & Constants.ACC_SUPER) != 0;
- }
-
- public final boolean isClass() {
- return (access_flags & Constants.ACC_INTERFACE) == 0;
- }
-
- /** @return returns either HEAP (generated), FILE, or ZIP
- */
- public final byte getSource() {
- return source;
- }
- }