/* * reserved comment block * DO NOT REMOVE OR ALTER! */ 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 java.io.*; import java.util.HashMap; /** * Abstract super class for <em>Attribute</em> objects. Currently the * <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>, * <em>Exceptiontable</em>, <em>LineNumberTable</em>, * <em>LocalVariableTable</em>, <em>InnerClasses</em> and * <em>Synthetic</em> attributes are supported. The * <em>Unknown</em> attribute stands for non-standard-attributes. * * @version $Id: Attribute.java,v 1.1.2.1 2005/07/31 23:46:25 jeffsuttor Exp $ * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> * @see ConstantValue * @see SourceFile * @see Code * @see Unknown * @see ExceptionTable * @see LineNumberTable * @see LocalVariableTable * @see InnerClasses * @see Synthetic * @see Deprecated * @see Signature */ public abstract class Attribute implements Cloneable, Node, Serializable { protected int name_index; // Points to attribute name in constant pool protected int length; // Content length of attribute field protected byte tag; // Tag to distiguish subclasses protected ConstantPool constant_pool; protected Attribute(byte tag, int name_index, int length, ConstantPool constant_pool) { this.tag = tag; this.name_index = name_index; this.length = length; this.constant_pool = constant_pool; } /** * 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 abstract void accept(Visitor v); /** * Dump attribute to file stream in binary format. * * @param file Output file stream * @throws IOException */ public void dump(DataOutputStream file) throws IOException { file.writeShort(name_index); file.writeInt(length); } private static HashMap readers = new HashMap(); /** Add an Attribute reader capable of parsing (user-defined) attributes * named "name". You should not add readers for the standard attributes * such as "LineNumberTable", because those are handled internally. * * @param name the name of the attribute as stored in the class file * @param r the reader object */ public static void addAttributeReader(String name, AttributeReader r) { readers.put(name, r); } /** Remove attribute reader * * @param name the name of the attribute as stored in the class file */ public static void removeAttributeReader(String name) { readers.remove(name); } /* Class method reads one attribute from the input data stream. * This method must not be accessible from the outside. It is * called by the Field and Method constructor methods. * * @see Field * @see Method * @param file Input stream * @param constant_pool Array of constants * @return Attribute * @throws IOException * @throws ClassFormatException */ public static final Attribute readAttribute(DataInputStream file, ConstantPool constant_pool) throws IOException, ClassFormatException { ConstantUtf8 c; String name; int name_index; int length; byte tag = Constants.ATTR_UNKNOWN; // Unknown attribute // Get class name from constant pool via `name_index' indirection name_index = (int)file.readUnsignedShort(); c = (ConstantUtf8)constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8); name = c.getBytes(); // Length of data in bytes length = file.readInt(); // Compare strings to find known attribute for(byte i=0; i < Constants.KNOWN_ATTRIBUTES; i++) { if(name.equals(Constants.ATTRIBUTE_NAMES[i])) { tag = i; // found! break; } } // Call proper constructor, depending on `tag' switch(tag) { case Constants.ATTR_UNKNOWN: AttributeReader r = (AttributeReader)readers.get(name); if(r != null) return r.createAttribute(name_index, length, file, constant_pool); else return new Unknown(name_index, length, file, constant_pool); case Constants.ATTR_CONSTANT_VALUE: return new ConstantValue(name_index, length, file, constant_pool); case Constants.ATTR_SOURCE_FILE: return new SourceFile(name_index, length, file, constant_pool); case Constants.ATTR_CODE: return new Code(name_index, length, file, constant_pool); case Constants.ATTR_EXCEPTIONS: return new ExceptionTable(name_index, length, file, constant_pool); case Constants.ATTR_LINE_NUMBER_TABLE: return new LineNumberTable(name_index, length, file, constant_pool); case Constants.ATTR_LOCAL_VARIABLE_TABLE: return new LocalVariableTable(name_index, length, file, constant_pool); case Constants.ATTR_INNER_CLASSES: return new InnerClasses(name_index, length, file, constant_pool); case Constants.ATTR_SYNTHETIC: return new Synthetic(name_index, length, file, constant_pool); case Constants.ATTR_DEPRECATED: return new Deprecated(name_index, length, file, constant_pool); case Constants.ATTR_PMG: return new PMGClass(name_index, length, file, constant_pool); case Constants.ATTR_SIGNATURE: return new Signature(name_index, length, file, constant_pool); case Constants.ATTR_STACK_MAP: return new StackMap(name_index, length, file, constant_pool); default: // Never reached throw new IllegalStateException("Ooops! default case reached."); } } /** * @return Length of attribute field in bytes. */ public final int getLength() { return length; } /** * @param Attribute length in bytes. */ public final void setLength(int length) { this.length = length; } /** * @param name_index of attribute. */ public final void setNameIndex(int name_index) { this.name_index = name_index; } /** * @return Name index in constant pool of attribute name. */ public final int getNameIndex() { return name_index; } /** * @return Tag of attribute, i.e., its type. Value may not be altered, thus * there is no setTag() method. */ public final byte getTag() { return tag; } /** * @return Constant pool used by this object. * @see ConstantPool */ public final ConstantPool getConstantPool() { return constant_pool; } /** * @param constant_pool Constant pool to be used for this object. * @see ConstantPool */ public final void setConstantPool(ConstantPool constant_pool) { this.constant_pool = constant_pool; } /** * Use copy() if you want to have a deep copy(), i.e., with all references * copied correctly. * * @return shallow copy of this attribute */ public Object clone() { Object o = null; try { o = super.clone(); } catch(CloneNotSupportedException e) { e.printStackTrace(); // Never occurs } return o; } /** * @return deep copy of this attribute */ public abstract Attribute copy(ConstantPool constant_pool); /** * @return attribute name. */ public String toString() { return Constants.ATTRIBUTE_NAMES[tag]; } }