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
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
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
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
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
235 _nameIndex = getPool().findUTF8Entry(name, true);
236
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
253 desc = getProject().getNameCache().getInternalForm(desc, true);
254 _descriptorIndex = getPool().findUTF8Entry(desc, true);
255
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
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
279
280
281
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
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
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
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 }