* src/classes/gnu: Renamed to src/classes/gnuclasspath.
[cacao.git] / src / classes / gnuclasspath / java / lang / reflect / VMMethod.java
1 /* java.lang.reflect.VMMethod - VM interface for reflection of Java methods
2    Copyright (C) 1998, 2001, 2002, 2005, 2007, 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.Arrays;
44 import java.util.Map;
45
46 final class VMMethod
47 {
48   Class clazz;
49   String name;
50   int slot;
51
52   /**
53    * Unparsed annotations.
54    */
55   private byte[] annotations          = null;
56
57   /**
58    * Unparsed parameter annotations.
59    */
60   private byte[] parameterAnnotations = null;
61   
62   /**
63    * Unparsed annotation default value.
64    */
65   private byte[] annotationDefault    = null;
66
67   /**
68    * Annotations get parsed the first time they are
69    * accessed and are then cached it this map.
70    */
71   private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
72
73   /**
74    * Helper array for creating a new array from a java.util.Container.
75    */
76   private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
77     new Annotation[0];
78
79   /** 
80    * This field allows us to refer back to the main constructor instance.
81    *  It is set by the constructor of Field.
82    */
83   Method m;
84
85   public Class getDeclaringClass()
86   {
87     return clazz;
88   }
89
90   public String getName()
91   {
92     return name;
93   }
94
95   /**
96    * Return the raw modifiers for this method.
97    * @return the method's modifiers
98    */
99   native int getModifiersInternal();
100
101   /**
102    * Gets the return type of this method.
103    * @return the type of this method
104    */
105   native Class getReturnType();
106
107   /**
108    * Get the parameter list for this method, in declaration order. If the
109    * method takes no parameters, returns a 0-length array (not null).
110    *
111    * @return a list of the types of the method's parameters
112    */
113   native Class[] getParameterTypes();
114
115   /**
116    * Get the exception types this method says it throws, in no particular
117    * order. If the method has no throws clause, returns a 0-length array
118    * (not null).
119    *
120    * @return a list of the types in the method's throws clause
121    */
122   native Class[] getExceptionTypes();
123
124   native Object invoke(Object o, Object[] args)
125     throws IllegalAccessException, InvocationTargetException;
126
127   /**
128    * Return the String in the Signature attribute for this method. If there
129    * is no Signature attribute, return null.
130    */
131   native String getSignature();
132
133   /**
134    * If this method is an annotation method, returns the default
135    * value for the method.  If there is no default value, or if the
136    * method is not a member of an annotation type, returns null.
137    * Primitive types are wrapped.
138    *
139    * @throws TypeNotPresentException if the method returns a Class,
140    * and the class cannot be found
141    *
142    * @since 1.5
143    */
144   native Object getDefaultValue();
145
146   /**
147    * <p>
148    * Return an array of arrays representing the annotations on each
149    * of the method's parameters.  The outer array is aligned against
150    * the parameters of the method and is thus equal in length to
151    * the number of parameters (thus having a length zero if there are none).
152    * Each array element in the outer array contains an inner array which
153    * holds the annotations.  This array has a length of zero if the parameter
154    * has no annotations.
155    * </p>
156    * <p>
157    * The returned annotations are serialized.  Changing the annotations has
158    * no affect on the return value of future calls to this method.
159    * </p>
160    * 
161    * @return an array of arrays which represents the annotations used on the
162    *         parameters of this method.  The order of the array elements
163    *         matches the declaration order of the parameters.
164    * @since 1.5
165    */
166   native Annotation[][] getParameterAnnotations();
167
168   /**
169    * Compare two objects to see if they are semantically equivalent.
170    * Two Methods are semantically equivalent if they have the same declaring
171    * class, name, parameter list, and return type.
172    *
173    * @param o the object to compare to
174    * @return <code>true</code> if they are equal; <code>false</code> if not
175    */
176   public boolean equals(Object o)
177   {
178       // Implementation note:
179       // The following is a correct but possibly slow implementation.
180       //
181       // This class has a private field 'slot' that could be used by
182       // the VM implementation to "link" a particular method to a Class.
183       // In that case equals could be simply implemented as:
184       //
185       // if (o instanceof Method)
186       // {
187       //    Method m = (Method)o;
188       //    return m.declaringClass == this.declaringClass
189       //           && m.slot == this.slot;
190       // }
191       // return false;
192       //
193       // If a VM uses the Method class as their native/internal representation
194       // then just using the following would be optimal:
195       //
196       // return this == o;
197       //
198     if (!(o instanceof Method))
199       return false;
200     Method that = (Method)o;
201     if (clazz != that.getDeclaringClass())
202       return false;
203     if (!name.equals(that.getName()))
204       return false;
205     if (getReturnType() != that.getReturnType())
206       return false;
207     if (!Arrays.equals(getParameterTypes(), that.getParameterTypes()))
208       return false;
209     return true;
210   }
211
212   /**
213    * Returns the element's annotation for the specified annotation type,
214    * or <code>null</code> if no such annotation exists.
215    *
216    * @param annotationClass the type of annotation to look for.
217    * @return this element's annotation for the specified type, or
218    *         <code>null</code> if no such annotation exists.
219    * @throws NullPointerException if the annotation class is <code>null</code>.
220    */
221 //   native Annotation getAnnotation(Class annotationClass);
222   Annotation getAnnotation(Class annotationClass) {
223     if (annotationClass == null)
224       throw new NullPointerException();
225
226     return declaredAnnotations().get(annotationClass);
227   }
228
229   /**
230    * Returns all annotations directly defined by the element.  If there are
231    * no annotations directly associated with the element, then a zero-length
232    * array will be returned.  The returned array may be modified by the client
233    * code, but this will have no effect on the annotation content of this
234    * class, and hence no effect on the return value of this method for
235    * future callers.
236    *
237    * @return the annotations directly defined by the element.
238    * @since 1.5
239    */
240 //   native Annotation[] getDeclaredAnnotations();
241   Annotation[] getDeclaredAnnotations() {
242     return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
243   }
244
245   /**
246    * Parses the annotations if they aren't parsed yet and stores them into
247    * the declaredAnnotations map and return this map.
248    */
249   private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
250
251 }
252