|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.reflect.generics.reflectiveObjects; |
|
|
|
import java.lang.annotation.*; |
|
import java.lang.reflect.AnnotatedType; |
|
import java.lang.reflect.Array; |
|
import java.lang.reflect.Constructor; |
|
import java.lang.reflect.GenericDeclaration; |
|
import java.lang.reflect.Member; |
|
import java.lang.reflect.Method; |
|
import java.lang.reflect.Type; |
|
import java.lang.reflect.TypeVariable; |
|
import java.util.LinkedHashMap; |
|
import java.util.Map; |
|
import java.util.Objects; |
|
import sun.reflect.annotation.AnnotationSupport; |
|
import sun.reflect.annotation.TypeAnnotationParser; |
|
import sun.reflect.annotation.AnnotationType; |
|
import sun.reflect.generics.factory.GenericsFactory; |
|
import sun.reflect.generics.tree.FieldTypeSignature; |
|
import sun.reflect.generics.visitor.Reifier; |
|
import sun.reflect.misc.ReflectUtil; |
|
|
|
|
|
|
|
|
|
*/ |
|
public class TypeVariableImpl<D extends GenericDeclaration> |
|
extends LazyReflectiveObjectGenerator implements TypeVariable<D> { |
|
D genericDeclaration; |
|
private String name; |
|
|
|
private Type[] bounds; |
|
|
|
// The ASTs for the bounds. We are required to evaluate the bounds |
|
// lazily, so we store these at least until we are first asked |
|
// for the bounds. This also neatly solves the |
|
// problem with F-bounds - you can't reify them before the formal |
|
|
|
private FieldTypeSignature[] boundASTs; |
|
|
|
|
|
private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs, |
|
GenericsFactory f) { |
|
super(f); |
|
genericDeclaration = decl; |
|
name = n; |
|
boundASTs = bs; |
|
} |
|
|
|
// Accessors |
|
|
|
// accessor for ASTs for bounds. Must not be called after |
|
// bounds have been evaluated, because we might throw the ASTs |
|
|
|
private FieldTypeSignature[] getBoundASTs() { |
|
|
|
assert(bounds == null); |
|
return boundASTs; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static <T extends GenericDeclaration> |
|
TypeVariableImpl<T> make(T decl, String name, |
|
FieldTypeSignature[] bs, |
|
GenericsFactory f) { |
|
|
|
if (!((decl instanceof Class) || |
|
(decl instanceof Method) || |
|
(decl instanceof Constructor))) { |
|
throw new AssertionError("Unexpected kind of GenericDeclaration" + |
|
decl.getClass().toString()); |
|
} |
|
return new TypeVariableImpl<T>(decl, name, bs, f); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Type[] getBounds() { |
|
|
|
if (bounds == null) { |
|
FieldTypeSignature[] fts = getBoundASTs(); |
|
// allocate result array; note that |
|
|
|
Type[] ts = new Type[fts.length]; |
|
|
|
for ( int j = 0; j < fts.length; j++) { |
|
Reifier r = getReifier(); |
|
fts[j].accept(r); |
|
ts[j] = r.getResult(); |
|
} |
|
|
|
bounds = ts; |
|
// could throw away bound ASTs here; thread safety? |
|
} |
|
return bounds.clone(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public D getGenericDeclaration(){ |
|
if (genericDeclaration instanceof Class) |
|
ReflectUtil.checkPackageAccess((Class)genericDeclaration); |
|
else if ((genericDeclaration instanceof Method) || |
|
(genericDeclaration instanceof Constructor)) |
|
ReflectUtil.conservativeCheckMemberAccess((Member)genericDeclaration); |
|
else |
|
throw new AssertionError("Unexpected kind of GenericDeclaration"); |
|
return genericDeclaration; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String getName() { return name; } |
|
|
|
public String toString() {return getName();} |
|
|
|
@Override |
|
public boolean equals(Object o) { |
|
if (o instanceof TypeVariable && |
|
o.getClass() == TypeVariableImpl.class) { |
|
TypeVariable<?> that = (TypeVariable<?>) o; |
|
|
|
GenericDeclaration thatDecl = that.getGenericDeclaration(); |
|
String thatName = that.getName(); |
|
|
|
return Objects.equals(genericDeclaration, thatDecl) && |
|
Objects.equals(name, thatName); |
|
|
|
} else |
|
return false; |
|
} |
|
|
|
@Override |
|
public int hashCode() { |
|
return genericDeclaration.hashCode() ^ name.hashCode(); |
|
} |
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
|
Objects.requireNonNull(annotationClass); |
|
|
|
return (T)mapAnnotations(getAnnotations()).get(annotationClass); |
|
} |
|
|
|
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) { |
|
Objects.requireNonNull(annotationClass); |
|
return getAnnotation(annotationClass); |
|
} |
|
|
|
@Override |
|
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { |
|
Objects.requireNonNull(annotationClass); |
|
return AnnotationSupport.getDirectlyAndIndirectlyPresent(mapAnnotations(getAnnotations()), annotationClass); |
|
} |
|
|
|
@Override |
|
public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) { |
|
Objects.requireNonNull(annotationClass); |
|
return getAnnotationsByType(annotationClass); |
|
} |
|
|
|
public Annotation[] getAnnotations() { |
|
int myIndex = typeVarIndex(); |
|
if (myIndex < 0) |
|
throw new AssertionError("Index must be non-negative."); |
|
return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex); |
|
} |
|
|
|
public Annotation[] getDeclaredAnnotations() { |
|
return getAnnotations(); |
|
} |
|
|
|
public AnnotatedType[] getAnnotatedBounds() { |
|
return TypeAnnotationParser.parseAnnotatedBounds(getBounds(), |
|
getGenericDeclaration(), |
|
typeVarIndex()); |
|
} |
|
|
|
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; |
|
|
|
|
|
private int typeVarIndex() { |
|
TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters(); |
|
int i = -1; |
|
for (TypeVariable<?> v : tVars) { |
|
i++; |
|
if (equals(v)) |
|
return i; |
|
} |
|
return -1; |
|
} |
|
|
|
private static Map<Class<? extends Annotation>, Annotation> mapAnnotations(Annotation[] annos) { |
|
Map<Class<? extends Annotation>, Annotation> result = |
|
new LinkedHashMap<>(); |
|
for (Annotation a : annos) { |
|
Class<? extends Annotation> klass = a.annotationType(); |
|
AnnotationType type = AnnotationType.getInstance(klass); |
|
if (type.retention() == RetentionPolicy.RUNTIME) |
|
if (result.put(klass, a) != null) |
|
throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a); |
|
} |
|
return result; |
|
} |
|
} |