View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   package com.sun.org.apache.bcel.internal.classfile;
6   
7   /* ====================================================================
8    * The Apache Software License, Version 1.1
9    *
10   * Copyright (c) 2001 The Apache Software Foundation.  All rights
11   * reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions
15   * are met:
16   *
17   * 1. Redistributions of source code must retain the above copyright
18   *    notice, this list of conditions and the following disclaimer.
19   *
20   * 2. Redistributions in binary form must reproduce the above copyright
21   *    notice, this list of conditions and the following disclaimer in
22   *    the documentation and/or other materials provided with the
23   *    distribution.
24   *
25   * 3. The end-user documentation included with the redistribution,
26   *    if any, must include the following acknowledgment:
27   *       "This product includes software developed by the
28   *        Apache Software Foundation (http://www.apache.org/)."
29   *    Alternately, this acknowledgment may appear in the software itself,
30   *    if and wherever such third-party acknowledgments normally appear.
31   *
32   * 4. The names "Apache" and "Apache Software Foundation" and
33   *    "Apache BCEL" must not be used to endorse or promote products
34   *    derived from this software without prior written permission. For
35   *    written permission, please contact apache@apache.org.
36   *
37   * 5. Products derived from this software may not be called "Apache",
38   *    "Apache BCEL", nor may "Apache" appear in their name, without
39   *    prior written permission of the Apache Software Foundation.
40   *
41   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52   * SUCH DAMAGE.
53   * ====================================================================
54   *
55   * This software consists of voluntary contributions made by many
56   * individuals on behalf of the Apache Software Foundation.  For more
57   * information on the Apache Software Foundation, please see
58   * <http://www.apache.org/>.
59   */
60  
61  import com.sun.org.apache.bcel.internal.Constants;
62  import java.io.*;
63  import java.util.HashMap;
64  
65  /**
66   * Abstract super class for <em>Attribute</em> objects. Currently the
67   * <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>,
68   * <em>Exceptiontable</em>, <em>LineNumberTable</em>,
69   * <em>LocalVariableTable</em>, <em>InnerClasses</em> and
70   * <em>Synthetic</em> attributes are supported. The
71   * <em>Unknown</em> attribute stands for non-standard-attributes.
72   *
73   * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
74   * @see     ConstantValue
75   * @see     SourceFile
76   * @see     Code
77   * @see     Unknown
78   * @see     ExceptionTable
79   * @see     LineNumberTable
80   * @see     LocalVariableTable
81   * @see     InnerClasses
82   * @see     Synthetic
83   * @see     Deprecated
84   * @see     Signature
85  */
86  public abstract class Attribute implements Cloneable, Node, Serializable {
87    protected int          name_index; // Points to attribute name in constant pool
88    protected int          length;     // Content length of attribute field
89    protected byte         tag;        // Tag to distiguish subclasses
90    protected ConstantPool constant_pool;
91  
92    protected Attribute(byte tag, int name_index, int length,
93                        ConstantPool constant_pool) {
94      this.tag           = tag;
95      this.name_index    = name_index;
96      this.length        = length;
97      this.constant_pool = constant_pool;
98    }
99  
100   /**
101    * Called by objects that are traversing the nodes of the tree implicitely
102    * defined by the contents of a Java class. I.e., the hierarchy of methods,
103    * fields, attributes, etc. spawns a tree of objects.
104    *
105    * @param v Visitor object
106    */
107   public abstract void accept(Visitor v);
108 
109   /**
110    * Dump attribute to file stream in binary format.
111    *
112    * @param file Output file stream
113    * @throws IOException
114    */
115   public void dump(DataOutputStream file) throws IOException
116   {
117     file.writeShort(name_index);
118     file.writeInt(length);
119   }
120 
121   private static HashMap readers = new HashMap();
122 
123   /** Add an Attribute reader capable of parsing (user-defined) attributes
124    * named "name". You should not add readers for the standard attributes
125    * such as "LineNumberTable", because those are handled internally.
126    *
127    * @param name the name of the attribute as stored in the class file
128    * @param r the reader object
129    */
130   public static void addAttributeReader(String name, AttributeReader r) {
131     readers.put(name, r);
132   }
133 
134   /** Remove attribute reader
135    *
136    * @param name the name of the attribute as stored in the class file
137    */
138   public static void removeAttributeReader(String name) {
139     readers.remove(name);
140   }
141 
142   /* Class method reads one attribute from the input data stream.
143    * This method must not be accessible from the outside.  It is
144    * called by the Field and Method constructor methods.
145    *
146    * @see    Field
147    * @see    Method
148    * @param  file Input stream
149    * @param  constant_pool Array of constants
150    * @return Attribute
151    * @throws  IOException
152    * @throws  ClassFormatException
153    */
154   public static final Attribute readAttribute(DataInputStream file,
155                                               ConstantPool constant_pool)
156     throws IOException, ClassFormatException
157   {
158     ConstantUtf8 c;
159     String       name;
160     int          name_index;
161     int          length;
162     byte         tag = Constants.ATTR_UNKNOWN; // Unknown attribute
163 
164     // Get class name from constant pool via `name_index' indirection
165     name_index = (int)file.readUnsignedShort();
166     c          = (ConstantUtf8)constant_pool.getConstant(name_index,
167                                                          Constants.CONSTANT_Utf8);
168     name       = c.getBytes();
169 
170     // Length of data in bytes
171     length = file.readInt();
172 
173     // Compare strings to find known attribute
174     for(byte i=0; i < Constants.KNOWN_ATTRIBUTES; i++) {
175       if(name.equals(Constants.ATTRIBUTE_NAMES[i])) {
176         tag = i; // found!
177         break;
178       }
179     }
180 
181     // Call proper constructor, depending on `tag'
182     switch(tag) {
183     case Constants.ATTR_UNKNOWN:
184       AttributeReader r = (AttributeReader)readers.get(name);
185 
186       if(r != null)
187         return r.createAttribute(name_index, length, file, constant_pool);
188       else
189         return new Unknown(name_index, length, file, constant_pool);
190 
191     case Constants.ATTR_CONSTANT_VALUE:
192       return new ConstantValue(name_index, length, file, constant_pool);
193 
194     case Constants.ATTR_SOURCE_FILE:
195       return new SourceFile(name_index, length, file, constant_pool);
196 
197     case Constants.ATTR_CODE:
198       return new Code(name_index, length, file, constant_pool);
199 
200     case Constants.ATTR_EXCEPTIONS:
201       return new ExceptionTable(name_index, length, file, constant_pool);
202 
203     case Constants.ATTR_LINE_NUMBER_TABLE:
204       return new LineNumberTable(name_index, length, file, constant_pool);
205 
206     case Constants.ATTR_LOCAL_VARIABLE_TABLE:
207       return new LocalVariableTable(name_index, length, file, constant_pool);
208 
209     case Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
210       return new LocalVariableTypeTable(name_index, length, file, constant_pool);
211 
212     case Constants.ATTR_INNER_CLASSES:
213       return new InnerClasses(name_index, length, file, constant_pool);
214 
215     case Constants.ATTR_SYNTHETIC:
216       return new Synthetic(name_index, length, file, constant_pool);
217 
218     case Constants.ATTR_DEPRECATED:
219       return new Deprecated(name_index, length, file, constant_pool);
220 
221     case Constants.ATTR_PMG:
222       return new PMGClass(name_index, length, file, constant_pool);
223 
224     case Constants.ATTR_SIGNATURE:
225       return new Signature(name_index, length, file, constant_pool);
226 
227     case Constants.ATTR_STACK_MAP:
228       return new StackMap(name_index, length, file, constant_pool);
229 
230     default: // Never reached
231       throw new IllegalStateException("Ooops! default case reached.");
232     }
233   }
234 
235   /**
236    * @return Length of attribute field in bytes.
237    */
238   public final int   getLength()    { return length; }
239 
240   /**
241    * @param Attribute length in bytes.
242    */
243   public final void setLength(int length) {
244     this.length = length;
245   }
246 
247   /**
248    * @param name_index of attribute.
249    */
250   public final void setNameIndex(int name_index) {
251     this.name_index = name_index;
252   }
253 
254   /**
255    * @return Name index in constant pool of attribute name.
256    */
257   public final int getNameIndex() { return name_index; }
258 
259   /**
260    * @return Tag of attribute, i.e., its type. Value may not be altered, thus
261    * there is no setTag() method.
262    */
263   public final byte  getTag()       { return tag; }
264 
265   /**
266    * @return Constant pool used by this object.
267    * @see ConstantPool
268    */
269   public final ConstantPool getConstantPool() { return constant_pool; }
270 
271   /**
272    * @param constant_pool Constant pool to be used for this object.
273    * @see ConstantPool
274    */
275   public final void setConstantPool(ConstantPool constant_pool) {
276     this.constant_pool = constant_pool;
277   }
278 
279   /**
280    * Use copy() if you want to have a deep copy(), i.e., with all references
281    * copied correctly.
282    *
283    * @return shallow copy of this attribute
284    */
285   public Object clone() {
286     Object o = null;
287 
288     try {
289       o = super.clone();
290     } catch(CloneNotSupportedException e) {
291       e.printStackTrace(); // Never occurs
292     }
293 
294     return o;
295   }
296 
297   /**
298    * @return deep copy of this attribute
299    */
300   public abstract Attribute copy(ConstantPool constant_pool);
301 
302   /**
303    * @return attribute name.
304    */
305   public String toString() {
306     return Constants.ATTRIBUTE_NAMES[tag];
307   }
308 }