0f6e1f0038f631fd72b50e8dade67a697d3f1981
[cacao.git] / src / lib / gnu / java / lang / reflect / Constructor.java
1 /* java.lang.reflect.Constructor - reflection of Java constructors
2    Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10  
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package java.lang.reflect;
40
41 import gnu.java.lang.ClassHelper;
42
43 import gnu.java.lang.reflect.MethodSignatureParser;
44
45 import java.lang.annotation.Annotation;
46 import java.util.Map;
47 import java.util.Arrays;
48
49 /**
50  * The Constructor class represents a constructor of a class. It also allows
51  * dynamic creation of an object, via reflection. Invocation on Constructor
52  * objects knows how to do widening conversions, but throws
53  * {@link IllegalArgumentException} if a narrowing conversion would be
54  * necessary. You can query for information on this Constructor regardless
55  * of location, but construction access may be limited by Java language
56  * access controls. If you can't do it in the compiler, you can't normally
57  * do it here either.<p>
58  *
59  * <B>Note:</B> This class returns and accepts types as Classes, even
60  * primitive types; there are Class types defined that represent each
61  * different primitive type.  They are <code>java.lang.Boolean.TYPE,
62  * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
63  * byte.class</code>, etc.  These are not to be confused with the
64  * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
65  * real classes.<p>
66  *
67  * Also note that this is not a serializable class.  It is entirely feasible
68  * to make it serializable using the Externalizable interface, but this is
69  * on Sun, not me.
70  *
71  * @author John Keiser
72  * @author Eric Blake <ebb9@email.byu.edu>
73  * @see Member
74  * @see Class
75  * @see java.lang.Class#getConstructor(Class[])
76  * @see java.lang.Class#getDeclaredConstructor(Class[])
77  * @see java.lang.Class#getConstructors()
78  * @see java.lang.Class#getDeclaredConstructors()
79  * @since 1.1
80  * @status updated to 1.4
81  */
82 public final class Constructor<T>
83   extends AccessibleObject
84   implements GenericDeclaration, Member
85 {
86   private Class<T> clazz;
87   private int slot;
88
89   /**
90    * Unparsed annotations.
91    */
92   private byte[] annotations = null;
93
94   /**
95    * Unparsed parameter annotations.
96    */
97   private byte[] parameterAnnotations = null;
98   
99   /**
100    * Annotations get parsed the first time they are
101    * accessed and are then cached it this map.
102    */
103   private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
104   
105   private static final int CONSTRUCTOR_MODIFIERS
106     = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
107   
108   /**
109    * Helper array for creating a new array from a java.util.Container.
110    */
111   private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
112     new Annotation[0];
113
114   /**
115    * This class is uninstantiable except from native code.
116    */
117   private Constructor(Class declaringClass,int slot)
118   {
119     this.clazz = declaringClass;
120     this.slot = slot;
121   }
122
123   private Constructor()
124   {
125   }
126
127   /**
128    * Gets the class that declared this constructor.
129    * @return the class that declared this member
130    */
131   public Class<T> getDeclaringClass()
132   {
133     return clazz;
134   }
135
136   /**
137    * Gets the name of this constructor (the non-qualified name of the class
138    * it was declared in).
139    * @return the name of this constructor
140    */
141   public String getName()
142   {
143     return getDeclaringClass().getName();
144   }
145
146   /**
147    * Return the raw modifiers for this constructor.  In particular
148    * this will include the synthetic and varargs bits.
149    * @return the constructor's modifiers
150    */
151   private native int getModifiersInternal();
152
153   /**
154    * Gets the modifiers this constructor uses.  Use the <code>Modifier</code>
155    * class to interpret the values. A constructor can only have a subset of the
156    * following modifiers: public, private, protected.
157    *
158    * @return an integer representing the modifiers to this Member
159    * @see Modifier
160    */
161   public int getModifiers()
162   {
163     return getModifiersInternal() & CONSTRUCTOR_MODIFIERS;
164   }
165
166   /**
167    * Return true if this constructor is synthetic, false otherwise.
168    * A synthetic member is one which is created by the compiler,
169    * and which does not appear in the user's source code.
170    * @since 1.5
171    */
172   public boolean isSynthetic()
173   {
174     return (getModifiersInternal() & Modifier.SYNTHETIC) != 0;
175   }
176
177   /**
178    * Return true if this is a varargs constructor, that is if
179    * the constructor takes a variable number of arguments.
180    * @since 1.5
181    */
182   public boolean isVarArgs()
183   {
184     return (getModifiersInternal() & Modifier.VARARGS) != 0;
185   }
186
187   /**
188    * Get the parameter list for this constructor, in declaration order. If the
189    * constructor takes no parameters, returns a 0-length array (not null).
190    *
191    * @return a list of the types of the constructor's parameters
192    */
193   public native Class<?>[] getParameterTypes();
194
195   /**
196    * Get the exception types this constructor says it throws, in no particular
197    * order. If the constructor has no throws clause, returns a 0-length array
198    * (not null).
199    *
200    * @return a list of the types in the constructor's throws clause
201    */
202   public native Class<?>[] getExceptionTypes();
203
204   /**
205    * Compare two objects to see if they are semantically equivalent.
206    * Two Constructors are semantically equivalent if they have the same
207    * declaring class and the same parameter list.  This ignores different
208    * exception clauses, but since you can't create a Method except through the
209    * VM, this is just the == relation.
210    *
211    * @param o the object to compare to
212    * @return <code>true</code> if they are equal; <code>false</code> if not.
213    */
214   public boolean equals(Object o)
215   {
216     if (!(o instanceof Constructor))
217       return false;
218     Constructor that = (Constructor)o; 
219     if (this.getDeclaringClass() != that.getDeclaringClass())
220       return false;
221     if (!Arrays.equals(this.getParameterTypes(), that.getParameterTypes()))
222       return false;
223     return true;
224   }
225
226   /**
227    * Get the hash code for the Constructor. The Constructor hash code is the
228    * hash code of the declaring class's name.
229    *
230    * @return the hash code for the object
231    */
232   public int hashCode()
233   {
234     return getDeclaringClass().getName().hashCode();
235   }
236
237   /**
238    * Get a String representation of the Constructor. A Constructor's String
239    * representation is "&lt;modifier&gt; &lt;classname&gt;(&lt;paramtypes&gt;)
240    * throws &lt;exceptions&gt;", where everything after ')' is omitted if
241    * there are no exceptions.<br> Example:
242    * <code>public java.io.FileInputStream(java.lang.Runnable)
243    * throws java.io.FileNotFoundException</code>
244    *
245    * @return the String representation of the Constructor
246    */
247   public String toString()
248   {
249     // 128 is a reasonable buffer initial size for constructor
250     StringBuilder sb = new StringBuilder(128);
251     Modifier.toString(getModifiers(), sb).append(' ');
252     sb.append(getDeclaringClass().getName()).append('(');
253     Class[] c = getParameterTypes();
254     if (c.length > 0)
255       {
256         sb.append(ClassHelper.getUserName(c[0]));
257         for (int i = 1; i < c.length; i++)
258           sb.append(',').append(ClassHelper.getUserName(c[i]));
259       }
260     sb.append(')');
261     c = getExceptionTypes();
262     if (c.length > 0)
263       {
264         sb.append(" throws ").append(c[0].getName());
265         for (int i = 1; i < c.length; i++)
266           sb.append(',').append(c[i].getName());
267       }
268     return sb.toString();
269   }
270
271   static <X extends GenericDeclaration>
272   void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs)
273   {
274     if (typeArgs.length == 0)
275       return;
276     sb.append('<');
277     for (int i = 0; i < typeArgs.length; ++i)
278       {
279         if (i > 0)
280           sb.append(',');
281         sb.append(typeArgs[i]);
282       }
283     sb.append("> ");
284   }
285
286   public String toGenericString()
287   {
288     StringBuilder sb = new StringBuilder(128);
289     Modifier.toString(getModifiers(), sb).append(' ');
290     addTypeParameters(sb, getTypeParameters());
291     sb.append(getDeclaringClass().getName()).append('(');
292     Type[] types = getGenericParameterTypes();
293     if (types.length > 0)
294       {
295         sb.append(types[0]);
296         for (int i = 1; i < types.length; ++i)
297           sb.append(',').append(types[i]);
298       }
299     sb.append(')');
300     types = getGenericExceptionTypes();
301     if (types.length > 0)
302       {
303         sb.append(" throws ").append(types[0]);
304         for (int i = 1; i < types.length; i++)
305           sb.append(',').append(types[i]);
306       }
307     return sb.toString();
308   }
309
310   /**
311    * Create a new instance by invoking the constructor. Arguments are
312    * automatically unwrapped and widened, if needed.<p>
313    *
314    * If this class is abstract, you will get an
315    * <code>InstantiationException</code>. If the constructor takes 0
316    * arguments, you may use null or a 0-length array for <code>args</code>.<p>
317    *
318    * If this Constructor enforces access control, your runtime context is
319    * evaluated, and you may have an <code>IllegalAccessException</code> if
320    * you could not create this object in similar compiled code. If the class
321    * is uninitialized, you trigger class initialization, which may end in a
322    * <code>ExceptionInInitializerError</code>.<p>
323    *
324    * Then, the constructor is invoked. If it completes normally, the return
325    * value will be the new object. If it completes abruptly, the exception is
326    * wrapped in an <code>InvocationTargetException</code>.
327    *
328    * @param args the arguments to the constructor
329    * @return the newly created object
330    * @throws IllegalAccessException if the constructor could not normally be
331    *         called by the Java code (i.e. it is not public)
332    * @throws IllegalArgumentException if the number of arguments is incorrect;
333    *         or if the arguments types are wrong even with a widening
334    *         conversion
335    * @throws InstantiationException if the class is abstract
336    * @throws InvocationTargetException if the constructor throws an exception
337    * @throws ExceptionInInitializerError if construction triggered class
338    *         initialization, which then failed
339    */
340   public T newInstance(Object... args)
341     throws InstantiationException, IllegalAccessException,
342            InvocationTargetException
343   {
344     return constructNative(args, clazz, slot);
345   }
346
347   private native T constructNative(Object[] args, Class declaringClass,
348                                    int slot)
349     throws InstantiationException, IllegalAccessException,
350            InvocationTargetException;
351
352   /**
353    * Returns an array of <code>TypeVariable</code> objects that represents
354    * the type variables declared by this constructor, in declaration order.
355    * An array of size zero is returned if this constructor has no type
356    * variables.
357    *
358    * @return the type variables associated with this constructor.
359    * @throws GenericSignatureFormatError if the generic signature does
360    *         not conform to the format specified in the Virtual Machine
361    *         specification, version 3.
362    * @since 1.5
363    */
364   public TypeVariable<Constructor<T>>[] getTypeParameters()
365   {
366     String sig = getSignature();
367     if (sig == null)
368       return new TypeVariable[0];
369     MethodSignatureParser p = new MethodSignatureParser(this, sig);
370     return p.getTypeParameters();
371   }
372
373   /**
374    * Return the String in the Signature attribute for this constructor. If there
375    * is no Signature attribute, return null.
376    */
377   private native String getSignature();
378
379   /**
380    * Returns an array of <code>Type</code> objects that represents
381    * the exception types declared by this constructor, in declaration order.
382    * An array of size zero is returned if this constructor declares no
383    * exceptions.
384    *
385    * @return the exception types declared by this constructor. 
386    * @throws GenericSignatureFormatError if the generic signature does
387    *         not conform to the format specified in the Virtual Machine
388    *         specification, version 3.
389    * @since 1.5
390    */
391   public Type[] getGenericExceptionTypes()
392   {
393     String sig = getSignature();
394     if (sig == null)
395       return getExceptionTypes();
396     MethodSignatureParser p = new MethodSignatureParser(this, sig);
397     return p.getGenericExceptionTypes();
398   }
399
400   /**
401    * Returns an array of <code>Type</code> objects that represents
402    * the parameter list for this constructor, in declaration order.
403    * An array of size zero is returned if this constructor takes no
404    * parameters.
405    *
406    * @return a list of the types of the constructor's parameters
407    * @throws GenericSignatureFormatError if the generic signature does
408    *         not conform to the format specified in the Virtual Machine
409    *         specification, version 3.
410    * @since 1.5
411    */
412   public Type[] getGenericParameterTypes()
413   {
414     String sig = getSignature();
415     if (sig == null)
416       return getParameterTypes();
417     MethodSignatureParser p = new MethodSignatureParser(this, sig);
418     return p.getGenericParameterTypes();
419   }
420     
421   /**
422    * @throws NullPointerException {@inheritDoc}
423    * @since 1.5
424    */
425   public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
426     if (annotationClass == null)
427       throw new NullPointerException();
428
429     return (T)declaredAnnotations().get(annotationClass);
430   }
431
432   /**
433    * @since 1.5
434    */
435   public Annotation[] getDeclaredAnnotations() {
436     return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
437   }
438
439   /**
440    * Parses the annotations if they aren't parsed yet and stores them into
441    * the declaredAnnotations map and return this map.
442    */
443   private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
444   
445   /**
446    * Returns an array of arrays that represent the annotations on the formal
447    * parameters, in declaration order, of the method represented by
448    * this <tt>Method</tt> object. (Returns an array of length zero if the
449    * underlying method is parameterless.  If the method has one or more
450    * parameters, a nested array of length zero is returned for each parameter
451    * with no annotations.) The annotation objects contained in the returned
452    * arrays are serializable.  The caller of this method is free to modify
453    * the returned arrays; it will have no effect on the arrays returned to
454    * other callers.
455    *
456    * @return an array of arrays that represent the annotations on the formal
457    *    parameters, in declaration order, of the method represented by this
458    *    Method object
459    * @since 1.5
460    */
461   public native Annotation[][] getParameterAnnotations();
462 }