• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License.  Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */
15 
16 package javassist.bytecode;
17 
18 import java.io.DataInputStream;
19 import java.io.DataOutputStream;
20 import java.io.IOException;
21 import java.util.Map;
22 import java.util.ArrayList;
23 import java.util.ListIterator;
24 import java.util.List;
25 import java.util.Iterator;
26 
27 // Note: if you define a new subclass of AttributeInfo, then
28 //       update AttributeInfo.read(), .copy(), and (maybe) write().
29 
30 /**
31  * <code>attribute_info</code> structure.
32  */
33 public class AttributeInfo {
34     protected ConstPool constPool;
35     int name;
36     byte[] info;
37 
AttributeInfo(ConstPool cp, int attrname, byte[] attrinfo)38     protected AttributeInfo(ConstPool cp, int attrname, byte[] attrinfo) {
39         constPool = cp;
40         name = attrname;
41         info = attrinfo;
42     }
43 
AttributeInfo(ConstPool cp, String attrname)44     protected AttributeInfo(ConstPool cp, String attrname) {
45         this(cp, attrname, (byte[])null);
46     }
47 
48     /**
49      * Constructs an <code>attribute_info</code> structure.
50      *
51      * @param cp                constant pool table
52      * @param attrname          attribute name
53      * @param attrinfo          <code>info</code> field
54      *                          of <code>attribute_info</code> structure.
55      */
AttributeInfo(ConstPool cp, String attrname, byte[] attrinfo)56     public AttributeInfo(ConstPool cp, String attrname, byte[] attrinfo) {
57         this(cp, cp.addUtf8Info(attrname), attrinfo);
58     }
59 
AttributeInfo(ConstPool cp, int n, DataInputStream in)60     protected AttributeInfo(ConstPool cp, int n, DataInputStream in)
61         throws IOException
62     {
63         constPool = cp;
64         name = n;
65         int len = in.readInt();
66         info = new byte[len];
67         if (len > 0)
68             in.readFully(info);
69     }
70 
read(ConstPool cp, DataInputStream in)71     static AttributeInfo read(ConstPool cp, DataInputStream in)
72         throws IOException
73     {
74         int name = in.readUnsignedShort();
75         String nameStr = cp.getUtf8Info(name);
76         if (nameStr.charAt(0) < 'L') {
77             if (nameStr.equals(AnnotationDefaultAttribute.tag))
78                 return new AnnotationDefaultAttribute(cp, name, in);
79             else if (nameStr.equals(CodeAttribute.tag))
80                 return new CodeAttribute(cp, name, in);
81             else if (nameStr.equals(ConstantAttribute.tag))
82                 return new ConstantAttribute(cp, name, in);
83             else if (nameStr.equals(DeprecatedAttribute.tag))
84                 return new DeprecatedAttribute(cp, name, in);
85             else if (nameStr.equals(EnclosingMethodAttribute.tag))
86                 return new EnclosingMethodAttribute(cp, name, in);
87             else if (nameStr.equals(ExceptionsAttribute.tag))
88                 return new ExceptionsAttribute(cp, name, in);
89             else if (nameStr.equals(InnerClassesAttribute.tag))
90                 return new InnerClassesAttribute(cp, name, in);
91         }
92         else {
93             /* Note that the names of Annotations attributes begin with 'R'.
94              */
95             if (nameStr.equals(LineNumberAttribute.tag))
96                 return new LineNumberAttribute(cp, name, in);
97             else if (nameStr.equals(LocalVariableAttribute.tag))
98                 return new LocalVariableAttribute(cp, name, in);
99             else if (nameStr.equals(LocalVariableTypeAttribute.tag))
100                 return new LocalVariableTypeAttribute(cp, name, in);
101             else if (nameStr.equals(AnnotationsAttribute.visibleTag)
102                      || nameStr.equals(AnnotationsAttribute.invisibleTag)) {
103                 // RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations
104                 return new AnnotationsAttribute(cp, name, in);
105             }
106             else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag)
107                 || nameStr.equals(ParameterAnnotationsAttribute.invisibleTag))
108                 return new ParameterAnnotationsAttribute(cp, name, in);
109             else if (nameStr.equals(SignatureAttribute.tag))
110                 return new SignatureAttribute(cp, name, in);
111             else if (nameStr.equals(SourceFileAttribute.tag))
112                 return new SourceFileAttribute(cp, name, in);
113             else if (nameStr.equals(SyntheticAttribute.tag))
114                 return new SyntheticAttribute(cp, name, in);
115             else if (nameStr.equals(StackMap.tag))
116                 return new StackMap(cp, name, in);
117             else if (nameStr.equals(StackMapTable.tag))
118                 return new StackMapTable(cp, name, in);
119         }
120 
121         return new AttributeInfo(cp, name, in);
122     }
123 
124     /**
125      * Returns an attribute name.
126      */
getName()127     public String getName() {
128         return constPool.getUtf8Info(name);
129     }
130 
131     /**
132      * Returns a constant pool table.
133      */
getConstPool()134     public ConstPool getConstPool() { return constPool; }
135 
136     /**
137      * Returns the length of this <code>attribute_info</code>
138      * structure.
139      * The returned value is <code>attribute_length + 6</code>.
140      */
length()141     public int length() {
142         return info.length + 6;
143     }
144 
145     /**
146      * Returns the <code>info</code> field
147      * of this <code>attribute_info</code> structure.
148      *
149      * <p>This method is not available if the object is an instance
150      * of <code>CodeAttribute</code>.
151      */
get()152     public byte[] get() { return info; }
153 
154     /**
155      * Sets the <code>info</code> field
156      * of this <code>attribute_info</code> structure.
157      *
158      * <p>This method is not available if the object is an instance
159      * of <code>CodeAttribute</code>.
160      */
set(byte[] newinfo)161     public void set(byte[] newinfo) { info = newinfo; }
162 
163     /**
164      * Makes a copy.  Class names are replaced according to the
165      * given <code>Map</code> object.
166      *
167      * @param newCp     the constant pool table used by the new copy.
168      * @param classnames        pairs of replaced and substituted
169      *                          class names.
170      */
copy(ConstPool newCp, Map classnames)171     public AttributeInfo copy(ConstPool newCp, Map classnames) {
172         int s = info.length;
173         byte[] srcInfo = info;
174         byte[] newInfo = new byte[s];
175         for (int i = 0; i < s; ++i)
176             newInfo[i] = srcInfo[i];
177 
178         return new AttributeInfo(newCp, getName(), newInfo);
179     }
180 
write(DataOutputStream out)181     void write(DataOutputStream out) throws IOException {
182         out.writeShort(name);
183         out.writeInt(info.length);
184         if (info.length > 0)
185             out.write(info);
186     }
187 
getLength(ArrayList list)188     static int getLength(ArrayList list) {
189         int size = 0;
190         int n = list.size();
191         for (int i = 0; i < n; ++i) {
192             AttributeInfo attr = (AttributeInfo)list.get(i);
193             size += attr.length();
194         }
195 
196         return size;
197     }
198 
lookup(ArrayList list, String name)199     static AttributeInfo lookup(ArrayList list, String name) {
200         if (list == null)
201             return null;
202 
203         ListIterator iterator = list.listIterator();
204         while (iterator.hasNext()) {
205             AttributeInfo ai = (AttributeInfo)iterator.next();
206             if (ai.getName().equals(name))
207                 return ai;
208         }
209 
210         return null;            // no such attribute
211     }
212 
remove(ArrayList list, String name)213     static synchronized void remove(ArrayList list, String name) {
214         if (list == null)
215             return;
216 
217         ListIterator iterator = list.listIterator();
218         while (iterator.hasNext()) {
219             AttributeInfo ai = (AttributeInfo)iterator.next();
220             if (ai.getName().equals(name))
221                 iterator.remove();
222         }
223     }
224 
writeAll(ArrayList list, DataOutputStream out)225     static void writeAll(ArrayList list, DataOutputStream out)
226         throws IOException
227     {
228         if (list == null)
229             return;
230 
231         int n = list.size();
232         for (int i = 0; i < n; ++i) {
233             AttributeInfo attr = (AttributeInfo)list.get(i);
234             attr.write(out);
235         }
236     }
237 
copyAll(ArrayList list, ConstPool cp)238     static ArrayList copyAll(ArrayList list, ConstPool cp) {
239         if (list == null)
240             return null;
241 
242         ArrayList newList = new ArrayList();
243         int n = list.size();
244         for (int i = 0; i < n; ++i) {
245             AttributeInfo attr = (AttributeInfo)list.get(i);
246             newList.add(attr.copy(cp, null));
247         }
248 
249         return newList;
250     }
251 
252     /* The following two methods are used to implement
253      * ClassFile.renameClass().
254      * Only CodeAttribute, LocalVariableAttribute,
255      * AnnotationsAttribute, and SignatureAttribute
256      * override these methods.
257      */
renameClass(String oldname, String newname)258     void renameClass(String oldname, String newname) {}
renameClass(Map classnames)259     void renameClass(Map classnames) {}
260 
renameClass(List attributes, String oldname, String newname)261     static void renameClass(List attributes, String oldname, String newname) {
262         Iterator iterator = attributes.iterator();
263         while (iterator.hasNext()) {
264             AttributeInfo ai = (AttributeInfo)iterator.next();
265             ai.renameClass(oldname, newname);
266         }
267     }
268 
renameClass(List attributes, Map classnames)269     static void renameClass(List attributes, Map classnames) {
270         Iterator iterator = attributes.iterator();
271         while (iterator.hasNext()) {
272             AttributeInfo ai = (AttributeInfo)iterator.next();
273             ai.renameClass(classnames);
274         }
275     }
276 
getRefClasses(Map classnames)277     void getRefClasses(Map classnames) {}
278 
getRefClasses(List attributes, Map classnames)279     static void getRefClasses(List attributes, Map classnames) {
280         Iterator iterator = attributes.iterator();
281         while (iterator.hasNext()) {
282             AttributeInfo ai = (AttributeInfo)iterator.next();
283             ai.getRefClasses(classnames);
284         }
285     }
286 }
287