View Javadoc

1   /*
2    * Copyright  2000-2004 The Apache Software Foundation
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
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; // Points to attribute name in constant pool
52      protected int length; // Content length of attribute field
53      protected byte tag; // Tag to distiguish subclasses
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     /* Class method reads one attribute from the input data stream.
111      * This method must not be accessible from the outside.  It is
112      * called by the Field and Method constructor methods.
113      *
114      * @see    Field
115      * @see    Method
116      * @param  file Input stream
117      * @param  constant_pool Array of constants
118      * @return Attribute
119      * @throws  IOException
120      * @throws  ClassFormatException
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; // Unknown attribute
129         // Get class name from constant pool via `name_index' indirection
130         name_index = file.readUnsignedShort();
131         c = (ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8);
132         name = c.getBytes();
133         // Length of data in bytes
134         length = file.readInt();
135         // Compare strings to find known attribute
136         for (byte i = 0; i < Constants.KNOWN_ATTRIBUTES; i++) {
137             if (name.equals(Constants.ATTRIBUTE_NAMES[i])) {
138                 tag = i; // found!
139                 break;
140             }
141         }
142         // Call proper constructor, depending on `tag'
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                 //    case Constants.ATTR_RUNTIMEVISIBLE_ANNOTATIONS:
175                 //      return new RuntimeVisibleAnnotations(name_index, length, file, constant_pool);
176                 //    case Constants.ATTR_RUNTIMEINVISIBLE_ANNOTATIONS:
177                 //      return new RuntimeInvisibleAnnotations(name_index, length, file, constant_pool);
178                 //    case Constants.ATTR_RUNTIMEVISIBLE_PARAMETER_ANNOTATIONS:
179                 //      return new RuntimeVisibleParameterAnnotations(name_index, length, file, constant_pool);
180                 //    case Constants.ATTR_RUNTIMEINVISIBLE_PARAMETER_ANNOTATIONS:
181                 //      return new RuntimeInvisibleParameterAnnotations(name_index, length, file, constant_pool);
182                 //    case Constants.ATTR_ANNOTATION_DEFAULT:
183                 //      return new AnnotationDefault(name_index, length, file, constant_pool);
184             default: // Never reached
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(); // Never occurs
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 }