--- old/src/share/classes/sun/reflect/annotation/AnnotationParser.java 2013-07-05 10:11:28.434821086 +0200
+++ new/src/share/classes/sun/reflect/annotation/AnnotationParser.java 2013-07-05 10:11:28.318823094 +0200
@@ -69,7 +69,35 @@
return Collections.emptyMap();
try {
- return parseAnnotations2(rawAnnotations, constPool, container);
+ 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).
+ * 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, 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) {
@@ -81,20 +109,21 @@
private static Map, Annotation> parseAnnotations2(
byte[] rawAnnotations,
ConstantPool constPool,
- Class> container) {
+ Class> container,
+ Class extends Annotation>[] selectAnnotationClasses) {
Map, Annotation> result =
new LinkedHashMap, 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);
+ Annotation a = parseAnnotation2(buf, constPool, container, false, selectAnnotationClasses);
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);
+ if (AnnotationType.getInstance(klass).retention() == RetentionPolicy.RUNTIME &&
+ result.put(klass, a) != null) {
+ throw new AnnotationFormatError(
+ "Duplicate annotation for class: "+klass+": " + a);
+ }
}
}
return result;
@@ -189,11 +218,19 @@
* TypeNotPresentException if a referenced annotation type is not
* available at runtime
*/
- @SuppressWarnings("unchecked")
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) {
+ boolean exceptionOnMissingAnnotationClass,
+ Class extends Annotation>[] selectAnnotationClasses) {
int typeIndex = buf.getShort() & 0xFFFF;
Class extends Annotation> annotationClass = null;
String sig = "[unknown]";
@@ -219,6 +256,10 @@
skipAnnotation(buf, false);
return null;
}
+ if (selectAnnotationClasses != null && !contains(selectAnnotationClasses, annotationClass)) {
+ skipAnnotation(buf, false);
+ return null;
+ }
AnnotationType type = null;
try {
type = AnnotationType.getInstance(annotationClass);
@@ -800,6 +841,17 @@
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(),