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) 2012 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.List;
38 import libcore.reflect.GenericSignatureParser;
39 import libcore.reflect.ListOfTypes;
40 import libcore.reflect.Types;
41 import libcore.util.EmptyArray;
42 
43 /**
44  * This class represents an abstract method. Abstract methods are either methods or constructors.
45  * @hide
46  */
47 public abstract class AbstractMethod extends AccessibleObject {
48     /** Bits encoding access (e.g. public, private) as well as other runtime specific flags */
49     protected int accessFlags;
50 
51     /**
52      * The ArtMethod associated with this Method, requried for dispatching due to entrypoints
53      * Classloader is held live by the declaring class.
54      * Hidden to workaround b/16828157.
55      * @hide
56      */
57     protected long artMethod;
58 
59     /** Method's declaring class */
60     protected Class<?> declaringClass;
61 
62     /** Overriden method's declaring class (same as declaringClass unless declaringClass
63      * is a proxy class) */
64     protected Class<?> declaringClassOfOverriddenMethod;
65 
66     /** The method index of this method within its defining dex file */
67     protected int dexMethodIndex;
68 
69     /**
70      * Hidden to workaround b/16828157.
71      * @hide
72      */
AbstractMethod()73     protected AbstractMethod() {
74     }
75 
getAnnotation(Class<T> annotationClass)76     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
77         return super.getAnnotation(annotationClass);
78     }
79 
80     /**
81      * We insert native method stubs for abstract methods so we don't have to
82      * check the access flags at the time of the method call.  This results in
83      * "native abstract" methods, which can't exist.  If we see the "abstract"
84      * flag set, clear the "native" flag.
85      *
86      * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
87      * position, because the callers of this function are trying to convey
88      * the "traditional" meaning of the flags to their callers.
89      */
fixMethodFlags(int flags)90     private static int fixMethodFlags(int flags) {
91         if ((flags & Modifier.ABSTRACT) != 0) {
92             flags &= ~Modifier.NATIVE;
93         }
94         flags &= ~Modifier.SYNCHRONIZED;
95         int ACC_DECLARED_SYNCHRONIZED = 0x00020000;
96         if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) {
97             flags |= Modifier.SYNCHRONIZED;
98         }
99         return flags & 0xffff;  // mask out bits not used by Java
100     }
101 
getModifiers()102     int getModifiers() {
103         return fixMethodFlags(accessFlags);
104     }
105 
isVarArgs()106     boolean isVarArgs() {
107         return (accessFlags & Modifier.VARARGS) != 0;
108     }
109 
isBridge()110     boolean isBridge() {
111         return (accessFlags & Modifier.BRIDGE) != 0;
112     }
113 
isSynthetic()114     boolean isSynthetic() {
115         return (accessFlags & Modifier.SYNTHETIC) != 0;
116     }
117 
isDefault()118     boolean isDefault() {
119       return (accessFlags & Modifier.DEFAULT) != 0;
120     }
121 
122     /**
123      * @hide
124      */
getAccessFlags()125     public final int getAccessFlags() {
126         return accessFlags;
127     }
128 
129     /**
130      * Returns the class that declares this constructor or method.
131      */
getDeclaringClass()132     Class<?> getDeclaringClass() {
133         return declaringClass;
134     }
135 
136     /**
137      * Returns the index of this method's ID in its dex file.
138      *
139      * @hide
140      */
getDexMethodIndex()141     public final int getDexMethodIndex() {
142         return dexMethodIndex;
143     }
144 
145     /**
146      * Returns the name of the method or constructor represented by this
147      * instance.
148      *
149      * @return the name of this method
150      */
getName()151     abstract public String getName();
152 
153     /**
154      * Returns an array of {@code Class} objects associated with the parameter types of this
155      * abstract method. If the method was declared with no parameters, an
156      * empty array will be returned.
157      *
158      * @return the parameter types
159      */
getParameterTypes()160     Class<?>[] getParameterTypes() {
161         Dex dex = declaringClassOfOverriddenMethod.getDex();
162         short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
163         if (types.length == 0) {
164             return EmptyArray.CLASS;
165         }
166         Class<?>[] parametersArray = new Class[types.length];
167         for (int i = 0; i < types.length; i++) {
168             // Note, in the case of a Proxy the dex cache types are equal.
169             parametersArray[i] = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]);
170         }
171         return parametersArray;
172     }
173 
174     /**
175      * Returns true if {@code other} has the same declaring class, name,
176      * parameters and return type as this method.
177      */
equals(Object other)178     @Override public boolean equals(Object other) {
179         if (!(other instanceof AbstractMethod)) {
180             return false;
181         }
182         // Exactly one instance of each member in this runtime, todo, does this work for proxies?
183         AbstractMethod otherMethod = (AbstractMethod) other;
184         return this.declaringClass == otherMethod.declaringClass &&
185             this.dexMethodIndex == otherMethod.dexMethodIndex;
186     }
187 
toGenericString()188     String toGenericString() {
189         return toGenericStringHelper();
190     }
191 
getGenericParameterTypes()192     Type[] getGenericParameterTypes() {
193         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false);
194     }
195 
getGenericExceptionTypes()196     Type[] getGenericExceptionTypes() {
197         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false);
198     }
199 
getDeclaredAnnotations()200     @Override public native Annotation[] getDeclaredAnnotations();
201 
isAnnotationPresent(Class<? extends Annotation> annotationType)202     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
203         if (annotationType == null) {
204             throw new NullPointerException("annotationType == null");
205         }
206         return isAnnotationPresentNative(annotationType);
207     }
208 
isAnnotationPresentNative(Class<? extends Annotation> annotationType)209     private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
210 
getAnnotations()211     public Annotation[] getAnnotations() {
212         return super.getAnnotations();
213     }
214 
215     /**
216      * Returns an array of arrays that represent the annotations of the formal
217      * parameters of this method. If there are no parameters on this method,
218      * then an empty array is returned. If there are no annotations set, then
219      * and array of empty arrays is returned.
220      *
221      * @return an array of arrays of {@code Annotation} instances
222      */
getParameterAnnotations()223     public abstract Annotation[][] getParameterAnnotations();
224 
225     /**
226      * Returns the constructor's signature in non-printable form. This is called
227      * (only) from IO native code and needed for deriving the serialVersionUID
228      * of the class
229      *
230      * @return The constructor's signature.
231      */
232     @SuppressWarnings("unused")
getSignature()233     abstract String getSignature();
234 
235     static final class GenericInfo {
236         final ListOfTypes genericExceptionTypes;
237         final ListOfTypes genericParameterTypes;
238         final Type genericReturnType;
239         final TypeVariable<?>[] formalTypeParameters;
240 
GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret, TypeVariable<?>[] formal)241         GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret,
242                     TypeVariable<?>[] formal) {
243             genericExceptionTypes = exceptions;
244             genericParameterTypes = parameters;
245             genericReturnType = ret;
246             formalTypeParameters = formal;
247         }
248     }
249 
250     /**
251      * Returns generic information associated with this method/constructor member.
252      */
getMethodOrConstructorGenericInfo()253     final GenericInfo getMethodOrConstructorGenericInfo() {
254         String signatureAttribute = getSignatureAttribute();
255         Member member;
256         Class<?>[] exceptionTypes;
257         boolean method = this instanceof Method;
258         if (method) {
259             Method m = (Method) this;
260             member = m;
261             exceptionTypes = m.getExceptionTypes();
262         } else {
263             Constructor<?> c = (Constructor<?>) this;
264             member = c;
265             exceptionTypes = c.getExceptionTypes();
266         }
267         GenericSignatureParser parser =
268             new GenericSignatureParser(member.getDeclaringClass().getClassLoader());
269         if (method) {
270             parser.parseForMethod((GenericDeclaration) this, signatureAttribute, exceptionTypes);
271         } else {
272             parser.parseForConstructor((GenericDeclaration) this,
273                                        signatureAttribute,
274                                        exceptionTypes);
275         }
276         return new GenericInfo(parser.exceptionTypes, parser.parameterTypes,
277                                parser.returnType, parser.formalTypeParameters);
278     }
279 
getSignatureAttribute()280     private String getSignatureAttribute() {
281         String[] annotation = getSignatureAnnotation();
282         if (annotation == null) {
283             return null;
284         }
285         StringBuilder result = new StringBuilder();
286         for (String s : annotation) {
287             result.append(s);
288         }
289         return result.toString();
290     }
291 
getSignatureAnnotation()292     private native String[] getSignatureAnnotation();
293 
equalMethodParameters(Class<?>[] params)294     protected boolean equalMethodParameters(Class<?>[] params) {
295         Dex dex = declaringClassOfOverriddenMethod.getDex();
296         short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
297         if (types.length != params.length) {
298             return false;
299         }
300         for (int i = 0; i < types.length; i++) {
301             if (declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]) != params[i]) {
302                 return false;
303             }
304         }
305         return true;
306     }
307 
compareParameters(Class<?>[] params)308     protected int compareParameters(Class<?>[] params) {
309         Dex dex = declaringClassOfOverriddenMethod.getDex();
310         short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex);
311         int length = Math.min(types.length, params.length);
312         for (int i = 0; i < length; i++) {
313             Class<?> aType = declaringClassOfOverriddenMethod.getDexCacheType(dex, types[i]);
314             Class<?> bType = params[i];
315             if (aType != bType) {
316                 int comparison = aType.getName().compareTo(bType.getName());
317                 if (comparison != 0) {
318                     return comparison;
319                 }
320             }
321         }
322         return types.length - params.length;
323     }
324 
325     /**
326      * Helper for Method and Constructor for toGenericString
327      */
toGenericStringHelper()328     final String toGenericStringHelper() {
329         StringBuilder sb = new StringBuilder(80);
330         GenericInfo info =  getMethodOrConstructorGenericInfo();
331         int modifiers = ((Member)this).getModifiers();
332         // append modifiers if any
333         if (modifiers != 0) {
334             sb.append(Modifier.toString(modifiers & ~Modifier.VARARGS)).append(' ');
335         }
336         // append type parameters
337         if (info.formalTypeParameters != null && info.formalTypeParameters.length > 0) {
338             sb.append('<');
339             for (int i = 0; i < info.formalTypeParameters.length; i++) {
340                 Types.appendGenericType(sb, info.formalTypeParameters[i]);
341                 if (i < info.formalTypeParameters.length - 1) {
342                     sb.append(",");
343                 }
344             }
345             sb.append("> ");
346         }
347         Class<?> declaringClass = ((Member) this).getDeclaringClass();
348         if (this instanceof Constructor) {
349             // append constructor name
350             Types.appendTypeName(sb, declaringClass);
351         } else {
352             // append return type
353             Types.appendGenericType(sb, Types.getType(info.genericReturnType));
354             sb.append(' ');
355             // append method name
356             Types.appendTypeName(sb, declaringClass);
357             sb.append(".").append(((Method) this).getName());
358         }
359         // append parameters
360         sb.append('(');
361         Types.appendArrayGenericType(sb, info.genericParameterTypes.getResolvedTypes());
362         sb.append(')');
363         // append exceptions if any
364         Type[] genericExceptionTypeArray =
365             Types.getTypeArray(info.genericExceptionTypes, false);
366         if (genericExceptionTypeArray.length > 0) {
367             sb.append(" throws ");
368             Types.appendArrayGenericType(sb, genericExceptionTypeArray);
369         }
370         return sb.toString();
371     }
372 }
373