8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,382 @@
/*
* 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<Class <? extends Annotation>, 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 extends Annotation> T getAnnotation(Class<T> annotation) {
return getDeclaredAnnotation(annotation);
}
@Override
public final <T extends Annotation> T[] getAnnotationsByType(Class<T> annotation) {
return getDeclaredAnnotationsByType(annotation);
}
@Override
public final Annotation[] getDeclaredAnnotations() {
return annotations.values().toArray(new Annotation[0]);
}
@Override
@SuppressWarnings("unchecked")
public final <T extends Annotation> T getDeclaredAnnotation(Class<T> annotation) {
return (T)annotations.get(annotation);
}
@Override
public final <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> 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<TypeAnnotation> 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<TypeAnnotation> 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<TypeAnnotation> 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<TypeAnnotation> 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;
}
}
}

View file

@ -0,0 +1,634 @@
/*
* Copyright (c) 2003, 2016, 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.io.ObjectInputStream;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.io.Serializable;
import java.util.*;
import java.util.stream.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* InvocationHandler for dynamic proxy implementation of Annotation.
*
* @author Josh Bloch
* @since 1.5
*/
class AnnotationInvocationHandler implements InvocationHandler, Serializable {
private static final long serialVersionUID = 6182022883658399397L;
private final Class<? extends Annotation> type;
private final Map<String, Object> memberValues;
AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) {
Class<?>[] superInterfaces = type.getInterfaces();
if (!type.isAnnotation() ||
superInterfaces.length != 1 ||
superInterfaces[0] != java.lang.annotation.Annotation.class)
throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type.");
this.type = type;
this.memberValues = memberValues;
}
public Object invoke(Object proxy, Method method, Object[] args) {
String member = method.getName();
Class<?>[] paramTypes = method.getParameterTypes();
// Handle Object and Annotation methods
if (member.equals("equals") && paramTypes.length == 1 &&
paramTypes[0] == Object.class)
return equalsImpl(proxy, args[0]);
if (paramTypes.length != 0)
throw new AssertionError("Too many parameters for an annotation method");
switch(member) {
case "toString":
return toStringImpl();
case "hashCode":
return hashCodeImpl();
case "annotationType":
return type;
}
// Handle annotation member accessors
Object result = memberValues.get(member);
if (result == null)
throw new IncompleteAnnotationException(type, member);
if (result instanceof ExceptionProxy)
throw ((ExceptionProxy) result).generateException();
if (result.getClass().isArray() && Array.getLength(result) != 0)
result = cloneArray(result);
return result;
}
/**
* This method, which clones its array argument, would not be necessary
* if Cloneable had a public clone method.
*/
private Object cloneArray(Object array) {
Class<?> type = array.getClass();
if (type == byte[].class) {
byte[] byteArray = (byte[])array;
return byteArray.clone();
}
if (type == char[].class) {
char[] charArray = (char[])array;
return charArray.clone();
}
if (type == double[].class) {
double[] doubleArray = (double[])array;
return doubleArray.clone();
}
if (type == float[].class) {
float[] floatArray = (float[])array;
return floatArray.clone();
}
if (type == int[].class) {
int[] intArray = (int[])array;
return intArray.clone();
}
if (type == long[].class) {
long[] longArray = (long[])array;
return longArray.clone();
}
if (type == short[].class) {
short[] shortArray = (short[])array;
return shortArray.clone();
}
if (type == boolean[].class) {
boolean[] booleanArray = (boolean[])array;
return booleanArray.clone();
}
Object[] objectArray = (Object[])array;
return objectArray.clone();
}
/**
* Implementation of dynamicProxy.toString()
*/
private String toStringImpl() {
StringBuilder result = new StringBuilder(128);
result.append('@');
result.append(type.getName());
result.append('(');
boolean firstMember = true;
for (Map.Entry<String, Object> e : memberValues.entrySet()) {
if (firstMember)
firstMember = false;
else
result.append(", ");
result.append(e.getKey());
result.append('=');
result.append(memberValueToString(e.getValue()));
}
result.append(')');
return result.toString();
}
/**
* Translates a member value (in "dynamic proxy return form") into a string.
*/
private static String memberValueToString(Object value) {
Class<?> type = value.getClass();
if (!type.isArray()) {
// primitive value, string, class, enum const, or annotation
if (type == Class.class)
return toSourceString((Class<?>) value);
else if (type == String.class)
return toSourceString((String) value);
if (type == Character.class)
return toSourceString((char) value);
else if (type == Double.class)
return toSourceString((double) value);
else if (type == Float.class)
return toSourceString((float) value);
else if (type == Long.class)
return toSourceString((long) value);
else
return value.toString();
} else {
Stream<String> stringStream;
if (type == byte[].class)
stringStream = convert((byte[]) value);
else if (type == char[].class)
stringStream = convert((char[]) value);
else if (type == double[].class)
stringStream = DoubleStream.of((double[]) value)
.mapToObj(AnnotationInvocationHandler::toSourceString);
else if (type == float[].class)
stringStream = convert((float[]) value);
else if (type == int[].class)
stringStream = IntStream.of((int[]) value).mapToObj(String::valueOf);
else if (type == long[].class) {
stringStream = LongStream.of((long[]) value)
.mapToObj(AnnotationInvocationHandler::toSourceString);
} else if (type == short[].class)
stringStream = convert((short[]) value);
else if (type == boolean[].class)
stringStream = convert((boolean[]) value);
else if (type == Class[].class)
stringStream =
Arrays.stream((Class<?>[]) value).
map(AnnotationInvocationHandler::toSourceString);
else if (type == String[].class)
stringStream =
Arrays.stream((String[])value).
map(AnnotationInvocationHandler::toSourceString);
else
stringStream = Arrays.stream((Object[])value).map(Objects::toString);
return stringStreamToString(stringStream);
}
}
/**
* Translates a Class value to a form suitable for use in the
* string representation of an annotation.
*/
private static String toSourceString(Class<?> clazz) {
Class<?> finalComponent = clazz;
StringBuilder arrayBackets = new StringBuilder();
while(finalComponent.isArray()) {
finalComponent = finalComponent.getComponentType();
arrayBackets.append("[]");
}
return finalComponent.getName() + arrayBackets.toString() + ".class" ;
}
private static String toSourceString(float f) {
if (Float.isFinite(f))
return Float.toString(f) + "f" ;
else {
if (Float.isInfinite(f)) {
return (f < 0.0f) ? "-1.0f/0.0f": "1.0f/0.0f";
} else
return "0.0f/0.0f";
}
}
private static String toSourceString(double d) {
if (Double.isFinite(d))
return Double.toString(d);
else {
if (Double.isInfinite(d)) {
return (d < 0.0f) ? "-1.0/0.0": "1.0/0.0";
} else
return "0.0/0.0";
}
}
private static String toSourceString(char c) {
StringBuilder sb = new StringBuilder(4);
sb.append('\'');
if (c == '\'')
sb.append("\\'");
else
sb.append(c);
return sb.append('\'')
.toString();
}
private static String toSourceString(long ell) {
String str = String.valueOf(ell);
return (ell < Integer.MIN_VALUE || ell > Integer.MAX_VALUE)
? (str + 'L') : str;
}
/**
* Return a string suitable for use in the string representation
* of an annotation.
*/
private static String toSourceString(String s) {
StringBuilder sb = new StringBuilder();
sb.append('"');
// Escape embedded quote characters, if present, but don't do
// anything more heroic.
sb.append(s.replace("\"", "\\\""));
sb.append('"');
return sb.toString();
}
private static Stream<String> convert(byte[] values) {
List<String> list = new ArrayList<>(values.length);
for (byte b : values)
list.add(Byte.toString(b));
return list.stream();
}
private static Stream<String> convert(char[] values) {
List<String> list = new ArrayList<>(values.length);
for (char c : values)
list.add(toSourceString(c));
return list.stream();
}
private static Stream<String> convert(float[] values) {
List<String> list = new ArrayList<>(values.length);
for (float f : values) {
list.add(toSourceString(f));
}
return list.stream();
}
private static Stream<String> convert(short[] values) {
List<String> list = new ArrayList<>(values.length);
for (short s : values)
list.add(Short.toString(s));
return list.stream();
}
private static Stream<String> convert(boolean[] values) {
List<String> list = new ArrayList<>(values.length);
for (boolean b : values)
list.add(Boolean.toString(b));
return list.stream();
}
private static String stringStreamToString(Stream<String> stream) {
return stream.collect(Collectors.joining(", ", "{", "}"));
}
/**
* Implementation of dynamicProxy.equals(Object o)
*/
private Boolean equalsImpl(Object proxy, Object o) {
if (o == proxy)
return true;
if (!type.isInstance(o))
return false;
for (Method memberMethod : getMemberMethods()) {
String member = memberMethod.getName();
Object ourValue = memberValues.get(member);
Object hisValue = null;
AnnotationInvocationHandler hisHandler = asOneOfUs(o);
if (hisHandler != null) {
hisValue = hisHandler.memberValues.get(member);
} else {
try {
hisValue = memberMethod.invoke(o);
} catch (InvocationTargetException e) {
return false;
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
if (!memberValueEquals(ourValue, hisValue))
return false;
}
return true;
}
/**
* Returns an object's invocation handler if that object is a dynamic
* proxy with a handler of type AnnotationInvocationHandler.
* Returns null otherwise.
*/
private AnnotationInvocationHandler asOneOfUs(Object o) {
if (Proxy.isProxyClass(o.getClass())) {
InvocationHandler handler = Proxy.getInvocationHandler(o);
if (handler instanceof AnnotationInvocationHandler)
return (AnnotationInvocationHandler) handler;
}
return null;
}
/**
* Returns true iff the two member values in "dynamic proxy return form"
* are equal using the appropriate equality function depending on the
* member type. The two values will be of the same type unless one of
* the containing annotations is ill-formed. If one of the containing
* annotations is ill-formed, this method will return false unless the
* two members are identical object references.
*/
private static boolean memberValueEquals(Object v1, Object v2) {
Class<?> type = v1.getClass();
// Check for primitive, string, class, enum const, annotation,
// or ExceptionProxy
if (!type.isArray())
return v1.equals(v2);
// Check for array of string, class, enum const, annotation,
// or ExceptionProxy
if (v1 instanceof Object[] && v2 instanceof Object[])
return Arrays.equals((Object[]) v1, (Object[]) v2);
// Check for ill formed annotation(s)
if (v2.getClass() != type)
return false;
// Deal with array of primitives
if (type == byte[].class)
return Arrays.equals((byte[]) v1, (byte[]) v2);
if (type == char[].class)
return Arrays.equals((char[]) v1, (char[]) v2);
if (type == double[].class)
return Arrays.equals((double[]) v1, (double[]) v2);
if (type == float[].class)
return Arrays.equals((float[]) v1, (float[]) v2);
if (type == int[].class)
return Arrays.equals((int[]) v1, (int[]) v2);
if (type == long[].class)
return Arrays.equals((long[]) v1, (long[]) v2);
if (type == short[].class)
return Arrays.equals((short[]) v1, (short[]) v2);
assert type == boolean[].class;
return Arrays.equals((boolean[]) v1, (boolean[]) v2);
}
/**
* Returns the member methods for our annotation type. These are
* obtained lazily and cached, as they're expensive to obtain
* and we only need them if our equals method is invoked (which should
* be rare).
*/
private Method[] getMemberMethods() {
Method[] value = memberMethods;
if (value == null) {
value = computeMemberMethods();
memberMethods = value;
}
return value;
}
private Method[] computeMemberMethods() {
return AccessController.doPrivileged(
new PrivilegedAction<Method[]>() {
public Method[] run() {
final Method[] methods = type.getDeclaredMethods();
validateAnnotationMethods(methods);
AccessibleObject.setAccessible(methods, true);
return methods;
}});
}
private transient volatile Method[] memberMethods;
/**
* Validates that a method is structurally appropriate for an
* annotation type. As of Java SE 8, annotation types cannot
* contain static methods and the declared methods of an
* annotation type must take zero arguments and there are
* restrictions on the return type.
*/
private void validateAnnotationMethods(Method[] memberMethods) {
/*
* Specification citations below are from JLS
* 9.6.1. Annotation Type Elements
*/
boolean valid = true;
for(Method method : memberMethods) {
/*
* "By virtue of the AnnotationTypeElementDeclaration
* production, a method declaration in an annotation type
* declaration cannot have formal parameters, type
* parameters, or a throws clause.
*
* "By virtue of the AnnotationTypeElementModifier
* production, a method declaration in an annotation type
* declaration cannot be default or static."
*/
if (method.getModifiers() != (Modifier.PUBLIC | Modifier.ABSTRACT) ||
method.isDefault() ||
method.getParameterCount() != 0 ||
method.getExceptionTypes().length != 0) {
valid = false;
break;
}
/*
* "It is a compile-time error if the return type of a
* method declared in an annotation type is not one of the
* following: a primitive type, String, Class, any
* parameterized invocation of Class, an enum type
* (section 8.9), an annotation type, or an array type
* (chapter 10) whose element type is one of the preceding
* types."
*/
Class<?> returnType = method.getReturnType();
if (returnType.isArray()) {
returnType = returnType.getComponentType();
if (returnType.isArray()) { // Only single dimensional arrays
valid = false;
break;
}
}
if (!((returnType.isPrimitive() && returnType != void.class) ||
returnType == java.lang.String.class ||
returnType == java.lang.Class.class ||
returnType.isEnum() ||
returnType.isAnnotation())) {
valid = false;
break;
}
/*
* "It is a compile-time error if any method declared in an
* annotation type has a signature that is
* override-equivalent to that of any public or protected
* method declared in class Object or in the interface
* java.lang.annotation.Annotation."
*
* The methods in Object or Annotation meeting the other
* criteria (no arguments, contrained return type, etc.)
* above are:
*
* String toString()
* int hashCode()
* Class<? extends Annotation> annotationType()
*/
String methodName = method.getName();
if ((methodName.equals("toString") && returnType == java.lang.String.class) ||
(methodName.equals("hashCode") && returnType == int.class) ||
(methodName.equals("annotationType") && returnType == java.lang.Class.class)) {
valid = false;
break;
}
}
if (valid)
return;
else
throw new AnnotationFormatError("Malformed method on an annotation type");
}
/**
* Implementation of dynamicProxy.hashCode()
*/
private int hashCodeImpl() {
int result = 0;
for (Map.Entry<String, Object> e : memberValues.entrySet()) {
result += (127 * e.getKey().hashCode()) ^
memberValueHashCode(e.getValue());
}
return result;
}
/**
* Computes hashCode of a member value (in "dynamic proxy return form")
*/
private static int memberValueHashCode(Object value) {
Class<?> type = value.getClass();
if (!type.isArray()) // primitive, string, class, enum const,
// or annotation
return value.hashCode();
if (type == byte[].class)
return Arrays.hashCode((byte[]) value);
if (type == char[].class)
return Arrays.hashCode((char[]) value);
if (type == double[].class)
return Arrays.hashCode((double[]) value);
if (type == float[].class)
return Arrays.hashCode((float[]) value);
if (type == int[].class)
return Arrays.hashCode((int[]) value);
if (type == long[].class)
return Arrays.hashCode((long[]) value);
if (type == short[].class)
return Arrays.hashCode((short[]) value);
if (type == boolean[].class)
return Arrays.hashCode((boolean[]) value);
return Arrays.hashCode((Object[]) value);
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = s.readFields();
@SuppressWarnings("unchecked")
Class<? extends Annotation> t = (Class<? extends Annotation>)fields.get("type", null);
@SuppressWarnings("unchecked")
Map<String, Object> streamVals = (Map<String, Object>)fields.get("memberValues", null);
// Check to make sure that types have not evolved incompatibly
AnnotationType annotationType = null;
try {
annotationType = AnnotationType.getInstance(t);
} catch(IllegalArgumentException e) {
// Class is no longer an annotation type; time to punch out
throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream");
}
Map<String, Class<?>> memberTypes = annotationType.memberTypes();
// consistent with runtime Map type
Map<String, Object> mv = new LinkedHashMap<>();
// If there are annotation members without values, that
// situation is handled by the invoke method.
for (Map.Entry<String, Object> memberValue : streamVals.entrySet()) {
String name = memberValue.getKey();
Object value = null;
Class<?> memberType = memberTypes.get(name);
if (memberType != null) { // i.e. member still exists
value = memberValue.getValue();
if (!(memberType.isInstance(value) ||
value instanceof ExceptionProxy)) {
value = new AnnotationTypeMismatchExceptionProxy(
value.getClass() + "[" + value + "]").setMember(
annotationType.members().get(name));
}
}
mv.put(name, value);
}
UnsafeAccessor.setType(this, t);
UnsafeAccessor.setMemberValues(this, mv);
}
private static class UnsafeAccessor {
private static final jdk.internal.misc.Unsafe unsafe
= jdk.internal.misc.Unsafe.getUnsafe();
private static final long typeOffset = unsafe.objectFieldOffset
(AnnotationInvocationHandler.class, "type");
private static final long memberValuesOffset = unsafe.objectFieldOffset
(AnnotationInvocationHandler.class, "memberValues");
static void setType(AnnotationInvocationHandler o,
Class<? extends Annotation> type) {
unsafe.putObject(o, typeOffset, type);
}
static void setMemberValues(AnnotationInvocationHandler o,
Map<String, Object> memberValues) {
unsafe.putObject(o, memberValuesOffset, memberValues);
}
}
}

View file

@ -0,0 +1,869 @@
/*
* Copyright (c) 2003, 2013, 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.util.*;
import java.nio.ByteBuffer;
import java.nio.BufferUnderflowException;
import java.lang.reflect.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.internal.reflect.ConstantPool;
import sun.reflect.generics.parser.SignatureParser;
import sun.reflect.generics.tree.TypeSignature;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.visitor.Reifier;
import sun.reflect.generics.scope.ClassScope;
/**
* Parser for Java programming language annotations. Translates
* annotation byte streams emitted by compiler into annotation objects.
*
* @author Josh Bloch
* @since 1.5
*/
public class AnnotationParser {
/**
* Parses the annotations described by the specified byte array.
* resolving constant references in the specified constant pool.
* The array must contain an array of annotations as described
* in the RuntimeVisibleAnnotations_attribute:
*
* u2 num_annotations;
* annotation annotations[num_annotations];
*
* @throws AnnotationFormatError if an annotation is found to be
* malformed.
*/
public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(
byte[] rawAnnotations,
ConstantPool constPool,
Class<?> container) {
if (rawAnnotations == null)
return Collections.emptyMap();
try {
return parseAnnotations2(rawAnnotations, constPool, container, null);
} catch(BufferUnderflowException e) {
throw new AnnotationFormatError("Unexpected end of annotations.");
} catch(IllegalArgumentException e) {
// Type mismatch in constant pool
throw new AnnotationFormatError(e);
}
}
/**
* Like {@link #parseAnnotations(byte[], sun.reflect.ConstantPool, Class)}
* with an additional parameter {@code selectAnnotationClasses} which selects the
* annotation types to parse (other than selected are quickly skipped).<p>
* This method is only used to parse select meta annotations in the construction
* phase of {@link AnnotationType} instances to prevent infinite recursion.
*
* @param selectAnnotationClasses an array of annotation types to select when parsing
*/
@SafeVarargs
@SuppressWarnings("varargs") // selectAnnotationClasses is used safely
static Map<Class<? extends Annotation>, Annotation> parseSelectAnnotations(
byte[] rawAnnotations,
ConstantPool constPool,
Class<?> container,
Class<? extends Annotation> ... selectAnnotationClasses) {
if (rawAnnotations == null)
return Collections.emptyMap();
try {
return parseAnnotations2(rawAnnotations, constPool, container, selectAnnotationClasses);
} catch(BufferUnderflowException e) {
throw new AnnotationFormatError("Unexpected end of annotations.");
} catch(IllegalArgumentException e) {
// Type mismatch in constant pool
throw new AnnotationFormatError(e);
}
}
private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(
byte[] rawAnnotations,
ConstantPool constPool,
Class<?> container,
Class<? extends Annotation>[] selectAnnotationClasses) {
Map<Class<? extends Annotation>, Annotation> result =
new LinkedHashMap<Class<? extends Annotation>, Annotation>();
ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
int numAnnotations = buf.getShort() & 0xFFFF;
for (int i = 0; i < numAnnotations; i++) {
Annotation a = parseAnnotation2(buf, constPool, container, false, selectAnnotationClasses);
if (a != null) {
Class<? extends Annotation> klass = a.annotationType();
if (AnnotationType.getInstance(klass).retention() == RetentionPolicy.RUNTIME &&
result.put(klass, a) != null) {
throw new AnnotationFormatError(
"Duplicate annotation for class: "+klass+": " + a);
}
}
}
return result;
}
/**
* Parses the parameter annotations described by the specified byte array.
* resolving constant references in the specified constant pool.
* The array must contain an array of annotations as described
* in the RuntimeVisibleParameterAnnotations_attribute:
*
* u1 num_parameters;
* {
* u2 num_annotations;
* annotation annotations[num_annotations];
* } parameter_annotations[num_parameters];
*
* Unlike parseAnnotations, rawAnnotations must not be null!
* A null value must be handled by the caller. This is so because
* we cannot determine the number of parameters if rawAnnotations
* is null. Also, the caller should check that the number
* of parameters indicated by the return value of this method
* matches the actual number of method parameters. A mismatch
* indicates that an AnnotationFormatError should be thrown.
*
* @throws AnnotationFormatError if an annotation is found to be
* malformed.
*/
public static Annotation[][] parseParameterAnnotations(
byte[] rawAnnotations,
ConstantPool constPool,
Class<?> container) {
try {
return parseParameterAnnotations2(rawAnnotations, constPool, container);
} catch(BufferUnderflowException e) {
throw new AnnotationFormatError(
"Unexpected end of parameter annotations.");
} catch(IllegalArgumentException e) {
// Type mismatch in constant pool
throw new AnnotationFormatError(e);
}
}
private static Annotation[][] parseParameterAnnotations2(
byte[] rawAnnotations,
ConstantPool constPool,
Class<?> container) {
ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
int numParameters = buf.get() & 0xFF;
Annotation[][] result = new Annotation[numParameters][];
for (int i = 0; i < numParameters; i++) {
int numAnnotations = buf.getShort() & 0xFFFF;
List<Annotation> annotations =
new ArrayList<Annotation>(numAnnotations);
for (int j = 0; j < numAnnotations; j++) {
Annotation a = parseAnnotation(buf, constPool, container, false);
if (a != null) {
AnnotationType type = AnnotationType.getInstance(
a.annotationType());
if (type.retention() == RetentionPolicy.RUNTIME)
annotations.add(a);
}
}
result[i] = annotations.toArray(EMPTY_ANNOTATIONS_ARRAY);
}
return result;
}
private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
new Annotation[0];
/**
* Parses the annotation at the current position in the specified
* byte buffer, resolving constant references in the specified constant
* pool. The cursor of the byte buffer must point to an "annotation
* structure" as described in the RuntimeVisibleAnnotations_attribute:
*
* annotation {
* u2 type_index;
* u2 num_member_value_pairs;
* { u2 member_name_index;
* member_value value;
* } member_value_pairs[num_member_value_pairs];
* }
* }
*
* Returns the annotation, or null if the annotation's type cannot
* be found by the VM, or is not a valid annotation type.
*
* @param exceptionOnMissingAnnotationClass if true, throw
* TypeNotPresentException if a referenced annotation type is not
* available at runtime
*/
static Annotation parseAnnotation(ByteBuffer buf,
ConstantPool constPool,
Class<?> container,
boolean exceptionOnMissingAnnotationClass) {
return parseAnnotation2(buf, constPool, container, exceptionOnMissingAnnotationClass, null);
}
@SuppressWarnings("unchecked")
private static Annotation parseAnnotation2(ByteBuffer buf,
ConstantPool constPool,
Class<?> container,
boolean exceptionOnMissingAnnotationClass,
Class<? extends Annotation>[] selectAnnotationClasses) {
int typeIndex = buf.getShort() & 0xFFFF;
Class<? extends Annotation> annotationClass = null;
String sig = "[unknown]";
try {
try {
sig = constPool.getUTF8At(typeIndex);
annotationClass = (Class<? extends Annotation>)parseSig(sig, container);
} catch (IllegalArgumentException ex) {
// support obsolete early jsr175 format class files
annotationClass = (Class<? extends Annotation>)constPool.getClassAt(typeIndex);
}
} catch (NoClassDefFoundError e) {
if (exceptionOnMissingAnnotationClass)
// note: at this point sig is "[unknown]" or VM-style
// name instead of a binary name
throw new TypeNotPresentException(sig, e);
skipAnnotation(buf, false);
return null;
}
catch (TypeNotPresentException e) {
if (exceptionOnMissingAnnotationClass)
throw e;
skipAnnotation(buf, false);
return null;
}
if (selectAnnotationClasses != null && !contains(selectAnnotationClasses, annotationClass)) {
skipAnnotation(buf, false);
return null;
}
AnnotationType type = null;
try {
type = AnnotationType.getInstance(annotationClass);
} catch (IllegalArgumentException e) {
skipAnnotation(buf, false);
return null;
}
Map<String, Class<?>> memberTypes = type.memberTypes();
Map<String, Object> memberValues =
new LinkedHashMap<String, Object>(type.memberDefaults());
int numMembers = buf.getShort() & 0xFFFF;
for (int i = 0; i < numMembers; i++) {
int memberNameIndex = buf.getShort() & 0xFFFF;
String memberName = constPool.getUTF8At(memberNameIndex);
Class<?> memberType = memberTypes.get(memberName);
if (memberType == null) {
// Member is no longer present in annotation type; ignore it
skipMemberValue(buf);
} else {
Object value = parseMemberValue(memberType, buf, constPool, container);
if (value instanceof AnnotationTypeMismatchExceptionProxy)
((AnnotationTypeMismatchExceptionProxy) value).
setMember(type.members().get(memberName));
memberValues.put(memberName, value);
}
}
return annotationForMap(annotationClass, memberValues);
}
/**
* Returns an annotation of the given type backed by the given
* member {@literal ->} value map.
*/
public static Annotation annotationForMap(final Class<? extends Annotation> type,
final Map<String, Object> memberValues)
{
return AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
public Annotation run() {
return (Annotation) Proxy.newProxyInstance(
type.getClassLoader(), new Class<?>[] { type },
new AnnotationInvocationHandler(type, memberValues));
}});
}
/**
* Parses the annotation member value at the current position in the
* specified byte buffer, resolving constant references in the specified
* constant pool. The cursor of the byte buffer must point to a
* "member_value structure" as described in the
* RuntimeVisibleAnnotations_attribute:
*
* member_value {
* u1 tag;
* union {
* u2 const_value_index;
* {
* u2 type_name_index;
* u2 const_name_index;
* } enum_const_value;
* u2 class_info_index;
* annotation annotation_value;
* {
* u2 num_values;
* member_value values[num_values];
* } array_value;
* } value;
* }
*
* The member must be of the indicated type. If it is not, this
* method returns an AnnotationTypeMismatchExceptionProxy.
*/
@SuppressWarnings("unchecked")
public static Object parseMemberValue(Class<?> memberType,
ByteBuffer buf,
ConstantPool constPool,
Class<?> container) {
Object result = null;
int tag = buf.get();
switch(tag) {
case 'e':
return parseEnumValue((Class<? extends Enum<?>>)memberType, buf, constPool, container);
case 'c':
result = parseClassValue(buf, constPool, container);
break;
case '@':
result = parseAnnotation(buf, constPool, container, true);
break;
case '[':
return parseArray(memberType, buf, constPool, container);
default:
result = parseConst(tag, buf, constPool);
}
if (!(result instanceof ExceptionProxy) &&
!memberType.isInstance(result))
result = new AnnotationTypeMismatchExceptionProxy(
result.getClass() + "[" + result + "]");
return result;
}
/**
* Parses the primitive or String annotation member value indicated by
* the specified tag byte at the current position in the specified byte
* buffer, resolving constant reference in the specified constant pool.
* The cursor of the byte buffer must point to an annotation member value
* of the type indicated by the specified tag, as described in the
* RuntimeVisibleAnnotations_attribute:
*
* u2 const_value_index;
*/
private static Object parseConst(int tag,
ByteBuffer buf, ConstantPool constPool) {
int constIndex = buf.getShort() & 0xFFFF;
switch(tag) {
case 'B':
return Byte.valueOf((byte) constPool.getIntAt(constIndex));
case 'C':
return Character.valueOf((char) constPool.getIntAt(constIndex));
case 'D':
return Double.valueOf(constPool.getDoubleAt(constIndex));
case 'F':
return Float.valueOf(constPool.getFloatAt(constIndex));
case 'I':
return Integer.valueOf(constPool.getIntAt(constIndex));
case 'J':
return Long.valueOf(constPool.getLongAt(constIndex));
case 'S':
return Short.valueOf((short) constPool.getIntAt(constIndex));
case 'Z':
return Boolean.valueOf(constPool.getIntAt(constIndex) != 0);
case 's':
return constPool.getUTF8At(constIndex);
default:
throw new AnnotationFormatError(
"Invalid member-value tag in annotation: " + tag);
}
}
/**
* Parses the Class member value at the current position in the
* specified byte buffer, resolving constant references in the specified
* constant pool. The cursor of the byte buffer must point to a "class
* info index" as described in the RuntimeVisibleAnnotations_attribute:
*
* u2 class_info_index;
*/
private static Object parseClassValue(ByteBuffer buf,
ConstantPool constPool,
Class<?> container) {
int classIndex = buf.getShort() & 0xFFFF;
try {
try {
String sig = constPool.getUTF8At(classIndex);
return parseSig(sig, container);
} catch (IllegalArgumentException ex) {
// support obsolete early jsr175 format class files
return constPool.getClassAt(classIndex);
}
} catch (NoClassDefFoundError e) {
return new TypeNotPresentExceptionProxy("[unknown]", e);
}
catch (TypeNotPresentException e) {
return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
}
}
private static Class<?> parseSig(String sig, Class<?> container) {
if (sig.equals("V")) return void.class;
SignatureParser parser = SignatureParser.make();
TypeSignature typeSig = parser.parseTypeSig(sig);
GenericsFactory factory = CoreReflectionFactory.make(container, ClassScope.make(container));
Reifier reify = Reifier.make(factory);
typeSig.accept(reify);
Type result = reify.getResult();
return toClass(result);
}
static Class<?> toClass(Type o) {
if (o instanceof GenericArrayType)
return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
0)
.getClass();
return (Class)o;
}
/**
* Parses the enum constant member value at the current position in the
* specified byte buffer, resolving constant references in the specified
* constant pool. The cursor of the byte buffer must point to a
* "enum_const_value structure" as described in the
* RuntimeVisibleAnnotations_attribute:
*
* {
* u2 type_name_index;
* u2 const_name_index;
* } enum_const_value;
*/
@SuppressWarnings({"rawtypes", "unchecked"})
private static Object parseEnumValue(Class<? extends Enum> enumType, ByteBuffer buf,
ConstantPool constPool,
Class<?> container) {
int typeNameIndex = buf.getShort() & 0xFFFF;
String typeName = constPool.getUTF8At(typeNameIndex);
int constNameIndex = buf.getShort() & 0xFFFF;
String constName = constPool.getUTF8At(constNameIndex);
if (!typeName.endsWith(";")) {
// support now-obsolete early jsr175-format class files.
if (!enumType.getName().equals(typeName))
return new AnnotationTypeMismatchExceptionProxy(
typeName + "." + constName);
} else if (enumType != parseSig(typeName, container)) {
return new AnnotationTypeMismatchExceptionProxy(
typeName + "." + constName);
}
try {
return Enum.valueOf(enumType, constName);
} catch(IllegalArgumentException e) {
return new EnumConstantNotPresentExceptionProxy(
(Class<? extends Enum<?>>)enumType, constName);
}
}
/**
* Parses the array value at the current position in the specified byte
* buffer, resolving constant references in the specified constant pool.
* The cursor of the byte buffer must point to an array value struct
* as specified in the RuntimeVisibleAnnotations_attribute:
*
* {
* u2 num_values;
* member_value values[num_values];
* } array_value;
*
* If the array values do not match arrayType, an
* AnnotationTypeMismatchExceptionProxy will be returned.
*/
@SuppressWarnings("unchecked")
private static Object parseArray(Class<?> arrayType,
ByteBuffer buf,
ConstantPool constPool,
Class<?> container) {
int length = buf.getShort() & 0xFFFF; // Number of array components
Class<?> componentType = arrayType.getComponentType();
if (componentType == byte.class) {
return parseByteArray(length, buf, constPool);
} else if (componentType == char.class) {
return parseCharArray(length, buf, constPool);
} else if (componentType == double.class) {
return parseDoubleArray(length, buf, constPool);
} else if (componentType == float.class) {
return parseFloatArray(length, buf, constPool);
} else if (componentType == int.class) {
return parseIntArray(length, buf, constPool);
} else if (componentType == long.class) {
return parseLongArray(length, buf, constPool);
} else if (componentType == short.class) {
return parseShortArray(length, buf, constPool);
} else if (componentType == boolean.class) {
return parseBooleanArray(length, buf, constPool);
} else if (componentType == String.class) {
return parseStringArray(length, buf, constPool);
} else if (componentType == Class.class) {
return parseClassArray(length, buf, constPool, container);
} else if (componentType.isEnum()) {
return parseEnumArray(length, (Class<? extends Enum<?>>)componentType, buf,
constPool, container);
} else {
assert componentType.isAnnotation();
return parseAnnotationArray(length, (Class <? extends Annotation>)componentType, buf,
constPool, container);
}
}
private static Object parseByteArray(int length,
ByteBuffer buf, ConstantPool constPool) {
byte[] result = new byte[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'B') {
int index = buf.getShort() & 0xFFFF;
result[i] = (byte) constPool.getIntAt(index);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseCharArray(int length,
ByteBuffer buf, ConstantPool constPool) {
char[] result = new char[length];
boolean typeMismatch = false;
byte tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'C') {
int index = buf.getShort() & 0xFFFF;
result[i] = (char) constPool.getIntAt(index);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseDoubleArray(int length,
ByteBuffer buf, ConstantPool constPool) {
double[] result = new double[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'D') {
int index = buf.getShort() & 0xFFFF;
result[i] = constPool.getDoubleAt(index);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseFloatArray(int length,
ByteBuffer buf, ConstantPool constPool) {
float[] result = new float[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'F') {
int index = buf.getShort() & 0xFFFF;
result[i] = constPool.getFloatAt(index);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseIntArray(int length,
ByteBuffer buf, ConstantPool constPool) {
int[] result = new int[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'I') {
int index = buf.getShort() & 0xFFFF;
result[i] = constPool.getIntAt(index);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseLongArray(int length,
ByteBuffer buf, ConstantPool constPool) {
long[] result = new long[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'J') {
int index = buf.getShort() & 0xFFFF;
result[i] = constPool.getLongAt(index);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseShortArray(int length,
ByteBuffer buf, ConstantPool constPool) {
short[] result = new short[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'S') {
int index = buf.getShort() & 0xFFFF;
result[i] = (short) constPool.getIntAt(index);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseBooleanArray(int length,
ByteBuffer buf, ConstantPool constPool) {
boolean[] result = new boolean[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'Z') {
int index = buf.getShort() & 0xFFFF;
result[i] = (constPool.getIntAt(index) != 0);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseStringArray(int length,
ByteBuffer buf, ConstantPool constPool) {
String[] result = new String[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 's') {
int index = buf.getShort() & 0xFFFF;
result[i] = constPool.getUTF8At(index);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseClassArray(int length,
ByteBuffer buf,
ConstantPool constPool,
Class<?> container) {
Object[] result = new Class<?>[length];
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'c') {
result[i] = parseClassValue(buf, constPool, container);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseEnumArray(int length, Class<? extends Enum<?>> enumType,
ByteBuffer buf,
ConstantPool constPool,
Class<?> container) {
Object[] result = (Object[]) Array.newInstance(enumType, length);
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == 'e') {
result[i] = parseEnumValue(enumType, buf, constPool, container);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
private static Object parseAnnotationArray(int length,
Class<? extends Annotation> annotationType,
ByteBuffer buf,
ConstantPool constPool,
Class<?> container) {
Object[] result = (Object[]) Array.newInstance(annotationType, length);
boolean typeMismatch = false;
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == '@') {
result[i] = parseAnnotation(buf, constPool, container, true);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
return typeMismatch ? exceptionProxy(tag) : result;
}
/**
* Returns an appropriate exception proxy for a mismatching array
* annotation where the erroneous array has the specified tag.
*/
private static ExceptionProxy exceptionProxy(int tag) {
return new AnnotationTypeMismatchExceptionProxy(
"Array with component tag: " + tag);
}
/**
* Skips the annotation at the current position in the specified
* byte buffer. The cursor of the byte buffer must point to
* an "annotation structure" OR two bytes into an annotation
* structure (i.e., after the type index).
*
* @parameter complete true if the byte buffer points to the beginning
* of an annotation structure (rather than two bytes in).
*/
private static void skipAnnotation(ByteBuffer buf, boolean complete) {
if (complete)
buf.getShort(); // Skip type index
int numMembers = buf.getShort() & 0xFFFF;
for (int i = 0; i < numMembers; i++) {
buf.getShort(); // Skip memberNameIndex
skipMemberValue(buf);
}
}
/**
* Skips the annotation member value at the current position in the
* specified byte buffer. The cursor of the byte buffer must point to a
* "member_value structure."
*/
private static void skipMemberValue(ByteBuffer buf) {
int tag = buf.get();
skipMemberValue(tag, buf);
}
/**
* Skips the annotation member value at the current position in the
* specified byte buffer. The cursor of the byte buffer must point
* immediately after the tag in a "member_value structure."
*/
private static void skipMemberValue(int tag, ByteBuffer buf) {
switch(tag) {
case 'e': // Enum value
buf.getInt(); // (Two shorts, actually.)
break;
case '@':
skipAnnotation(buf, true);
break;
case '[':
skipArray(buf);
break;
default:
// Class, primitive, or String
buf.getShort();
}
}
/**
* Skips the array value at the current position in the specified byte
* buffer. The cursor of the byte buffer must point to an array value
* struct.
*/
private static void skipArray(ByteBuffer buf) {
int length = buf.getShort() & 0xFFFF;
for (int i = 0; i < length; i++)
skipMemberValue(buf);
}
/**
* Searches for given {@code element} in given {@code array} by identity.
* Returns {@code true} if found {@code false} if not.
*/
private static boolean contains(Object[] array, Object element) {
for (Object e : array)
if (e == element)
return true;
return false;
}
/*
* This method converts the annotation map returned by the parseAnnotations()
* method to an array. It is called by Field.getDeclaredAnnotations(),
* Method.getDeclaredAnnotations(), and Constructor.getDeclaredAnnotations().
* This avoids the reflection classes to load the Annotation class until
* it is needed.
*/
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
public static Annotation[] toArray(Map<Class<? extends Annotation>, Annotation> annotations) {
return annotations.values().toArray(EMPTY_ANNOTATION_ARRAY);
}
static Annotation[] getEmptyAnnotationArray() { return EMPTY_ANNOTATION_ARRAY; }
}

View file

@ -0,0 +1,283 @@
/*
* Copyright (c) 2012, 2013, 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.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.reflect.ReflectionFactory;
public final class AnnotationSupport {
private static final JavaLangAccess LANG_ACCESS = SharedSecrets.getJavaLangAccess();
/**
* Finds and returns all annotations in {@code annotations} matching
* the given {@code annoClass}.
*
* Apart from annotations directly present in {@code annotations} this
* method searches for annotations inside containers i.e. indirectly
* present annotations.
*
* The order of the elements in the array returned depends on the iteration
* order of the provided map. Specifically, the directly present annotations
* come before the indirectly present annotations if and only if the
* directly present annotations come before the indirectly present
* annotations in the map.
*
* @param annotations the {@code Map} in which to search for annotations
* @param annoClass the type of annotation to search for
*
* @return an array of instances of {@code annoClass} or an empty
* array if none were found
*/
public static <A extends Annotation> A[] getDirectlyAndIndirectlyPresent(
Map<Class<? extends Annotation>, Annotation> annotations,
Class<A> annoClass) {
List<A> result = new ArrayList<>();
@SuppressWarnings("unchecked")
A direct = (A) annotations.get(annoClass);
if (direct != null)
result.add(direct);
A[] indirect = getIndirectlyPresent(annotations, annoClass);
if (indirect != null && indirect.length != 0) {
boolean indirectFirst = direct == null ||
containerBeforeContainee(annotations, annoClass);
result.addAll((indirectFirst ? 0 : 1), Arrays.asList(indirect));
}
@SuppressWarnings("unchecked")
A[] arr = (A[]) Array.newInstance(annoClass, result.size());
return result.toArray(arr);
}
/**
* Finds and returns all annotations matching the given {@code annoClass}
* indirectly present in {@code annotations}.
*
* @param annotations annotations to search indexed by their types
* @param annoClass the type of annotation to search for
*
* @return an array of instances of {@code annoClass} or an empty array if no
* indirectly present annotations were found
*/
private static <A extends Annotation> A[] getIndirectlyPresent(
Map<Class<? extends Annotation>, Annotation> annotations,
Class<A> annoClass) {
Repeatable repeatable = annoClass.getDeclaredAnnotation(Repeatable.class);
if (repeatable == null)
return null; // Not repeatable -> no indirectly present annotations
Class<? extends Annotation> containerClass = repeatable.value();
Annotation container = annotations.get(containerClass);
if (container == null)
return null;
// Unpack container
A[] valueArray = getValueArray(container);
checkTypes(valueArray, container, annoClass);
return valueArray;
}
/**
* Figures out if container class comes before containee class among the
* keys of the given map.
*
* @return true if container class is found before containee class when
* iterating over annotations.keySet().
*/
private static <A extends Annotation> boolean containerBeforeContainee(
Map<Class<? extends Annotation>, Annotation> annotations,
Class<A> annoClass) {
Class<? extends Annotation> containerClass =
annoClass.getDeclaredAnnotation(Repeatable.class).value();
for (Class<? extends Annotation> c : annotations.keySet()) {
if (c == containerClass) return true;
if (c == annoClass) return false;
}
// Neither containee nor container present
return false;
}
/**
* Finds and returns all associated annotations matching the given class.
*
* The order of the elements in the array returned depends on the iteration
* order of the provided maps. Specifically, the directly present annotations
* come before the indirectly present annotations if and only if the
* directly present annotations come before the indirectly present
* annotations in the relevant map.
*
* @param declaredAnnotations the declared annotations indexed by their types
* @param decl the class declaration on which to search for annotations
* @param annoClass the type of annotation to search for
*
* @return an array of instances of {@code annoClass} or an empty array if none were found.
*/
public static <A extends Annotation> A[] getAssociatedAnnotations(
Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
Class<?> decl,
Class<A> annoClass) {
Objects.requireNonNull(decl);
// Search declared
A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass);
// Search inherited
if(AnnotationType.getInstance(annoClass).isInherited()) {
Class<?> superDecl = decl.getSuperclass();
while (result.length == 0 && superDecl != null) {
result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass);
superDecl = superDecl.getSuperclass();
}
}
return result;
}
/* Reflectively invoke the values-method of the given annotation
* (container), cast it to an array of annotations and return the result.
*/
private static <A extends Annotation> A[] getValueArray(Annotation container) {
try {
// According to JLS the container must have an array-valued value
// method. Get the AnnotationType, get the "value" method and invoke
// it to get the content.
Class<? extends Annotation> containerClass = container.annotationType();
AnnotationType annoType = AnnotationType.getInstance(containerClass);
if (annoType == null)
throw invalidContainerException(container, null);
Method m = annoType.members().get("value");
if (m == null)
throw invalidContainerException(container, null);
if (Proxy.isProxyClass(container.getClass())) {
// Invoke by invocation handler
InvocationHandler handler = Proxy.getInvocationHandler(container);
try {
// This will erase to (Annotation[]) but we do a runtime cast on the
// return-value in the method that call this method.
@SuppressWarnings("unchecked")
A[] values = (A[]) handler.invoke(container, m, null);
return values;
} catch (Throwable t) { // from InvocationHandler::invoke
throw invalidContainerException(container, t);
}
} else {
// In theory there might be instances of Annotations that are not
// implemented using Proxies. Try to invoke the "value" element with
// reflection.
// Declaring class should be an annotation type
Class<?> iface = m.getDeclaringClass();
if (!iface.isAnnotation())
throw new UnsupportedOperationException("Unsupported container annotation type.");
// Method must be public
if (!Modifier.isPublic(m.getModifiers()))
throw new UnsupportedOperationException("Unsupported value member.");
// Interface might not be public though
final Method toInvoke;
if (!Modifier.isPublic(iface.getModifiers())) {
if (System.getSecurityManager() != null) {
toInvoke = AccessController.doPrivileged(new PrivilegedAction<Method>() {
@Override
public Method run() {
Method res = ReflectionFactory.getReflectionFactory().leafCopyMethod(m);
res.setAccessible(true);
return res;
}
});
} else {
toInvoke = ReflectionFactory.getReflectionFactory().leafCopyMethod(m);
toInvoke.setAccessible(true);
}
} else {
toInvoke = m;
}
// This will erase to (Annotation[]) but we do a runtime cast on the
// return-value in the method that call this method.
@SuppressWarnings("unchecked")
A[] values = (A[]) toInvoke.invoke(container);
return values;
}
} catch (IllegalAccessException | // couldn't loosen security
IllegalArgumentException | // parameters doesn't match
InvocationTargetException | // the value method threw an exception
ClassCastException e) {
throw invalidContainerException(container, e);
}
}
private static AnnotationFormatError invalidContainerException(Annotation anno,
Throwable cause) {
return new AnnotationFormatError(
anno + " is an invalid container for repeating annotations",
cause);
}
/* Sanity check type of all the annotation instances of type {@code annoClass}
* from {@code container}.
*/
private static <A extends Annotation> void checkTypes(A[] annotations,
Annotation container,
Class<A> annoClass) {
for (A a : annotations) {
if (!annoClass.isInstance(a)) {
throw new AnnotationFormatError(
String.format("%s is an invalid container for " +
"repeating annotations of type: %s",
container, annoClass));
}
}
}
}

View file

@ -0,0 +1,238 @@
/*
* Copyright (c) 2003, 2016, 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.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaLangAccess;
/**
* Represents an annotation type at run time. Used to type-check annotations
* and apply member defaults.
*
* @author Josh Bloch
* @since 1.5
*/
public class AnnotationType {
/**
* Member name -> type mapping. Note that primitive types
* are represented by the class objects for the corresponding wrapper
* types. This matches the return value that must be used for a
* dynamic proxy, allowing for a simple isInstance test.
*/
private final Map<String, Class<?>> memberTypes;
/**
* Member name -> default value mapping.
*/
private final Map<String, Object> memberDefaults;
/**
* Member name -> Method object mapping. This (and its associated
* accessor) are used only to generate AnnotationTypeMismatchExceptions.
*/
private final Map<String, Method> members;
/**
* The retention policy for this annotation type.
*/
private final RetentionPolicy retention;
/**
* Whether this annotation type is inherited.
*/
private final boolean inherited;
/**
* Returns an AnnotationType instance for the specified annotation type.
*
* @throws IllegalArgumentException if the specified class object
* does not represent a valid annotation type
*/
public static AnnotationType getInstance(
Class<? extends Annotation> annotationClass)
{
JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
AnnotationType result = jla.getAnnotationType(annotationClass); // volatile read
if (result == null) {
result = new AnnotationType(annotationClass);
// try to CAS the AnnotationType: null -> result
if (!jla.casAnnotationType(annotationClass, null, result)) {
// somebody was quicker -> read it's result
result = jla.getAnnotationType(annotationClass);
assert result != null;
}
}
return result;
}
/**
* Sole constructor.
*
* @param annotationClass the class object for the annotation type
* @throws IllegalArgumentException if the specified class object for
* does not represent a valid annotation type
*/
private AnnotationType(final Class<? extends Annotation> annotationClass) {
if (!annotationClass.isAnnotation())
throw new IllegalArgumentException("Not an annotation type");
Method[] methods =
AccessController.doPrivileged(new PrivilegedAction<>() {
public Method[] run() {
// Initialize memberTypes and defaultValues
return annotationClass.getDeclaredMethods();
}
});
memberTypes = new HashMap<>(methods.length+1, 1.0f);
memberDefaults = new HashMap<>(0);
members = new HashMap<>(methods.length+1, 1.0f);
for (Method method : methods) {
if (Modifier.isPublic(method.getModifiers()) &&
Modifier.isAbstract(method.getModifiers()) &&
!method.isSynthetic()) {
if (method.getParameterTypes().length != 0) {
throw new IllegalArgumentException(method + " has params");
}
String name = method.getName();
Class<?> type = method.getReturnType();
memberTypes.put(name, invocationHandlerReturnType(type));
members.put(name, method);
Object defaultValue = method.getDefaultValue();
if (defaultValue != null) {
memberDefaults.put(name, defaultValue);
}
}
}
// Initialize retention, & inherited fields. Special treatment
// of the corresponding annotation types breaks infinite recursion.
if (annotationClass != Retention.class &&
annotationClass != Inherited.class) {
JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
Map<Class<? extends Annotation>, Annotation> metaAnnotations =
AnnotationParser.parseSelectAnnotations(
jla.getRawClassAnnotations(annotationClass),
jla.getConstantPool(annotationClass),
annotationClass,
Retention.class, Inherited.class
);
Retention ret = (Retention) metaAnnotations.get(Retention.class);
retention = (ret == null ? RetentionPolicy.CLASS : ret.value());
inherited = metaAnnotations.containsKey(Inherited.class);
}
else {
retention = RetentionPolicy.RUNTIME;
inherited = false;
}
}
/**
* Returns the type that must be returned by the invocation handler
* of a dynamic proxy in order to have the dynamic proxy return
* the specified type (which is assumed to be a legal member type
* for an annotation).
*/
public static Class<?> invocationHandlerReturnType(Class<?> type) {
// Translate primitives to wrappers
if (type == byte.class)
return Byte.class;
if (type == char.class)
return Character.class;
if (type == double.class)
return Double.class;
if (type == float.class)
return Float.class;
if (type == int.class)
return Integer.class;
if (type == long.class)
return Long.class;
if (type == short.class)
return Short.class;
if (type == boolean.class)
return Boolean.class;
// Otherwise, just return declared type
return type;
}
/**
* Returns member types for this annotation type
* (member name {@literal ->} type mapping).
*/
public Map<String, Class<?>> memberTypes() {
return memberTypes;
}
/**
* Returns members of this annotation type
* (member name {@literal ->} associated Method object mapping).
*/
public Map<String, Method> members() {
return members;
}
/**
* Returns the default values for this annotation type
* (Member name {@literal ->} default value mapping).
*/
public Map<String, Object> memberDefaults() {
return memberDefaults;
}
/**
* Returns the retention policy for this annotation type.
*/
public RetentionPolicy retention() {
return retention;
}
/**
* Returns true if this annotation type is inherited.
*/
public boolean isInherited() {
return inherited;
}
/**
* For debugging.
*/
public String toString() {
return "Annotation Type:\n" +
" Member types: " + memberTypes + "\n" +
" Member defaults: " + memberDefaults + "\n" +
" Retention policy: " + retention + "\n" +
" Inherited: " + inherited;
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2004, 2016, 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.Method;
/**
* ExceptionProxy for AnnotationTypeMismatchException.
*
* @author Josh Bloch
* @since 1.5
*/
class AnnotationTypeMismatchExceptionProxy extends ExceptionProxy {
private static final long serialVersionUID = 7844069490309503934L;
private Method member;
private final String foundType;
/**
* It turns out to be convenient to construct these proxies in
* two stages. Since this is a private implementation class, we
* permit ourselves this liberty even though it's normally a very
* bad idea.
*/
AnnotationTypeMismatchExceptionProxy(String foundType) {
this.foundType = foundType;
}
AnnotationTypeMismatchExceptionProxy setMember(Method member) {
this.member = member;
return this;
}
protected RuntimeException generateException() {
return new AnnotationTypeMismatchException(member, foundType);
}
@Override
public String toString() {
return "/* Warning type mismatch! \"" + foundType + "\" */" ;
}
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2004, 2016, 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;
/**
* ExceptionProxy for EnumConstantNotPresentException.
*
* @author Josh Bloch
* @since 1.5
*/
public class EnumConstantNotPresentExceptionProxy extends ExceptionProxy {
private static final long serialVersionUID = -604662101303187330L;
final Class<? extends Enum<?>> enumType;
final String constName;
public EnumConstantNotPresentExceptionProxy(Class<? extends Enum<?>> enumType,
String constName) {
this.enumType = enumType;
this.constName = constName;
}
protected RuntimeException generateException() {
return new EnumConstantNotPresentException(enumType, constName);
}
@Override
public String toString() {
return constName + " /* Warning: constant not present! */";
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2004, 2014, 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;
/**
* An instance of this class is stored in an AnnotationInvocationHandler's
* "memberValues" map in lieu of a value for an annotation member that
* cannot be returned due to some exceptional condition (typically some
* form of illegal evolution of the annotation class). The ExceptionProxy
* instance describes the exception that the dynamic proxy should throw if
* it is queried for this member.
*
* @author Josh Bloch
* @since 1.5
*/
public abstract class ExceptionProxy implements java.io.Serializable {
private static final long serialVersionUID = 7241930048386631401L;
protected abstract RuntimeException generateException();
}

View file

@ -0,0 +1,244 @@
/*
* 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.Annotation;
import java.lang.annotation.AnnotationFormatError;
import java.lang.reflect.AnnotatedElement;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* A TypeAnnotation contains all the information needed to transform type
* annotations on declarations in the class file to actual Annotations in
* AnnotatedType instances.
*
* TypeAnnotaions contain a base Annotation, location info (which lets you
* distinguish between '@A Inner.@B Outer' in for example nested types),
* target info and the declaration the TypeAnnotaiton was parsed from.
*/
public final class TypeAnnotation {
private final TypeAnnotationTargetInfo targetInfo;
private final LocationInfo loc;
private final Annotation annotation;
private final AnnotatedElement baseDeclaration;
public TypeAnnotation(TypeAnnotationTargetInfo targetInfo,
LocationInfo loc,
Annotation annotation,
AnnotatedElement baseDeclaration) {
this.targetInfo = targetInfo;
this.loc = loc;
this.annotation = annotation;
this.baseDeclaration = baseDeclaration;
}
public TypeAnnotationTargetInfo getTargetInfo() {
return targetInfo;
}
public Annotation getAnnotation() {
return annotation;
}
public AnnotatedElement getBaseDeclaration() {
return baseDeclaration;
}
public LocationInfo getLocationInfo() {
return loc;
}
public static List<TypeAnnotation> filter(TypeAnnotation[] typeAnnotations,
TypeAnnotationTarget predicate) {
ArrayList<TypeAnnotation> typeAnnos = new ArrayList<>(typeAnnotations.length);
for (TypeAnnotation t : typeAnnotations)
if (t.getTargetInfo().getTarget() == predicate)
typeAnnos.add(t);
typeAnnos.trimToSize();
return typeAnnos;
}
public static enum TypeAnnotationTarget {
CLASS_TYPE_PARAMETER,
METHOD_TYPE_PARAMETER,
CLASS_EXTENDS,
CLASS_IMPLEMENTS, // Not in the spec
CLASS_TYPE_PARAMETER_BOUND,
METHOD_TYPE_PARAMETER_BOUND,
FIELD,
METHOD_RETURN,
METHOD_RECEIVER,
METHOD_FORMAL_PARAMETER,
THROWS;
}
public static final class TypeAnnotationTargetInfo {
private final TypeAnnotationTarget target;
private final int count;
private final int secondaryIndex;
private static final int UNUSED_INDEX = -2; // this is not a valid index in the 308 spec
public TypeAnnotationTargetInfo(TypeAnnotationTarget target) {
this(target, UNUSED_INDEX, UNUSED_INDEX);
}
public TypeAnnotationTargetInfo(TypeAnnotationTarget target,
int count) {
this(target, count, UNUSED_INDEX);
}
public TypeAnnotationTargetInfo(TypeAnnotationTarget target,
int count,
int secondaryIndex) {
this.target = target;
this.count = count;
this.secondaryIndex = secondaryIndex;
}
public TypeAnnotationTarget getTarget() {
return target;
}
public int getCount() {
return count;
}
public int getSecondaryIndex() {
return secondaryIndex;
}
@Override
public String toString() {
return "" + target + ": " + count + ", " + secondaryIndex;
}
}
public static final class LocationInfo {
private final int depth;
private final Location[] locations;
private LocationInfo() {
this(0, new Location[0]);
}
private LocationInfo(int depth, Location[] locations) {
this.depth = depth;
this.locations = locations;
}
public static final LocationInfo BASE_LOCATION = new LocationInfo();
public static LocationInfo parseLocationInfo(ByteBuffer buf) {
int depth = buf.get() & 0xFF;
if (depth == 0)
return BASE_LOCATION;
Location[] locations = new Location[depth];
for (int i = 0; i < depth; i++) {
byte tag = buf.get();
short index = (short)(buf.get() & 0xFF);
if (!(tag == 0 || tag == 1 | tag == 2 || tag == 3))
throw new AnnotationFormatError("Bad Location encoding in Type Annotation");
if (tag != 3 && index != 0)
throw new AnnotationFormatError("Bad Location encoding in Type Annotation");
locations[i] = new Location(tag, index);
}
return new LocationInfo(depth, locations);
}
public LocationInfo pushArray() {
return pushLocation((byte)0, (short)0);
}
public LocationInfo pushInner() {
return pushLocation((byte)1, (short)0);
}
public LocationInfo pushWildcard() {
return pushLocation((byte) 2, (short) 0);
}
public LocationInfo pushTypeArg(short index) {
return pushLocation((byte) 3, index);
}
public LocationInfo pushLocation(byte tag, short index) {
int newDepth = this.depth + 1;
Location[] res = new Location[newDepth];
System.arraycopy(this.locations, 0, res, 0, depth);
res[newDepth - 1] = new Location(tag, (short)(index & 0xFF));
return new LocationInfo(newDepth, res);
}
/** Pop a series of locations matching {@code tag}. Stop poping as soon as a non-matching tag is found. */
public LocationInfo popAllLocations(byte tag) {
LocationInfo l = this;
int newDepth = l.depth;
while(newDepth > 0 && l.locations[newDepth - 1].tag == tag) {
newDepth--;
}
if (newDepth != l.depth) {
Location[] res = new Location[newDepth];
System.arraycopy(this.locations, 0, res, 0, newDepth);
return new LocationInfo(newDepth, res);
} else
return l;
}
public TypeAnnotation[] filter(TypeAnnotation[] ta) {
ArrayList<TypeAnnotation> l = new ArrayList<>(ta.length);
for (TypeAnnotation t : ta) {
if (isSameLocationInfo(t.getLocationInfo()))
l.add(t);
}
return l.toArray(AnnotatedTypeFactory.EMPTY_TYPE_ANNOTATION_ARRAY);
}
boolean isSameLocationInfo(LocationInfo other) {
if (depth != other.depth)
return false;
for (int i = 0; i < depth; i++)
if (!locations[i].isSameLocation(other.locations[i]))
return false;
return true;
}
public static final class Location {
public final byte tag;
public final short index;
boolean isSameLocation(Location other) {
return tag == other.tag && index == other.index;
}
public Location(byte tag, short index) {
this.tag = tag;
this.index = index;
}
}
}
@Override
public String toString() {
return annotation.toString() + " with Targetnfo: " +
targetInfo.toString() + " on base declaration: " +
baseDeclaration.toString();
}
}

View file

@ -0,0 +1,525 @@
/*
* Copyright (c) 2013, 2017, 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.nio.ByteBuffer;
import java.nio.BufferUnderflowException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.LinkedHashMap;
import java.util.Map;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.reflect.ConstantPool;
import static sun.reflect.annotation.TypeAnnotation.*;
/**
* TypeAnnotationParser implements the logic needed to parse
* TypeAnnotations from an array of bytes.
*/
public final class TypeAnnotationParser {
private static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0];
/**
* Build an AnnotatedType from the parameters supplied.
*
* This method and {@code buildAnnotatedTypes} are probably
* the entry points you are looking for.
*
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
* @param cp the ConstantPool needed to parse the embedded Annotation
* @param decl the declaration this type annotation is on
* @param container the Class this type annotation is on (may be the same as decl)
* @param type the type the AnnotatedType corresponds to
* @param filter the type annotation targets included in this AnnotatedType
*/
public static AnnotatedType buildAnnotatedType(byte[] rawAnnotations,
ConstantPool cp,
AnnotatedElement decl,
Class<?> container,
Type type,
TypeAnnotationTarget filter) {
TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
cp, decl, container);
List<TypeAnnotation> l = new ArrayList<>(tas.length);
for (TypeAnnotation t : tas) {
TypeAnnotationTargetInfo ti = t.getTargetInfo();
if (ti.getTarget() == filter)
l.add(t);
}
TypeAnnotation[] typeAnnotations = l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY);
return AnnotatedTypeFactory.buildAnnotatedType(type,
AnnotatedTypeFactory.nestingForType(type, LocationInfo.BASE_LOCATION),
typeAnnotations,
typeAnnotations,
decl);
}
/**
* Build an array of AnnotatedTypes from the parameters supplied.
*
* This method and {@code buildAnnotatedType} are probably
* the entry points you are looking for.
*
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
* @param cp the ConstantPool needed to parse the embedded Annotation
* @param decl the declaration this type annotation is on
* @param container the Class this type annotation is on (may be the same as decl)
* @param types the Types the AnnotatedTypes corresponds to
* @param filter the type annotation targets that included in this AnnotatedType
*/
public static AnnotatedType[] buildAnnotatedTypes(byte[] rawAnnotations,
ConstantPool cp,
AnnotatedElement decl,
Class<?> container,
Type[] types,
TypeAnnotationTarget filter) {
int size = types.length;
AnnotatedType[] result = new AnnotatedType[size];
Arrays.fill(result, AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE);
@SuppressWarnings("rawtypes")
ArrayList[] l = new ArrayList[size]; // array of ArrayList<TypeAnnotation>
TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
cp, decl, container);
for (TypeAnnotation t : tas) {
TypeAnnotationTargetInfo ti = t.getTargetInfo();
if (ti.getTarget() == filter) {
int pos = ti.getCount();
if (l[pos] == null) {
ArrayList<TypeAnnotation> tmp = new ArrayList<>(tas.length);
l[pos] = tmp;
}
@SuppressWarnings("unchecked")
ArrayList<TypeAnnotation> tmp = l[pos];
tmp.add(t);
}
}
// If a constructor has a mandated outer this, that parameter
// has no annotations and the annotations to parameter mapping
// should be offset by 1.
boolean offset = false;
if (decl instanceof Constructor) {
Constructor<?> ctor = (Constructor<?>) decl;
Class<?> declaringClass = ctor.getDeclaringClass();
if (!declaringClass.isEnum() &&
(declaringClass.isMemberClass() &&
(declaringClass.getModifiers() & Modifier.STATIC) == 0) ) {
offset = true;
}
}
for (int i = 0; i < size; i++) {
ArrayList<TypeAnnotation> list;
if (offset) {
@SuppressWarnings("unchecked")
ArrayList<TypeAnnotation> tmp = (i == 0) ? null : l[i - 1];
list = tmp;
} else {
@SuppressWarnings("unchecked")
ArrayList<TypeAnnotation> tmp = l[i];
list = tmp;
}
TypeAnnotation[] typeAnnotations;
if (list != null) {
typeAnnotations = list.toArray(new TypeAnnotation[list.size()]);
} else {
typeAnnotations = EMPTY_TYPE_ANNOTATION_ARRAY;
}
result[i] = AnnotatedTypeFactory.buildAnnotatedType(types[i],
AnnotatedTypeFactory.nestingForType(types[i], LocationInfo.BASE_LOCATION),
typeAnnotations,
typeAnnotations,
decl);
}
return result;
}
// Class helpers
/**
* Build an AnnotatedType for the class decl's supertype.
*
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
* @param cp the ConstantPool needed to parse the embedded Annotation
* @param decl the Class which annotated supertype is being built
*/
public static AnnotatedType buildAnnotatedSuperclass(byte[] rawAnnotations,
ConstantPool cp,
Class<?> decl) {
Type supertype = decl.getGenericSuperclass();
if (supertype == null)
return AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE;
return buildAnnotatedType(rawAnnotations,
cp,
decl,
decl,
supertype,
TypeAnnotationTarget.CLASS_EXTENDS);
}
/**
* Build an array of AnnotatedTypes for the class decl's implemented
* interfaces.
*
* @param rawAnnotations the byte[] encoding of all type annotations on this declaration
* @param cp the ConstantPool needed to parse the embedded Annotation
* @param decl the Class whose annotated implemented interfaces is being built
*/
public static AnnotatedType[] buildAnnotatedInterfaces(byte[] rawAnnotations,
ConstantPool cp,
Class<?> decl) {
if (decl == Object.class ||
decl.isArray() ||
decl.isPrimitive() ||
decl == Void.TYPE)
return AnnotatedTypeFactory.EMPTY_ANNOTATED_TYPE_ARRAY;
return buildAnnotatedTypes(rawAnnotations,
cp,
decl,
decl,
decl.getGenericInterfaces(),
TypeAnnotationTarget.CLASS_IMPLEMENTS);
}
// TypeVariable helpers
/**
* Parse regular annotations on a TypeVariable declared on genericDecl.
*
* Regular Annotations on TypeVariables are stored in the type
* annotation byte[] in the class file.
*
* @param genericDecl the declaration declaring the type variable
* @param typeVarIndex the 0-based index of this type variable in the declaration
*/
public static <D extends GenericDeclaration> Annotation[] parseTypeVariableAnnotations(D genericDecl,
int typeVarIndex) {
AnnotatedElement decl;
TypeAnnotationTarget predicate;
if (genericDecl instanceof Class) {
decl = (Class<?>)genericDecl;
predicate = TypeAnnotationTarget.CLASS_TYPE_PARAMETER;
} else if (genericDecl instanceof Executable) {
decl = (Executable)genericDecl;
predicate = TypeAnnotationTarget.METHOD_TYPE_PARAMETER;
} else {
throw new AssertionError("Unknown GenericDeclaration " + genericDecl + "\nthis should not happen.");
}
List<TypeAnnotation> typeVarAnnos = TypeAnnotation.filter(parseAllTypeAnnotations(decl),
predicate);
List<Annotation> res = new ArrayList<>(typeVarAnnos.size());
for (TypeAnnotation t : typeVarAnnos)
if (t.getTargetInfo().getCount() == typeVarIndex)
res.add(t.getAnnotation());
return res.toArray(new Annotation[0]);
}
/**
* Build an array of AnnotatedTypes for the declaration decl's bounds.
*
* @param bounds the bounds corresponding to the annotated bounds
* @param decl the declaration whose annotated bounds is being built
* @param typeVarIndex the index of this type variable on the decl
*/
public static <D extends GenericDeclaration> AnnotatedType[] parseAnnotatedBounds(Type[] bounds,
D decl,
int typeVarIndex) {
return parseAnnotatedBounds(bounds, decl, typeVarIndex, LocationInfo.BASE_LOCATION);
}
//helper for above
private static <D extends GenericDeclaration> AnnotatedType[] parseAnnotatedBounds(Type[] bounds,
D decl,
int typeVarIndex,
LocationInfo loc) {
List<TypeAnnotation> candidates = fetchBounds(decl);
if (bounds != null) {
int startIndex = 0;
AnnotatedType[] res = new AnnotatedType[bounds.length];
// Adjust bounds index
//
// Figure out if the type annotations for this bound starts with 0
// or 1. The spec says within a bound the 0:th type annotation will
// always be on an bound of a Class type (not Interface type). So
// if the programmer starts with an Interface type for the first
// (and following) bound(s) the implicit Object bound is considered
// the first (that is 0:th) bound and type annotations start on
// index 1.
if (bounds.length > 0) {
Type b0 = bounds[0];
if (!(b0 instanceof Class<?>)) {
startIndex = 1;
} else {
Class<?> c = (Class<?>)b0;
if (c.isInterface()) {
startIndex = 1;
}
}
}
for (int i = 0; i < bounds.length; i++) {
List<TypeAnnotation> l = new ArrayList<>(candidates.size());
for (TypeAnnotation t : candidates) {
TypeAnnotationTargetInfo tInfo = t.getTargetInfo();
if (tInfo.getSecondaryIndex() == i + startIndex &&
tInfo.getCount() == typeVarIndex) {
l.add(t);
}
}
res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i],
AnnotatedTypeFactory.nestingForType(bounds[i], loc),
l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
candidates.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
(AnnotatedElement)decl);
}
return res;
}
return new AnnotatedType[0];
}
private static <D extends GenericDeclaration> List<TypeAnnotation> fetchBounds(D decl) {
AnnotatedElement boundsDecl;
TypeAnnotationTarget target;
if (decl instanceof Class) {
target = TypeAnnotationTarget.CLASS_TYPE_PARAMETER_BOUND;
boundsDecl = (Class)decl;
} else {
target = TypeAnnotationTarget.METHOD_TYPE_PARAMETER_BOUND;
boundsDecl = (Executable)decl;
}
return TypeAnnotation.filter(TypeAnnotationParser.parseAllTypeAnnotations(boundsDecl), target);
}
/*
* Parse all type annotations on the declaration supplied. This is needed
* when you go from for example an annotated return type on a method that
* is a type variable declared on the class. In this case you need to
* 'jump' to the decl of the class and parse all type annotations there to
* find the ones that are applicable to the type variable.
*/
static TypeAnnotation[] parseAllTypeAnnotations(AnnotatedElement decl) {
Class<?> container;
byte[] rawBytes;
JavaLangAccess javaLangAccess = SharedSecrets.getJavaLangAccess();
if (decl instanceof Class) {
container = (Class<?>)decl;
rawBytes = javaLangAccess.getRawClassTypeAnnotations(container);
} else if (decl instanceof Executable) {
container = ((Executable)decl).getDeclaringClass();
rawBytes = javaLangAccess.getRawExecutableTypeAnnotations((Executable)decl);
} else {
// Should not reach here. Assert?
return EMPTY_TYPE_ANNOTATION_ARRAY;
}
return parseTypeAnnotations(rawBytes, javaLangAccess.getConstantPool(container),
decl, container);
}
/* Parse type annotations encoded as an array of bytes */
private static TypeAnnotation[] parseTypeAnnotations(byte[] rawAnnotations,
ConstantPool cp,
AnnotatedElement baseDecl,
Class<?> container) {
if (rawAnnotations == null)
return EMPTY_TYPE_ANNOTATION_ARRAY;
ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
int annotationCount = buf.getShort() & 0xFFFF;
List<TypeAnnotation> typeAnnotations = new ArrayList<>(annotationCount);
// Parse each TypeAnnotation
for (int i = 0; i < annotationCount; i++) {
TypeAnnotation ta = parseTypeAnnotation(buf, cp, baseDecl, container);
if (ta != null)
typeAnnotations.add(ta);
}
return typeAnnotations.toArray(EMPTY_TYPE_ANNOTATION_ARRAY);
}
// Helper
static Map<Class<? extends Annotation>, Annotation> mapTypeAnnotations(TypeAnnotation[] typeAnnos) {
Map<Class<? extends Annotation>, Annotation> result =
new LinkedHashMap<>();
for (TypeAnnotation t : typeAnnos) {
Annotation a = t.getAnnotation();
if (a != null) {
Class<? extends Annotation> klass = a.annotationType();
AnnotationType type = AnnotationType.getInstance(klass);
if (type.retention() == RetentionPolicy.RUNTIME &&
result.put(klass, a) != null) {
throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
}
}
}
return result;
}
// Position codes
// Regular type parameter annotations
private static final byte CLASS_TYPE_PARAMETER = 0x00;
private static final byte METHOD_TYPE_PARAMETER = 0x01;
// Type Annotations outside method bodies
private static final byte CLASS_EXTENDS = 0x10;
private static final byte CLASS_TYPE_PARAMETER_BOUND = 0x11;
private static final byte METHOD_TYPE_PARAMETER_BOUND = 0x12;
private static final byte FIELD = 0x13;
private static final byte METHOD_RETURN = 0x14;
private static final byte METHOD_RECEIVER = 0x15;
private static final byte METHOD_FORMAL_PARAMETER = 0x16;
private static final byte THROWS = 0x17;
// Type Annotations inside method bodies
private static final byte LOCAL_VARIABLE = (byte)0x40;
private static final byte RESOURCE_VARIABLE = (byte)0x41;
private static final byte EXCEPTION_PARAMETER = (byte)0x42;
private static final byte INSTANCEOF = (byte)0x43;
private static final byte NEW = (byte)0x44;
private static final byte CONSTRUCTOR_REFERENCE = (byte)0x45;
private static final byte METHOD_REFERENCE = (byte)0x46;
private static final byte CAST = (byte)0x47;
private static final byte CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = (byte)0x48;
private static final byte METHOD_INVOCATION_TYPE_ARGUMENT = (byte)0x49;
private static final byte CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = (byte)0x4A;
private static final byte METHOD_REFERENCE_TYPE_ARGUMENT = (byte)0x4B;
private static TypeAnnotation parseTypeAnnotation(ByteBuffer buf,
ConstantPool cp,
AnnotatedElement baseDecl,
Class<?> container) {
try {
TypeAnnotationTargetInfo ti = parseTargetInfo(buf);
LocationInfo locationInfo = LocationInfo.parseLocationInfo(buf);
Annotation a = AnnotationParser.parseAnnotation(buf, cp, container, false);
if (ti == null) // Inside a method for example
return null;
return new TypeAnnotation(ti, locationInfo, a, baseDecl);
} catch (IllegalArgumentException | // Bad type in const pool at specified index
BufferUnderflowException e) {
throw new AnnotationFormatError(e);
}
}
private static TypeAnnotationTargetInfo parseTargetInfo(ByteBuffer buf) {
int posCode = buf.get() & 0xFF;
switch(posCode) {
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER: {
int index = buf.get() & 0xFF;
TypeAnnotationTargetInfo res;
if (posCode == CLASS_TYPE_PARAMETER)
res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_TYPE_PARAMETER,
index);
else
res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_TYPE_PARAMETER,
index);
return res;
} // unreachable break;
case CLASS_EXTENDS: {
short index = buf.getShort(); //needs to be signed
if (index == -1) {
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_EXTENDS);
} else if (index >= 0) {
TypeAnnotationTargetInfo res = new TypeAnnotationTargetInfo(TypeAnnotationTarget.CLASS_IMPLEMENTS,
index);
return res;
}} break;
case CLASS_TYPE_PARAMETER_BOUND:
return parse2ByteTarget(TypeAnnotationTarget.CLASS_TYPE_PARAMETER_BOUND, buf);
case METHOD_TYPE_PARAMETER_BOUND:
return parse2ByteTarget(TypeAnnotationTarget.METHOD_TYPE_PARAMETER_BOUND, buf);
case FIELD:
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.FIELD);
case METHOD_RETURN:
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RETURN);
case METHOD_RECEIVER:
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_RECEIVER);
case METHOD_FORMAL_PARAMETER: {
int index = buf.get() & 0xFF;
return new TypeAnnotationTargetInfo(TypeAnnotationTarget.METHOD_FORMAL_PARAMETER,
index);
} //unreachable break;
case THROWS:
return parseShortTarget(TypeAnnotationTarget.THROWS, buf);
/*
* The ones below are inside method bodies, we don't care about them for core reflection
* other than adjusting for them in the byte stream.
*/
case LOCAL_VARIABLE:
case RESOURCE_VARIABLE:
short length = buf.getShort();
for (int i = 0; i < length; ++i) {
short offset = buf.getShort();
short varLength = buf.getShort();
short index = buf.getShort();
}
return null;
case EXCEPTION_PARAMETER: {
byte index = buf.get();
}
return null;
case INSTANCEOF:
case NEW:
case CONSTRUCTOR_REFERENCE:
case METHOD_REFERENCE: {
short offset = buf.getShort();
}
return null;
case CAST:
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT: {
short offset = buf.getShort();
byte index = buf.get();
}
return null;
default:
// will throw error below
break;
}
throw new AnnotationFormatError("Could not parse bytes for type annotations");
}
private static TypeAnnotationTargetInfo parseShortTarget(TypeAnnotationTarget target, ByteBuffer buf) {
int index = buf.getShort() & 0xFFFF;
return new TypeAnnotationTargetInfo(target, index);
}
private static TypeAnnotationTargetInfo parse2ByteTarget(TypeAnnotationTarget target, ByteBuffer buf) {
int count = buf.get() & 0xFF;
int secondaryIndex = buf.get() & 0xFF;
return new TypeAnnotationTargetInfo(target,
count,
secondaryIndex);
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2004, 2016, 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.*;
/**
* ExceptionProxy for TypeNotPresentException.
*
* @author Josh Bloch
* @since 1.5
*/
public class TypeNotPresentExceptionProxy extends ExceptionProxy {
private static final long serialVersionUID = 5565925172427947573L;
final String typeName;
final Throwable cause;
public TypeNotPresentExceptionProxy(String typeName, Throwable cause) {
this.typeName = typeName;
this.cause = cause;
}
protected RuntimeException generateException() {
return new TypeNotPresentException(typeName, cause);
}
public String typeName() {
return typeName;
}
public Throwable getCause() {
return cause;
}
@Override
public String toString() {
return typeName + ".class /* Warning: type not present! */";
}
}

View file

@ -0,0 +1,138 @@
/*
* Copyright (c) 2003, 2008, 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.generics.factory;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
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 sun.reflect.generics.reflectiveObjects.*;
import sun.reflect.generics.scope.Scope;
import sun.reflect.generics.tree.FieldTypeSignature;
/**
* Factory for reflective generic type objects for use by
* core reflection (java.lang.reflect).
*/
public class CoreReflectionFactory implements GenericsFactory {
private final GenericDeclaration decl;
private final Scope scope;
private CoreReflectionFactory(GenericDeclaration d, Scope s) {
decl = d;
scope = s;
}
private GenericDeclaration getDecl(){ return decl;}
private Scope getScope(){ return scope;}
private ClassLoader getDeclsLoader() {
if (decl instanceof Class) {return ((Class) decl).getClassLoader();}
if (decl instanceof Method) {
return ((Method) decl).getDeclaringClass().getClassLoader();
}
assert decl instanceof Constructor : "Constructor expected";
return ((Constructor) decl).getDeclaringClass().getClassLoader();
}
/**
* Factory for this class. Returns an instance of
* {@code CoreReflectionFactory} for the declaration and scope
* provided.
* This factory will produce reflective objects of the appropriate
* kind. Classes produced will be those that would be loaded by the
* defining class loader of the declaration {@code d} (if {@code d}
* is a type declaration, or by the defining loader of the declaring
* class of {@code d} otherwise.
* <p> Type variables will be created or lookup as necessary in the
* scope {@code s}.
* @param d - the generic declaration (class, interface, method or
* constructor) that this factory services
* @param s the scope in which the factory will allocate and search for
* type variables
* @return an instance of {@code CoreReflectionFactory}
*/
public static CoreReflectionFactory make(GenericDeclaration d, Scope s) {
return new CoreReflectionFactory(d, s);
}
public TypeVariable<?> makeTypeVariable(String name,
FieldTypeSignature[] bounds){
return TypeVariableImpl.make(getDecl(), name, bounds, this);
}
public WildcardType makeWildcard(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs) {
return WildcardTypeImpl.make(ubs, lbs, this);
}
public ParameterizedType makeParameterizedType(Type declaration,
Type[] typeArgs,
Type owner) {
return ParameterizedTypeImpl.make((Class<?>) declaration,
typeArgs, owner);
}
public TypeVariable<?> findTypeVariable(String name){
return getScope().lookup(name);
}
public Type makeNamedType(String name){
try {return Class.forName(name, false, // don't initialize
getDeclsLoader());}
catch (ClassNotFoundException c) {
throw new TypeNotPresentException(name, c);
}
}
public Type makeArrayType(Type componentType){
if (componentType instanceof Class<?>)
return Array.newInstance((Class<?>) componentType, 0).getClass();
else
return GenericArrayTypeImpl.make(componentType);
}
public Type makeByte(){return byte.class;}
public Type makeBool(){return boolean.class;}
public Type makeShort(){return short.class;}
public Type makeChar(){return char.class;}
public Type makeInt(){return int.class;}
public Type makeLong(){return long.class;}
public Type makeFloat(){return float.class;}
public Type makeDouble(){return double.class;}
public Type makeVoid(){return void.class;}
}

View file

@ -0,0 +1,190 @@
/*
* Copyright (c) 2003, 2006, 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.generics.factory;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import sun.reflect.generics.tree.FieldTypeSignature;
/**
* A factory interface for reflective objects representing generic types.
* Implementors (such as core reflection or JDI, or possibly javadoc
* will manufacture instances of (potentially) different classes
* in response to invocations of the methods described here.
* <p> The intent is that reflective systems use these factories to
* produce generic type information on demand.
* Certain components of such reflective systems can be independent
* of a specific implementation by using this interface. For example,
* repositories of generic type information are initialized with a
* factory conforming to this interface, and use it to generate the
* type information they are required to provide. As a result, such
* repository code can be shared across different reflective systems.
*/
public interface GenericsFactory {
/**
* Returns a new type variable declaration. Note that {@code name}
* may be empty (but not {@code null}). If {@code bounds} is
* empty, a bound of {@code java.lang.Object} is used.
* @param name The name of the type variable
* @param bounds An array of abstract syntax trees representing
* the upper bound(s) on the type variable being declared
* @return a new type variable declaration
* @throws NullPointerException if any of the actual parameters
* or any of the elements of {@code bounds} are {@code null}.
*/
TypeVariable<?> makeTypeVariable(String name,
FieldTypeSignature[] bounds);
/**
* Returns an instance of the {@code ParameterizedType} interface
* that corresponds to a generic type instantiation of the
* generic declaration {@code declaration} with actual type arguments
* {@code typeArgs}.
* If {@code owner} is {@code null}, the declaring class of
* {@code declaration} is used as the owner of this parameterized
* type.
* <p> This method throws a MalformedParameterizedTypeException
* under the following circumstances:
* If the type declaration does not represent a generic declaration
* (i.e., it is not an instance of {@code GenericDeclaration}).
* If the number of actual type arguments (i.e., the size of the
* array {@code typeArgs}) does not correspond to the number of
* formal type arguments.
* If any of the actual type arguments is not an instance of the
* bounds on the corresponding formal.
* @param declaration - the generic type declaration that is to be
* instantiated
* @param typeArgs - the list of actual type arguments
* @return - a parameterized type representing the instantiation
* of the declaration with the actual type arguments
* @throws MalformedParameterizedTypeException if the instantiation
* is invalid
* @throws NullPointerException if any of {@code declaration},
* {@code typeArgs}
* or any of the elements of {@code typeArgs} are {@code null}
*/
ParameterizedType makeParameterizedType(Type declaration,
Type[] typeArgs,
Type owner);
/**
* Returns the type variable with name {@code name}, if such
* a type variable is declared in the
* scope used to create this factory.
* Returns {@code null} otherwise.
* @param name - the name of the type variable to search for
* @return - the type variable with name {@code name}, or {@code null}
* @throws NullPointerException if any of actual parameters are
* {@code null}
*/
TypeVariable<?> findTypeVariable(String name);
/**
* Returns a new wildcard type variable. If
* {@code ubs} is empty, a bound of {@code java.lang.Object} is used.
* @param ubs An array of abstract syntax trees representing
* the upper bound(s) on the type variable being declared
* @param lbs An array of abstract syntax trees representing
* the lower bound(s) on the type variable being declared
* @return a new wildcard type variable
* @throws NullPointerException if any of the actual parameters
* or any of the elements of {@code ubs} or {@code lbs} are
* {@code null}
*/
WildcardType makeWildcard(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs);
Type makeNamedType(String name);
/**
* Returns a (possibly generic) array type.
* If the component type is a parameterized type, it must
* only have unbounded wildcard arguments, otherwise
* a MalformedParameterizedTypeException is thrown.
* @param componentType - the component type of the array
* @return a (possibly generic) array type.
* @throws MalformedParameterizedTypeException if {@code componentType}
* is a parameterized type with non-wildcard type arguments
* @throws NullPointerException if any of the actual parameters
* are {@code null}
*/
Type makeArrayType(Type componentType);
/**
* Returns the reflective representation of type {@code byte}.
* @return the reflective representation of type {@code byte}.
*/
Type makeByte();
/**
* Returns the reflective representation of type {@code boolean}.
* @return the reflective representation of type {@code boolean}.
*/
Type makeBool();
/**
* Returns the reflective representation of type {@code short}.
* @return the reflective representation of type {@code short}.
*/
Type makeShort();
/**
* Returns the reflective representation of type {@code char}.
* @return the reflective representation of type {@code char}.
*/
Type makeChar();
/**
* Returns the reflective representation of type {@code int}.
* @return the reflective representation of type {@code int}.
*/
Type makeInt();
/**
* Returns the reflective representation of type {@code long}.
* @return the reflective representation of type {@code long}.
*/
Type makeLong();
/**
* Returns the reflective representation of type {@code float}.
* @return the reflective representation of type {@code float}.
*/
Type makeFloat();
/**
* Returns the reflective representation of type {@code double}.
* @return the reflective representation of type {@code double}.
*/
Type makeDouble();
/**
* Returns the reflective representation of {@code void}.
* @return the reflective representation of {@code void}.
*/
Type makeVoid();
}

View file

@ -0,0 +1,634 @@
/*
* Copyright (c) 2003, 2016, 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.generics.parser;
import java.lang.reflect.GenericSignatureFormatError;
import java.util.*;
import sun.reflect.generics.tree.*;
/**
* Parser for type signatures, as defined in the Java Virtual
* Machine Specification (JVMS) chapter 4.
* Converts the signatures into an abstract syntax tree (AST) representation.
* See the package sun.reflect.generics.tree for details of the AST.
*/
public class SignatureParser {
// The input is conceptually a character stream (though currently it's
// a string). This is slightly different than traditional parsers,
// because there is no lexical scanner performing tokenization.
// Having a separate tokenizer does not fit with the nature of the
// input format.
// Other than the absence of a tokenizer, this parser is a classic
// recursive descent parser. Its structure corresponds as closely
// as possible to the grammar in the JVMS.
//
// A note on asserts vs. errors: The code contains assertions
// in situations that should never occur. An assertion failure
// indicates a failure of the parser logic. A common pattern
// is an assertion that the current input is a particular
// character. This is often paired with a separate check
// that this is the case, which seems redundant. For example:
//
// assert(current() != x);
// if (current != x {error("expected an x");
//
// where x is some character constant.
// The assertion indicates, that, as currently written,
// the code should never reach this point unless the input is an
// x. On the other hand, the test is there to check the legality
// of the input wrt to a given production. It may be that at a later
// time the code might be called directly, and if the input is
// invalid, the parser should flag an error in accordance
// with its logic.
private String input; // the input signature
private int index; // index into the input
private int mark; // index of mark
// used to mark end of input
private static final char EOI = ':';
private static final boolean DEBUG = false;
// private constructor - enforces use of static factory
private SignatureParser(){}
// prepares parser for new parsing session
private void init(String s) {
input = s;
mark = index = 0;
}
// Utility methods.
// Most parsing routines use the following routines to access the
// input stream, and advance it as necessary.
// This makes it easy to adapt the parser to operate on streams
// of various kinds as well as strings.
// returns current element of the input
private char current(){
assert(index <= input.length());
return index < input.length() ? input.charAt(index) : EOI;
}
// advance the input
private void advance(){
assert(index <= input.length());
if (index < input.length()) index++;
}
// mark current position
private void mark() {
mark = index;
}
// For debugging, prints current character to the end of the input.
private String remainder() {
return input.substring(index);
}
// returns a substring of input from mark (inclusive)
// to current position (exclusive)
private String markToCurrent() {
return input.substring(mark, index);
}
// Error handling routine. Encapsulates error handling.
// Takes a string error message as argument.
// Currently throws a GenericSignatureFormatError.
private Error error(String errorMsg) {
return new GenericSignatureFormatError("Signature Parse error: " + errorMsg +
"\n\tRemaining input: " + remainder());
}
/**
* Verify the parse has made forward progress; throw an exception
* if no progress.
*/
private void progress(int startingPosition) {
if (index <= startingPosition)
throw error("Failure to make progress!");
}
/**
* Static factory method. Produces a parser instance.
* @return an instance of {@code SignatureParser}
*/
public static SignatureParser make() {
return new SignatureParser();
}
/**
* Parses a class signature (as defined in the JVMS, chapter 4)
* and produces an abstract syntax tree representing it.
* @param s a string representing the input class signature
* @return An abstract syntax tree for a class signature
* corresponding to the input string
* @throws GenericSignatureFormatError if the input is not a valid
* class signature
*/
public ClassSignature parseClassSig(String s) {
if (DEBUG) System.out.println("Parsing class sig:" + s);
init(s);
return parseClassSignature();
}
/**
* Parses a method signature (as defined in the JVMS, chapter 4)
* and produces an abstract syntax tree representing it.
* @param s a string representing the input method signature
* @return An abstract syntax tree for a method signature
* corresponding to the input string
* @throws GenericSignatureFormatError if the input is not a valid
* method signature
*/
public MethodTypeSignature parseMethodSig(String s) {
if (DEBUG) System.out.println("Parsing method sig:" + s);
init(s);
return parseMethodTypeSignature();
}
/**
* Parses a type signature
* and produces an abstract syntax tree representing it.
*
* @param s a string representing the input type signature
* @return An abstract syntax tree for a type signature
* corresponding to the input string
* @throws GenericSignatureFormatError if the input is not a valid
* type signature
*/
public TypeSignature parseTypeSig(String s) {
if (DEBUG) System.out.println("Parsing type sig:" + s);
init(s);
return parseTypeSignature();
}
// Parsing routines.
// As a rule, the parsing routines access the input using the
// utilities current() and advance().
// The convention is that when a parsing routine is invoked
// it expects the current input to be the first character it should parse
// and when it completes parsing, it leaves the input at the first
// character after the input parses.
/*
* Note on grammar conventions: a trailing "*" matches zero or
* more occurrences, a trailing "+" matches one or more occurrences,
* "_opt" indicates an optional component.
*/
/**
* ClassSignature:
* FormalTypeParameters_opt SuperclassSignature SuperinterfaceSignature*
*/
private ClassSignature parseClassSignature() {
// parse a class signature based on the implicit input.
assert(index == 0);
return ClassSignature.make(parseZeroOrMoreFormalTypeParameters(),
parseClassTypeSignature(), // Only rule for SuperclassSignature
parseSuperInterfaces());
}
private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters(){
if (current() == '<') {
return parseFormalTypeParameters();
} else {
return new FormalTypeParameter[0];
}
}
/**
* FormalTypeParameters:
* "<" FormalTypeParameter+ ">"
*/
private FormalTypeParameter[] parseFormalTypeParameters(){
List<FormalTypeParameter> ftps = new ArrayList<>(3);
assert(current() == '<'); // should not have been called at all
if (current() != '<') { throw error("expected '<'");}
advance();
ftps.add(parseFormalTypeParameter());
while (current() != '>') {
int startingPosition = index;
ftps.add(parseFormalTypeParameter());
progress(startingPosition);
}
advance();
return ftps.toArray(new FormalTypeParameter[ftps.size()]);
}
/**
* FormalTypeParameter:
* Identifier ClassBound InterfaceBound*
*/
private FormalTypeParameter parseFormalTypeParameter(){
String id = parseIdentifier();
FieldTypeSignature[] bs = parseBounds();
return FormalTypeParameter.make(id, bs);
}
private String parseIdentifier() {
mark();
skipIdentifier();
return markToCurrent();
}
private void skipIdentifier() {
char c = current();
while (c != ';' && c != '.' && c != '/' &&
c != '[' && c != ':' && c != '>' &&
c != '<' && !Character.isWhitespace(c)) {
advance();
c = current();
}
}
/**
* FieldTypeSignature:
* ClassTypeSignature
* ArrayTypeSignature
* TypeVariableSignature
*/
private FieldTypeSignature parseFieldTypeSignature() {
return parseFieldTypeSignature(true);
}
private FieldTypeSignature parseFieldTypeSignature(boolean allowArrays) {
switch(current()) {
case 'L':
return parseClassTypeSignature();
case 'T':
return parseTypeVariableSignature();
case '[':
if (allowArrays)
return parseArrayTypeSignature();
else
throw error("Array signature not allowed here.");
default: throw error("Expected Field Type Signature");
}
}
/**
* ClassTypeSignature:
* "L" PackageSpecifier_opt SimpleClassTypeSignature ClassTypeSignatureSuffix* ";"
*/
private ClassTypeSignature parseClassTypeSignature(){
assert(current() == 'L');
if (current() != 'L') { throw error("expected a class type");}
advance();
List<SimpleClassTypeSignature> scts = new ArrayList<>(5);
scts.add(parsePackageNameAndSimpleClassTypeSignature());
parseClassTypeSignatureSuffix(scts);
if (current() != ';')
throw error("expected ';' got '" + current() + "'");
advance();
return ClassTypeSignature.make(scts);
}
/**
* PackageSpecifier:
* Identifier "/" PackageSpecifier*
*/
private SimpleClassTypeSignature parsePackageNameAndSimpleClassTypeSignature() {
// Parse both any optional leading PackageSpecifier as well as
// the following SimpleClassTypeSignature.
mark();
skipIdentifier();
while (current() == '/') {
advance();
skipIdentifier();
}
String id = markToCurrent().replace('/', '.');
switch (current()) {
case ';':
return SimpleClassTypeSignature.make(id, false, new TypeArgument[0]); // all done!
case '<':
if (DEBUG) System.out.println("\t remainder: " + remainder());
return SimpleClassTypeSignature.make(id, false, parseTypeArguments());
default:
throw error("expected '<' or ';' but got " + current());
}
}
/**
* SimpleClassTypeSignature:
* Identifier TypeArguments_opt
*/
private SimpleClassTypeSignature parseSimpleClassTypeSignature(boolean dollar){
String id = parseIdentifier();
char c = current();
switch (c) {
case ';':
case '.':
return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]) ;
case '<':
return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments());
default:
throw error("expected '<' or ';' or '.', got '" + c + "'.");
}
}
/**
* ClassTypeSignatureSuffix:
* "." SimpleClassTypeSignature
*/
private void parseClassTypeSignatureSuffix(List<SimpleClassTypeSignature> scts) {
while (current() == '.') {
advance();
scts.add(parseSimpleClassTypeSignature(true));
}
}
/**
* TypeArguments:
* "<" TypeArgument+ ">"
*/
private TypeArgument[] parseTypeArguments() {
List<TypeArgument> tas = new ArrayList<>(3);
assert(current() == '<');
if (current() != '<') { throw error("expected '<'");}
advance();
tas.add(parseTypeArgument());
while (current() != '>') {
//(matches(current(), '+', '-', 'L', '[', 'T', '*')) {
tas.add(parseTypeArgument());
}
advance();
return tas.toArray(new TypeArgument[tas.size()]);
}
/**
* TypeArgument:
* WildcardIndicator_opt FieldTypeSignature
* "*"
*/
private TypeArgument parseTypeArgument() {
FieldTypeSignature[] ub, lb;
ub = new FieldTypeSignature[1];
lb = new FieldTypeSignature[1];
TypeArgument[] ta = new TypeArgument[0];
char c = current();
switch (c) {
case '+': {
advance();
ub[0] = parseFieldTypeSignature();
lb[0] = BottomSignature.make(); // bottom
return Wildcard.make(ub, lb);
}
case '*':{
advance();
ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
lb[0] = BottomSignature.make(); // bottom
return Wildcard.make(ub, lb);
}
case '-': {
advance();
lb[0] = parseFieldTypeSignature();
ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
return Wildcard.make(ub, lb);
}
default:
return parseFieldTypeSignature();
}
}
/**
* TypeVariableSignature:
* "T" Identifier ";"
*/
private TypeVariableSignature parseTypeVariableSignature() {
assert(current() == 'T');
if (current() != 'T') { throw error("expected a type variable usage");}
advance();
TypeVariableSignature ts = TypeVariableSignature.make(parseIdentifier());
if (current() != ';') {
throw error("; expected in signature of type variable named" +
ts.getIdentifier());
}
advance();
return ts;
}
/**
* ArrayTypeSignature:
* "[" TypeSignature
*/
private ArrayTypeSignature parseArrayTypeSignature() {
if (current() != '[') {throw error("expected array type signature");}
advance();
return ArrayTypeSignature.make(parseTypeSignature());
}
/**
* TypeSignature:
* FieldTypeSignature
* BaseType
*/
private TypeSignature parseTypeSignature() {
switch (current()) {
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z':
return parseBaseType();
default:
return parseFieldTypeSignature();
}
}
private BaseType parseBaseType() {
switch(current()) {
case 'B':
advance();
return ByteSignature.make();
case 'C':
advance();
return CharSignature.make();
case 'D':
advance();
return DoubleSignature.make();
case 'F':
advance();
return FloatSignature.make();
case 'I':
advance();
return IntSignature.make();
case 'J':
advance();
return LongSignature.make();
case 'S':
advance();
return ShortSignature.make();
case 'Z':
advance();
return BooleanSignature.make();
default: {
assert(false);
throw error("expected primitive type");
}
}
}
/**
* ClassBound:
* ":" FieldTypeSignature_opt
*
* InterfaceBound:
* ":" FieldTypeSignature
*/
private FieldTypeSignature[] parseBounds() {
List<FieldTypeSignature> fts = new ArrayList<>(3);
if (current() == ':') {
advance();
switch(current()) {
case ':': // empty class bound
break;
default: // parse class bound
fts.add(parseFieldTypeSignature());
}
// zero or more interface bounds
while (current() == ':') {
advance();
fts.add(parseFieldTypeSignature());
}
} else
error("Bound expected");
return fts.toArray(new FieldTypeSignature[fts.size()]);
}
/**
* SuperclassSignature:
* ClassTypeSignature
*/
private ClassTypeSignature[] parseSuperInterfaces() {
List<ClassTypeSignature> cts = new ArrayList<>(5);
while(current() == 'L') {
cts.add(parseClassTypeSignature());
}
return cts.toArray(new ClassTypeSignature[cts.size()]);
}
/**
* MethodTypeSignature:
* FormalTypeParameters_opt "(" TypeSignature* ")" ReturnType ThrowsSignature*
*/
private MethodTypeSignature parseMethodTypeSignature() {
// Parse a method signature based on the implicit input.
FieldTypeSignature[] ets;
assert(index == 0);
return MethodTypeSignature.make(parseZeroOrMoreFormalTypeParameters(),
parseFormalParameters(),
parseReturnType(),
parseZeroOrMoreThrowsSignatures());
}
// "(" TypeSignature* ")"
private TypeSignature[] parseFormalParameters() {
if (current() != '(') {throw error("expected '('");}
advance();
TypeSignature[] pts = parseZeroOrMoreTypeSignatures();
if (current() != ')') {throw error("expected ')'");}
advance();
return pts;
}
// TypeSignature*
private TypeSignature[] parseZeroOrMoreTypeSignatures() {
List<TypeSignature> ts = new ArrayList<>();
boolean stop = false;
while (!stop) {
switch(current()) {
case 'B':
case 'C':
case 'D':
case 'F':
case 'I':
case 'J':
case 'S':
case 'Z':
case 'L':
case 'T':
case '[': {
ts.add(parseTypeSignature());
break;
}
default: stop = true;
}
}
return ts.toArray(new TypeSignature[ts.size()]);
}
/**
* ReturnType:
* TypeSignature
* VoidDescriptor
*/
private ReturnType parseReturnType(){
if (current() == 'V') {
advance();
return VoidDescriptor.make();
} else
return parseTypeSignature();
}
// ThrowSignature*
private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures(){
List<FieldTypeSignature> ets = new ArrayList<>(3);
while( current() == '^') {
ets.add(parseThrowsSignature());
}
return ets.toArray(new FieldTypeSignature[ets.size()]);
}
/**
* ThrowsSignature:
* "^" ClassTypeSignature
* "^" TypeVariableSignature
*/
private FieldTypeSignature parseThrowsSignature() {
assert(current() == '^');
if (current() != '^') { throw error("expected throws signature");}
advance();
return parseFieldTypeSignature(false);
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2003, 2016, 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.generics.reflectiveObjects;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.util.Objects;
/**
* Implementation of GenericArrayType interface for core reflection.
*/
public class GenericArrayTypeImpl
implements GenericArrayType {
private final Type genericComponentType;
// private constructor enforces use of static factory
private GenericArrayTypeImpl(Type ct) {
genericComponentType = ct;
}
/**
* Factory method.
* @param ct - the desired component type of the generic array type
* being created
* @return a generic array type with the desired component type
*/
public static GenericArrayTypeImpl make(Type ct) {
return new GenericArrayTypeImpl(ct);
}
/**
* Returns a {@code Type} object representing the component type
* of this array.
*
* @return a {@code Type} object representing the component type
* of this array
* @since 1.5
*/
public Type getGenericComponentType() {
return genericComponentType; // return cached component type
}
public String toString() {
return getGenericComponentType().getTypeName() + "[]";
}
@Override
public boolean equals(Object o) {
if (o instanceof GenericArrayType) {
GenericArrayType that = (GenericArrayType) o;
return Objects.equals(genericComponentType, that.getGenericComponentType());
} else
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(genericComponentType);
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2003, 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.generics.reflectiveObjects;
import java.lang.reflect.Type;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.visitor.Reifier;
/**
* Common infrastructure for things that lazily generate reflective generics
* objects.
* <p> In all these cases, one needs produce a visitor that will, on demand,
* traverse the stored AST(s) and reify them into reflective objects.
* The visitor needs to be initialized with a factory, which will be
* provided when the instance is initialized.
* The factory should be cached.
*
*/
public abstract class LazyReflectiveObjectGenerator {
private final GenericsFactory factory; // cached factory
protected LazyReflectiveObjectGenerator(GenericsFactory f) {
factory = f;
}
// accessor for factory
private GenericsFactory getFactory() {
return factory;
}
// produce a reifying visitor (could this be typed as a TypeTreeVisitor?
protected Reifier getReifier(){return Reifier.make(getFactory());}
Type[] reifyBounds(FieldTypeSignature[] boundASTs) {
final int length = boundASTs.length;
final Type[] bounds = new Type[length];
// iterate over bound trees, reifying each in turn
for (int i = 0; i < length; i++) {
Reifier r = getReifier();
boundASTs[i].accept(r);
bounds[i] = r.getResult();
}
return bounds;
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2003, 2011, 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.generics.reflectiveObjects;
/** Temporary class used to indicate missing functionality */
public class NotImplementedException extends RuntimeException {
private static final long serialVersionUID = -9177857708926624790L;
}

View file

@ -0,0 +1,236 @@
/*
* Copyright (c) 2003, 2016, 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.generics.reflectiveObjects;
import sun.reflect.generics.tree.FieldTypeSignature;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.StringJoiner;
import java.util.Objects;
/** Implementing class for ParameterizedType interface. */
public class ParameterizedTypeImpl implements ParameterizedType {
private final Type[] actualTypeArguments;
private final Class<?> rawType;
private final Type ownerType;
private ParameterizedTypeImpl(Class<?> rawType,
Type[] actualTypeArguments,
Type ownerType) {
this.actualTypeArguments = actualTypeArguments;
this.rawType = rawType;
this.ownerType = (ownerType != null) ? ownerType : rawType.getDeclaringClass();
validateConstructorArguments();
}
private void validateConstructorArguments() {
TypeVariable<?>[] formals = rawType.getTypeParameters();
// check correct arity of actual type args
if (formals.length != actualTypeArguments.length){
throw new MalformedParameterizedTypeException();
}
for (int i = 0; i < actualTypeArguments.length; i++) {
// check actuals against formals' bounds
}
}
/**
* Static factory. Given a (generic) class, actual type arguments
* and an owner type, creates a parameterized type.
* This class can be instantiated with a a raw type that does not
* represent a generic type, provided the list of actual type
* arguments is empty.
* If the ownerType argument is null, the declaring class of the
* raw type is used as the owner type.
* <p> This method throws a MalformedParameterizedTypeException
* under the following circumstances:
* If the number of actual type arguments (i.e., the size of the
* array {@code typeArgs}) does not correspond to the number of
* formal type arguments.
* If any of the actual type arguments is not an instance of the
* bounds on the corresponding formal.
* @param rawType the Class representing the generic type declaration being
* instantiated
* @param actualTypeArguments a (possibly empty) array of types
* representing the actual type arguments to the parameterized type
* @param ownerType the enclosing type, if known.
* @return An instance of {@code ParameterizedType}
* @throws MalformedParameterizedTypeException if the instantiation
* is invalid
*/
public static ParameterizedTypeImpl make(Class<?> rawType,
Type[] actualTypeArguments,
Type ownerType) {
return new ParameterizedTypeImpl(rawType, actualTypeArguments,
ownerType);
}
/**
* Returns an array of {@code Type} objects representing the actual type
* arguments to this type.
*
* <p>Note that in some cases, the returned array be empty. This can occur
* if this type represents a non-parameterized type nested within
* a parameterized type.
*
* @return an array of {@code Type} objects representing the actual type
* arguments to this type
* @throws TypeNotPresentException if any of the
* actual type arguments refers to a non-existent type declaration
* @throws MalformedParameterizedTypeException if any of the
* actual type parameters refer to a parameterized type that cannot
* be instantiated for any reason
* @since 1.5
*/
public Type[] getActualTypeArguments() {
return actualTypeArguments.clone();
}
/**
* Returns the {@code Type} object representing the class or interface
* that declared this type.
*
* @return the {@code Type} object representing the class or interface
* that declared this type
*/
public Class<?> getRawType() {
return rawType;
}
/**
* Returns a {@code Type} object representing the type that this type
* is a member of. For example, if this type is {@code O<T>.I<S>},
* return a representation of {@code O<T>}.
*
* <p>If this type is a top-level type, {@code null} is returned.
*
* @return a {@code Type} object representing the type that
* this type is a member of. If this type is a top-level type,
* {@code null} is returned
* @throws TypeNotPresentException if the owner type
* refers to a non-existent type declaration
* @throws MalformedParameterizedTypeException if the owner type
* refers to a parameterized type that cannot be instantiated
* for any reason
*
*/
public Type getOwnerType() {
return ownerType;
}
/*
* From the JavaDoc for java.lang.reflect.ParameterizedType
* "Instances of classes that implement this interface must
* implement an equals() method that equates any two instances
* that share the same generic type declaration and have equal
* type parameters."
*/
@Override
public boolean equals(Object o) {
if (o instanceof ParameterizedType) {
// Check that information is equivalent
ParameterizedType that = (ParameterizedType) o;
if (this == that)
return true;
Type thatOwner = that.getOwnerType();
Type thatRawType = that.getRawType();
if (false) { // Debugging
boolean ownerEquality = (ownerType == null ?
thatOwner == null :
ownerType.equals(thatOwner));
boolean rawEquality = (rawType == null ?
thatRawType == null :
rawType.equals(thatRawType));
boolean typeArgEquality = Arrays.equals(actualTypeArguments, // avoid clone
that.getActualTypeArguments());
for (Type t : actualTypeArguments) {
System.out.printf("\t\t%s%s%n", t, t.getClass());
}
System.out.printf("\towner %s\traw %s\ttypeArg %s%n",
ownerEquality, rawEquality, typeArgEquality);
return ownerEquality && rawEquality && typeArgEquality;
}
return
Objects.equals(ownerType, thatOwner) &&
Objects.equals(rawType, thatRawType) &&
Arrays.equals(actualTypeArguments, // avoid clone
that.getActualTypeArguments());
} else
return false;
}
@Override
public int hashCode() {
return
Arrays.hashCode(actualTypeArguments) ^
Objects.hashCode(ownerType) ^
Objects.hashCode(rawType);
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (ownerType != null) {
sb.append(ownerType.getTypeName());
sb.append("$");
if (ownerType instanceof ParameterizedTypeImpl) {
// Find simple name of nested type by removing the
// shared prefix with owner.
sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$",
""));
} else
sb.append(rawType.getSimpleName());
} else
sb.append(rawType.getName());
if (actualTypeArguments != null) {
StringJoiner sj = new StringJoiner(", ", "<", ">");
sj.setEmptyValue("");
for(Type t: actualTypeArguments) {
sj.add(t.getTypeName());
}
sb.append(sj.toString());
}
return sb.toString();
}
}

View file

@ -0,0 +1,249 @@
/*
* Copyright (c) 2003, 2013, 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.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;
/**
* Implementation of {@code java.lang.reflect.TypeVariable} interface
* for core reflection.
*/
public class TypeVariableImpl<D extends GenericDeclaration>
extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
private final D genericDeclaration;
private final String name;
/**
* The upper bounds. Lazily converted from FieldTypeSignature[] to Type[].
* We are required to evaluate the bounds lazily, so we store them as ASTs
* until we are first asked for them. This also neatly solves the problem
* with F-bounds - you can't reify them before the formal is defined.
*/
private volatile Object[] bounds;
// constructor is private to enforce access through static factory
private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
GenericsFactory f) {
super(f);
genericDeclaration = decl;
name = n;
bounds = bs;
}
/**
* Factory method.
* @param decl - the reflective object that declared the type variable
* that this method should create
* @param name - the name of the type variable to be returned
* @param bs - an array of ASTs representing the bounds for the type
* variable to be created
* @param f - a factory that can be used to manufacture reflective
* objects that represent the bounds of this type variable
* @return A type variable with name, bounds, declaration and factory
* specified
*/
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);
}
/**
* Returns an array of {@code Type} objects representing the
* upper bound(s) of this type variable. Note that if no upper bound is
* explicitly declared, the upper bound is {@code Object}.
*
* <p>For each upper bound B:
* <ul>
* <li>if B is a parameterized type or a type variable, it is created,
* (see {@link #ParameterizedType} for the details of the creation
* process for parameterized types).
* <li>Otherwise, B is resolved.
* </ul>
*
* @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
* @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
* @return an array of Types representing the upper bound(s) of this
* type variable
*/
public Type[] getBounds() {
Object[] value = bounds;
if (value instanceof FieldTypeSignature[]) {
value = reifyBounds((FieldTypeSignature[])value);
bounds = value;
}
return (Type[])value.clone();
}
/**
* Returns the {@code GenericDeclaration} object representing the
* generic declaration that declared this type variable.
*
* @return the generic declaration that declared this type variable.
*
* @since 1.5
*/
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;
}
/**
* Returns the name of this type variable, as it occurs in the source code.
*
* @return the name of this type variable, as it appears in the source code
*/
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();
}
// Implementations of AnnotatedElement methods.
@SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
// T is an Annotation type, the return value of get will be an annotation
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];
// Helpers for annotation methods
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;
}
}

View file

@ -0,0 +1,189 @@
/*
* Copyright (c) 2003, 2016, 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.generics.reflectiveObjects;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.visitor.Reifier;
import java.util.Arrays;
import java.util.StringJoiner;
/**
* Implementation of WildcardType interface for core reflection.
*/
public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
implements WildcardType {
/*
* We are required to evaluate the bounds lazily, so we store them as ASTs
* until we are first asked for them. This also neatly solves the problem
* with F-bounds - you can't reify them before the formal is defined.
*/
/** The upper bounds. Lazily converted from FieldTypeSignature[] to Type[]. */
private volatile Object[] upperBounds;
/** The lower bounds. Lazily converted from FieldTypeSignature[] to Type[]. */
private volatile Object[] lowerBounds;
// constructor is private to enforce access through static factory
private WildcardTypeImpl(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs,
GenericsFactory f) {
super(f);
upperBounds = ubs;
lowerBounds = lbs;
}
/**
* Factory method.
* @param ubs - an array of ASTs representing the upper bounds for the type
* variable to be created
* @param lbs - an array of ASTs representing the lower bounds for the type
* variable to be created
* @param f - a factory that can be used to manufacture reflective
* objects that represent the bounds of this wildcard type
* @return a wild card type with the requested bounds and factory
*/
public static WildcardTypeImpl make(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs,
GenericsFactory f) {
return new WildcardTypeImpl(ubs, lbs, f);
}
/**
* Returns an array of {@code Type} objects representing the upper
* bound(s) of this type variable. Note that if no upper bound is
* explicitly declared, the upper bound is {@code Object}.
*
* <p>For each upper bound B :
* <ul>
* <li>if B is a parameterized type or a type variable, it is created,
* (see {@link #ParameterizedType} for the details of the creation
* process for parameterized types).
* <li>Otherwise, B is resolved.
* </ul>
*
* @return an array of Types representing the upper bound(s) of this
* type variable
* @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
* @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
*/
public Type[] getUpperBounds() {
Object[] value = upperBounds;
if (value instanceof FieldTypeSignature[]) {
value = reifyBounds((FieldTypeSignature[])value);
upperBounds = value;
}
return (Type[])value.clone();
}
/**
* Returns an array of {@code Type} objects representing the
* lower bound(s) of this type variable. Note that if no lower bound is
* explicitly declared, the lower bound is the type of {@code null}.
* In this case, a zero length array is returned.
*
* <p>For each lower bound B :
* <ul>
* <li>if B is a parameterized type or a type variable, it is created,
* (see {@link #ParameterizedType} for the details of the creation
* process for parameterized types).
* <li>Otherwise, B is resolved.
* </ul>
*
* @return an array of Types representing the lower bound(s) of this
* type variable
* @throws {@code TypeNotPresentException} if any of the
* bounds refers to a non-existent type declaration
* @throws {@code MalformedParameterizedTypeException} if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
*/
public Type[] getLowerBounds() {
Object[] value = lowerBounds;
if (value instanceof FieldTypeSignature[]) {
value = reifyBounds((FieldTypeSignature[])value);
lowerBounds = value;
}
return (Type[])value.clone();
}
public String toString() {
Type[] lowerBounds = getLowerBounds();
Type[] bounds = lowerBounds;
StringBuilder sb = new StringBuilder();
if (lowerBounds.length > 0)
sb.append("? super ");
else {
Type[] upperBounds = getUpperBounds();
if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class) ) {
bounds = upperBounds;
sb.append("? extends ");
} else
return "?";
}
assert bounds.length > 0;
StringJoiner sj = new StringJoiner(" & ");
for(Type bound: bounds) {
sj.add(bound.getTypeName());
}
sb.append(sj.toString());
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (o instanceof WildcardType) {
WildcardType that = (WildcardType) o;
return
Arrays.equals(this.getLowerBounds(),
that.getLowerBounds()) &&
Arrays.equals(this.getUpperBounds(),
that.getUpperBounds());
} else
return false;
}
@Override
public int hashCode() {
Type [] lowerBounds = getLowerBounds();
Type [] upperBounds = getUpperBounds();
return Arrays.hashCode(lowerBounds) ^ Arrays.hashCode(upperBounds);
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2003, 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.generics.repository;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.Tree;
import sun.reflect.generics.visitor.Reifier;
/**
* Abstract superclass for representing the generic type information for
* a reflective entity.
* The code is not dependent on a particular reflective implementation.
* It is designed to be used unchanged by at least core reflection and JDI.
*/
public abstract class AbstractRepository<T extends Tree> {
// A factory used to produce reflective objects. Provided when the
//repository is created. Will vary across implementations.
private final GenericsFactory factory;
private final T tree; // the AST for the generic type info
//accessors
private GenericsFactory getFactory() { return factory;}
/**
* Accessor for {@code tree}.
* @return the cached AST this repository holds
*/
protected T getTree(){ return tree;}
/**
* Returns a {@code Reifier} used to convert parts of the
* AST into reflective objects.
* @return a {@code Reifier} used to convert parts of the
* AST into reflective objects
*/
protected Reifier getReifier(){return Reifier.make(getFactory());}
/**
* Constructor. Should only be used by subclasses. Concrete subclasses
* should make their constructors private and provide public factory
* methods.
* @param rawSig - the generic signature of the reflective object
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
*/
protected AbstractRepository(String rawSig, GenericsFactory f) {
tree = parse(rawSig);
factory = f;
}
/**
* Returns the AST for the generic type info of this entity.
* @param s - a string representing the generic signature of this
* entity
* @return the AST for the generic type info of this entity.
*/
protected abstract T parse(String s);
}

View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 2003, 2013, 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.generics.repository;
import java.lang.reflect.Type;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.ClassSignature;
import sun.reflect.generics.tree.TypeTree;
import sun.reflect.generics.visitor.Reifier;
import sun.reflect.generics.parser.SignatureParser;
/**
* This class represents the generic type information for a class.
* The code is not dependent on a particular reflective implementation.
* It is designed to be used unchanged by at least core reflection and JDI.
*/
public class ClassRepository extends GenericDeclRepository<ClassSignature> {
public static final ClassRepository NONE = ClassRepository.make("Ljava/lang/Object;", null);
/** The generic superclass info. Lazily initialized. */
private volatile Type superclass;
/** The generic superinterface info. Lazily initialized. */
private volatile Type[] superInterfaces;
// private, to enforce use of static factory
private ClassRepository(String rawSig, GenericsFactory f) {
super(rawSig, f);
}
protected ClassSignature parse(String s) {
return SignatureParser.make().parseClassSig(s);
}
/**
* Static factory method.
* @param rawSig - the generic signature of the reflective object
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
* @return a {@code ClassRepository} that manages the generic type
* information represented in the signature {@code rawSig}
*/
public static ClassRepository make(String rawSig, GenericsFactory f) {
return new ClassRepository(rawSig, f);
}
/*
* When queried for a particular piece of type information, the
* general pattern is to consult the corresponding cached value.
* If the corresponding field is non-null, it is returned.
* If not, it is created lazily. This is done by selecting the appropriate
* part of the tree and transforming it into a reflective object
* using a visitor, which is created by feeding it the factory
* with which the repository was created.
*/
public Type getSuperclass() {
Type value = superclass;
if (value == null) {
value = computeSuperclass();
superclass = value;
}
return value;
}
public Type[] getSuperInterfaces() {
Type[] value = superInterfaces;
if (value == null) {
value = computeSuperInterfaces();
superInterfaces = value;
}
return value.clone();
}
private Type computeSuperclass() {
Reifier r = getReifier(); // obtain visitor
// Extract superclass subtree from AST and reify
getTree().getSuperclass().accept(r);
return r.getResult();
}
private Type[] computeSuperInterfaces() {
// first, extract super interface subtree(s) from AST
TypeTree[] ts = getTree().getSuperInterfaces();
// create array to store reified subtree(s)
int length = ts.length;
Type[] superInterfaces = new Type[length];
// reify all subtrees
for (int i = 0; i < length; i++) {
Reifier r = getReifier(); // obtain visitor
ts[i].accept(r);// reify subtree
// extract result from visitor and store it
superInterfaces[i] = r.getResult();
}
return superInterfaces;
}
}

View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 2003, 2004, 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.generics.repository;
import java.lang.reflect.Type;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.parser.SignatureParser;
import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.tree.MethodTypeSignature;
import sun.reflect.generics.tree.TypeSignature;
import sun.reflect.generics.visitor.Reifier;
/**
* This class represents the generic type information for a constructor.
* The code is not dependent on a particular reflective implementation.
* It is designed to be used unchanged by at least core reflection and JDI.
*/
public class ConstructorRepository
extends GenericDeclRepository<MethodTypeSignature> {
/** The generic parameter types. Lazily initialized. */
private volatile Type[] parameterTypes;
/** The generic exception types. Lazily initialized. */
private volatile Type[] exceptionTypes;
// protected, to enforce use of static factory yet allow subclassing
protected ConstructorRepository(String rawSig, GenericsFactory f) {
super(rawSig, f);
}
protected MethodTypeSignature parse(String s) {
return SignatureParser.make().parseMethodSig(s);
}
/**
* Static factory method.
* @param rawSig - the generic signature of the reflective object
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
* @return a {@code ConstructorRepository} that manages the generic type
* information represented in the signature {@code rawSig}
*/
public static ConstructorRepository make(String rawSig, GenericsFactory f) {
return new ConstructorRepository(rawSig, f);
}
/*
* When queried for a particular piece of type information, the
* general pattern is to consult the corresponding cached value.
* If the corresponding field is non-null, it is returned.
* If not, it is created lazily. This is done by selecting the appropriate
* part of the tree and transforming it into a reflective object
* using a visitor, which is created by feeding it the factory
* with which the repository was created.
*/
public Type[] getParameterTypes() {
Type[] value = parameterTypes;
if (value == null) {
value = computeParameterTypes();
parameterTypes = value;
}
return value.clone();
}
public Type[] getExceptionTypes() {
Type[] value = exceptionTypes;
if (value == null) {
value = computeExceptionTypes();
exceptionTypes = value;
}
return value.clone();
}
private Type[] computeParameterTypes() {
// first, extract parameter type subtree(s) from AST
TypeSignature[] pts = getTree().getParameterTypes();
// create array to store reified subtree(s)
int length = pts.length;
Type[] parameterTypes = new Type[length];
// reify all subtrees
for (int i = 0; i < length; i++) {
Reifier r = getReifier(); // obtain visitor
pts[i].accept(r); // reify subtree
// extract result from visitor and store it
parameterTypes[i] = r.getResult();
}
return parameterTypes;
}
private Type[] computeExceptionTypes() {
// first, extract exception type subtree(s) from AST
FieldTypeSignature[] ets = getTree().getExceptionTypes();
// create array to store reified subtree(s)
int length = ets.length;
Type[] exceptionTypes = new Type[length];
// reify all subtrees
for (int i = 0; i < length; i++) {
Reifier r = getReifier(); // obtain visitor
ets[i].accept(r); // reify subtree
// extract result from visitor and store it
exceptionTypes[i] = r.getResult();
}
return exceptionTypes;
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2003, 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.generics.repository;
import java.lang.reflect.Type;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.TypeSignature;
import sun.reflect.generics.parser.SignatureParser;
import sun.reflect.generics.visitor.Reifier;
/**
* This class represents the generic type information for a constructor.
* The code is not dependent on a particular reflective implementation.
* It is designed to be used unchanged by at least core reflection and JDI.
*/
public class FieldRepository extends AbstractRepository<TypeSignature> {
/** The generic type info. Lazily initialized. */
private volatile Type genericType;
// protected, to enforce use of static factory yet allow subclassing
protected FieldRepository(String rawSig, GenericsFactory f) {
super(rawSig, f);
}
protected TypeSignature parse(String s) {
return SignatureParser.make().parseTypeSig(s);
}
/**
* Static factory method.
* @param rawSig - the generic signature of the reflective object
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
* @return a {@code FieldRepository} that manages the generic type
* information represented in the signature {@code rawSig}
*/
public static FieldRepository make(String rawSig, GenericsFactory f) {
return new FieldRepository(rawSig, f);
}
/*
* When queried for a particular piece of type information, the
* general pattern is to consult the corresponding cached value.
* If the corresponding field is non-null, it is returned.
* If not, it is created lazily. This is done by selecting the appropriate
* part of the tree and transforming it into a reflective object
* using a visitor, which is created by feeding it the factory
* with which the repository was created.
*/
public Type getGenericType() {
Type value = genericType;
if (value == null) {
value = computeGenericType();
genericType = value;
}
return value;
}
private Type computeGenericType() {
Reifier r = getReifier(); // obtain visitor
getTree().accept(r); // reify subtree
return r.getResult(); // extract result from visitor
}
}

View file

@ -0,0 +1,90 @@
/*
* Copyright (c) 2003, 2013, 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.generics.repository;
import java.lang.reflect.TypeVariable;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FormalTypeParameter;
import sun.reflect.generics.tree.Signature;
import sun.reflect.generics.visitor.Reifier;
/**
* This class represents the generic type information for a generic
* declaration.
* The code is not dependent on a particular reflective implementation.
* It is designed to be used unchanged by at least core reflection and JDI.
*/
public abstract class GenericDeclRepository<S extends Signature>
extends AbstractRepository<S> {
/** The formal type parameters. Lazily initialized. */
private volatile TypeVariable<?>[] typeParameters;
protected GenericDeclRepository(String rawSig, GenericsFactory f) {
super(rawSig, f);
}
/*
* When queried for a particular piece of type information, the
* general pattern is to consult the corresponding cached value.
* If the corresponding field is non-null, it is returned.
* If not, it is created lazily. This is done by selecting the appropriate
* part of the tree and transforming it into a reflective object
* using a visitor, which is created by feeding it the factory
* with which the repository was created.
*/
/**
* Returns the formal type parameters of this generic declaration.
* @return the formal type parameters of this generic declaration
*/
public TypeVariable<?>[] getTypeParameters() {
TypeVariable<?>[] value = typeParameters;
if (value == null) {
value = computeTypeParameters();
typeParameters = value;
}
return value.clone();
}
private TypeVariable<?>[] computeTypeParameters() {
// first, extract type parameter subtree(s) from AST
FormalTypeParameter[] ftps = getTree().getFormalTypeParameters();
// create array to store reified subtree(s)
int length = ftps.length;
TypeVariable<?>[] typeParameters = new TypeVariable<?>[length];
// reify all subtrees
for (int i = 0; i < length; i++) {
Reifier r = getReifier(); // obtain visitor
ftps[i].accept(r); // reify subtree
// extract result from visitor and store it
typeParameters[i] = (TypeVariable<?>) r.getResult();
}
return typeParameters;
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright (c) 2003, 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.generics.repository;
import java.lang.reflect.Type;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.visitor.Reifier;
/**
* This class represents the generic type information for a method.
* The code is not dependent on a particular reflective implementation.
* It is designed to be used unchanged by at least core reflection and JDI.
*/
public class MethodRepository extends ConstructorRepository {
/** The generic return type info. Lazily initialized. */
private volatile Type returnType;
// private, to enforce use of static factory
private MethodRepository(String rawSig, GenericsFactory f) {
super(rawSig, f);
}
/**
* Static factory method.
* @param rawSig - the generic signature of the reflective object
* that this repository is servicing
* @param f - a factory that will provide instances of reflective
* objects when this repository converts its AST
* @return a {@code MethodRepository} that manages the generic type
* information represented in the signature {@code rawSig}
*/
public static MethodRepository make(String rawSig, GenericsFactory f) {
return new MethodRepository(rawSig, f);
}
public Type getReturnType() {
Type value = returnType;
if (value == null) {
value = computeReturnType();
returnType = value;
}
return value;
}
private Type computeReturnType() {
Reifier r = getReifier(); // obtain visitor
// Extract return type subtree from AST and reify
getTree().getReturnType().accept(r);
// extract result from visitor and cache it
return r.getResult();
}
}

View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 2003, 2011, 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.generics.scope;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.TypeVariable;
/**
* Abstract superclass for lazy scope objects, used when building
* factories for generic information repositories.
* The type parameter {@code D} represents the type of reflective
* object whose scope this class is representing.
* <p> To subclass this, all one needs to do is implement
* {@code computeEnclosingScope} and the subclass' constructor.
*/
public abstract class AbstractScope<D extends GenericDeclaration>
implements Scope {
private final D recvr; // the declaration whose scope this instance represents
/** The enclosing scope of this scope. Lazily initialized. */
private volatile Scope enclosingScope;
/**
* Constructor. Takes a reflective object whose scope the newly
* constructed instance will represent.
* @param decl - A generic declaration whose scope the newly
* constructed instance will represent
*/
protected AbstractScope(D decl){ recvr = decl;}
/**
* Accessor for the receiver - the object whose scope this {@code Scope}
* object represents.
* @return The object whose scope this {@code Scope} object represents
*/
protected D getRecvr() {return recvr;}
/** This method must be implemented by any concrete subclass.
* It must return the enclosing scope of this scope. If this scope
* is a top-level scope, an instance of DummyScope must be returned.
* @return The enclosing scope of this scope
*/
protected abstract Scope computeEnclosingScope();
/**
* Accessor for the enclosing scope, which is computed lazily and cached.
* @return the enclosing scope
*/
protected Scope getEnclosingScope() {
Scope value = enclosingScope;
if (value == null) {
value = computeEnclosingScope();
enclosingScope = value;
}
return value;
}
/**
* Lookup a type variable in the scope, using its name. Returns null if
* no type variable with this name is declared in this scope or any of its
* surrounding scopes.
* @param name - the name of the type variable being looked up
* @return the requested type variable, if found
*/
public TypeVariable<?> lookup(String name) {
TypeVariable<?>[] tas = getRecvr().getTypeParameters();
for (TypeVariable<?> tv : tas) {
if (tv.getName().equals(name)) {return tv;}
}
return getEnclosingScope().lookup(name);
}
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2003, 2004, 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.generics.scope;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* This class represents the scope containing the type variables of
* a class.
*/
public class ClassScope extends AbstractScope<Class<?>> implements Scope {
// constructor is private to enforce use of factory method
private ClassScope(Class<?> c){
super(c);
}
/**
* Overrides the abstract method in the superclass.
* @return the enclosing scope
*/
protected Scope computeEnclosingScope() {
Class<?> receiver = getRecvr();
Method m = receiver.getEnclosingMethod();
if (m != null)
// Receiver is a local or anonymous class enclosed in a
// method.
return MethodScope.make(m);
Constructor<?> cnstr = receiver.getEnclosingConstructor();
if (cnstr != null)
// Receiver is a local or anonymous class enclosed in a
// constructor.
return ConstructorScope.make(cnstr);
Class<?> c = receiver.getEnclosingClass();
// if there is a declaring class, recvr is a member class
// and its enclosing scope is that of the declaring class
if (c != null)
// Receiver is a local class, an anonymous class, or a
// member class (static or not).
return ClassScope.make(c);
// otherwise, recvr is a top level class, and it has no real
// enclosing scope.
return DummyScope.make();
}
/**
* Factory method. Takes a {@code Class} object and creates a
* scope for it.
* @param c - a Class whose scope we want to obtain
* @return The type-variable scope for the class c
*/
public static ClassScope make(Class<?> c) { return new ClassScope(c);}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2003, 2011, 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.generics.scope;
import java.lang.reflect.Constructor;
/**
* This class represents the scope containing the type variables of
* a constructor.
*/
public class ConstructorScope extends AbstractScope<Constructor<?>> {
// constructor is private to enforce use of factory method
private ConstructorScope(Constructor<?> c){
super(c);
}
// utility method; computes enclosing class, from which we can
// derive enclosing scope.
private Class<?> getEnclosingClass(){
return getRecvr().getDeclaringClass();
}
/**
* Overrides the abstract method in the superclass.
* @return the enclosing scope
*/
protected Scope computeEnclosingScope() {
// the enclosing scope of a (generic) constructor is the scope of the
// class in which it was declared.
return ClassScope.make(getEnclosingClass());
}
/**
* Factory method. Takes a {@code Constructor} object and creates a
* scope for it.
* @param c - A Constructor whose scope we want to obtain
* @return The type-variable scope for the constructor m
*/
public static ConstructorScope make(Constructor<?> c) {
return new ConstructorScope(c);
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2003, 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.generics.scope;
import java.lang.reflect.TypeVariable;
/**
* This class is used to provide enclosing scopes for top level classes.
* We cannot use {@code null} to represent such a scope, since the
* enclosing scope is computed lazily, and so the field storing it is
* null until it has been computed. Therefore, {@code null} is reserved
* to represent an as-yet-uncomputed scope, and cannot be used for any
* other kind of scope.
*/
public class DummyScope implements Scope {
// Caches the unique instance of this class; instances contain no data
// so we can use the singleton pattern
private static final DummyScope singleton = new DummyScope();
// constructor is private to enforce use of factory method
private DummyScope(){}
/**
* Factory method. Enforces the singleton pattern - only one
* instance of this class ever exists.
*/
public static DummyScope make() {
return singleton;
}
/**
* Lookup a type variable in the scope, using its name. Always returns
* {@code null}.
* @param name - the name of the type variable being looked up
* @return null
*/
public TypeVariable<?> lookup(String name) {return null;}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2003, 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.generics.scope;
import java.lang.reflect.Method;
/**
* This class represents the scope containing the type variables of
* a method.
*/
public class MethodScope extends AbstractScope<Method> {
// constructor is private to enforce use of factory method
private MethodScope(Method m){
super(m);
}
// utility method; computes enclosing class, from which we can
// derive enclosing scope.
private Class<?> getEnclosingClass(){
return getRecvr().getDeclaringClass();
}
/**
* Overrides the abstract method in the superclass.
* @return the enclosing scope
*/
protected Scope computeEnclosingScope() {
// the enclosing scope of a (generic) method is the scope of the
// class in which it was declared.
return ClassScope.make(getEnclosingClass());
}
/**
* Factory method. Takes a {@code Method} object and creates a
* scope for it.
* @param m - A Method whose scope we want to obtain
* @return The type-variable scope for the method m
*/
public static MethodScope make(Method m) {
return new MethodScope(m);
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2003, 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.generics.scope;
import java.lang.reflect.TypeVariable;
public interface Scope {
TypeVariable<?> lookup(String name);
}

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
public class ArrayTypeSignature implements FieldTypeSignature {
private final TypeSignature componentType;
private ArrayTypeSignature(TypeSignature ct) {componentType = ct;}
public static ArrayTypeSignature make(TypeSignature ct) {
return new ArrayTypeSignature(ct);
}
public TypeSignature getComponentType(){return componentType;}
public void accept(TypeTreeVisitor<?> v){
v.visitArrayTypeSignature(this);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2003, 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.generics.tree;
/**
* Common superinterface for all nodes representing a primitive type.
* Corresponds to the production of the same name in the JVMS
* section on signatures.
*/
public interface BaseType
extends TypeSignature{}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the type boolean. */
public class BooleanSignature implements BaseType {
private static final BooleanSignature singleton = new BooleanSignature();
private BooleanSignature(){}
public static BooleanSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){
v.visitBooleanSignature(this);
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
public class BottomSignature implements FieldTypeSignature {
private static final BottomSignature singleton = new BottomSignature();
private BottomSignature(){}
public static BottomSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){v.visitBottomSignature(this);}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the type byte. */
public class ByteSignature implements BaseType {
private static final ByteSignature singleton = new ByteSignature();
private ByteSignature(){}
public static ByteSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){
v.visitByteSignature(this);
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the type char. */
public class CharSignature implements BaseType {
private static final CharSignature singleton = new CharSignature();
private CharSignature(){}
public static CharSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){
v.visitCharSignature(this);
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2003, 2011, 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.generics.tree;
import sun.reflect.generics.visitor.Visitor;
public class ClassSignature implements Signature {
private final FormalTypeParameter[] formalTypeParams;
private final ClassTypeSignature superclass;
private final ClassTypeSignature[] superInterfaces;
private ClassSignature(FormalTypeParameter[] ftps,
ClassTypeSignature sc,
ClassTypeSignature[] sis) {
formalTypeParams = ftps;
superclass = sc;
superInterfaces = sis;
}
public static ClassSignature make(FormalTypeParameter[] ftps,
ClassTypeSignature sc,
ClassTypeSignature[] sis) {
return new ClassSignature(ftps, sc, sis);
}
public FormalTypeParameter[] getFormalTypeParameters(){
return formalTypeParams;
}
public ClassTypeSignature getSuperclass(){return superclass;}
public ClassTypeSignature[] getSuperInterfaces(){return superInterfaces;}
public void accept(Visitor<?> v){v.visitClassSignature(this);}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import java.util.List;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/**
* AST representing class types.
*/
public class ClassTypeSignature implements FieldTypeSignature {
private final List<SimpleClassTypeSignature> path;
private ClassTypeSignature(List<SimpleClassTypeSignature> p) {
path = p;
}
public static ClassTypeSignature make(List<SimpleClassTypeSignature> p) {
return new ClassTypeSignature(p);
}
public List<SimpleClassTypeSignature> getPath(){return path;}
public void accept(TypeTreeVisitor<?> v){v.visitClassTypeSignature(this);}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the type double. */
public class DoubleSignature implements BaseType {
private static final DoubleSignature singleton = new DoubleSignature();
private DoubleSignature(){}
public static DoubleSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){v.visitDoubleSignature(this);}
}

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2003, 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.generics.tree;
/**
* Common superinterface for nodes that represent a (possibly generic)
* type.
* Corresponds to the production of the same name in the JVMS
* section on signatures.
*/
public interface FieldTypeSignature
extends BaseType, TypeSignature, TypeArgument {}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the type float. */
public class FloatSignature implements BaseType {
private static final FloatSignature singleton = new FloatSignature();
private FloatSignature(){}
public static FloatSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){v.visitFloatSignature(this);}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents a formal type parameter. */
public class FormalTypeParameter implements TypeTree {
private final String name;
private final FieldTypeSignature[] bounds;
private FormalTypeParameter(String n, FieldTypeSignature[] bs) {
name = n;
bounds = bs;
}
/**
* Factory method.
* Returns a formal type parameter with the requested name and bounds.
* @param n the name of the type variable to be created by this method.
* @param bs - the bounds of the type variable to be created by this method.
* @return a formal type parameter with the requested name and bounds
*/
public static FormalTypeParameter make(String n, FieldTypeSignature[] bs){
return new FormalTypeParameter(n,bs);
}
public FieldTypeSignature[] getBounds(){return bounds;}
public String getName(){return name;}
public void accept(TypeTreeVisitor<?> v){v.visitFormalTypeParameter(this);}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the type int. */
public class IntSignature implements BaseType {
private static final IntSignature singleton = new IntSignature();
private IntSignature(){}
public static IntSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){v.visitIntSignature(this);}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the type long. */
public class LongSignature implements BaseType {
private static final LongSignature singleton = new LongSignature();
private LongSignature(){}
public static LongSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){v.visitLongSignature(this);}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2003, 2011, 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.generics.tree;
import sun.reflect.generics.visitor.Visitor;
public class MethodTypeSignature implements Signature {
private final FormalTypeParameter[] formalTypeParams;
private final TypeSignature[] parameterTypes;
private final ReturnType returnType;
private final FieldTypeSignature[] exceptionTypes;
private MethodTypeSignature(FormalTypeParameter[] ftps,
TypeSignature[] pts,
ReturnType rt,
FieldTypeSignature[] ets) {
formalTypeParams = ftps;
parameterTypes = pts;
returnType = rt;
exceptionTypes = ets;
}
public static MethodTypeSignature make(FormalTypeParameter[] ftps,
TypeSignature[] pts,
ReturnType rt,
FieldTypeSignature[] ets) {
return new MethodTypeSignature(ftps, pts, rt, ets);
}
public FormalTypeParameter[] getFormalTypeParameters(){
return formalTypeParams;
}
public TypeSignature[] getParameterTypes(){return parameterTypes;}
public ReturnType getReturnType(){return returnType;}
public FieldTypeSignature[] getExceptionTypes(){return exceptionTypes;}
public void accept(Visitor<?> v){v.visitMethodTypeSignature(this);}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2003, 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.generics.tree;
public interface ReturnType extends TypeTree{}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the type short. */
public class ShortSignature implements BaseType {
private static final ShortSignature singleton = new ShortSignature();
private ShortSignature(){}
public static ShortSignature make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){
v.visitShortSignature(this);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2003, 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.generics.tree;
/**
* Common superinterface for generic signatures. These are the signatures
* of complete class and method/constructor declarations.
*/
public interface Signature extends Tree{
FormalTypeParameter[] getFormalTypeParameters();
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2003, 2004, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
public class SimpleClassTypeSignature implements FieldTypeSignature {
private final boolean dollar;
private final String name;
private final TypeArgument[] typeArgs;
private SimpleClassTypeSignature(String n, boolean dollar, TypeArgument[] tas) {
name = n;
this.dollar = dollar;
typeArgs = tas;
}
public static SimpleClassTypeSignature make(String n,
boolean dollar,
TypeArgument[] tas){
return new SimpleClassTypeSignature(n, dollar, tas);
}
/*
* Should a '$' be used instead of '.' to separate this component
* of the name from the previous one when composing a string to
* pass to Class.forName; in other words, is this a transition to
* a nested class.
*/
public boolean getDollar(){return dollar;}
public String getName(){return name;}
public TypeArgument[] getTypeArguments(){return typeArgs;}
public void accept(TypeTreeVisitor<?> v){
v.visitSimpleClassTypeSignature(this);
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2003, 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.generics.tree;
/** Root of the abstract syntax tree hierarchy for generic signatures */
public interface Tree{}

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2003, 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.generics.tree;
/** Common supertype for all possible type arguments in the
* generic signature AST. Corresponds to the production TypeArgument
* in the JVMS.
*/
public interface TypeArgument extends TypeTree {}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2003, 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.generics.tree;
/**
* Common superinterface for all signatures that represent a
* type expression.
* Corresponds to the production of the same name in the JVMS
* section on signatures.
*/
public interface TypeSignature extends ReturnType {}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** Common supertype for all nodes that represent type expressions in
* the generic signature AST.
*/
public interface TypeTree extends Tree {
/**
* Accept method for the visitor pattern.
* @param v a {@code TypeTreeVisitor} that will process this
* tree
*/
void accept(TypeTreeVisitor<?> v);
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
public class TypeVariableSignature implements FieldTypeSignature {
private final String identifier;
private TypeVariableSignature(String id) {identifier = id;}
public static TypeVariableSignature make(String id) {
return new TypeVariableSignature(id);
}
public String getIdentifier(){return identifier;}
public void accept(TypeTreeVisitor<?> v){
v.visitTypeVariableSignature(this);
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2003, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** AST that represents the pseudo-type void. */
public class VoidDescriptor implements ReturnType {
private static final VoidDescriptor singleton = new VoidDescriptor();
private VoidDescriptor(){}
public static VoidDescriptor make() {return singleton;}
public void accept(TypeTreeVisitor<?> v){v.visitVoidDescriptor(this);}
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (c) 2003, 2004, 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.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
public class Wildcard implements TypeArgument {
private final FieldTypeSignature[] upperBounds;
private final FieldTypeSignature[] lowerBounds;
private Wildcard(FieldTypeSignature[] ubs, FieldTypeSignature[] lbs) {
upperBounds = ubs;
lowerBounds = lbs;
}
private static final FieldTypeSignature[] emptyBounds = new FieldTypeSignature[0];
public static Wildcard make(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs) {
return new Wildcard(ubs, lbs);
}
public FieldTypeSignature[] getUpperBounds() {
return upperBounds;
}
public FieldTypeSignature[] getLowerBounds() {
if (lowerBounds.length == 1 &&
lowerBounds[0] == BottomSignature.make())
return emptyBounds;
else
return lowerBounds;
}
public void accept(TypeTreeVisitor<?> v){v.visitWildcard(this);}
}

View file

@ -0,0 +1,218 @@
/*
* Copyright (c) 2003, 2005, 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.generics.visitor;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Iterator;
import sun.reflect.generics.tree.*;
import sun.reflect.generics.factory.*;
/**
* Visitor that converts AST to reified types.
*/
public class Reifier implements TypeTreeVisitor<Type> {
private Type resultType;
private final GenericsFactory factory;
private Reifier(GenericsFactory f){
factory = f;
}
private GenericsFactory getFactory(){ return factory;}
/**
* Factory method. The resulting visitor will convert an AST
* representing generic signatures into corresponding reflective
* objects, using the provided factory, {@code f}.
* @param f - a factory that can be used to manufacture reflective
* objects returned by this visitor
* @return A visitor that can be used to reify ASTs representing
* generic type information into reflective objects
*/
public static Reifier make(GenericsFactory f){
return new Reifier(f);
}
// Helper method. Visits an array of TypeArgument and produces
// reified Type array.
private Type[] reifyTypeArguments(TypeArgument[] tas) {
Type[] ts = new Type[tas.length];
for (int i = 0; i < tas.length; i++) {
tas[i].accept(this);
ts[i] = resultType;
}
return ts;
}
/**
* Accessor for the result of the last visit by this visitor,
* @return The type computed by this visitor based on its last
* visit
*/
public Type getResult() { assert resultType != null;return resultType;}
public void visitFormalTypeParameter(FormalTypeParameter ftp){
resultType = getFactory().makeTypeVariable(ftp.getName(),
ftp.getBounds());
}
public void visitClassTypeSignature(ClassTypeSignature ct){
// This method examines the pathname stored in ct, which has the form
// n1.n2...nk<targs>....
// where n1 ... nk-1 might not exist OR
// nk might not exist (but not both). It may be that k equals 1.
// The idea is that nk is the simple class type name that has
// any type parameters associated with it.
// We process this path in two phases.
// First, we scan until we reach nk (if it exists).
// If nk does not exist, this identifies a raw class n1 ... nk-1
// which we can return.
// if nk does exist, we begin the 2nd phase.
// Here nk defines a parameterized type. Every further step nj (j > k)
// down the path must also be represented as a parameterized type,
// whose owner is the representation of the previous step in the path,
// n{j-1}.
// extract iterator on list of simple class type sigs
List<SimpleClassTypeSignature> scts = ct.getPath();
assert(!scts.isEmpty());
Iterator<SimpleClassTypeSignature> iter = scts.iterator();
SimpleClassTypeSignature sc = iter.next();
StringBuilder n = new StringBuilder(sc.getName());
boolean dollar = sc.getDollar();
// phase 1: iterate over simple class types until
// we are either done or we hit one with non-empty type parameters
while (iter.hasNext() && sc.getTypeArguments().length == 0) {
sc = iter.next();
dollar = sc.getDollar();
n.append(dollar?"$":".").append(sc.getName());
}
// Now, either sc is the last element of the list, or
// it has type arguments (or both)
assert(!(iter.hasNext()) || (sc.getTypeArguments().length > 0));
// Create the raw type
Type c = getFactory().makeNamedType(n.toString());
// if there are no type arguments
if (sc.getTypeArguments().length == 0) {
//we have surely reached the end of the path
assert(!iter.hasNext());
resultType = c; // the result is the raw type
} else {
assert(sc.getTypeArguments().length > 0);
// otherwise, we have type arguments, so we create a parameterized
// type, whose declaration is the raw type c, and whose owner is
// the declaring class of c (if any). This latter fact is indicated
// by passing null as the owner.
// First, we reify the type arguments
Type[] pts = reifyTypeArguments(sc.getTypeArguments());
Type owner = getFactory().makeParameterizedType(c, pts, null);
// phase 2: iterate over remaining simple class types
dollar =false;
while (iter.hasNext()) {
sc = iter.next();
dollar = sc.getDollar();
n.append(dollar?"$":".").append(sc.getName()); // build up raw class name
c = getFactory().makeNamedType(n.toString()); // obtain raw class
pts = reifyTypeArguments(sc.getTypeArguments());// reify params
// Create a parameterized type, based on type args, raw type
// and previous owner
owner = getFactory().makeParameterizedType(c, pts, owner);
}
resultType = owner;
}
}
public void visitArrayTypeSignature(ArrayTypeSignature a){
// extract and reify component type
a.getComponentType().accept(this);
Type ct = resultType;
resultType = getFactory().makeArrayType(ct);
}
public void visitTypeVariableSignature(TypeVariableSignature tv){
resultType = getFactory().findTypeVariable(tv.getIdentifier());
}
public void visitWildcard(Wildcard w){
resultType = getFactory().makeWildcard(w.getUpperBounds(),
w.getLowerBounds());
}
public void visitSimpleClassTypeSignature(SimpleClassTypeSignature sct){
resultType = getFactory().makeNamedType(sct.getName());
}
public void visitBottomSignature(BottomSignature b){
}
public void visitByteSignature(ByteSignature b){
resultType = getFactory().makeByte();
}
public void visitBooleanSignature(BooleanSignature b){
resultType = getFactory().makeBool();
}
public void visitShortSignature(ShortSignature s){
resultType = getFactory().makeShort();
}
public void visitCharSignature(CharSignature c){
resultType = getFactory().makeChar();
}
public void visitIntSignature(IntSignature i){
resultType = getFactory().makeInt();
}
public void visitLongSignature(LongSignature l){
resultType = getFactory().makeLong();
}
public void visitFloatSignature(FloatSignature f){
resultType = getFactory().makeFloat();
}
public void visitDoubleSignature(DoubleSignature d){
resultType = getFactory().makeDouble();
}
public void visitVoidDescriptor(VoidDescriptor v){
resultType = getFactory().makeVoid();
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2003, 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.generics.visitor;
import sun.reflect.generics.tree.*;
/**
* Visit a TypeTree and produce a result of type T.
*/
public interface TypeTreeVisitor<T> {
/**
* Returns the result of the visit.
* @return the result of the visit
*/
T getResult();
// Visitor methods, per node type
void visitFormalTypeParameter(FormalTypeParameter ftp);
void visitClassTypeSignature(ClassTypeSignature ct);
void visitArrayTypeSignature(ArrayTypeSignature a);
void visitTypeVariableSignature(TypeVariableSignature tv);
void visitWildcard(Wildcard w);
void visitSimpleClassTypeSignature(SimpleClassTypeSignature sct);
void visitBottomSignature(BottomSignature b);
// Primitives and Void
void visitByteSignature(ByteSignature b);
void visitBooleanSignature(BooleanSignature b);
void visitShortSignature(ShortSignature s);
void visitCharSignature(CharSignature c);
void visitIntSignature(IntSignature i);
void visitLongSignature(LongSignature l);
void visitFloatSignature(FloatSignature f);
void visitDoubleSignature(DoubleSignature d);
void visitVoidDescriptor(VoidDescriptor v);
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2003, 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.generics.visitor;
import sun.reflect.generics.tree.*;
public interface Visitor<T> extends TypeTreeVisitor<T> {
void visitClassSignature(ClassSignature cs);
void visitMethodTypeSignature(MethodTypeSignature ms);
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2005, 2011, 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.misc;
import java.lang.reflect.Constructor;
public final class ConstructorUtil {
private ConstructorUtil() {
}
public static Constructor<?> getConstructor(Class<?> cls, Class<?>[] params)
throws NoSuchMethodException {
ReflectUtil.checkPackageAccess(cls);
return cls.getConstructor(params);
}
public static Constructor<?>[] getConstructors(Class<?> cls) {
ReflectUtil.checkPackageAccess(cls);
return cls.getConstructors();
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2005, 2011, 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.misc;
import java.lang.reflect.Field;
/*
* Create a trampoline class.
*/
public final class FieldUtil {
private FieldUtil() {
}
public static Field getField(Class<?> cls, String name)
throws NoSuchFieldException {
ReflectUtil.checkPackageAccess(cls);
return cls.getField(name);
}
public static Field[] getFields(Class<?> cls) {
ReflectUtil.checkPackageAccess(cls);
return cls.getFields();
}
}

View file

@ -0,0 +1,373 @@
/*
* Copyright (c) 2005, 2013, 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.misc;
import java.io.EOFException;
import java.security.AllPermission;
import java.security.AccessController;
import java.security.PermissionCollection;
import java.security.SecureClassLoader;
import java.security.PrivilegedExceptionAction;
import java.security.CodeSource;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
class Trampoline {
static {
if (Trampoline.class.getClassLoader() == null) {
throw new Error(
"Trampoline must not be defined by the bootstrap classloader");
}
}
private static void ensureInvocableMethod(Method m)
throws InvocationTargetException
{
Class<?> clazz = m.getDeclaringClass();
if (clazz.equals(AccessController.class) ||
clazz.equals(Method.class) ||
clazz.getName().startsWith("java.lang.invoke."))
throw new InvocationTargetException(
new UnsupportedOperationException("invocation not supported"));
}
private static Object invoke(Method m, Object obj, Object[] params)
throws InvocationTargetException, IllegalAccessException
{
ensureInvocableMethod(m);
return m.invoke(obj, params);
}
}
/*
* Create a trampoline class.
*/
public final class MethodUtil extends SecureClassLoader {
private static final String MISC_PKG = "sun.reflect.misc.";
private static final String TRAMPOLINE = MISC_PKG + "Trampoline";
private static final Method bounce = getTrampoline();
private MethodUtil() {
super();
}
public static Method getMethod(Class<?> cls, String name, Class<?>[] args)
throws NoSuchMethodException {
ReflectUtil.checkPackageAccess(cls);
return cls.getMethod(name, args);
}
public static Method[] getMethods(Class<?> cls) {
ReflectUtil.checkPackageAccess(cls);
return cls.getMethods();
}
/*
* Discover the public methods on public classes
* and interfaces accessible to any caller by calling
* Class.getMethods() and walking towards Object until
* we're done.
*/
public static Method[] getPublicMethods(Class<?> cls) {
// compatibility for update release
if (System.getSecurityManager() == null) {
return cls.getMethods();
}
Map<Signature, Method> sigs = new HashMap<Signature, Method>();
while (cls != null) {
boolean done = getInternalPublicMethods(cls, sigs);
if (done) {
break;
}
getInterfaceMethods(cls, sigs);
cls = cls.getSuperclass();
}
return sigs.values().toArray(new Method[sigs.size()]);
}
/*
* Process the immediate interfaces of this class or interface.
*/
private static void getInterfaceMethods(Class<?> cls,
Map<Signature, Method> sigs) {
Class<?>[] intfs = cls.getInterfaces();
for (int i=0; i < intfs.length; i++) {
Class<?> intf = intfs[i];
boolean done = getInternalPublicMethods(intf, sigs);
if (!done) {
getInterfaceMethods(intf, sigs);
}
}
}
/*
*
* Process the methods in this class or interface
*/
private static boolean getInternalPublicMethods(Class<?> cls,
Map<Signature, Method> sigs) {
Method[] methods = null;
try {
/*
* This class or interface is non-public so we
* can't use any of it's methods. Go back and
* try again with a superclass or superinterface.
*/
if (!Modifier.isPublic(cls.getModifiers())) {
return false;
}
if (!ReflectUtil.isPackageAccessible(cls)) {
return false;
}
methods = cls.getMethods();
} catch (SecurityException se) {
return false;
}
/*
* Check for inherited methods with non-public
* declaring classes. They might override and hide
* methods from their superclasses or
* superinterfaces.
*/
boolean done = true;
for (int i=0; i < methods.length; i++) {
Class<?> dc = methods[i].getDeclaringClass();
if (!Modifier.isPublic(dc.getModifiers())) {
done = false;
break;
}
}
if (done) {
/*
* We're done. Spray all the methods into
* the list and then we're out of here.
*/
for (int i=0; i < methods.length; i++) {
addMethod(sigs, methods[i]);
}
} else {
/*
* Simulate cls.getDeclaredMethods() by
* stripping away inherited methods.
*/
for (int i=0; i < methods.length; i++) {
Class<?> dc = methods[i].getDeclaringClass();
if (cls.equals(dc)) {
addMethod(sigs, methods[i]);
}
}
}
return done;
}
private static void addMethod(Map<Signature, Method> sigs, Method method) {
Signature signature = new Signature(method);
if (!sigs.containsKey(signature)) {
sigs.put(signature, method);
} else if (!method.getDeclaringClass().isInterface()){
/*
* Superclasses beat interfaces.
*/
Method old = sigs.get(signature);
if (old.getDeclaringClass().isInterface()) {
sigs.put(signature, method);
}
}
}
/**
* A class that represents the unique elements of a method that will be a
* key in the method cache.
*/
private static class Signature {
private final String methodName;
private final Class<?>[] argClasses;
private final int hashCode;
Signature(Method m) {
this.methodName = m.getName();
this.argClasses = m.getParameterTypes();
this.hashCode = methodName.hashCode() + Arrays.hashCode(argClasses);
}
@Override public int hashCode() {
return hashCode;
}
@Override public boolean equals(Object o2) {
if (this == o2) {
return true;
}
Signature that = (Signature)o2;
if (!(methodName.equals(that.methodName))) {
return false;
}
if (argClasses.length != that.argClasses.length) {
return false;
}
for (int i = 0; i < argClasses.length; i++) {
if (!(argClasses[i] == that.argClasses[i])) {
return false;
}
}
return true;
}
}
/*
* Bounce through the trampoline.
*/
public static Object invoke(Method m, Object obj, Object[] params)
throws InvocationTargetException, IllegalAccessException {
try {
return bounce.invoke(null, new Object[] {m, obj, params});
} catch (InvocationTargetException ie) {
Throwable t = ie.getCause();
if (t instanceof InvocationTargetException) {
throw (InvocationTargetException)t;
} else if (t instanceof IllegalAccessException) {
throw (IllegalAccessException)t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException)t;
} else if (t instanceof Error) {
throw (Error)t;
} else {
throw new Error("Unexpected invocation error", t);
}
} catch (IllegalAccessException iae) {
// this can't happen
throw new Error("Unexpected invocation error", iae);
}
}
private static Method getTrampoline() {
try {
return AccessController.doPrivileged(
new PrivilegedExceptionAction<Method>() {
public Method run() throws Exception {
Class<?> t = getTrampolineClass();
Class<?>[] types = {
Method.class, Object.class, Object[].class
};
Method b = t.getDeclaredMethod("invoke", types);
b.setAccessible(true);
return b;
}
});
} catch (Exception e) {
throw new InternalError("bouncer cannot be found", e);
}
}
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
ReflectUtil.checkPackageAccess(name);
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
c = findClass(name);
} catch (ClassNotFoundException e) {
// Fall through ...
}
if (c == null) {
c = getParent().loadClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
protected Class<?> findClass(final String name)
throws ClassNotFoundException
{
if (!name.startsWith(MISC_PKG)) {
throw new ClassNotFoundException(name);
}
String path = name.replace('.', '/').concat(".class");
try {
InputStream in = Object.class.getModule().getResourceAsStream(path);
if (in != null) {
try (in) {
byte[] b = in.readAllBytes();
return defineClass(name, b);
}
}
} catch (IOException e) {
throw new ClassNotFoundException(name, e);
}
throw new ClassNotFoundException(name);
}
/*
* Define the proxy classes
*/
private Class<?> defineClass(String name, byte[] b) throws IOException {
CodeSource cs = new CodeSource(null, (java.security.cert.Certificate[])null);
if (!name.equals(TRAMPOLINE)) {
throw new IOException("MethodUtil: bad name " + name);
}
return defineClass(name, b, 0, b.length, cs);
}
protected PermissionCollection getPermissions(CodeSource codesource)
{
PermissionCollection perms = super.getPermissions(codesource);
perms.add(new AllPermission());
return perms;
}
private static Class<?> getTrampolineClass() {
try {
return Class.forName(TRAMPOLINE, true, new MethodUtil());
} catch (ClassNotFoundException e) {
}
return null;
}
}

View file

@ -0,0 +1,324 @@
/*
* Copyright (c) 2005, 2013, 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.misc;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import jdk.internal.reflect.Reflection;
import sun.security.util.SecurityConstants;
public final class ReflectUtil {
private ReflectUtil() {
}
public static Class<?> forName(String name)
throws ClassNotFoundException {
checkPackageAccess(name);
return Class.forName(name);
}
/**
* Ensures that access to a method or field is granted and throws
* IllegalAccessException if not. This method is not suitable for checking
* access to constructors.
*
* @param currentClass the class performing the access
* @param memberClass the declaring class of the member being accessed
* @param target the target object if accessing instance field or method;
* or null if accessing static field or method or if target
* object access rights will be checked later
* @param modifiers the member's access modifiers
* @throws IllegalAccessException if access to member is denied
* @implNote Delegates directly to
* {@link Reflection#ensureMemberAccess(Class, Class, Class, int)}
* which should be used instead.
*/
public static void ensureMemberAccess(Class<?> currentClass,
Class<?> memberClass,
Object target,
int modifiers)
throws IllegalAccessException
{
Reflection.ensureMemberAccess(currentClass,
memberClass,
target == null ? null : target.getClass(),
modifiers);
}
/**
* Does a conservative approximation of member access check. Use this if
* you don't have an actual 'userland' caller Class/ClassLoader available.
* This might be more restrictive than a precise member access check where
* you have a caller, but should never allow a member access that is
* forbidden.
*
* @param m the {@code Member} about to be accessed
*/
public static void conservativeCheckMemberAccess(Member m) throws SecurityException{
final SecurityManager sm = System.getSecurityManager();
if (sm == null)
return;
// Check for package access on the declaring class.
//
// In addition, unless the member and the declaring class are both
// public check for access declared member permissions.
//
// This is done regardless of ClassLoader relations between the {@code
// Member m} and any potential caller.
final Class<?> declaringClass = m.getDeclaringClass();
privateCheckPackageAccess(sm, declaringClass);
if (Modifier.isPublic(m.getModifiers()) &&
Modifier.isPublic(declaringClass.getModifiers()))
return;
// Check for declared member access.
sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
/**
* Checks package access on the given class.
*
* If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements
* a non-public interface (i.e. may be in a non-restricted package),
* also check the package access on the proxy interfaces.
*/
public static void checkPackageAccess(Class<?> clazz) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
privateCheckPackageAccess(s, clazz);
}
}
/**
* NOTE: should only be called if a SecurityManager is installed
*/
private static void privateCheckPackageAccess(SecurityManager s, Class<?> clazz) {
while (clazz.isArray()) {
clazz = clazz.getComponentType();
}
String pkg = clazz.getPackageName();
if (pkg != null && !pkg.isEmpty()) {
s.checkPackageAccess(pkg);
}
if (isNonPublicProxyClass(clazz)) {
privateCheckProxyPackageAccess(s, clazz);
}
}
/**
* Checks package access on the given classname.
* This method is typically called when the Class instance is not
* available and the caller attempts to load a class on behalf
* the true caller (application).
*/
public static void checkPackageAccess(String name) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
String cname = name.replace('/', '.');
if (cname.startsWith("[")) {
int b = cname.lastIndexOf('[') + 2;
if (b > 1 && b < cname.length()) {
cname = cname.substring(b);
}
}
int i = cname.lastIndexOf('.');
if (i != -1) {
s.checkPackageAccess(cname.substring(0, i));
}
}
}
public static boolean isPackageAccessible(Class<?> clazz) {
try {
checkPackageAccess(clazz);
} catch (SecurityException e) {
return false;
}
return true;
}
// Returns true if p is an ancestor of cl i.e. class loader 'p' can
// be found in the cl's delegation chain
private static boolean isAncestor(ClassLoader p, ClassLoader cl) {
ClassLoader acl = cl;
do {
acl = acl.getParent();
if (p == acl) {
return true;
}
} while (acl != null);
return false;
}
/**
* Returns true if package access check is needed for reflective
* access from a class loader 'from' to classes or members in
* a class defined by class loader 'to'. This method returns true
* if 'from' is not the same as or an ancestor of 'to'. All code
* in a system domain are granted with all permission and so this
* method returns false if 'from' class loader is a class loader
* loading system classes. On the other hand, if a class loader
* attempts to access system domain classes, it requires package
* access check and this method will return true.
*/
public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) {
if (from == null || from == to)
return false;
if (to == null)
return true;
return !isAncestor(from, to);
}
/**
* Check package access on the proxy interfaces that the given proxy class
* implements.
*
* @param clazz Proxy class object
*/
public static void checkProxyPackageAccess(Class<?> clazz) {
SecurityManager s = System.getSecurityManager();
if (s != null) {
privateCheckProxyPackageAccess(s, clazz);
}
}
/**
* NOTE: should only be called if a SecurityManager is installed
*/
private static void privateCheckProxyPackageAccess(SecurityManager s, Class<?> clazz) {
// check proxy interfaces if the given class is a proxy class
if (Proxy.isProxyClass(clazz)) {
for (Class<?> intf : clazz.getInterfaces()) {
privateCheckPackageAccess(s, intf);
}
}
}
/**
* Access check on the interfaces that a proxy class implements and throw
* {@code SecurityException} if it accesses a restricted package from
* the caller's class loader.
*
* @param ccl the caller's class loader
* @param interfaces the list of interfaces that a proxy class implements
*/
public static void checkProxyPackageAccess(ClassLoader ccl,
Class<?>... interfaces)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
for (Class<?> intf : interfaces) {
ClassLoader cl = intf.getClassLoader();
if (needsPackageAccessCheck(ccl, cl)) {
privateCheckPackageAccess(sm, intf);
}
}
}
}
// Note that bytecode instrumentation tools may exclude 'sun.*'
// classes but not generated proxy classes and so keep it in com.sun.*
public static final String PROXY_PACKAGE = "com.sun.proxy";
/**
* Test if the given class is a proxy class that implements
* non-public interface. Such proxy class may be in a non-restricted
* package that bypasses checkPackageAccess.
*/
public static boolean isNonPublicProxyClass(Class<?> cls) {
if (!Proxy.isProxyClass(cls)) {
return false;
}
String pkg = cls.getPackageName();
return pkg == null || !pkg.startsWith(PROXY_PACKAGE);
}
/**
* Check if the given method is a method declared in the proxy interface
* implemented by the given proxy instance.
*
* @param proxy a proxy instance
* @param method an interface method dispatched to a InvocationHandler
*
* @throws IllegalArgumentException if the given proxy or method is invalid.
*/
public static void checkProxyMethod(Object proxy, Method method) {
// check if it is a valid proxy instance
if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("Not a Proxy instance");
}
if (Modifier.isStatic(method.getModifiers())) {
throw new IllegalArgumentException("Can't handle static method");
}
Class<?> c = method.getDeclaringClass();
if (c == Object.class) {
String name = method.getName();
if (name.equals("hashCode") || name.equals("equals") || name.equals("toString")) {
return;
}
}
if (isSuperInterface(proxy.getClass(), c)) {
return;
}
// disallow any method not declared in one of the proxy interfaces
throw new IllegalArgumentException("Can't handle: " + method);
}
private static boolean isSuperInterface(Class<?> c, Class<?> intf) {
for (Class<?> i : c.getInterfaces()) {
if (i == intf) {
return true;
}
if (isSuperInterface(i, intf)) {
return true;
}
}
return false;
}
/**
* Checks if {@code Class cls} is a VM-anonymous class
* as defined by {@link jdk.internal.misc.Unsafe#defineAnonymousClass}
* (not to be confused with a Java Language anonymous inner class).
*/
public static boolean isVMAnonymousClass(Class<?> cls) {
return cls.getName().indexOf('/') > -1;
}
}