8005712: Simplify support for repeating annotations in j.l.r.AnnotatedElement
8004919: AnnotationSupport uses possibly half-constructed AnnotationType instances Implements the simplified semantics for repeating annotations and removes the incorrect obtaining of an AnnotationType Reviewed-by: darcy, abuckley
This commit is contained in:
parent
b29b479461
commit
34e1726860
@ -3075,11 +3075,12 @@ public final
|
||||
* @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 final
|
||||
*/
|
||||
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 final
|
||||
*/
|
||||
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
|
||||
|
@ -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 final class System {
|
||||
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();
|
||||
}
|
||||
|
@ -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 @@ import java.lang.annotation.Annotation;
|
||||
* 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 @@ import java.lang.annotation.Annotation;
|
||||
* 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 @@ public interface AnnotatedElement {
|
||||
* 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 @@ public interface AnnotatedElement {
|
||||
<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.
|
||||
*
|
||||
* @return all annotations present on this element
|
||||
* If there are no annotations <em>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 present on this element
|
||||
* @since 1.5
|
||||
*/
|
||||
Annotation[] getAnnotations();
|
||||
@ -157,14 +181,16 @@ public interface AnnotatedElement {
|
||||
<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();
|
||||
|
@ -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 abstract class Executable extends AccessibleObject
|
||||
*/
|
||||
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 @@ public abstract class Executable extends AccessibleObject
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
return AnnotationSupport.unpackToArray(declaredAnnotations());
|
||||
return AnnotationParser.toArray(declaredAnnotations());
|
||||
}
|
||||
|
||||
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
||||
|
@ -1021,8 +1021,7 @@ class Field extends AccessibleObject implements Member {
|
||||
*/
|
||||
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 @@ class Field extends AccessibleObject implements Member {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Annotation[] getDeclaredAnnotations() {
|
||||
return AnnotationSupport.unpackToArray(declaredAnnotations());
|
||||
return AnnotationParser.toArray(declaredAnnotations());
|
||||
}
|
||||
|
||||
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
|
||||
|
@ -233,8 +233,7 @@ public final class Parameter implements AnnotatedElement {
|
||||
*/
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
|
||||
return annotationClass.cast(declaredAnnotations().get(annotationClass));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,9 +97,4 @@ public interface JavaLangAccess {
|
||||
* 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);
|
||||
}
|
||||
|
@ -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 @@ 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 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 @@ public final class AnnotationSupport {
|
||||
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 @@ public final class AnnotationSupport {
|
||||
// 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 @@ public final class AnnotationSupport {
|
||||
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 @@ public final class AnnotationSupport {
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ public class RepeatedUnitTest {
|
||||
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 @@ public class RepeatedUnitTest {
|
||||
|
||||
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 @@ public class RepeatedUnitTest {
|
||||
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 @@ public class RepeatedUnitTest {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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 @@ package subpackage;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContainedBy(Container.class)
|
||||
@Repeatable(Container.class)
|
||||
public @interface Containee {
|
||||
int value();
|
||||
|
@ -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 @@ package subpackage;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContainerFor(Containee.class)
|
||||
public @interface Container {
|
||||
Containee[] value();
|
||||
}
|
||||
|
@ -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 @@ import java.lang.annotation.*;
|
||||
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContainedBy(InheritedContainer.class)
|
||||
@Repeatable(InheritedContainer.class)
|
||||
public @interface InheritedContainee {
|
||||
int value();
|
||||
|
@ -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 @@ import java.lang.annotation.*;
|
||||
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ContainerFor(InheritedContainee.class)
|
||||
public @interface InheritedContainer {
|
||||
InheritedContainee[] value();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user