org.jboss.reflect.plugins.ClassInfoImpl Maven / Gradle / Ivy
The newest version!
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.reflect.plugins;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.jboss.reflect.plugins.introspection.IntrospectionTypeInfoFactory;
import org.jboss.reflect.spi.AnnotationValue;
import org.jboss.reflect.spi.ClassInfo;
import org.jboss.reflect.spi.ConstructorInfo;
import org.jboss.reflect.spi.DelegateClassInfo;
import org.jboss.reflect.spi.FieldInfo;
import org.jboss.reflect.spi.InterfaceInfo;
import org.jboss.reflect.spi.MethodInfo;
import org.jboss.reflect.spi.PackageInfo;
import org.jboss.reflect.spi.TypeInfo;
import org.jboss.reflect.spi.TypeInfoFactory;
import org.jboss.util.JBossStringBuilder;
/**
* Class info
*
* TODO JBREFLECT-4 fix the introspection assumption
* @author Bill Burke
* @author Adrian Brock
* @author Ales Justin
*/
public class ClassInfoImpl extends InheritableAnnotationHolder implements ClassInfo
{
/** serialVersionUID */
private static final long serialVersionUID = 3545798779904340792L;
/** Marker for generation */
public static final ClassInfo UNKNOWN_CLASS = new DelegateClassInfo(null, true);
/** Marker for generation */
public static final ClassInfo[] UNKNOWN_CLASSES = new ClassInfo[0];
/** Marker for generation */
public static final TypeInfo UNKNOWN_TYPE = UNKNOWN_CLASS;
/** Marker for generation */
public static final TypeInfo[] UNKNOWN_TYPES = new TypeInfo[0];
/** Marker for generation */
public static final InterfaceInfo[] UNKNOWN_INTERFACES = new InterfaceInfo[0];
/** Marker for generation */
public static final ConstructorInfo[] UNKNOWN_CONSTRUCTORS = new ConstructorInfo[0];
/** Marker for generation */
public static final MethodInfo[] UNKNOWN_METHODS = new MethodInfo[0];
/** Marker for generation */
public static final FieldInfo[] UNKNOWN_FIELDS = new FieldInfo[0];
/** The class name */
protected String name;
/** The class modifiers */
protected int modifiers;
/** The interfaces */
protected InterfaceInfo[] interfaces = UNKNOWN_INTERFACES;
/** The generic interfaces */
protected InterfaceInfo[] genericInterfaces = UNKNOWN_INTERFACES;
/** The methods */
protected MethodInfo[] methods = UNKNOWN_METHODS;
/** The fields */
protected FieldInfo[] fields = UNKNOWN_FIELDS;
/** Field map Map */
protected HashMap fieldMap;
/** The super class */
protected ClassInfo superclass = UNKNOWN_CLASS;
/** The generic super class */
protected ClassInfo genericSuperclass = UNKNOWN_CLASS;
/** The constructor info */
protected ConstructorInfo[] constructors = UNKNOWN_CONSTRUCTORS;
/** The package info */
protected PackageInfo packageInfo;
/** The component type */
private transient TypeInfo componentType = ClassInfoImpl.UNKNOWN_TYPE;
/** The key type */
private transient TypeInfo keyType = ClassInfoImpl.UNKNOWN_TYPE;
/** The key type */
private transient TypeInfo valueType = ClassInfoImpl.UNKNOWN_TYPE;
/** The class info helper */
protected transient ClassInfoHelper classInfoHelper;
/** The type info factory */
protected transient TypeInfoFactory typeInfoFactory;
/** The attachments */
private transient TypeInfoAttachments attachments;
/**
* Create a new abstract ClassInfo.
*/
public ClassInfoImpl()
{
}
/**
* Create a new class info
*
* @param name the class name
*/
public ClassInfoImpl(String name)
{
this.name = name;
}
/**
* Create a new abstract ClassInfo.
*
* @param name the class name
* @param modifiers the class modifiers
*/
public ClassInfoImpl(String name, int modifiers)
{
this.name = name;
this.modifiers = modifiers;
}
/**
* Create a new abstract ClassInfo.
*
* @param name the class name
* @param modifiers the class modifiers
* @param interfaces the interfaces
* @param superclass the super class
*/
public ClassInfoImpl(String name, int modifiers, InterfaceInfo[] interfaces,
ClassInfoImpl superclass)
{
this.name = name;
this.modifiers = modifiers;
this.interfaces = interfaces;
this.superclass = superclass;
}
@Override
public AnnotationValue[] getAnnotations()
{
return getDeclaredAnnotations();
}
@Override
public AnnotationValue getAnnotation(String name)
{
return getDeclaredAnnotation(name);
}
@Override
public boolean isAnnotationPresent(String name)
{
return isDeclaredAnnotationPresent(name);
}
public TypeInfoFactory getTypeInfoFactory()
{
return typeInfoFactory;
}
public void setTypeInfoFactory(TypeInfoFactory typeInfoFactory)
{
this.typeInfoFactory = typeInfoFactory;
}
public void setClassInfoHelper(ClassInfoHelper classInfoHelper)
{
this.classInfoHelper = classInfoHelper;
}
/**
* Find a method
*
* @param methods the methods
* @param name the name
* @param parameters the parameters
* @return the method info
*/
public static MethodInfo findMethod(MethodInfo[] methods, String name, TypeInfo[] parameters)
{
if (methods == null) return null;
for (int i = 0; i < methods.length; i++)
{
if (methods[i].getName().equals(name))
{
final int length = (parameters != null) ? parameters.length : 0;
if (methods[i].getParameterTypes().length == length)
{
boolean ok = true;
for (int j = 0; j < length; j++)
{
if (!parameters[j].equals(methods[i].getParameterTypes()[j]))
{
ok = false;
break;
}
}
if (ok) return methods[i];
}
}
}
return null;
}
/**
* Find a constructor
*
* @param constructors the constructors
* @param parameters the parameters
* @return the constructor info
*/
public static ConstructorInfo findConstructor(ConstructorInfo[] constructors, TypeInfo[] parameters)
{
if (constructors == null) return null;
for (int i = 0; i < constructors.length; i++)
{
final int length = (parameters != null) ? parameters.length : 0;
if (constructors[i].getParameterTypes().length == length)
{
boolean ok = true;
for (int j = 0; j < length; j++)
{
if (!parameters[j].equals(constructors[i].getParameterTypes()[j]))
{
ok = false;
break;
}
}
if (ok) return constructors[i];
}
}
return null;
}
/**
* Get an array class
*
* @param clazz the class
* @return the array class
*/
public static Class> getArrayClass(Class> clazz)
{
return Array.newInstance(clazz, 0).getClass();
}
/**
* Set the type
*
* @param type the class
*/
public void setType(Class> type)
{
setAnnotatedElement(type);
if (type != null)
modifiers = type.getModifiers();
}
/**
* Set the interfaces
*
* @param interfaces the interfaces
*/
public void setInterfaces(InterfaceInfo[] interfaces)
{
this.interfaces = interfaces;
}
/**
* Set the generic interfaces
*
* @param interfaces the interfaces
*/
public void setGenericInterfaces(InterfaceInfo[] interfaces)
{
this.genericInterfaces = interfaces;
}
/**
* Set the declared methods
*
* @param methods the methods
*/
public void setDeclaredMethods(MethodInfoImpl[] methods)
{
this.methods = methods;
if (methods != null)
{
for (int i = 0; i < methods.length; i++)
methods[i].declaringClass = this;
}
}
/**
* Set the declared fields
*
* @param fields the fields
*/
public void setDeclaredFields(FieldInfoImpl[] fields)
{
this.fields = fields;
if (fields != null)
{
fieldMap = new HashMap(fields.length);
for (int i = 0; i < fields.length; ++i)
{
fields[i].declaringClass = this;
fieldMap.put(fields[i].getName(), fields[i]);
}
}
}
/**
* Set the declared constructors
*
* @param constructors the constructors
*/
public void setDeclaredConstructors(ConstructorInfoImpl[] constructors)
{
this.constructors = constructors;
if (constructors != null)
{
for (int i = 0; i < constructors.length; i++)
constructors[i].declaringClass = this;
}
}
/**
* Set the super class
*
* @param superInfo the super class
*/
void setSuperclass(ClassInfo superInfo)
{
this.superclass = superInfo;
}
/**
* Set the generic super class
*
* @param superInfo the super class
*/
public void setGenericSuperclass(ClassInfo superInfo)
{
this.genericSuperclass = superInfo;
}
public boolean isInterface()
{
return false;
}
public InterfaceInfo[] getInterfaces()
{
if (interfaces == UNKNOWN_INTERFACES)
setInterfaces(classInfoHelper.getInterfaces(this));
return interfaces;
}
public InterfaceInfo[] getGenericInterfaces()
{
if (genericInterfaces == UNKNOWN_INTERFACES)
setGenericInterfaces(classInfoHelper.getGenericInterfaces(this));
return genericInterfaces;
}
public MethodInfo getDeclaredMethod(String methodName, TypeInfo... parameters)
{
if (methods == UNKNOWN_METHODS)
setDeclaredMethods(classInfoHelper.getMethods(this));
return findMethod(methods, methodName, parameters);
}
public MethodInfo[] getDeclaredMethods()
{
if (methods == UNKNOWN_METHODS)
setDeclaredMethods(classInfoHelper.getMethods(this));
return methods;
}
public FieldInfo getDeclaredField(String fieldName)
{
if (fields == UNKNOWN_FIELDS)
setDeclaredFields(classInfoHelper.getFields(this));
if (fieldMap == null)
return null;
return fieldMap.get(fieldName);
}
public FieldInfo[] getDeclaredFields()
{
if (fields == UNKNOWN_FIELDS)
setDeclaredFields(classInfoHelper.getFields(this));
return fields;
}
public ConstructorInfo getDeclaredConstructor(TypeInfo... parameters)
{
if (constructors == UNKNOWN_CONSTRUCTORS)
setDeclaredConstructors(classInfoHelper.getConstructors(this));
return findConstructor(constructors, parameters);
}
public ConstructorInfo[] getDeclaredConstructors()
{
if (constructors == UNKNOWN_CONSTRUCTORS)
setDeclaredConstructors(classInfoHelper.getConstructors(this));
return constructors;
}
public ClassInfo getSuperclass()
{
if (superclass == UNKNOWN_CLASS)
setSuperclass(classInfoHelper.getSuperClass(this));
return superclass;
}
public ClassInfo getGenericSuperclass()
{
if (genericSuperclass == UNKNOWN_CLASS)
setGenericSuperclass(classInfoHelper.getGenericSuperClass(this));
return genericSuperclass;
}
public int getModifiers()
{
return modifiers;
}
public boolean isStatic()
{
return Modifier.isStatic(modifiers);
}
public boolean isPublic()
{
return Modifier.isPublic(modifiers);
}
public boolean isVolatile()
{
return Modifier.isVolatile(modifiers);
}
public String getName()
{
return name;
}
public String getSimpleName()
{
return getType().getSimpleName();
}
@Deprecated
public Class extends Object> getType()
{
return (Class extends Object>) annotatedElement;
}
public ClassLoader getClassLoader()
{
return getType().getClassLoader();
}
public Object convertValue(Object value) throws Throwable
{
return ValueConvertor.convertValue(getType(), value);
}
public Object convertValue(Object value, boolean replaceProperties) throws Throwable
{
return ValueConvertor.convertValue(getType(), value, replaceProperties);
}
public Object convertValue(Object value, boolean replaceProperties, boolean trim) throws Throwable
{
return ValueConvertor.convertValue(getType(), value, replaceProperties, trim);
}
public boolean isArray()
{
return getType().isArray();
}
public boolean isCollection()
{
return Collection.class.isAssignableFrom(getType());
}
public boolean isMap()
{
return Map.class.isAssignableFrom(getType());
}
public boolean isAnnotation()
{
return getType().isAnnotation();
}
public boolean isEnum()
{
return getType().isEnum();
}
public boolean isPrimitive()
{
return false;
}
public TypeInfo getArrayType()
{
Class> arrayClass = getArrayClass(getType());
return classInfoHelper.getTypeInfo(arrayClass);
}
@SuppressWarnings("deprecation")
public Object newArrayInstance(int size) throws Throwable
{
if (isArray() == false)
throw new ClassCastException(this + " is not an array.");
return Array.newInstance(getComponentType().getType(), size);
}
@SuppressWarnings("deprecation")
public boolean isAssignableFrom(TypeInfo info)
{
if (info == null)
throw new NullPointerException("Parameter info cannot be null!");
return getType().isAssignableFrom(info.getType());
}
public boolean isInstance(Object object)
{
return getType().isInstance(object);
}
public TypeInfo[] getActualTypeArguments()
{
return UNKNOWN_TYPES;
}
public TypeInfo getOwnerType()
{
return null;
}
public ClassInfo getRawType()
{
return this;
}
public TypeInfo getComponentType()
{
if (componentType == UNKNOWN_TYPE)
componentType = classInfoHelper.getComponentType(this);
return componentType;
}
public TypeInfo getKeyType()
{
if (keyType == UNKNOWN_TYPE)
keyType = classInfoHelper.getKeyType(this);
return keyType;
}
public TypeInfo getValueType()
{
if (valueType == UNKNOWN_TYPE)
valueType = classInfoHelper.getValueType(this);
return valueType;
}
public PackageInfo getPackage()
{
if (packageInfo == null)
packageInfo = classInfoHelper.getPackage(this);
return packageInfo;
}
public void setAttachment(String name, Object attachment)
{
if (name == null)
throw new IllegalArgumentException("Null name");
synchronized (this)
{
if (attachments == null)
{
if (attachment == null)
return;
attachments = new TypeInfoAttachments();
}
}
if (attachment == null)
attachments.removeAttachment(name);
else
attachments.addAttachment(name, attachment);
}
public T getAttachment(Class expectedType)
{
if (expectedType == null)
throw new IllegalArgumentException("Null expectedType");
Object result = getAttachment(expectedType.getName());
if (result == null)
return null;
return expectedType.cast(result);
}
public Object getAttachment(String attachName)
{
if (attachName == null)
throw new IllegalArgumentException("Null name");
synchronized (this)
{
if (attachments == null)
return null;
}
return attachments.getAttachment(attachName);
}
@Override
protected ClassInfo getSuperHolder()
{
return getSuperclass();
}
@Override
protected void toString(JBossStringBuilder buffer)
{
buffer.append("name=").append(getName());
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null || obj instanceof ClassInfo == false)
return false;
final ClassInfo other = (ClassInfo) obj;
String thisName = getName();
if (thisName != null ? thisName.equals(other.getName()) == false : other.getName() != null)
return false;
return true;
}
@Override
public int hashCode()
{
return (name != null ? name.hashCode() : 0);
}
protected Object writeReplace()
{
return new MarshalledClassInfo(getType());
}
public static class MarshalledClassInfo implements Serializable
{
private static final long serialVersionUID = 1L;
Class> type;
public MarshalledClassInfo(Class> type)
{
this.type = type;
}
protected Object readResolve()
{
TypeInfoFactory tif = new IntrospectionTypeInfoFactory();
return tif.getTypeInfo(type);
}
}
public String getTypeVariable()
{
return null;
}
}