| /* |
| * Copyright (c) 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 |
| * 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 8005294 |
| * @summary Check behavior of default methods of AnnotatedElement |
| * @author Joseph D. Darcy |
| */ |
| |
| import java.lang.annotation.*; |
| import java.lang.reflect.*; |
| import java.util.*; |
| |
| /** |
| * For annotation type tokens including, null, DirectlyPresent.class, |
| * IndirectlyPresent.class, etc. the behavior of |
| * AnnotedElementDelegate.foo(arg) is compared for equality to |
| * baseAnnotatedElement.foo(arg) on various kinds of annotated |
| * elements. |
| */ |
| public class TestAnnotatedElementDefaults { |
| public static void main(String... args) throws SecurityException { |
| int failures = 0; |
| |
| for (AnnotatedElement annotElement : elementsToTest()) { |
| System.out.println(annotElement); |
| AnnotatedElementDelegate delegate = new AnnotatedElementDelegate(annotElement); |
| failures += testNullHandling(delegate); |
| for (Class<? extends Annotation> annotType : annotationsToTest()) { |
| failures += AnnotatedElementDelegate.testDelegate(delegate, annotType); |
| } |
| } |
| |
| if (failures > 0) { |
| System.err.printf("%d failures%n", failures); |
| throw new RuntimeException(); |
| } |
| } |
| |
| private static List<AnnotatedElement> elementsToTest() { |
| List<AnnotatedElement> annotatedElements = new ArrayList<>(); |
| annotatedElements.add(TestClass1Super.class); |
| annotatedElements.add(TestClass1.class); |
| for (Method method : TestClass1.class.getDeclaredMethods()) { |
| annotatedElements.add(method); |
| } |
| return annotatedElements; |
| } |
| |
| private static List<Class<? extends Annotation>> annotationsToTest() { |
| List<Class<? extends Annotation>> annotations = new ArrayList<>(); |
| annotations.add(Missing.class); |
| |
| annotations.add(MissingRepeatable.class); |
| |
| annotations.add(DirectlyPresent.class); |
| |
| annotations.add(IndirectlyPresent.class); |
| annotations.add(IndirectlyPresentContainer.class); |
| |
| annotations.add(DirectlyAndIndirectlyPresent.class); |
| annotations.add(DirectlyAndIndirectlyPresentContainer.class); |
| |
| annotations.add(AssociatedDirectOnSuperClass.class); |
| annotations.add(AssociatedDirectOnSuperClassContainer.class); |
| |
| annotations.add(AssociatedDirectOnSuperClassIndirectOnSubclass.class); |
| annotations.add(AssociatedDirectOnSuperClassIndirectOnSubclassContainer.class); |
| |
| annotations.add(AssociatedIndirectOnSuperClassDirectOnSubclass.class); |
| annotations.add(AssociatedIndirectOnSuperClassDirectOnSubclassContainer.class); |
| return annotations; |
| } |
| |
| private static int testNullHandling(AnnotatedElementDelegate delegate) { |
| int failures = 0; |
| try { |
| Object result = delegate.getDeclaredAnnotationsByType(null); |
| failures++; |
| } catch (NullPointerException npe) { |
| ; // Expected |
| } |
| |
| try { |
| Object result = delegate.getAnnotationsByType(null); |
| failures++; |
| } catch (NullPointerException npe) { |
| ; // Expected |
| } |
| |
| try { |
| Object result = delegate.getDeclaredAnnotation(null); |
| failures++; |
| } catch (NullPointerException npe) { |
| ; // Expected |
| } |
| |
| return failures; |
| } |
| |
| } |
| |
| // ----------------------------------------------------- |
| |
| @AssociatedDirectOnSuperClass(123) |
| @AssociatedIndirectOnSuperClass(234) @AssociatedIndirectOnSuperClass(345) |
| @AssociatedDirectOnSuperClassIndirectOnSubclass(987) |
| @AssociatedIndirectOnSuperClassDirectOnSubclass(1111) @AssociatedIndirectOnSuperClassDirectOnSubclass(2222) |
| class TestClass1Super {} |
| |
| @DirectlyPresent(1) |
| @IndirectlyPresent(10) @IndirectlyPresent(11) |
| @AssociatedDirectOnSuperClassIndirectOnSubclass(876) @AssociatedDirectOnSuperClassIndirectOnSubclass(765) |
| @AssociatedIndirectOnSuperClassDirectOnSubclass(3333) |
| class TestClass1 extends TestClass1Super { |
| |
| @DirectlyPresent(2) |
| @IndirectlyPresentContainer({@IndirectlyPresent(12)}) |
| @DirectlyAndIndirectlyPresentContainer({@DirectlyAndIndirectlyPresent(84), @DirectlyAndIndirectlyPresent(96)}) |
| public void foo() {return ;} |
| |
| @IndirectlyPresentContainer({}) |
| @DirectlyAndIndirectlyPresentContainer({@DirectlyAndIndirectlyPresent(11), @DirectlyAndIndirectlyPresent(22)}) |
| @DirectlyAndIndirectlyPresent(33) |
| public void bar() {return ;} |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface Missing { |
| int value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @Repeatable(MissingRepeatableContainer.class) |
| @interface MissingRepeatable { |
| int value(); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface MissingRepeatableContainer { |
| MissingRepeatable[] value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface DirectlyPresent { |
| int value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @Repeatable(IndirectlyPresentContainer.class) |
| @interface IndirectlyPresent { |
| int value(); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface IndirectlyPresentContainer { |
| IndirectlyPresent[] value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @Repeatable(DirectlyAndIndirectlyPresentContainer.class) |
| @interface DirectlyAndIndirectlyPresent { |
| int value(); |
| |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface DirectlyAndIndirectlyPresentContainer { |
| DirectlyAndIndirectlyPresent[] value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @Repeatable(AssociatedDirectOnSuperClassContainer.class) |
| @interface AssociatedDirectOnSuperClass { |
| int value(); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface AssociatedDirectOnSuperClassContainer { |
| AssociatedDirectOnSuperClass[] value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @Repeatable(AssociatedIndirectOnSuperClassContainer.class) |
| @interface AssociatedIndirectOnSuperClass { |
| int value(); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface AssociatedIndirectOnSuperClassContainer { |
| AssociatedIndirectOnSuperClass[] value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @Repeatable(AssociatedDirectOnSuperClassIndirectOnSubclassContainer.class) |
| @interface AssociatedDirectOnSuperClassIndirectOnSubclass { |
| int value(); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface AssociatedDirectOnSuperClassIndirectOnSubclassContainer { |
| AssociatedDirectOnSuperClassIndirectOnSubclass[] value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @Repeatable(AssociatedIndirectOnSuperClassDirectOnSubclassContainer.class) |
| @interface AssociatedIndirectOnSuperClassDirectOnSubclass { |
| int value(); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface AssociatedIndirectOnSuperClassDirectOnSubclassContainer { |
| AssociatedIndirectOnSuperClassDirectOnSubclass[] value(); |
| } |
| |
| // ----------------------------------------------------- |
| |
| /** |
| * Helper class to ease calling the default methods of {@code |
| * AnnotatedElement} and comparing the results to other |
| * implementation. |
| */ |
| class AnnotatedElementDelegate implements AnnotatedElement { |
| private AnnotatedElement base; |
| |
| public AnnotatedElementDelegate(AnnotatedElement base) { |
| Objects.requireNonNull(base); |
| this.base = base; |
| } |
| |
| // Delegate to base implemenetation of AnnotatedElement methods |
| // without defaults. |
| @Override |
| public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
| return base.getAnnotation(annotationClass); |
| } |
| |
| @Override |
| public Annotation[] getAnnotations() { |
| return base.getAnnotations(); |
| } |
| |
| @Override |
| public Annotation[] getDeclaredAnnotations() { |
| return base.getDeclaredAnnotations(); |
| } |
| |
| public AnnotatedElement getBase() { |
| return base; |
| } |
| |
| static int testDelegate(AnnotatedElementDelegate delegate, |
| Class<? extends Annotation> annotationClass) { |
| int failures = 0; |
| AnnotatedElement base = delegate.getBase(); |
| |
| // System.out.println("\tTesting " + delegate + "\ton\t" + annotationClass); |
| |
| // <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) |
| failures += annotationArrayCheck(delegate.getDeclaredAnnotationsByType(annotationClass), |
| base.getDeclaredAnnotationsByType(annotationClass), |
| annotationClass, |
| "Equality failure on getDeclaredAnnotationsByType(%s) on %s)%n"); |
| |
| // <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) |
| failures += annotationArrayCheck(delegate.getAnnotationsByType(annotationClass), |
| base.getAnnotationsByType(annotationClass), |
| annotationClass, |
| "Equality failure on getAnnotationsByType(%s) on %s)%n"); |
| |
| // <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) |
| if (!Objects.equals(delegate.getDeclaredAnnotation(annotationClass), |
| base.getDeclaredAnnotation(annotationClass))) { |
| failures++; |
| System.err.printf("Equality failure on getDeclaredAnnotation(%s) on %s)%n", |
| annotationClass, delegate); |
| } |
| return failures; |
| } |
| private static <T extends Annotation> int annotationArrayCheck(T[] delegate, |
| T[] base, |
| Class<? extends Annotation> annotationClass, |
| String message) { |
| int failures = 0; |
| |
| if (!Objects.deepEquals(delegate,base)) { |
| failures = 1; |
| |
| System.err.printf(message, |
| annotationClass, |
| delegate); |
| |
| System.err.println("Base result:\t" + Arrays.toString(base)); |
| System.err.println("Delegate result:\t " + Arrays.toString(delegate)); |
| System.err.println(); |
| } |
| |
| return failures; |
| } |
| } |