Home | History | Annotate | Download | only in reflect
      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      */
     73     protected AbstractMethod() {
     74     }
     75 
     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      */
     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 
    102     int getModifiers() {
    103         return fixMethodFlags(accessFlags);
    104     }
    105 
    106     boolean isVarArgs() {
    107         return (accessFlags & Modifier.VARARGS) != 0;
    108     }
    109 
    110     boolean isBridge() {
    111         return (accessFlags & Modifier.BRIDGE) != 0;
    112     }
    113 
    114     boolean isSynthetic() {
    115         return (accessFlags & Modifier.SYNTHETIC) != 0;
    116     }
    117 
    118     boolean isDefault() {
    119       return (accessFlags & Modifier.DEFAULT) != 0;
    120     }
    121 
    122     /**
    123      * @hide
    124      */
    125     public final int getAccessFlags() {
    126         return accessFlags;
    127     }
    128 
    129     /**
    130      * Returns the class that declares this constructor or method.
    131      */
    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      */
    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      */
    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      */
    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      */
    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 
    188     String toGenericString() {
    189         return toGenericStringHelper();
    190     }
    191 
    192     Type[] getGenericParameterTypes() {
    193         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericParameterTypes, false);
    194     }
    195 
    196     Type[] getGenericExceptionTypes() {
    197         return Types.getTypeArray(getMethodOrConstructorGenericInfo().genericExceptionTypes, false);
    198     }
    199 
    200     @Override public native Annotation[] getDeclaredAnnotations();
    201 
    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 
    209     private native boolean isAnnotationPresentNative(Class<? extends Annotation> annotationType);
    210 
    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      */
    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")
    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 
    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      */
    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 
    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 
    292     private native String[] getSignatureAnnotation();
    293 
    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 
    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      */
    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