Home | History | Annotate | Download | only in attribute
      1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
      2  *
      3  * This program and the accompanying materials are made available under
      4  * the terms of the Common Public License v1.0 which accompanies this distribution,
      5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
      6  *
      7  * $Id: Attribute_info.java,v 1.1.1.1 2004/05/09 16:57:47 vlad_r Exp $
      8  */
      9 package com.vladium.jcd.cls.attribute;
     10 
     11 import java.io.IOException;
     12 
     13 import com.vladium.jcd.cls.ClassDef;
     14 import com.vladium.jcd.cls.IConstantCollection;
     15 import com.vladium.jcd.cls.constant.*;
     16 import com.vladium.jcd.compiler.IClassFormatOutput;
     17 import com.vladium.jcd.lib.UDataInputStream;
     18 import com.vladium.jcd.lib.UDataOutputStream;
     19 
     20 // ----------------------------------------------------------------------------
     21 /**
     22  * Abstract base for all XXXAttribute_info structures. It also works in conjunction
     23  * with {@link GenericAttribute_info} class to process all unrecognized attributes.<P>
     24  *
     25  * Attributes are used in the {@link com.vladium.jcd.cls.ClassDef}, {@link com.vladium.jcd.cls.Field_info},
     26  * {@link com.vladium.jcd.cls.Method_info}, and {@link CodeAttribute_info}
     27  * structures of the .class file format. All attributes have the following
     28  * general format:
     29  * <PRE>
     30  *  attribute_info {
     31  *          u2 attribute_name_index;
     32  *          u4 attribute_length;
     33  *          u1 info[attribute_length];
     34  *  }
     35  * </PRE>
     36  *
     37  * For all attributes, the attribute_name_index must be a valid unsigned 16-bit
     38  * index into the constant pool of the class. The constant pool entry at
     39  * attribute_name_index must be a {@link com.vladium.jcd.cls.constant.CONSTANT_Utf8_info}
     40  * string representing the name of the attribute. The value of the attribute_length
     41  * item indicates the length of the subsequent information in bytes. The length
     42  * does not include the initial six bytes that contain the attribute_name_index
     43  * and attribute_length items.
     44  *
     45  * @see GenericAttribute_info
     46  *
     47  * @author (C) 2001, Vlad Roubtsov
     48  */
     49 public
     50 abstract class Attribute_info implements Cloneable, IClassFormatOutput
     51 {
     52     // public: ................................................................
     53 
     54     public static final String ATTRIBUTE_CODE               = "Code";
     55     public static final String ATTRIBUTE_CONSTANT_VALUE     = "ConstantValue";
     56     public static final String ATTRIBUTE_LINE_NUMBER_TABLE  = "LineNumberTable";
     57     public static final String ATTRIBUTE_EXCEPTIONS         = "Exceptions";
     58     public static final String ATTRIBUTE_SYNTHETIC          = "Synthetic";
     59     public static final String ATTRIBUTE_BRIDGE             = "Bridge";
     60     public static final String ATTRIBUTE_SOURCEFILE         = "SourceFile";
     61     public static final String ATTRIBUTE_INNERCLASSES       = "InnerClasses";
     62 
     63     /**
     64      * Constant pool index for {@link com.vladium.jcd.cls.constant.CONSTANT_Utf8_info}
     65      * string representing the name of this attribute [always positive].
     66      */
     67     public int m_name_index;
     68 
     69     /**
     70      * Returns the name for this attribute within the constant pool context of 'cls'
     71      * class definition.
     72      *
     73      * @param cls class that contains this attribute
     74      * @return attribute name
     75      */
     76     public String getName (final ClassDef cls)
     77     {
     78         return ((CONSTANT_Utf8_info) cls.getConstants ().get (m_name_index)).m_value;
     79     }
     80 
     81     /**
     82      * Returns the total length of this attribute when converted to
     83      * .class format [including the 6-byte header]
     84      */
     85     public abstract long length (); // including the 6-byte header
     86 
     87     // Visitor:
     88 
     89     public abstract void accept (IAttributeVisitor visitor, Object ctx);
     90 
     91     public abstract String toString ();
     92 
     93     // TODO: use a hashmap lookup in this method + control which set of attrs get mapped to generic
     94     /**
     95      * Parses out a single Attribute_info element out of .class data in
     96      * 'bytes'.
     97      *
     98      * @param constants constant pool for the parent class [may not be null; not validated]
     99      * @param bytes input .class data stream [may not be null; not validated]
    100      *
    101      * @return a single parsed attribute
    102      *
    103      * @throws IOException on input errors
    104      */
    105     public static Attribute_info new_Attribute_info (final IConstantCollection constants,
    106                                                      final UDataInputStream bytes)
    107         throws IOException
    108     {
    109         final int attribute_name_index = bytes.readU2 ();
    110         final long attribute_length = bytes.readU4 ();
    111 
    112         final CONSTANT_Utf8_info attribute_name = (CONSTANT_Utf8_info) constants.get (attribute_name_index);
    113         final String name = attribute_name.m_value;
    114 
    115         if (ATTRIBUTE_CODE.equals (name))
    116         {
    117             return new CodeAttribute_info (constants, attribute_name_index, attribute_length, bytes);
    118         }
    119         else if (ATTRIBUTE_CONSTANT_VALUE.equals (name))
    120         {
    121             return new ConstantValueAttribute_info (attribute_name_index, attribute_length, bytes);
    122         }
    123         else if (ATTRIBUTE_EXCEPTIONS.equals (name))
    124         {
    125             return new ExceptionsAttribute_info (attribute_name_index, attribute_length, bytes);
    126         }
    127         else if (ATTRIBUTE_INNERCLASSES.equals (name))
    128         {
    129             return new InnerClassesAttribute_info (attribute_name_index, attribute_length, bytes);
    130         }
    131         else if (ATTRIBUTE_SYNTHETIC.equals (name))
    132         {
    133             return new SyntheticAttribute_info (attribute_name_index, attribute_length);
    134         }
    135         else if (ATTRIBUTE_BRIDGE.equals (name))
    136         {
    137             return new BridgeAttribute_info (attribute_name_index, attribute_length);
    138         }
    139         else if (ATTRIBUTE_LINE_NUMBER_TABLE.equals (name))
    140         {
    141             return new LineNumberTableAttribute_info (attribute_name_index, attribute_length, bytes);
    142         }
    143         else if (ATTRIBUTE_SOURCEFILE.equals (name))
    144         {
    145             return new SourceFileAttribute_info (attribute_name_index, attribute_length, bytes);
    146         }
    147         else
    148         {
    149             // default:
    150             return new GenericAttribute_info (attribute_name_index, attribute_length, bytes);
    151         }
    152     }
    153 
    154     // Cloneable:
    155 
    156     /**
    157      * Chains to super.clone() and removes CloneNotSupportedException
    158      * from the method signature.
    159      */
    160     public Object clone ()
    161     {
    162         try
    163         {
    164             return super.clone ();
    165         }
    166         catch (CloneNotSupportedException e)
    167         {
    168             throw new InternalError (e.toString ());
    169         }
    170     }
    171 
    172     // IClassFormatOutput:
    173 
    174     public void writeInClassFormat (UDataOutputStream out) throws IOException
    175     {
    176         out.writeU2 (m_name_index);
    177         out.writeU4 (length () - 6); // don't use m_attribute_length
    178     }
    179 
    180     // protected: .............................................................
    181 
    182     /*
    183     protected Attribute_info (UDataInputStream bytes) throws IOException
    184     {
    185         //m_name_index = bytes.readU2 ();
    186         //m_attribute_length = bytes.readU4 ();
    187     }
    188     */
    189 
    190     protected Attribute_info (final int attribute_name_index, final long attribute_length)
    191     {
    192         m_name_index = attribute_name_index;
    193         m_attribute_length = attribute_length;
    194     }
    195 
    196     // TODO: remove this field as it is invalidated easily by most attribute mutations
    197     protected long m_attribute_length; // excluding the 6-byte header
    198 
    199     // package: ...............................................................
    200 
    201     // private: ...............................................................
    202 
    203 } // end of class
    204 // ----------------------------------------------------------------------------
    205