1 /*
   2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8005294
  27  * @summary Check behavior of default methods of AnnotatedElement
  28  * @author Joseph D. Darcy
  29  */
  30 
  31 import java.lang.annotation.*;
  32 import java.lang.reflect.*;
  33 import java.util.*;
  34 
  35 /**
  36  * For annotation type tokens including, null, DirectlyPresent.class,
  37  * IndirectlyPresent.class, etc. the behavior of
  38  * AnnotedElementDelegate.foo(arg) is compared for equality to
  39  * baseAnnotatedElement.foo(arg) on various kinds of annotated
  40  * elements.
  41  */
  42 public class TestAnnotatedElementDefaults {
  43     public static void main(String... args) throws SecurityException {
  44         int failures = 0;
  45 
  46         for (AnnotatedElement annotElement : elementsToTest()) {
  47             System.out.println(annotElement);
  48             AnnotatedElementDelegate delegate = new AnnotatedElementDelegate(annotElement);
  49             failures += testNullHandling(delegate);
  50             for (Class<? extends Annotation> annotType : annotationsToTest()) {
  51                 failures += AnnotatedElementDelegate.testDelegate(delegate, annotType);
  52             }
  53         }
  54 
  55         if (failures > 0) {
  56             System.err.printf("%d failures%n", failures);
  57             throw new RuntimeException();
  58         }
  59     }
  60 
  61     private static List<AnnotatedElement> elementsToTest() {
  62         List<AnnotatedElement> annotatedElements = new ArrayList<>();
  63         annotatedElements.add(TestClass1Super.class);
  64         annotatedElements.add(TestClass1.class);
  65         for (Method method : TestClass1.class.getDeclaredMethods()) {
  66             annotatedElements.add(method);
  67         }
  68         return annotatedElements;
  69     }
  70 
  71     private static List<Class<? extends Annotation>> annotationsToTest() {
  72         List<Class<? extends Annotation>> annotations = new ArrayList<>();
  73         annotations.add(Missing.class);
  74 
  75         annotations.add(MissingRepeatable.class);
  76 
  77         annotations.add(DirectlyPresent.class);
  78 
  79         annotations.add(IndirectlyPresent.class);
  80         annotations.add(IndirectlyPresentContainer.class);
  81 
  82         annotations.add(DirectlyAndIndirectlyPresent.class);
  83         annotations.add(DirectlyAndIndirectlyPresentContainer.class);
  84 
  85         annotations.add(AssociatedDirectOnSuperClass.class);
  86         annotations.add(AssociatedDirectOnSuperClassContainer.class);
  87 
  88         annotations.add(AssociatedDirectOnSuperClassIndirectOnSubclass.class);
  89         annotations.add(AssociatedDirectOnSuperClassIndirectOnSubclassContainer.class);
  90 
  91         annotations.add(AssociatedIndirectOnSuperClassDirectOnSubclass.class);
  92         annotations.add(AssociatedIndirectOnSuperClassDirectOnSubclassContainer.class);
  93         return annotations;
  94     }
  95 
  96     private static int testNullHandling(AnnotatedElementDelegate delegate) {
  97         int failures = 0;
  98         try {
  99             Object result = delegate.getDeclaredAnnotationsByType(null);
 100             failures++;
 101         } catch (NullPointerException npe) {
 102             ; // Expected
 103         }
 104 
 105         try {
 106             Object result = delegate.getAnnotationsByType(null);
 107             failures++;
 108         } catch (NullPointerException npe) {
 109             ; // Expected
 110         }
 111 
 112         try {
 113             Object result = delegate.getDeclaredAnnotation(null);
 114             failures++;
 115         } catch (NullPointerException npe) {
 116             ; // Expected
 117         }
 118 
 119         return failures;
 120     }
 121 
 122 }
 123 
 124 // -----------------------------------------------------
 125 
 126 @AssociatedDirectOnSuperClass(123)
 127 @AssociatedIndirectOnSuperClass(234) @AssociatedIndirectOnSuperClass(345)
 128 @AssociatedDirectOnSuperClassIndirectOnSubclass(987)
 129 @AssociatedIndirectOnSuperClassDirectOnSubclass(1111) @AssociatedIndirectOnSuperClassDirectOnSubclass(2222)
 130 class TestClass1Super {}
 131 
 132 @DirectlyPresent(1)
 133 @IndirectlyPresent(10) @IndirectlyPresent(11)
 134 @AssociatedDirectOnSuperClassIndirectOnSubclass(876) @AssociatedDirectOnSuperClassIndirectOnSubclass(765)
 135 @AssociatedIndirectOnSuperClassDirectOnSubclass(3333)
 136 class TestClass1 extends TestClass1Super {
 137 
 138     @DirectlyPresent(2)
 139     @IndirectlyPresentContainer({@IndirectlyPresent(12)})
 140     @DirectlyAndIndirectlyPresentContainer({@DirectlyAndIndirectlyPresent(84), @DirectlyAndIndirectlyPresent(96)})
 141     public void foo() {return ;}
 142 
 143     @IndirectlyPresentContainer({})
 144     @DirectlyAndIndirectlyPresentContainer({@DirectlyAndIndirectlyPresent(11), @DirectlyAndIndirectlyPresent(22)})
 145     @DirectlyAndIndirectlyPresent(33)
 146     public void bar()  {return ;}
 147 }
 148 
 149 // -----------------------------------------------------
 150 
 151 @Retention(RetentionPolicy.RUNTIME)
 152 @interface Missing {
 153     int value();
 154 }
 155 
 156 // -----------------------------------------------------
 157 
 158 @Retention(RetentionPolicy.RUNTIME)
 159 @Repeatable(MissingRepeatableContainer.class)
 160 @interface MissingRepeatable {
 161     int value();
 162 }
 163 
 164 @Retention(RetentionPolicy.RUNTIME)
 165 @interface MissingRepeatableContainer {
 166     MissingRepeatable[] value();
 167 }
 168 
 169 // -----------------------------------------------------
 170 
 171 @Retention(RetentionPolicy.RUNTIME)
 172 @interface DirectlyPresent {
 173     int value();
 174 }
 175 
 176 // -----------------------------------------------------
 177 
 178 @Retention(RetentionPolicy.RUNTIME)
 179 @Repeatable(IndirectlyPresentContainer.class)
 180 @interface IndirectlyPresent {
 181     int value();
 182 }
 183 
 184 @Retention(RetentionPolicy.RUNTIME)
 185 @interface IndirectlyPresentContainer {
 186     IndirectlyPresent[] value();
 187 }
 188 
 189 // -----------------------------------------------------
 190 
 191 @Retention(RetentionPolicy.RUNTIME)
 192 @Repeatable(DirectlyAndIndirectlyPresentContainer.class)
 193 @interface DirectlyAndIndirectlyPresent {
 194     int value();
 195 
 196 }
 197 
 198 @Retention(RetentionPolicy.RUNTIME)
 199 @interface DirectlyAndIndirectlyPresentContainer {
 200     DirectlyAndIndirectlyPresent[] value();
 201 }
 202 
 203 // -----------------------------------------------------
 204 
 205 @Retention(RetentionPolicy.RUNTIME)
 206 @Repeatable(AssociatedDirectOnSuperClassContainer.class)
 207 @interface AssociatedDirectOnSuperClass {
 208     int value();
 209 }
 210 
 211 @Retention(RetentionPolicy.RUNTIME)
 212 @interface AssociatedDirectOnSuperClassContainer {
 213     AssociatedDirectOnSuperClass[] value();
 214 }
 215 
 216 // -----------------------------------------------------
 217 
 218 @Retention(RetentionPolicy.RUNTIME)
 219 @Repeatable(AssociatedIndirectOnSuperClassContainer.class)
 220 @interface AssociatedIndirectOnSuperClass {
 221     int value();
 222 }
 223 
 224 @Retention(RetentionPolicy.RUNTIME)
 225 @interface AssociatedIndirectOnSuperClassContainer {
 226     AssociatedIndirectOnSuperClass[] value();
 227 }
 228 
 229 // -----------------------------------------------------
 230 
 231 @Retention(RetentionPolicy.RUNTIME)
 232 @Repeatable(AssociatedDirectOnSuperClassIndirectOnSubclassContainer.class)
 233 @interface  AssociatedDirectOnSuperClassIndirectOnSubclass {
 234     int value();
 235 }
 236 
 237 @Retention(RetentionPolicy.RUNTIME)
 238 @interface AssociatedDirectOnSuperClassIndirectOnSubclassContainer {
 239     AssociatedDirectOnSuperClassIndirectOnSubclass[] value();
 240 }
 241 
 242 // -----------------------------------------------------
 243 
 244 @Retention(RetentionPolicy.RUNTIME)
 245 @Repeatable(AssociatedIndirectOnSuperClassDirectOnSubclassContainer.class)
 246 @interface  AssociatedIndirectOnSuperClassDirectOnSubclass {
 247     int value();
 248 }
 249 
 250 @Retention(RetentionPolicy.RUNTIME)
 251 @interface AssociatedIndirectOnSuperClassDirectOnSubclassContainer {
 252     AssociatedIndirectOnSuperClassDirectOnSubclass[] value();
 253 }
 254 
 255 // -----------------------------------------------------
 256 
 257 /**
 258  * Helper class to ease calling the default methods of {@code
 259  * AnnotatedElement} and comparing the results to other
 260  * implementation.
 261  */
 262 class AnnotatedElementDelegate implements AnnotatedElement {
 263     private AnnotatedElement base;
 264 
 265     public AnnotatedElementDelegate(AnnotatedElement base) {
 266         Objects.requireNonNull(base);
 267         this.base = base;
 268     }
 269 
 270     // Delegate to base implemenetation of AnnotatedElement methods
 271     // without defaults.
 272     @Override
 273     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 274         return base.getAnnotation(annotationClass);
 275     }
 276 
 277     @Override
 278     public Annotation[] getAnnotations() {
 279         return base.getAnnotations();
 280     }
 281 
 282     @Override
 283     public Annotation[] getDeclaredAnnotations() {
 284         return base.getDeclaredAnnotations();
 285     }
 286 
 287     public AnnotatedElement getBase() {
 288         return base;
 289     }
 290 
 291     static int testDelegate(AnnotatedElementDelegate delegate,
 292                             Class<? extends Annotation> annotationClass) {
 293         int failures = 0;
 294         AnnotatedElement base = delegate.getBase();
 295 
 296         // System.out.println("\tTesting " + delegate + "\ton\t" + annotationClass);
 297 
 298         // <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
 299         failures += annotationArrayCheck(delegate.getDeclaredAnnotationsByType(annotationClass),
 300                                          base.getDeclaredAnnotationsByType(annotationClass),
 301                                          annotationClass,
 302                                          "Equality failure on getDeclaredAnnotationsByType(%s) on %s)%n");
 303 
 304         // <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
 305         failures += annotationArrayCheck(delegate.getAnnotationsByType(annotationClass),
 306                                          base.getAnnotationsByType(annotationClass),
 307                                          annotationClass,
 308                                          "Equality failure on getAnnotationsByType(%s) on %s)%n");
 309 
 310         // <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
 311         if (!Objects.equals(delegate.getDeclaredAnnotation(annotationClass),
 312                             base.getDeclaredAnnotation(annotationClass))) {
 313             failures++;
 314             System.err.printf("Equality failure on getDeclaredAnnotation(%s) on %s)%n",
 315                               annotationClass, delegate);
 316         }
 317         return failures;
 318     }
 319     private static <T extends Annotation> int annotationArrayCheck(T[] delegate,
 320                                                            T[] base,
 321                                                            Class<? extends Annotation> annotationClass,
 322                                                            String message) {
 323         int failures = 0;
 324 
 325         if (!Objects.deepEquals(delegate,base)) {
 326             failures = 1;
 327 
 328             System.err.printf(message,
 329                               annotationClass,
 330                               delegate);
 331             
 332             System.err.println("Base result:\t" + Arrays.toString(base));
 333             System.err.println("Delegate result:\t " + Arrays.toString(delegate));
 334             System.err.println();
 335         }
 336 
 337         return failures;
 338     }
 339 }