• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.AnnotationAccess;
39 import libcore.reflect.GenericSignatureParser;
40 import libcore.reflect.ListOfTypes;
41 import libcore.reflect.Types;
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 
49     /**
50      * Hidden to workaround b/16828157.
51      * @hide
52      */
53     protected final ArtMethod artMethod;
54 
55     /**
56      * Hidden to workaround b/16828157.
57      * @hide
58      */
AbstractMethod(ArtMethod artMethod)59     protected AbstractMethod(ArtMethod artMethod) {
60         if (artMethod == null) {
61             throw new NullPointerException("artMethod == null");
62         }
63         this.artMethod = artMethod;
64     }
65 
getAnnotation(Class<T> annotationClass)66     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
67         return super.getAnnotation(annotationClass);
68     }
69 
70     /**
71      * We insert native method stubs for abstract methods so we don't have to
72      * check the access flags at the time of the method call.  This results in
73      * "native abstract" methods, which can't exist.  If we see the "abstract"
74      * flag set, clear the "native" flag.
75      *
76      * We also move the DECLARED_SYNCHRONIZED flag into the SYNCHRONIZED
77      * position, because the callers of this function are trying to convey
78      * the "traditional" meaning of the flags to their callers.
79      */
fixMethodFlags(int flags)80     private static int fixMethodFlags(int flags) {
81         if ((flags & Modifier.ABSTRACT) != 0) {
82             flags &= ~Modifier.NATIVE;
83         }
84         flags &= ~Modifier.SYNCHRONIZED;
85         int ACC_DECLARED_SYNCHRONIZED = 0x00020000;
86         if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) {
87             flags |= Modifier.SYNCHRONIZED;
88         }
89         return flags & 0xffff;  // mask out bits not used by Java
90     }
91 
getModifiers()92     int getModifiers() {
93         return fixMethodFlags(artMethod.getAccessFlags());
94     }
95 
isVarArgs()96     boolean isVarArgs() {
97         return (artMethod.getAccessFlags() & Modifier.VARARGS) != 0;
98     }
99 
isBridge()100     boolean isBridge() {
101         return (artMethod.getAccessFlags() & Modifier.BRIDGE) != 0;
102     }
103 
isSynthetic()104     boolean isSynthetic() {
105         return (artMethod.getAccessFlags() & Modifier.SYNTHETIC) != 0;
106     }
107 
108     /**
109      * @hide
110      */
getAccessFlags()111     public final int getAccessFlags() {
112         return artMethod.getAccessFlags();
113     }
114 
115     /**
116      * Returns the class that declares this constructor or method.
117      */
getDeclaringClass()118     Class<?> getDeclaringClass() {
119         return artMethod.getDeclaringClass();
120     }
121 
122     /**
123      * Returns the index of this method's ID in its dex file.
124      *
125      * @hide
126      */
getDexMethodIndex()127     public final int getDexMethodIndex() {
128         return artMethod.getDexMethodIndex();
129     }
130 
131     /**
132      * Returns the name of the method or constructor represented by this
133      * instance.
134      *
135      * @return the name of this method
136      */
getName()137     abstract public String getName();
138 
139     /**
140      * Returns an array of {@code Class} objects associated with the parameter types of this
141      * abstract method. If the method was declared with no parameters, an
142      * empty array will be returned.
143      *
144      * @return the parameter types
145      */
getParameterTypes()146     Class<?>[] getParameterTypes() {
147         return artMethod.getParameterTypes();
148     }
149 
150     /**
151      * Returns true if {@code other} has the same declaring class, name,
152      * parameters and return type as this method.
153      */
equals(Object other)154     @Override public boolean equals(Object other) {
155         if (!(other instanceof AbstractMethod)) {
156             return false;
157         }
158         // exactly one instance of each member in this runtime
159         return this.artMethod == ((AbstractMethod) other).artMethod;
160     }
161 
toGenericString()162     String toGenericString() {
163         return toGenericStringHelper();
164     }
165 
getGenericParameterTypes()166     Type[] getGenericParameterTypes() {
167         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false);
168     }
169 
getGenericExceptionTypes()170     Type[] getGenericExceptionTypes() {
171         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false);
172     }
173 
getDeclaredAnnotations()174     @Override public Annotation[] getDeclaredAnnotations() {
175         List<Annotation> result = AnnotationAccess.getDeclaredAnnotations(this);
176         return result.toArray(new Annotation[result.size()]);
177     }
178 
isAnnotationPresent(Class<? extends Annotation> annotationType)179     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
180         if (annotationType == null) {
181             throw new NullPointerException("annotationType == null");
182         }
183         return AnnotationAccess.isDeclaredAnnotationPresent(this, annotationType);
184     }
185 
getAnnotations()186     public Annotation[] getAnnotations() {
187         return super.getAnnotations();
188     }
189 
190     /**
191      * Returns an array of arrays that represent the annotations of the formal
192      * parameters of this method. If there are no parameters on this method,
193      * then an empty array is returned. If there are no annotations set, then
194      * and array of empty arrays is returned.
195      *
196      * @return an array of arrays of {@code Annotation} instances
197      */
getParameterAnnotations()198     public abstract Annotation[][] getParameterAnnotations();
199 
200     /**
201      * Returns the constructor's signature in non-printable form. This is called
202      * (only) from IO native code and needed for deriving the serialVersionUID
203      * of the class
204      *
205      * @return The constructor's signature.
206      */
207     @SuppressWarnings("unused")
getSignature()208     abstract String getSignature();
209 
210     static final class GenericInfo {
211         final ListOfTypes genericExceptionTypes;
212         final ListOfTypes genericParameterTypes;
213         final Type genericReturnType;
214         final TypeVariable<?>[] formalTypeParameters;
215 
GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret, TypeVariable<?>[] formal)216         GenericInfo(ListOfTypes exceptions, ListOfTypes parameters, Type ret,
217                     TypeVariable<?>[] formal) {
218             genericExceptionTypes = exceptions;
219             genericParameterTypes = parameters;
220             genericReturnType = ret;
221             formalTypeParameters = formal;
222         }
223     }
224 
225     /**
226      * Returns generic information associated with this method/constructor member.
227      */
getMethodOrConstructorGenericInfo()228     final GenericInfo getMethodOrConstructorGenericInfo() {
229         String signatureAttribute = AnnotationAccess.getSignature(this);
230         Member member;
231         Class<?>[] exceptionTypes;
232         boolean method = this instanceof Method;
233         if (method) {
234             Method m = (Method) this;
235             member = m;
236             exceptionTypes = m.getExceptionTypes();
237         } else {
238             Constructor<?> c = (Constructor<?>) this;
239             member = c;
240             exceptionTypes = c.getExceptionTypes();
241         }
242         GenericSignatureParser parser =
243             new GenericSignatureParser(member.getDeclaringClass().getClassLoader());
244         if (method) {
245             parser.parseForMethod((GenericDeclaration) this, signatureAttribute, exceptionTypes);
246         } else {
247             parser.parseForConstructor((GenericDeclaration) this,
248                                        signatureAttribute,
249                                        exceptionTypes);
250         }
251         return new GenericInfo(parser.exceptionTypes, parser.parameterTypes,
252                                parser.returnType, parser.formalTypeParameters);
253     }
254 
255     /**
256      * Helper for Method and Constructor for toGenericString
257      */
toGenericStringHelper()258     final String toGenericStringHelper() {
259         StringBuilder sb = new StringBuilder(80);
260         GenericInfo info =  getMethodOrConstructorGenericInfo();
261         int modifiers = ((Member)this).getModifiers();
262         // append modifiers if any
263         if (modifiers != 0) {
264             sb.append(Modifier.toString(modifiers & ~Modifier.VARARGS)).append(' ');
265         }
266         // append type parameters
267         if (info.formalTypeParameters != null && info.formalTypeParameters.length > 0) {
268             sb.append('<');
269             for (int i = 0; i < info.formalTypeParameters.length; i++) {
270                 Types.appendGenericType(sb, info.formalTypeParameters[i]);
271                 if (i < info.formalTypeParameters.length - 1) {
272                     sb.append(",");
273                 }
274             }
275             sb.append("> ");
276         }
277         Class<?> declaringClass = ((Member) this).getDeclaringClass();
278         if (this instanceof Constructor) {
279             // append constructor name
280             Types.appendTypeName(sb, declaringClass);
281         } else {
282             // append return type
283             Types.appendGenericType(sb, Types.getType(info.genericReturnType));
284             sb.append(' ');
285             // append method name
286             Types.appendTypeName(sb, declaringClass);
287             sb.append(".").append(((Method) this).getName());
288         }
289         // append parameters
290         sb.append('(');
291         Types.appendArrayGenericType(sb, info.genericParameterTypes.getResolvedTypes());
292         sb.append(')');
293         // append exceptions if any
294         Type[] genericExceptionTypeArray =
295             Types.getTypeArray(info.genericExceptionTypes, false);
296         if (genericExceptionTypeArray.length > 0) {
297             sb.append(" throws ");
298             Types.appendArrayGenericType(sb, genericExceptionTypeArray);
299         }
300         return sb.toString();
301     }
302 }
303