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 
Attribute(byte tag, int name_index, int length, ConstantPool constant_pool)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    */
accept(Visitor v)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    */
dump(DataOutputStream file)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    */
addAttributeReader(String name, AttributeReader r)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    */
removeAttributeReader(String name)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    */
readAttribute(DataInputStream file, ConstantPool constant_pool)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    */
getLength()238   public final int   getLength()    { return length; }
239 
240   /**
241    * @param Attribute length in bytes.
242    */
setLength(int length)243   public final void setLength(int length) {
244     this.length = length;
245   }
246 
247   /**
248    * @param name_index of attribute.
249    */
setNameIndex(int name_index)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    */
getNameIndex()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    */
getTag()263   public final byte  getTag()       { return tag; }
264 
265   /**
266    * @return Constant pool used by this object.
267    * @see ConstantPool
268    */
getConstantPool()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    */
setConstantPool(ConstantPool constant_pool)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    */
clone()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    */
copy(ConstantPool constant_pool)300   public abstract Attribute copy(ConstantPool constant_pool);
301 
302   /**
303    * @return attribute name.
304    */
toString()305   public String toString() {
306     return Constants.ATTRIBUTE_NAMES[tag];
307   }
308 }
309