View Javadoc

1   package serp.bytecode;
2   
3   import java.io.*;
4   import java.util.*;
5   
6   import serp.bytecode.lowlevel.*;
7   
8   /***
9    * A member field or method of a class.
10   *
11   * @author Abe White
12   */
13  public abstract class BCMember extends Annotated {
14      private BCClass _owner = null;
15      private int _access = Constants.ACCESS_PRIVATE;
16      private int _nameIndex = 0;
17      private int _descriptorIndex = 0;
18      private Collection _attrs = new LinkedList();
19  
20      BCMember(BCClass owner) {
21          _owner = owner;
22      }
23  
24      /***
25       * Return the {@link BCClass} that declares this member.
26       */
27      public BCClass getDeclarer() {
28          return _owner;
29      }
30  
31      /////////////////////
32      // Access operations
33      /////////////////////
34  
35      /***
36       * Return the access flags for this member as a bit array of
37       * ACCESS_XXX constants from {@link Constants}. This can be used to
38       * transfer access flags between members without getting/setting each
39       * possible access flag. Defaults to {@link Constants#ACCESS_PRIVATE}
40       */
41      public int getAccessFlags() {
42          return _access;
43      }
44  
45      /***
46       * Set the access flags for this member as a bit array of
47       * ACCESS_XXX constants from {@link Constants}. This can be used to
48       * transfer access flags between members without getting/setting each
49       * possible access flag. Defaults to {@link Constants#ACCESS_PRIVATE}
50       */
51      public void setAccessFlags(int access) {
52          _access = access;
53      }
54  
55      /***
56       * Manipulate the member access flags.
57       */
58      public boolean isPublic() {
59          return (getAccessFlags() & Constants.ACCESS_PUBLIC) > 0;
60      }
61  
62      /***
63       * Manipulate the member access flags.
64       */
65      public void makePublic() {
66          setAccessFlags(getAccessFlags() | Constants.ACCESS_PUBLIC);
67          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE);
68          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED);
69      }
70  
71      /***
72       * Manipulate the member access flags.
73       */
74      public boolean isProtected() {
75          return (getAccessFlags() & Constants.ACCESS_PROTECTED) > 0;
76      }
77  
78      /***
79       * Manipulate the member access flags.
80       */
81      public void makeProtected() {
82          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC);
83          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE);
84          setAccessFlags(getAccessFlags() | Constants.ACCESS_PROTECTED);
85      }
86  
87      /***
88       * Manipulate the member access flags.
89       */
90      public boolean isPrivate() {
91          return (getAccessFlags() & Constants.ACCESS_PRIVATE) > 0;
92      }
93  
94      /***
95       * Manipulate the member access flags.
96       */
97      public void makePrivate() {
98          setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC);
99          setAccessFlags(getAccessFlags() | Constants.ACCESS_PRIVATE);
100         setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED);
101     }
102 
103     /***
104      * Manipulate the member access flags.
105      */
106     public boolean isPackage() {
107         boolean hasAccess = false;
108         hasAccess |= (getAccessFlags() & Constants.ACCESS_PRIVATE) > 0;
109         hasAccess |= (getAccessFlags() & Constants.ACCESS_PROTECTED) > 0;
110         hasAccess |= (getAccessFlags() & Constants.ACCESS_PUBLIC) > 0;
111         return !hasAccess;
112     }
113 
114     /***
115      * Manipulate the member access flags.
116      */
117     public void makePackage() {
118         setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC);
119         setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE);
120         setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED);
121     }
122 
123     /***
124      * Manipulate the member access flags.
125      */
126     public boolean isFinal() {
127         return (getAccessFlags() & Constants.ACCESS_FINAL) > 0;
128     }
129 
130     /***
131      * Manipulate the member access flags.
132      */
133     public void setFinal(boolean on) {
134         if (on)
135             setAccessFlags(getAccessFlags() | Constants.ACCESS_FINAL);
136         else
137             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_FINAL);
138     }
139 
140     /***
141      * Manipulate the member access flags.
142      */
143     public boolean isStatic() {
144         return (getAccessFlags() & Constants.ACCESS_STATIC) > 0;
145     }
146 
147     /***
148      * Manipulate the member access flags.
149      */
150     public void setStatic(boolean on) {
151         if (on)
152             setAccessFlags(getAccessFlags() | Constants.ACCESS_STATIC);
153         else
154             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_STATIC);
155     }
156 
157     /***
158      * Manipulate the field access flags.  This method also checks the synthetic
159      * member attribute.
160      */
161     public boolean isSynthetic() {
162         return (getAccessFlags() & Constants.ACCESS_SYNTHETIC) > 0
163             || getAttribute(Constants.ATTR_SYNTHETIC) != null;
164     }
165 
166     /***
167      * Manipulate the field access flags.  This method also manipulates the
168      * synthetic member attribute.
169      */
170     public void setSynthetic(boolean on) {
171         if (on) {
172             setAccessFlags(getAccessFlags() | Constants.ACCESS_SYNTHETIC);
173             addAttribute(Constants.ATTR_SYNTHETIC);
174         } else {
175             setAccessFlags(getAccessFlags() & ~Constants.ACCESS_SYNTHETIC);
176             removeAttribute(Constants.ATTR_SYNTHETIC);
177         }
178     }
179 
180     /////////////////////////
181     // Descriptor operations
182     /////////////////////////
183 
184     /***
185      * Return the index in the class {@link ConstantPool} of the
186      * {@link UTF8Entry} holding the name of this member.
187      */
188     public int getNameIndex() {
189         return _nameIndex;
190     }
191 
192     /***
193      * Set the index in the class {@link ConstantPool} of the
194      * {@link UTF8Entry} holding the name of this member.
195      */
196     public void setNameIndex(int index) {
197         String origName = getName();
198         _nameIndex = index;
199         // change all the references in the owning class
200         setEntry(origName, getDescriptor());
201     }
202 
203     /***
204      * Return the index in the class {@link ConstantPool} of the
205      * {@link UTF8Entry} holding the descriptor of this member.
206      */
207     public int getDescriptorIndex() {
208         return _descriptorIndex;
209     }
210 
211     /***
212      * Set the index in the class {@link ConstantPool} of the
213      * {@link UTF8Entry} holding the descriptor of this member.
214      */
215     public void setDescriptorIndex(int index) {
216         String origDesc = getDescriptor();
217         _descriptorIndex = index;
218         // change all the references in the owning class
219         setEntry(getName(), origDesc);
220     }
221 
222     /***
223      * Return the name of this member.
224      */
225     public String getName() {
226         return ((UTF8Entry) getPool().getEntry(_nameIndex)).getValue();
227     }
228 
229     /***
230      * Set the name of this member.
231      */
232     public void setName(String name) {
233         String origName = getName();
234         // reset the name
235         _nameIndex = getPool().findUTF8Entry(name, true);
236         // change all references in the owning class
237         setEntry(origName, getDescriptor());
238     }
239 
240     /***
241      * Return the descriptor of this member, in internal form.
242      */
243     public String getDescriptor() {
244         return ((UTF8Entry) getPool().getEntry(_descriptorIndex)).getValue();
245     }
246 
247     /***
248      * Set the descriptor of this member.
249      */
250     public void setDescriptor(String desc) {
251         String origDesc = getDescriptor();
252         // reset the desc
253         desc = getProject().getNameCache().getInternalForm(desc, true);
254         _descriptorIndex = getPool().findUTF8Entry(desc, true);
255         // change all the references in the owning class
256         setEntry(getName(), origDesc);
257     }
258 
259     /***
260      * Resets the {@link ComplexEntry} of the owning class corresponding to
261      * this member. Changes in the member will therefore propogate to all
262      * code in the class.
263      */
264     private void setEntry(String origName, String origDesc) {
265         // find the entry matching this member, if any
266         String owner = getProject().getNameCache().getInternalForm
267             (_owner.getName(), false);
268         ConstantPool pool = getPool();
269         int index;
270         if (this instanceof BCField)
271             index = pool.findFieldEntry(origName, origDesc, owner, false);
272         else if (!_owner.isInterface())
273             index = pool.findMethodEntry(origName, origDesc, owner, false);
274         else
275             index = pool.findInterfaceMethodEntry(origName, origDesc, owner,
276                 false);
277 
278         // change the entry to match the new info; this is dones so
279         // that refs to the member in code will still be valid after the 
280         // change, without changing any other constants that happened to match
281         // the old name and/or descriptor
282         if (index != 0) {
283             ComplexEntry complex = (ComplexEntry) pool.getEntry(index);
284             int ntIndex = pool.findNameAndTypeEntry(getName(), getDescriptor(),
285                 true);
286             complex.setNameAndTypeIndex(ntIndex);
287         }
288     }
289 
290     ///////////////////////
291     // Convenience methods
292     ///////////////////////
293 
294     /***
295      * Convenience method to return deprecation information for the member.
296      * Acts internally through the {@link Attributes} interface.
297      */
298     public boolean isDeprecated() {
299         return getAttribute(Constants.ATTR_DEPRECATED) != null;
300     }
301 
302     /***
303      * Convenience method to set whether this member should be considered
304      * deprecated. Acts internally through the {@link Attributes} interface.
305      */
306     public void setDeprecated(boolean on) {
307         if (!on)
308             removeAttribute(Constants.ATTR_DEPRECATED);
309         else if (!isDeprecated())
310             addAttribute(Constants.ATTR_DEPRECATED);
311     }
312 
313     ////////////////////////////////
314     // Implementation of Attributes
315     ////////////////////////////////
316 
317     public Project getProject() {
318         return _owner.getProject();
319     }
320 
321     public ConstantPool getPool() {
322         return _owner.getPool();
323     }
324 
325     public ClassLoader getClassLoader() {
326         return _owner.getClassLoader();
327     }
328 
329     public boolean isValid() {
330         return _owner != null;
331     }
332 
333     Collection getAttributesHolder() {
334         return _attrs;
335     }
336 
337     /***
338      * Either this method or {@link #read} must be called prior to use
339      * of this class. The given descriptor must be in internal form.
340      */
341     void initialize(String name, String descriptor) {
342         _nameIndex = getPool().findUTF8Entry(name, true);
343         _descriptorIndex = getPool().findUTF8Entry(descriptor, true);
344     }
345 
346     ///////////////////////////////
347     // Implementation of Annotated
348     ///////////////////////////////
349 
350     BCClass getBCClass() {
351         return _owner;
352     }
353 
354     /***
355      * Used when this member is deleted from its class.
356      */
357     void invalidate() {
358         _owner = null;
359     }
360 
361     void read(DataInput in) throws IOException {
362         _access = in.readUnsignedShort();
363         _nameIndex = in.readUnsignedShort();
364         _descriptorIndex = in.readUnsignedShort();
365         readAttributes(in);
366     }
367 
368     void write(DataOutput out) throws IOException {
369         out.writeShort(_access);
370         out.writeShort(_nameIndex);
371         out.writeShort(_descriptorIndex);
372         writeAttributes(out);
373     }
374 }