[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