--- old/src/share/classes/sun/reflect/annotation/AnnotationParser.java 2013-06-24 20:09:29.055576167 +0200
+++ new/src/share/classes/sun/reflect/annotation/AnnotationParser.java 2013-06-24 20:09:28.946578130 +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);
+ }
+ }
+
+ /**
+ * 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).
+ * 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, 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) {
@@ -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 = parseAnnotation(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;
@@ -151,7 +180,7 @@
List annotations =
new ArrayList(numAnnotations);
for (int j = 0; j < numAnnotations; j++) {
- Annotation a = parseAnnotation(buf, constPool, container, false);
+ Annotation a = parseAnnotation(buf, constPool, container, false, null);
if (a != null) {
AnnotationType type = AnnotationType.getInstance(
a.annotationType());
@@ -193,7 +222,8 @@
static Annotation parseAnnotation(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 +249,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);
@@ -307,7 +341,7 @@
result = parseClassValue(buf, constPool, container);
break;
case '@':
- result = parseAnnotation(buf, constPool, container, true);
+ result = parseAnnotation(buf, constPool, container, true, null);
break;
case '[':
return parseArray(memberType, buf, constPool, container);
@@ -720,7 +754,7 @@
for (int i = 0; i < length; i++) {
tag = buf.get();
if (tag == '@') {
- result[i] = parseAnnotation(buf, constPool, container, true);
+ result[i] = parseAnnotation(buf, constPool, container, true, null);
} else {
skipMemberValue(tag, buf);
typeMismatch = true;
@@ -800,6 +834,14 @@
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(),