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 */ getName(final ClassDef cls)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 */ length()85 public abstract long length (); // including the 6-byte header 86 87 // Visitor: 88 accept(IAttributeVisitor visitor, Object ctx)89 public abstract void accept (IAttributeVisitor visitor, Object ctx); 90 toString()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 */ new_Attribute_info(final IConstantCollection constants, final UDataInputStream bytes)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 */ clone()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 writeInClassFormat(UDataOutputStream out)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 Attribute_info(final int attribute_name_index, final long attribute_length)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