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