View Javadoc

    1   /*
    2    * Copyright  2000-2004 The Apache Software Foundation
    3    *
    4    *  Licensed under the Apache License, Version 2.0 (the "License");
    5    *  you may not use this file except in compliance with the License.
    6    *  You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   *  Unless required by applicable law or agreed to in writing, software
    11   *  distributed under the License is distributed on an "AS IS" BASIS,
    12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   *  See the License for the specific language governing permissions and
    14   *  limitations under the License.
    15   *
    16   */
    17  package org.apache.bcel.classfile;
    18
    19  import java.io.DataInputStream;
    20  import java.io.DataOutputStream;
    21  import java.io.IOException;
    22  import java.io.Serializable;
    23  import java.util.HashMap;
    24  import java.util.Map;
    25  import org.apache.bcel.Constants;
    26
    27  /***
    28   * Abstract super class for <em>Attribute</em> objects. Currently the
    29   * <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>,
    30   * <em>Exceptiontable</em>, <em>LineNumberTable</em>,
    31   * <em>LocalVariableTable</em>, <em>InnerClasses</em> and
    32   * <em>Synthetic</em> attributes are supported. The
    33   * <em>Unknown</em> attribute stands for non-standard-attributes.
    34   *
    35   * @version $Id: Attribute.java 386056 2006-03-15 11:31:56Z tcurdt $
    36   * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
    37   * @see     ConstantValue
    38   * @see     SourceFile
    39   * @see     Code
    40   * @see     Unknown
    41   * @see     ExceptionTable
    42   * @see     LineNumberTable
    43   * @see     LocalVariableTable
    44   * @see     InnerClasses
    45   * @see     Synthetic
    46   * @see     Deprecated
    47   * @see     Signature
    48   */
    49  public abstract class Attribute implements Cloneable, Node, Serializable {
    50
    51      protected int name_index; // Points to attribute name in constant pool
    52      protected int length; // Content length of attribute field
    53      protected byte tag; // Tag to distiguish subclasses
    54      protected ConstantPool constant_pool;
    55
    56
    57      protected Attribute(byte tag, int name_index, int length, ConstantPool constant_pool) {
    58          this.tag = tag;
    59          this.name_index = name_index;
    60          this.length = length;
    61          this.constant_pool = constant_pool;
    62      }
    63
    64
    65      /***
    66       * Called by objects that are traversing the nodes of the tree implicitely
    67       * defined by the contents of a Java class. I.e., the hierarchy of methods,
    68       * fields, attributes, etc. spawns a tree of objects.
    69       *
    70       * @param v Visitor object
    71       */
    72      public abstract void accept( Visitor v );
    73
    74
    75      /***
    76       * Dump attribute to file stream in binary format.
    77       *
    78       * @param file Output file stream
    79       * @throws IOException
    80       */
    81      public void dump( DataOutputStream file ) throws IOException {
    82          file.writeShort(name_index);
    83          file.writeInt(length);
    84      }
    85
    86      private static Map readers = new HashMap();
    87
    88
    89      /*** Add an Attribute reader capable of parsing (user-defined) attributes
    90       * named "name". You should not add readers for the standard attributes
    91       * such as "LineNumberTable", because those are handled internally.
    92       *
    93       * @param name the name of the attribute as stored in the class file
    94       * @param r the reader object
    95       */
    96      public static void addAttributeReader( String name, AttributeReader r ) {
    97          readers.put(name, r);
    98      }
    99
    100
    101     /*** Remove attribute reader
    102      *
    103      * @param name the name of the attribute as stored in the class file
    104      */
    105     public static void removeAttributeReader( String name ) {
    106         readers.remove(name);
    107     }
    108
    109
    110     /* Class method reads one attribute from the input data stream.
    111      * This method must not be accessible from the outside.  It is
    112      * called by the Field and Method constructor methods.
    113      *
    114      * @see    Field
    115      * @see    Method
    116      * @param  file Input stream
    117      * @param  constant_pool Array of constants
    118      * @return Attribute
    119      * @throws  IOException
    120      * @throws  ClassFormatException
    121      */
    122     public static final Attribute readAttribute( DataInputStream file, ConstantPool constant_pool )
    123             throws IOException, ClassFormatException {
    124         ConstantUtf8 c;
    125         String name;
    126         int name_index;
    127         int length;
    128         byte tag = Constants.ATTR_UNKNOWN; // Unknown attribute
    129         // Get class name from constant pool via `name_index' indirection
    130         name_index = file.readUnsignedShort();
    131         c = (ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8);
    132         name = c.getBytes();
    133         // Length of data in bytes
    134         length = file.readInt();
    135         // Compare strings to find known attribute
    136         for (byte i = 0; i < Constants.KNOWN_ATTRIBUTES; i++) {
    137             if (name.equals(Constants.ATTRIBUTE_NAMES[i])) {
    138                 tag = i; // found!
    139                 break;
    140             }
    141         }
    142         // Call proper constructor, depending on `tag'
    143         switch (tag) {
    144             case Constants.ATTR_UNKNOWN:
    145                 AttributeReader r = (AttributeReader) readers.get(name);
    146                 if (r != null) {
    147                     return r.createAttribute(name_index, length, file, constant_pool);
    148                 }
    149                 return new Unknown(name_index, length, file, constant_pool);
    150             case Constants.ATTR_CONSTANT_VALUE:
    151                 return new ConstantValue(name_index, length, file, constant_pool);
    152             case Constants.ATTR_SOURCE_FILE:
    153                 return new SourceFile(name_index, length, file, constant_pool);
    154             case Constants.ATTR_CODE:
    155                 return new Code(name_index, length, file, constant_pool);
    156             case Constants.ATTR_EXCEPTIONS:
    157                 return new ExceptionTable(name_index, length, file, constant_pool);
    158             case Constants.ATTR_LINE_NUMBER_TABLE:
    159                 return new LineNumberTable(name_index, length, file, constant_pool);
    160             case Constants.ATTR_LOCAL_VARIABLE_TABLE:
    161                 return new LocalVariableTable(name_index, length, file, constant_pool);
    162             case Constants.ATTR_INNER_CLASSES:
    163                 return new InnerClasses(name_index, length, file, constant_pool);
    164             case Constants.ATTR_SYNTHETIC:
    165                 return new Synthetic(name_index, length, file, constant_pool);
    166             case Constants.ATTR_DEPRECATED:
    167                 return new Deprecated(name_index, length, file, constant_pool);
    168             case Constants.ATTR_PMG:
    169                 return new PMGClass(name_index, length, file, constant_pool);
    170             case Constants.ATTR_SIGNATURE:
    171                 return new Signature(name_index, length, file, constant_pool);
    172             case Constants.ATTR_STACK_MAP:
    173                 return new StackMap(name_index, length, file, constant_pool);
    174                 //    case Constants.ATTR_RUNTIMEVISIBLE_ANNOTATIONS:
    175                 //      return new RuntimeVisibleAnnotations(name_index, length, file, constant_pool);
    176                 //    case Constants.ATTR_RUNTIMEINVISIBLE_ANNOTATIONS:
    177                 //      return new RuntimeInvisibleAnnotations(name_index, length, file, constant_pool);
    178                 //    case Constants.ATTR_RUNTIMEVISIBLE_PARAMETER_ANNOTATIONS:
    179                 //      return new RuntimeVisibleParameterAnnotations(name_index, length, file, constant_pool);
    180                 //    case Constants.ATTR_RUNTIMEINVISIBLE_PARAMETER_ANNOTATIONS:
    181                 //      return new RuntimeInvisibleParameterAnnotations(name_index, length, file, constant_pool);
    182                 //    case Constants.ATTR_ANNOTATION_DEFAULT:
    183                 //      return new AnnotationDefault(name_index, length, file, constant_pool);
    184             default: // Never reached
    185                 throw new IllegalStateException("Ooops! default case reached.");
    186         }
    187     }
    188
    189
    190     /***
    191      * @return Length of attribute field in bytes.
    192      */
    193     public final int getLength() {
    194         return length;
    195     }
    196
    197
    198     /***
    199      * @param length length in bytes.
    200      */
    201     public final void setLength( int length ) {
    202         this.length = length;
    203     }
    204
    205
    206     /***
    207      * @param name_index of attribute.
    208      */
    209     public final void setNameIndex( int name_index ) {
    210         this.name_index = name_index;
    211     }
    212
    213
    214     /***
    215      * @return Name index in constant pool of attribute name.
    216      */
    217     public final int getNameIndex() {
    218         return name_index;
    219     }
    220
    221
    222     /***
    223      * @return Tag of attribute, i.e., its type. Value may not be altered, thus
    224      * there is no setTag() method.
    225      */
    226     public final byte getTag() {
    227         return tag;
    228     }
    229
    230
    231     /***
    232      * @return Constant pool used by this object.
    233      * @see ConstantPool
    234      */
    235     public final ConstantPool getConstantPool() {
    236         return constant_pool;
    237     }
    238
    239
    240     /***
    241      * @param constant_pool Constant pool to be used for this object.
    242      * @see ConstantPool
    243      */
    244     public final void setConstantPool( ConstantPool constant_pool ) {
    245         this.constant_pool = constant_pool;
    246     }
    247
    248
    249     /***
    250      * Use copy() if you want to have a deep copy(), i.e., with all references
    251      * copied correctly.
    252      *
    253      * @return shallow copy of this attribute
    254      */
    255     public Object clone() {
    256         Object o = null;
    257         try {
    258             o = super.clone();
    259         } catch (CloneNotSupportedException e) {
    260             e.printStackTrace(); // Never occurs
    261         }
    262         return o;
    263     }
    264
    265
    266     /***
    267      * @return deep copy of this attribute
    268      */
    269     public abstract Attribute copy( ConstantPool _constant_pool );
    270
    271
    272     /***
    273      * @return attribute name.
    274      */
    275     public String toString() {
    276         return Constants.ATTRIBUTE_NAMES[tag];
    277     }
    278 }