blob: ff6b25bf1877541640932a97e31da37573de0e6f [file] [log] [blame]
/* 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
// ----------------------------------------------------------------------------