src/share/classes/sun/reflect/annotation/AnnotationParser.java
Print this page
*** 67,77 ****
Class<?> container) {
if (rawAnnotations == null)
return Collections.emptyMap();
try {
! return parseAnnotations2(rawAnnotations, constPool, container);
} catch(BufferUnderflowException e) {
throw new AnnotationFormatError("Unexpected end of annotations.");
} catch(IllegalArgumentException e) {
// Type mismatch in constant pool
throw new AnnotationFormatError(e);
--- 67,105 ----
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);
! }
! }
!
! /**
! * An overload of {@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
! public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(
! 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);
*** 79,104 ****
}
private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(
byte[] rawAnnotations,
ConstantPool constPool,
! Class<?> container) {
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 = parseAnnotation(buf, constPool, container, false);
if (a != null) {
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;
}
/**
* Parses the parameter annotations described by the specified byte array.
--- 107,133 ----
}
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 = parseAnnotation(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.
*** 149,159 ****
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);
--- 178,188 ----
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, null);
if (a != null) {
AnnotationType type = AnnotationType.getInstance(
a.annotationType());
if (type.retention() == RetentionPolicy.RUNTIME)
annotations.add(a);
*** 191,201 ****
*/
@SuppressWarnings("unchecked")
static Annotation parseAnnotation(ByteBuffer buf,
ConstantPool constPool,
Class<?> container,
! boolean exceptionOnMissingAnnotationClass) {
int typeIndex = buf.getShort() & 0xFFFF;
Class<? extends Annotation> annotationClass = null;
String sig = "[unknown]";
try {
try {
--- 220,231 ----
*/
@SuppressWarnings("unchecked")
static Annotation parseAnnotation(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 {
*** 217,226 ****
--- 247,260 ----
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);
*** 305,315 ****
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);
--- 339,349 ----
return parseEnumValue((Class<? extends Enum<?>>)memberType, buf, constPool, container);
case 'c':
result = parseClassValue(buf, constPool, container);
break;
case '@':
! result = parseAnnotation(buf, constPool, container, true, null);
break;
case '[':
return parseArray(memberType, buf, constPool, container);
default:
result = parseConst(tag, buf, constPool);
*** 718,728 ****
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;
}
}
--- 752,762 ----
int tag = 0;
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == '@') {
! result[i] = parseAnnotation(buf, constPool, container, true, null);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
}
}
*** 798,807 ****
--- 832,849 ----
int length = buf.getShort() & 0xFFFF;
for (int i = 0; i < length; i++)
skipMemberValue(buf);
}
+ // utility
+ 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