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    
007    This software is copyrighted work licensed under the terms of the
008    Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
009    details.  */
010     
011    package java.lang.reflect;
012    
013    import gnu.gcj.RawData;
014    import gnu.java.lang.reflect.MethodSignatureParser;
015    import 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     */
051    public 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    }