001// Method.java - Represent method of class or interface.
002
003/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007  Free Software Foundation
004
005   This file is part of libgcj.
006
007This software is copyrighted work licensed under the terms of the
008Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
009details.  */
010 
011package java.lang.reflect;
012
013import gnu.gcj.RawData;
014import gnu.java.lang.reflect.MethodSignatureParser;
015import java.lang.annotation.Annotation;
016
017/**
018 * The Method class represents a member method of a class. It also allows
019 * dynamic invocation, via reflection. This works for both static and
020 * instance methods. Invocation on Method objects knows how to do
021 * widening conversions, but throws {@link IllegalArgumentException} if
022 * a narrowing conversion would be necessary. You can query for information
023 * on this Method regardless of location, but invocation access may be limited
024 * by Java language access controls. If you can't do it in the compiler, you
025 * can't normally do it here either.<p>
026 *
027 * <B>Note:</B> This class returns and accepts types as Classes, even
028 * primitive types; there are Class types defined that represent each
029 * different primitive type.  They are <code>java.lang.Boolean.TYPE,
030 * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
031 * byte.class</code>, etc.  These are not to be confused with the
032 * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
033 * real classes.<p>
034 *
035 * Also note that this is not a serializable class.  It is entirely feasible
036 * to make it serializable using the Externalizable interface, but this is
037 * on Sun, not me.
038 *
039 * @author John Keiser
040 * @author Eric Blake <ebb9@email.byu.edu>
041 * @author Tom Tromey <tromey@redhat.com>
042 * @see Member
043 * @see Class
044 * @see java.lang.Class#getMethod(String,Class[])
045 * @see java.lang.Class#getDeclaredMethod(String,Class[])
046 * @see java.lang.Class#getMethods()
047 * @see java.lang.Class#getDeclaredMethods()
048 * @since 1.1
049 * @status updated to 1.4
050 */
051public final class Method
052  extends AccessibleObject implements Member, GenericDeclaration
053{
054  static final int METHOD_MODIFIERS
055    = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE
056      | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC
057      | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED;
058
059  /**
060   * This class is uninstantiable.
061   */
062  private Method ()
063  {
064  }
065
066  /**
067   * Gets the class that declared this method, or the class where this method
068   * is a non-inherited member.
069   * @return the class that declared this member
070   */
071  public Class<?> getDeclaringClass()
072  {
073    return declaringClass;
074  }
075
076  /**
077   * Gets the name of this method.
078   * @return the name of this method
079   */
080  public native String getName ();
081
082  /**
083   * Return the raw modifiers for this method.
084   * @return the method's modifiers
085   */
086  private native int getModifiersInternal();
087
088  /**
089   * Gets the modifiers this method uses.  Use the <code>Modifier</code>
090   * class to interpret the values.  A method can only have a subset of the
091   * following modifiers: public, private, protected, abstract, static,
092   * final, synchronized, native, and strictfp.
093   *
094   * @return an integer representing the modifiers to this Member
095   * @see Modifier
096   */
097  public int getModifiers()
098  {
099    return getModifiersInternal() & METHOD_MODIFIERS;
100  }
101
102  /**
103   * Return true if this method is a bridge method.  A bridge method
104   * is generated by the compiler in some situations involving
105   * generics and inheritance.
106   * @since 1.5
107   */
108  public boolean isBridge()
109  {
110    return (getModifiersInternal() & Modifier.BRIDGE) != 0;
111  }
112
113  /**
114   * Return true if this method is synthetic, false otherwise.
115   * @since 1.5
116   */
117  public boolean isSynthetic()
118  {
119    return (getModifiersInternal() & Modifier.SYNTHETIC) != 0;
120  }
121
122  /**
123   * Return true if this is a varargs method, that is if
124   * the method takes a variable number of arguments.
125   * @since 1.5
126   */
127  public boolean isVarArgs()
128  {
129    return (getModifiersInternal() & Modifier.VARARGS) != 0;
130  }
131
132  /**
133   * Gets the return type of this method.
134   * @return the type of this method
135   */
136  public Class<?> getReturnType ()
137  {
138    if (return_type == null)
139      getType();
140    return return_type;
141  }
142
143  /**
144   * Get the parameter list for this method, in declaration order. If the
145   * method takes no parameters, returns a 0-length array (not null).
146   *
147   * @return a list of the types of the method's parameters
148   */
149  public Class<?>[] getParameterTypes ()
150  {
151    if (parameter_types == null)
152      getType();
153    return (Class<?>[]) parameter_types.clone();
154  }
155
156  // Just like getParameterTypes, but don't clone the array.
157  // Package private for use by VMProxy.
158  final Class<?>[] internalGetParameterTypes ()
159  {
160    if (parameter_types == null)
161      getType();
162    return (Class<?>[]) parameter_types;
163  }
164
165  /**
166   * Get the exception types this method says it throws, in no particular
167   * order. If the method has no throws clause, returns a 0-length array
168   * (not null).
169   *
170   * @return a list of the types in the method's throws clause
171   */
172  public Class<?>[] getExceptionTypes ()
173  {
174    if (exception_types == null)
175      getType();
176    return (Class<?>[]) exception_types.clone();
177  }
178
179  // Just like getExceptionTypes, but don't clone the array.
180  // Package private for use by VMProxy.
181  final Class<?>[] internalGetExceptionTypes ()
182  {
183    if (exception_types == null)
184      getType();
185    return (Class<?>[]) exception_types;
186  }
187
188  /**
189   * Compare two objects to see if they are semantically equivalent.
190   * Two Methods are semantically equivalent if they have the same declaring
191   * class, name, and parameter list.  This ignores different exception
192   * clauses or return types.
193   *
194   * @param o the object to compare to
195   * @return <code>true</code> if they are equal; <code>false</code> if not
196   */
197  public boolean equals (Object obj)
198  {
199    if (! (obj instanceof Method))
200      return false;
201    Method m = (Method) obj;
202    return declaringClass == m.declaringClass && offset == m.offset;
203  }
204
205  /**
206   * Get the hash code for the Method. The Method hash code is the hash code
207   * of its name XOR'd with the hash code of its class name.
208   *
209   * @return the hash code for the object
210   */
211  public int hashCode()
212  {
213    return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
214  }
215
216  /**
217   * Get a String representation of the Method. A Method's String
218   * representation is "&lt;modifiers&gt; &lt;returntype&gt;
219   * &lt;methodname&gt;(&lt;paramtypes&gt;) throws &lt;exceptions&gt;", where
220   * everything after ')' is omitted if there are no exceptions.<br> Example:
221   * <code>public static int run(java.lang.Runnable,int)</code>
222   *
223   * @return the String representation of the Method
224   */
225  public String toString()
226  {
227    if (parameter_types == null)
228      getType ();
229
230    StringBuffer b = new StringBuffer ();
231    int mods = getModifiers();
232    if (mods != 0)
233      {
234        Modifier.toString(mods, b);
235        b.append(" ");
236      }
237    appendClassName (b, return_type);
238    b.append(" ");
239    appendClassName (b, declaringClass);
240    b.append(".");
241    b.append(getName());
242    b.append("(");
243    for (int i = 0; i < parameter_types.length; ++i)
244      {
245        appendClassName (b, parameter_types[i]);
246        if (i < parameter_types.length - 1)
247          b.append(",");
248      }
249    b.append(")");
250    if (exception_types.length > 0)
251      {
252        b.append(" throws ");
253        for (int i = 0; i < exception_types.length; ++i)
254          {
255            appendClassName (b, exception_types[i]);
256            if (i < exception_types.length - 1)
257              b.append(",");
258          }
259      }
260    return b.toString();
261  }
262
263  public String toGenericString()
264  {
265    // 128 is a reasonable buffer initial size for constructor
266    StringBuilder sb = new StringBuilder(128);
267    Modifier.toString(getModifiers(), sb).append(' ');
268    Constructor.addTypeParameters(sb, getTypeParameters());
269    sb.append(getGenericReturnType()).append(' ');
270    sb.append(getDeclaringClass().getName()).append('.');
271    sb.append(getName()).append('(');
272    Type[] types = getGenericParameterTypes();
273    if (types.length > 0)
274      {
275        sb.append(types[0]);
276        for (int i = 1; i < types.length; i++)
277          sb.append(',').append(types[i]);
278      }
279    sb.append(')');
280    types = getGenericExceptionTypes();
281    if (types.length > 0)
282      {
283        sb.append(" throws ").append(types[0]);
284        for (int i = 1; i < types.length; i++)
285          sb.append(',').append(types[i]);
286      }
287    return sb.toString();
288  }
289
290  /**
291   * Invoke the method. Arguments are automatically unwrapped and widened,
292   * and the result is automatically wrapped, if needed.<p>
293   *
294   * If the method is static, <code>o</code> will be ignored. Otherwise,
295   * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot
296   * mimic the behavior of nonvirtual lookup (as in super.foo()). This means
297   * you will get a <code>NullPointerException</code> if <code>o</code> is
298   * null, and an <code>IllegalArgumentException</code> if it is incompatible
299   * with the declaring class of the method. If the method takes 0 arguments,
300   * you may use null or a 0-length array for <code>args</code>.<p>
301   *
302   * Next, if this Method enforces access control, your runtime context is
303   * evaluated, and you may have an <code>IllegalAccessException</code> if
304   * you could not acces this method in similar compiled code. If the method
305   * is static, and its class is uninitialized, you trigger class
306   * initialization, which may end in a
307   * <code>ExceptionInInitializerError</code>.<p>
308   *
309   * Finally, the method is invoked. If it completes normally, the return value
310   * will be null for a void method, a wrapped object for a primitive return
311   * method, or the actual return of an Object method. If it completes
312   * abruptly, the exception is wrapped in an
313   * <code>InvocationTargetException</code>.
314   *
315   * @param o the object to invoke the method on
316   * @param args the arguments to the method
317   * @return the return value of the method, wrapped in the appropriate
318   *         wrapper if it is primitive
319   * @throws IllegalAccessException if the method could not normally be called
320   *         by the Java code (i.e. it is not public)
321   * @throws IllegalArgumentException if the number of arguments is incorrect;
322   *         if the arguments types are wrong even with a widening conversion;
323   *         or if <code>o</code> is not an instance of the class or interface
324   *         declaring this method
325   * @throws InvocationTargetException if the method throws an exception
326   * @throws NullPointerException if <code>o</code> is null and this field
327   *         requires an instance
328   * @throws ExceptionInInitializerError if accessing a static method triggered
329   *         class initialization, which then failed
330   */
331  public native Object invoke (Object obj, Object... args)
332    throws IllegalAccessException, IllegalArgumentException,
333    InvocationTargetException;
334
335  /**
336   * Returns an array of <code>TypeVariable</code> objects that represents
337   * the type variables declared by this constructor, in declaration order.
338   * An array of size zero is returned if this class has no type
339   * variables.
340   *
341   * @return the type variables associated with this class. 
342   * @throws GenericSignatureFormatError if the generic signature does
343   *         not conform to the format specified in the Virtual Machine
344   *         specification, version 3.
345   * @since 1.5
346   */
347  public TypeVariable<Method>[] getTypeParameters()
348  {
349    String sig = getSignature();
350    if (sig == null)
351      return new TypeVariable[0];
352    MethodSignatureParser p = new MethodSignatureParser(this, sig);
353    return p.getTypeParameters();
354  }
355
356  /**
357   * Return the String in the Signature attribute for this method. If there
358   * is no Signature attribute, return null.
359   */
360  private native String getSignature();
361
362  /**
363   * Returns an array of <code>Type</code> objects that represents
364   * the exception types declared by this method, in declaration order.
365   * An array of size zero is returned if this method declares no
366   * exceptions.
367   *
368   * @return the exception types declared by this method. 
369   * @throws GenericSignatureFormatError if the generic signature does
370   *         not conform to the format specified in the Virtual Machine
371   *         specification, version 3.
372   * @since 1.5
373   */
374  public Type[] getGenericExceptionTypes()
375  {
376    String sig = getSignature();
377    if (sig == null)
378      return getExceptionTypes();
379    MethodSignatureParser p = new MethodSignatureParser(this, sig);
380    return p.getGenericExceptionTypes();
381  }
382
383  /**
384   * Returns an array of <code>Type</code> objects that represents
385   * the parameter list for this method, in declaration order.
386   * An array of size zero is returned if this method takes no
387   * parameters.
388   *
389   * @return a list of the types of the method's parameters
390   * @throws GenericSignatureFormatError if the generic signature does
391   *         not conform to the format specified in the Virtual Machine
392   *         specification, version 3.
393   * @since 1.5
394   */
395  public Type[] getGenericParameterTypes()
396  {
397    String sig = getSignature();
398    if (sig == null)
399      return getParameterTypes();
400    MethodSignatureParser p = new MethodSignatureParser(this, sig);
401    return p.getGenericParameterTypes();
402  }
403
404  /**
405   * Returns the return type of this method.
406   *
407   * @return the return type of this method
408   * @throws GenericSignatureFormatError if the generic signature does
409   *         not conform to the format specified in the Virtual Machine
410   *         specification, version 3.
411   * @since 1.5
412   */
413  public Type getGenericReturnType()
414  {
415    String sig = getSignature();
416    if (sig == null)
417      return getReturnType();
418    MethodSignatureParser p = new MethodSignatureParser(this, sig);
419    return p.getGenericReturnType();
420  }
421
422  /**
423   * If this method is an annotation method, returns the default
424   * value for the method.  If there is no default value, or if the
425   * method is not a member of an annotation type, returns null.
426   * Primitive types are wrapped.
427   *
428   * @throws TypeNotPresentException if the method returns a Class,
429   * and the class cannot be found
430   *
431   * @since 1.5
432   */
433  public native Object getDefaultValue();
434
435  public <T extends Annotation> T getAnnotation(Class<T> annoClass)
436  {
437    Annotation[] annos = getDeclaredAnnotations();
438    for (int i = 0; i < annos.length; ++i)
439      if (annos[i].annotationType() == annoClass)
440        return (T) annos[i];
441    return null;
442  }
443
444  public Annotation[] getDeclaredAnnotations()
445  {
446    Annotation[] result = getDeclaredAnnotationsInternal();
447    if (result == null)
448      result = new Annotation[0];
449    return result;
450  }
451
452  public Annotation[][] getParameterAnnotations()
453  {
454    // FIXME: should check that we have the right number
455    // of parameters ...?
456    Annotation[][] result = getParameterAnnotationsInternal();
457    if (result == null)
458      result = new Annotation[0][0];
459    return result;
460  }
461
462  private native Annotation[] getDeclaredAnnotationsInternal();
463  private native Annotation[][] getParameterAnnotationsInternal();
464
465  private native void getType ();
466
467  // Append a class name to a string buffer.  We try to print the
468  // fully-qualified name, the way that a Java programmer would expect
469  // it to be written.  Weirdly, Class has no appropriate method for
470  // this.
471  static void appendClassName (StringBuffer buf, Class k)
472  {
473    if (k.isArray ())
474      {
475        appendClassName (buf, k.getComponentType ());
476        buf.append ("[]");
477      }
478    else
479      {
480        // This is correct for primitive and reference types.  Really
481        // we'd like `Main$Inner' to be printed as `Main.Inner', I
482        // think, but that is a pain.
483        buf.append (k.getName ());
484      }
485  }
486
487  // Declaring class.
488  private Class declaringClass;
489
490  // Exception types.
491  Class[] exception_types;
492  // Name cache.  (Initially null.)
493  private String name;
494  // Parameter types.
495  Class[] parameter_types;
496  // Return type.
497  Class return_type;
498
499  // Offset in bytes from the start of declaringClass's methods array.
500  private int offset;
501}