--- 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 ... 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[] 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 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[] selectAnnotationClasses) { int typeIndex = buf.getShort() & 0xFFFF; Class 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(),