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);
! }
! }
!
! /**
! * 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
! 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);
*** 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 = 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.
*** 187,201 ****
*
* @param exceptionOnMissingAnnotationClass if true, throw
* TypeNotPresentException if a referenced annotation type is not
* available at runtime
*/
- @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 {
--- 216,238 ----
*
* @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 {
*** 217,226 ****
--- 254,267 ----
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);
*** 798,807 ****
--- 839,859 ----
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