1 package serp.bytecode;
2
3 import serp.bytecode.visitor.*;
4 import serp.util.*;
5
6 /***
7 * A method of a class.
8 *
9 * @author Abe White
10 */
11 public class BCMethod extends BCMember implements VisitAcceptor {
12 BCMethod(BCClass owner) {
13 super(owner);
14 }
15
16
17
18
19
20 /***
21 * Manipulate the method access flags.
22 */
23 public boolean isSynchronized() {
24 return (getAccessFlags() & Constants.ACCESS_SYNCHRONIZED) > 0;
25 }
26
27 /***
28 * Manipulate the method access flags.
29 */
30 public void setSynchronized(boolean on) {
31 if (on)
32 setAccessFlags(getAccessFlags() | Constants.ACCESS_SYNCHRONIZED);
33 else
34 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_SYNCHRONIZED);
35 }
36
37 /***
38 * Manipulate the method access flags.
39 */
40 public boolean isNative() {
41 return (getAccessFlags() & Constants.ACCESS_NATIVE) > 0;
42 }
43
44 /***
45 * Manipulate the method access flags.
46 */
47 public void setNative(boolean on) {
48 if (on)
49 setAccessFlags(getAccessFlags() | Constants.ACCESS_NATIVE);
50 else
51 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_NATIVE);
52 }
53
54 /***
55 * Manipulate the method access flags.
56 */
57 public boolean isAbstract() {
58 return (getAccessFlags() & Constants.ACCESS_ABSTRACT) > 0;
59 }
60
61 /***
62 * Manipulate the method access flags.
63 */
64 public void setAbstract(boolean on) {
65 if (on)
66 setAccessFlags(getAccessFlags() | Constants.ACCESS_ABSTRACT);
67 else
68 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_ABSTRACT);
69 }
70
71 /***
72 * Manipulate the method access flags.
73 */
74 public boolean isStrict() {
75 return (getAccessFlags() & Constants.ACCESS_STRICT) > 0;
76 }
77
78 /***
79 * Manipulate the method access flags.
80 */
81 public void setStrict(boolean on) {
82 if (on)
83 setAccessFlags(getAccessFlags() | Constants.ACCESS_STRICT);
84 else
85 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_STRICT);
86 }
87
88 /***
89 * Manipulate the method access flags.
90 */
91 public boolean isVarArgs() {
92 return (getAccessFlags() & Constants.ACCESS_VARARGS) > 0;
93 }
94
95 /***
96 * Manipulate the method access flags.
97 */
98 public void setVarArgs(boolean on) {
99 if (on)
100 setAccessFlags(getAccessFlags() | Constants.ACCESS_VARARGS);
101 else
102 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_VARARGS);
103 }
104
105 /***
106 * Manipulate the method access flags.
107 */
108 public boolean isBridge() {
109 return (getAccessFlags() & Constants.ACCESS_BRIDGE) > 0;
110 }
111
112 /***
113 * Manipulate the method access flags.
114 */
115 public void setBridge(boolean on) {
116 if (on)
117 setAccessFlags(getAccessFlags() | Constants.ACCESS_BRIDGE);
118 else
119 setAccessFlags(getAccessFlags() & ~Constants.ACCESS_BRIDGE);
120 }
121
122
123
124
125
126 /***
127 * Return the name of the type returned by this method. The name
128 * will be given in a form suitable for a {@link Class#forName} call.
129 *
130 * @see BCMember#getDescriptor
131 */
132 public String getReturnName() {
133 return getProject().getNameCache().getExternalForm(getProject().
134 getNameCache().getDescriptorReturnName(getDescriptor()), false);
135 }
136
137 /***
138 * Return the {@link Class} object for the return type of this method.
139 *
140 * @see BCMember#getDescriptor
141 */
142 public Class getReturnType() {
143 return Strings.toClass(getReturnName(), getClassLoader());
144 }
145
146 /***
147 * Return the bytecode for the return type of this method.
148 *
149 * @see BCMember#getDescriptor
150 */
151 public BCClass getReturnBC() {
152 return getProject().loadClass(getReturnName(), getClassLoader());
153 }
154
155 /***
156 * Set the return type of this method.
157 */
158 public void setReturn(String name) {
159 setDescriptor(getProject().getNameCache().getDescriptor(name,
160 getParamNames()));
161 }
162
163 /***
164 * Set the return type of this method.
165 */
166 public void setReturn(Class type) {
167 setReturn(type.getName());
168 }
169
170 /***
171 * Set the return type of this method.
172 */
173 public void setReturn(BCClass type) {
174 setReturn(type.getName());
175 }
176
177
178
179
180
181 /***
182 * Return the names of all the parameter types for this method. The names
183 * will be returned in a form suitable for a {@link Class#forName} call.
184 *
185 * @see BCMember#getDescriptor
186 */
187 public String[] getParamNames() {
188
189 String[] params = getProject().getNameCache().getDescriptorParamNames
190 (getDescriptor());
191
192
193 for (int i = 0; i < params.length; i++)
194 params[i] = getProject().getNameCache().getExternalForm(params[i],
195 false);
196 return params;
197 }
198
199 /***
200 * Return the {@link Class} objects for all the parameter types for this
201 * method.
202 *
203 * @see BCMember#getDescriptor
204 */
205 public Class[] getParamTypes() {
206 String[] paramNames = getParamNames();
207 Class[] params = new Class[paramNames.length];
208 for (int i = 0; i < paramNames.length; i++)
209 params[i] = Strings.toClass(paramNames[i], getClassLoader());
210 return params;
211 }
212
213 /***
214 * Return the bytecode for all the parameter types for this method.
215 *
216 * @see BCMember#getDescriptor
217 */
218 public BCClass[] getParamBCs() {
219 String[] paramNames = getParamNames();
220 BCClass[] params = new BCClass[paramNames.length];
221 for (int i = 0; i < paramNames.length; i++)
222 params[i] = getProject().loadClass(paramNames[i], getClassLoader());
223 return params;
224 }
225
226 /***
227 * Set the parameter types of this method.
228 *
229 * @see BCMember#setDescriptor
230 */
231 public void setParams(String[] names) {
232 if (names == null)
233 names = new String[0];
234 setDescriptor(getProject().getNameCache().getDescriptor(getReturnName(),
235 names));
236 }
237
238 /***
239 * Set the parameter type of this method.
240 *
241 * @see BCMember#setDescriptor
242 */
243 public void setParams(Class[] types) {
244 if (types == null)
245 setParams((String[]) null);
246 else {
247 String[] names = new String[types.length];
248 for (int i = 0; i < types.length; i++)
249 names[i] = types[i].getName();
250 setParams(names);
251 }
252 }
253
254 /***
255 * Set the parameter type of this method.
256 *
257 * @see BCMember#setDescriptor
258 */
259 public void setParams(BCClass[] types) {
260 if (types == null)
261 setParams((String[]) null);
262 else {
263 String[] names = new String[types.length];
264 for (int i = 0; i < types.length; i++)
265 names[i] = types[i].getName();
266 setParams(names);
267 }
268 }
269
270 /***
271 * Add a parameter type to this method.
272 */
273 public void addParam(String type) {
274 String[] origParams = getParamNames();
275 String[] params = new String[origParams.length + 1];
276 for (int i = 0; i < origParams.length; i++)
277 params[i] = origParams[i];
278 params[origParams.length] = type;
279 setParams(params);
280 }
281
282 /***
283 * Add a parameter type to this method.
284 */
285 public void addParam(Class type) {
286 addParam(type.getName());
287 }
288
289 /***
290 * Add a parameter type to this method.
291 */
292 public void addParam(BCClass type) {
293 addParam(type.getName());
294 }
295
296 /***
297 * Add a parameter type to this method.
298 *
299 * @see java.util.List#add(int,Object)
300 */
301 public void addParam(int pos, String type) {
302 String[] origParams = getParamNames();
303 if ((pos < 0) || (pos >= origParams.length))
304 throw new IndexOutOfBoundsException("pos = " + pos);
305
306 String[] params = new String[origParams.length + 1];
307 for (int i = 0, index = 0; i < params.length; i++) {
308 if (i == pos)
309 params[i] = type;
310 else
311 params[i] = origParams[index++];
312 }
313 setParams(params);
314 }
315
316 /***
317 * Add a parameter type to this method.
318 *
319 * @see java.util.List#add(int,Object)
320 */
321 public void addParam(int pos, Class type) {
322 addParam(pos, type.getName());
323 }
324
325 /***
326 * Add a parameter type to this method.
327 *
328 * @see java.util.List#add(int,Object)
329 */
330 public void addParam(int pos, BCClass type) {
331 addParam(pos, type.getName());
332 }
333
334 /***
335 * Change a parameter type of this method.
336 *
337 * @see java.util.List#set(int,Object)
338 */
339 public void setParam(int pos, String type) {
340 String[] origParams = getParamNames();
341 if ((pos < 0) || (pos >= origParams.length))
342 throw new IndexOutOfBoundsException("pos = " + pos);
343
344 String[] params = new String[origParams.length];
345 for (int i = 0; i < params.length; i++) {
346 if (i == pos)
347 params[i] = type;
348 else
349 params[i] = origParams[i];
350 }
351 setParams(params);
352 }
353
354 /***
355 * Change a parameter type of this method.
356 *
357 * @see java.util.List#set(int,Object)
358 */
359 public void setParam(int pos, Class type) {
360 setParam(pos, type.getName());
361 }
362
363 /***
364 * Change a parameter type of this method.
365 *
366 * @see java.util.List#set(int,Object)
367 */
368 public void setParam(int pos, BCClass type) {
369 setParam(pos, type.getName());
370 }
371
372 /***
373 * Clear all parameters from this method.
374 */
375 public void clearParams() {
376 setParams((String[]) null);
377 }
378
379 /***
380 * Remove a parameter from this method.
381 */
382 public void removeParam(int pos) {
383 String[] origParams = getParamNames();
384 if ((pos < 0) || (pos >= origParams.length))
385 throw new IndexOutOfBoundsException("pos = " + pos);
386
387 String[] params = new String[origParams.length - 1];
388
389 for (int i = 0, index = 0; i < origParams.length; i++)
390 if (i != pos)
391 params[index++] = origParams[i];
392 setParams(params);
393 }
394
395
396
397
398
399 /***
400 * Return the checked exceptions information for the method.
401 * Acts internally through the {@link Attributes} interface.
402 *
403 * @param add if true, a new exceptions attribute will be added
404 * if not already present
405 * @return the exceptions information, or null if none and the
406 * <code>add</code> param is set to false
407 */
408 public Exceptions getExceptions(boolean add) {
409 Exceptions exceptions = (Exceptions) getAttribute
410 (Constants.ATTR_EXCEPTIONS);
411 if (!add || (exceptions != null))
412 return exceptions;
413
414 if (exceptions == null)
415 exceptions = (Exceptions) addAttribute(Constants.ATTR_EXCEPTIONS);
416 return exceptions;
417 }
418
419 /***
420 * Remove the exceptions attribute for the method.
421 * Acts internally through the {@link Attributes} interface.
422 *
423 * @return true if there was a value to remove
424 */
425 public boolean removeExceptions() {
426 return removeAttribute(Constants.ATTR_EXCEPTIONS);
427 }
428
429 /***
430 * Return the code for the method. If the code already exists, its
431 * iterator will be reset to the first instruction.
432 * Acts internally through the {@link Attributes} interface.
433 *
434 * @param add if true, a new code attribute will be added
435 * if not already present
436 * @return the code for the metohd, or null if none and the
437 * <code>add</code> param is set to false
438 */
439 public Code getCode(boolean add) {
440 Code code = (Code) getAttribute(Constants.ATTR_CODE);
441 if (code != null) {
442 code.beforeFirst();
443 return code;
444 }
445 if (!add)
446 return null;
447 return (Code) addAttribute(Constants.ATTR_CODE);
448 }
449
450 /***
451 * Remove the code attribute from the method.
452 * Acts internally through the {@link Attributes} interface.
453 *
454 * @return true if there was a value to remove
455 */
456 public boolean removeCode() {
457 return removeAttribute(Constants.ATTR_CODE);
458 }
459
460
461
462
463
464 public void acceptVisit(BCVisitor visit) {
465 visit.enterBCMethod(this);
466 visitAttributes(visit);
467 visit.exitBCMethod(this);
468 }
469
470 void initialize(String name, String descriptor) {
471 super.initialize(name, descriptor);
472 makePublic();
473 }
474 }