Clean merge -> gc7-branch
[cacao.git] / src / classes / gnu / java / lang / reflect / VMField.java
1 /* java.lang.reflect.Field - VM interface for reflection of Java fields
2    Copyright (C) 1998, 2001, 2005, 2008 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 java.lang.annotation.Annotation;
42
43 import java.util.Map;
44
45 final class VMField
46 {
47   Class clazz;
48   String name;
49   int slot;
50   
51   /**
52    * Unparsed annotations.
53    */
54   private byte[] annotations = null;
55
56   /**
57    * Annotations get parsed the first time they are
58    * accessed and are then cached it this map.
59    */
60   private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
61
62   /**
63    * Helper array for creating a new array from a java.util.Container.
64    */
65   private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
66     new Annotation[0];
67
68   /** 
69    * This field allows us to refer back to the main constructor instance.
70    *  It is set by the constructor of Field.
71    */
72   Field f;
73
74   VMField(Class clazz, String name, int slot)
75   {
76     this.clazz = clazz;
77     this.name = name;
78     this.slot = slot;
79   }
80
81   public Class getDeclaringClass()
82   {
83     return clazz;
84   }
85
86   public String getName()
87   {
88     return name;
89   }
90
91   /**
92    * Return the raw modifiers for this field.
93    * @return the field's modifiers
94    */
95   native int getModifiersInternal();
96
97   /**
98    * Gets the type of this field.
99    * @return the type of this field
100    */
101   native Class getType();
102
103   /**
104    * Get the value of this Field.  If it is primitive, it will be wrapped
105    * in the appropriate wrapper type (boolean = java.lang.Boolean).<p>
106    *
107    * If the field is static, <code>o</code> will be ignored. Otherwise, if
108    * <code>o</code> is null, you get a <code>NullPointerException</code>,
109    * and if it is incompatible with the declaring class of the field, you
110    * get an <code>IllegalArgumentException</code>.<p>
111    *
112    * Next, if this Field enforces access control, your runtime context is
113    * evaluated, and you may have an <code>IllegalAccessException</code> if
114    * you could not access this field in similar compiled code. If the field
115    * is static, and its class is uninitialized, you trigger class
116    * initialization, which may end in a
117    * <code>ExceptionInInitializerError</code>.<p>
118    *
119    * Finally, the field is accessed, and primitives are wrapped (but not
120    * necessarily in new objects). This method accesses the field of the
121    * declaring class, even if the instance passed in belongs to a subclass
122    * which declares another field to hide this one.
123    *
124    * @param o the object to get the value of this Field from
125    * @return the value of the Field
126    * @throws IllegalAccessException if you could not normally access this field
127    *         (i.e. it is not public)
128    * @throws IllegalArgumentException if <code>o</code> is not an instance of
129    *         the class or interface declaring this field
130    * @throws NullPointerException if <code>o</code> is null and this field
131    *         requires an instance
132    * @throws ExceptionInInitializerError if accessing a static field triggered
133    *         class initialization, which then failed
134    * @see #getBoolean(Object)
135    * @see #getByte(Object)
136    * @see #getChar(Object)
137    * @see #getShort(Object)
138    * @see #getInt(Object)
139    * @see #getLong(Object)
140    * @see #getFloat(Object)
141    * @see #getDouble(Object)
142    */
143   native Object get(Object o)
144     throws IllegalAccessException;
145
146   /**
147    * Get the value of this boolean Field. If the field is static,
148    * <code>o</code> will be ignored.
149    *
150    * @param o the object to get the value of this Field from
151    * @return the value of the Field
152    * @throws IllegalAccessException if you could not normally access this field
153    *         (i.e. it is not public)
154    * @throws IllegalArgumentException if this is not a boolean field of
155    *         <code>o</code>, or if <code>o</code> is not an instance of the
156    *         declaring class of this field
157    * @throws NullPointerException if <code>o</code> is null and this field
158    *         requires an instance
159    * @throws ExceptionInInitializerError if accessing a static field triggered
160    *         class initialization, which then failed
161    * @see #get(Object)
162    */
163   native boolean getBoolean(Object o)
164     throws IllegalAccessException;
165
166   /**
167    * Get the value of this byte Field. If the field is static,
168    * <code>o</code> will be ignored.
169    *
170    * @param o the object to get the value of this Field from
171    * @return the value of the Field
172    * @throws IllegalAccessException if you could not normally access this field
173    *         (i.e. it is not public)
174    * @throws IllegalArgumentException if this is not a byte field of
175    *         <code>o</code>, or if <code>o</code> is not an instance of the
176    *         declaring class of this field
177    * @throws NullPointerException if <code>o</code> is null and this field
178    *         requires an instance
179    * @throws ExceptionInInitializerError if accessing a static field triggered
180    *         class initialization, which then failed
181    * @see #get(Object)
182    */
183   native byte getByte(Object o)
184     throws IllegalAccessException;
185
186   /**
187    * Get the value of this Field as a char. If the field is static,
188    * <code>o</code> will be ignored.
189    *
190    * @param o the object to get the value of this Field from
191    * @throws IllegalAccessException if you could not normally access this field
192    *         (i.e. it is not public)
193    * @throws IllegalArgumentException if this is not a char field of
194    *         <code>o</code>, or if <code>o</code> is not an instance
195    *         of the declaring class of this field
196    * @throws NullPointerException if <code>o</code> is null and this field
197    *         requires an instance
198    * @throws ExceptionInInitializerError if accessing a static field triggered
199    *         class initialization, which then failed
200    * @see #get(Object)
201    */
202   native char getChar(Object o)
203     throws IllegalAccessException;
204
205   /**
206    * Get the value of this Field as a short. If the field is static,
207    * <code>o</code> will be ignored.
208    *
209    * @param o the object to get the value of this Field from
210    * @return the value of the Field
211    * @throws IllegalAccessException if you could not normally access this field
212    *         (i.e. it is not public)
213    * @throws IllegalArgumentException if this is not a byte or short
214    *         field of <code>o</code>, or if <code>o</code> is not an instance
215    *         of the declaring class of this field
216    * @throws NullPointerException if <code>o</code> is null and this field
217    *         requires an instance
218    * @throws ExceptionInInitializerError if accessing a static field triggered
219    *         class initialization, which then failed
220    * @see #get(Object)
221    */
222   native short getShort(Object o)
223     throws IllegalAccessException;
224
225   /**
226    * Get the value of this Field as an int. If the field is static,
227    * <code>o</code> will be ignored.
228    *
229    * @param o the object to get the value of this Field from
230    * @return the value of the Field
231    * @throws IllegalAccessException if you could not normally access this field
232    *         (i.e. it is not public)
233    * @throws IllegalArgumentException if this is not a byte, short, char, or
234    *         int field of <code>o</code>, or if <code>o</code> is not an
235    *         instance of the declaring class of this field
236    * @throws NullPointerException if <code>o</code> is null and this field
237    *         requires an instance
238    * @throws ExceptionInInitializerError if accessing a static field triggered
239    *         class initialization, which then failed
240    * @see #get(Object)
241    */
242   native int getInt(Object o)
243     throws IllegalAccessException;
244
245   /**
246    * Get the value of this Field as a long. If the field is static,
247    * <code>o</code> will be ignored.
248    *
249    * @param o the object to get the value of this Field from
250    * @return the value of the Field
251    * @throws IllegalAccessException if you could not normally access this field
252    *         (i.e. it is not public)
253    * @throws IllegalArgumentException if this is not a byte, short, char, int,
254    *         or long field of <code>o</code>, or if <code>o</code> is not an
255    *         instance of the declaring class of this field
256    * @throws NullPointerException if <code>o</code> is null and this field
257    *         requires an instance
258    * @throws ExceptionInInitializerError if accessing a static field triggered
259    *         class initialization, which then failed
260    * @see #get(Object)
261    */
262   native long getLong(Object o)
263     throws IllegalAccessException;
264
265   /**
266    * Get the value of this Field as a float. If the field is static,
267    * <code>o</code> will be ignored.
268    *
269    * @param o the object to get the value of this Field from
270    * @return the value of the Field
271    * @throws IllegalAccessException if you could not normally access this field
272    *         (i.e. it is not public)
273    * @throws IllegalArgumentException if this is not a byte, short, char, int,
274    *         long, or float field of <code>o</code>, or if <code>o</code> is
275    *         not an instance of the declaring class of this field
276    * @throws NullPointerException if <code>o</code> is null and this field
277    *         requires an instance
278    * @throws ExceptionInInitializerError if accessing a static field triggered
279    *         class initialization, which then failed
280    * @see #get(Object)
281    */
282   native float getFloat(Object o)
283     throws IllegalAccessException;
284
285   /**
286    * Get the value of this Field as a double. If the field is static,
287    * <code>o</code> will be ignored.
288    *
289    * @param o the object to get the value of this Field from
290    * @return the value of the Field
291    * @throws IllegalAccessException if you could not normally access this field
292    *         (i.e. it is not public)
293    * @throws IllegalArgumentException if this is not a byte, short, char, int,
294    *         long, float, or double field of <code>o</code>, or if
295    *         <code>o</code> is not an instance of the declaring class of this
296    *         field
297    * @throws NullPointerException if <code>o</code> is null and this field
298    *         requires an instance
299    * @throws ExceptionInInitializerError if accessing a static field triggered
300    *         class initialization, which then failed
301    * @see #get(Object)
302    */
303   native double getDouble(Object o)
304     throws IllegalAccessException;
305
306   /**
307    * Set the value of this Field.  If it is a primitive field, the value
308    * will be unwrapped from the passed object (boolean = java.lang.Boolean).<p>
309    *
310    * If the field is static, <code>o</code> will be ignored. Otherwise, if
311    * <code>o</code> is null, you get a <code>NullPointerException</code>,
312    * and if it is incompatible with the declaring class of the field, you
313    * get an <code>IllegalArgumentException</code>.<p>
314    *
315    * Next, if this Field enforces access control, your runtime context is
316    * evaluated, and you may have an <code>IllegalAccessException</code> if
317    * you could not access this field in similar compiled code. This also
318    * occurs whether or not there is access control if the field is final.
319    * If the field is primitive, and unwrapping your argument fails, you will
320    * get an <code>IllegalArgumentException</code>; likewise, this error
321    * happens if <code>value</code> cannot be cast to the correct object type.
322    * If the field is static, and its class is uninitialized, you trigger class
323    * initialization, which may end in a
324    * <code>ExceptionInInitializerError</code>.<p>
325    *
326    * Finally, the field is set with the widened value. This method accesses
327    * the field of the declaring class, even if the instance passed in belongs
328    * to a subclass which declares another field to hide this one.
329    *
330    * @param o the object to set this Field on
331    * @param value the value to set this Field to
332    * @throws IllegalAccessException if you could not normally access this field
333    *         (i.e. it is not public)
334    * @throws IllegalArgumentException if <code>value</code> cannot be
335    *         converted by a widening conversion to the underlying type of
336    *         the Field, or if <code>o</code> is not an instance of the class
337    *         declaring this field
338    * @throws NullPointerException if <code>o</code> is null and this field
339    *         requires an instance
340    * @throws ExceptionInInitializerError if accessing a static field triggered
341    *         class initialization, which then failed
342    * @see #setBoolean(Object, boolean)
343    * @see #setByte(Object, byte)
344    * @see #setChar(Object, char)
345    * @see #setShort(Object, short)
346    * @see #setInt(Object, int)
347    * @see #setLong(Object, long)
348    * @see #setFloat(Object, float)
349    * @see #setDouble(Object, double)
350    */
351   native void set(Object o, Object value)
352     throws IllegalAccessException;
353
354   /**
355    * Set this boolean Field. If the field is static, <code>o</code> will be
356    * ignored.
357    *
358    * @param o the object to set this Field on
359    * @param value the value to set this Field to
360    * @throws IllegalAccessException if you could not normally access this field
361    *         (i.e. it is not public)
362    * @throws IllegalArgumentException if this is not a boolean field, or if
363    *         <code>o</code> is not an instance of the class declaring this
364    *         field
365    * @throws NullPointerException if <code>o</code> is null and this field
366    *         requires an instance
367    * @throws ExceptionInInitializerError if accessing a static field triggered
368    *         class initialization, which then failed
369    * @see #set(Object, Object)
370    */
371   native void setBoolean(Object o, boolean value)
372     throws IllegalAccessException;
373
374   /**
375    * Set this byte Field. If the field is static, <code>o</code> will be
376    * ignored.
377    *
378    * @param o the object to set this Field on
379    * @param value the value to set this Field to
380    * @throws IllegalAccessException if you could not normally access this field
381    *         (i.e. it is not public)
382    * @throws IllegalArgumentException if this is not a byte, short, int, long,
383    *         float, or double field, or if <code>o</code> is not an instance
384    *         of the class declaring this field
385    * @throws NullPointerException if <code>o</code> is null and this field
386    *         requires an instance
387    * @throws ExceptionInInitializerError if accessing a static field triggered
388    *         class initialization, which then failed
389    * @see #set(Object, Object)
390    */
391   native void setByte(Object o, byte value)
392     throws IllegalAccessException;
393
394   /**
395    * Set this char Field. If the field is static, <code>o</code> will be
396    * ignored.
397    *
398    * @param o the object to set this Field on
399    * @param value the value to set this Field to
400    * @throws IllegalAccessException if you could not normally access this field
401    *         (i.e. it is not public)
402    * @throws IllegalArgumentException if this is not a char, int, long,
403    *         float, or double field, or if <code>o</code> is not an instance
404    *         of the class declaring this field
405    * @throws NullPointerException if <code>o</code> is null and this field
406    *         requires an instance
407    * @throws ExceptionInInitializerError if accessing a static field triggered
408    *         class initialization, which then failed
409    * @see #set(Object, Object)
410    */
411   native void setChar(Object o, char value)
412     throws IllegalAccessException;
413
414   /**
415    * Set this short Field. If the field is static, <code>o</code> will be
416    * ignored.
417    *
418    * @param o the object to set this Field on
419    * @param value the value to set this Field to
420    * @throws IllegalAccessException if you could not normally access this field
421    *         (i.e. it is not public)
422    * @throws IllegalArgumentException if this is not a short, int, long,
423    *         float, or double field, or if <code>o</code> is not an instance
424    *         of the class declaring this field
425    * @throws NullPointerException if <code>o</code> is null and this field
426    *         requires an instance
427    * @throws ExceptionInInitializerError if accessing a static field triggered
428    *         class initialization, which then failed
429    * @see #set(Object, Object)
430    */
431   native void setShort(Object o, short value)
432     throws IllegalAccessException;
433
434   /**
435    * Set this int Field. If the field is static, <code>o</code> will be
436    * ignored.
437    *
438    * @param o the object to set this Field on
439    * @param value the value to set this Field to
440    * @throws IllegalAccessException if you could not normally access this field
441    *         (i.e. it is not public)
442    * @throws IllegalArgumentException if this is not an int, long, float, or
443    *         double field, or if <code>o</code> is not an instance of the
444    *         class declaring this field
445    * @throws NullPointerException if <code>o</code> is null and this field
446    *         requires an instance
447    * @throws ExceptionInInitializerError if accessing a static field triggered
448    *         class initialization, which then failed
449    * @see #set(Object, Object)
450    */
451   native void setInt(Object o, int value)
452     throws IllegalAccessException;
453
454   /**
455    * Set this long Field. If the field is static, <code>o</code> will be
456    * ignored.
457    *
458    * @param o the object to set this Field on
459    * @param value the value to set this Field to
460    * @throws IllegalAccessException if you could not normally access this field
461    *         (i.e. it is not public)
462    * @throws IllegalArgumentException if this is not a long, float, or double
463    *         field, or if <code>o</code> is not an instance of the class
464    *         declaring this field
465    * @throws NullPointerException if <code>o</code> is null and this field
466    *         requires an instance
467    * @throws ExceptionInInitializerError if accessing a static field triggered
468    *         class initialization, which then failed
469    * @see #set(Object, Object)
470    */
471   native void setLong(Object o, long value)
472     throws IllegalAccessException;
473
474   /**
475    * Set this float Field. If the field is static, <code>o</code> will be
476    * ignored.
477    *
478    * @param o the object to set this Field on
479    * @param value the value to set this Field to
480    * @throws IllegalAccessException if you could not normally access this field
481    *         (i.e. it is not public)
482    * @throws IllegalArgumentException if this is not a float or long field, or
483    *         if <code>o</code> is not an instance of the class declaring this
484    *         field
485    * @throws NullPointerException if <code>o</code> is null and this field
486    *         requires an instance
487    * @throws ExceptionInInitializerError if accessing a static field triggered
488    *         class initialization, which then failed
489    * @see #set(Object, Object)
490    */
491   native void setFloat(Object o, float value)
492     throws IllegalAccessException;
493
494   /**
495    * Set this double Field. If the field is static, <code>o</code> will be
496    * ignored.
497    *
498    * @param o the object to set this Field on
499    * @param value the value to set this Field to
500    * @throws IllegalAccessException if you could not normally access this field
501    *         (i.e. it is not public)
502    * @throws IllegalArgumentException if this is not a double field, or if
503    *         <code>o</code> is not an instance of the class declaring this
504    *         field
505    * @throws NullPointerException if <code>o</code> is null and this field
506    *         requires an instance
507    * @throws ExceptionInInitializerError if accessing a static field triggered
508    *         class initialization, which then failed
509    * @see #set(Object, Object)
510    */
511   native void setDouble(Object o, double value)
512     throws IllegalAccessException;
513
514   /**
515    * Return the String in the Signature attribute for this field. If there
516    * is no Signature attribute, return null.
517    *
518    */
519   native String getSignature();
520
521   /**
522    * Compare two objects to see if they are semantically equivalent.
523    * Two Fields are semantically equivalent if they have the same declaring
524    * class, name, and type. Since you can't create a Field except through
525    * the VM, this is just the == relation.
526    *
527    * @param o the object to compare to
528    * @return <code>true</code> if they are equal; <code>false</code> if not
529    */
530   public boolean equals(Object o)
531   {
532     if (!(o instanceof Field))
533       return false;
534     Field that = (Field)o; 
535     if (clazz != that.getDeclaringClass())
536       return false;
537     if (!name.equals(that.getName()))
538       return false;
539     if (getType() != that.getType())
540       return false;
541     return true;
542   }
543
544   /**
545    * Returns the element's annotation for the specified annotation type,
546    * or <code>null</code> if no such annotation exists.
547    *
548    * @param annotationClass the type of annotation to look for.
549    * @return this element's annotation for the specified type, or
550    *         <code>null</code> if no such annotation exists.
551    * @throws NullPointerException if the annotation class is <code>null</code>.
552    */
553 //   native Annotation getAnnotation(Class annotationClass);
554   Annotation getAnnotation(Class annotationClass){
555     if (annotationClass == null)
556       throw new NullPointerException();
557
558     return declaredAnnotations().get(annotationClass);
559   }
560
561   /**
562    * Returns all annotations directly defined by the element.  If there are
563    * no annotations directly associated with the element, then a zero-length
564    * array will be returned.  The returned array may be modified by the client
565    * code, but this will have no effect on the annotation content of this
566    * class, and hence no effect on the return value of this method for
567    * future callers.
568    *
569    * @return the annotations directly defined by the element.
570    * @since 1.5
571    */
572 //   native Annotation[] getDeclaredAnnotations();
573   Annotation[] getDeclaredAnnotations() {
574     return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
575   }
576
577   /**
578    * Parses the annotations if they aren't parsed yet and stores them into
579    * the declaredAnnotations map and return this map.
580    */
581   private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
582
583 }