2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
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
10 * http://www.apache.org/licenses/LICENSE-2.0.
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.
19 package gov.nasa.jpf.util;
21 import gov.nasa.jpf.JPFException;
22 import gov.nasa.jpf.vm.ClassInfo;
23 import gov.nasa.jpf.vm.ClinitRequired;
24 import gov.nasa.jpf.vm.ElementInfo;
25 import gov.nasa.jpf.vm.FieldInfo;
26 import gov.nasa.jpf.vm.Fields;
27 import gov.nasa.jpf.vm.MJIEnv;
29 import java.lang.reflect.Array;
30 import java.lang.reflect.Field;
33 * Object transformer from Java objects to JPF objects
34 * @author Ivan Mushketik
36 public class ObjectConverter {
38 * Create JPF object from Java object
39 * @param env - MJI environment
40 * @param javaObject - java object that is used to created JPF object from
41 * @return reference to new JPF object
43 public static int JPFObjectFromJavaObject(MJIEnv env, Object javaObject) throws ClinitRequired {
44 Class<?> javaClass = javaObject.getClass();
45 String typeName = javaClass.getName();
46 int newObjRef = env.newObject(typeName);
47 ElementInfo newObjEI = env.getModifiableElementInfo(newObjRef);
49 ClassInfo ci = env.getClassInfo(newObjRef);
52 for (FieldInfo fi : ci.getDeclaredInstanceFields()) {
53 if (!fi.isReference()) {
54 setJPFPrimitive(newObjEI, fi, javaObject);
58 Field arrField = getField(fi.getName(), javaClass);
59 arrField.setAccessible(true);
60 Object fieldJavaObj = arrField.get(javaObject);
63 if (isArrayField(fi)) {
64 fieldJPFObjRef = getJPFArrayRef(env, fieldJavaObj);
66 fieldJPFObjRef = JPFObjectFromJavaObject(env, fieldJavaObj);
69 newObjEI.setReferenceField(fi, fieldJPFObjRef);
71 } catch (NoSuchFieldException nsfx){
72 throw new JPFException("JPF object creation failed, no such field: " + fi.getFullName(), nsfx);
73 } catch (IllegalAccessException iax){
74 throw new JPFException("JPF object creation failed, illegal access: " + fi.getFullName(), iax);
79 ci = ci.getSuperClass();
85 private Object createObject(String className) {
89 private static void setJPFPrimitive(ElementInfo newObjEI, FieldInfo fi, Object javaObject) {
92 String jpfTypeName = fi.getType();
93 Class javaClass = javaObject.getClass();
94 Field javaField = getField(fi.getName(), javaClass);
95 javaField.setAccessible(true);
97 if (jpfTypeName.equals("char")) {
98 newObjEI.setCharField(fi, javaField.getChar(javaObject));
100 else if (jpfTypeName.equals("byte")) {
101 newObjEI.setByteField(fi, javaField.getByte(javaObject));
103 else if (jpfTypeName.equals("short")) {
104 newObjEI.setShortField(fi, javaField.getShort(javaObject));
106 else if (jpfTypeName.equals("int")) {
107 newObjEI.setIntField(fi, javaField.getInt(javaObject));
109 else if (jpfTypeName.equals("long")) {
110 newObjEI.setLongField(fi, javaField.getLong(javaObject));
112 else if (jpfTypeName.equals("float")) {
113 newObjEI.setFloatField(fi, javaField.getFloat(javaObject));
115 else if (jpfTypeName.equals("double")) {
116 newObjEI.setDoubleField(fi, javaField.getDouble(javaObject));
119 catch (Exception ex) {
120 throw new JPFException(ex);
124 private static Field getField(String fieldName, Class javaClass) throws NoSuchFieldException {
127 Field field = javaClass.getDeclaredField(fieldName);
129 } catch (NoSuchFieldException ex) {
130 // Try to search this field in a super class
131 javaClass = javaClass.getSuperclass();
133 // No more super class. Wrong field
134 if (javaClass == null) {
142 private static int getJPFArrayRef(MJIEnv env, Object javaArr) throws NoSuchFieldException, IllegalAccessException {
144 Class arrayElementClass = javaArr.getClass().getComponentType();
146 int javaArrLength = Array.getLength(javaArr);
149 if (arrayElementClass == Character.TYPE) {
150 arrRef = env.newCharArray(javaArrLength);
151 ElementInfo charArrRef = env.getModifiableElementInfo(arrRef);
152 char[] charArr = charArrRef.asCharArray();
154 for (int i = 0; i < javaArrLength; i++) {
155 charArr[i] = Array.getChar(javaArr, i);
158 else if (arrayElementClass == Byte.TYPE) {
159 arrRef = env.newByteArray(javaArrLength);
160 ElementInfo byteArrRef = env.getModifiableElementInfo(arrRef);
161 byte[] byteArr = byteArrRef.asByteArray();
163 for (int i = 0; i < javaArrLength; i++) {
164 byteArr[i] = Array.getByte(javaArr, i);
167 else if (arrayElementClass == Short.TYPE) {
168 arrRef = env.newShortArray(javaArrLength);
169 ElementInfo shortArrRef = env.getModifiableElementInfo(arrRef);
170 short[] shortArr = shortArrRef.asShortArray();
172 for (int i = 0; i < javaArrLength; i++) {
173 shortArr[i] = Array.getShort(javaArr, i);
176 else if (arrayElementClass == Integer.TYPE) {
177 arrRef = env.newIntArray(javaArrLength);
178 ElementInfo intArrRef = env.getModifiableElementInfo(arrRef);
179 int[] intArr = intArrRef.asIntArray();
181 for (int i = 0; i < javaArrLength; i++) {
182 intArr[i] = Array.getInt(javaArr, i);
185 else if (arrayElementClass == Long.TYPE) {
186 arrRef = env.newLongArray(javaArrLength);
187 ElementInfo longArrRef = env.getModifiableElementInfo(arrRef);
188 long[] longArr = longArrRef.asLongArray();
190 for (int i = 0; i < javaArrLength; i++) {
191 longArr[i] = Array.getLong(javaArr, i);
194 else if (arrayElementClass == Float.TYPE) {
195 arrRef = env.newFloatArray(javaArrLength);
196 ElementInfo floatArrRef = env.getModifiableElementInfo(arrRef);
197 float[] floatArr = floatArrRef.asFloatArray();
199 for (int i = 0; i < javaArrLength; i++) {
200 floatArr[i] = Array.getFloat(javaArr, i);
203 else if (arrayElementClass == Double.TYPE) {
204 arrRef = env.newDoubleArray(javaArrLength);
205 ElementInfo floatArrRef = env.getModifiableElementInfo(arrRef);
206 double[] doubleArr = floatArrRef.asDoubleArray();
208 for (int i = 0; i < javaArrLength; i++) {
209 doubleArr[i] = Array.getDouble(javaArr, i);
213 arrRef = env.newObjectArray(arrayElementClass.getCanonicalName(), javaArrLength);
214 ElementInfo arrayEI = env.getModifiableElementInfo(arrRef);
216 Fields fields = arrayEI.getFields();
218 for (int i = 0; i < javaArrLength; i++) {
220 Object javaArrEl = Array.get(javaArr, i);
222 if (javaArrEl != null) {
223 if (javaArrEl.getClass().isArray()) {
224 newArrElRef = getJPFArrayRef(env, javaArrEl);
227 newArrElRef = JPFObjectFromJavaObject(env, javaArrEl);
231 newArrElRef = MJIEnv.NULL;
234 fields.setReferenceValue(i, newArrElRef);
242 public static Object javaObjectFromJPFObject(ElementInfo ei) {
244 String typeName = ei.getType();
245 Class clazz = ClassLoader.getSystemClassLoader().loadClass(typeName);
247 Object javaObject = clazz.newInstance();
248 ClassInfo ci = ei.getClassInfo();
251 for (FieldInfo fi : ci.getDeclaredInstanceFields()) {
252 if (!fi.isReference()) {
253 setJavaPrimitive(javaObject, ei, fi);
257 ci = ci.getSuperClass();
261 } catch (Exception ex) {
262 throw new JPFException(ex);
266 private static void setJavaPrimitive(Object javaObject, ElementInfo ei, FieldInfo fi) throws NoSuchFieldException, IllegalAccessException {
267 String primitiveType = fi.getName();
268 String fieldName = fi.getName();
270 Class javaClass = javaObject.getClass();
271 Field javaField = javaClass.getDeclaredField(fieldName);
272 javaField.setAccessible(true);
274 if (primitiveType.equals("char")) {
275 javaField.setChar(javaObject, ei.getCharField(fi));
277 else if (primitiveType.equals("byte")) {
278 javaField.setByte(javaObject, ei.getByteField(fi));
280 else if (primitiveType.equals("short")) {
281 javaField.setShort(javaObject, ei.getShortField(fi));
283 else if (primitiveType.equals("int")) {
284 javaField.setInt(javaObject, ei.getIntField(fi));
286 else if (primitiveType.equals("long")) {
287 javaField.setLong(javaObject, ei.getLongField(fi));
289 else if (primitiveType.equals("float")) {
290 javaField.setFloat(javaObject, ei.getFloatField(fi));
292 else if (primitiveType.equals("double")) {
293 javaField.setDouble(javaObject, ei.getDoubleField(fi));
296 throw new JPFException("Can't convert " + primitiveType + " to " +
297 javaField.getClass().getCanonicalName());
301 private static boolean isArrayField(FieldInfo fi) {
302 return fi.getType().lastIndexOf('[') >= 0;