META-INF.modules.java.base.classes.sun.reflect.annotation.AnnotatedTypeFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java.base Show documentation
Show all versions of java.base Show documentation
Bytecoder java.base Module
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.reflect.annotation;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static sun.reflect.annotation.TypeAnnotation.*;
public final class AnnotatedTypeFactory {
/**
* Create an AnnotatedType.
*
* @param type the type this AnnotatedType corresponds to
* @param currentLoc the location this AnnotatedType corresponds to
* @param actualTypeAnnos the type annotations this AnnotatedType has
* @param allOnSameTarget all type annotation on the same TypeAnnotationTarget
* as the AnnotatedType being built
* @param decl the declaration having the type use this AnnotatedType
* corresponds to
*/
public static AnnotatedType buildAnnotatedType(Type type,
LocationInfo currentLoc,
TypeAnnotation[] actualTypeAnnos,
TypeAnnotation[] allOnSameTarget,
AnnotatedElement decl) {
if (type == null) {
return EMPTY_ANNOTATED_TYPE;
}
if (isArray(type))
return new AnnotatedArrayTypeImpl(type,
currentLoc,
actualTypeAnnos,
allOnSameTarget,
decl);
if (type instanceof Class) {
return new AnnotatedTypeBaseImpl(type,
currentLoc,
actualTypeAnnos,
allOnSameTarget,
decl);
} else if (type instanceof TypeVariable) {
return new AnnotatedTypeVariableImpl((TypeVariable)type,
currentLoc,
actualTypeAnnos,
allOnSameTarget,
decl);
} else if (type instanceof ParameterizedType) {
return new AnnotatedParameterizedTypeImpl((ParameterizedType)type,
currentLoc,
actualTypeAnnos,
allOnSameTarget,
decl);
} else if (type instanceof WildcardType) {
return new AnnotatedWildcardTypeImpl((WildcardType) type,
currentLoc,
actualTypeAnnos,
allOnSameTarget,
decl);
}
throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen.");
}
public static LocationInfo nestingForType(Type type, LocationInfo addTo) {
if (isArray(type))
return addTo;
if (type instanceof Class) {
Class clz = (Class)type;
if (clz.getEnclosingClass() == null)
return addTo;
if (Modifier.isStatic(clz.getModifiers()))
return nestingForType(clz.getEnclosingClass(), addTo);
return nestingForType(clz.getEnclosingClass(), addTo.pushInner());
} else if (type instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType)type;
if (t.getOwnerType() == null)
return addTo;
return nestingForType(t.getOwnerType(), addTo.pushInner());
}
return addTo;
}
private static boolean isArray(Type t) {
if (t instanceof Class) {
Class c = (Class)t;
if (c.isArray())
return true;
} else if (t instanceof GenericArrayType) {
return true;
}
return false;
}
static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0];
static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION,
EMPTY_TYPE_ANNOTATION_ARRAY, EMPTY_TYPE_ANNOTATION_ARRAY, null);
static final AnnotatedType[] EMPTY_ANNOTATED_TYPE_ARRAY = new AnnotatedType[0];
private static class AnnotatedTypeBaseImpl implements AnnotatedType {
private final Type type;
private final AnnotatedElement decl;
private final LocationInfo location;
private final TypeAnnotation[] allOnSameTargetTypeAnnotations;
private final Map, Annotation> annotations;
AnnotatedTypeBaseImpl(Type type, LocationInfo location,
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
AnnotatedElement decl) {
this.type = type;
this.decl = decl;
this.location = location;
this.allOnSameTargetTypeAnnotations = allOnSameTargetTypeAnnotations;
this.annotations = TypeAnnotationParser.mapTypeAnnotations(location.filter(actualTypeAnnotations));
}
// AnnotatedElement
@Override
public final Annotation[] getAnnotations() {
return getDeclaredAnnotations();
}
@Override
public final T getAnnotation(Class annotation) {
return getDeclaredAnnotation(annotation);
}
@Override
public final T[] getAnnotationsByType(Class annotation) {
return getDeclaredAnnotationsByType(annotation);
}
@Override
public final Annotation[] getDeclaredAnnotations() {
return annotations.values().toArray(new Annotation[0]);
}
@Override
@SuppressWarnings("unchecked")
public final T getDeclaredAnnotation(Class annotation) {
return (T)annotations.get(annotation);
}
@Override
public final T[] getDeclaredAnnotationsByType(Class annotation) {
return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotations, annotation);
}
// AnnotatedType
@Override
public final Type getType() {
return type;
}
@Override
public AnnotatedType getAnnotatedOwnerType() {
if (!(type instanceof Class))
throw new IllegalStateException("Can't compute owner");
Class inner = (Class)type;
Class owner = inner.getDeclaringClass();
if (owner == null) // top-level, local or anonymous
return null;
if (inner.isPrimitive() || inner == Void.TYPE)
return null;
LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
TypeAnnotation[]all = getTypeAnnotations();
List l = new ArrayList<>(all.length);
for (TypeAnnotation t : all)
if (t.getLocationInfo().isSameLocationInfo(outerLoc))
l.add(t);
return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
}
// Implementation details
final LocationInfo getLocation() {
return location;
}
final TypeAnnotation[] getTypeAnnotations() {
return allOnSameTargetTypeAnnotations;
}
final AnnotatedElement getDecl() {
return decl;
}
}
private static final class AnnotatedArrayTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedArrayType {
AnnotatedArrayTypeImpl(Type type, LocationInfo location,
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
AnnotatedElement decl) {
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
}
@Override
public AnnotatedType getAnnotatedGenericComponentType() {
Type t = getComponentType();
return AnnotatedTypeFactory.buildAnnotatedType(t,
nestingForType(t, getLocation().pushArray()),
getTypeAnnotations(),
getTypeAnnotations(),
getDecl());
}
@Override
public AnnotatedType getAnnotatedOwnerType() {
return null;
}
private Type getComponentType() {
Type t = getType();
if (t instanceof Class) {
Class c = (Class)t;
return c.getComponentType();
}
return ((GenericArrayType)t).getGenericComponentType();
}
}
private static final class AnnotatedTypeVariableImpl extends AnnotatedTypeBaseImpl implements AnnotatedTypeVariable {
AnnotatedTypeVariableImpl(TypeVariable type, LocationInfo location,
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
AnnotatedElement decl) {
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
}
@Override
public AnnotatedType[] getAnnotatedBounds() {
return getTypeVariable().getAnnotatedBounds();
}
@Override
public AnnotatedType getAnnotatedOwnerType() {
return null;
}
private TypeVariable getTypeVariable() {
return (TypeVariable)getType();
}
}
private static final class AnnotatedParameterizedTypeImpl extends AnnotatedTypeBaseImpl
implements AnnotatedParameterizedType {
AnnotatedParameterizedTypeImpl(ParameterizedType type, LocationInfo location,
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
AnnotatedElement decl) {
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
}
@Override
public AnnotatedType[] getAnnotatedActualTypeArguments() {
Type[] arguments = getParameterizedType().getActualTypeArguments();
AnnotatedType[] res = new AnnotatedType[arguments.length];
Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
int initialCapacity = getTypeAnnotations().length;
for (int i = 0; i < res.length; i++) {
List l = new ArrayList<>(initialCapacity);
LocationInfo newLoc = nestingForType(arguments[i], getLocation().pushTypeArg((byte)i));
for (TypeAnnotation t : getTypeAnnotations())
if (t.getLocationInfo().isSameLocationInfo(newLoc))
l.add(t);
res[i] = buildAnnotatedType(arguments[i],
newLoc,
l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
getTypeAnnotations(),
getDecl());
}
return res;
}
@Override
public AnnotatedType getAnnotatedOwnerType() {
Type owner = getParameterizedType().getOwnerType();
if (owner == null)
return null;
LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
TypeAnnotation[]all = getTypeAnnotations();
List l = new ArrayList<>(all.length);
for (TypeAnnotation t : all)
if (t.getLocationInfo().isSameLocationInfo(outerLoc))
l.add(t);
return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
}
private ParameterizedType getParameterizedType() {
return (ParameterizedType)getType();
}
}
private static final class AnnotatedWildcardTypeImpl extends AnnotatedTypeBaseImpl implements AnnotatedWildcardType {
private final boolean hasUpperBounds;
AnnotatedWildcardTypeImpl(WildcardType type, LocationInfo location,
TypeAnnotation[] actualTypeAnnotations, TypeAnnotation[] allOnSameTargetTypeAnnotations,
AnnotatedElement decl) {
super(type, location, actualTypeAnnotations, allOnSameTargetTypeAnnotations, decl);
hasUpperBounds = (type.getLowerBounds().length == 0);
}
@Override
public AnnotatedType[] getAnnotatedUpperBounds() {
if (!hasUpperBounds()) {
return new AnnotatedType[] { buildAnnotatedType(Object.class,
LocationInfo.BASE_LOCATION,
EMPTY_TYPE_ANNOTATION_ARRAY,
EMPTY_TYPE_ANNOTATION_ARRAY,
null)
};
}
return getAnnotatedBounds(getWildcardType().getUpperBounds());
}
@Override
public AnnotatedType[] getAnnotatedLowerBounds() {
if (hasUpperBounds)
return new AnnotatedType[0];
return getAnnotatedBounds(getWildcardType().getLowerBounds());
}
@Override
public AnnotatedType getAnnotatedOwnerType() {
return null;
}
private AnnotatedType[] getAnnotatedBounds(Type[] bounds) {
AnnotatedType[] res = new AnnotatedType[bounds.length];
Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
int initialCapacity = getTypeAnnotations().length;
for (int i = 0; i < res.length; i++) {
LocationInfo newLoc = nestingForType(bounds[i], getLocation().pushWildcard());
List l = new ArrayList<>(initialCapacity);
for (TypeAnnotation t : getTypeAnnotations())
if (t.getLocationInfo().isSameLocationInfo(newLoc))
l.add(t);
res[i] = buildAnnotatedType(bounds[i],
newLoc,
l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
getTypeAnnotations(),
getDecl());
}
return res;
}
private WildcardType getWildcardType() {
return (WildcardType)getType();
}
private boolean hasUpperBounds() {
return hasUpperBounds;
}
}
}