Initial import
[jpf-core.git] / src / peers / gov / nasa / jpf / vm / JPF_java_lang_reflect_Constructor.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 gov.nasa.jpf.vm;
19
20 import java.lang.reflect.Modifier;
21
22 import gov.nasa.jpf.Config;
23 import gov.nasa.jpf.annotation.MJI;
24 import gov.nasa.jpf.util.MethodInfoRegistry;
25 import gov.nasa.jpf.util.RunListener;
26 import gov.nasa.jpf.util.RunRegistry;
27
28 /**
29  * native peer for rudimentary constructor reflection.
30  * 
31  * Unfortunately, this is quite redundant to the Method peer, but Constructor
32  * is not a Method subclass, and hence we can't rely on it's initialization
33  */
34 public class JPF_java_lang_reflect_Constructor extends NativePeer {
35   
36   static MethodInfoRegistry registry;
37   
38   public static boolean init (Config conf) {
39     // this is an example of how to handle cross-initialization between
40     // native peers - this might also get explicitly called by the java.lang.Class
41     // peer, since it creates Constructor objects. Here we have to make sure
42     // we only reset between JPF runs
43     
44     if (registry == null){
45       registry = new MethodInfoRegistry();
46       
47       RunRegistry.getDefaultRegistry().addListener( new RunListener() {
48         @Override
49                 public void reset (RunRegistry reg){
50           registry = null;
51         }
52       });
53     }
54     return true;
55   }
56
57   static int createConstructorObject (MJIEnv env, ClassInfo ciCtor, MethodInfo mi){
58     // note - it is the callers responsibility to ensure Constructor is properly initialized    
59     
60     int regIdx = registry.registerMethodInfo(mi);
61     int eidx = env.newObject(ciCtor);
62     ElementInfo ei = env.getModifiableElementInfo(eidx);
63     
64     ei.setIntField("regIdx", regIdx);
65     return eidx;
66   }
67
68   static MethodInfo getMethodInfo (MJIEnv env, int objRef){
69     return registry.getMethodInfo(env,objRef, "regIdx");
70   }
71   
72   @MJI
73   public int getName____Ljava_lang_String_2 (MJIEnv env, int objRef) {
74     MethodInfo mi = getMethodInfo(env, objRef);
75     
76     int nameRef = env.getReferenceField( objRef, "name");
77     if (nameRef == MJIEnv.NULL) {
78       nameRef = env.newString(mi.getName());
79       env.setReferenceField(objRef, "name", nameRef);
80     }
81    
82     return nameRef;
83   }
84   
85   // <2do> .. and some more delegations to JPF_java_lang_Method
86
87   @MJI
88   public int newInstance___3Ljava_lang_Object_2__Ljava_lang_Object_2 (MJIEnv env, int mthRef, int argsRef) {
89     ThreadInfo ti = env.getThreadInfo();
90     DirectCallStackFrame frame = ti.getReturnedDirectCall();
91     MethodInfo miCallee = getMethodInfo(env,mthRef);
92
93     if (frame == null) { // first time
94       ClassInfo ci = miCallee.getClassInfo();
95
96        if (ci.isAbstract()){
97         env.throwException("java.lang.InstantiationException");
98         return MJIEnv.NULL;
99       }
100
101       int objRef = env.newObjectOfUncheckedClass( ci);
102       frame = miCallee.createDirectCallStackFrame( ti, 1);
103       frame.setReflection();
104       
105       frame.setLocalReferenceVariable(0, objRef);  // (1) store the objRef for retrieval during re-exec
106       
107       int argOffset = frame.setReferenceArgument(0, objRef, null);
108       if (!JPF_java_lang_reflect_Method.pushUnboxedArguments( env, miCallee, frame, argOffset, argsRef)) {
109         // we've got a IllegalArgumentException
110         return MJIEnv.NULL;
111       }
112       ti.pushFrame(frame);
113        
114       ci.initializeClass(ti);
115       
116       env.repeatInvocation();
117       return MJIEnv.NULL;
118       
119     } else { // reflection call returned
120       int objRef = frame.getLocalVariable(0); // that's the object ref we stored in (1)
121       return objRef;
122     }
123   }
124     
125   @MJI
126   public int getParameterTypes_____3Ljava_lang_Class_2 (MJIEnv env, int objRef){
127     // kind of dangerous, but we don't refer to any fields and the underlying JPF construct
128     // (MethodInfo) is the same, so we just delegate to avoid copying non-trivial code
129     return JPF_java_lang_reflect_Method.getParameterTypes (env, getMethodInfo(env,objRef));
130   }
131
132   @MJI
133   public int getAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int objRef){
134     // <2do> check if ctor annotations are inherited, which is a bit off
135     return JPF_java_lang_reflect_Method.getAnnotations( env, getMethodInfo(env,objRef));
136   }
137   
138   @MJI
139   public int getDeclaredAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int objRef){
140     return JPF_java_lang_reflect_Method.getDeclaredAnnotations( env, getMethodInfo(env,objRef));
141   }
142   
143   @MJI
144   public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int objRef, int annotationClsRef) {
145     return JPF_java_lang_reflect_Method.getAnnotation( env, getMethodInfo(env,objRef), annotationClsRef);
146   }
147   
148   @MJI
149   public int getParameterAnnotations_____3_3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int objRef){
150     return JPF_java_lang_reflect_Method.getParameterAnnotations( env, getMethodInfo(env,objRef));
151   }
152
153   @MJI
154   public int getModifiers____I (MJIEnv env, int objRef){
155     MethodInfo mi = getMethodInfo(env, objRef);
156     return mi.getModifiers();
157   }
158
159   @MJI
160   public int getDeclaringClass____Ljava_lang_Class_2 (MJIEnv env, int objRef){
161     MethodInfo mi = getMethodInfo(env, objRef);    
162     ClassInfo ci = mi.getClassInfo();
163     // can't get a Constructor object w/o having initialized it's declaring class first
164     return ci.getClassObjectRef();
165   }
166   
167   @MJI
168   public int toString____Ljava_lang_String_2 (MJIEnv env, int objRef){
169     StringBuilder sb = new StringBuilder();
170     
171     MethodInfo mi = getMethodInfo(env, objRef);
172
173     sb.append(Modifier.toString(mi.getModifiers()));
174     sb.append(' ');
175
176     sb.append(mi.getClassInfo().getName());
177     sb.append('(');
178     
179     String[] at = mi.getArgumentTypeNames();
180     for (int i=0; i<at.length; i++){
181       if (i>0) sb.append(',');
182       sb.append(at[i]);
183     }
184     
185     sb.append(')');
186     
187     int sref = env.newString(sb.toString());
188     return sref;
189   }
190
191   @MJI
192   public boolean equals__Ljava_lang_Object_2__Z (MJIEnv env, int objRef, int mthRef){
193     ElementInfo ei = env.getElementInfo(mthRef);
194     ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo(JPF_java_lang_Class.CONSTRUCTOR_CLASSNAME);
195
196     if (ei.getClassInfo() == ci){
197       MethodInfo mi1 = getMethodInfo(env, objRef);
198       MethodInfo mi2 = getMethodInfo(env, mthRef);
199       if (mi1.getClassInfo() == mi2.getClassInfo()){
200         if (mi1.getName().equals(mi2.getName())){
201           if (mi1.getReturnType().equals(mi2.getReturnType())){
202             byte[] params1 = mi1.getArgumentTypes();
203             byte[] params2 = mi2.getArgumentTypes();
204             if (params1.length == params2.length){
205               for (int i = 0; i < params1.length; i++){
206                 if (params1[i] != params2[i])
207                   return false;
208               }
209               return true;
210             }
211           }
212         }
213       }
214     }
215     return false;
216   }
217
218   @MJI
219   public int hashCode____I (MJIEnv env, int objRef){
220     MethodInfo ctor = getMethodInfo(env, objRef);
221     return ctor.getClassName().hashCode();
222   }
223 }