/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. * * This program and the accompanying materials are made available under * the terms of the Common Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/cpl-v10.html * * $Id: Attribute_info.java,v 1.1.1.1 2004/05/09 16:57:47 vlad_r Exp $ */ package com.vladium.jcd.cls.attribute; import java.io.IOException; import com.vladium.jcd.cls.ClassDef; import com.vladium.jcd.cls.IConstantCollection; import com.vladium.jcd.cls.constant.*; import com.vladium.jcd.compiler.IClassFormatOutput; import com.vladium.jcd.lib.UDataInputStream; import com.vladium.jcd.lib.UDataOutputStream; // ---------------------------------------------------------------------------- /** * Abstract base for all XXXAttribute_info structures. It also works in conjunction * with {@link GenericAttribute_info} class to process all unrecognized attributes.<P> * * Attributes are used in the {@link com.vladium.jcd.cls.ClassDef}, {@link com.vladium.jcd.cls.Field_info}, * {@link com.vladium.jcd.cls.Method_info}, and {@link CodeAttribute_info} * structures of the .class file format. All attributes have the following * general format: * <PRE> * attribute_info { * u2 attribute_name_index; * u4 attribute_length; * u1 info[attribute_length]; * } * </PRE> * * For all attributes, the attribute_name_index must be a valid unsigned 16-bit * index into the constant pool of the class. The constant pool entry at * attribute_name_index must be a {@link com.vladium.jcd.cls.constant.CONSTANT_Utf8_info} * string representing the name of the attribute. The value of the attribute_length * item indicates the length of the subsequent information in bytes. The length * does not include the initial six bytes that contain the attribute_name_index * and attribute_length items. * * @see GenericAttribute_info * * @author (C) 2001, Vlad Roubtsov */ public abstract class Attribute_info implements Cloneable, IClassFormatOutput { // public: ................................................................ public static final String ATTRIBUTE_CODE = "Code"; public static final String ATTRIBUTE_CONSTANT_VALUE = "ConstantValue"; public static final String ATTRIBUTE_LINE_NUMBER_TABLE = "LineNumberTable"; public static final String ATTRIBUTE_EXCEPTIONS = "Exceptions"; public static final String ATTRIBUTE_SYNTHETIC = "Synthetic"; public static final String ATTRIBUTE_BRIDGE = "Bridge"; public static final String ATTRIBUTE_SOURCEFILE = "SourceFile"; public static final String ATTRIBUTE_INNERCLASSES = "InnerClasses"; /** * Constant pool index for {@link com.vladium.jcd.cls.constant.CONSTANT_Utf8_info} * string representing the name of this attribute [always positive]. */ public int m_name_index; /** * Returns the name for this attribute within the constant pool context of 'cls' * class definition. * * @param cls class that contains this attribute * @return attribute name */ public String getName (final ClassDef cls) { return ((CONSTANT_Utf8_info) cls.getConstants ().get (m_name_index)).m_value; } /** * Returns the total length of this attribute when converted to * .class format [including the 6-byte header] */ public abstract long length (); // including the 6-byte header // Visitor: public abstract void accept (IAttributeVisitor visitor, Object ctx); public abstract String toString (); // TODO: use a hashmap lookup in this method + control which set of attrs get mapped to generic /** * Parses out a single Attribute_info element out of .class data in * 'bytes'. * * @param constants constant pool for the parent class [may not be null; not validated] * @param bytes input .class data stream [may not be null; not validated] * * @return a single parsed attribute * * @throws IOException on input errors */ public static Attribute_info new_Attribute_info (final IConstantCollection constants, final UDataInputStream bytes) throws IOException { final int attribute_name_index = bytes.readU2 (); final long attribute_length = bytes.readU4 (); final CONSTANT_Utf8_info attribute_name = (CONSTANT_Utf8_info) constants.get (attribute_name_index); final String name = attribute_name.m_value; if (ATTRIBUTE_CODE.equals (name)) { return new CodeAttribute_info (constants, attribute_name_index, attribute_length, bytes); } else if (ATTRIBUTE_CONSTANT_VALUE.equals (name)) { return new ConstantValueAttribute_info (attribute_name_index, attribute_length, bytes); } else if (ATTRIBUTE_EXCEPTIONS.equals (name)) { return new ExceptionsAttribute_info (attribute_name_index, attribute_length, bytes); } else if (ATTRIBUTE_INNERCLASSES.equals (name)) { return new InnerClassesAttribute_info (attribute_name_index, attribute_length, bytes); } else if (ATTRIBUTE_SYNTHETIC.equals (name)) { return new SyntheticAttribute_info (attribute_name_index, attribute_length); } else if (ATTRIBUTE_BRIDGE.equals (name)) { return new BridgeAttribute_info (attribute_name_index, attribute_length); } else if (ATTRIBUTE_LINE_NUMBER_TABLE.equals (name)) { return new LineNumberTableAttribute_info (attribute_name_index, attribute_length, bytes); } else if (ATTRIBUTE_SOURCEFILE.equals (name)) { return new SourceFileAttribute_info (attribute_name_index, attribute_length, bytes); } else { // default: return new GenericAttribute_info (attribute_name_index, attribute_length, bytes); } } // Cloneable: /** * Chains to super.clone() and removes CloneNotSupportedException * from the method signature. */ public Object clone () { try { return super.clone (); } catch (CloneNotSupportedException e) { throw new InternalError (e.toString ()); } } // IClassFormatOutput: public void writeInClassFormat (UDataOutputStream out) throws IOException { out.writeU2 (m_name_index); out.writeU4 (length () - 6); // don't use m_attribute_length } // protected: ............................................................. /* protected Attribute_info (UDataInputStream bytes) throws IOException { //m_name_index = bytes.readU2 (); //m_attribute_length = bytes.readU4 (); } */ protected Attribute_info (final int attribute_name_index, final long attribute_length) { m_name_index = attribute_name_index; m_attribute_length = attribute_length; } // TODO: remove this field as it is invalidated easily by most attribute mutations protected long m_attribute_length; // excluding the 6-byte header // package: ............................................................... // private: ............................................................... } // end of class // ----------------------------------------------------------------------------