1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
52 protected int length;
53 protected byte tag;
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
111
112
113
114
115
116
117
118
119
120
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;
129
130 name_index = file.readUnsignedShort();
131 c = (ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8);
132 name = c.getBytes();
133
134 length = file.readInt();
135
136 for (byte i = 0; i < Constants.KNOWN_ATTRIBUTES; i++) {
137 if (name.equals(Constants.ATTRIBUTE_NAMES[i])) {
138 tag = i;
139 break;
140 }
141 }
142
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
175
176
177
178
179
180
181
182
183
184 default:
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();
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 }