[jboss-cvs] JBossAS SVN: r102626 - in projects/jboss-reflect/trunk/src: main/java/org/jboss/reflect/plugins/introspection and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Mar 19 11:02:43 EDT 2010


Author: kabir.khan at jboss.com
Date: 2010-03-19 11:02:41 -0400 (Fri, 19 Mar 2010)
New Revision: 102626

Added:
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/introspection/SecurityActions.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeVariableSpy.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/SecurityActions.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperClassTypeVariable.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperClassTypeVariableBounded.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperInterfaceTypeVariable.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperInterfaceTypeVariableBounded.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoTypeVariable.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoTypeVariableBounded.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoGenericMembersTest.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/IntrospectionClassInfoGenericMembersTestCase.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/JavassistClassInfoGenericMembersTestCase.java
Modified:
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/GenericsUtil.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/introspection/IntrospectionTypeInfoFactoryImpl.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistConstructorInfo.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistFieldInfo.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistHelper.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistMethodInfo.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistParameterizedClassInfo.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfo.java
   projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfoFactoryImpl.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoGenericClassTest.java
   projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoTestSuite.java
Log:
[JBREFLECT-5] Make JavassistMethodInfo/-FieldInfo/ConstructorInfo's getParameterTypes(), getReturnType() and getFieldType() etc. return Parameterized type infos if generics are used

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/GenericsUtil.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/GenericsUtil.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/GenericsUtil.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -63,12 +63,10 @@
          
          if (lower.length > 0)
          {
-            sb.append("? super ");
             appendTypeGenericInfo(lower[0], sb);
          }
          else if (upper.length > 0)
          {
-            sb.append("? extends ");
             appendTypeGenericInfo(upper[0], sb);
          }
       }
@@ -94,9 +92,8 @@
       }
       else if (type instanceof TypeVariable)
       {
-         //This is probably the wrong name, revisit when implementing type variables
          TypeVariable typeVar = (TypeVariable)type;
-         sb.append(typeVar.getName());
+         appendTypeGenericInfo(typeVar.getBounds()[0], sb);
       }
       else
       {

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/introspection/IntrospectionTypeInfoFactoryImpl.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/introspection/IntrospectionTypeInfoFactoryImpl.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/introspection/IntrospectionTypeInfoFactoryImpl.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -724,4 +724,33 @@
       Type bound = type.getLowerBounds().length > 0 ? type.getLowerBounds()[0] : type.getUpperBounds()[0];
       return getTypeInfo(bound);
    }
+
+   @Override
+   protected TypeInfo peek(ParameterizedType type)
+   {
+      //FIXME improved version of what exists in WeakTypeCache. Should be put there
+      Class<?> rawType = (Class<?>) type.getRawType();
+      ClassLoader cl = SecurityActions.getClassLoader(rawType);
+      Map<String, TypeInfo> classLoaderCache = getClassLoaderCache(cl);
+      
+      synchronized (classLoaderCache)
+      {
+         return classLoaderCache.get(GenericsUtil.getGenericName(type));
+      }
+   }
+
+   @Override
+   protected void put(ParameterizedType type, TypeInfo result)
+   {
+      //FIXME improved version of what exists in WeakTypeCache. Should be put there
+      Class<?> rawType = (Class<?>) type.getRawType();
+      ClassLoader cl = SecurityActions.getClassLoader(rawType);
+      Map<String, TypeInfo> classLoaderCache = getClassLoaderCache(cl);
+
+      synchronized (classLoaderCache)
+      {
+         classLoaderCache.put(GenericsUtil.getGenericName(type), result);
+      }
+   }
+
 }

Added: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/introspection/SecurityActions.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/introspection/SecurityActions.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/introspection/SecurityActions.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,69 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.reflect.plugins.introspection;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class SecurityActions
+{
+   interface GetClassLoaderAction 
+   {
+      ClassLoader getClassLoader(Class<?> clazz);
+      
+      GetClassLoaderAction NON_PRIVILEGED = new GetClassLoaderAction() {
+
+         public ClassLoader getClassLoader(Class<?> clazz)
+         {
+            return clazz.getClassLoader();
+         }};
+
+     GetClassLoaderAction PRIVILEGED = new GetClassLoaderAction() {
+
+         public ClassLoader getClassLoader(final Class<?> clazz)
+         {
+            return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+
+               public ClassLoader run()
+               {
+                  return clazz.getClassLoader();
+               }});
+         }};
+   }
+   
+   static ClassLoader getClassLoader(Class<?> clazz)
+   {
+      if (System.getSecurityManager() == null)
+      {
+         return GetClassLoaderAction.NON_PRIVILEGED.getClassLoader(clazz);
+      }
+      else
+      {
+         return GetClassLoaderAction.PRIVILEGED.getClassLoader(clazz);
+      }
+   }
+}

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistConstructorInfo.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistConstructorInfo.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistConstructorInfo.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -28,6 +28,7 @@
 import javassist.CtClass;
 import javassist.CtConstructor;
 import javassist.NotFoundException;
+import javassist.bytecode.SignatureAttribute.MethodSignature;
 
 import org.jboss.reflect.plugins.AnnotationHelper;
 import org.jboss.reflect.spi.AnnotationValue;
@@ -189,12 +190,20 @@
    {
       try
       {
-         CtClass[] types = ctConstructor.getParameterTypes();
-         parameterTypes = new TypeInfo[types.length];
-         for (int i = 0; i < types.length; ++i)
-            parameterTypes[i] = typeInfo.getFactory().getTypeInfo(types[i]);
-         parameters = new ParameterInfo[types.length];
-         for (int i = 0; i < types.length; ++i)
+         MethodSignature sig = JavassistHelper.getMethodSignature(ctConstructor);
+         if (sig != null && sig.getParameterTypes().length == ctConstructor.getParameterTypes().length)
+         {
+            parameterTypes = JavassistHelper.createParameterTypes(ctConstructor, sig, typeInfo);
+         }
+         else
+         {
+            CtClass[] types = ctConstructor.getParameterTypes();
+            parameterTypes = new TypeInfo[types.length];
+            for (int i = 0; i < types.length; ++i)
+               parameterTypes[i] = typeInfo.getFactory().getTypeInfo(types[i]);
+         }
+         parameters = new ParameterInfo[parameterTypes.length];
+         for (int i = 0; i < parameterTypes.length; ++i)
             parameters[i] = new JavassistParameterInfo(annotationHelper, this, i, parameterTypes[i]);
       }
       catch (NotFoundException e)

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistFieldInfo.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistFieldInfo.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistFieldInfo.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -35,6 +35,8 @@
 import javassist.CtClass;
 import javassist.CtField;
 import javassist.NotFoundException;
+import javassist.bytecode.SignatureAttribute.ClassSignature;
+import javassist.bytecode.SignatureAttribute.ObjectType;
 
 /**
  * FieldInfo that relies on Javassist to answer reflective queries and to access
@@ -119,6 +121,13 @@
          return fieldType;
       try
       {
+         ObjectType type = JavassistHelper.getFieldSignature(ctField);
+         if (type != null)
+         {
+            ClassSignature sig = JavassistHelper.getClassSignature(ctField.getDeclaringClass());
+            return typeInfo.getFactory().getTypeInfo(typeInfo.getClassLoader(), type, JavassistTypeVariableSpy.createForField(sig));
+         }
+         
          CtClass clazz = ctField.getType();
          fieldType = typeInfo.getFactory().getTypeInfo(clazz);
          return fieldType;

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistHelper.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistHelper.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistHelper.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -24,13 +24,18 @@
 import java.util.Arrays;
 import java.util.Stack;
 
+import javassist.CtBehavior;
 import javassist.CtClass;
+import javassist.CtField;
 import javassist.NotFoundException;
 import javassist.bytecode.BadBytecode;
 import javassist.bytecode.SignatureAttribute;
+import javassist.bytecode.SignatureAttribute.ArrayType;
 import javassist.bytecode.SignatureAttribute.ClassSignature;
 import javassist.bytecode.SignatureAttribute.ClassType;
+import javassist.bytecode.SignatureAttribute.MethodSignature;
 import javassist.bytecode.SignatureAttribute.ObjectType;
+import javassist.bytecode.SignatureAttribute.Type;
 import javassist.bytecode.SignatureAttribute.TypeArgument;
 import javassist.bytecode.SignatureAttribute.TypeParameter;
 import javassist.bytecode.SignatureAttribute.TypeVariable;
@@ -51,7 +56,7 @@
     * @param clazz the sub class
     * @param search the parent class or interface we are searching for
     * @param parameter the index of the type parameter we are looking for
-    * @return the type
+    * @return the generic type
     */
    static ClassType determineType(CtClass clazz, CtClass search, int parameter)
    {
@@ -67,7 +72,16 @@
       return determineType(hierarchy, parameter);
    }
 
-   static int determineInfoIndex(TypeInfo[] actualTypeArguments, CtClass clazz, CtClass search, int parameter)
+   /**
+    * Looking at the classes between clazz and search, determine the type of the type parameter with the passed in index
+    *
+    * @param actualTypeArguments the actual type arguments
+    * @param clazz the sub class
+    * @param search the parent class or interface we are searching for
+    * @param parameter the index of the type parameter we are looking for
+    * @return the type
+    */
+   static TypeInfo determineInfoIndex(TypeInfo[] actualTypeArguments, CtClass clazz, CtClass search, int parameter)
    {
       Stack<CtClass> hierarchy = new Stack<CtClass>();      
       try
@@ -78,10 +92,81 @@
       {
          throw new RuntimeException(e);
       }
-      return determineInfoIndex(actualTypeArguments, hierarchy, parameter);
+      return actualTypeArguments[determineInfoIndex(actualTypeArguments, hierarchy, parameter)];
    }
+
+   /**
+    * Get the full name of the generic javassist object type
+    *
+    * @param type the type
+    * @param spy used to determine actual types of type variables
+    * @return the generic type name
+    */
+   static String getGenericName(ObjectType type, JavassistTypeVariableSpy spy)
+   {
+      StringBuilder sb = new StringBuilder();
+      appendTypeGenericInfo(type, spy, sb);
+      return sb.toString();
+   }
    
    /**
+    * Append the information of the type to the name builder
+    *
+    * @param type the type
+    * @param spy used to determine actual types of type variables
+    * @param sb the string builder receiving the name
+    * @return the generic type name
+    */
+   private static void appendTypeGenericInfo(ObjectType type, JavassistTypeVariableSpy spy, StringBuilder sb)
+   {
+      
+      if (type instanceof ClassType)
+      {
+         ClassType ctype = (ClassType)type;
+         sb.append(ctype.getName());
+
+         TypeArgument[] arguments = ctype.getTypeArguments();
+         
+         if (arguments != null && arguments.length > 0)
+         {
+            sb.append("<");
+            
+            for (int i = 0 ; i < arguments.length ; i++)
+            {
+               if (i > 0)
+                  sb.append(", ");
+               
+               if (arguments[i].getType() == null)
+                  sb.append(Object.class.getName());
+               else
+                  appendTypeGenericInfo(arguments[i].getType(), spy, sb);
+            }
+            sb.append(">");
+         }
+      }
+      else if (type instanceof SignatureAttribute.TypeVariable)
+      {
+         Type real = spy.getTypeBound((TypeVariable)type);
+         if (real instanceof ObjectType == false)
+            throw new IllegalStateException("Type is not an instance of ObjectType " + real);
+         appendTypeGenericInfo((ObjectType)real, spy, sb);
+      }
+      else if (type instanceof ArrayType)
+      {
+         ArrayType array = (ArrayType)type;
+         
+         appendTypeGenericInfo((ObjectType)array.getComponentType(), spy, sb);
+         for (int i = 0 ; i < array.getDimension() ; i++)
+            sb.append("[]");
+      }
+      else
+      {
+         //TODO This might need implementing once we test wildcards
+         throw new IllegalArgumentException("Unhandled type " + type);
+      }
+   }
+
+   /**
     * Determine the type of the parameter in the top-level class. 
     * 
     * @param hierarchy the hierarchy of classes as determined by {@link JavassistHelper#determineHierarchy(Stack, CtClass, CtClass)}
@@ -107,15 +192,16 @@
     * 
     * @param clazz the CtClass
     * @return the ClassSignature
+    * @throws IllegalArgumentException if clazz is null 
     */
    public static ClassSignature getClassSignature(CtClass clazz)
    {
       if (clazz == null)
          throw new IllegalArgumentException("Null clazz");
 
-      //Use getClassFile2 since in some cases the class has been frozen
       if (clazz.isArray() || clazz.isPrimitive())
          return null;
+      //Use getClassFile2 since in some cases the class has been frozen
       SignatureAttribute signature = (SignatureAttribute)clazz.getClassFile2().getAttribute(SignatureAttribute.tag);
       if (signature == null)
          return null;
@@ -130,8 +216,79 @@
          throw new IllegalStateException(e);
       }
    }
+   
+   /**
+    * Creates the generic parameter types for a constructor or method
+    * 
+    * @param behavior the method or constructor
+    * @param sig the method/constructor signature
+    * @param typeInfo the javassist type info
+    * @return the parameter types 
+    */
+   public static TypeInfo[] createParameterTypes(CtBehavior behavior, MethodSignature sig, JavassistTypeInfo typeInfo)
+   {
+      SignatureAttribute.Type[] types = sig.getParameterTypes();
+      TypeInfo[] parameterTypes = new TypeInfo[types.length];
+      for (int i = 0 ; i < types.length ; i++)
+         parameterTypes[i] = typeInfo.getFactory().getTypeInfo(typeInfo.getClassLoader(), types[i], JavassistTypeVariableSpy.createForBehavior(behavior, sig));
+      return parameterTypes;
+   }
+   
+   /**
+    * Gets the ClassSignature for a method/constructor
+    * 
+    * @param behaviour the method/constructor
+    * @return the ClassSignature
+    * @throws IllegalArgumentException if clazz is null 
+    */
+   public static MethodSignature getMethodSignature(CtBehavior behaviour)
+   {
+      if (behaviour == null)
+         throw new IllegalArgumentException("Null method/constructor");
+      
+      //Use getMethodInfo2 since in some cases the class has been frozen
+      SignatureAttribute signature = (SignatureAttribute)behaviour.getMethodInfo2().getAttribute(SignatureAttribute.tag);
+      if (signature == null)
+         return null;
+      String sig = signature.getSignature();
+      try
+      {
+         return SignatureAttribute.toMethodSignature(sig);
+      }
+      catch (BadBytecode e)
+      {
+         throw new IllegalStateException(e);
+      }
+   }
 
    /**
+    * Gets the FieldSignature for a field
+    * 
+    * @param field the field
+    * @return the FieldSignature
+    * @throws IllegalArgumentException if clazz is null 
+    */
+   public static ObjectType getFieldSignature(CtField field)
+   {
+      if (field == null)
+         throw new IllegalArgumentException("Null method/constructor");
+      
+      //Use getMethodInfo2 since in some cases the class has been frozen
+      SignatureAttribute signature = (SignatureAttribute)field.getFieldInfo2().getAttribute(SignatureAttribute.tag);
+      if (signature == null)
+         return null;
+      String sig = signature.getSignature();
+      try
+      {
+         return SignatureAttribute.toFieldSignature(sig);
+      }
+      catch (BadBytecode e)
+      {
+         throw new IllegalStateException(e);
+      }
+   }
+
+   /**
     * Figures out the path between the passed in classes
     * 
     * @param hierarchy receives the CtClasses that make up the hierarchy. This parameter may be null, in which 

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistMethodInfo.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistMethodInfo.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistMethodInfo.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -29,6 +29,8 @@
 import javassist.CtClass;
 import javassist.CtMethod;
 import javassist.NotFoundException;
+import javassist.bytecode.SignatureAttribute.BaseType;
+import javassist.bytecode.SignatureAttribute.MethodSignature;
 
 import org.jboss.reflect.plugins.AnnotationHelper;
 import org.jboss.reflect.spi.AnnotationValue;
@@ -142,9 +144,15 @@
          return returnType;
       try
       {
+         MethodSignature sig = JavassistHelper.getMethodSignature(ctMethod);
+         if (sig != null)
+         {
+            if (sig.getReturnType() instanceof BaseType == false)
+               return typeInfo.getFactory().getTypeInfo(typeInfo.getClassLoader(), sig.getReturnType(), JavassistTypeVariableSpy.createForBehavior(ctMethod, sig));
+         }
+
          CtClass clazz = ctMethod.getReturnType();
-         returnType = typeInfo.getFactory().getTypeInfo(clazz);
-         return returnType;
+         return typeInfo.getFactory().getTypeInfo(clazz);
       }
       catch (NotFoundException e)
       {
@@ -218,12 +226,20 @@
    {
       try
       {
-         CtClass[] types = ctMethod.getParameterTypes();
-         parameterTypes = new TypeInfo[types.length];
-         for (int i = 0; i < types.length; ++i)
-            parameterTypes[i] = typeInfo.getFactory().getTypeInfo(types[i]);
-         parameters = new ParameterInfo[types.length];
-         for (int i = 0; i < types.length; ++i)
+         MethodSignature sig = JavassistHelper.getMethodSignature(ctMethod);
+         if (sig != null && sig.getParameterTypes().length == ctMethod.getParameterTypes().length)
+         {
+            parameterTypes = JavassistHelper.createParameterTypes(ctMethod, sig, typeInfo);
+         }
+         else
+         {
+            CtClass[] types = ctMethod.getParameterTypes();
+            parameterTypes = new TypeInfo[types.length];
+            for (int i = 0; i < types.length; ++i)
+               parameterTypes[i] = typeInfo.getFactory().getTypeInfo(types[i]);
+         }
+         parameters = new ParameterInfo[parameterTypes.length];
+         for (int i = 0; i < parameterTypes.length; ++i)
             parameters[i] = new JavassistParameterInfo(annotationHelper, this, i, parameterTypes[i]);
       }
       catch (NotFoundException e)

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistParameterizedClassInfo.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistParameterizedClassInfo.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistParameterizedClassInfo.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -36,6 +36,7 @@
 import org.jboss.util.JBossStringBuilder;
 
 /**
+ * Delegate class info to handle generic parameterized types in javassist
  * 
  * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
  * @version $Revision: 1.1 $
@@ -49,20 +50,41 @@
    /** The factory */
    private final JavassistTypeInfoFactoryImpl factory;
    
+   /** The javassist generic type arguments */
    private final TypeArgument[] typeArguments;
    
+   /** The generic type argument type infos */
    private volatile TypeInfo[] typeArgumentInfos = ClassInfoImpl.UNKNOWN_TYPES; 
    
-   JavassistParameterizedClassInfo(JavassistTypeInfoFactoryImpl factory, ClassInfo delegate, TypeArgument[] typeArguments)
+   /** Utility to determine the actual bounds of generic type variables */
+   private final JavassistTypeVariableSpy spy;
+   
+   /**
+    * Constructor
+    * 
+    * @param factory the javassist type info factory
+    * @param delegate the class info containing the parameterized type's raw type
+    * @param typeArguments the javassist generic type arguments
+    * @param spy used to determine the actual bounds of generic type variables
+    */
+   JavassistParameterizedClassInfo(JavassistTypeInfoFactoryImpl factory, ClassInfo delegate, TypeArgument[] typeArguments, JavassistTypeVariableSpy spy)
    {
       super(delegate);
       this.factory = factory;
       this.typeArguments = typeArguments;
+      this.spy = spy;
    }
    
+   /**
+    * Constructor
+    * 
+    * @param factory the javassist type info factory
+    * @param delegate the class info containing the parameterized type's raw type
+    * @param typeArgumentInfos the type infos for the type arguments
+    */
    public JavassistParameterizedClassInfo(JavassistTypeInfoFactoryImpl factory, ClassInfo delegate, TypeInfo[] typeArgumentInfos)
    {
-      this(factory, delegate, (TypeArgument[])null);
+      this(factory, delegate, (TypeArgument[])null, null);
       this.typeArgumentInfos = typeArgumentInfos;
    }
    
@@ -80,7 +102,7 @@
          TypeInfo[] infos = new TypeInfo[typeArguments.length];
          for (int i = 0 ; i < typeArguments.length ; i++)
          {
-            infos[i] = factory.createTypeInfoForTypeArgument(typeArguments[i], delegate.getClassLoader());
+            infos[i] = factory.createTypeInfoForTypeArgument(typeArguments[i], delegate.getClassLoader(), spy);
          }
          typeArgumentInfos = infos;
       }
@@ -119,8 +141,7 @@
       {
          CtClass ctClass = ((JavassistTypeInfo)delegate).getCtClass();
          CtClass collection = ctClass.getClassPool().get(target);
-         int index = JavassistHelper.determineInfoIndex(getActualTypeArguments(), ((JavassistTypeInfo)delegate).getCtClass(), collection, parameter);
-         return getActualTypeArguments()[index];
+         return JavassistHelper.determineInfoIndex(getActualTypeArguments(), ((JavassistTypeInfo)delegate).getCtClass(), collection, parameter);
       }
       catch (Exception e1)
       {

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfo.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfo.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfo.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -239,7 +239,7 @@
          if (classSig != null)
          {
             ClassType type = classSig.getSuperClass();
-            genericSuperClass = factory.getParameterizedClassInfo(getClassLoader(), type);
+            genericSuperClass = (ClassInfo)factory.getTypeInfo(getClassLoader(), type, JavassistTypeVariableSpy.createForClass(classSig));
          }
          else
          {
@@ -281,7 +281,7 @@
             ClassType[] types = classSig.getInterfaces();
             for (int i = 0 ; i < types.length ; i++)
             {
-               ClassInfo info = factory.getParameterizedClassInfo(getClassLoader(), types[i]);
+               ClassInfo info = (ClassInfo)factory.getTypeInfo(getClassLoader(), types[i], JavassistTypeVariableSpy.createForClass(classSig));
                if (info instanceof InterfaceInfo == false)
                   throw new IllegalStateException(info + " is not an InterfaceInfo");
                infos[i] = (InterfaceInfo)info; 
@@ -831,7 +831,8 @@
       {
          CtClass collection = ctClass.getClassPool().get(target);
          ClassType type = JavassistHelper.determineType(ctClass, collection, parameter);
-         return factory.getParameterizedClassInfo(getClassLoader(), type);
+         ClassSignature sig = JavassistHelper.getClassSignature(ctClass);
+         return factory.getTypeInfo(getClassLoader(), type, JavassistTypeVariableSpy.createForClass(sig));
       }
       catch (Exception e1)
       {

Modified: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfoFactoryImpl.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfoFactoryImpl.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfoFactoryImpl.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -36,6 +36,9 @@
 import javassist.CtMethod;
 import javassist.CtPrimitiveType;
 import javassist.NotFoundException;
+import javassist.bytecode.SignatureAttribute;
+import javassist.bytecode.SignatureAttribute.ArrayType;
+import javassist.bytecode.SignatureAttribute.BaseType;
 import javassist.bytecode.SignatureAttribute.ClassType;
 import javassist.bytecode.SignatureAttribute.ObjectType;
 import javassist.bytecode.SignatureAttribute.TypeArgument;
@@ -50,6 +53,7 @@
 import org.jboss.reflect.plugins.javassist.classpool.DefaultClassPoolFactory;
 import org.jboss.reflect.spi.AnnotationInfo;
 import org.jboss.reflect.spi.AnnotationValue;
+import org.jboss.reflect.spi.ArrayInfo;
 import org.jboss.reflect.spi.ClassInfo;
 import org.jboss.reflect.spi.DelegateClassInfo;
 import org.jboss.reflect.spi.MutableClassInfo;
@@ -299,7 +303,7 @@
       {
          ClassLoader cl = clazz.getClassLoader();
          if(cl == null)
-            cl = Thread.currentThread().getContextClassLoader();
+            cl = SecurityActions.getContextClassLoader();
          return get(clazz.getName(), cl, clazz);
       }
       catch (ClassNotFoundException e)
@@ -346,7 +350,7 @@
                   {
                      throw new RuntimeException(e);
                   }
-                  number.setDelegate(get(clazz));
+                  number.setDelegate(get(useClass));
                }
                return number;
             }
@@ -369,6 +373,9 @@
       return result;
    }
    
+   /**
+    * Reads the type info from the cache
+    */
    private TypeInfo getFromCache(String name, Map<String, WeakReference<TypeInfo>> classLoaderCache)
    {
       WeakReference<TypeInfo> weak = classLoaderCache.get(name);
@@ -377,22 +384,13 @@
          TypeInfo result = weak.get();
          if (result != null)
          {
-            if (result instanceof JavassistTypeInfo)
+            CtClass clazz = getCtClass(result, false);
+            if (clazz != null)
             {
-               if(compare(((JavassistTypeInfo)result).getCtClass(), (ClassInfo) result))
-                  return result;
-            }
-            else if (result instanceof DelegateClassInfo)
-            {
-               ClassInfo info = ((DelegateClassInfo)result).getDelegate();
-               if (info instanceof JavassistTypeInfo)
-                  if(compare(((JavassistTypeInfo)info).getCtClass(),  info))
+               if (compare(clazz, (ClassInfo)result))
                      return result;
             }
-            else
-            {
-               classLoaderCache.remove(name);
-            }
+            classLoaderCache.remove(name);
          }
       }
       return null;
@@ -504,12 +502,18 @@
    }
 
    
+   /**
+    * Gets the type info for a class
+    * 
+    * @param type the type
+    * @return the type info
+    */
    public TypeInfo getTypeInfo(String name, ClassLoader cl) throws ClassNotFoundException
    {
       if (name == null)
          throw new IllegalArgumentException("Null class name");
       if (cl == null)
-         cl = Thread.currentThread().getContextClassLoader();
+         cl = SecurityActions.getContextClassLoader();
 
       TypeInfo primitive = PrimitiveInfo.valueOf(name);
       if (primitive != null)
@@ -536,6 +540,12 @@
       return getTypeInfo(clazz);
    }
    
+   /**
+    * Gets the type info for a reflect type
+    * 
+    * @param type the type
+    * @return the type info
+    */
    public TypeInfo getTypeInfo(Type type)
    {
       if (type instanceof Class)
@@ -645,6 +655,12 @@
       return new JavassistTypeInfo(this, clazz, null);
    }
 
+   /**
+    * Creates a type info from a reflect generic paramemeterized type
+    * 
+    * @param type the parameterized type
+    * @return the type info
+    */
    protected TypeInfo getParameterizedType(ParameterizedType type)
    {
       
@@ -681,15 +697,47 @@
       return info;
    }
 
-   protected ClassInfo getParameterizedClassInfo(ClassLoader loader, ClassType type)
+   /**
+    * Gets the type info for a javassist type
+    * 
+    * @param loader the class loader
+    * @param type the class type
+    * @param spy used to determine actual types of type variables
+    * @return the type info
+    */
+   protected TypeInfo getTypeInfo(ClassLoader loader, SignatureAttribute.Type type, JavassistTypeVariableSpy spy)
    {
+      if (type instanceof ClassType)
+         return getTypeInfo(loader, (ClassType)type, spy);
+      else if (type instanceof ArrayType)
+         return getGenericArrayType(loader, (ArrayType)type, spy);
+      else if (type instanceof BaseType)
+      {
+         String s = String.valueOf(((BaseType)type).getDescriptor());
+         Class<?> clazz = PrimitiveInfo.getPrimativeArrayComponentType(s);
+         return PrimitiveInfo.valueOf(clazz.getName()); 
+      }
+      
+      throw new IllegalArgumentException("Bad type " + type + " - " + type.getClass().getName());
+   }
+   
+   /**
+    * Gets the type info for a javassist generic class type
+    * 
+    * @param loader the class loader
+    * @param type the class type
+    * @param spy used to determine actual types of type variables
+    * @return the type info
+    */
+   protected TypeInfo getTypeInfo(ClassLoader loader, ClassType type, JavassistTypeVariableSpy spy)
+   {
       //If it is not a parameterized type, just return the type
       boolean isParameterized = type.getTypeArguments() != null && type.getTypeArguments().length > 0;
       if (!isParameterized)
       {
          try
          {
-            return (ClassInfo)get(type.getName(), loader);
+            return get(type.getName(), loader);
          }
          catch (ClassNotFoundException e)
          {
@@ -698,14 +746,14 @@
       }
       
       //Look in the cache first
-      String genericName = getGenericName(type);
+      String genericName = JavassistHelper.getGenericName(type, spy);
       Map<String, WeakReference<TypeInfo>> cache = getClassLoaderCache(loader);
       TypeInfo info = getFromCache(genericName, cache);
       if (info != null)
       {
          if (info instanceof ClassInfo == false)
             throw new IllegalStateException("Not a ClassInfo " + info);
-         return (ClassInfo)info;
+         return info;
       }
       
       //Create the parameterized type info
@@ -714,7 +762,7 @@
          ClassInfo delegate = (ClassInfo)get(type.getName(), loader);
          if (!isParameterized)
             return delegate;
-         info = new JavassistParameterizedClassInfo(this, delegate, type.getTypeArguments());
+         info = new JavassistParameterizedClassInfo(this, delegate, type.getTypeArguments(), spy);
       }
       catch (ClassNotFoundException e)
       {
@@ -724,19 +772,48 @@
       //Cache the parameterized type info
       cache.put(genericName, new WeakReference<TypeInfo>(info));
       
-      return (ClassInfo)info;
+      return info;
    }
    
-   protected TypeInfo createTypeInfoForTypeArgument(TypeArgument arg, ClassLoader loader)
+   /**
+    * Gets the type info for a javassist type argument
+    * 
+    * @param arg the type argument
+    * @param loader the class loader
+    * @param spy used to determine actual types of type variables
+    * @return the type info
+    */
+   protected TypeInfo createTypeInfoForTypeArgument(TypeArgument arg, ClassLoader loader, JavassistTypeVariableSpy spy)
    {
       ObjectType type = arg.getType();
-      if (type instanceof ClassType)
+      if (type == null)
       {
-         return getParameterizedClassInfo(loader, (ClassType) type);
+         try
+         {
+            return get(Object.class.getName(), loader, null);
+         }
+         catch(ClassNotFoundException e)
+         {
+            throw new RuntimeException(e);
+         }
       }
+      else if (type instanceof ClassType)
+      {
+         return getTypeInfo(loader, (ClassType) type, spy);
+      }
+      else if (type instanceof javassist.bytecode.SignatureAttribute.TypeVariable)
+      {
+         return getTypeInfo(loader, spy.getTypeBound((javassist.bytecode.SignatureAttribute.TypeVariable)type), spy);
+      }
       throw new IllegalStateException("Unhandled type " + type);
    }
 
+   /**
+    * Gets the type info for a reflect wildcard type
+    * 
+    * @param type the wildcard type
+    * @return the type info
+    */
    protected TypeInfo getWildcardType(WildcardType type)
    {
       //Create the wildcard type info
@@ -744,52 +821,22 @@
       return getTypeInfo(bound);
    }
    
+   /**
+    * Gets the classloader cache for the passed in classloader. 
+    * 
+    * @param cl the classloader. If null is used, the Thread context classloader will be used instead
+    * @return the cache of type infos by name
+    */
    @Override
    protected Map<String, WeakReference<TypeInfo>> getClassLoaderCache(ClassLoader cl)
    {
       if (cl == null)
-         cl = Thread.currentThread().getContextClassLoader();
+         cl = SecurityActions.getContextClassLoader();
       return super.getClassLoaderCache(cl);
    }
 
-   protected String getGenericName(ObjectType type)
-   {
-      StringBuilder sb = new StringBuilder();
-      appendTypeGenericInfo(type, sb);
-      return sb.toString();
-   }
-   
-   protected void appendTypeGenericInfo(ObjectType type, StringBuilder sb)
-   {
-      if (type instanceof ClassType)
-      {
-         ClassType ctype = (ClassType)type;
-         sb.append(ctype.getName());
-
-         TypeArgument[] arguments = ctype.getTypeArguments();
-         
-         if (arguments != null && arguments.length > 0)
-         {
-            sb.append("<");
-            
-            for (int i = 0 ; i < arguments.length ; i++)
-            {
-               if (i > 0)
-                  sb.append(", ");
-               appendTypeGenericInfo(arguments[i].getType(), sb);
-            }
-            sb.append(">");
-         }
-      }
-      else
-      {
-         //TODO This might need implementing once we test wildcards
-         throw new IllegalArgumentException("Unhandled type " + type.getClass().getName());
-      }
-   }
-   
    /**
-    * Get the information for an array type
+    * Get the type info for a reflect generic array type
     * 
     * @param type the array type
     * @return the info
@@ -808,7 +855,7 @@
       Type compType = type.getGenericComponentType();
       TypeInfo componentType = getTypeInfo(compType);
       
-      String arrayName = getArrayCtClass(componentType);
+      String arrayName = getCtClass(componentType, true).getName();
       CtClass clazz = getCtClass(arrayName + "[]", cl);
       info = new JavassistArrayInfoImpl(this, clazz, null, componentType);
       
@@ -818,25 +865,109 @@
       return info;
    }
 
-   private String getArrayCtClass(TypeInfo componentType)
+   /**
+    * Get the type info for a javassist array type
+    * 
+    * @param cl the classloader
+    * @param type the array type
+    * @param spy used to determine actual types of type variables
+    * @return the type info 
+    */
+   protected ArrayInfo getGenericArrayType(ClassLoader cl, ArrayType type, JavassistTypeVariableSpy spy)
    {
-      if (componentType instanceof JavassistTypeInfo)
-      {
-         if(compare(((JavassistTypeInfo)componentType).getCtClass(), (ClassInfo) componentType))
-            return ((JavassistTypeInfo)componentType).getCtClass().getName();
-      }
-      else if (componentType instanceof DelegateClassInfo)
-      {
-         ClassInfo info = ((DelegateClassInfo)componentType).getDelegate();
-         if (info instanceof JavassistTypeInfo)
-            return ((JavassistTypeInfo)info).getCtClass().getName();
-      }
+      ModifiableArrayType wrapped = new ModifiableArrayType(type);
+      return getGenericArrayType(cl, wrapped, spy);
+   }
+   
+   /**
+    * Recursively get the type info for a javassist array type
+    * 
+    * @param cl the classloader
+    * @param type the array type
+    * @param spy used to determine actual types of type variables
+    * @return the type info 
+    */
+   protected ArrayInfo getGenericArrayType(ClassLoader cl, ModifiableArrayType type, JavassistTypeVariableSpy spy)
+   {
+      //Look in the cache first
+      String genericName = JavassistHelper.getGenericName(type, spy);
+      Map<String, WeakReference<TypeInfo>> cache = getClassLoaderCache(cl);
+      ArrayInfo info = (ArrayInfo)getFromCache(genericName, cache);
+      if (info != null)
+         return info;
+
+      type.decrement();
+      TypeInfo componentType = type.getDimension() > 0 ?
+         getGenericArrayType(cl, type, spy) : getTypeInfo(cl, type.getComponentType(), spy);
       
-      throw new IllegalArgumentException(componentType + " is not a JavassistType info or a JavassistParameterizedType");
+      String arrayName = getCtClass(componentType, true).getName();
+      CtClass clazz = getCtClass(arrayName + "[]", cl);
+      info = new JavassistArrayInfoImpl(this, clazz, null, componentType);
+
+      
+      //Cache the wildcard type info
+      cache.put(genericName, new WeakReference<TypeInfo>(info));
+      
+      return info;
    }
    
+   /**
+    * Gets the CtClass from a TypeInfo if it is a javassist one
+    * 
+    * @param typeInfo the type info
+    * @param error if true and the type can not be determined, throw an error
+    * @return null if the type could not be determined and <code>error</code> is false
+    * @throws IllegalArgumentException if <code>error</code> is true and the type can not be determined
+    */
+   private CtClass getCtClass(TypeInfo typeInfo, boolean error)
+   {
+      if (typeInfo instanceof JavassistTypeInfo)
+         return ((JavassistTypeInfo)typeInfo).getCtClass();
+      else if (typeInfo instanceof DelegateClassInfo)
+         return getCtClass(((DelegateClassInfo) typeInfo).getDelegate(), error);
+
+      if (error)
+         throw new IllegalArgumentException(typeInfo + " is not a JavassistType info or a JavassistParameterizedType");
+      
+      return null; 
+   }
+   
+   /**
+    * Get the type info for a reflect TypeVariable
+    * 
+    * @param type the type variable
+    * @return the type info 
+    * 
+    */
    protected TypeInfo getTypeVariable(TypeVariable<?> type)
    {
       return getTypeInfo(type.getBounds()[0]);
    }
+   
+   /**
+    * Wrapper around {@link ArrayType} to make it easier to 
+    * create the name used to look up the array type infos 
+    * in the cache 
+    */
+   protected static class ModifiableArrayType extends ArrayType
+   {
+      int dims;
+      
+      ModifiableArrayType(ArrayType original)
+      {
+         super(original.getDimension(), original.getComponentType());
+         dims = original.getDimension();
+      }
+      
+      @Override
+      public int getDimension()
+      {
+         return dims;
+      }
+
+      void decrement()
+      {
+         dims--;
+      }
+   }
 }

Added: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeVariableSpy.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeVariableSpy.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeVariableSpy.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,145 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.reflect.plugins.javassist;
+
+import javassist.CtBehavior;
+import javassist.CtClass;
+import javassist.bytecode.SignatureAttribute.ClassSignature;
+import javassist.bytecode.SignatureAttribute.MethodSignature;
+import javassist.bytecode.SignatureAttribute.Type;
+import javassist.bytecode.SignatureAttribute.TypeParameter;
+import javassist.bytecode.SignatureAttribute.TypeVariable;
+
+/**
+ * When a type is of type {@link TypeVariable} this class helps determine what the actual type is
+ * from the signature of the member or the class
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+abstract class JavassistTypeVariableSpy
+{
+   /**
+    * Create a JavassistTypeVariableSpy for a method or constructor
+    * 
+    * @param behavior the CtBehavior of the method or constructor
+    * @param sig the method signature
+    * @return the JavassistTypeVariableSpy
+    */
+   static JavassistTypeVariableSpy createForBehavior(CtBehavior behavior, MethodSignature sig)
+   {
+      return new MethodTypeVariable(behavior.getDeclaringClass(), sig);
+   }
+   
+   /**
+    * Create a JavassistTypeVariableSpy for a class
+    * 
+    * @param sig the class signature of the class
+    * @return the JavassistTypeVariableSpy
+    */
+   static JavassistTypeVariableSpy createForClass(ClassSignature sig)
+   {
+      return new ClassTypeVariable(sig);
+   }
+   
+   /**
+    * Create a JavassistTypeVariableSpy for a field
+    * 
+    * @param sig the class signature of the class containing the field
+    * @return the JavassistTypeVariableSpy
+    */
+   static JavassistTypeVariableSpy createForField(ClassSignature sig)
+   {
+      return new ClassTypeVariable(sig);
+   }
+   
+   /**
+    * Get the actual bound of a type variable
+    * 
+    * @param tv the type variable
+    * @throws IllegalStateException if the type can not be determined. This should only 
+    * happen if the TypeVariable passed in does not belong to the signature used to 
+    * create this JavassistTypeVariableSpy instance
+    */
+   abstract Type getTypeBound(TypeVariable tv);
+   
+   private static Type getTypeFromTypeParameters(TypeVariable tv, TypeParameter[] parameters)
+   {
+      if (parameters == null)
+         return null;
+
+      for (int i = 0 ; i < parameters.length ; i++)
+      {
+         if (parameters[i].getName().equals(tv.getName()))
+            return parameters[i].getClassBound();
+      }
+      
+      return null;
+   }
+   
+   private static class MethodTypeVariable extends JavassistTypeVariableSpy
+   {
+      protected final CtClass clazz;
+      private final MethodSignature sig;
+
+      MethodTypeVariable(CtClass clazz, MethodSignature sig)
+      {
+         this.clazz = clazz;
+         this.sig = sig;
+      }
+
+      @Override
+      Type getTypeBound(TypeVariable tv)
+      {
+         Type type = getTypeFromTypeParameters(tv, sig.getTypeParameters());
+         if (type != null)
+            return type;
+
+         ClassSignature classSig = JavassistHelper.getClassSignature(clazz);
+         type = getTypeFromTypeParameters(tv, classSig.getParameters());
+         if (type != null)
+            return type;
+         
+         throw new IllegalStateException("No type parameter found called " + tv.getName() + " in " + sig + " or in " + classSig);
+      }
+   }
+   
+   private static class ClassTypeVariable extends JavassistTypeVariableSpy
+   {
+      private final ClassSignature sig;
+
+      public ClassTypeVariable(ClassSignature sig)
+      {
+         this.sig = sig;
+      }
+
+      @Override
+      Type getTypeBound(TypeVariable tv)
+      {
+         Type type = getTypeFromTypeParameters(tv, sig.getParameters());
+         if (type != null)
+            return type;
+
+         throw new IllegalStateException("No type parameter found called " + tv.getName() + " in " + sig);
+      }
+   }   
+}

Added: projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/SecurityActions.java
===================================================================
--- projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/SecurityActions.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/javassist/SecurityActions.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,52 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.reflect.plugins.javassist;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+class SecurityActions
+{
+   static ClassLoader getContextClassLoader()
+   {
+      if (System.getSecurityManager() == null)
+         return Thread.currentThread().getContextClassLoader();
+      else
+         return AccessController.doPrivileged(GetContextClassLoaderAction.INSTANCE);
+   }
+   
+   static class GetContextClassLoaderAction implements PrivilegedAction<ClassLoader>
+   {
+      final static GetContextClassLoaderAction INSTANCE = new GetContextClassLoaderAction(); 
+      
+      public ClassLoader run()
+      {
+         return Thread.currentThread().getContextClassLoader();
+      }
+      
+   }
+}

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperClassTypeVariable.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperClassTypeVariable.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperClassTypeVariable.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.classinfo.support;
+
+/**
+ * ClassInfoSuperClass
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class ClassInfoGenericSuperClassTypeVariable<T> extends ClassInfoGenericClass<T>
+{
+}

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperClassTypeVariableBounded.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperClassTypeVariableBounded.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperClassTypeVariableBounded.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.classinfo.support;
+
+/**
+ * ClassInfoSuperClass
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class ClassInfoGenericSuperClassTypeVariableBounded<T extends String> extends ClassInfoGenericClass<T>
+{
+}

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperInterfaceTypeVariable.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperInterfaceTypeVariable.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperInterfaceTypeVariable.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.classinfo.support;
+
+/**
+ * ClassInfoGenericSuperInterfaceEmptyClass.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class ClassInfoGenericSuperInterfaceTypeVariable<T> implements ClassInfoGenericInterface<T>
+{
+}

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperInterfaceTypeVariableBounded.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperInterfaceTypeVariableBounded.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoGenericSuperInterfaceTypeVariableBounded.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,32 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.classinfo.support;
+
+/**
+ * ClassInfoGenericSuperInterfaceEmptyClass.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class ClassInfoGenericSuperInterfaceTypeVariableBounded<T extends String> implements ClassInfoGenericInterface<T>
+{
+}

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoTypeVariable.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoTypeVariable.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoTypeVariable.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,43 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.test.classinfo.support;
+
+import java.util.Collection;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class ClassInfoTypeVariable<E>
+{
+   public Collection<E> genericTypeVariable;
+
+   public <E> ClassInfoTypeVariable(Integer id, Collection<E> collA, Collection<E> collB, Collection<Long> collC)
+   {
+   }
+
+   public Collection<E> genericTypeVariable(Collection<E> collA, Collection<Long> collB)
+   {
+      return null;
+   }
+}

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoTypeVariableBounded.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoTypeVariableBounded.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/support/ClassInfoTypeVariableBounded.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,43 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.test.classinfo.support;
+
+import java.util.Collection;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class ClassInfoTypeVariableBounded<E extends Number>
+{
+   public Collection<E> genericTypeVariableBounded;
+
+   public <E> ClassInfoTypeVariableBounded(Integer id, Collection<E> collA, Collection<E> collB, Collection<Long> collC)
+   {
+   }
+
+   public Collection<E> genericTypeVariableBounded(Collection<E> collA, Collection<Long> collB)
+   {
+      return null;
+   }
+}

Modified: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoGenericClassTest.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoGenericClassTest.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoGenericClassTest.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -24,6 +24,7 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
@@ -68,11 +69,15 @@
 import org.jboss.test.classinfo.support.ClassInfoGenericSuperClassEmptyClass;
 import org.jboss.test.classinfo.support.ClassInfoGenericSuperClassNotGeneric;
 import org.jboss.test.classinfo.support.ClassInfoGenericSuperClassString;
+import org.jboss.test.classinfo.support.ClassInfoGenericSuperClassTypeVariable;
+import org.jboss.test.classinfo.support.ClassInfoGenericSuperClassTypeVariableBounded;
 import org.jboss.test.classinfo.support.ClassInfoGenericSuperInterfaceCollection;
 import org.jboss.test.classinfo.support.ClassInfoGenericSuperInterfaceComplicated;
 import org.jboss.test.classinfo.support.ClassInfoGenericSuperInterfaceEmptyClass;
 import org.jboss.test.classinfo.support.ClassInfoGenericSuperInterfaceNotGeneric;
 import org.jboss.test.classinfo.support.ClassInfoGenericSuperInterfaceString;
+import org.jboss.test.classinfo.support.ClassInfoGenericSuperInterfaceTypeVariable;
+import org.jboss.test.classinfo.support.ClassInfoGenericSuperInterfaceTypeVariableBounded;
 
 
 
@@ -109,6 +114,16 @@
       testGenericSuperClass(ClassInfoGenericSuperClassNotGeneric.class, ClassInfoGenericClass.class, new Class[0]);
    }
    
+   public void testGenericSuperClassTypeVariable()
+   {
+      testGenericSuperClass(ClassInfoGenericSuperClassTypeVariable.class, ClassInfoGenericClass.class, new Class[] {Object.class});
+   }
+   
+   public void testGenericSuperClassTypeVariableBounded()
+   {
+      testGenericSuperClass(ClassInfoGenericSuperClassTypeVariableBounded.class, ClassInfoGenericClass.class, new Class[] {String.class});
+   }
+   
    public void testGenericSuperClassCollection()
    {
       ParameterizedType type = assertInstanceOf(ClassInfoGenericSuperClassCollection.class.getGenericSuperclass(), ParameterizedType.class);
@@ -140,6 +155,16 @@
       testGenericSuperInterface(ClassInfoGenericSuperInterfaceNotGeneric.class, ClassInfoGenericInterface.class, new Class[0]);
    }
    
+   public void testGenericSuperInterfaceEmptyClassTypeVariable()
+   {
+      testGenericSuperInterface(ClassInfoGenericSuperInterfaceTypeVariable.class, ClassInfoGenericInterface.class, new Class[] { Object.class });
+   }
+
+   public void testGenericSuperInterfaceEmptyClassTypeVariableBounded()
+   {
+      testGenericSuperInterface(ClassInfoGenericSuperInterfaceTypeVariableBounded.class, ClassInfoGenericInterface.class, new Class[] { String.class });
+   }
+
    public void testGenericSuperInterfaceCollection()
    {
       Type[] infos = ClassInfoGenericSuperInterfaceCollection.class.getGenericInterfaces();
@@ -759,7 +784,12 @@
          Type[] reflectTypes = superClass.getActualTypeArguments();
          assertEquals(genericTypes.length, reflectTypes.length);
          for (int i = 0 ; i < genericTypes.length ; i++)
-            assertEquals(genericTypes[i], reflectTypes[i]);
+         {
+            if (reflectTypes[i] instanceof TypeVariable)
+               assertEquals(genericTypes[i], ((TypeVariable)reflectTypes[i]).getBounds()[0]);
+            else
+               assertEquals(genericTypes[i], reflectTypes[i]);
+         }
    
          //Compare the classinfo stuff vs raw reflect
          TypeInfoFactory factory = getTypeInfoFactory();
@@ -791,7 +821,12 @@
          Type[] reflectTypes = iface.getActualTypeArguments();
          assertEquals(genericTypes.length, reflectTypes.length);
          for (int i = 0 ; i < genericTypes.length ; i++)
-            assertEquals(genericTypes[i], reflectTypes[i]);
+         {
+            if (reflectTypes[i] instanceof TypeVariable)
+               assertEquals(genericTypes[i], ((TypeVariable)reflectTypes[i]).getBounds()[0]);
+            else
+               assertEquals(genericTypes[i], reflectTypes[i]);
+         }
 
          //Compare the classinfo stuff vs raw reflect
          TypeInfoFactory factory = getTypeInfoFactory();
@@ -832,9 +867,12 @@
          Class<?> typeClass = (Class<?>)reflectType;
          assertEquals(typeClass.getName(), actualType.getName());
       }
+      else if (reflectType instanceof TypeVariable)
+      {
+         assertTypeAgainstRawReflect(((TypeVariable)reflectType).getBounds()[0], actualType);
+      }
       else
       {
-         //We might need to handle wildcards in which case we need to do something here
          fail("Not yet implemented");
       }
    }

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoGenericMembersTest.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoGenericMembersTest.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoGenericMembersTest.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,532 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.test.classinfo.test;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Collection;
+
+import org.jboss.reflect.spi.ArrayInfo;
+import org.jboss.reflect.spi.ClassInfo;
+import org.jboss.reflect.spi.ConstructorInfo;
+import org.jboss.reflect.spi.FieldInfo;
+import org.jboss.reflect.spi.MethodInfo;
+import org.jboss.reflect.spi.TypeInfo;
+import org.jboss.test.classinfo.support.ClassInfoTypeVariable;
+import org.jboss.test.classinfo.support.ClassInfoTypeVariableBounded;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class ClassInfoGenericMembersTest extends AbstractClassInfoTest
+{
+   @SuppressWarnings("unchecked")
+   public Collection notGeneric;
+   
+   public Collection<String> generic;
+   
+   public Collection<?> genericWildcard;
+
+   public Collection<? extends String> genericWildcardUpperBounded;
+
+   public Collection<? super String> genericWildcardLowerBounded;
+   
+   public Collection<String>[] genericArray;
+   
+   public ClassInfoGenericMembersTest(String name)
+   {
+      super(name);
+   }
+   
+   //Todo 
+   //mix primitives and generics, e.g. int someMethod(int, Class<String>)
+   //Test complex things
+
+   @SuppressWarnings("unchecked")
+   public ClassInfoGenericMembersTest(Long id, Collection collA, Collection collB, Collection collC)
+   {
+      super(id.toString());
+   }
+
+   public ClassInfoGenericMembersTest(Short id, Collection<String> collA, Collection<String> collB, Collection<Long> collC)
+   {
+      super(id.toString());
+   }
+   
+   public ClassInfoGenericMembersTest(Boolean id, Collection<?> collA, Collection<?> collB, Collection<Long> collC)
+   {
+      super(id.toString());
+   }
+   
+   public ClassInfoGenericMembersTest(Double id, Collection<? extends String> collA, Collection<? extends String> collB, Collection<Long> collC)
+   {
+      super(id.toString());
+   }
+   
+   public ClassInfoGenericMembersTest(Float id, Collection<? super String> collA, Collection<? super String> collB, Collection<Long> collC)
+   {
+      super(id.toString());
+   }
+   
+   public <E> ClassInfoGenericMembersTest(Integer id, Collection<E> collA, Collection<E> collB, Collection<Long> collC)
+   {
+      super(id.toString());
+   }
+   
+   public <E extends String> ClassInfoGenericMembersTest(Number id, Collection<E> collA, Collection<E> collB, Collection<Long> collC)
+   {
+      super(id.toString());
+   }
+   
+   public ClassInfoGenericMembersTest(System id, Collection<String>[][] collA, Collection<String>[][] collB, Collection<Long>[][] collC)
+   {
+      super(id.toString());
+   }
+   
+   @SuppressWarnings("unchecked")
+   public ClassInfoGenericMembersTest(Runtime id, Collection<String> collA, Collection<String> collB, Collection collC)
+   {
+      super(id.toString());
+   }
+   
+   public ClassInfoGenericMembersTest(Package id, Collection<String> collA, Collection<String> collB, long lng)
+   {
+      super(id.toString());
+   }
+   
+   public void testNotGenericConstructor() throws Throwable
+   {
+      testConstructor(false, Long.class);
+   }
+   
+   public void testGenericConstructor() throws Throwable
+   {
+      testConstructor(true, Short.class);
+   }
+   
+   public void testGenericWildcardConstructor() throws Throwable
+   {
+      testConstructor(true, Boolean.class);
+   }
+   
+   public void testGenericWildcardUpperBoundedConstructor() throws Throwable
+   {
+      testConstructor(true, Double.class);
+   }
+   
+   public void testGenericWildcardLowerBoundedConstructor() throws Throwable
+   {
+      testConstructor(true, Float.class);
+   }
+   
+   public void testGenericTypeVariableUpperBoundedConstructor() throws Throwable
+   {
+      testConstructor(true, Integer.class);
+   }
+   
+   public void testGenericTypeVariableLowerBoundedConstructor() throws Throwable
+   {
+      testConstructor(true, Number.class);
+   }
+   
+   public void testGenericTypeVariableUpperBoundedConstructorTypeFromClass() throws Throwable
+   {
+      testConstructor(true, ClassInfoTypeVariable.class, Integer.class);
+   }
+   
+   public void testGenericTypeVariableLowerBoundedConstructorTypeFromClass() throws Throwable
+   {
+      testConstructor(true, ClassInfoTypeVariableBounded.class, Integer.class);
+   }
+   
+   public void testGenericArrayConstructor() throws Throwable
+   {
+      testConstructor(true, System.class);
+   }
+   
+   public void testMixGenericAndNonGenericConstructor() throws Throwable
+   {
+      testConstructor(true, Runtime.class);
+   }
+   
+   public void testMixGenericAndPrimitivesConstructor() throws Throwable
+   {
+      testConstructor(true, Package.class);
+   }
+   
+   @SuppressWarnings("unchecked")
+   public Collection notGeneric(Collection collA, Collection collB)
+   {
+      return null;
+   }
+
+   public Collection<String> generic(Collection<String> collA, Collection<Long> collB)
+   {
+      return null;
+   }
+   
+   public Collection<?> genericWildcard(Collection<?> collA, Collection<Long> collB)
+   {
+      return null;
+   }
+   
+   public Collection<? extends String> genericWildcardUpperBounded(Collection<? extends String> collA, Collection<Long> collB)
+   {
+      return null;
+   }
+   
+   public Collection<? super String> genericWildcardLowerBounded(Collection<? super String> collA, Collection<Long> collB)
+   {
+      return null;
+   }
+   
+   public <E> Collection<E> genericTypeVariable(Collection<E> collA, Collection<Long> collB)
+   {
+      return null;
+   }
+   
+   public <E extends String> Collection<E> genericTypeVariableBounded(Collection<E> collA, Collection<Long> collB)
+   {
+      return null;
+   }
+   
+   public Collection<String>[] genericArrayMethod(Collection<String>[] collA, Collection<Long>[] collB)
+   {
+      return null;
+   }
+   
+   @SuppressWarnings("unchecked")
+   public Collection<String> mixGenericsAndNonGenerics(Collection<String> collA, Collection collB)
+   {
+      return null;
+   }
+   
+   public Collection<String> mixGenericsAndPrimitives(Collection<String> collA, long l)
+   {
+      return null;
+   }
+   
+   public void testNotGenericMethod() throws Throwable
+   {
+      testMethod(false, "notGeneric");
+   }
+   
+   public void testGenericMethod() throws Throwable
+   {
+      testMethod(true, "generic");
+   }
+   
+   public void testGenericWildcardMethod() throws Throwable
+   {
+      testMethod(true, "genericWildcard");
+   }
+   
+   public void testGenericWildcardUpperBoundedMethod() throws Throwable
+   {
+      testMethod(true, "genericWildcardUpperBounded");
+   }
+   
+   public void testGenericWildcardLowerBoundedMethod() throws Throwable
+   {
+      testMethod(true, "genericWildcardLowerBounded");
+   }
+   
+   public void testGenericTypeVariableMethod() throws Throwable
+   {
+      testMethod(true, "genericTypeVariable");
+   }
+   
+   public void testGenericArrayMethod() throws Throwable
+   {
+      testMethod(true, "genericArrayMethod");
+   }
+   
+   public void testGenericTypeVariableMethodTypeFromClass() throws Throwable
+   {
+      testMethod(true, ClassInfoTypeVariable.class, "genericTypeVariable");
+   }
+   
+   public void testGenericTypeVariableBoundedMethodTypeFromClass() throws Throwable
+   {
+      testMethod(true, ClassInfoTypeVariableBounded.class, "genericTypeVariableBounded");
+   }
+   
+   public void testGenericTypeVariableBoundedMethod() throws Throwable
+   {
+      testMethod(true, "genericTypeVariableBounded");
+   }
+   
+   public void testMixGenericsAndNonGenericsMethod() throws Throwable
+   {
+      testMethod(true, "mixGenericsAndNonGenerics");
+   }
+   
+   public void testMixGenericsAndPrimitivesMethod() throws Throwable
+   {
+      testMethod(true, "mixGenericsAndPrimitives");
+   }
+   
+   public void testNotGenericField() throws Throwable
+   {
+      testField("notGeneric");
+   }
+
+   public void testGenericField() throws Throwable
+   {
+      testField("generic");
+   }
+
+   public void testGenericWildcardField() throws Throwable
+   {
+      testField("genericWildcard");
+   }
+   
+   public void testGenericWildcardUpperBoundedField() throws Throwable
+   {
+      testField("genericWildcardUpperBounded");
+   }
+   
+   public void testGenericWildcardLowerBoundedField() throws Throwable
+   {
+      testField("genericWildcardLowerBounded");
+   }
+   
+   public void testGenericTypeVariableFieldTypeFromClass() throws Throwable
+   {
+      testField(ClassInfoTypeVariable.class, "genericTypeVariable");
+   }
+   
+   public void testGenericTypeVariableBoundedFieldTypeFromClass() throws Throwable
+   {
+      testField(ClassInfoTypeVariableBounded.class, "genericTypeVariableBounded");
+   }
+
+   public void testGenericArrayField() throws Throwable
+   {
+      testField("genericArray");
+   }
+
+   private void testMethod(boolean generic, String name) throws Throwable
+   {
+      testMethod(generic, ClassInfoGenericMembersTest.class, name);
+   }
+   
+   private void testMethod(boolean generic, Class<?> clazz, String name) throws Throwable
+   {
+      ClassInfo info = getClassInfo(clazz);
+      Method m = getMethod(clazz, name);
+      MethodInfo minfo = getMethodInfo(info, name);
+      
+      assertTypeAgainstRawReflect(m.getGenericReturnType(), minfo.getReturnType());
+      
+      Type[] parameterTypes = m.getGenericParameterTypes();
+      TypeInfo[] parameterInfos = minfo.getParameterTypes();
+      assertEquals(parameterTypes.length, parameterInfos.length);
+      for (int i = 0 ; i < parameterTypes.length ; i++)
+      {
+         assertTypeAgainstRawReflect(parameterTypes[i], parameterInfos[i]);
+      }
+      
+      assertEquals(m.getGenericReturnType(), parameterTypes[0]);
+      assertSame(minfo.getReturnType(), parameterInfos[0]);
+
+      if (!generic)
+      {
+         assertEquals(parameterTypes[0], parameterTypes[1]);
+         assertSame(parameterInfos[0], parameterInfos[1]);
+      }
+      else
+      {
+         assertNotSame(parameterInfos[0], parameterInfos[1]);
+      }
+   }
+
+   private void testConstructor(boolean generic, Class<?> id) throws Throwable
+   {
+      testConstructor(generic, ClassInfoGenericMembersTest.class, id);
+   }
+   
+   private void testConstructor(boolean generic, Class<?> clazz, Class<?> id) throws Throwable
+   {
+      ClassInfo info = getClassInfo(clazz);
+      Constructor<?> c = getConstructor(clazz, id);
+      ConstructorInfo cinfo = getConstructorInfo(info, id);
+      
+      Type[] parameterTypes = c.getGenericParameterTypes();
+      TypeInfo[] parameterInfos = cinfo.getParameterTypes();
+      assertEquals(parameterTypes.length, parameterInfos.length);
+      for (int i = 1 ; i < parameterTypes.length ; i++)
+      {
+         assertTypeAgainstRawReflect(parameterTypes[i], parameterInfos[i]);
+      }
+      
+      assertEquals(parameterTypes[1], parameterTypes[2]);
+      assertSame(parameterInfos[1], parameterInfos[2]);
+
+      if (!generic)
+      {
+         assertEquals(parameterTypes[2], parameterTypes[3]);
+         assertSame(parameterInfos[2], parameterInfos[3]);
+      }
+      else
+      {
+         assertNotSame(parameterInfos[2], parameterInfos[3]);
+      }
+   }
+
+   private void testField(String name) throws Throwable
+   {
+      testField(ClassInfoGenericMembersTest.class, name);
+   }
+   
+   private void testField(Class<?> clazz, String name) throws Throwable
+   {
+      ClassInfo info = getClassInfo(clazz);
+      Field f = getField(clazz, name);
+      FieldInfo finfo = getFieldInfo(info, name);
+      
+      assertTypeAgainstRawReflect(f.getGenericType(),  finfo.getType());
+   }
+   
+   protected void assertTypeArgumentsAgainstRawReflect(Type[] reflectTypes, TypeInfo[] actualTypeArguments)
+   {
+      assertEquals(reflectTypes.length, actualTypeArguments.length);
+      for (int i = 0 ; i < reflectTypes.length ; i++)
+      {
+         assertTypeAgainstRawReflect(reflectTypes[i], actualTypeArguments[i]);
+      }
+   }
+
+   protected void assertTypeAgainstRawReflect(Type reflectType, TypeInfo actualType)
+   {
+      if (reflectType instanceof ParameterizedType)
+      {
+         ParameterizedType type = (ParameterizedType)reflectType;
+         Type rawType = type.getRawType();
+         assertTypeAgainstRawReflect(rawType, actualType);
+         
+         assertTypeArgumentsAgainstRawReflect(type.getActualTypeArguments(), ((ClassInfo)actualType).getActualTypeArguments());
+      }
+      else if (reflectType instanceof Class)
+      {
+         Class<?> typeClass = (Class<?>)reflectType;
+         assertEquals(typeClass.getName(), actualType.getName());
+      }
+      else if (reflectType instanceof WildcardType)
+      {
+         WildcardType wtype = (WildcardType)reflectType; 
+         if (wtype.getLowerBounds().length > 0)
+            assertTypeAgainstRawReflect(wtype.getLowerBounds()[0], actualType);
+         else
+            assertTypeAgainstRawReflect(wtype.getUpperBounds()[0], actualType);
+      }
+      else if (reflectType instanceof TypeVariable)
+      {
+         assertTypeAgainstRawReflect(((TypeVariable)reflectType).getBounds()[0], actualType);
+      }
+      else if (reflectType instanceof GenericArrayType)
+      {
+         ArrayInfo array = assertInstanceOf(actualType, ArrayInfo.class);
+         assertTypeAgainstRawReflect(((GenericArrayType)reflectType).getGenericComponentType(), array.getComponentType());
+      }
+      else
+      {
+         //We might need to handle wildcards in which case we need to do something here
+         fail("Not yet implemented " + reflectType);
+      }
+   }
+   
+   private ClassInfo getClassInfo(Class<?> clazz)
+   {
+      TypeInfo info = getTypeInfoFactory().getTypeInfo(clazz);
+      return assertInstanceOf(info, ClassInfo.class);
+   }
+   
+   private Method getMethod(Class<?> clazz, String name) throws Exception
+   {
+      for (Method m : clazz.getMethods())
+      {
+         if (m.getName().equals(name))
+            return m;
+      }
+      throw new IllegalArgumentException("No method called " + name);
+   }
+   
+   private Constructor<?> getConstructor(Class<?> clazz, Class<?> id) throws Exception
+   {
+      for (Constructor<?> c : clazz.getConstructors())
+      {
+         if (c.getParameterTypes()[0].equals(id))
+            return c;
+      }
+      throw new IllegalArgumentException("No constructor");
+   }
+   
+   private Field getField(Class<?> clazz, String name) throws Exception
+   {
+      for (Field f : clazz.getFields())
+      {
+         if (f.getName().equals(name))
+            return f;
+      }
+      throw new IllegalArgumentException("No field called " + name);
+   }
+   
+   private MethodInfo getMethodInfo(ClassInfo classInfo, String name) throws Exception
+   {
+      for (MethodInfo m : classInfo.getDeclaredMethods())
+      {
+         if (m.getName().equals(name))
+            return m;
+      }
+      throw new IllegalArgumentException("No method called " + name);
+   }
+
+   private ConstructorInfo getConstructorInfo(ClassInfo classInfo, Class<?> clazz) throws Exception
+   {
+      for (ConstructorInfo c : classInfo.getDeclaredConstructors())
+      {
+         if (c.getParameterTypes()[0].getName().equals(clazz.getName()))
+            return c;
+      }
+      throw new IllegalArgumentException("No constructor");
+   }
+
+   private FieldInfo getFieldInfo(ClassInfo classInfo, String name) throws Exception
+   {
+      for (FieldInfo f : classInfo.getDeclaredFields())
+      {
+         if (f.getName().equals(name))
+            return f;
+      }
+      throw new IllegalArgumentException("No field called " + name);
+   }
+
+}

Modified: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoTestSuite.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoTestSuite.java	2010-03-19 14:22:56 UTC (rev 102625)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/ClassInfoTestSuite.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -64,6 +64,8 @@
       suite.addTest(JavassistGenericClassUnitTestCase.suite());
       suite.addTest(FieldAccessRestrictionTestCase.suite());
       suite.addTest(MethodAccessRestrictionTestCase.suite());
+      suite.addTest(IntrospectionClassInfoGenericMembersTestCase.suite());
+      suite.addTest(JavassistClassInfoGenericMembersTestCase.suite());
 
       return suite;
    }

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/IntrospectionClassInfoGenericMembersTestCase.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/IntrospectionClassInfoGenericMembersTestCase.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/IntrospectionClassInfoGenericMembersTestCase.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,52 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.test.classinfo.test;
+
+import junit.framework.Test;
+
+import org.jboss.reflect.plugins.introspection.IntrospectionTypeInfoFactory;
+import org.jboss.reflect.spi.TypeInfoFactory;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class IntrospectionClassInfoGenericMembersTestCase extends ClassInfoGenericMembersTest
+{
+   public IntrospectionClassInfoGenericMembersTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return suite(IntrospectionClassInfoGenericMembersTestCase.class);
+   }
+
+   @Override
+   protected TypeInfoFactory getTypeInfoFactory()
+   {
+      return new IntrospectionTypeInfoFactory();
+   }
+
+}

Added: projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/JavassistClassInfoGenericMembersTestCase.java
===================================================================
--- projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/JavassistClassInfoGenericMembersTestCase.java	                        (rev 0)
+++ projects/jboss-reflect/trunk/src/test/java/org/jboss/test/classinfo/test/JavassistClassInfoGenericMembersTestCase.java	2010-03-19 15:02:41 UTC (rev 102626)
@@ -0,0 +1,51 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file in the
+* distribution for a full listing of individual contributors. 
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/ 
+package org.jboss.test.classinfo.test;
+
+import junit.framework.Test;
+
+import org.jboss.reflect.plugins.javassist.JavassistTypeInfoFactory;
+import org.jboss.reflect.spi.TypeInfoFactory;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class JavassistClassInfoGenericMembersTestCase extends ClassInfoGenericMembersTest
+{
+   public JavassistClassInfoGenericMembersTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return suite(JavassistClassInfoGenericMembersTestCase.class);
+   }
+
+   @Override
+   protected TypeInfoFactory getTypeInfoFactory()
+   {
+      return new JavassistTypeInfoFactory();
+   }
+}




More information about the jboss-cvs-commits mailing list