//
// Copyright (C) 2006 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.vm;
import cmu.conditional.Conditional;
import cmu.conditional.One;
import de.fosd.typechef.featureexpr.FeatureExpr;
import gov.nasa.jpf.annotation.MJI;
/**
* MJI NativePeer class for java.lang.reflect.Array library abstraction
*/
public class JPF_java_lang_reflect_Array extends NativePeer {
@MJI
public int getLength__Ljava_lang_Object_2__I (MJIEnv env, int clsObjRef,
int objRef, FeatureExpr ctx) {
if (objRef == MJIEnv.NULL) {
env.throwException(ctx, "java.lang.NullPointerException", "array argument is null");
return 0;
}
if (!env.isArray(objRef)) {
env.throwException(ctx, "java.lang.IllegalArgumentException", "argument is not an array");
return 0;
}
return env.getArrayLength(ctx, objRef);
}
@MJI
public int newArray__Ljava_lang_Class_2I__Ljava_lang_Object_2 (MJIEnv env, int clsRef,
int componentTypeRef, int length, FeatureExpr ctx) {
ClassInfo ci = env.getReferredClassInfo(ctx, componentTypeRef);
String clsName = ci.getName();
return createNewArray( env, clsName, length, ctx);
}
static int createNewArray (MJIEnv env, String clsName, int length, FeatureExpr ctx) {
int aRef = MJIEnv.NULL;
if ("boolean".equals(clsName)) { aRef = env.newBooleanArray(length); }
else if ("byte".equals(clsName)) { aRef = env.newByteArray(length); }
else if ("char".equals(clsName)) { aRef = env.newCharArray(ctx, length); }
else if ("short".equals(clsName)) { aRef = env.newShortArray(length); }
else if ("int".equals(clsName)) { aRef = env.newIntArray(length); }
else if ("long".equals(clsName)) { aRef = env.newLongArray(length); }
else if ("float".equals(clsName)) { aRef = env.newFloatArray(length); }
else if ("double".equals(clsName)) { aRef = env.newDoubleArray(length); }
else { aRef = env.newObjectArray(clsName, length); }
return aRef;
}
@MJI
public int multiNewArray__Ljava_lang_Class_2_3I__Ljava_lang_Object_2 (MJIEnv env, int clsRef,
int componentTypeRef,
int dimArrayRef, FeatureExpr ctx) {
ClassInfo ci = env.getReferredClassInfo(ctx, componentTypeRef);
String clsName = ci.getName();
int n = env.getArrayLength(ctx, dimArrayRef);
int i;
clsName = Types.getTypeSignature(clsName, true);
String arrayType = "[";
for (i=2; i<n; i++) arrayType += '[';
arrayType += clsName;
int[] dim = new int[n];
for (i=0; i<n; i++) {
dim[i] = env.getIntArrayElement(dimArrayRef, i).getValue();
}
int aRef = createNewMultiArray(env, arrayType, dim, 0, ctx);
return aRef;
}
static int createNewMultiArray (MJIEnv env, String arrayType, int[] dim, int level, FeatureExpr ctx) {
int aRef = MJIEnv.NULL;
int len = dim[level];
if (level < dim.length-1) {
aRef = env.newObjectArray(arrayType, len);
for (int i=0; i<len; i++) {
int eRef = createNewMultiArray(env, arrayType.substring(1), dim, level+1, ctx);
env.setReferenceArrayElement(ctx, aRef, i, new One<>(eRef));
}
} else {
aRef = createNewArray( env, arrayType, len, ctx);
}
return aRef;
}
@MJI
public int get__Ljava_lang_Object_2I__Ljava_lang_Object_2 (MJIEnv env, int clsRef,
int aref, int index, FeatureExpr ctx){
String at = env.getArrayType(aref);
if (at.equals("int") || "I".equals(at)){
int vref = env.newObject(ctx, "java.lang.Integer");
env.setIntField(ctx, vref, "value", env.getIntArrayElement(aref,index));
return vref;
} else if (at.equals("long") || "J".equals(at)){
int vref = env.newObject(ctx, "java.lang.Long");
env.setLongField(ctx, vref, "value", env.getLongArrayElement(aref,index));
return vref;
} else if (at.equals("double") || "D".equals(at)){
int vref = env.newObject(ctx, "java.lang.Double");
env.setDoubleField(ctx, vref, "value", env.getDoubleArrayElement(aref,index));
return vref;
} else if (at.equals("boolean") || "Z".equals(at)){
int vref = env.newObject(ctx, "java.lang.Boolean");
env.setBooleanField(ctx, vref, "value", env.getBooleanArrayElement(aref,index));
return vref;
} else if (at.equals("char") || "C".equals(at)){
int vref = env.newObject(ctx, "java.lang.Character");
env.setCharField(ctx, vref, "value", env.getCharArrayElement(aref,index));
return vref;
} else if (at.equals("byte") || "B".equals(at)){
int vref = env.newObject(ctx, "java.lang.Byte");
env.setByteField(ctx, vref, "value", env.getByteArrayElement(aref,index));
return vref;
} else if (at.equals("short") || "S".equals(at)){
int vref = env.newObject(ctx, "java.lang.Short");
env.setShortField(ctx, vref, "value", env.getShortArrayElement(aref,index));
return vref;
} else if (at.equals("float") || "F".equals(at)){
int vref = env.newObject(ctx, "java.lang.Float");
env.setFloatField(ctx, vref, "value", env.getFloatArrayElement(aref,index));
return vref;
} else {
return env.getReferenceArrayElement(aref, index).simplify(ctx).getValue();
}
}
private static boolean check (MJIEnv env, int aref, int index, FeatureExpr ctx) {
if (aref == MJIEnv.NULL) {
env.throwException(ctx, "java.lang.NullPointerException", "array argument is null");
return false;
}
if (!env.isArray(aref)) {
env.throwException(ctx, "java.lang.IllegalArgumentException", "argument is not an array");
return false;
}
if (index < 0 || index >= env.getArrayLength(ctx, aref)) {
env.throwException(ctx, "java.lang.IndexOutOfBoundsException", "index " + index + " is out of bounds");
return false;
}
return true;
}
@MJI
public boolean getBoolean__Ljava_lang_Object_2I__Z (MJIEnv env, int clsRef, int aref, int index, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
return env.getBooleanArrayElement(aref, index).getValue();
}
return false;
}
@MJI
public static byte getByte__Ljava_lang_Object_2I__B (MJIEnv env, int clsRef, int aref, int index, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
return env.getByteArrayElement(aref, index).getValue();
}
return 0;
}
@MJI
public char getChar__Ljava_lang_Object_2I__C (MJIEnv env, int clsRef, int aref, int index, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
return env.getCharArrayElement(aref, index).getValue();
}
return 0;
}
@MJI
public short getShort__Ljava_lang_Object_2I__S (MJIEnv env, int clsRef, int aref, int index, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
return env.getShortArrayElement(aref, index).getValue();
}
return 0;
}
@MJI
public Conditional<Integer> getInt__Ljava_lang_Object_2I__I (MJIEnv env, int clsRef, int aref, int index, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
return env.getIntArrayElement(aref, index);
}
return One.valueOf(0);
}
@MJI
public long getLong__Ljava_lang_Object_2I__J (MJIEnv env, int clsRef, int aref, int index, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
return env.getLongArrayElement(aref, index).getValue();
}
return 0;
}
@MJI
public float getFloat__Ljava_lang_Object_2I__F (MJIEnv env, int clsRef, int aref, int index, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
return env.getFloatArrayElement(aref, index).getValue();
}
return 0;
}
@MJI
public double getDouble__Ljava_lang_Object_2I__D (MJIEnv env, int clsRef, int aref, int index, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
return env.getDoubleArrayElement(aref, index).getValue();
}
return 0;
}
@MJI
public void setBoolean__Ljava_lang_Object_2IZ__V (MJIEnv env, int clsRef, int aref, int index, boolean val, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
env.setBooleanArrayElement(ctx, aref, index, new One<>(val));
}
}
@MJI
public void setByte__Ljava_lang_Object_2IB__V (MJIEnv env, int clsRef, int aref, int index, byte val, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
env.setByteArrayElement(ctx, aref, index, new One<>(val));
}
}
@MJI
public void setChar__Ljava_lang_Object_2IC__V (MJIEnv env, int clsRef, int aref, int index, char val, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
env.setCharArrayElement(ctx, aref, index, new One<>(val));
}
}
@MJI
public void setShort__Ljava_lang_Object_2IS__V (MJIEnv env, int clsRef, int aref, int index, short val, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
env.setShortArrayElement(ctx, aref, index, new One<>(val));
}
}
@MJI
public void setInt__Ljava_lang_Object_2II__V (MJIEnv env, int clsRef, int aref, int index, int val, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
env.setIntArrayElement(ctx, aref, index, One.valueOf(val));
}
}
@MJI
public void setLong__Ljava_lang_Object_2IJ__V (MJIEnv env, int clsRef, int aref, int index, long val, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
env.setLongArrayElement(ctx, aref, index, new One<>(val));
}
}
@MJI
public void setFloat__Ljava_lang_Object_2IF__V (MJIEnv env, int clsRef, int aref, int index, float val, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
env.setFloatArrayElement(ctx, aref, index, new One<>(val));
}
}
@MJI
public void setDouble__Ljava_lang_Object_2ID__V (MJIEnv env, int clsRef, int aref, int index, double val, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
env.setDoubleArrayElement(ctx, aref, index, new One<>(val));
}
}
@MJI
public void set__Ljava_lang_Object_2ILjava_lang_Object_2__V(MJIEnv env, int clsRef, int aref, int index, int valRef, FeatureExpr ctx) {
if (check(env, aref, index, ctx)) {
String arrayType = env.getArrayType(aref);
if ("Z".equals(arrayType)) {
env.setBooleanArrayElement(ctx, aref, index, env.getBooleanValue(valRef));
} else if ("C".equals(arrayType)) {
env.setCharArrayElement(ctx, aref, index, env.getCharValue(valRef));
} else if ("S".equals(arrayType)) {
env.setShortArrayElement(ctx, aref, index, env.getShortValue(valRef));
} else if ("B".equals(arrayType)) {
env.setByteArrayElement(ctx, aref, index, env.getByteValue(valRef));
} else if ("I".equals(arrayType)) {
env.setIntArrayElement(ctx, aref, index, env.getIntValue(valRef));
} else if ("J".equals(arrayType)) {
env.setLongArrayElement(ctx, aref, index, env.getLongValue(valRef));
} else if ("F".equals(arrayType)) {
env.setFloatArrayElement(ctx, aref, index, env.getFloatValue(valRef));
} else if ("D".equals(arrayType)) {
env.setDoubleArrayElement(ctx, aref, index, env.getDoubleValue(valRef));
} else {
env.setReferenceArrayElement(ctx, aref, index, new One<>(valRef));
}
}
}
}