• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999- 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  * or the Apache License Version 2.0.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  */
16 
17 package javassist.bytecode;
18 
19 import java.io.DataInputStream;
20 import java.io.DataOutputStream;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.List;
24 
25 /**
26  * <code>field_info</code> structure.
27  *
28  * <p>The following code adds a public field <code>width</code>
29  * of <code>int</code> type:
30  * <blockquote><pre>
31  * ClassFile cf = ...
32  * FieldInfo f = new FieldInfo(cf.getConstPool(), "width", "I");
33  * f.setAccessFlags(AccessFlag.PUBLIC);
34  * cf.addField(f);
35  * </pre></blockquote>
36  *
37  * @see javassist.CtField#getFieldInfo()
38  */
39 public final class FieldInfo {
40     ConstPool constPool;
41     int accessFlags;
42     int name;
43     String cachedName;
44     String cachedType;
45     int descriptor;
46     List<AttributeInfo> attribute;       // may be null.
47 
FieldInfo(ConstPool cp)48     private FieldInfo(ConstPool cp) {
49         constPool = cp;
50         accessFlags = 0;
51         attribute = null;
52     }
53 
54     /**
55      * Constructs a <code>field_info</code> structure.
56      *
57      * @param cp                a constant pool table
58      * @param fieldName         field name
59      * @param desc              field descriptor
60      *
61      * @see Descriptor
62      */
FieldInfo(ConstPool cp, String fieldName, String desc)63     public FieldInfo(ConstPool cp, String fieldName, String desc) {
64         this(cp);
65         name = cp.addUtf8Info(fieldName);
66         cachedName = fieldName;
67         descriptor = cp.addUtf8Info(desc);
68     }
69 
FieldInfo(ConstPool cp, DataInputStream in)70     FieldInfo(ConstPool cp, DataInputStream in) throws IOException {
71         this(cp);
72         read(in);
73     }
74 
75     /**
76      * Returns a string representation of the object.
77      */
78     @Override
toString()79     public String toString() {
80         return getName() + " " + getDescriptor();
81     }
82 
83     /**
84      * Copies all constant pool items to a given new constant pool
85      * and replaces the original items with the new ones.
86      * This is used for garbage collecting the items of removed fields
87      * and methods.
88      *
89      * @param cp    the destination
90      */
compact(ConstPool cp)91     void compact(ConstPool cp) {
92         name = cp.addUtf8Info(getName());
93         descriptor = cp.addUtf8Info(getDescriptor());
94         attribute = AttributeInfo.copyAll(attribute, cp);
95         constPool = cp;
96     }
97 
prune(ConstPool cp)98     void prune(ConstPool cp) {
99         List<AttributeInfo> newAttributes = new ArrayList<AttributeInfo>();
100         AttributeInfo invisibleAnnotations
101             = getAttribute(AnnotationsAttribute.invisibleTag);
102         if (invisibleAnnotations != null) {
103             invisibleAnnotations = invisibleAnnotations.copy(cp, null);
104             newAttributes.add(invisibleAnnotations);
105          }
106 
107         AttributeInfo visibleAnnotations
108             = getAttribute(AnnotationsAttribute.visibleTag);
109         if (visibleAnnotations != null) {
110             visibleAnnotations = visibleAnnotations.copy(cp, null);
111             newAttributes.add(visibleAnnotations);
112         }
113 
114         AttributeInfo signature
115             = getAttribute(SignatureAttribute.tag);
116         if (signature != null) {
117             signature = signature.copy(cp, null);
118             newAttributes.add(signature);
119         }
120 
121         int index = getConstantValue();
122         if (index != 0) {
123             index = constPool.copy(index, cp, null);
124             newAttributes.add(new ConstantAttribute(cp, index));
125         }
126 
127         attribute = newAttributes;
128         name = cp.addUtf8Info(getName());
129         descriptor = cp.addUtf8Info(getDescriptor());
130         constPool = cp;
131     }
132 
133     /**
134      * Returns the constant pool table used
135      * by this <code>field_info</code>.
136      */
getConstPool()137     public ConstPool getConstPool() {
138         return constPool;
139     }
140 
141     /**
142      * Returns the field name.
143      */
getName()144     public String getName() {
145        if (cachedName == null)
146            cachedName = constPool.getUtf8Info(name);
147 
148        return cachedName;
149     }
150 
151     /**
152      * Sets the field name.
153      */
setName(String newName)154     public void setName(String newName) {
155         name = constPool.addUtf8Info(newName);
156         cachedName = newName;
157     }
158 
159     /**
160      * Returns the access flags.
161      *
162      * @see AccessFlag
163      */
getAccessFlags()164     public int getAccessFlags() {
165         return accessFlags;
166     }
167 
168     /**
169      * Sets the access flags.
170      *
171      * @see AccessFlag
172      */
setAccessFlags(int acc)173     public void setAccessFlags(int acc) {
174         accessFlags = acc;
175     }
176 
177     /**
178      * Returns the field descriptor.
179      *
180      * @see Descriptor
181      */
getDescriptor()182     public String getDescriptor() {
183         return constPool.getUtf8Info(descriptor);
184     }
185 
186     /**
187      * Sets the field descriptor.
188      *
189      * @see Descriptor
190      */
setDescriptor(String desc)191     public void setDescriptor(String desc) {
192         if (!desc.equals(getDescriptor()))
193             descriptor = constPool.addUtf8Info(desc);
194     }
195 
196     /**
197      * Finds a ConstantValue attribute and returns the index into
198      * the <code>constant_pool</code> table.
199      *
200      * @return 0    if a ConstantValue attribute is not found.
201      */
getConstantValue()202     public int getConstantValue() {
203         if ((accessFlags & AccessFlag.STATIC) == 0)
204             return 0;
205 
206         ConstantAttribute attr
207             = (ConstantAttribute)getAttribute(ConstantAttribute.tag);
208         if (attr == null)
209             return 0;
210         return attr.getConstantValue();
211     }
212 
213     /**
214      * Returns all the attributes.    The returned <code>List</code> object
215      * is shared with this object.  If you add a new attribute to the list,
216      * the attribute is also added to the field represented by this
217      * object.  If you remove an attribute from the list, it is also removed
218      * from the field.
219      *
220      * @return a list of <code>AttributeInfo</code> objects.
221      * @see AttributeInfo
222      */
getAttributes()223     public List<AttributeInfo> getAttributes() {
224         if (attribute == null)
225             attribute = new ArrayList<AttributeInfo>();
226 
227         return attribute;
228     }
229 
230     /**
231      * Returns the attribute with the specified name.
232      * It returns null if the specified attribute is not found.
233      *
234      * <p>An attribute name can be obtained by, for example,
235      * {@link AnnotationsAttribute#visibleTag} or
236      * {@link AnnotationsAttribute#invisibleTag}.
237      * </p>
238      *
239      * @param name      attribute name
240      * @see #getAttributes()
241      */
getAttribute(String name)242     public AttributeInfo getAttribute(String name) {
243         return AttributeInfo.lookup(attribute, name);
244     }
245 
246     /**
247      * Removes an attribute with the specified name.
248      *
249      * @param name      attribute name.
250      * @return          the removed attribute or null.
251      * @since 3.21
252      */
removeAttribute(String name)253     public AttributeInfo removeAttribute(String name) {
254         return AttributeInfo.remove(attribute, name);
255     }
256 
257     /**
258      * Appends an attribute.  If there is already an attribute with
259      * the same name, the new one substitutes for it.
260      *
261      * @see #getAttributes()
262      */
addAttribute(AttributeInfo info)263     public void addAttribute(AttributeInfo info) {
264         if (attribute == null)
265             attribute = new ArrayList<AttributeInfo>();
266 
267         AttributeInfo.remove(attribute, info.getName());
268         attribute.add(info);
269     }
270 
read(DataInputStream in)271     private void read(DataInputStream in) throws IOException {
272         accessFlags = in.readUnsignedShort();
273         name = in.readUnsignedShort();
274         descriptor = in.readUnsignedShort();
275         int n = in.readUnsignedShort();
276         attribute = new ArrayList<AttributeInfo>();
277         for (int i = 0; i < n; ++i)
278             attribute.add(AttributeInfo.read(constPool, in));
279     }
280 
write(DataOutputStream out)281     void write(DataOutputStream out) throws IOException {
282         out.writeShort(accessFlags);
283         out.writeShort(name);
284         out.writeShort(descriptor);
285         if (attribute == null)
286             out.writeShort(0);
287         else {
288             out.writeShort(attribute.size());
289             AttributeInfo.writeAll(attribute, out);
290         }
291     }
292 }
293