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 
33 package java.lang.reflect;
34 
35 import com.android.dex.Dex;
36 import java.lang.annotation.Annotation;
37 import java.util.Comparator;
38 import java.util.List;
39 import libcore.reflect.AnnotationAccess;
40 import libcore.reflect.Types;
41 
42 /**
43  * This class represents a method. Information about the method can be accessed,
44  * and the method can be invoked dynamically.
45  */
46 public final class Method extends AbstractMethod implements GenericDeclaration, Member {
47 
48     /**
49      * Orders methods by their name, parameters and return type.
50      *
51      * @hide
52      */
53     public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() {
54         @Override public int compare(Method a, Method b) {
55             if (a == b) {
56                 return 0;
57             }
58             int comparison = a.getName().compareTo(b.getName());
59             if (comparison == 0) {
60                 comparison = a.artMethod.findOverriddenMethodIfProxy().compareParameters(
61                         b.getParameterTypes());
62                 if (comparison == 0) {
63                     // This is necessary for methods that have covariant return types.
64                     Class<?> aReturnType = a.getReturnType();
65                     Class<?> bReturnType = b.getReturnType();
66                     if (aReturnType == bReturnType) {
67                         comparison = 0;
68                     } else {
69                         comparison = aReturnType.getName().compareTo(bReturnType.getName());
70                     }
71                 }
72             }
73             return comparison;
74         }
75     };
76 
77     /**
78      * @hide
79      */
Method(ArtMethod artMethod)80     public Method(ArtMethod artMethod) {
81         super(artMethod);
82     }
83 
getArtMethod()84     ArtMethod getArtMethod() {
85         return artMethod;
86     }
87 
getAnnotations()88     public Annotation[] getAnnotations() {
89         return super.getAnnotations();
90     }
91 
92     /**
93      * Returns the modifiers for this method. The {@link Modifier} class should
94      * be used to decode the result.
95      *
96      * @return the modifiers for this method
97      *
98      * @see Modifier
99      */
getModifiers()100     @Override public int getModifiers() {
101         return super.getModifiers();
102     }
103 
104     /**
105      * Indicates whether or not this method takes a variable number argument.
106      *
107      * @return {@code true} if a vararg is declared, {@code false} otherwise
108      */
isVarArgs()109     public boolean isVarArgs() {
110         return super.isVarArgs();
111     }
112 
113     /**
114      * Indicates whether or not this method is a bridge.
115      *
116      * @return {@code true} if this method is a bridge, {@code false} otherwise
117      */
isBridge()118     public boolean isBridge() {
119         return super.isBridge();
120 
121     }
122 
123     /**
124      * Indicates whether or not this method is synthetic.
125      *
126      * @return {@code true} if this method is synthetic, {@code false} otherwise
127      */
isSynthetic()128     @Override public boolean isSynthetic() {
129         return super.isSynthetic();
130     }
131 
132     /**
133      * Returns the name of the method represented by this {@code Method}
134      * instance.
135      *
136      * @return the name of this method
137      */
getName()138     @Override public String getName() {
139         return ArtMethod.getMethodName(artMethod);
140     }
141 
142     /**
143      * Returns the class that declares this method.
144      */
getDeclaringClass()145     @Override public Class<?> getDeclaringClass() {
146         return super.getDeclaringClass();
147     }
148 
149     /**
150      * Returns the exception types as an array of {@code Class} instances. If
151      * this method has no declared exceptions, an empty array is returned.
152      *
153      * @return the declared exception classes
154      */
getExceptionTypes()155     public Class<?>[] getExceptionTypes() {
156         if (getDeclaringClass().isProxy()) {
157             return getExceptionTypesNative();
158         } else {
159             // TODO: use dex cache to speed looking up class
160             return AnnotationAccess.getExceptions(this);
161         }
162     }
163 
getExceptionTypesNative()164     private native Class<?>[] getExceptionTypesNative();
165 
166     /**
167      * Returns an array of {@code Class} objects associated with the parameter
168      * types of this method. If the method was declared with no parameters, an
169      * empty array will be returned.
170      *
171      * @return the parameter types
172      */
getParameterTypes()173     @Override public Class<?>[] getParameterTypes() {
174         return artMethod.findOverriddenMethodIfProxy().getParameterTypes();
175     }
176 
177     /**
178      * Returns the {@code Class} associated with the return type of this
179      * method.
180      *
181      * @return the return type
182      */
getReturnType()183     public Class<?> getReturnType() {
184         return artMethod.findOverriddenMethodIfProxy().getReturnType();
185     }
186 
187     /**
188      * {@inheritDoc}
189      *
190      * <p>Equivalent to {@code getDeclaringClass().getName().hashCode() ^ getName().hashCode()}.
191      */
hashCode()192     @Override public int hashCode() {
193         return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
194     }
195 
196     /**
197      * Returns true if {@code other} has the same declaring class, name,
198      * parameters and return type as this method.
199      */
equals(Object other)200     @Override public boolean equals(Object other) {
201         return super.equals(other);
202     }
203 
204     /**
205      * Returns true if this and {@code method} have the same name and the same
206      * parameters in the same order. Such methods can share implementation if
207      * one method's return types is assignable to the other.
208      *
209      * @hide needed by Proxy
210      */
equalNameAndParameters(Method m)211     boolean equalNameAndParameters(Method m) {
212         return getName().equals(m.getName()) &&
213                 ArtMethod.equalMethodParameters(artMethod,m.getParameterTypes());
214     }
215 
216     /**
217      * Returns the string representation of the method's declaration, including
218      * the type parameters.
219      *
220      * @return the string representation of this method
221      */
toGenericString()222     public String toGenericString() {
223         return super.toGenericString();
224     }
225 
getTypeParameters()226     @Override public TypeVariable<Method>[] getTypeParameters() {
227         GenericInfo info = getMethodOrConstructorGenericInfo();
228         return (TypeVariable<Method>[]) info.formalTypeParameters.clone();
229     }
230 
231     /**
232      * Returns the parameter types as an array of {@code Type} instances, in
233      * declaration order. If this method has no parameters, an empty array is
234      * returned.
235      *
236      * @return the parameter types
237      *
238      * @throws GenericSignatureFormatError
239      *             if the generic method signature is invalid
240      * @throws TypeNotPresentException
241      *             if any parameter type points to a missing type
242      * @throws MalformedParameterizedTypeException
243      *             if any parameter type points to a type that cannot be
244      *             instantiated for some reason
245      */
getGenericParameterTypes()246     public Type[] getGenericParameterTypes() {
247         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false);
248     }
249 
isAnnotationPresent(Class<? extends Annotation> annotationType)250     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
251         if (annotationType == null) {
252             throw new NullPointerException("annotationType == null");
253         }
254         return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
255     }
256 
257     /**
258      * Returns the exception types as an array of {@code Type} instances. If
259      * this method has no declared exceptions, an empty array will be returned.
260      *
261      * @return an array of generic exception types
262      *
263      * @throws GenericSignatureFormatError
264      *             if the generic method signature is invalid
265      * @throws TypeNotPresentException
266      *             if any exception type points to a missing type
267      * @throws MalformedParameterizedTypeException
268      *             if any exception type points to a type that cannot be
269      *             instantiated for some reason
270      */
getGenericExceptionTypes()271     public Type[] getGenericExceptionTypes() {
272         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false);
273     }
274 
275     /**
276      * Returns the return type of this method as a {@code Type} instance.
277      *
278      * @return the return type of this method
279      *
280      * @throws GenericSignatureFormatError
281      *             if the generic method signature is invalid
282      * @throws TypeNotPresentException
283      *             if the return type points to a missing type
284      * @throws MalformedParameterizedTypeException
285      *             if the return type points to a type that cannot be
286      *             instantiated for some reason
287      */
getGenericReturnType()288     public Type getGenericReturnType() {
289         return Types.getType(getMethodOrConstructorGenericInfo().genericReturnType);
290     }
291 
getDeclaredAnnotations()292     @Override public Annotation[] getDeclaredAnnotations() {
293         List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
294         return result.toArray(new Annotation[result.size()]);
295     }
296 
getAnnotation(Class<A> annotationType)297     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
298         if (annotationType == null) {
299             throw new NullPointerException("annotationType == null");
300         }
301         return AnnotationAccess.getDeclaredAnnotation(this, annotationType);
302     }
303 
304     /**
305      * Returns an array of arrays that represent the annotations of the formal
306      * parameters of this method. If there are no parameters on this method,
307      * then an empty array is returned. If there are no annotations set, then
308      * and array of empty arrays is returned.
309      *
310      * @return an array of arrays of {@code Annotation} instances
311      */
getParameterAnnotations()312     public Annotation[][] getParameterAnnotations() {
313         return artMethod.findOverriddenMethodIfProxy().getParameterAnnotations();
314     }
315 
316     /**
317      * Returns the default value for the annotation member represented by this
318      * method.
319      *
320      * @return the default value, or {@code null} if none
321      *
322      * @throws TypeNotPresentException
323      *             if this annotation member is of type {@code Class} and no
324      *             definition can be found
325      */
getDefaultValue()326     public Object getDefaultValue() {
327         return AnnotationAccess.getDefaultValue(this);
328     }
329 
330     /**
331      * Returns the result of dynamically invoking this method. Equivalent to
332      * {@code receiver.methodName(arg1, arg2, ... , argN)}.
333      *
334      * <p>If the method is static, the receiver argument is ignored (and may be null).
335      *
336      * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of
337      * allocating an empty array.
338      *
339      * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the
340      * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and
341      * the reflection machinery does not do this for you. (It couldn't, because it would be
342      * ambiguous.)
343      *
344      * <p>Reflective method invocation follows the usual process for method lookup.
345      *
346      * <p>If an exception is thrown during the invocation it is caught and
347      * wrapped in an InvocationTargetException. This exception is then thrown.
348      *
349      * <p>If the invocation completes normally, the return value itself is
350      * returned. If the method is declared to return a primitive type, the
351      * return value is boxed. If the return type is void, null is returned.
352      *
353      * @param receiver
354      *            the object on which to call this method (or null for static methods)
355      * @param args
356      *            the arguments to the method
357      * @return the result
358      *
359      * @throws NullPointerException
360      *             if {@code receiver == null} for a non-static method
361      * @throws IllegalAccessException
362      *             if this method is not accessible (see {@link AccessibleObject})
363      * @throws IllegalArgumentException
364      *             if the number of arguments doesn't match the number of parameters, the receiver
365      *             is incompatible with the declaring class, or an argument could not be unboxed
366      *             or converted by a widening conversion to the corresponding parameter type
367      * @throws InvocationTargetException
368      *             if an exception was thrown by the invoked method
369      */
invoke(Object receiver, Object... args)370     public Object invoke(Object receiver, Object... args)
371             throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
372         return invoke(receiver, args, isAccessible());
373     }
374 
invoke(Object receiver, Object[] args, boolean accessible)375     private native Object invoke(Object receiver, Object[] args, boolean accessible)
376             throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
377 
378     /**
379      * Returns a string containing a concise, human-readable description of this
380      * method. The format of the string is:
381      *
382      * <ol>
383      *   <li>modifiers (if any)
384      *   <li>return type or 'void'
385      *   <li>declaring class name
386      *   <li>'('
387      *   <li>parameter types, separated by ',' (if any)
388      *   <li>')'
389      *   <li>'throws' plus exception types, separated by ',' (if any)
390      * </ol>
391      *
392      * For example: {@code public native Object
393      * java.lang.Method.invoke(Object,Object) throws
394      * IllegalAccessException,IllegalArgumentException
395      * ,InvocationTargetException}
396      *
397      * @return a printable representation for this method
398      */
399     @Override
toString()400     public String toString() {
401         StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
402 
403         if (result.length() != 0) {
404             result.append(' ');
405         }
406         result.append(getReturnType().getName());
407         result.append(' ');
408         result.append(getDeclaringClass().getName());
409         result.append('.');
410         result.append(getName());
411         result.append("(");
412         Class<?>[] parameterTypes = getParameterTypes();
413         result.append(Types.toString(parameterTypes));
414         result.append(")");
415         Class<?>[] exceptionTypes = getExceptionTypes();
416         if (exceptionTypes.length != 0) {
417             result.append(" throws ");
418             result.append(Types.toString(exceptionTypes));
419         }
420         return result.toString();
421     }
422 
423     /**
424      * Returns the constructor's signature in non-printable form. This is called
425      * (only) from IO native code and needed for deriving the serialVersionUID
426      * of the class
427      *
428      * @return The constructor's signature.
429      */
430     @SuppressWarnings("unused")
getSignature()431     String getSignature() {
432         StringBuilder result = new StringBuilder();
433 
434         result.append('(');
435         Class<?>[] parameterTypes = getParameterTypes();
436         for (Class<?> parameterType : parameterTypes) {
437             result.append(Types.getSignature(parameterType));
438         }
439         result.append(')');
440         result.append(Types.getSignature(getReturnType()));
441 
442         return result.toString();
443     }
444 }
445