001 package serp.bytecode;
002
003 import java.io.*;
004 import java.util.*;
005
006 import serp.bytecode.lowlevel.*;
007
008 /**
009 * A member field or method of a class.
010 *
011 * @author Abe White
012 */
013 public abstract class BCMember extends Annotated {
014 private BCClass _owner = null;
015 private int _access = Constants.ACCESS_PRIVATE;
016 private int _nameIndex = 0;
017 private int _descriptorIndex = 0;
018 private Collection _attrs = new LinkedList();
019
020 BCMember(BCClass owner) {
021 _owner = owner;
022 }
023
024 /**
025 * Return the {@link BCClass} that declares this member.
026 */
027 public BCClass getDeclarer() {
028 return _owner;
029 }
030
031 /////////////////////
032 // Access operations
033 /////////////////////
034
035 /**
036 * Return the access flags for this member as a bit array of
037 * ACCESS_XXX constants from {@link Constants}. This can be used to
038 * transfer access flags between members without getting/setting each
039 * possible access flag. Defaults to {@link Constants#ACCESS_PRIVATE}
040 */
041 public int getAccessFlags() {
042 return _access;
043 }
044
045 /**
046 * Set the access flags for this member as a bit array of
047 * ACCESS_XXX constants from {@link Constants}. This can be used to
048 * transfer access flags between members without getting/setting each
049 * possible access flag. Defaults to {@link Constants#ACCESS_PRIVATE}
050 */
051 public void setAccessFlags(int access) {
052 _access = access;
053 }
054
055 /**
056 * Manipulate the member access flags.
057 */
058 public boolean isPublic() {
059 return (getAccessFlags() & Constants.ACCESS_PUBLIC) > 0;
060 }
061
062 /**
063 * Manipulate the member access flags.
064 */
065 public void makePublic() {
066 setAccessFlags(getAccessFlags() | Constants.ACCESS_PUBLIC);
067 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE);
068 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PROTECTED);
069 }
070
071 /**
072 * Manipulate the member access flags.
073 */
074 public boolean isProtected() {
075 return (getAccessFlags() & Constants.ACCESS_PROTECTED) > 0;
076 }
077
078 /**
079 * Manipulate the member access flags.
080 */
081 public void makeProtected() {
082 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC);
083 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PRIVATE);
084 setAccessFlags(getAccessFlags() | Constants.ACCESS_PROTECTED);
085 }
086
087 /**
088 * Manipulate the member access flags.
089 */
090 public boolean isPrivate() {
091 return (getAccessFlags() & Constants.ACCESS_PRIVATE) > 0;
092 }
093
094 /**
095 * Manipulate the member access flags.
096 */
097 public void makePrivate() {
098 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_PUBLIC);
099 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 }