A proper implementation for getGenericParameterTypes using the class ParameterizedTyp...
authorRahmadi Trimananda <rtrimana@uci.edu>
Wed, 19 Jun 2019 03:01:33 +0000 (20:01 -0700)
committerRahmadi Trimananda <rtrimana@uci.edu>
Wed, 19 Jun 2019 03:01:33 +0000 (20:01 -0700)
examples/Reflection.java
src/main/gov/nasa/jpf/vm/Types.java
src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java

index ae0e853..fe2927c 100644 (file)
@@ -42,25 +42,25 @@ public class Reflection {
 
    public static void main(String[] args) {
 
-      /*Method[] methods = SampleClass.class.getMethods();
+      Method[] methods = SampleClass.class.getMethods();
       Type[] parameters = methods[0].getGenericParameterTypes();
       //Type[] parameters = methods[0].getGenericParameterTypes();
       for (int i = 0; i < parameters.length; i++) {
          System.out.println(parameters[i]);
       }
       System.out.println();
-      Class[] parameterTypes = methods[0].getParameterTypes();
+      /*Class[] parameterTypes = methods[0].getParameterTypes();
       for(Class parameterType: parameterTypes){
          System.out.println(parameterType.getName());   
  
       }
       System.out.println();*/
-      TypeVariable[] typeParameters = GenericShort.class.getTypeParameters();
+      /*TypeVariable[] typeParameters = GenericShort.class.getTypeParameters();
       //TypeVariable[] typeParameters = SampleClass.class.getTypeParameters();
       for(TypeVariable typeVar: typeParameters){
          System.out.println(typeVar);   
  
-      }
+      }*/
       System.out.println();
       /*
       Type returnType = methods[0].getGenericReturnType();
index 873b065..2e98b25 100644 (file)
@@ -1177,21 +1177,22 @@ public class Types {
     throw new JPFException("invalid method declaration: " + methodDecl);
   }
 
+  // TODO: Fix for Groovy's model-checking
   public static String[] getGenericTypeVariableNames(String signature) {
     int pos = 0;
-    int opening = 0;
+    int marker = 0;
     ArrayList<String> typeVarNames = new ArrayList<>();
 
     while (pos < signature.length()) {
       if (pos > 0) {
         // Start from ';' if this is not the first type variable name
-        opening = signature.indexOf(';', pos);
+        marker = signature.indexOf(';', pos);
         // Break if this is the end of the type variable names
-        if (signature.charAt(opening + 1) == '>')
+        if (signature.charAt(marker + 1) == '>')
           break;
       }
       int colon = signature.indexOf(':', pos);
-      String typeVarName = signature.substring(opening + 1, colon);
+      String typeVarName = signature.substring(marker + 1, colon);
       typeVarNames.add(typeVarName);
       pos = colon + 1;
     }
@@ -1201,5 +1202,53 @@ public class Types {
 
     return arrTypeVarNames;
   }
-  
+
+  // TODO: Fix for Groovy's model-checking
+  public static String[] getParameterizedTypesFromArgumentTypeNames(String signature) {
+    int pos = signature.indexOf('<', 0);
+    if (pos == -1)
+      return new String[0];
+    ArrayList<String> typeVarNames = new ArrayList<>();
+
+    while (pos < signature.length()) {
+      String typeVarName = "";
+      int comma = signature.indexOf(',', pos);
+      if (comma == -1) {
+        int closing = signature.indexOf('>', pos);
+        typeVarName = signature.substring(pos + 1, closing);
+        pos = signature.length();
+      } else {
+        typeVarName = signature.substring(pos + 1, comma);
+        pos = comma + 1;
+      }
+      typeVarNames.add(typeVarName);
+    }
+
+    String[] arrTypeVarNames = new String[typeVarNames.size()];
+    typeVarNames.toArray(arrTypeVarNames);
+
+    return arrTypeVarNames;
+  }
+
+  public static String getGenericClassName(String signature) {
+    int opening = signature.indexOf('<');
+    if (opening == -1)
+      return signature;
+    else
+      return signature.substring(0, opening);
+  }
+
+  public static String getOwnerClassName(String signature) {
+    int marker = signature.indexOf('$');
+    if (marker == -1)
+      return null;
+    else
+      return signature.substring(0, marker);
+  }
+
+  public static boolean isGenericSignature(String signature) {
+    int opening = signature.indexOf('<');
+    return (opening != -1);
+  }
+  // TODO: Fix for Groovy's model-checking
 }
index 4e1987b..efb46e8 100644 (file)
@@ -115,27 +115,72 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
   }
 
   // TODO: Fix for Groovy's model-checking
-  // TODO: We have been able to only register the generic class and not yet the parameterized types
-  static int getGenericParameterTypes( MJIEnv env, MethodInfo mi) {
+  private static int getParameterizedTypeImplObj(String signature, MJIEnv env) {
+
+    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.getParameterizedTypesFromArgumentTypeNames(signature);
+    int[] types = new int[parameterizedTypes.length];
+    for(int j = 0; j < parameterizedTypes.length; j++) {
+      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;
+  }
+
+  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])) {
+        ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env);
+      } 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]);
@@ -146,7 +191,7 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
 
   @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