Fix get/setShort for field and array reflection
[jpf-core.git] / src / peers / gov / nasa / jpf / vm / JPF_java_lang_reflect_Array.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 gov.nasa.jpf.annotation.MJI;
21 import gov.nasa.jpf.vm.ClassInfo;
22 import gov.nasa.jpf.vm.MJIEnv;
23 import gov.nasa.jpf.vm.NativePeer;
24 import gov.nasa.jpf.vm.Types;
25
26 /**
27  * MJI NativePeer class for java.lang.reflect.Array library abstraction
28  */
29 public class JPF_java_lang_reflect_Array extends NativePeer {
30   @MJI
31   public int getLength__Ljava_lang_Object_2__I (MJIEnv env, int clsObjRef, 
32                                                     int objRef) {
33     if (objRef == MJIEnv.NULL) {
34       env.throwException("java.lang.NullPointerException", "array argument is null");
35       return 0;
36     }
37     if (!env.isArray(objRef)) {
38       env.throwException("java.lang.IllegalArgumentException", "argument is not an array");
39       return 0;
40     }
41
42     return env.getArrayLength(objRef);
43   }
44   
45   @MJI
46   public int newArray__Ljava_lang_Class_2I__Ljava_lang_Object_2 (MJIEnv env, int clsRef,
47                                                                         int componentTypeRef, int length) {
48     ClassInfo ci = env.getReferredClassInfo(componentTypeRef);
49     String clsName = ci.getName();
50     
51     return createNewArray( env, clsName, length);
52   }
53   
54   static int createNewArray (MJIEnv env, String clsName, int length) {
55     int aRef = MJIEnv.NULL;
56     
57     if ("boolean".equals(clsName)) { aRef = env.newBooleanArray(length); }
58     else if ("byte".equals(clsName)) { aRef = env.newByteArray(length); }
59     else if ("char".equals(clsName)) { aRef = env.newCharArray(length); }
60     else if ("short".equals(clsName)) { aRef = env.newShortArray(length); }
61     else if ("int".equals(clsName)) { aRef = env.newIntArray(length); }
62     else if ("long".equals(clsName)) { aRef = env.newLongArray(length); }
63     else if ("float".equals(clsName)) { aRef = env.newFloatArray(length); }
64     else if ("double".equals(clsName)) { aRef = env.newDoubleArray(length); }
65     else { aRef = env.newObjectArray(clsName, length); }
66     return aRef;    
67   }
68   
69   @MJI
70   public int multiNewArray__Ljava_lang_Class_2_3I__Ljava_lang_Object_2 (MJIEnv env, int clsRef,
71                                                                                int componentTypeRef,
72                                                                                int dimArrayRef) {
73     ClassInfo ci = env.getReferredClassInfo(componentTypeRef);
74     String clsName = ci.getName();
75     int n = env.getArrayLength(dimArrayRef);
76     int i;
77
78     clsName = Types.getTypeSignature(clsName, true);
79     
80     String arrayType = "[";
81     for (i=2; i<n; i++) arrayType += '[';
82     arrayType += clsName;
83     
84     int[] dim = new int[n];
85     for (i=0; i<n; i++) {
86       dim[i] = env.getIntArrayElement(dimArrayRef, i);
87     }
88     
89     int aRef = createNewMultiArray(env, arrayType, dim, 0); 
90     return aRef;
91   }
92   
93   static int createNewMultiArray (MJIEnv env, String arrayType, int[] dim, int level) {
94     int aRef = MJIEnv.NULL;
95     int len = dim[level];
96     
97     if (level < dim.length-1) {
98       aRef = env.newObjectArray(arrayType, len);
99     
100       for (int i=0; i<len; i++) {
101         int eRef = createNewMultiArray(env, arrayType.substring(1), dim, level+1);
102         env.setReferenceArrayElement(aRef, i, eRef);
103       }
104     } else {
105       aRef = createNewArray( env, arrayType, len);
106     }
107     
108     return aRef;
109   }
110
111   @MJI
112   public int get__Ljava_lang_Object_2I__Ljava_lang_Object_2 (MJIEnv env, int clsRef,
113                                                                     int aref, int index){
114     String at = Types.getTypeName(env.getArrayType(aref));
115     if (at.equals("int")){
116       int vref = env.newObject("java.lang.Integer");
117       env.setIntField(vref, "value", env.getIntArrayElement(aref,index));
118       return vref;
119       
120     } else if (at.equals("long")){
121       int vref = env.newObject("java.lang.Long");
122       env.setLongField(vref, "value", env.getLongArrayElement(aref,index));
123       return vref;
124       
125     } else if (at.equals("double")){
126       int vref = env.newObject("java.lang.Double");
127       env.setDoubleField(vref, "value", env.getDoubleArrayElement(aref,index));
128       return vref;
129       
130     } else if (at.equals("boolean")){
131       int vref = env.newObject("java.lang.Boolean");
132       env.setBooleanField(vref, "value", env.getBooleanArrayElement(aref,index));
133       return vref;
134       
135     } else if (at.equals("char")){
136       int vref = env.newObject("java.lang.Character");
137       env.setCharField(vref, "value", env.getCharArrayElement(aref,index));
138       return vref;
139       
140     } else if (at.equals("byte")){
141       int vref = env.newObject("java.lang.Byte");
142       env.setByteField(vref, "value", env.getByteArrayElement(aref,index));
143       return vref;
144       
145     } else if (at.equals("short")){
146       int vref = env.newObject("java.lang.Short");
147       env.setShortField(vref, "value", env.getShortArrayElement(aref,index));
148       return vref;
149
150     } else if (at.equals("float")){
151       int vref = env.newObject("java.lang.Float");
152       env.setFloatField(vref, "value", env.getFloatArrayElement(aref,index));
153       return vref;
154
155     } else {
156       return env.getReferenceArrayElement(aref, index);
157     }
158   }
159
160   private static boolean check (MJIEnv env, int aref, int index) {
161     if (aref == MJIEnv.NULL) {
162       env.throwException("java.lang.NullPointerException", "array argument is null");
163       return false;
164     }
165     if (!env.isArray(aref)) {
166       env.throwException("java.lang.IllegalArgumentException", "argument is not an array");
167       return false;
168     }
169     if (index < 0 || index >= env.getArrayLength(aref)) {
170       env.throwException("java.lang.IndexOutOfBoundsException", "index " + index + " is out of bounds");
171       return false;
172     }
173     return true;
174   }
175
176   @MJI
177   public boolean getBoolean__Ljava_lang_Object_2I__Z (MJIEnv env, int clsRef, int aref, int index) {
178     if (check(env, aref, index)) {
179       return env.getBooleanArrayElement(aref, index);
180     }
181     return false;
182   }
183
184   @MJI
185   public static byte getByte__Ljava_lang_Object_2I__B (MJIEnv env, int clsRef, int aref, int index) {
186     if (check(env, aref, index)) {
187       return env.getByteArrayElement(aref, index);
188     }
189     return 0;
190   }
191
192   @MJI
193   public char getChar__Ljava_lang_Object_2I__C (MJIEnv env, int clsRef, int aref, int index) {
194     if (check(env, aref, index)) {
195       return env.getCharArrayElement(aref, index);
196     }
197     return 0;
198   }
199
200   @MJI
201   public short getShort__Ljava_lang_Object_2I__S (MJIEnv env, int clsRef, int aref, int index) {
202     if (check(env, aref, index)) {
203       return env.getShortArrayElement(aref, index);
204     }
205     return 0;
206   }
207
208   @MJI
209   public int getInt__Ljava_lang_Object_2I__I (MJIEnv env, int clsRef, int aref, int index) {
210     if (check(env, aref, index)) {
211       return env.getIntArrayElement(aref, index);
212     }
213     return 0;
214   }
215
216   @MJI
217   public long getLong__Ljava_lang_Object_2I__J (MJIEnv env, int clsRef, int aref, int index) {
218     if (check(env, aref, index)) {
219       return env.getLongArrayElement(aref, index);
220     }
221     return 0;
222   }
223
224   @MJI
225   public float getFloat__Ljava_lang_Object_2I__F (MJIEnv env, int clsRef, int aref, int index) {
226     if (check(env, aref, index)) {
227       return env.getFloatArrayElement(aref, index);
228     }
229     return 0;
230   }
231
232   @MJI
233   public double getDouble__Ljava_lang_Object_2I__D (MJIEnv env, int clsRef, int aref, int index) {
234     if (check(env, aref, index)) {
235       return env.getDoubleArrayElement(aref, index);
236     }
237     return 0;
238   }
239
240   @MJI
241   public void setBoolean__Ljava_lang_Object_2IZ__V (MJIEnv env, int clsRef, int aref, int index, boolean val) {
242     if (check(env, aref, index)) {
243       env.setBooleanArrayElement(aref, index, val);
244     }
245   }
246
247   @MJI
248   public void setByte__Ljava_lang_Object_2IB__V (MJIEnv env, int clsRef, int aref, int index, byte val) {
249     if (check(env, aref, index)) {
250       env.setByteArrayElement(aref, index, val);
251     }
252   }
253
254   @MJI
255   public void setChar__Ljava_lang_Object_2IC__V (MJIEnv env, int clsRef, int aref, int index, char val) {
256     if (check(env, aref, index)) {
257       env.setCharArrayElement(aref, index, val);
258     }
259   }
260
261   @MJI
262   public void setShort__Ljava_lang_Object_2IS__V (MJIEnv env, int clsRef, int aref, int index, short val) {
263     if (check(env, aref, index)) {
264       env.setShortArrayElement(aref, index, val);
265     }
266   }
267
268   @MJI
269   public void setInt__Ljava_lang_Object_2II__V (MJIEnv env, int clsRef, int aref, int index, int val) {
270     if (check(env, aref, index)) {
271       env.setIntArrayElement(aref, index, val);
272     }
273   }
274
275   @MJI
276   public void setLong__Ljava_lang_Object_2IJ__V (MJIEnv env, int clsRef, int aref, int index, long val) {
277     if (check(env, aref, index)) {
278       env.setLongArrayElement(aref, index, val);
279     }
280   }
281
282   @MJI
283   public void setFloat__Ljava_lang_Object_2IF__V (MJIEnv env, int clsRef, int aref, int index, float val) {
284     if (check(env, aref, index)) {
285       env.setFloatArrayElement(aref, index, val);
286     }
287   }
288
289   @MJI
290   public void setDouble__Ljava_lang_Object_2ID__V (MJIEnv env, int clsRef, int aref, int index, double val) {
291     if (check(env, aref, index)) {
292       env.setDoubleArrayElement(aref, index, val);
293     }
294   }
295 }