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 public class TestAnnotatedElementDefaults {
  36     public static void main(String... args) throws SecurityException {
  37         int failures = 0;
  38 
  39         List<AnnotatedElement> annotatedElements = new ArrayList<>();
  40         annotatedElements.add(TestClass1Super.class);
  41         annotatedElements.add(TestClass1.class);
  42         for (Method method : TestClass1.class.getDeclaredMethods()) {
  43             annotatedElements.add(method);
  44         }
  45 
  46         List<Class<? extends Annotation>> annotations = new ArrayList<>();
  47         annotations.add(Missing.class);
  48         annotations.add(MissingRepeatable.class);
  49         annotations.add(DirectlyPresent.class);
  50         annotations.add(IndirectlyPresent.class);
  51         annotations.add(IndirectlyPresentContainer.class);
  52         annotations.add(DirectlyAndIndirectlyPresent.class);
  53         annotations.add(DirectlyAndIndirectlyPresentContainer.class);
  54 
  55         for (AnnotatedElement annotElement : annotatedElements) {
  56             System.out.println(annotElement);
  57             AnnotatedElementDelegate delegate = new AnnotatedElementDelegate(annotElement);
  58             failures += testNullHandling(delegate);
  59             for (Class<? extends Annotation> annotType : annotations) {
  60                 failures += AnnotatedElementDelegate.testDelegate(delegate, annotType);
  61             }
  62         }
  63 
  64         if (failures > 0)
  65             throw new RuntimeException();
  66     }
  67 
  68     private static int testNullHandling(AnnotatedElementDelegate delegate) {
  69         int failures = 0;
  70         try {
  71             Object result = delegate.getDeclaredAnnotationsByType(null);
  72             failures++;
  73         } catch (NullPointerException npe) {
  74             ; // Expected
  75         }
  76 
  77         try {
  78             Object result = delegate.getAnnotationsByType(null);
  79             failures++;
  80         } catch (NullPointerException npe) {
  81             ; // Expected
  82         }
  83 
  84         try {
  85             Object result = delegate.getDeclaredAnnotation(null);
  86             failures++;
  87         } catch (NullPointerException npe) {
  88             ; // Expected
  89         }
  90 
  91         return failures;
  92     }
  93 
  94 }
  95 
  96 // -----------------------------------------------------
  97 
  98 /*
  99  * For annotation types including {null, PresentAnnotation,
 100  * MissingAnnotation, RepeatableAnnotation, ...} the behavior of
 101  * AnnotedElementDelegate.foo(arg) is compared for equality to
 102  * baseAnnotatedElement.foo(arg).
 103 
 104  * Consider annotation types
 105 
 106  * @NonRepeatable
 107  * @NonRepeatableInheritable
 108 
 109 * Base annotated elements will include a Class object (where
 110 * annotation inheritance can some input play) and a non-Class object.
 111 
 112 */
 113 
 114 @AssociatedDirectOnSuperClass(123)
 115 @AssociatedIndirectOnSuperClass(234) @AssociatedIndirectOnSuperClass(345)
 116 class TestClass1Super {}
 117 
 118 @DirectlyPresent(1)
 119 @IndirectlyPresent(10) @IndirectlyPresent(11)
 120 class TestClass1 extends TestClass1Super {
 121 
 122     @DirectlyPresent(2)
 123     @IndirectlyPresentContainer({@IndirectlyPresent(12)})
 124     @DirectlyAndIndirectlyPresentContainer({@DirectlyAndIndirectlyPresent(84), @DirectlyAndIndirectlyPresent(96)})
 125     public void foo() {return ;}
 126 
 127     @IndirectlyPresentContainer({})
 128     @DirectlyAndIndirectlyPresentContainer({@DirectlyAndIndirectlyPresent(11), @DirectlyAndIndirectlyPresent(22)})
 129     @DirectlyAndIndirectlyPresent(33)
 130     public void bar()  {return ;}
 131 }
 132 
 133 // -----------------------------------------------------
 134 
 135 @Retention(RetentionPolicy.RUNTIME)
 136 @interface DirectlyPresent {
 137     int value();
 138 }
 139 
 140 // -----------------------------------------------------
 141 
 142 @Retention(RetentionPolicy.RUNTIME)
 143 @Repeatable(IndirectlyPresentContainer.class)
 144 @interface IndirectlyPresent {
 145     int value();
 146 }
 147 
 148 @Retention(RetentionPolicy.RUNTIME)
 149 @interface IndirectlyPresentContainer {
 150     IndirectlyPresent[] value();
 151 }
 152 
 153 // -----------------------------------------------------
 154 
 155 @Retention(RetentionPolicy.RUNTIME)
 156 @Repeatable(DirectlyAndIndirectlyPresentContainer.class)
 157 @interface DirectlyAndIndirectlyPresent {
 158     int value();
 159 
 160 }
 161 
 162 @Retention(RetentionPolicy.RUNTIME)
 163 @interface DirectlyAndIndirectlyPresentContainer {
 164     DirectlyAndIndirectlyPresent[] value();
 165 }
 166 
 167 // -----------------------------------------------------
 168 
 169 @Retention(RetentionPolicy.RUNTIME)
 170 @interface Missing {
 171     int value();
 172 }
 173 
 174 // -----------------------------------------------------
 175 
 176 @Retention(RetentionPolicy.RUNTIME)
 177 @Repeatable(MissingRepeatableContainer.class)
 178 @interface MissingRepeatable {
 179     int value();
 180 }
 181 
 182 @Retention(RetentionPolicy.RUNTIME)
 183 @interface MissingRepeatableContainer {
 184     MissingRepeatable[] value();
 185 }
 186 
 187 // -----------------------------------------------------
 188 
 189 @Retention(RetentionPolicy.RUNTIME)
 190 @Repeatable(AssociatedDirectOnSuperClassContainer.class)
 191 @interface AssociatedDirectOnSuperClass {
 192     int value();
 193 }
 194 
 195 @Retention(RetentionPolicy.RUNTIME)
 196 @interface AssociatedDirectOnSuperClassContainer {
 197     AssociatedDirectOnSuperClass[] value();
 198 }
 199 
 200 // -----------------------------------------------------
 201 
 202 @Retention(RetentionPolicy.RUNTIME)
 203 @Repeatable(AssociatedIndirectOnSuperClassContainer.class)
 204 @interface AssociatedIndirectOnSuperClass {
 205     int value();
 206 }
 207 
 208 @Retention(RetentionPolicy.RUNTIME)
 209 @interface AssociatedIndirectOnSuperClassContainer {
 210     AssociatedIndirectOnSuperClass[] value();
 211 }
 212 
 213 // -----------------------------------------------------
 214 
 215 /**
 216  * Helper class to ease calling the default methods of {@code
 217  * AnnotatedElement} and comparing the results to other
 218  * implementation.
 219  */
 220 class AnnotatedElementDelegate implements AnnotatedElement {
 221     private AnnotatedElement base;
 222 
 223     public AnnotatedElementDelegate(AnnotatedElement base) {
 224         Objects.requireNonNull(base);
 225         this.base = base;
 226     }
 227 
 228 //     // FIXME -- adjust once build / vm problems resolved
 229 //     @Override
 230 //     public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
 231 //         return base.getDeclaredAnnotationsByType(annotationClass);
 232 //     }
 233 
 234     // Delegate to base implemenetation of AnnotatedElement methods
 235     // without defaults.
 236     @Override
 237     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 238         return base.getAnnotation(annotationClass);
 239     }
 240 
 241     @Override
 242     public Annotation[] getAnnotations() {
 243         return base.getAnnotations();
 244     }
 245 
 246     @Override
 247     public Annotation[] getDeclaredAnnotations() {
 248         return base.getDeclaredAnnotations();
 249     }
 250 
 251     public AnnotatedElement getBase() {
 252         return base;
 253     }
 254 
 255     static int testDelegate(AnnotatedElementDelegate delegate,
 256                             Class<? extends Annotation> annotationClass) {
 257         int failures = 0;
 258         AnnotatedElement base = delegate.getBase();
 259 
 260         // System.out.println("\tTesting " + delegate + "\ton\t" + annotationClass);
 261 
 262         // <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
 263         if (!Objects.deepEquals(delegate.getDeclaredAnnotationsByType(annotationClass),
 264                                 base.getDeclaredAnnotationsByType(annotationClass))) {
 265             failures++;
 266             System.err.printf("Equality failure on getDeclaredAnnotationsByType(%s) on %s)%n",
 267                               annotationClass, delegate);
 268         }
 269 
 270         // <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
 271         if (!Objects.deepEquals(delegate.getAnnotationsByType(annotationClass),
 272                                 base.getAnnotationsByType(annotationClass))) {
 273             failures++;
 274             System.err.printf("Equality failure on getAnnotationsByType(%s) on %s)%n",
 275                               annotationClass, delegate);
 276         }
 277 
 278         // <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
 279         if (!Objects.equals(delegate.getDeclaredAnnotation(annotationClass),
 280                             base.getDeclaredAnnotation(annotationClass))) {
 281             failures++;
 282             System.err.printf("Equality failure on getDeclaredAnnotation(%s) on %s)%n",
 283                               annotationClass, delegate);
 284         }
 285         return failures;
 286     }
 287 }