import gov.nasa.jpf.util.RunListener;
import gov.nasa.jpf.util.RunRegistry;
+import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
}
// TODO: Fix for Groovy's model-checking
- // TODO: We haven't been able to show the parameterized types
- static int getGenericParameterTypes( MJIEnv env, MethodInfo mi) {
+ private static int getGenericArrayTypeImplObj(String signature, MJIEnv env, int objRef, MethodInfo mi) {
+
+ ThreadInfo ti = env.getThreadInfo();
+ ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
+ ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl");
+
+ // Create a new object of type GenericArrayTypeImpl
+ int genArrRef = env.newObject(ci);
+ ElementInfo ei = env.getModifiableElementInfo(genArrRef);
+
+ // Get field information and fill out the fields
+ String clsSig = Types.getArrayClassName(signature);
+ int paramTypeRef = getParameterizedTypeImplObj(clsSig, env, objRef, mi);
+ ei.setReferenceField("genericComponentType", paramTypeRef);
+
+ return genArrRef;
+ }
+
+ private static int getParameterizedTypeImplObj(String signature, MJIEnv env, int objRef, MethodInfo mi) {
+
+ ThreadInfo ti = env.getThreadInfo();
+ ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
+ ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl");
+ // Create a new object of type ParameterizedTypeImpl
+ int paramTypeRef = env.newObject(ci);
+ ElementInfo ei = env.getModifiableElementInfo(paramTypeRef);
+ // Get field information and fill out the fields
+ // rawType field
+ String className = Types.getGenericClassName(signature);
+ ClassInfo gci = cli.getResolvedClassInfo(className);
+ if (!gci.isRegistered()) {
+ gci.registerClass(ti);
+ }
+ ei.setReferenceField("rawType", gci.getClassObjectRef());
+
+ // actualTypeArguments
+ String[] parameterizedTypes = Types.getParameterizedTypes(signature);
+ int[] types = new int[parameterizedTypes.length];
+ String classGenericSig = mi.getClassInfo().getGenericSignature();
+ String methodGenericSig = mi.getGenericSignature();
+ for(int j = 0; j < parameterizedTypes.length; j++) {
+ if (Types.isTypeParameter(parameterizedTypes[j], methodGenericSig) ||
+ Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) {
+ types[j] = getTypeVariableImplObject(env, objRef, parameterizedTypes[j]);
+ } else if (Types.isWildcardType(parameterizedTypes[j])) {
+ types[j] = getWildcardTypeImplObject(env, objRef, parameterizedTypes[j], mi);
+ } else if (Types.isParameterizedType(parameterizedTypes[j])) {
+ // Recursion!
+ types[j] = getParameterizedTypeImplObj(parameterizedTypes[j], env, objRef, mi);
+ } else {
+ ClassInfo pci = cli.getResolvedClassInfo(parameterizedTypes[j]);
+ if (!pci.isRegistered()) {
+ pci.registerClass(ti);
+ }
+ types[j] = pci.getClassObjectRef();
+ }
+ }
+ int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", parameterizedTypes.length);
+ // Set references for every array element
+ for (int j = 0; j < parameterizedTypes.length; j++) {
+ env.setReferenceArrayElement(aRef, j, types[j]);
+ }
+ ei.setReferenceField("actualTypeArguments", aRef);
+
+ // ownerType
+ String ownerType = Types.getOwnerClassName(signature);
+ if (ownerType != null) {
+ ClassInfo oci = ClassLoaderInfo.getCurrentResolvedClassInfo(ownerType);
+ if (!oci.isRegistered()) {
+ oci.registerClass(ti);
+ }
+ ei.setReferenceField("ownerType", oci.getClassObjectRef());
+ } else {
+ ei.setReferenceField("ownerType", MJIEnv.NULL);
+ }
+
+ return paramTypeRef;
+ }
+
+ private static int getWildcardTypeImplObject(MJIEnv env, int objRef, String wildcardType, MethodInfo mi) {
+ ThreadInfo ti = env.getThreadInfo();
+ ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
+ ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.WildcardTypeImpl");
+
+ int wildcardRef = env.newObject(ci);
+ ElementInfo ei = env.getModifiableElementInfo(wildcardRef);
+ // Type parameter test
+ // TODO: This test could probably be made cleaner
+ String classGenericSig = mi.getClassInfo().getGenericSignature();
+ String methodGenericSig = mi.getGenericSignature();
+ String typeParameter = Types.getTypeParameter(wildcardType);
+ int uRef = MJIEnv.NULL;
+ int lRef = MJIEnv.NULL;
+ if (Types.isTypeParameter(typeParameter, methodGenericSig) ||
+ Types.isTypeParameter(typeParameter, classGenericSig)) {
+ int tpRef = getTypeVariableImplObject(env, objRef, typeParameter);
+ if (wildcardType.startsWith("+")) {
+ // Set upperBounds
+ uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
+ env.setReferenceArrayElement(uRef, 0, tpRef);
+ lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
+ } else { // wildcardType.startsWith("-")
+ // Set lowerBounds
+ lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
+ env.setReferenceArrayElement(lRef, 0, tpRef);
+ }
+ } else {
+
+ String actualType = Types.getWildcardType(wildcardType);
+ ClassInfo uci = cli.getResolvedClassInfo(actualType);
+ if (!uci.isRegistered()) {
+ uci.registerClass(ti);
+ }
+ if (wildcardType.startsWith("+L") || wildcardType.equals("*")) {
+ // Set upperBounds
+ uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
+ env.setReferenceArrayElement(uRef, 0, uci.getClassObjectRef());
+ lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
+ } else { // wildcardType.startsWith("-L")
+ // Set lowerBounds
+ lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
+ env.setReferenceArrayElement(lRef, 0, uci.getClassObjectRef());
+ }
+ }
+ ei.setReferenceField("upperBounds", uRef);
+ ei.setReferenceField("lowerBounds", lRef);
+
+ return wildcardRef;
+ }
+
+ private static int getTypeVariableImplObject(MJIEnv env, int objRef, String parameterizedType) {
+
+ ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
+ ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
+
+ int typeVarRef = env.newObject(ci);
+ ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
+ // genericDeclaration contains this java.lang.reflect.Method object
+ ei.setReferenceField("genericDeclaration", objRef);
+ ei.setReferenceField("name", env.newString(parameterizedType));
+
+ return typeVarRef;
+ }
+
+ static int getGenericParameterTypes( MJIEnv env, int objRef, MethodInfo mi) {
ThreadInfo ti = env.getThreadInfo();
String[] argTypeNames = mi.getArgumentGenericTypeNames();
int[] ar = new int[argTypeNames.length];
for (int i = 0; i < argTypeNames.length; i++) {
// Change this into just the generic class type if it is a generic class
- String genericTypeName = argTypeNames[i];
- int startOfGenericParameter = argTypeNames[i].indexOf('<');
- if (startOfGenericParameter != -1) {
- genericTypeName = argTypeNames[i].substring(0, startOfGenericParameter);
- }
- ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(genericTypeName);
- if (!ci.isRegistered()) {
- ci.registerClass(ti);
+ if (Types.isGenericSignature(argTypeNames[i])) {
+ if (Types.isArraySignature(argTypeNames[i])) {
+ // Generic array
+ ar[i] = getGenericArrayTypeImplObj(argTypeNames[i], env, objRef, mi);
+ } else {
+ ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env, objRef, mi);
+ }
+ } else {
+ ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(argTypeNames[i]);
+ if (!ci.isRegistered()) {
+ ci.registerClass(ti);
+ }
+ ar[i] = ci.getClassObjectRef();
}
-
- ar[i] = ci.getClassObjectRef();
}
-
int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", argTypeNames.length);
for (int i = 0; i < argTypeNames.length; i++) {
env.setReferenceArrayElement(aRef, i, ar[i]);
@MJI
public int getGenericParameterTypes_____3Ljava_lang_reflect_Type_2 (MJIEnv env, int objRef){
- return getGenericParameterTypes(env, getMethodInfo(env, objRef));
+ return getGenericParameterTypes(env, objRef, getMethodInfo(env, objRef));
}
@MJI
MethodInfo mi = getMethodInfo(env, objRef);
ThreadInfo ti = env.getThreadInfo();
- ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName());
- if (!ci.isRegistered()) {
- ci.registerClass(ti);
+ int retRef;
+ if (Types.isGenericSignature(mi.getGenericReturnTypeName())) {
+ if (Types.isArraySignature(mi.getGenericReturnTypeName())) {
+ // Generic array
+ retRef = getGenericArrayTypeImplObj(mi.getGenericReturnTypeName(), env, objRef, mi);
+ } else {
+ retRef = getParameterizedTypeImplObj(mi.getGenericReturnTypeName(), env, objRef, mi);
+ }
+ } else {
+ ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName());
+ if (!ci.isRegistered()) {
+ ci.registerClass(ti);
+ }
+ retRef = ci.getClassObjectRef();
}
- return ci.getClassObjectRef();
+ return retRef;
}
// TODO: Fix for Groovy's model-checking
- // TODO: We haven't been able to show the parameterized types
-
+ // TODO: We have been able to only register the generic class and not yet the parameterized types
+
int getExceptionTypes(MJIEnv env, MethodInfo mi) {
ThreadInfo ti = env.getThreadInfo();
String[] exceptionNames = mi.getThrownExceptionClassNames();