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) 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 java.lang.annotation.Annotation;
     36 import libcore.util.EmptyArray;
     37 import org.apache.harmony.kernel.vm.StringUtils;
     38 import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
     39 import org.apache.harmony.luni.lang.reflect.ListOfTypes;
     40 import org.apache.harmony.luni.lang.reflect.Types;
     41 
     42 /**
     43  * This class represents a constructor. Information about the constructor can be
     44  * accessed, and the constructor can be invoked dynamically.
     45  *
     46  * @param <T> the class that declares this constructor
     47  */
     48 public final class Constructor<T> extends AccessibleObject implements GenericDeclaration,
     49         Member {
     50 
     51     Class<T> declaringClass;
     52 
     53     Class<?>[] parameterTypes;
     54 
     55     Class<?>[] exceptionTypes;
     56 
     57     ListOfTypes genericExceptionTypes;
     58     ListOfTypes genericParameterTypes;
     59     TypeVariable<Constructor<T>>[] formalTypeParameters;
     60     private volatile boolean genericTypesAreInitialized = false;
     61 
     62     private synchronized void initGenericTypes() {
     63         if (!genericTypesAreInitialized) {
     64             String signatureAttribute = getSignatureAttribute();
     65             GenericSignatureParser parser = new GenericSignatureParser(
     66                     declaringClass.getClassLoader());
     67             parser.parseForConstructor(this, signatureAttribute, exceptionTypes);
     68             formalTypeParameters = parser.formalTypeParameters;
     69             genericParameterTypes = parser.parameterTypes;
     70             genericExceptionTypes = parser.exceptionTypes;
     71             genericTypesAreInitialized = true;
     72         }
     73     }
     74 
     75     int slot;
     76 
     77     /**
     78      * Prevent this class from being instantiated.
     79      */
     80     private Constructor(){
     81         //do nothing
     82     }
     83 
     84     /**
     85      * Creates an instance of the class. Only called from native code, thus
     86      * private.
     87      *
     88      * @param declaringClass
     89      *            the class this constructor object belongs to
     90      * @param ptypes
     91      *            the parameter types of the constructor
     92      * @param extypes
     93      *            the exception types of the constructor
     94      * @param slot
     95      *            the slot of the constructor inside the VM class structure
     96      */
     97     private Constructor (Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot){
     98         this.declaringClass = declaringClass;
     99         this.parameterTypes = ptypes;
    100         this.exceptionTypes = extypes;          // may be null
    101         this.slot = slot;
    102     }
    103 
    104     @Override /*package*/ String getSignatureAttribute() {
    105         Object[] annotation = Method.getSignatureAnnotation(declaringClass, slot);
    106 
    107         if (annotation == null) {
    108             return null;
    109         }
    110 
    111         return StringUtils.combineStrings(annotation);
    112     }
    113 
    114     public TypeVariable<Constructor<T>>[] getTypeParameters() {
    115         initGenericTypes();
    116         return formalTypeParameters.clone();
    117     }
    118 
    119     /**
    120      * Returns the string representation of the constructor's declaration,
    121      * including the type parameters.
    122      *
    123      * @return the string representation of the constructor's declaration
    124      */
    125     public String toGenericString() {
    126         StringBuilder sb = new StringBuilder(80);
    127         initGenericTypes();
    128         // append modifiers if any
    129         int modifier = getModifiers();
    130         if (modifier != 0) {
    131             sb.append(Modifier.toString(modifier & ~Modifier.VARARGS)).append(' ');
    132         }
    133         // append type parameters
    134         if (formalTypeParameters != null && formalTypeParameters.length > 0) {
    135             sb.append('<');
    136             for (int i = 0; i < formalTypeParameters.length; i++) {
    137                 appendGenericType(sb, formalTypeParameters[i]);
    138                 if (i < formalTypeParameters.length - 1) {
    139                     sb.append(",");
    140                 }
    141             }
    142             sb.append("> ");
    143         }
    144         // append constructor name
    145         appendTypeName(sb, getDeclaringClass());
    146         // append parameters
    147         sb.append('(');
    148         appendArrayGenericType(sb,
    149                 Types.getClonedTypeArray(genericParameterTypes));
    150         sb.append(')');
    151         // append exceptions if any
    152         Type[] genericExceptionTypeArray =
    153                 Types.getClonedTypeArray(genericExceptionTypes);
    154         if (genericExceptionTypeArray.length > 0) {
    155             sb.append(" throws ");
    156             appendArrayGenericType(sb, genericExceptionTypeArray);
    157         }
    158         return sb.toString();
    159     }
    160 
    161     /**
    162      * Returns the generic parameter types as an array of {@code Type}
    163      * instances, in declaration order. If this constructor has no generic
    164      * parameters, an empty array is returned.
    165      *
    166      * @return the parameter types
    167      *
    168      * @throws GenericSignatureFormatError
    169      *             if the generic constructor signature is invalid
    170      * @throws TypeNotPresentException
    171      *             if any parameter type points to a missing type
    172      * @throws MalformedParameterizedTypeException
    173      *             if any parameter type points to a type that cannot be
    174      *             instantiated for some reason
    175      */
    176     public Type[] getGenericParameterTypes() {
    177         initGenericTypes();
    178         return Types.getClonedTypeArray(genericParameterTypes);
    179     }
    180 
    181     /**
    182      * Returns the exception types as an array of {@code Type} instances. If
    183      * this constructor has no declared exceptions, an empty array will be
    184      * returned.
    185      *
    186      * @return an array of generic exception types
    187      *
    188      * @throws GenericSignatureFormatError
    189      *             if the generic constructor signature is invalid
    190      * @throws TypeNotPresentException
    191      *             if any exception type points to a missing type
    192      * @throws MalformedParameterizedTypeException
    193      *             if any exception type points to a type that cannot be
    194      *             instantiated for some reason
    195      */
    196     public Type[] getGenericExceptionTypes() {
    197         initGenericTypes();
    198         return Types.getClonedTypeArray(genericExceptionTypes);
    199     }
    200 
    201     @Override
    202     public Annotation[] getDeclaredAnnotations() {
    203         return Method.getDeclaredAnnotations(declaringClass, slot);
    204     }
    205 
    206     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
    207         if (annotationType == null) {
    208             throw new NullPointerException("annotationType == null");
    209         }
    210         return Method.getAnnotation(declaringClass, slot, annotationType);
    211     }
    212 
    213     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
    214         if (annotationType == null) {
    215             throw new NullPointerException("annotationType == null");
    216         }
    217         return Method.isAnnotationPresent(declaringClass, slot, annotationType);
    218     }
    219 
    220     /**
    221      * Returns an array of arrays that represent the annotations of the formal
    222      * parameters of this constructor. If there are no parameters on this
    223      * constructor, then an empty array is returned. If there are no annotations
    224      * set, then an array of empty arrays is returned.
    225      *
    226      * @return an array of arrays of {@code Annotation} instances
    227      */
    228     public Annotation[][] getParameterAnnotations() {
    229         Annotation[][] parameterAnnotations
    230                 = Method.getParameterAnnotations(declaringClass, slot);
    231         if (parameterAnnotations.length == 0) {
    232             return Method.noAnnotations(parameterTypes.length);
    233         }
    234         return parameterAnnotations;
    235     }
    236 
    237     /**
    238      * Indicates whether or not this constructor takes a variable number of
    239      * arguments.
    240      *
    241      * @return {@code true} if a vararg is declare, otherwise
    242      *         {@code false}
    243      */
    244     public boolean isVarArgs() {
    245         int mods = Method.getMethodModifiers(declaringClass, slot);
    246         return (mods & Modifier.VARARGS) != 0;
    247     }
    248 
    249     /**
    250      * Indicates whether or not this constructor is synthetic (artificially
    251      * introduced by the compiler).
    252      *
    253      * @return {@code true} if this constructor is synthetic, {@code false}
    254      *         otherwise
    255      */
    256     public boolean isSynthetic() {
    257         int mods = Method.getMethodModifiers(declaringClass, slot);
    258         return (mods & Modifier.SYNTHETIC) != 0;
    259     }
    260 
    261     /**
    262      * Indicates whether or not the specified {@code object} is equal to this
    263      * constructor. To be equal, the specified object must be an instance
    264      * of {@code Constructor} with the same declaring class and parameter types
    265      * as this constructor.
    266      *
    267      * @param object
    268      *            the object to compare
    269      *
    270      * @return {@code true} if the specified object is equal to this
    271      *         constructor, {@code false} otherwise
    272      *
    273      * @see #hashCode
    274      */
    275     @Override
    276     public boolean equals(Object object) {
    277         return object instanceof Constructor && toString().equals(object.toString());
    278     }
    279 
    280     /**
    281      * Returns the class that declares this constructor.
    282      *
    283      * @return the declaring class
    284      */
    285     public Class<T> getDeclaringClass() {
    286         return declaringClass;
    287     }
    288 
    289     /**
    290      * Returns the exception types as an array of {@code Class} instances. If
    291      * this constructor has no declared exceptions, an empty array will be
    292      * returned.
    293      *
    294      * @return the declared exception classes
    295      */
    296     public Class<?>[] getExceptionTypes() {
    297         if (exceptionTypes == null) {
    298             return EmptyArray.CLASS;
    299         }
    300         return exceptionTypes.clone();
    301     }
    302 
    303     /**
    304      * Returns the modifiers for this constructor. The {@link Modifier} class
    305      * should be used to decode the result.
    306      *
    307      * @return the modifiers for this constructor
    308      *
    309      * @see Modifier
    310      */
    311     public int getModifiers() {
    312         return Method.getMethodModifiers(declaringClass, slot);
    313     }
    314 
    315     /**
    316      * Returns the name of this constructor.
    317      *
    318      * @return the name of this constructor
    319      */
    320     public String getName() {
    321         return declaringClass.getName();
    322     }
    323 
    324     /**
    325      * Returns an array of the {@code Class} objects associated with the
    326      * parameter types of this constructor. If the constructor was declared with
    327      * no parameters, an empty array will be returned.
    328      *
    329      * @return the parameter types
    330      */
    331     public Class<?>[] getParameterTypes() {
    332         return parameterTypes.clone();
    333     }
    334 
    335     /**
    336      * Returns the constructor's signature in non-printable form. This is called
    337      * (only) from IO native code and needed for deriving the serialVersionUID
    338      * of the class
    339      *
    340      * @return the constructor's signature
    341      */
    342     @SuppressWarnings("unused")
    343     private String getSignature() {
    344         StringBuilder result = new StringBuilder();
    345 
    346         result.append('(');
    347         for (int i = 0; i < parameterTypes.length; i++) {
    348             result.append(getSignature(parameterTypes[i]));
    349         }
    350         result.append(")V");
    351 
    352         return result.toString();
    353     }
    354 
    355     /**
    356      * Returns an integer hash code for this constructor. Constructors which are
    357      * equal return the same value for this method. The hash code for a
    358      * Constructor is the hash code of the name of the declaring class.
    359      *
    360      * @return the hash code
    361      *
    362      * @see #equals
    363      */
    364     @Override
    365     public int hashCode() {
    366         return declaringClass.getName().hashCode();
    367     }
    368 
    369     /**
    370      * Returns a new instance of the declaring class, initialized by dynamically
    371      * invoking the constructor represented by this {@code Constructor} object.
    372      * This reproduces the effect of {@code new declaringClass(arg1, arg2, ... ,
    373      * argN)} This method performs the following:
    374      * <ul>
    375      * <li>A new instance of the declaring class is created. If the declaring
    376      * class cannot be instantiated (i.e. abstract class, an interface, an array
    377      * type, or a primitive type) then an InstantiationException is thrown.</li>
    378      * <li>If this Constructor object is enforcing access control (see
    379      * {@link AccessibleObject}) and this constructor is not accessible from the
    380      * current context, an IllegalAccessException is thrown.</li>
    381      * <li>If the number of arguments passed and the number of parameters do not
    382      * match, an IllegalArgumentException is thrown.</li>
    383      * <li>For each argument passed:
    384      * <ul>
    385      * <li>If the corresponding parameter type is a primitive type, the argument
    386      * is unboxed. If the unboxing fails, an IllegalArgumentException is
    387      * thrown.</li>
    388      * <li>If the resulting argument cannot be converted to the parameter type
    389      * via a widening conversion, an IllegalArgumentException is thrown.</li>
    390      * </ul>
    391      * <li>The constructor represented by this {@code Constructor} object is
    392      * then invoked. If an exception is thrown during the invocation, it is
    393      * caught and wrapped in an InvocationTargetException. This exception is
    394      * then thrown. If the invocation completes normally, the newly initialized
    395      * object is returned.
    396      * </ul>
    397      *
    398      * @param args
    399      *            the arguments to the constructor
    400      *
    401      * @return the new, initialized, object
    402      *
    403      * @exception InstantiationException
    404      *                if the class cannot be instantiated
    405      * @exception IllegalAccessException
    406      *                if this constructor is not accessible
    407      * @exception IllegalArgumentException
    408      *                if an incorrect number of arguments are passed, or an
    409      *                argument could not be converted by a widening conversion
    410      * @exception InvocationTargetException
    411      *                if an exception was thrown by the invoked constructor
    412      *
    413      * @see AccessibleObject
    414      */
    415     public T newInstance(Object... args) throws InstantiationException, IllegalAccessException,
    416             IllegalArgumentException, InvocationTargetException {
    417         return constructNative (args, declaringClass, parameterTypes, slot, flag);
    418     }
    419 
    420     private native T constructNative(Object[] args, Class<T> declaringClass,
    421             Class<?>[] parameterTypes, int slot,
    422             boolean noAccessCheck) throws InstantiationException, IllegalAccessException,
    423             InvocationTargetException;
    424 
    425     /**
    426      * Returns a string containing a concise, human-readable description of this
    427      * constructor. The format of the string is:
    428      *
    429      * <ol>
    430      *   <li>modifiers (if any)
    431      *   <li>declaring class name
    432      *   <li>'('
    433      *   <li>parameter types, separated by ',' (if any)
    434      *   <li>')'
    435      *   <li>'throws' plus exception types, separated by ',' (if any)
    436      * </ol>
    437      *
    438      * For example:
    439      * {@code public String(byte[],String) throws UnsupportedEncodingException}
    440      *
    441      * @return a printable representation for this constructor
    442      */
    443     @Override
    444     public String toString() {
    445         StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
    446 
    447         if (result.length() != 0)
    448             result.append(' ');
    449         result.append(declaringClass.getName());
    450         result.append("(");
    451         result.append(toString(parameterTypes));
    452         result.append(")");
    453         if (exceptionTypes != null && exceptionTypes.length != 0) {
    454             result.append(" throws ");
    455             result.append(toString(exceptionTypes));
    456         }
    457 
    458         return result.toString();
    459     }
    460 }
    461