Adding recursive call to the getResolvedClassInfo() method: look into the parent...
[jpf-core.git] / src / classes / java / lang / Class.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package java.lang;
19
20 import java.io.ByteArrayInputStream;
21 import java.io.InputStream;
22 import java.io.Serializable;
23 import java.lang.annotation.Annotation;
24 import java.lang.reflect.*;
25 import java.net.URL;
26 import java.util.HashMap;
27 import java.util.Map;
28
29 import sun.reflect.ConstantPool;
30 import sun.reflect.annotation.AnnotationType;
31
32 /**
33  * MJI model class for java.lang.Class library abstraction
34  *
35  * This is a JPF specific version of a system class because we can't use the real,
36  * platform VM specific version (it's native all over the place, its field
37  * structure isn't documented, most of its methods are private, hence we can't
38  * even instantiate it properly).
39  *
40  * Note that this class never gets seen by the real VM - it's for JPF's eyes only.
41  *
42  * For now, it's only a fragment to test the mechanism, and provide basic
43  * class.getName() / Class.ForName() support (which is (almost) enough for
44  * Java assertion support
45  */
46 @SuppressWarnings("unused")  // native peer uses
47 public final class Class<T> implements Serializable, GenericDeclaration, Type, AnnotatedElement {
48
49   /** don't use serialVersionUID from JDK 1.1 for interoperability */
50   private static final long serialVersionUID = 3206093459760846163L + 1;
51
52    // we init this on demand (from MJIEnv) since it's not used too often
53   private static Annotation[] emptyAnnotations; // = new Annotation[0];
54   
55   private String name;
56
57   private ClassLoader classLoader;
58   
59   /**
60    * search global id of the corresponding ClassInfo, which factors in the classloader
61    */
62   private int nativeId;
63
64   /**
65    * to be set during <clinit> of the corresponding class
66    */
67   private boolean isPrimitive;
68   
69   private Class() {}
70
71   public native boolean isArray ();
72
73   @Override
74   public native Annotation[] getAnnotations();
75
76   @Override
77   public native <A extends Annotation> A getAnnotation( Class<A> annotationCls);
78
79   // those are from Java 6
80   public native boolean isAnnotation ();
81   @Override
82   public native boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
83
84   public native Class<?> getComponentType ();
85
86   public native Field[] getFields() throws SecurityException;
87   
88   public native Field getDeclaredField (String fieldName) throws NoSuchFieldException,
89                                                           SecurityException;
90
91   public native Field[] getDeclaredFields () throws SecurityException;
92
93   public native Method getDeclaredMethod (String mthName, Class<?>... paramTypes)
94                             throws NoSuchMethodException, SecurityException;
95
96   public native Method getMethod (String mthName, Class<?>... paramTypes)
97                     throws NoSuchMethodException, SecurityException;
98
99   public native Method[] getDeclaredMethods () throws SecurityException;
100
101   public native Method[] getMethods () throws SecurityException;
102     
103   public native Constructor<?>[] getDeclaredConstructors() throws SecurityException;
104
105   public native Constructor<?>[] getConstructors() throws SecurityException;
106
107   private native byte[] getByteArrayFromResourceStream(String name);
108
109   public InputStream getResourceAsStream (String name) {
110     byte[] byteArray = getByteArrayFromResourceStream(name);
111     if (byteArray == null) return null;
112     return new ByteArrayInputStream(byteArray);
113   }
114
115   private native String getResolvedName (String rname);
116
117   public URL getResource (String rname) {
118     String resolvedName = getResolvedName(rname);
119     return getClassLoader().getResource(resolvedName);
120   }
121
122   public Package getPackage() {
123     // very very crude version for now, only supports the package name
124     String pkgName = null;
125
126     int idx = name.lastIndexOf('.');
127     if (idx >=0){
128       pkgName = name.substring(0,idx);
129
130       Package pkg = new Package(pkgName,
131                                 "spectitle", "specversion", "specvendor",
132                                 "impltitle", "implversion", "implvendor",
133                                  null, getClassLoader());
134         return pkg;
135
136     } else { // weird, but there is no Package object for the default package
137       return null;
138     }
139
140   }
141
142   //--- enum support ()
143   // Java 1.5
144   public native T[] getEnumConstants();
145
146   // Java 6
147   T[] getEnumConstantsShared() {
148     return getEnumConstants();
149   }
150   
151   // lazy initialized map for field name -> Enum constants
152   // <2do> we should move this to the native side, since Enum constants don't change
153   private transient Map<String, T> enumConstantDirectory = null;
154
155   // package private helper for Enum.valueOf()
156   Map<String,T> enumConstantDirectory() {
157     if (enumConstantDirectory == null) {
158       Map<String,T> map = new HashMap<String,T>();
159
160       T[] ae = getEnumConstants();
161       for (T e: ae) {
162         map.put(((Enum)e).name(), e);
163       }
164
165       enumConstantDirectory = map;
166     }
167     return enumConstantDirectory;
168   }
169
170
171   public native Constructor<T> getDeclaredConstructor (Class<?>... paramTypes)
172               throws NoSuchMethodException, SecurityException;
173
174   public native Field getField (String fieldName) throws NoSuchFieldException,
175                                                   SecurityException;
176
177   public native boolean isInstance (Object o);
178
179   public native boolean isAssignableFrom (Class<?> clazz);
180
181   public native boolean isInterface();
182
183   public native Constructor<T> getConstructor (Class<?>... argTypes) throws NoSuchMethodException, SecurityException;
184
185   public native int getModifiers();
186
187   public native Class<?>[] getInterfaces();
188
189   // no use to have a ctor, we can't call it
190   public String getName () {
191     return name;
192   }
193
194   public String getSimpleName () {
195     int idx; // <2do> not really - inner classes?
196     Class<?> enclosingClass = getEnclosingClass();
197     
198     if(enclosingClass!=null){
199       idx = enclosingClass.getName().length();
200     } else{
201       idx = name.lastIndexOf('.');
202     }
203     
204     return name.substring(idx+1);
205   }
206
207   static native Class<?> getPrimitiveClass (String clsName);
208
209    /**
210     * this one is in JPF reflection land, it's 'native' for us
211     */
212   public static native Class<?> forName (String clsName) throws ClassNotFoundException;
213
214   public static Class<?> forName (String clsName, boolean initialize, ClassLoader loader) throws ClassNotFoundException {
215     Class<?> cls;
216     if (loader == null){
217       cls = forName(clsName);
218     } else {
219       cls = loader.loadClass(clsName);
220     }
221     
222     if (initialize) {
223       cls.initialize0();
224     }
225     return cls;
226   }
227
228   /**
229    * forces clinit without explicit field or method access
230    */
231   private native void initialize0 ();
232   
233   public boolean isPrimitive () {
234     return isPrimitive;
235   }
236
237   public native Class<? super T> getSuperclass ();
238
239   public native T newInstance () throws InstantiationException,
240                                       IllegalAccessException;
241
242   @Override
243   public String toString () {
244     return (isInterface() ? "interface " : "class ") + name;
245   }
246
247   @SuppressWarnings("unchecked")
248   public T cast(Object o) {
249     if (o != null && !isInstance(o)) throw new ClassCastException();
250     return (T) o;
251   }
252   
253   @SuppressWarnings("unchecked")
254   public <U> Class<? extends U> asSubclass(Class<U> clazz) {
255     if (clazz.isAssignableFrom(this)) {
256       return (Class<? extends U>) this;
257     } else {
258       throw new ClassCastException("" + this + " is not a " + clazz);
259     }
260   }
261
262   native public boolean desiredAssertionStatus ();
263
264   public ClassLoader getClassLoader() {
265     return classLoader;
266   }
267
268   native ConstantPool getConstantPool();
269
270   native void setAnnotationType (AnnotationType at);
271
272   native AnnotationType getAnnotationType();
273   
274   // TODO: Fix for Groovy's model-checking
275   public native TypeVariable<Class<T>>[] getTypeParameters();
276
277   public native Type getGenericSuperclass();
278   /*public Type getGenericSuperclass() {
279     throw new UnsupportedOperationException();
280   }*/
281
282   public native Type[] getGenericInterfaces();
283   /*public Type[] getGenericInterfaces() {
284     throw new UnsupportedOperationException();
285   }*/
286
287   public Object[] getSigners() {
288     throw new UnsupportedOperationException();
289   }
290
291   void setSigners(Object[] signers) {
292     signers = null;  // Get rid of IDE warning 
293     throw new UnsupportedOperationException();
294   }
295   
296   public Method getEnclosingMethod() {
297     throw new UnsupportedOperationException();
298   }
299
300   public Constructor<?> getEnclosingConstructor() {
301     throw new UnsupportedOperationException();
302   }
303
304   public Class<?> getDeclaringClass() {
305     throw new UnsupportedOperationException();
306   }
307
308   public native Class<?> getEnclosingClass();
309   
310   public String getCanonicalName() {
311     throw new UnsupportedOperationException();
312   }
313
314   public boolean isAnonymousClass() {
315     throw new UnsupportedOperationException();
316   }
317
318   public boolean isLocalClass() {
319     throw new UnsupportedOperationException();
320   }
321
322   public boolean isMemberClass() {
323     throw new UnsupportedOperationException();
324   }
325
326   public Class<?>[] getClasses() {
327     throw new UnsupportedOperationException();
328   }
329   
330   public Class<?>[] getDeclaredClasses() throws SecurityException {
331     throw new UnsupportedOperationException();
332   }
333
334   // TODO: Fix for Groovy's model-checking
335   public native java.security.ProtectionDomain getProtectionDomain();
336   /*public java.security.ProtectionDomain getProtectionDomain() {
337     throw new UnsupportedOperationException();
338   }*/
339
340   void setProtectionDomain0(java.security.ProtectionDomain pd) {
341     pd = null;  // Get rid of IDE warning 
342     throw new UnsupportedOperationException();
343   }
344
345   public boolean isEnum() {
346     throw new UnsupportedOperationException();
347   }
348   
349   @Override
350   public Annotation[] getDeclaredAnnotations() {
351     throw new UnsupportedOperationException();
352   }
353
354   // TODO: Fix for Groovy's model-checking
355   transient ClassValue.ClassValueMap classValueMap;
356
357   public boolean isSynthetic (){
358     final int SYNTHETIC = 0x00001000;
359     return (getModifiers() & SYNTHETIC) != 0;
360   }
361 }