KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > bytecode > JavaMethod


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.bytecode;
31
32 import com.caucho.log.Log;
33
34 import java.io.ByteArrayInputStream JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.lang.reflect.*;
37 import java.util.ArrayList JavaDoc;
38 import java.util.logging.Level JavaDoc;
39 import java.util.logging.Logger JavaDoc;
40
41 /**
42  * Represents a java field.
43  */

44 public class JavaMethod extends JMethod {
45   static private final Logger JavaDoc log = Log.open(JavaMethod.class);
46
47   private static final JClass []NULL_CLASS = new JClass[0];
48
49   private JavaClassLoader _loader;
50
51   private JavaClass _jClass;
52
53   private int _accessFlags;
54   private String JavaDoc _name;
55   private String JavaDoc _descriptor;
56   private JClass []_exceptions = NULL_CLASS;
57   private int _line = -1;
58
59   private ArrayList JavaDoc<Attribute> _attributes = new ArrayList JavaDoc<Attribute>();
60
61   private JavaAnnotation []_annotations;
62
63   public JavaMethod(JavaClassLoader loader)
64   {
65     _loader = loader;
66   }
67
68   public JavaMethod()
69   {
70   }
71
72   /**
73    * Sets the JavaClass.
74    */

75   public void setJavaClass(JavaClass jClass)
76   {
77     _jClass = jClass;
78   }
79
80   /**
81    * Sets the name.
82    */

83   public void setName(String JavaDoc name)
84   {
85     _name = name;
86
87     if (_jClass != null)
88       _jClass.getConstantPool().addUTF8(name);
89   }
90
91   /**
92    * Gets the name.
93    */

94   public String JavaDoc getName()
95   {
96     return _name;
97   }
98
99   /**
100    * Returns the line number.
101    */

102   public int getLine()
103   {
104     if (_line >= 0)
105       return _line;
106
107     Attribute attr = getAttribute("LineNumberTable");
108
109     if (attr == null) {
110       _line = 0;
111       return _line;
112     }
113
114     _line = 0;
115     return _line;
116   }
117
118   /**
119    * Returns the class loader.
120    */

121   public JavaClassLoader getClassLoader()
122   {
123     return _loader;
124   }
125
126   /**
127    * Sets the access flags
128    */

129   public void setAccessFlags(int flags)
130   {
131     _accessFlags = flags;
132   }
133
134   /**
135    * Gets the access flags
136    */

137   public int getAccessFlags()
138   {
139     return _accessFlags;
140   }
141
142   /**
143    * Returns true for a final method
144    */

145   public boolean isFinal()
146   {
147     return Modifier.isFinal(getAccessFlags());
148   }
149
150   /**
151    * Returns true for a public method
152    */

153   public boolean isPublic()
154   {
155     return Modifier.isPublic(getAccessFlags());
156   }
157
158   /**
159    * Returns true for a private method
160    */

161   public boolean isPrivate()
162   {
163     return Modifier.isPrivate(getAccessFlags());
164   }
165
166   /**
167    * Returns true for an abstract method
168    */

169   public boolean isAbstract()
170   {
171     return Modifier.isAbstract(getAccessFlags());
172   }
173
174   /**
175    * Returns true for a static method
176    */

177   public boolean isStatic()
178   {
179     return Modifier.isStatic(getAccessFlags());
180   }
181
182   /**
183    * Sets the descriptor.
184    */

185   public void setDescriptor(String JavaDoc descriptor)
186   {
187     _descriptor = descriptor;
188
189     if (_jClass != null)
190       _jClass.getConstantPool().addUTF8(descriptor);
191   }
192
193   /**
194    * Gets the descriptor.
195    */

196   public String JavaDoc getDescriptor()
197   {
198     return _descriptor;
199   }
200
201   /**
202    * Returns the declaring class.
203    */

204   public JClass getDeclaringClass()
205   {
206     return _jClass;
207   }
208
209   /**
210    * Returns the return types.
211    */

212   public JClass getReturnType()
213   {
214     String JavaDoc descriptor = getDescriptor();
215
216     int i = descriptor.lastIndexOf(')');
217
218     return getClassLoader().descriptorToClass(descriptor, i + 1);
219   }
220
221   /**
222    * Returns the return type.
223    */

224   public JType getGenericReturnType()
225   {
226     SignatureAttribute sigAttr = (SignatureAttribute) getAttribute("Signature");
227
228     if (sigAttr != null) {
229       String JavaDoc sig = sigAttr.getSignature();
230
231       int t = sig.lastIndexOf(')');
232
233       return _loader.parseParameterizedType(sig.substring(t + 1));
234     }
235
236     return getReturnType();
237   }
238
239   /**
240    * Returns the parameter types.
241    */

242   public JClass []getParameterTypes()
243   {
244     String JavaDoc descriptor = getDescriptor();
245
246     ArrayList JavaDoc<JClass> typeList = new ArrayList JavaDoc<JClass>();
247
248     int i = 0;
249     while ((i = nextDescriptor(descriptor, i)) >= 0) {
250       typeList.add(getClassLoader().descriptorToClass(descriptor, i));
251     }
252
253     JClass []types = new JClass[typeList.size()];
254
255     typeList.toArray(types);
256
257     return types;
258   }
259
260   private int nextDescriptor(String JavaDoc name, int i)
261   {
262     switch (name.charAt(i)) {
263     case ')':
264       return -1;
265
266     case '(':
267     case 'V':
268     case 'Z':
269     case 'C':
270     case 'B':
271     case 'S':
272     case 'I':
273     case 'J':
274     case 'F':
275     case 'D':
276       i += 1;
277       break;
278
279     case '[':
280       return nextDescriptor(name, i + 1);
281
282     case 'L':
283       {
284   int tail = name.indexOf( ';', i);
285
286   if (tail < 0)
287     throw new IllegalStateException JavaDoc();
288
289   i = tail + 1;
290       }
291       break;
292
293     default:
294       throw new UnsupportedOperationException JavaDoc(name.substring(i));
295     }
296
297     if (name.length() <= i)
298       return -1;
299     else if (name.charAt(i) == ')')
300       return -1;
301     else
302       return i;
303   }
304
305   /**
306    * Sets the exception types
307    */

308   public void setExceptionTypes(JClass []exceptions)
309   {
310     _exceptions = exceptions;
311   }
312
313   /**
314    * Returns the exception types.
315    */

316   public JClass []getExceptionTypes()
317   {
318     return _exceptions;
319   }
320
321   /**
322    * Adds an attribute.
323    */

324   public void addAttribute(Attribute attr)
325   {
326     _attributes.add(attr);
327   }
328
329   /**
330    * Removes an attribute.
331    */

332   public Attribute removeAttribute(String JavaDoc name)
333   {
334     for (int i = _attributes.size() - 1; i >= 0; i--) {
335       Attribute attr = _attributes.get(i);
336
337       if (attr.getName().equals(name)) {
338     _attributes.remove(i);
339     return attr;
340       }
341     }
342
343     return null;
344   }
345
346   /**
347    * Returns the attribute.
348    */

349   public ArrayList JavaDoc<Attribute> getAttributes()
350   {
351     return _attributes;
352   }
353
354   /**
355    * Returns the attribute.
356    */

357   public Attribute getAttribute(String JavaDoc name)
358   {
359     for (int i = _attributes.size() - 1; i >= 0; i--) {
360       Attribute attr = _attributes.get(i);
361
362       if (attr.getName().equals(name))
363   return attr;
364     }
365
366     return null;
367   }
368
369   /**
370    * Returns the declared annotations.
371    */

372   public JAnnotation []getDeclaredAnnotations()
373   {
374     if (_annotations == null) {
375       Attribute attr = getAttribute("RuntimeVisibleAnnotations");
376
377       if (attr instanceof OpaqueAttribute) {
378   byte []buffer = ((OpaqueAttribute) attr).getValue();
379
380   try {
381     ByteArrayInputStream JavaDoc is = new ByteArrayInputStream JavaDoc(buffer);
382
383     ConstantPool cp = _jClass.getConstantPool();
384
385     _annotations = JavaAnnotation.parseAnnotations(is, cp,
386                getClassLoader());
387   } catch (IOException JavaDoc e) {
388     log.log(Level.FINER, e.toString(), e);
389   }
390       }
391
392       if (_annotations == null) {
393   _annotations = new JavaAnnotation[0];
394       }
395     }
396
397     return _annotations;
398   }
399
400   /**
401    * Returns the code attribute.
402    */

403   public CodeAttribute getCode()
404   {
405     for (int i = 0; i < _attributes.size(); i++) {
406       Attribute attr = _attributes.get(i);
407
408       if (attr instanceof CodeAttribute)
409   return (CodeAttribute) attr;
410     }
411
412     return null;
413   }
414
415
416   /**
417    * Writes the field to the output.
418    */

419   public void write(ByteCodeWriter out)
420     throws IOException JavaDoc
421   {
422     out.writeShort(_accessFlags);
423     out.writeUTF8Const(_name);
424     out.writeUTF8Const(_descriptor);
425
426     out.writeShort(_attributes.size());
427     for (int i = 0; i < _attributes.size(); i++) {
428       Attribute attr = _attributes.get(i);
429
430       attr.write(out);
431     }
432   }
433
434   /**
435    * exports the method.
436    */

437   public JavaMethod export(JavaClass source, JavaClass target)
438   {
439     JavaMethod method = new JavaMethod(_loader);
440     method.setName(_name);
441     method.setDescriptor(_descriptor);
442     method.setAccessFlags(_accessFlags);
443
444     target.getConstantPool().addUTF8(_name);
445     target.getConstantPool().addUTF8(_descriptor);
446
447     for (int i = 0; i < _attributes.size(); i++) {
448       Attribute attr = _attributes.get(i);
449
450       method.addAttribute(attr.export(source, target));
451     }
452
453     return method;
454   }
455
456   /**
457    * Concatenates the method.
458    */

459   public void concatenate(JavaMethod tail)
460   {
461     CodeAttribute codeAttr = getCode();
462     CodeAttribute tailCodeAttr = tail.getCode();
463
464     byte []code = codeAttr.getCode();
465     byte []tailCode = tailCodeAttr.getCode();
466
467     int codeLength = code.length;
468
469     if ((code[codeLength - 1] & 0xff) == CodeVisitor.RETURN)
470       codeLength = codeLength - 1;
471
472     byte []newCode = new byte[codeLength + tailCode.length];
473     System.arraycopy(code, 0, newCode, 0, codeLength);
474     System.arraycopy(tailCode, 0, newCode, codeLength, tailCode.length);
475
476     codeAttr.setCode(newCode);
477
478     if (codeAttr.getMaxStack() < tailCodeAttr.getMaxStack())
479       codeAttr.setMaxStack(tailCodeAttr.getMaxStack());
480
481     if (codeAttr.getMaxLocals() < tailCodeAttr.getMaxLocals())
482       codeAttr.setMaxLocals(tailCodeAttr.getMaxLocals());
483
484     ArrayList JavaDoc<CodeAttribute.ExceptionItem> exns = tailCodeAttr.getExceptions();
485     for (int i = 0; i < exns.size(); i++) {
486       CodeAttribute.ExceptionItem exn = exns.get(i);
487
488       CodeAttribute.ExceptionItem newExn = new CodeAttribute.ExceptionItem();
489
490       newExn.setType(exn.getType());
491       newExn.setStart(exn.getStart() + codeLength);
492       newExn.setEnd(exn.getEnd() + codeLength);
493       newExn.setHandler(exn.getHandler() + codeLength);
494     }
495   }
496
497   public String JavaDoc toString()
498   {
499     return "JavaMethod[" + _name + "]";
500   }
501 }
502
Popular Tags