[jboss-cvs] JBossAS SVN: r110312 - in projects/jboss-reflect/branches/Branch_2_2/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
Mon Jan 10 09:01:46 EST 2011


Author: alesj
Date: 2011-01-10 09:01:46 -0500 (Mon, 10 Jan 2011)
New Revision: 110312

Added:
   projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/support/Obligation.java
   projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/support/UML.java
Modified:
   projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/bytecode/BytecodeTypeInfoFactoryImpl.java
   projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/introspection/IntrospectionTypeInfoFactoryImpl.java
   projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfoFactoryImpl.java
   projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/test/AnnotatedClassInfoTest.java
Log:
Port JBREFLECT-139 to 2_2.


Modified: projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/bytecode/BytecodeTypeInfoFactoryImpl.java
===================================================================
--- projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/bytecode/BytecodeTypeInfoFactoryImpl.java	2011-01-10 13:48:09 UTC (rev 110311)
+++ projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/bytecode/BytecodeTypeInfoFactoryImpl.java	2011-01-10 14:01:46 UTC (rev 110312)
@@ -31,6 +31,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -80,6 +81,9 @@
 {
    private final ClassBytesFactory classBytesFactory = AsmClassBytesFactory.INSTANCE;
    
+   /** Tmp invocation results */
+   private static ThreadLocal<Map<ClassBytes, TypeInfo>> results = new ThreadLocal<Map<ClassBytes, TypeInfo>>();
+
    private volatile ClassLoaderFinder finder;
    
    public BytecodeTypeInfoFactoryImpl()
@@ -141,59 +145,92 @@
    
    protected TypeInfo instantiate(String name, ClassBytes classBytes, Class<?> clazz)
    {
-      if (classBytes.getComponentType() != null)
+      boolean start = false;
+      Map<ClassBytes, TypeInfo> tmp = results.get();
+      if (tmp == null)
       {
-         try
-         {
-            TypeInfo componentType = getTypeInfo(classBytes.getComponentType().getTypeInfoName(), classBytes.getClassLoader());
-            //TypeInfo componentType = getTypeInfo(classBytes.getComponentType());
-            return new BytecodeArrayInfoImpl(this, classBytes, clazz, componentType);
-         }
-         catch (ClassNotFoundException e)
-         {
-            throw new RuntimeException(e);
-         }
+         start = true;
+         tmp = new HashMap<ClassBytes, TypeInfo>();
+         results.set(tmp);
       }
-      //TODO handle arrays
 
-      if (classBytes.isAnnotation())
+      // if we return here, it means we're already in a loop,
+      // hence no need to cleanup
+      TypeInfo cached = tmp.get(classBytes);
+      if (cached != null)
+         return cached;
+
+      try
       {
-         BytecodeAnnotationInfo result = new BytecodeAnnotationInfo(this, name, classBytes, clazz);
-         MethodBytes[] methods = classBytes.getDeclaredMethodBytes();
-         AnnotationAttributeImpl[] atttributes = new AnnotationAttributeImpl[methods.length];
-         for (int i = 0 ; i < methods.length ; i++)
+         if (classBytes.getComponentType() != null)
          {
             try
             {
-               atttributes[i] = new AnnotationAttributeImpl(methods[i].getName(), getTypeInfo(SignatureKey.getReturnType(methods[i]), classBytes.getClassLoader()), null);
+               TypeInfo componentType = getTypeInfo(classBytes.getComponentType().getTypeInfoName(), classBytes.getClassLoader());
+               BytecodeArrayInfoImpl arrayInfo = new BytecodeArrayInfoImpl(this, classBytes, clazz, componentType);
+               tmp.put(classBytes, arrayInfo);
+               return arrayInfo;
             }
             catch (ClassNotFoundException e)
             {
-               throw new RuntimeException("Error reading attribute " + methods[i].getName() + " for " + classBytes.getJvmName());
+               throw new RuntimeException(e);
             }
          }
-         result.setAttributes(atttributes);
-         return result;
+         //TODO handle arrays
+         else if (classBytes.isAnnotation())
+         {
+            BytecodeAnnotationInfo result = new BytecodeAnnotationInfo(this, name, classBytes, clazz);
+            tmp.put(classBytes, result);
 
-      }
-      else if (classBytes.isEnum())
-      {
-         BytecodeEnumInfo enumInfo = new BytecodeEnumInfo(this, name, classBytes, clazz);
-         FieldBytes[] fields = classBytes.getDeclaredFieldBytes();
-         List<EnumConstantInfoImpl> constants = new ArrayList<EnumConstantInfoImpl>();
-         for (FieldBytes field : fields)
+            MethodBytes[] methods = classBytes.getDeclaredMethodBytes();
+            AnnotationAttributeImpl[] atttributes = new AnnotationAttributeImpl[methods.length];
+            for (int i = 0 ; i < methods.length ; i++)
+            {
+               try
+               {
+                  atttributes[i] = new AnnotationAttributeImpl(methods[i].getName(), getTypeInfo(SignatureKey.getReturnType(methods[i]), classBytes.getClassLoader()), null);
+               }
+               catch (ClassNotFoundException e)
+               {
+                  throw new RuntimeException("Error reading attribute " + methods[i].getName() + " for " + classBytes.getJvmName());
+               }
+            }
+            result.setAttributes(atttributes);
+
+            return result;
+
+         }
+         else if (classBytes.isEnum())
          {
-            if (field.isEnumConstant())
+            BytecodeEnumInfo enumInfo = new BytecodeEnumInfo(this, name, classBytes, clazz);
+            tmp.put(classBytes, enumInfo);
+
+            FieldBytes[] fields = classBytes.getDeclaredFieldBytes();
+            List<EnumConstantInfoImpl> constants = new ArrayList<EnumConstantInfoImpl>();
+            for (FieldBytes field : fields)
             {
-               AnnotationValue[] annotations = getAnnotations(field);
-               constants.add(new EnumConstantInfoImpl(field.getName(), enumInfo, annotations));
+               if (field.isEnumConstant())
+               {
+                  AnnotationValue[] annotations = getAnnotations(field);
+                  constants.add(new EnumConstantInfoImpl(field.getName(), enumInfo, annotations));
+               }
             }
+            enumInfo.setEnumConstants(constants.toArray(new EnumConstantInfoImpl[constants.size()]));
+
+            return enumInfo;
          }
-         enumInfo.setEnumConstants(constants.toArray(new EnumConstantInfoImpl[constants.size()]));
-         return enumInfo;
+         else
+         {
+            BytecodeTypeInfo typeInfo = new BytecodeTypeInfo(this, name, classBytes, clazz);
+            tmp.put(classBytes, typeInfo);
+            return typeInfo;
+         }
       }
-
-      return new BytecodeTypeInfo(this, name, classBytes, clazz);
+      finally
+      {
+         if (start)
+            results.remove();
+      }
    }
    
 

Modified: projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/introspection/IntrospectionTypeInfoFactoryImpl.java
===================================================================
--- projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/introspection/IntrospectionTypeInfoFactoryImpl.java	2011-01-10 13:48:09 UTC (rev 110311)
+++ projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/introspection/IntrospectionTypeInfoFactoryImpl.java	2011-01-10 14:01:46 UTC (rev 110312)
@@ -22,62 +22,38 @@
 package org.jboss.reflect.plugins.introspection;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.GenericDeclaration;
-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.lang.reflect.*;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.jboss.reflect.plugins.AnnotationAttributeImpl;
-import org.jboss.reflect.plugins.AnnotationHelper;
-import org.jboss.reflect.plugins.AnnotationInfoImpl;
-import org.jboss.reflect.plugins.AnnotationValueFactory;
-import org.jboss.reflect.plugins.ArrayInfoImpl;
-import org.jboss.reflect.plugins.ClassInfoHelper;
-import org.jboss.reflect.plugins.ClassInfoImpl;
-import org.jboss.reflect.plugins.ConstructorInfoImpl;
-import org.jboss.reflect.plugins.EnumConstantInfoImpl;
-import org.jboss.reflect.plugins.EnumInfoImpl;
-import org.jboss.reflect.plugins.FieldInfoImpl;
-import org.jboss.reflect.plugins.GenericsUtil;
-import org.jboss.reflect.plugins.MethodInfoImpl;
-import org.jboss.reflect.plugins.PackageInfoImpl;
-import org.jboss.reflect.plugins.TypeVariableAware;
-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.InterfaceInfo;
-import org.jboss.reflect.spi.NumberInfo;
-import org.jboss.reflect.spi.PrimitiveInfo;
-import org.jboss.reflect.spi.TypeInfo;
-import org.jboss.reflect.spi.TypeInfoFactory;
+import org.jboss.reflect.plugins.*;
+import org.jboss.reflect.spi.*;
 import org.jboss.util.collection.WeakTypeCache;
 
 /**
  * An introspection type factory.
  *
  * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
  */
 public class IntrospectionTypeInfoFactoryImpl extends WeakTypeCache<TypeInfo> implements TypeInfoFactory, AnnotationHelper, ClassInfoHelper
 {
    final static AnnotationValue[] NO_ANNOTATIONS = new AnnotationValue[0];
 
+   /** Tmp invocation results */
+   private static ThreadLocal<Map<Class<?>, TypeInfo>> results = new ThreadLocal<Map<Class<?>, TypeInfo>>();
+
    IntrospectionTypeInfoFactoryImpl()
    {
    }
-   
+
    /**
     * Generate the type info for a class
     *
@@ -162,19 +138,19 @@
             for (int i = 0; i < constructors.length; ++i)
             {
                AnnotationValue[] annotations = getAnnotations(constructors[i]);
-               
+
                Type[] genericParameterTypes = constructors[i].getGenericParameterTypes();
 
                // HACK: This is to workaround a bug in Sun's compiler related to enum constructors
                //       having no generic parameters?
-               Type[] parameterTypes = constructors[i].getParameterTypes(); 
+               Type[] parameterTypes = constructors[i].getParameterTypes();
                if (genericParameterTypes.length != parameterTypes.length)
                   genericParameterTypes = parameterTypes;
 
-               infos[i] = new ReflectConstructorInfoImpl(annotations, 
-                     getTypeInfos(genericParameterTypes), 
-                     getParameterAnnotations(constructors[i].getParameterAnnotations()), 
-                     getClassInfos(constructors[i].getGenericExceptionTypes()), 
+               infos[i] = new ReflectConstructorInfoImpl(annotations,
+                     getTypeInfos(genericParameterTypes),
+                     getParameterAnnotations(readParameterAnnotations(constructors[i])),
+                     getClassInfos(constructors[i].getGenericExceptionTypes()),
                      constructors[i].getModifiers(),
                      (ClassInfo) getTypeInfo(constructors[i].getDeclaringClass()));
             }
@@ -194,15 +170,15 @@
             Field[] fields = getDeclaredFields(clazz);
             if (fields == null || fields.length == 0)
                return null;
-            
+
             ReflectFieldInfoImpl[] infos = new ReflectFieldInfoImpl[fields.length];
             for (int i = 0; i < fields.length; ++i)
             {
                AnnotationValue[] annotations = getAnnotations(fields[i]);
-               infos[i] = new ReflectFieldInfoImpl(annotations, 
-                     fields[i].getName(), 
-                     getTypeInfo(fields[i].getGenericType()), 
-                     fields[i].getModifiers(), 
+               infos[i] = new ReflectFieldInfoImpl(annotations,
+                     fields[i].getName(),
+                     getTypeInfo(fields[i].getGenericType()),
+                     fields[i].getModifiers(),
                      (ClassInfo) getTypeInfo(fields[i].getDeclaringClass()));
             }
 
@@ -227,13 +203,13 @@
             for (int i = 0; i < methods.length; ++i)
             {
                AnnotationValue[] annotations = getAnnotations(methods[i]);
-               infos[i] = new ReflectMethodInfoImpl(annotations, 
-                     methods[i].getName(), 
+               infos[i] = new ReflectMethodInfoImpl(annotations,
+                     methods[i].getName(),
                      getTypeInfo(methods[i].getGenericReturnType()),
-                     getTypeInfos(methods[i].getGenericParameterTypes()), 
-                     getParameterAnnotations(methods[i].getParameterAnnotations()), 
-                     getClassInfos(methods[i].getGenericExceptionTypes()), 
-                     methods[i].getModifiers(), 
+                     getTypeInfos(methods[i].getGenericParameterTypes()),
+                     getParameterAnnotations(readParameterAnnotations(methods[i])),
+                     getClassInfos(methods[i].getGenericExceptionTypes()),
+                     methods[i].getModifiers(),
                      (ClassInfo) getTypeInfo(methods[i].getDeclaringClass()));
                infos[i].setMethod(methods[i]);
             }
@@ -416,7 +392,7 @@
 
    /**
     * Get the information for an array type
-    * 
+    *
     * @param type the array type
     * @return the info
     */
@@ -430,14 +406,14 @@
       TypeInfo info = cache.get(genericName);
       if (info != null)
          return info;
-      
+
       //Create the wildcard type info
       TypeInfo raw = getTypeInfo(type.getGenericComponentType());
       info = new ArrayInfoImpl(raw);
 
       //Cache the wildcard type info
       cache.put(genericName, info);
-      
+
       return info;
    }
 
@@ -462,57 +438,98 @@
    @Override
    protected TypeInfo instantiate(Class<?> clazz)
    {
-      ClassInfoImpl result;
-      if (clazz.isArray())
+      boolean start = false;
+      Map<Class<?>, TypeInfo> tmp = results.get();
+      if (tmp == null)
       {
-         TypeInfo componentType = getTypeInfo(clazz.getComponentType());
-         result = new ArrayInfoImpl(componentType);
+         start = true;
+         tmp = new HashMap<Class<?>, TypeInfo>();
+         results.set(tmp);
       }
-      else if (clazz.isEnum())
+
+      // if we return here, it means we're already in a loop,
+      // hence no need to cleanup
+      TypeInfo cached = tmp.get(clazz);
+      if (cached != null)
+         return cached;
+
+      try
       {
-         EnumInfoImpl enumInfoImpl = new EnumInfoImpl(clazz.getName(), clazz.getModifiers());
-         result = enumInfoImpl;
-         Field[] fields = clazz.getFields();
-         
-         List<EnumConstantInfoImpl> constants = new ArrayList<EnumConstantInfoImpl>();
-         for (Field field : fields)
+         ClassInfoImpl result;
+         if (clazz.isArray())
          {
-            if (field.isEnumConstant())
+            TypeInfo componentType = getTypeInfo(clazz.getComponentType());
+            result = new ArrayInfoImpl(componentType);
+            init(result, clazz);
+         }
+         else if (clazz.isEnum())
+         {
+            EnumInfoImpl enumInfoImpl = new EnumInfoImpl(clazz.getName(), clazz.getModifiers());
+            result = enumInfoImpl;
+            init(result, clazz);
+
+            Field[] fields = clazz.getFields();
+            List<EnumConstantInfoImpl> constants = new ArrayList<EnumConstantInfoImpl>();
+            for (Field field : fields)
             {
-               AnnotationValue[] annotations = getAnnotations(field);
-               constants.add(new EnumConstantInfoImpl(field.getName(), enumInfoImpl, annotations));
+               if (field.isEnumConstant())
+               {
+                  AnnotationValue[] annotations = getAnnotations(field);
+                  constants.add(new EnumConstantInfoImpl(field.getName(), enumInfoImpl, annotations));
+               }
             }
+            enumInfoImpl.setEnumConstants(constants.toArray(new EnumConstantInfoImpl[constants.size()]));
          }
-         enumInfoImpl.setEnumConstants(constants.toArray(new EnumConstantInfoImpl[constants.size()]));
-      }
-      else if (clazz.isAnnotation())
-      {
-         result = new AnnotationInfoImpl(clazz.getName(), clazz.getModifiers());
-         Method[] methods = getDeclaredMethods(clazz);
-         AnnotationAttributeImpl[] atttributes = new AnnotationAttributeImpl[methods.length];
-         for (int i = 0 ; i < methods.length ; i++)
+         else if (clazz.isAnnotation())
          {
-            atttributes[i] = new AnnotationAttributeImpl(methods[i].getName(), getTypeInfo(methods[i].getReturnType()), null);
+            result = new AnnotationInfoImpl(clazz.getName(), clazz.getModifiers());
+            init(result, clazz);
+
+            Method[] methods = getDeclaredMethods(clazz);
+            AnnotationAttributeImpl[] atttributes = new AnnotationAttributeImpl[methods.length];
+            for (int i = 0 ; i < methods.length ; i++)
+            {
+               atttributes[i] = new AnnotationAttributeImpl(methods[i].getName(), getTypeInfo(methods[i].getReturnType()), null);
+            }
+            ((AnnotationInfoImpl)result).setAttributes(atttributes);
          }
-         ((AnnotationInfoImpl)result).setAttributes(atttributes);
+         else
+         {
+            result = new ReflectClassInfoImpl(clazz.getName());
+            init(result, clazz);
+         }
+
+         return result;
       }
-      else
+      finally
       {
-         result = new ReflectClassInfoImpl(clazz.getName());
+         if (start)
+            results.remove();
       }
+   }
+
+   /**
+    * Initialize default configuration.
+    *
+    * @param result the result
+    * @param clazz the class
+    */
+   private void init(ClassInfoImpl result, Class<?> clazz)
+   {
+      Map<Class<?>, TypeInfo> tmp = results.get();
+      tmp.put(clazz, result);
+
       result.setType(clazz);
       result.setTypeInfoFactory(this);
       result.setClassInfoHelper(this);
       result.setAnnotationHelper(this);
-      return result;
    }
 
-   
    /**
     * Overrides the {@link WeakTypeCache#getParameterizedType(ParameterizedType)}
     * method so that parameterized types are not cached when getTypeInfo(Type) is called
     * with a ParameterizedType with no information about the classloader.
-    * 
+    *
     * @param type the parameterized type
     * @return the parameterized type info
     */
@@ -540,7 +557,7 @@
       return info;
    }
 
-   
+
    @Override
    protected void generate(Class<?> clazz, TypeInfo result)
    {
@@ -606,22 +623,67 @@
 
    private Annotation[] readAnnotations(final AnnotatedElement ao)
    {
-      if (System.getSecurityManager() == null)
-         return ao.getAnnotations();
-      else
+      try
       {
-         PrivilegedAction<Annotation[]> action = new PrivilegedAction<Annotation[]>()
+         if (System.getSecurityManager() == null)
+            return ao.getAnnotations();
+         else
          {
-            public Annotation[] run()
+            try
             {
-               return ao.getAnnotations();
+               PrivilegedExceptionAction<Annotation[]> action = new PrivilegedExceptionAction<Annotation[]>()
+               {
+                  public Annotation[] run()
+                  {
+                     return ao.getAnnotations();
+                  }
+               };
+
+               return AccessController.doPrivileged(action);
             }
-         };
-         
-         return AccessController.doPrivileged(action);
+            catch (PrivilegedActionException e)
+            {
+               throw e.getCause();
+            }
+         }
       }
+      catch (Throwable e)
+      {
+         throw new RuntimeException("Could not read annotations for " + ao, e);
+      }
    }
 
+   private Annotation[][] readParameterAnnotations(final Method method)
+   {
+      try
+      {
+         return method.getParameterAnnotations();
+      }
+      catch (Exception e)
+      {
+         handleReadParameterAnnotationsFailure(method, e);
+         return null;
+      }
+   }
+
+   private Annotation[][] readParameterAnnotations(final Constructor<?> constructor)
+   {
+      try
+      {
+         return constructor.getParameterAnnotations();
+      }
+      catch (Exception e)
+      {
+         handleReadParameterAnnotationsFailure(constructor, e);
+         return null;
+      }
+   }
+
+   private void handleReadParameterAnnotationsFailure(Member m, Throwable t)
+   {
+      throw new RuntimeException("Could not read parameter annotations for " + m, t);
+   }
+
    protected AnnotationValue[][] getParameterAnnotations(Annotation[][] annotations)
    {
       AnnotationValue[][] annotationValues = new AnnotationValue[annotations.length][];
@@ -643,38 +705,38 @@
       Type[] types = type.getActualTypeArguments();
       if (types == null)
          return null;
-      
+
       TypeInfo[] result = new TypeInfo[types.length];
       for (int i = 0; i < types.length; ++i)
          result[i] = getTypeInfo(types[i]);
-      
+
       return result;
    }
-   
+
    public TypeInfo getOwnerType(ParameterizedClassInfo classInfo)
    {
       ParameterizedType type = classInfo.parameterizedType;
       Type owner = type.getOwnerType();
       if (owner == null)
          return null;
-      
+
       return getTypeInfo(owner);
    }
-   
+
    public TypeInfo getComponentType(ClassInfo classInfo)
    {
       if (classInfo.isCollection() == false)
          return null;
       return findActualType(classInfo, Collection.class, 0);
    }
-   
+
    public TypeInfo getKeyType(ClassInfo classInfo)
    {
       if (classInfo.isMap() == false)
          return null;
       return findActualType(classInfo, Map.class, 0);
    }
-   
+
    public TypeInfo getValueType(ClassInfo classInfo)
    {
       if (classInfo.isMap() == false)
@@ -714,7 +776,7 @@
             return parameterized.getActualTypeArguments()[parameter];
          }
       }
-      
+
       Type[] interfaces = clazz.getGenericInterfaces();
       for (Type intf : interfaces)
       {
@@ -749,7 +811,7 @@
          result = getParameter(clazz, type, (TypeVariable) result);
       return result;
    }
-   
+
    private static Type getParameter(Class<?> clazz, Type type, TypeVariable<?> variable)
    {
       TypeVariable<?>[] variables = clazz.getTypeParameters();
@@ -783,7 +845,7 @@
       Class<?> rawType = (Class<?>) type.getRawType();
       ClassLoader cl = SecurityActions.getClassLoader(rawType);
       Map<String, TypeInfo> classLoaderCache = getClassLoaderCache(cl);
-      
+
       synchronized (classLoaderCache)
       {
          return classLoaderCache.get(GenericsUtil.getGenericName(type));

Modified: projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfoFactoryImpl.java
===================================================================
--- projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfoFactoryImpl.java	2011-01-10 13:48:09 UTC (rev 110311)
+++ projects/jboss-reflect/branches/Branch_2_2/src/main/java/org/jboss/reflect/plugins/javassist/JavassistTypeInfoFactoryImpl.java	2011-01-10 14:01:46 UTC (rev 110312)
@@ -31,16 +31,19 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.CtField;
-import javassist.CtMember;
-import javassist.CtMethod;
-import javassist.CtPrimitiveType;
-import javassist.Modifier;
+import org.jboss.reflect.plugins.*;
+import org.jboss.reflect.plugins.introspection.IntrospectionTypeInfoFactory;
+import org.jboss.reflect.plugins.javassist.classpool.ClassPoolFactory;
+import org.jboss.reflect.plugins.javassist.classpool.DefaultClassPoolFactory;
+import org.jboss.reflect.spi.*;
+import org.jboss.util.JBossStringBuilder;
+import org.jboss.util.collection.WeakClassCache;
+
+import javassist.*;
 import javassist.NotFoundException;
 import javassist.bytecode.Descriptor;
 import javassist.bytecode.SignatureAttribute;
@@ -50,34 +53,12 @@
 import javassist.bytecode.SignatureAttribute.ObjectType;
 import javassist.bytecode.SignatureAttribute.TypeArgument;
 
-import org.jboss.reflect.plugins.AnnotationAttributeImpl;
-import org.jboss.reflect.plugins.AnnotationHelper;
-import org.jboss.reflect.plugins.AnnotationValueFactory;
-import org.jboss.reflect.plugins.AnnotationValueImpl;
-import org.jboss.reflect.plugins.EnumConstantInfoImpl;
-import org.jboss.reflect.plugins.GenericsUtil;
-import org.jboss.reflect.plugins.TypeVariableAware;
-import org.jboss.reflect.plugins.introspection.IntrospectionTypeInfoFactory;
-import org.jboss.reflect.plugins.javassist.classpool.ClassPoolFactory;
-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;
-import org.jboss.reflect.spi.MutableTypeInfoFactory;
-import org.jboss.reflect.spi.NumberInfo;
-import org.jboss.reflect.spi.PrimitiveInfo;
-import org.jboss.reflect.spi.TypeInfo;
-import org.jboss.util.JBossStringBuilder;
-import org.jboss.util.collection.WeakClassCache;
-
 /**
  * A javassist type factory.
  * TODO: need to fix the cl stuff
  *
  * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
  *
  * @version $Revision$
  */
@@ -85,20 +66,23 @@
 {
    private static ClassPoolFactory poolFactory = DefaultClassPoolFactory.getInstance();
 
+   /** Tmp invocation results */
+   private static ThreadLocal<Map<CtClass, TypeInfo>> results = new ThreadLocal<Map<CtClass, TypeInfo>>();
+
    JavassistTypeInfoFactoryImpl()
    {
    }
-   
+
    public static ClassPoolFactory getPoolFactory()
    {
       return poolFactory;
    }
-   
+
    public static void setPoolFactory(ClassPoolFactory classPoolFactory)
    {
       poolFactory = classPoolFactory;
    }
-   
+
    static final AnnotationValue[] NO_ANNOTATIONS = new AnnotationValue[0];
    /**
     * Raise NoClassDefFoundError for javassist not found
@@ -170,20 +154,38 @@
       CtClass ctClass = getCtClass(clazz.getName(), clazz.getClassLoader());
       return instantiate(ctClass, clazz);
    }
-   
+
    protected TypeInfo instantiate(CtClass ctClass, Class<?> clazz)
    {
+      boolean start = false;
+      Map<CtClass, TypeInfo> tmp = results.get();
+      if (tmp == null)
+      {
+         start = true;
+         tmp = new HashMap<CtClass, TypeInfo>();
+         results.set(tmp);
+      }
+
+      // if we return here, it means we're already in a loop,
+      // hence no need to cleanup
+      TypeInfo cached = tmp.get(ctClass);
+      if (cached != null)
+         return cached;
+
       try
       {
          if (ctClass.isArray())
          {
             TypeInfo componentType = getTypeInfo(ctClass.getComponentType());
-            return new JavassistArrayInfoImpl(this, ctClass, clazz, componentType);
+            TypeInfo result = new JavassistArrayInfoImpl(this, ctClass, clazz, componentType);
+            tmp.put(ctClass, result);
+            return result;
          }
-
-         if (ctClass.isAnnotation())
+         else if (ctClass.isAnnotation())
          {
             JavassistAnnotationInfo result = new JavassistAnnotationInfo(this, ctClass, clazz);
+            tmp.put(ctClass, result);
+
             CtMethod[] methods = ctClass.getDeclaredMethods();
             AnnotationAttributeImpl[] atttributes = new AnnotationAttributeImpl[methods.length];
             for (int i = 0 ; i < methods.length ; i++)
@@ -191,12 +193,14 @@
                atttributes[i] = new AnnotationAttributeImpl(methods[i].getName(), getTypeInfo(methods[i].getReturnType()), null);
             }
             result.setAttributes(atttributes);
+
             return result;
-
          }
          else if (ctClass.isEnum())
          {
             JavassistEnumInfo enumInfo = new JavassistEnumInfo(this, ctClass, clazz);
+            tmp.put(ctClass, enumInfo);
+
             CtField[] fields = ctClass.getFields();
             List<EnumConstantInfoImpl> constants = new ArrayList<EnumConstantInfoImpl>();
             for (CtField field : fields)
@@ -208,17 +212,27 @@
                }
             }
             enumInfo.setEnumConstants(constants.toArray(new EnumConstantInfoImpl[constants.size()]));
+
             return enumInfo;
          }
-
-         return new JavassistTypeInfo(this, ctClass, clazz);
+         else
+         {
+            TypeInfo result = new JavassistTypeInfo(this, ctClass, clazz);
+            tmp.put(ctClass, result);
+            return result;
+         }
       }
       catch (NotFoundException e)
       {
          throw new RuntimeException(e);
       }
+      finally
+      {
+         if (start)
+            results.remove();
+      }
    }
-   
+
    /**
     * Get the type info
     *
@@ -297,7 +311,7 @@
          throw raiseClassNotFound(name, e);
       }
    }
-   
+
    /**
     * Gets the CtClass corresponding to {@code name} by using the bootstrap class pool.
     *
@@ -324,11 +338,11 @@
       return get(clazz);
    }
 
-   
+
    /**
     * Gets the type info for a class
-    * 
-    * @param type the type
+    *
+    * @param name the type
     * @return the type info
     */
    public TypeInfo getTypeInfo(String name, ClassLoader cl) throws ClassNotFoundException
@@ -340,10 +354,10 @@
 
       return get(name, cl);
    }
-   
+
    /**
     * Gets the type info for a reflect type
-    * 
+    *
     * @param type the type
     * @return the type info
     */
@@ -365,7 +379,7 @@
 
    /**
     * Get the information for a class
-    * 
+    *
     * @param name the name
     * @param cl the classloader
     * @return the info
@@ -379,8 +393,8 @@
 
    /**
     * Get the information for a class
-    * 
-    * 
+    *
+    *
     * @param clazz the class
     * @return the info
     */
@@ -403,7 +417,7 @@
 
    /**
     * Get the information for a class
-    * 
+    *
     * @param name the name
     * @param cl the classloader
     * @param clazz the class
@@ -416,22 +430,21 @@
          throw new IllegalArgumentException("Null name");
       if (cl == null)
          throw new IllegalArgumentException("Null classloader");
-   
+
       return get(null, clazz, name, cl, true);
    }
 
    /**
     * Get the information for a class
-    * 
+    *
     * @param ctClass the class
-    * @param clazz the class
     * @return the info
     */
    protected TypeInfo get(CtClass ctClass)
    {
       if (ctClass == null)
          throw new IllegalArgumentException("Null class");
-   
+
       try
       {
          return get(ctClass, null, ctClass.getName(), ctClass.getClassPool().getClassLoader(), false);
@@ -444,7 +457,7 @@
 
    /**
     * Get the information for a class
-    * 
+    *
     * @param ctClass the class, may be null
     * @param clazz the class, may be null
     * @param name the name of the class
@@ -458,7 +471,7 @@
          throw new IllegalArgumentException("Null name");
       if (cl == null)
          throw new IllegalArgumentException("Null class loader");
-      
+
       TypeInfo primitive = PrimitiveInfo.valueOf(name);
       if (primitive != null)
          return primitive;
@@ -489,16 +502,16 @@
             }
          }
       }
-      
+
       //Handle array names
       if (name.charAt(0) == '[')
          name = Descriptor.toClassName(name);
-      
+
       Map<String, WeakReference<TypeInfo>> classLoaderCache = getClassLoaderCache(cl);
       TypeInfo result = getFromCache(name, classLoaderCache);
       if (result != null)
          return result;
-      
+
       boolean changedCache = false;
       try
       {
@@ -533,24 +546,24 @@
          if (realLoader != cl)
             classLoaderCache = getClassLoaderCache(realLoader);
       }
-         
+
       WeakReference<TypeInfo>weak = new WeakReference<TypeInfo>(result);
       classLoaderCache.put(name, weak);
-      
+
 //      we just ignore generate(..) since it doesnt do anything atm
 //      generate(clazz, result);
-      
+
       return result;
    }
-   
+
    private ClassLoader getClassLoader(final TypeInfo info)
    {
       if (System.getSecurityManager() == null)
          return info.getClassLoader();
-      
+
       if (info instanceof JavassistTypeInfo)
          return ((JavassistTypeInfo)info).getClassLoaderInternal();
-      
+
       return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
       {
          public ClassLoader run()
@@ -565,10 +578,10 @@
     * <ul>
     * <li>JDK dynamic proxies</li>
     * <li>javassist ProxyFactory proxies - created by calling ClassLoader.defineClass()</li>
-    * </ul> 
+    * </ul>
     * are not visible to the javassist classpools, and neither will classes generated by cglib or other
     * frameworks, so try to load up the class from the reflect implementation.
-    * 
+    *
     * @param cl the classloader
     * @param name the name of the class
     * @return the info
@@ -577,44 +590,44 @@
    private TypeInfo delegateToIntrospectionImplementation(ClassLoader cl, String name) throws ClassNotFoundException
    {
 //      System.out.println("======> " + name + " " + cl);
-//      
+//
 //      //Extra code just for debugging
 //      ClassPool pool = poolFactory.getPoolForLoader(cl);
 //      try
 //      {
-//         CtClass ct = pool.get(name); 
+//         CtClass ct = pool.get(name);
 //      }
 //      catch(Exception alreadyHandled)
 //      {
 //         System.out.println("---> Not found in " + pool);
 //      }
-//      
+//
 //      Class<?> clazz = cl.loadClass(name);
 //      System.out.println("---> Loaded real class from " + clazz.getClassLoader());
-//      
+//
 //      try
 //      {
-//         CtClass ct = pool.get(name); 
+//         CtClass ct = pool.get(name);
 //      }
 //      catch(Exception alreadyHandled)
 //      {
 //         System.out.println("---> Not found again in " + pool);
 //      }
-//      
+//
 //      pool = poolFactory.getPoolForLoader(clazz.getClassLoader());
 //      try
 //      {
-//         CtClass ct = pool.get(name); 
+//         CtClass ct = pool.get(name);
 //         System.out.println("---> Found in actual pool " + pool);
 //      }
 //      catch(Exception alreadyHandled)
 //      {
 //         System.out.println("---> Not found in actual pool " + pool);
 //      }
-//      
+//
 
       //Extra code - END
-      
+
       try
       {
          IntrospectionTypeInfoFactory factory = new IntrospectionTypeInfoFactory();
@@ -625,10 +638,10 @@
          throw e;
       }
    }
-   
+
    /**
     * Reads the type info from the cache
-    * 
+    *
     * @param name the class name
     * @param classLoaderCache The cached type infos for the loader
     */
@@ -681,7 +694,7 @@
          for (int i = 0 ; i < annotations.length ; i++)
          {
             Class<?> clazz = ((Annotation)annotations[i]).annotationType();
-            
+
             AnnotationInfo info = (AnnotationInfo)getTypeInfo(clazz);
             annotationValues[i] = AnnotationValueFactory.createAnnotationValue(this, this, info, annotations[i]);
          }
@@ -689,7 +702,7 @@
       }
       catch (Throwable t)
       {
-         throw new RuntimeException(t);
+         throw new RuntimeException("Could not read annotations for " + (obj instanceof CtClass ? ((CtClass)obj).getName() : obj.toString()), t);
       }
    }
 
@@ -697,8 +710,8 @@
    {
       return AnnotationValueFactory.createAnnotationValue(this, this, info, ann);
    }
-   
 
+
    private boolean compare(CtClass clazz, ClassInfo info)
    {
       if(clazz.getDeclaredMethods().length == info.getDeclaredMethods().length &&
@@ -749,7 +762,7 @@
 
    /**
     * Creates a type info from a reflect generic paramemeterized type
-    * 
+    *
     * @param type the parameterized type
     * @return the type info
     */
@@ -759,13 +772,13 @@
       Class<?> rawType = (Class<?>) type.getRawType();
       ClassInfo raw = (ClassInfo)getTypeInfo(rawType);
       Type[] types = type.getActualTypeArguments();
-      
+
       return new JavassistParameterizedClassInfo(this, raw, types);
    }
 
    /**
     * 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
@@ -781,7 +794,7 @@
       {
          String s = String.valueOf(((BaseType)type).getDescriptor());
          Class<?> clazz = PrimitiveInfo.getPrimativeArrayComponentType(s);
-         return PrimitiveInfo.valueOf(clazz.getName()); 
+         return PrimitiveInfo.valueOf(clazz.getName());
       }
       else if (type instanceof javassist.bytecode.SignatureAttribute.TypeVariable)
       {
@@ -790,16 +803,15 @@
             ((TypeVariableAware)typeInfo).setTypeVariable(((javassist.bytecode.SignatureAttribute.TypeVariable)type).getName());
          return typeInfo;
       }
-      
+
       //Should not happen
       throw new IllegalArgumentException("Bad type " + type + " - " + type.getClass().getName());
    }
-   
+
    /**
     * Gets the type info for a javassist generic class type
-    * 
+    *
     * @param loader the class loader of the raw class
-    * @param parameterloaders the class of the
     * @param type the class type
     * @param spy used to determine actual types of type variables
     * @return the type info
@@ -819,7 +831,7 @@
             throw new IllegalStateException(e);
          }
       }
-      
+
       //Look in the cache first
       String genericName = JavassistHelper.getGenericName(type, spy);
       Map<String, WeakReference<TypeInfo>> cache = getClassLoaderCache(loader);
@@ -830,7 +842,7 @@
             throw new IllegalStateException("Not a ClassInfo " + info);
          return info;
       }
-      
+
       //Create the parameterized type info
       try
       {
@@ -846,13 +858,13 @@
 
       //Cache the parameterized type info
       cache.put(genericName, new WeakReference<TypeInfo>(info));
-      
+
       return info;
    }
-   
+
    /**
     * 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
@@ -885,7 +897,7 @@
 
    /**
     * Gets the type info for a reflect wildcard type
-    * 
+    *
     * @param type the wildcard type
     * @return the type info
     */
@@ -895,10 +907,10 @@
       Type bound = type.getLowerBounds().length > 0 ? type.getLowerBounds()[0] : type.getUpperBounds()[0];
       return getTypeInfo(bound);
    }
-   
+
    /**
-    * Gets the classloader cache for the passed in classloader. 
-    * 
+    * 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
     */
@@ -912,7 +924,7 @@
 
    /**
     * Get the type info for a reflect generic array type
-    * 
+    *
     * @param type the array type
     * @return the info
     */
@@ -925,42 +937,42 @@
       TypeInfo info = getFromCache(genericName, cache);
       if (info != null)
          return info;
-      
+
       //Create the wildcard type info
       Type compType = type.getGenericComponentType();
       TypeInfo componentType = getTypeInfo(compType);
-      
+
       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;
    }
 
    /**
     * 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 
+    * @return the type info
     */
    protected ArrayInfo getGenericArrayType(ClassLoader cl, ArrayType type, JavassistTypeVariableSpy spy)
    {
       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 
+    * @return the type info
     */
    protected ArrayInfo getGenericArrayType(ClassLoader cl, ModifiableArrayType type, JavassistTypeVariableSpy spy)
    {
@@ -974,21 +986,21 @@
       type.decrement();
       TypeInfo componentType = type.getDimension() > 0 ?
          getGenericArrayType(cl, type, spy) : getTypeInfo(cl, type.getComponentType(), spy);
-      
+
       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
@@ -1005,10 +1017,10 @@
 
       if (error)
          throw new IllegalArgumentException(typeInfo + " is not a JavassistType info, a PrimitiveTypeInfo or a JavassistParameterizedType");
-      
-      return null; 
+
+      return null;
    }
-   
+
    private CtClass getPrimitiveCtClass(String name)
    {
       try
@@ -1020,34 +1032,34 @@
          throw new IllegalStateException("Could not find primitive called " + name, e);
       }
    }
-   
+
    /**
     * Get the type info for a reflect TypeVariable
-    * 
+    *
     * @param type the type variable
-    * @return the type info 
-    * 
+    * @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 
+    * 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()
       {

Added: projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/support/Obligation.java
===================================================================
--- projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/support/Obligation.java	                        (rev 0)
+++ projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/support/Obligation.java	2011-01-10 14:01:46 UTC (rev 110312)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, 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;
+
+/**
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+ at UML(identifier="MD_ObligationCode")
+public enum Obligation
+{
+   CONDITIONAL,
+   @UML(identifier="optional", obligation=CONDITIONAL)
+   OPTIONAL,
+   @UML(identifier="mandatory", obligation=CONDITIONAL)
+   MANDATORY,
+   FORBIDDEN
+}

Added: projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/support/UML.java
===================================================================
--- projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/support/UML.java	                        (rev 0)
+++ projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/support/UML.java	2011-01-10 14:01:46 UTC (rev 110312)
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, 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.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+ at Documented
+ at Retention(RUNTIME)
+ at Target({TYPE, FIELD, METHOD})
+public @interface UML
+{
+   String identifier();
+
+   Obligation obligation() default Obligation.MANDATORY;
+}

Modified: projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/test/AnnotatedClassInfoTest.java
===================================================================
--- projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/test/AnnotatedClassInfoTest.java	2011-01-10 13:48:09 UTC (rev 110311)
+++ projects/jboss-reflect/branches/Branch_2_2/src/test/java/org/jboss/test/classinfo/test/AnnotatedClassInfoTest.java	2011-01-10 14:01:46 UTC (rev 110312)
@@ -44,25 +44,7 @@
 import org.jboss.reflect.spi.TypeInfoFactory;
 import org.jboss.reflect.spi.Value;
 import org.jboss.test.ContainerTest;
-import org.jboss.test.classinfo.support.AnnotatedClass;
-import org.jboss.test.classinfo.support.AnnotatedClassHierarchyWithInheritedAnnotations;
-import org.jboss.test.classinfo.support.AnnotatedClassHierarchyWithNotInheritedAnnotations;
-import org.jboss.test.classinfo.support.AnnotatedClassHierarchyWithNotInheritedAnnotations2;
-import org.jboss.test.classinfo.support.AnnotatedSubClass;
-import org.jboss.test.classinfo.support.AnnotationWithClass;
-import org.jboss.test.classinfo.support.AnotherAnnotation;
-import org.jboss.test.classinfo.support.ClassWithAnnotationWithClass;
-import org.jboss.test.classinfo.support.ClassWithAnnotationWithClassArray;
-import org.jboss.test.classinfo.support.ClassWithAnnotationWithInterfaceArray;
-import org.jboss.test.classinfo.support.ClassWithAnnotationWithPrimitiveClass;
-import org.jboss.test.classinfo.support.ComplexAnnotation;
-import org.jboss.test.classinfo.support.ExpectedAnnotations;
-import org.jboss.test.classinfo.support.JDK14ExpectedAnnotations;
-import org.jboss.test.classinfo.support.JDK50ExpectedAnnotations;
-import org.jboss.test.classinfo.support.NoAnnotationsBean;
-import org.jboss.test.classinfo.support.SimpleAnnotation;
-import org.jboss.test.classinfo.support.TestEnum;
-import org.jboss.test.classinfo.support.ValueAnnotation;
+import org.jboss.test.classinfo.support.*;
 
 /**
  * 
@@ -385,6 +367,14 @@
       checkAnnotations(infoC, AnnotatedClassHierarchyWithInheritedAnnotations.Test1.class, AnnotatedClassHierarchyWithInheritedAnnotations.Test2.class);
    }
 
+   public void testCycle() throws Throwable
+   {
+      ClassInfo info = getClassInfo(UML.class);
+      Annotation[] annotations = info.getUnderlyingAnnotations();
+      assertNotNull(annotations);
+      assertEquals(3, annotations.length);
+   }
+
    private void checkNoAnnotations(AnnotatedInfo info)
    {
       assertNull(info.getAnnotation("x"));



More information about the jboss-cvs-commits mailing list