1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/*
18 * Copyright (C) 2008 The Android Open Source Project
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License");
21 * you may not use this file except in compliance with the License.
22 * You may obtain a copy of the License at
23 *
24 *      http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
33package java.lang.reflect;
34
35import java.lang.annotation.Annotation;
36import java.util.Comparator;
37import libcore.util.EmptyArray;
38import org.apache.harmony.kernel.vm.StringUtils;
39import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
40import org.apache.harmony.luni.lang.reflect.ListOfTypes;
41import org.apache.harmony.luni.lang.reflect.Types;
42
43/**
44 * This class represents a method. Information about the method can be accessed,
45 * and the method can be invoked dynamically.
46 */
47public final class Method extends AccessibleObject implements GenericDeclaration, Member {
48
49    /**
50     * Orders methods by their name, parameters and return type.
51     *
52     * @hide
53     */
54    public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() {
55        public int compare(Method a, Method b) {
56            int comparison = a.name.compareTo(b.name);
57            if (comparison != 0) {
58                return comparison;
59            }
60
61            Class<?>[] aParameters = a.parameterTypes;
62            Class<?>[] bParameters = b.parameterTypes;
63            int length = Math.min(aParameters.length, bParameters.length);
64            for (int i = 0; i < length; i++) {
65                comparison = aParameters[i].getName().compareTo(bParameters[i].getName());
66                if (comparison != 0) {
67                    return comparison;
68                }
69            }
70
71            if (aParameters.length != bParameters.length) {
72                return aParameters.length - bParameters.length;
73            }
74
75            // this is necessary for methods that have covariant return types.
76            return a.getReturnType().getName().compareTo(b.getReturnType().getName());
77        }
78    };
79
80    private int slot;
81
82    private Class<?> declaringClass;
83
84    private String name;
85
86    private Class<?>[] parameterTypes;
87
88    private Class<?>[] exceptionTypes;
89
90    private Class<?> returnType;
91
92    private ListOfTypes genericExceptionTypes;
93    private ListOfTypes genericParameterTypes;
94    private Type genericReturnType;
95    private TypeVariable<Method>[] formalTypeParameters;
96    private volatile boolean genericTypesAreInitialized = false;
97
98    private synchronized void initGenericTypes() {
99        if (!genericTypesAreInitialized) {
100            String signatureAttribute = getSignatureAttribute();
101            GenericSignatureParser parser = new GenericSignatureParser(
102                    declaringClass.getClassLoader());
103            parser.parseForMethod(this, signatureAttribute, exceptionTypes);
104            formalTypeParameters = parser.formalTypeParameters;
105            genericParameterTypes = parser.parameterTypes;
106            genericExceptionTypes = parser.exceptionTypes;
107            genericReturnType = parser.returnType;
108            genericTypesAreInitialized = true;
109        }
110    }
111
112    /**
113     * Construct a clone of the given instance.
114     *
115     * @param orig non-null; the original instance to clone
116     */
117    /*package*/ Method(Method orig) {
118        this(orig.declaringClass, orig.parameterTypes, orig.exceptionTypes,
119                orig.returnType, orig.name, orig.slot);
120
121        // Copy the accessible flag.
122        if (orig.flag) {
123            this.flag = true;
124        }
125    }
126
127    private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot)
128    {
129        this.declaringClass = declaring;
130        this.name = name;
131        this.slot = slot;
132        this.parameterTypes = paramTypes;
133        this.exceptionTypes = exceptTypes;      // may be null
134        this.returnType = returnType;
135    }
136
137    public TypeVariable<Method>[] getTypeParameters() {
138        initGenericTypes();
139        return formalTypeParameters.clone();
140    }
141
142    /** {@inheritDoc} */
143    @Override /*package*/ String getSignatureAttribute() {
144        Object[] annotation = getSignatureAnnotation(declaringClass, slot);
145
146        if (annotation == null) {
147            return null;
148        }
149
150        return StringUtils.combineStrings(annotation);
151    }
152
153    /**
154     * Returns the Signature annotation for this method. Returns {@code null} if
155     * not found.
156     */
157    static native Object[] getSignatureAnnotation(Class declaringClass, int slot);
158
159    /**
160     * Returns the string representation of the method's declaration, including
161     * the type parameters.
162     *
163     * @return the string representation of this method
164     */
165    public String toGenericString() {
166        StringBuilder sb = new StringBuilder(80);
167
168        initGenericTypes();
169
170        // append modifiers if any
171        int modifier = getModifiers();
172        if (modifier != 0) {
173            sb.append(Modifier.toString(modifier & ~(Modifier.BRIDGE +
174                    Modifier.VARARGS))).append(' ');
175        }
176        // append type parameters
177        if (formalTypeParameters != null && formalTypeParameters.length > 0) {
178            sb.append('<');
179            for (int i = 0; i < formalTypeParameters.length; i++) {
180                appendGenericType(sb, formalTypeParameters[i]);
181                if (i < formalTypeParameters.length - 1) {
182                    sb.append(",");
183                }
184            }
185            sb.append("> ");
186        }
187        // append return type
188        appendGenericType(sb, Types.getType(genericReturnType));
189        sb.append(' ');
190        // append method name
191        appendTypeName(sb, getDeclaringClass());
192        sb.append(".").append(getName());
193        // append parameters
194        sb.append('(');
195        appendArrayGenericType(sb,
196                Types.getClonedTypeArray(genericParameterTypes));
197        sb.append(')');
198        // append exceptions if any
199        Type[] genericExceptionTypeArray = Types.getClonedTypeArray(
200                genericExceptionTypes);
201        if (genericExceptionTypeArray.length > 0) {
202            sb.append(" throws ");
203            appendArrayGenericType(sb, genericExceptionTypeArray);
204        }
205        return sb.toString();
206    }
207
208    /**
209     * Returns the parameter types as an array of {@code Type} instances, in
210     * declaration order. If this method has no parameters, an empty array is
211     * returned.
212     *
213     * @return the parameter types
214     *
215     * @throws GenericSignatureFormatError
216     *             if the generic method signature is invalid
217     * @throws TypeNotPresentException
218     *             if any parameter type points to a missing type
219     * @throws MalformedParameterizedTypeException
220     *             if any parameter type points to a type that cannot be
221     *             instantiated for some reason
222     */
223    public Type[] getGenericParameterTypes() {
224        initGenericTypes();
225        return Types.getClonedTypeArray(genericParameterTypes);
226    }
227
228    /**
229     * Returns the exception types as an array of {@code Type} instances. If
230     * this method has no declared exceptions, an empty array will be returned.
231     *
232     * @return an array of generic exception types
233     *
234     * @throws GenericSignatureFormatError
235     *             if the generic method signature is invalid
236     * @throws TypeNotPresentException
237     *             if any exception type points to a missing type
238     * @throws MalformedParameterizedTypeException
239     *             if any exception type points to a type that cannot be
240     *             instantiated for some reason
241     */
242    public Type[] getGenericExceptionTypes() {
243        initGenericTypes();
244        return Types.getClonedTypeArray(genericExceptionTypes);
245    }
246
247    /**
248     * Returns the return type of this method as a {@code Type} instance.
249     *
250     * @return the return type of this method
251     *
252     * @throws GenericSignatureFormatError
253     *             if the generic method signature is invalid
254     * @throws TypeNotPresentException
255     *             if the return type points to a missing type
256     * @throws MalformedParameterizedTypeException
257     *             if the return type points to a type that cannot be
258     *             instantiated for some reason
259     */
260    public Type getGenericReturnType() {
261        initGenericTypes();
262        return Types.getType(genericReturnType);
263    }
264
265    @Override
266    public Annotation[] getDeclaredAnnotations() {
267        return getDeclaredAnnotations(declaringClass, slot);
268    }
269    static native Annotation[] getDeclaredAnnotations(Class<?> declaringClass, int slot);
270
271    @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
272        if (annotationType == null) {
273            throw new NullPointerException("annotationType == null");
274        }
275        return getAnnotation(declaringClass, slot, annotationType);
276    }
277    static native <A extends Annotation> A getAnnotation(
278            Class<?> declaringClass, int slot, Class<A> annotationType);
279
280    @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
281        if (annotationType == null) {
282            throw new NullPointerException("annotationType == null");
283        }
284        return isAnnotationPresent(declaringClass, slot, annotationType);
285    }
286    static native boolean isAnnotationPresent(
287            Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType);
288
289    private static final Annotation[] NO_ANNOTATIONS = new Annotation[0];
290
291    /**
292     * Creates an array of empty Annotation arrays.
293     */
294    /*package*/ static Annotation[][] noAnnotations(int size) {
295        Annotation[][] annotations = new Annotation[size][];
296        for (int i = 0; i < size; i++) {
297            annotations[i] = NO_ANNOTATIONS;
298        }
299        return annotations;
300    }
301
302    /**
303     * Returns an array of arrays that represent the annotations of the formal
304     * parameters of this method. If there are no parameters on this method,
305     * then an empty array is returned. If there are no annotations set, then
306     * and array of empty arrays is returned.
307     *
308     * @return an array of arrays of {@code Annotation} instances
309     */
310    public Annotation[][] getParameterAnnotations() {
311        Annotation[][] parameterAnnotations
312                = getParameterAnnotations(declaringClass, slot);
313        if (parameterAnnotations.length == 0) {
314            return noAnnotations(parameterTypes.length);
315        }
316        return parameterAnnotations;
317    }
318
319    static native Annotation[][] getParameterAnnotations(Class declaringClass, int slot);
320
321    /**
322     * Indicates whether or not this method takes a variable number argument.
323     *
324     * @return {@code true} if a vararg is declared, {@code false} otherwise
325     */
326    public boolean isVarArgs() {
327        int modifiers = getMethodModifiers(declaringClass, slot);
328        return (modifiers & Modifier.VARARGS) != 0;
329    }
330
331    /**
332     * Indicates whether or not this method is a bridge.
333     *
334     * @return {@code true} if this method is a bridge, {@code false} otherwise
335     */
336    public boolean isBridge() {
337        int modifiers = getMethodModifiers(declaringClass, slot);
338        return (modifiers & Modifier.BRIDGE) != 0;
339    }
340
341    /**
342     * Indicates whether or not this method is synthetic.
343     *
344     * @return {@code true} if this method is synthetic, {@code false} otherwise
345     */
346    public boolean isSynthetic() {
347        int modifiers = getMethodModifiers(declaringClass, slot);
348        return (modifiers & Modifier.SYNTHETIC) != 0;
349    }
350
351    /**
352     * Returns the default value for the annotation member represented by this
353     * method.
354     *
355     * @return the default value, or {@code null} if none
356     *
357     * @throws TypeNotPresentException
358     *             if this annotation member is of type {@code Class} and no
359     *             definition can be found
360     */
361    public Object getDefaultValue() {
362        return getDefaultValue(declaringClass, slot);
363    }
364    native private Object getDefaultValue(Class declaringClass, int slot);
365
366    /**
367     * Indicates whether or not the specified {@code object} is equal to this
368     * method. To be equal, the specified object must be an instance
369     * of {@code Method} with the same declaring class and parameter types
370     * as this method.
371     *
372     * @param object
373     *            the object to compare
374     *
375     * @return {@code true} if the specified object is equal to this
376     *         method, {@code false} otherwise
377     *
378     * @see #hashCode
379     */
380    @Override
381    public boolean equals(Object object) {
382        return object instanceof Method && toString().equals(object.toString());
383    }
384
385    /**
386     * Returns the class that declares this method.
387     *
388     * @return the declaring class
389     */
390    public Class<?> getDeclaringClass() {
391        return declaringClass;
392    }
393
394    /**
395     * Returns the exception types as an array of {@code Class} instances. If
396     * this method has no declared exceptions, an empty array is returned.
397     *
398     * @return the declared exception classes
399     */
400    public Class<?>[] getExceptionTypes() {
401        if (exceptionTypes == null) {
402            return EmptyArray.CLASS;
403        }
404        return exceptionTypes.clone();
405    }
406
407    /**
408     * Returns the modifiers for this method. The {@link Modifier} class should
409     * be used to decode the result.
410     *
411     * @return the modifiers for this method
412     *
413     * @see Modifier
414     */
415    public int getModifiers() {
416        return getMethodModifiers(declaringClass, slot);
417    }
418
419    static native int getMethodModifiers(Class<?> declaringClass, int slot);
420
421    /**
422     * Returns the name of the method represented by this {@code Method}
423     * instance.
424     *
425     * @return the name of this method
426     */
427    public String getName() {
428        return name;
429    }
430
431    /**
432     * Returns an array of {@code Class} objects associated with the parameter
433     * types of this method. If the method was declared with no parameters, an
434     * empty array will be returned.
435     *
436     * @return the parameter types
437     */
438    public Class<?>[] getParameterTypes() {
439        return parameterTypes.clone();
440    }
441
442    /**
443     * Returns the {@code Class} associated with the return type of this
444     * method.
445     *
446     * @return the return type
447     */
448    public Class<?> getReturnType() {
449        return returnType;
450    }
451
452    /**
453     * Returns an integer hash code for this method. Objects which are equal
454     * return the same value for this method. The hash code for this Method is
455     * the hash code of the name of this method.
456     *
457     * @return hash code for this method
458     *
459     * @see #equals
460     */
461    @Override
462    public int hashCode() {
463        return name.hashCode();
464    }
465
466    /**
467     * Returns the result of dynamically invoking this method. Equivalent to
468     * {@code receiver.methodName(arg1, arg2, ... , argN)}.
469     *
470     * <p>If the method is static, the receiver argument is ignored (and may be null).
471     *
472     * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of
473     * allocating an empty array.
474     *
475     * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the
476     * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and
477     * the reflection machinery does not do this for you. (It couldn't, because it would be
478     * ambiguous.)
479     *
480     * <p>Reflective method invocation follows the usual process for method lookup.
481     *
482     * <p>If an exception is thrown during the invocation it is caught and
483     * wrapped in an InvocationTargetException. This exception is then thrown.
484     *
485     * <p>If the invocation completes normally, the return value itself is
486     * returned. If the method is declared to return a primitive type, the
487     * return value is boxed. If the return type is void, null is returned.
488     *
489     * @param receiver
490     *            the object on which to call this method (or null for static methods)
491     * @param args
492     *            the arguments to the method
493     * @return the result
494     *
495     * @throws NullPointerException
496     *             if {@code receiver == null} for a non-static method
497     * @throws IllegalAccessException
498     *             if this method is not accessible (see {@link AccessibleObject})
499     * @throws IllegalArgumentException
500     *             if the number of arguments doesn't match the number of parameters, the receiver
501     *             is incompatible with the declaring class, or an argument could not be unboxed
502     *             or converted by a widening conversion to the corresponding parameter type
503     * @throws InvocationTargetException
504     *             if an exception was thrown by the invoked method
505     */
506    public Object invoke(Object receiver, Object... args)
507            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
508        if (args == null) {
509            args = EmptyArray.OBJECT;
510        }
511        return invokeNative(receiver, args, declaringClass, parameterTypes, returnType, slot, flag);
512    }
513
514    private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass,
515            Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck)
516                    throws IllegalAccessException, IllegalArgumentException,
517                            InvocationTargetException;
518
519    /**
520     * Returns a string containing a concise, human-readable description of this
521     * method. The format of the string is:
522     *
523     * <ol>
524     *   <li>modifiers (if any)
525     *   <li>return type or 'void'
526     *   <li>declaring class name
527     *   <li>'('
528     *   <li>parameter types, separated by ',' (if any)
529     *   <li>')'
530     *   <li>'throws' plus exception types, separated by ',' (if any)
531     * </ol>
532     *
533     * For example: {@code public native Object
534     * java.lang.Method.invoke(Object,Object) throws
535     * IllegalAccessException,IllegalArgumentException
536     * ,InvocationTargetException}
537     *
538     * @return a printable representation for this method
539     */
540    @Override
541    public String toString() {
542        StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
543
544        if (result.length() != 0)
545            result.append(' ');
546        result.append(returnType.getName());
547        result.append(' ');
548        result.append(declaringClass.getName());
549        result.append('.');
550        result.append(name);
551        result.append("(");
552        result.append(toString(parameterTypes));
553        result.append(")");
554        if (exceptionTypes != null && exceptionTypes.length != 0) {
555            result.append(" throws ");
556            result.append(toString(exceptionTypes));
557        }
558
559        return result.toString();
560    }
561
562    /**
563     * Returns the constructor's signature in non-printable form. This is called
564     * (only) from IO native code and needed for deriving the serialVersionUID
565     * of the class
566     *
567     * @return The constructor's signature.
568     */
569    @SuppressWarnings("unused")
570    private String getSignature() {
571        StringBuilder result = new StringBuilder();
572
573        result.append('(');
574        for (int i = 0; i < parameterTypes.length; i++) {
575            result.append(getSignature(parameterTypes[i]));
576        }
577        result.append(')');
578        result.append(getSignature(returnType));
579
580        return result.toString();
581    }
582
583}
584