7154390: Add support for repeating annotations in j.l.r.AnnotatedElement
Reviewed-by: darcy
--- a/jdk/src/share/classes/java/lang/Class.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/Class.java Wed Nov 28 09:21:37 2012 -0800
@@ -48,6 +48,7 @@
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
+import java.util.Objects;
import sun.misc.Unsafe;
import sun.reflect.ConstantPool;
import sun.reflect.Reflection;
@@ -3044,34 +3045,62 @@
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
- @SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
+ Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary();
- return (A) annotations.get(annotationClass);
+ return AnnotationSupport.getOneAnnotation(annotations, annotationClass);
}
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
- public boolean isAnnotationPresent(
- Class<? extends Annotation> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
+ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
+ Objects.requireNonNull(annotationClass);
return getAnnotation(annotationClass) != null;
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <A extends Annotation> A[] getAnnotations(Class<A> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+
+ initAnnotationsIfNecessary();
+ return AnnotationSupport.getMultipleAnnotations(annotations, annotationClass);
+ }
/**
* @since 1.5
*/
public Annotation[] getAnnotations() {
initAnnotationsIfNecessary();
- return AnnotationParser.toArray(annotations);
+ return AnnotationSupport.unpackToArray(annotations);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+
+ initAnnotationsIfNecessary();
+ return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <A extends Annotation> A[] getDeclaredAnnotations(Class<A> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+
+ initAnnotationsIfNecessary();
+ return AnnotationSupport.getMultipleAnnotations(declaredAnnotations, annotationClass);
}
/**
@@ -3079,7 +3108,17 @@
*/
public Annotation[] getDeclaredAnnotations() {
initAnnotationsIfNecessary();
- return AnnotationParser.toArray(declaredAnnotations);
+ 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;
}
// Annotations cache
--- a/jdk/src/share/classes/java/lang/Package.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/Package.java Wed Nov 28 09:21:37 2012 -0800
@@ -395,6 +395,14 @@
}
/**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <A extends Annotation> A[] getAnnotations(Class<A> annotationClass) {
+ return getPackageInfo().getAnnotations(annotationClass);
+ }
+
+ /**
* @since 1.5
*/
public Annotation[] getAnnotations() {
@@ -402,6 +410,22 @@
}
/**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
+ return getPackageInfo().getDeclaredAnnotation(annotationClass);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <A extends Annotation> A[] getDeclaredAnnotations(Class<A> annotationClass) {
+ return getPackageInfo().getDeclaredAnnotations(annotationClass);
+ }
+
+ /**
* @since 1.5
*/
public Annotation[] getDeclaredAnnotations() {
--- a/jdk/src/share/classes/java/lang/System.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/System.java Wed Nov 28 09:21:37 2012 -0800
@@ -25,6 +25,7 @@
package java.lang;
import java.io.*;
+import java.lang.annotation.Annotation;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.StringTokenizer;
@@ -1195,6 +1196,9 @@
public AnnotationType getAnnotationType(Class<?> klass) {
return klass.getAnnotationType();
}
+ public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) {
+ return klass.getDirectDeclaredAnnotation(anno);
+ }
public <E extends Enum<E>>
E[] getEnumConstantsShared(Class<E> klass) {
return klass.getEnumConstantsShared();
--- a/jdk/src/share/classes/java/lang/annotation/ContainedBy.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/annotation/ContainedBy.java Wed Nov 28 09:21:37 2012 -0800
@@ -26,10 +26,35 @@
package java.lang.annotation;
/**
- * A meta-annotation to indicate which annotation type should be used
- * as a container for repeated values of the annotation type modified
- * by the {@code ContainedBy} annotation.
+ * The annotation type {@code java.lang.annotation.ContainedBy} is
+ * used to indicate that the annotation type whose declaration it
+ * (meta-)annotates is <em>repeatable</em>. The value of
+ * {@code @ContainedBy} indicates the <em>containing annotation
+ * type</em> for the repeatable annotation type.
+ *
+ * <p>The pair of annotation types {@code @ContainedBy} and
+ * {@link java.lang.annotation.ContainerFor @ContainerFor} are used to
+ * indicate that annotation types are repeatable. Specifically:
+ *
+ * <ul>
+ * <li>The annotation type {@code @ContainedBy} is used on the
+ * declaration of a repeatable annotation type (JLS 9.6) to indicate
+ * its containing annotation type.
*
+ * <li>The annotation type {@code @ContainerFor} is used on the
+ * declaration of a containing annotation type (JLS 9.6) to indicate
+ * the repeatable annotation type for which it serves as the
+ * containing annotation type.
+ * </ul>
+ *
+ * <p>
+ * An inconsistent pair of {@code @ContainedBy} and
+ * {@code @ContainerFor} annotations on a repeatable annotation type
+ * and its containing annotation type (JLS 9.6) will lead to
+ * compile-time errors and runtime exceptions when using reflection to
+ * read annotations of a repeatable type.
+ *
+ * @see java.lang.annotation.ContainerFor
* @since 1.8
* @jls 9.6 Annotation Types
* @jls 9.7 Annotations
@@ -39,8 +64,8 @@
@Target(ElementType.ANNOTATION_TYPE)
public @interface ContainedBy {
/**
- * The annotation type to use to store repeated values of another
- * annotation.
+ * Indicates the <em>containing annotation type</em> for the
+ * repeatable annotation type.
*/
Class<? extends Annotation> value();
}
--- a/jdk/src/share/classes/java/lang/annotation/ContainerFor.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/annotation/ContainerFor.java Wed Nov 28 09:21:37 2012 -0800
@@ -26,10 +26,36 @@
package java.lang.annotation;
/**
- * Indicates that an annotation type is a container for repeated
- * instances of annotations of the type of the value of the
- * {@code ContainerFor}'s value element.
+ * The annotation type {@code java.lang.annotation.ContainerFor} is
+ * used to indicate that the annotation type whose declaration it
+ * (meta-)annotates is a <em>containing annotation type</em>. The
+ * value of {@code @ContainerFor} indicates the <em>repeatable
+ * annotation type</em> for the containing annotation type.
+ *
+ * <p>The pair of annotation types {@link
+ * java.lang.annotation.ContainedBy @ContainedBy} and
+ * {@code @ContainerFor} are used to indicate that annotation types
+ * are repeatable. Specifically:
*
+ * <ul>
+ * <li>The annotation type {@code @ContainedBy} is used on the
+ * declaration of a repeatable annotation type (JLS 9.6) to indicate
+ * its containing annotation type.
+ *
+ * <li>The annotation type {@code @ContainerFor} is used on the
+ * declaration of a containing annotation type (JLS 9.6) to indicate
+ * the repeatable annotation type for which it serves as the
+ * containing annotation type.
+ * </ul>
+ *
+ * <p>
+ * An inconsistent pair of {@code @ContainedBy} and
+ * {@code @ContainerFor} annotations on a repeatable annotation type
+ * and its containing annotation type (JLS 9.6) will lead to
+ * compile-time errors and runtime exceptions when using reflection to
+ * read annotations of a repeatable type.
+ *
+ * @see java.lang.annotation.ContainedBy
* @since 1.8
* @jls 9.6 Annotation Types
* @jls 9.7 Annotations
@@ -38,9 +64,10 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface ContainerFor {
+
/**
- * The repeating annotation type that the annotation type
- * annotated with this annotation is a container for.
+ * Indicates the repeatable annotation type for the containing
+ * annotation type.
*/
Class<? extends Annotation> value();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/annotation/InvalidContainerAnnotationError.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.annotation;
+
+import java.util.Objects;
+
+/**
+ * Thrown to indicate that an annotation type whose declaration is
+ * (meta-)annotated with a {@link ContainerFor} annotation is not, in
+ * fact, the <em>containing annotation type of the type named by {@link
+ * ContainerFor}</em>.
+ *
+ * @see java.lang.reflect.AnnotatedElement
+ * @since 1.8
+ * @jls 9.6 Annotation Types
+ * @jls 9.7 Annotations
+ */
+public class InvalidContainerAnnotationError extends AnnotationFormatError {
+ private static final long serialVersionUID = 5023L;
+
+ /**
+ * The instance of the erroneous container.
+ */
+ private transient Annotation container;
+
+ /**
+ * The type of the annotation that should be contained in the
+ * container.
+ */
+ private transient Class<? extends Annotation> annotationType;
+
+ /**
+ * Constructs a new InvalidContainerAnnotationError with the
+ * specified detail message.
+ *
+ * @param message the detail message.
+ */
+ public InvalidContainerAnnotationError(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new InvalidContainerAnnotationError with the specified
+ * detail message and cause. Note that the detail message associated
+ * with {@code cause} is <i>not</i> automatically incorporated in
+ * this error's detail message.
+ *
+ * @param message the detail message
+ * @param cause the cause, may be {@code null}
+ */
+ public InvalidContainerAnnotationError(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new InvalidContainerAnnotationError with the
+ * specified cause and a detail message of {@code (cause == null ?
+ * null : cause.toString())} (which typically contains the class
+ * and detail message of {@code cause}).
+ *
+ * @param cause the cause, may be {@code null}
+ */
+ public InvalidContainerAnnotationError(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs InvalidContainerAnnotationError for the specified
+ * container instance and contained annotation type.
+ *
+ * @param message the detail message
+ * @param cause the cause, may be {@code null}
+ * @param container the erroneous container instance, may be
+ * {@code null}
+ * @param annotationType the annotation type intended to be
+ * contained, may be {@code null}
+ */
+ public InvalidContainerAnnotationError(String message,
+ Throwable cause,
+ Annotation container,
+ Class<? extends Annotation> annotationType) {
+ super(message, cause);
+ this.container = container;
+ this.annotationType = annotationType;
+ }
+
+ /**
+ * Returns the erroneous container.
+ *
+ * @return the erroneous container, may return {@code null}
+ */
+ public Annotation getContainer() {
+ return container;
+ }
+
+ /**
+ * Returns the annotation type intended to be contained. Returns
+ * {@code null} if the annotation type intended to be contained
+ * could not be determined.
+ *
+ * @return the annotation type intended to be contained, or {@code
+ * null} if unknown
+ */
+ public Class<? extends Annotation> getAnnotationType() {
+ return annotationType;
+ }
+}
--- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -184,12 +184,19 @@
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
- public boolean isAnnotationPresent(
- Class<? extends Annotation> annotationClass) {
+ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}
/**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+ throw new AssertionError("All subclasses should override this method");
+ }
+
+ /**
* @since 1.5
*/
public Annotation[] getAnnotations() {
@@ -197,6 +204,28 @@
}
/**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+ // Only annotations on classes are inherited, for all other
+ // objects getDeclaredAnnotation is the same as
+ // getAnnotation.
+ return getAnnotation(annotationClass);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
+ // Only annotations on classes are inherited, for all other
+ // objects getDeclaredAnnotations is the same as
+ // getAnnotations.
+ return getAnnotations(annotationClass);
+ }
+
+ /**
* @since 1.5
*/
public Annotation[] getDeclaredAnnotations() {
--- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -45,6 +45,11 @@
* a {@link EnumConstantNotPresentException} if the enum constant in the
* annotation is no longer present in the enum type.
*
+ * <p>Attempting to read annotations of a repeatable annotation type T
+ * that are contained in an annotation whose type is not, in fact, the
+ * containing annotation type of T will result in an
+ * InvalidContainerAnnotationError.
+ *
* <p>Finally, Attempting to read a member whose definition has evolved
* incompatibly will result in a {@link
* java.lang.annotation.AnnotationTypeMismatchException} or an
@@ -55,6 +60,7 @@
* @see java.lang.annotation.AnnotationFormatError
* @see java.lang.annotation.AnnotationTypeMismatchException
* @see java.lang.annotation.IncompleteAnnotationException
+ * @see java.lang.annotation.InvalidContainerAnnotationError
* @since 1.5
* @author Josh Bloch
*/
@@ -87,6 +93,23 @@
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
/**
+ * Returns an array of all this element's annotations for the
+ * specified type if one or more of such annotation is present,
+ * else an array of length zero.
+ *
+ * The caller of this method is free to modify the returned array;
+ * it will have no effect on the arrays returned to other callers.
+ *
+ * @param annotationClass the Class object corresponding to the
+ * annotation type
+ * @return all this element's annotations for the specified annotation type if
+ * present on this element, else an array of length zero
+ * @throws NullPointerException if the given annotation class is null
+ * @since 1.8
+ */
+ <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
@@ -98,12 +121,48 @@
Annotation[] getAnnotations();
/**
+ * Returns this element's annotation for the specified type if
+ * such an annotation is present, else null.
+ *
+ * This method ignores inherited annotations. (Returns null if no
+ * annotations are directly present on this element.)
+ *
+ * @param annotationClass the Class object corresponding to the
+ * annotation type
+ * @return this element's annotation for the specified annotation type if
+ * present on this element, else null
+ * @throws NullPointerException if the given annotation class is null
+ * @since 1.8
+ */
+ <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass);
+
+ /**
+ * Returns an array of all this element's annotations for the
+ * specified type if one or more of such annotation is directly
+ * present, else an array of length zero.
+ *
+ * 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.
+ *
+ * @param annotationClass the Class object corresponding to the
+ * annotation type
+ * @return all this element's annotations for the specified annotation type if
+ * present on this element, else an array of length zero
+ * @throws NullPointerException if the given annotation class is null
+ * @since 1.8
+ */
+ <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
+
+ /**
* Returns all annotations that are directly present on this
- * element. Unlike the other methods in this interface, 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.
+ * 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.
*
* @return All annotations directly present on this element
* @since 1.5
--- a/jdk/src/share/classes/java/lang/reflect/Executable.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Executable.java Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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,8 +26,11 @@
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;
+import sun.reflect.annotation.AnnotationSupport;
import sun.reflect.generics.repository.ConstructorRepository;
/**
@@ -363,19 +366,28 @@
* {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
- @SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
+ Objects.requireNonNull(annotationClass);
+
+ return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
+ }
- return (T) declaredAnnotations().get(annotationClass);
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+
+ return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
}
/**
* {@inheritDoc}
*/
public Annotation[] getDeclaredAnnotations() {
- return AnnotationParser.toArray(declaredAnnotations());
+ return AnnotationSupport.unpackToArray(declaredAnnotations());
}
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
--- a/jdk/src/share/classes/java/lang/reflect/Field.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/java/lang/reflect/Field.java Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, 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
@@ -33,7 +33,9 @@
import sun.reflect.generics.scope.ClassScope;
import java.lang.annotation.Annotation;
import java.util.Map;
+import java.util.Objects;
import sun.reflect.annotation.AnnotationParser;
+import sun.reflect.annotation.AnnotationSupport;
/**
@@ -1012,19 +1014,28 @@
* @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
- @SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
+ Objects.requireNonNull(annotationClass);
- return (T) declaredAnnotations().get(annotationClass);
+ return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
}
/**
- * @since 1.5
+ * {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+
+ return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
+ }
+
+ /**
+ * {@inheritDoc}
*/
public Annotation[] getDeclaredAnnotations() {
- return AnnotationParser.toArray(declaredAnnotations());
+ return AnnotationSupport.unpackToArray(declaredAnnotations());
}
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
--- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -25,6 +25,7 @@
package sun.misc;
+import java.lang.annotation.Annotation;
import sun.reflect.ConstantPool;
import sun.reflect.annotation.AnnotationType;
import sun.nio.ch.Interruptible;
@@ -83,4 +84,9 @@
* 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/AnnotationParser.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -806,4 +806,6 @@
public static Annotation[] toArray(Map<Class<? extends Annotation>, Annotation> annotations) {
return annotations.values().toArray(EMPTY_ANNOTATION_ARRAY);
}
+
+ static Annotation[] getEmptyAnnotationArray() { return EMPTY_ANNOTATION_ARRAY; }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationSupport.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.reflect.annotation;
+
+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 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).
+ *
+ * @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>();
+
+ @SuppressWarnings("unchecked")
+ final A candidate = (A)annotationMap.get(annotationClass);
+ if (candidate != null) {
+ res.add(candidate);
+ }
+
+ final Class<? extends Annotation> containerClass = getContainer(annotationClass);
+ if (containerClass != null) {
+ res.addAll(unpackAll(annotationMap.get(containerClass), annotationClass));
+ }
+
+ @SuppressWarnings("unchecked") // should be safe annotationClass is a token for A
+ final A[] emptyTemplateArray = (A[])Array.newInstance(annotationClass, 0);
+ 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
+ * annotaions 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();
+ }
+
+ /** Reflectively look up and get the returned array from the the
+ * invocation of the value() element on an instance of an
+ * Annotation.
+ */
+ private static <A extends Annotation> A[] getValueArray(Annotation containerInstance) {
+ try {
+ // the spec tells us the container must have an array-valued
+ // 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);
+ 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");
+ m.setAccessible(true);
+
+ @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
+ A[] a = (A[])m.invoke(containerInstance); // this will erase to (Annotation[]) but we
+ // do a runtime cast on the return-value
+ // in the methods that call this method
+ return a;
+ } catch (IllegalAccessException | // couldnt loosen security
+ IllegalArgumentException | // parameters doesn't match
+ InvocationTargetException | // the value method threw an exception
+ ClassCastException e) { // well, a cast failed ...
+ e.getCause().printStackTrace();
+ 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);
+ }
+ }
+
+ /* Sanity check type of and return a list of all the annotation
+ * instances of type {@code annotationClass} from {@code
+ * containerInstance}.
+ */
+ 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);
+ 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);
+ }
+ }
+}
--- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Wed Nov 28 05:18:57 2012 -0800
+++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Wed Nov 28 09:21:37 2012 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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,6 +26,7 @@
package sun.reflect.generics.reflectiveObjects;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
@@ -192,6 +193,25 @@
return null;
}
+ public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ // safe because annotationClass is the class for T
+ return (T[])Array.newInstance(annotationClass, 0);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ // safe because annotationClass is the class for T
+ return (T[])Array.newInstance(annotationClass, 0);
+ }
+
public Annotation[] getAnnotations() {
// Since zero-length, don't need defensive clone
return EMPTY_ANNOTATION_ARRAY;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7154390
+ * @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
+ * @run main RepeatedUnitTest
+ */
+
+import subpackage.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class RepeatedUnitTest {
+ public static void main(String[] args) throws Exception {
+ // PACKAGE ANNOTATIONS
+ Class c = Class.forName("subpackage.NonRepeated"); // force package "subpackage" load
+ Package p = Package.getPackage("subpackage");
+ packageNonRepeated(p);
+ packageRepeated(p);
+ packageContainer(p);
+
+ // INHERITED/NON-INHERITED ON CLASS
+ inheritedMe1();
+ inheritedMe2();
+ inheritedMe3();
+ inheritedMe4();
+
+ // CONSTRUCTOR
+ checkMultiplier(Me1.class.getConstructor(new Class[0]), 10);
+
+ // FIELD
+ checkMultiplier(Me1.class.getField("foo"), 1);
+
+ // METHOD
+ checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100);
+
+ // INNER CLASS
+ checkMultiplier(Me1.MiniMee.class, 1000);
+
+ // ENUM ELEMENT
+ checkMultiplier(Me1.E.class.getField("EE"), 10000);
+
+ // ENUM
+ checkMultiplier(Me1.E.class, 100000);
+ }
+
+ static void packageNonRepeated(AnnotatedElement e) {
+ NonRepeated nr = e.getAnnotation(NonRepeated.class);
+ check(nr.value() == 10);
+
+ check(1 == countAnnotation(e, NonRepeated.class));
+
+ nr = e.getAnnotations(NonRepeated.class)[0];
+ check(nr.value() == 10);
+
+ check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
+ }
+
+ static void packageRepeated(AnnotatedElement e) {
+ Containee c = e.getAnnotation(Containee.class);
+ check(c.value() == 1);
+
+ check(2 == countAnnotation(e, Containee.class));
+
+ c = e.getAnnotations(Containee.class)[0];
+ check(c.value() == 1);
+ c = e.getAnnotations(Containee.class)[1];
+ check(c.value() == 2);
+
+ check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
+ }
+
+ static void packageContainer(AnnotatedElement e) {
+ Container cr = e.getAnnotation(Container.class);
+ check(null != cr);
+ check(1 == containsAnnotationOfType(e.getAnnotations(Container.class), Container.class));
+ check(1 == countAnnotation(e, Container.class));
+ }
+
+ static void inheritedMe1() {
+ AnnotatedElement e = Me1.class;
+ check(null == e.getAnnotation(NonRepeated.class));
+ check(e.getAnnotation(InheritedNonRepeated.class).value() == 20);
+ check(0 == countAnnotation(e, Containee.class));
+ check(4 == countAnnotation(e, InheritedContainee.class));
+ check(0 == countAnnotation(e, Container.class));
+ check(1 == countAnnotation(e, InheritedContainer.class));
+ }
+
+ static void inheritedMe2() {
+ AnnotatedElement e = Me2.class;
+ check(e.getAnnotation(NonRepeated.class).value() == 100);
+ check(e.getAnnotation(InheritedNonRepeated.class).value() == 200);
+ check(4 == countAnnotation(e, Containee.class));
+ check(4 == countAnnotation(e, InheritedContainee.class));
+ check(1 == countAnnotation(e, Container.class));
+ check(1 == countAnnotation(e, InheritedContainer.class));
+ check(1 == countAnnotation(e, NonRepeated.class));
+ check(1 == countAnnotation(e, InheritedNonRepeated.class));
+
+ check(e.getAnnotations(Containee.class)[2].value() == 300);
+ check(e.getAnnotations(InheritedContainee.class)[2].value() == 300);
+ check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 200);
+ check(e.getAnnotations(NonRepeated.class)[0].value() == 100);
+ }
+
+ static void inheritedMe3() {
+ AnnotatedElement e = Me3.class;
+ check(null == e.getAnnotation(NonRepeated.class));
+
+ check(0 == countAnnotation(e, Containee.class));
+ check(4 == countAnnotation(e, InheritedContainee.class));
+ check(0 == countAnnotation(e, Container.class));
+ check(1 == countAnnotation(e, InheritedContainer.class));
+
+ check(e.getAnnotations(InheritedContainee.class)[2].value() == 350);
+ check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 15);
+ }
+
+ static void inheritedMe4() {
+ AnnotatedElement e = Me4.class;
+ check(e.getAnnotation(NonRepeated.class).value() == 1000);
+ check(e.getAnnotation(InheritedNonRepeated.class).value() == 2000);
+ check(4 == countAnnotation(e, Containee.class));
+ check(4 == countAnnotation(e, InheritedContainee.class));
+ check(1 == countAnnotation(e, Container.class));
+ check(1 == countAnnotation(e, InheritedContainer.class));
+ check(1 == countAnnotation(e, NonRepeated.class));
+ check(1 == countAnnotation(e, InheritedNonRepeated.class));
+
+ check(e.getAnnotations(Containee.class)[2].value() == 3000);
+ check(e.getAnnotations(InheritedContainee.class)[2].value() == 3000);
+ check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 2000);
+ check(e.getAnnotations(NonRepeated.class)[0].value() == 1000);
+ }
+
+ static void checkMultiplier(AnnotatedElement e, int m) {
+ check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
+
+ check(4 == countAnnotation(e, Containee.class));
+ check(1 == countAnnotation(e, Container.class));
+ check(1 == countAnnotation(e, NonRepeated.class));
+
+ check(e.getAnnotations(Containee.class)[2].value() == 3 * m);
+ check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m);
+ }
+
+ static void check(Boolean b) {
+ if (!b) throw new RuntimeException();
+ }
+
+ static int countAnnotation(AnnotatedElement e, Class<? extends Annotation> c) {
+ return containsAnnotationOfType(e.getAnnotations(c), c);
+ }
+
+ static <A extends Annotation> int containsAnnotationOfType(A[] l, Class<? extends Annotation> a) {
+ int count = 0;
+ for (Annotation an : l) {
+ if (an.annotationType().equals(a))
+ count++;
+ }
+ return count;
+ }
+}
+
+@NonRepeated @InheritedNonRepeated
+@InheritedContainee(1) @InheritedContainee(2) @InheritedContainee(3) @InheritedContainee(4)
+@Containee(1) @Containee(2) @Containee(3) @Containee(4)
+class Grandma {}
+
+class Mother extends Grandma {}
+
+@NonRepeated(5) @InheritedNonRepeated(15)
+@InheritedContainee(150) @InheritedContainee(250) @InheritedContainee(350) @InheritedContainee(450)
+@Containee(150) @Containee(250) @Containee(350) @Containee(450)
+class Father extends Grandma {}
+
+class Me1 extends Mother {
+
+ @NonRepeated(5)
+ @Containee(1) @Containee(2) @Containee(3) @Containee(4)
+ public String foo = "";
+
+ @NonRepeated(50)
+ @Containee(10) @Containee(20) @Containee(30) @Containee(40)
+ public Me1() {
+ }
+
+ @NonRepeated(500)
+ @Containee(100) @Containee(200) @Containee(300) @Containee(400)
+ public void mee() {
+ }
+
+ @NonRepeated(5000)
+ @Containee(1000) @Containee(2000) @Containee(3000) @Containee(4000)
+ public class MiniMee {}
+
+ @NonRepeated(500000)
+ @Containee(100000) @Containee(200000) @Containee(300000) @Containee(400000)
+ public enum E {
+ @NonRepeated(50000)
+ @Containee(10000) @Containee(20000) @Containee(30000) @Containee(40000)
+ EE(),
+ }
+}
+
+@NonRepeated(100) @InheritedNonRepeated(200)
+@InheritedContainee(100) @InheritedContainee(200) @InheritedContainee(300) @InheritedContainee(400)
+@Containee(100) @Containee(200) @Containee(300) @Containee(400)
+class Me2 extends Mother {}
+
+class Me3 extends Father {}
+
+@NonRepeated(1000) @InheritedNonRepeated(2000)
+@InheritedContainee(1000) @InheritedContainee(2000) @InheritedContainee(3000) @InheritedContainee(4000)
+@Containee(1000) @Containee(2000) @Containee(3000) @Containee(4000)
+class Me4 extends Father {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Containee.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@ContainedBy(Container.class)
+public @interface Containee {
+ int value();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/Container.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@ContainerFor(Containee.class)
+public @interface Container {
+ Containee[] value();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainee.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@ContainedBy(InheritedContainer.class)
+public @interface InheritedContainee {
+ int value();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedContainer.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@ContainerFor(InheritedContainee.class)
+public @interface InheritedContainer {
+ InheritedContainee[] value();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/InheritedNonRepeated.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+public @interface InheritedNonRepeated {
+ int value() default 20;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/NonRepeated.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package subpackage;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NonRepeated {
+ int value() default 10;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/repeatingAnnotations/subpackage/package-info.java Wed Nov 28 09:21:37 2012 -0800
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2012, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+@NonRepeated @Containee(1) @Containee(2)
+package subpackage;