Adding ParameterizedTypeImpl to getGenericSuperclass method.
[jpf-core.git] / src / peers / gov / nasa / jpf / vm / JPF_java_lang_Class.java
index 651e48b248fae9fc3583a597e753f145d1857a1e..cdc5dd709359a91bf10779a84a2ec15e84d7343b 100644 (file)
@@ -26,13 +26,6 @@ import java.util.Set;
 import gov.nasa.jpf.Config;
 import gov.nasa.jpf.annotation.MJI;
 
-// TODO: DIRTY HACKS!
-import java.lang.reflect.TypeVariable;
-import sun.reflect.generics.factory.CoreReflectionFactory;
-import sun.reflect.generics.factory.GenericsFactory;
-import sun.reflect.generics.repository.ClassRepository;
-import sun.reflect.generics.scope.ClassScope;
-
 /**
  * MJI NativePeer class for java.lang.Class library abstraction
  */
@@ -41,9 +34,7 @@ public class JPF_java_lang_Class extends NativePeer {
   static final String FIELD_CLASSNAME = "java.lang.reflect.Field";
   static final String METHOD_CLASSNAME = "java.lang.reflect.Method";
   static final String CONSTRUCTOR_CLASSNAME = "java.lang.reflect.Constructor";
-  // TODO: DIRTY HACKS!
-  static final String TYPEVARIABLE_CLASSNAME = "java.lang.reflect.TypeVariable";
-  
+
   public static boolean init (Config conf){
     // we create Method and Constructor objects, so we better make sure these
     // classes are initialized (they already might be)
@@ -115,6 +106,135 @@ public class JPF_java_lang_Class extends NativePeer {
       return MJIEnv.NULL;
     }
   }
+
+  // TODO: Fix for Groovy's model-checking
+  private static int getParameterizedTypeImplObj(String className, String[] parameterizedTypes, String ownerType,
+                                                 MJIEnv env, int objRef, int superObjRef) {
+
+    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
+    ei.setReferenceField("rawType", superObjRef);
+
+    // actualTypeArguments
+    int[] types = new int[parameterizedTypes.length];
+    for(int j = 0; j < parameterizedTypes.length; j++) {
+        types[j] = getTypeVariableImplObject(env, objRef, parameterizedTypes[j]);
+    }
+    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
+    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 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;
+  }
+
+  @MJI
+  public int getGenericSuperclass____Ljava_lang_reflect_Type_2 (MJIEnv env, int robj){
+    ClassInfo ci = env.getReferredClassInfo( robj);
+    ClassInfo sci = ci.getSuperClass();
+    if (sci != null) {
+      String[] typeVars = sci.getGenericTypeVariableNames();
+      // Not a generic class
+      if (typeVars.length == 0) {
+        return sci.getClassObjectRef();
+      }
+      String className = sci.getName();
+      String ownerType = Types.getOwnerClassName(className);
+      int gRef = getParameterizedTypeImplObj(className, typeVars, ownerType, env, ci.getClassObjectRef(),
+              sci.getClassObjectRef());
+
+      return gRef;
+    } else {
+      return MJIEnv.NULL;
+    }
+  }
+
+  @MJI
+  public int getGenericInterfaces_____3Ljava_lang_reflect_Type_2 (MJIEnv env, int robj) {
+    // TODO: Need to add ParameterizedTypeImpl
+    ClassInfo ci = env.getReferredClassInfo(robj);
+    int aref = MJIEnv.NULL;
+    ThreadInfo ti = env.getThreadInfo();
+
+    // contrary to the API doc, this only returns the interfaces directly
+    // implemented by this class, not it's bases
+    // <2do> this is not exactly correct, since the interfaces should be ordered
+    Set<ClassInfo> interfaces = ci.getInterfaceClassInfos();
+    aref = env.newObjectArray("Ljava/lang/Class;", interfaces.size());
+
+    int i=0;
+    for (ClassInfo ifc: interfaces){
+      env.setReferenceArrayElement(aref, i++, ifc.getClassObjectRef());
+    }
+
+    return aref;
+  }
+
+  @MJI
+  public int getTypeParameters_____3Ljava_lang_reflect_TypeVariable_2 (MJIEnv env, int robj){
+    // Get the ClassInfo for this class
+    ClassInfo tci = env.getReferredClassInfo(robj);
+    String[] typeVars = tci.getGenericTypeVariableNames();
+
+    // Return with null if this is not a generic class
+    if (typeVars.length == 0) {
+      int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", 0);
+      return aRef;
+    }
+    // Now create a TypeVariableImpl object for every type variable name; get the ClassInfo for TypeVariableImpl
+    ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
+    ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
+    int[] var = new int[typeVars.length];
+
+    for(int i = 0; i < typeVars.length; i++) {
+      int typeVarRef = env.newObject(ci);
+      ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
+      ei.setReferenceField("genericDeclaration", tci.getClassObjectRef());
+      ei.setReferenceField("name", env.newString(typeVars[i]));
+      var[i] = typeVarRef;
+    }
+    int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", typeVars.length);
+
+    // Set references for every array element
+    for (int i = 0; i < typeVars.length; i++) {
+      env.setReferenceArrayElement(aRef, i, var[i]);
+    }
+
+    return aRef;
+  }
   
   @MJI
   public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj,
@@ -154,48 +274,6 @@ public class JPF_java_lang_Class extends NativePeer {
     return ci.getClassObjectRef();
   }
 
-  // TODO: DIRTY HACKS!
-  /*int createTypeVariableObject (MJIEnv env, ClassInfo objectCi, MethodInfo mi) {
-    // NOTE - we rely on Constructor and Method peers being initialized
-    if (mi.isCtor()){
-      return JPF_java_lang_reflect_Constructor.createConstructorObject(env, objectCi, mi);
-    } else {
-      return JPF_java_lang_reflect_Method.createMethodObject(env, objectCi, mi);
-    }
-  }
-
-  // accessor for factory
-  private GenericsFactory getFactory() {
-    // create scope and factory
-    return CoreReflectionFactory.make(this, ClassScope.make(this));
-  }
-
-  @MJI
-  public int getTypeParameters_____3Ljava_lang_reflect_TypeVariable_2 (MJIEnv env, int objRef){
-    ClassInfo tci = getInitializedClassInfo(env, TYPEVARIABLE_CLASSNAME);
-    if (tci == null) {
-      env.repeatInvocation();
-      return MJIEnv.NULL;
-    }
-    // Get the object and the type parameters
-    ClassInfo ci = env.getReferredClassInfo(objRef);
-    String signature = ci.getType();
-    ClassRepository genericInfo = ClassRepository.make(signature, getFactory());
-    TypeVariable[] typeVariables = (TypeVariable[]) genericInfo.getTypeParameters();
-
-    int aref = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", typeVariables.length);
-
-    for(int i=0, j=0; i<typeVariables.length; i++){
-      if (typeVariables[i] != null) {
-        int mref = env.newObject(ci);
-        env.setReferenceArrayElement(aref,j++,mref);
-      }
-    }
-
-    return aref;
-  }*/
-  // TODO: DIRTY HACKS!
-
   @MJI
   public boolean desiredAssertionStatus____Z (MJIEnv env, int robj) {
     ClassInfo ci = env.getReferredClassInfo(robj);