8005712: Simplify support for repeating annotations in j.l.r.AnnotatedElement
authorjfranck
Thu, 31 Jan 2013 10:10:34 +0100
changeset 15511 8f45487ac694
parent 15510 898d924a7efd
child 15512 32046b0f4aa8
child 15518 4fed4c1bbc29
8005712: Simplify support for repeating annotations in j.l.r.AnnotatedElement 8004919: AnnotationSupport uses possibly half-constructed AnnotationType instances Summary: Implements the simplified semantics for repeating annotations and removes the incorrect obtaining of an AnnotationType Reviewed-by: darcy, abuckley
jdk/src/share/classes/java/lang/Class.java
jdk/src/share/classes/java/lang/System.java
jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java
jdk/src/share/classes/java/lang/reflect/Executable.java
jdk/src/share/classes/java/lang/reflect/Field.java
jdk/src/share/classes/java/lang/reflect/Parameter.java
jdk/src/share/classes/sun/misc/JavaLangAccess.java
jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java
jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java
jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java
--- a/jdk/src/share/classes/java/lang/Class.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/src/share/classes/java/lang/Class.java	Thu Jan 31 10:10:34 2013 +0100
@@ -3075,11 +3075,12 @@
      * @throws NullPointerException {@inheritDoc}
      * @since 1.5
      */
+    @SuppressWarnings("unchecked")
     public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
         Objects.requireNonNull(annotationClass);
 
         initAnnotationsIfNecessary();
-        return AnnotationSupport.getOneAnnotation(annotations, annotationClass);
+        return (A) annotations.get(annotationClass);
     }
 
     /**
@@ -3108,18 +3109,19 @@
      */
     public Annotation[] getAnnotations() {
         initAnnotationsIfNecessary();
-        return AnnotationSupport.unpackToArray(annotations);
+        return AnnotationParser.toArray(annotations);
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      * @since 1.8
      */
+    @SuppressWarnings("unchecked")
     public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
         Objects.requireNonNull(annotationClass);
 
         initAnnotationsIfNecessary();
-        return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass);
+        return (A) declaredAnnotations.get(annotationClass);
     }
 
     /**
@@ -3138,17 +3140,7 @@
      */
     public Annotation[] getDeclaredAnnotations()  {
         initAnnotationsIfNecessary();
-        return AnnotationSupport.unpackToArray(declaredAnnotations);
-    }
-
-    /** Returns one "directly" present annotation or null */
-    <A extends Annotation> A getDirectDeclaredAnnotation(Class<A> annotationClass) {
-        Objects.requireNonNull(annotationClass);
-
-        initAnnotationsIfNecessary();
-        @SuppressWarnings("unchecked") // TODO check safe
-        A ret = (A)declaredAnnotations.get(annotationClass);
-        return ret;
+        return AnnotationParser.toArray(declaredAnnotations);
     }
 
     // Annotations cache
--- a/jdk/src/share/classes/java/lang/System.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/src/share/classes/java/lang/System.java	Thu Jan 31 10:10:34 2013 +0100
@@ -25,7 +25,6 @@
 package java.lang;
 
 import java.io.*;
-import java.lang.annotation.Annotation;
 import java.lang.reflect.Executable;
 import java.util.Properties;
 import java.util.PropertyPermission;
@@ -1197,9 +1196,6 @@
             public AnnotationType getAnnotationType(Class<?> klass) {
                 return klass.getAnnotationType();
             }
-            public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) {
-                return klass.getDirectDeclaredAnnotation(anno);
-            }
             public byte[] getRawClassTypeAnnotations(Class<?> klass) {
                 return klass.getRawTypeAnnotations();
             }
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java	Thu Jan 31 10:10:34 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,24 @@
  * arrays returned by accessors for array-valued enum members; it will
  * have no affect on the arrays returned to other callers.
  *
+ * <p>An annotation A is <em>directly present</em> on an element E if the
+ * RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute
+ * associated with E either:
+ * <ul>
+ * <li>contains A; or
+ * <li>for invocations of get[Declared]Annotations(Class<T>),
+ * contains A or exactly one annotation C whose type is the containing
+ * annotation type of A's type (JLS 9.6) and whose value element contains A
+ * </ul>
+ *
+ * <p>An annotation A is <em>present</em> on an element E if either:
+ * <ul>
+ * <li>A is <em>directly present</em> on E; or
+ * <li>There are no annotations of A's type which are <em>directly present</em>
+ * on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is
+ * present on the superclass of E
+ * </ul>
+ *
  * <p>If an annotation returned by a method in this interface contains
  * (directly or indirectly) a {@link Class}-valued member referring to
  * a class that is not accessible in this VM, attempting to read the class
@@ -50,7 +68,7 @@
  * containing annotation type of T will result in an
  * InvalidContainerAnnotationError.
  *
- * <p>Finally, Attempting to read a member whose definition has evolved
+ * <p>Finally, attempting to read a member whose definition has evolved
  * incompatibly will result in a {@link
  * java.lang.annotation.AnnotationTypeMismatchException} or an
  * {@link java.lang.annotation.IncompleteAnnotationException}.
@@ -70,6 +88,9 @@
      * is present on this element, else false.  This method
      * is designed primarily for convenient access to marker annotations.
      *
+     * <p>The truth value returned by this method is equivalent to:
+     * {@code getAnnotation(annotationClass) != null}
+     *
      * @param annotationClass the Class object corresponding to the
      *        annotation type
      * @return true if an annotation for the specified annotation
@@ -110,12 +131,15 @@
     <T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
 
     /**
-     * Returns all annotations present on this element.  (Returns an array
-     * of length zero if this element has no annotations.)  The caller of
-     * this method is free to modify the returned array; it will have no
-     * effect on the arrays returned to other callers.
+     * Returns annotations that are <em>present</em> on this element.
+     *
+     * If there are no annotations <em>present</em> on this element, the return
+     * value is an array of length 0.
      *
-     * @return all annotations present on this element
+     * The caller of this method is free to modify the returned array; it will
+     * have no effect on the arrays returned to other callers.
+     *
+     * @return annotations present on this element
      * @since 1.5
      */
     Annotation[] getAnnotations();
@@ -157,14 +181,16 @@
     <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
 
     /**
-     * Returns all annotations that are directly present on this
-     * element. This method ignores inherited annotations. (Returns
-     * an array of length zero if no annotations are directly present
-     * on this element.)  The caller of this method is free to modify
-     * the returned array; it will have no effect on the arrays
-     * returned to other callers.
+     * Returns annotations that are <em>directly present</em> on this element.
+     * This method ignores inherited annotations.
      *
-     * @return All annotations directly present on this element
+     * If there are no annotations <em>directly present</em> on this element,
+     * the return value is an array of length 0.
+     *
+     * The caller of this method is free to modify the returned array; it will
+     * have no effect on the arrays returned to other callers.
+     *
+     * @return annotations directly present on this element
      * @since 1.5
      */
     Annotation[] getDeclaredAnnotations();
--- a/jdk/src/share/classes/java/lang/reflect/Executable.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/src/share/classes/java/lang/reflect/Executable.java	Thu Jan 31 10:10:34 2013 +0100
@@ -26,7 +26,6 @@
 package java.lang.reflect;
 
 import java.lang.annotation.*;
-import java.util.Collections;
 import java.util.Map;
 import java.util.Objects;
 import sun.reflect.annotation.AnnotationParser;
@@ -438,8 +437,7 @@
      */
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         Objects.requireNonNull(annotationClass);
-
-        return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+        return annotationClass.cast(declaredAnnotations().get(annotationClass));
     }
 
     /**
@@ -457,7 +455,7 @@
      * {@inheritDoc}
      */
     public Annotation[] getDeclaredAnnotations()  {
-        return AnnotationSupport.unpackToArray(declaredAnnotations());
+        return AnnotationParser.toArray(declaredAnnotations());
     }
 
     private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
--- a/jdk/src/share/classes/java/lang/reflect/Field.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/src/share/classes/java/lang/reflect/Field.java	Thu Jan 31 10:10:34 2013 +0100
@@ -1021,8 +1021,7 @@
      */
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         Objects.requireNonNull(annotationClass);
-
-        return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+        return annotationClass.cast(declaredAnnotations().get(annotationClass));
     }
 
     /**
@@ -1040,7 +1039,7 @@
      * {@inheritDoc}
      */
     public Annotation[] getDeclaredAnnotations()  {
-        return AnnotationSupport.unpackToArray(declaredAnnotations());
+        return AnnotationParser.toArray(declaredAnnotations());
     }
 
     private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
--- a/jdk/src/share/classes/java/lang/reflect/Parameter.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java	Thu Jan 31 10:10:34 2013 +0100
@@ -233,8 +233,7 @@
      */
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
         Objects.requireNonNull(annotationClass);
-
-        return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+        return annotationClass.cast(declaredAnnotations().get(annotationClass));
     }
 
     /**
--- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java	Thu Jan 31 10:10:34 2013 +0100
@@ -97,9 +97,4 @@
      * Returns the ith StackTraceElement for the given throwable.
      */
     StackTraceElement getStackTraceElement(Throwable t, int i);
-
-    /**
-     * Returns a directly present annotation.
-     */
-    public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno);
 }
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java	Thu Jan 31 10:10:34 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,63 +27,29 @@
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
-import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
-import sun.reflect.Reflection;
-import sun.misc.JavaLangAccess;
 
 public final class AnnotationSupport {
-    private static final JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
-
-    /**
-     * Finds and returns _one_ annotation of the type indicated by
-     * {@code annotationClass} from the {@code Map} {@code
-     * annotationMap}. Looks into containers of the {@code
-     * annotationClass} (as specified by an the {@code
-     * annotationClass} type being meta-annotated with an {@code
-     * ContainedBy} annotation).
-     *
-     * @param annotationMap the {@code Map} used to store annotations and indexed by their type
-     * @param annotationClass the type of annotation to search for
-     *
-     * @return in instance of {@code annotationClass} or {@code null} if none were found
-     */
-    public static <A extends Annotation> A getOneAnnotation(final Map<Class<? extends Annotation>, Annotation> annotationMap,
-                                                            final Class<A> annotationClass) {
-        @SuppressWarnings("unchecked")
-        final A candidate = (A)annotationMap.get(annotationClass);
-        if (candidate != null) {
-            return candidate;
-        }
-
-        final Class<? extends Annotation> containerClass = getContainer(annotationClass);
-        if (containerClass != null) {
-            return unpackOne(annotationMap.get(containerClass), annotationClass);
-        }
-
-        return null; // found none
-    }
-
     /**
      * Finds and returns all annotation of the type indicated by
      * {@code annotationClass} from the {@code Map} {@code
      * annotationMap}. Looks into containers of the {@code
      * annotationClass} (as specified by an the {@code
      * annotationClass} type being meta-annotated with an {@code
-     * ContainedBy} annotation).
+     * Repeatable} annotation).
      *
      * @param annotationMap the {@code Map} used to store annotations indexed by their type
      * @param annotationClass the type of annotation to search for
      *
      * @return an array of instances of {@code annotationClass} or an empty array if none were found
      */
-    public static  <A extends Annotation> A[] getMultipleAnnotations(final Map<Class<? extends Annotation>, Annotation> annotationMap,
-                                                                     final Class<A> annotationClass) {
-        final ArrayList<A> res = new ArrayList<A>();
+    public static  <A extends Annotation> A[] getMultipleAnnotations(
+            final Map<Class<? extends Annotation>, Annotation> annotationMap,
+            final Class<A> annotationClass) {
+        final List<A> res = new ArrayList<A>();
 
         @SuppressWarnings("unchecked")
         final A candidate = (A)annotationMap.get(annotationClass);
@@ -101,49 +67,10 @@
         return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray);
     }
 
-    /**
-     * Unpacks the {@code annotationMap} parameter into an array of
-     * {@code Annotation}s. This method will unpack all repeating
-     * annotations containers (once). An annotation type is marked as a
-     * container by meta-annotating it the with the {@code
-     * ContainerFor} annotation.
-     *
-     * @param annotationMap the {@code Map} from where the annotations are unpacked
-     *
-     * @return an array of Annotation
-     */
-    public static Annotation[] unpackToArray(Map<Class<? extends Annotation>, Annotation> annotationMap) {
-        List<Annotation> res = new ArrayList<>();
-        for (Map.Entry<Class<? extends Annotation>, Annotation> e : annotationMap.entrySet()) {
-            Class<? extends Annotation> annotationClass = e.getKey();
-            Annotation annotationInstance = e.getValue();
-            Class<? extends Annotation> containee = getContainee(e.getKey());
-            boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null;
-
-            if (isContainer) {
-                res.addAll(unpackAll(annotationInstance, containee));
-            } else {
-                res.add(annotationInstance);
-            }
-        }
-
-        return res.isEmpty()
-               ? AnnotationParser.getEmptyAnnotationArray()
-               : res.toArray(AnnotationParser.getEmptyAnnotationArray());
-    }
-
     /** Helper to get the container, or null if none, of an annotation. */
     private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
-        ContainedBy containerAnnotation =
-            javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class);
-        return (containerAnnotation == null) ? null : containerAnnotation.value();
-    }
-
-    /** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */
-    private static <A extends Annotation> Class<? extends Annotation> getContainee(Class<A> annotationClass) {
-        ContainerFor containerAnnotation =
-            javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class);
-        return (containerAnnotation == null) ? null : containerAnnotation.value();
+        Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class);
+        return (containingAnnotation == null) ? null : containingAnnotation.value();
     }
 
     /** Reflectively look up and get the returned array from the the
@@ -156,14 +83,15 @@
             // value element. Get the AnnotationType, get the "value" element
             // and invoke it to get the contents.
 
-            Class<?> containerClass = containerInstance.annotationType();
-            AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass);
+            Class<? extends Annotation> containerClass = containerInstance.annotationType();
+            AnnotationType annoType = AnnotationType.getInstance(containerClass);
             if (annoType == null)
                 throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
 
             Method m = annoType.members().get("value");
             if (m == null)
-                throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
+                throw new InvalidContainerAnnotationError(containerInstance +
+                                                          " is an invalid container for repeating annotations");
             m.setAccessible(true);
 
             @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
@@ -175,32 +103,11 @@
                  IllegalArgumentException | // parameters doesn't match
                  InvocationTargetException | // the value method threw an exception
                  ClassCastException e) { // well, a cast failed ...
-            throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations",
-                                                      e,
-                                                      containerInstance,
-                                                      null);
-        }
-    }
-
-    /* Sanity check type of and return the first annotation instance
-     * of type {@code annotationClass} from {@code
-     * containerInstance}.
-     */
-    private static <A extends Annotation> A unpackOne(Annotation containerInstance, Class<A> annotationClass) {
-        if (containerInstance == null) {
-            return null;
-        }
-
-        try {
-            return annotationClass.cast(getValueArray(containerInstance)[0]);
-        } catch (ArrayIndexOutOfBoundsException | // empty array
-                 ClassCastException | // well, a cast failed ...
-                 NullPointerException e) { // can this NP? for good meassure
-            throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
-                                                                    containerInstance, annotationClass),
-                                                      e,
-                                                      containerInstance,
-                                                      annotationClass);
+            throw new InvalidContainerAnnotationError(
+                    containerInstance + " is an invalid container for repeating annotations",
+                    e,
+                    containerInstance,
+                    null);
         }
     }
 
@@ -208,24 +115,26 @@
      * instances of type {@code annotationClass} from {@code
      * containerInstance}.
      */
-    private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance, Class<A> annotationClass) {
+    private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance,
+                                                            Class<A> annotationClass) {
         if (containerInstance == null) {
             return Collections.emptyList(); // container not present
         }
 
         try {
             A[] a = getValueArray(containerInstance);
-            ArrayList<A> l = new ArrayList<>(a.length);
+            List<A> l = new ArrayList<>(a.length);
             for (int i  = 0; i < a.length; i++)
                 l.add(annotationClass.cast(a[i]));
             return l;
         } catch (ClassCastException |
                  NullPointerException e) {
-            throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
-                                                                    containerInstance, annotationClass),
-                                                      e,
-                                                      containerInstance,
-                                                      annotationClass);
+            throw new InvalidContainerAnnotationError(
+                    String.format("%s is an invalid container for repeating annotations of type: %s",
+                        containerInstance, annotationClass),
+                    e,
+                    containerInstance,
+                    annotationClass);
         }
     }
 }
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java	Thu Jan 31 10:10:34 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug     7154390
+ * @bug     7154390 8005712
  * @summary Unit test for repeated annotation reflection
  *
  * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java
@@ -58,7 +58,7 @@
         checkMultiplier(Me1.class.getField("foo"), 1);
 
         // METHOD
-        checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100);
+        checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class<?>[])null), 100);
 
         // INNER CLASS
         checkMultiplier(Me1.MiniMee.class, 1000);
@@ -84,8 +84,7 @@
 
     static void packageRepeated(AnnotatedElement e) {
         Containee c = e.getAnnotation(Containee.class);
-        check(c.value() == 1);
-
+        check(c == null);
         check(2 == countAnnotation(e, Containee.class));
 
         c = e.getAnnotations(Containee.class)[0];
@@ -93,7 +92,7 @@
         c = e.getAnnotations(Containee.class)[1];
         check(c.value() == 2);
 
-        check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
+        check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
     }
 
     static void packageContainer(AnnotatedElement e) {
@@ -161,14 +160,26 @@
     }
 
     static void checkMultiplier(AnnotatedElement e, int m) {
+        // Basic sanity of non-repeating getAnnotation(Class)
         check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
 
+        // Check count of annotations returned from getAnnotations(Class)
         check(4 == countAnnotation(e, Containee.class));
         check(1 == countAnnotation(e, Container.class));
         check(1 == countAnnotation(e, NonRepeated.class));
 
+        // Check contents of array returned from getAnnotations(Class)
         check(e.getAnnotations(Containee.class)[2].value() == 3 * m);
         check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m);
+
+        // Check getAnnotation(Class)
+        check(e.getAnnotation(Containee.class) == null);
+        check(e.getAnnotation(Container.class) != null);
+
+        // Check count of annotations returned from getAnnotations()
+        check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
+        check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class));
+        check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
     }
 
     static void check(Boolean b) {
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java	Thu Jan 31 10:10:34 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
 import java.lang.annotation.*;
 
 @Retention(RetentionPolicy.RUNTIME)
-@ContainedBy(Container.class)
 @Repeatable(Container.class)
 public @interface Containee {
     int value();
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java	Thu Jan 31 10:10:34 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
 import java.lang.annotation.*;
 
 @Retention(RetentionPolicy.RUNTIME)
-@ContainerFor(Containee.class)
 public @interface Container {
     Containee[] value();
 }
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java	Thu Jan 31 10:10:34 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 
 @Inherited
 @Retention(RetentionPolicy.RUNTIME)
-@ContainedBy(InheritedContainer.class)
 @Repeatable(InheritedContainer.class)
 public @interface InheritedContainee {
     int value();
--- a/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java	Tue Jan 29 10:32:49 2013 +0100
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java	Thu Jan 31 10:10:34 2013 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 
 @Inherited
 @Retention(RetentionPolicy.RUNTIME)
-@ContainerFor(InheritedContainee.class)
 public @interface InheritedContainer {
     InheritedContainee[] value();
 }