1 /*
   2  * Copyright (c) 2015, 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 8058595
  27  * @summary Test that AnnotatedType.getAnnotatedOwnerType() works as expected
  28  *
  29  * @library /lib/testlibrary
  30  * @build jdk.testlibrary.Asserts
  31  * @run main GetAnnotatedOwnerType
  32  */
  33 
  34 import java.lang.annotation.*;
  35 import java.lang.reflect.*;
  36 
  37 import jdk.testlibrary.Asserts;
  38 
  39 public class GetAnnotatedOwnerType<Dummy> {
  40     public @TA("generic") GetAnnotatedOwnerType<String> . @TB("generic") Nested<Integer> genericField;
  41     public @TA("raw") GetAnnotatedOwnerType . @TB("raw") Nested rawField;
  42     public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("non-generic") Inner nonGeneric;
  43     public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("generic") InnerGeneric<String> innerGeneric;
  44     public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("raw") InnerGeneric innerRaw;
  45     public Object anonymous = new Object() {};
  46     public @TA("array") Dummy[] dummy;
  47     public @TA("wildcard") GetAnnotatedOwnerType<?> wildcard;
  48     public @TA("typevariable") Dummy tv;
  49     public @TA("bad") GetAnnotatedOwnerType<@TA("good") GetAnnotatedOwnerType<String> . @TB("tb") Nested<Integer> >  typeArgument;
  50     public GetAnnotatedOwnerType< GetAnnotatedOwnerType<String> .
  51             B .
  52             C<Class<?>, ? extends @TA("complicated") Exception> .
  53             D<Number> > [] complicated;
  54 
  55     public static void main(String[] args) throws Exception {
  56         testGeneric();
  57         testRaw();
  58         testNonGeneric();
  59         testInnerGeneric();
  60         testInnerRaw();
  61 
  62         testLocalClass();
  63         testAnonymousClass();
  64 
  65         testArray();
  66         testWildcard();
  67         testTypeParameter();
  68 
  69         testTypeArgument();
  70         testComplicated();
  71     }
  72 
  73     public static void testGeneric() throws Exception {
  74         Field f = GetAnnotatedOwnerType.class.getField("genericField");
  75 
  76         // make sure inner is correctly annotated
  77         AnnotatedType inner = f.getAnnotatedType();
  78         Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
  79         Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
  80                 + inner.getAnnotations().length);
  81 
  82         // make sure owner is correctly annotated, on the correct type
  83         AnnotatedType outer = inner.getAnnotatedOwnerType();
  84         Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
  85         Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "generic");
  86         Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
  87                 + outer.getAnnotations().length);
  88     }
  89 
  90     public static void testRaw() throws Exception {
  91         Field f = GetAnnotatedOwnerType.class.getField("rawField");
  92 
  93         // make sure inner is correctly annotated
  94         AnnotatedType inner = f.getAnnotatedType();
  95         Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
  96         Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
  97                 + inner.getAnnotations().length);
  98 
  99         // make sure owner is correctly annotated, on the correct type
 100         AnnotatedType outer = inner.getAnnotatedOwnerType();
 101         Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
 102         Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "raw");
 103         Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 104                 + outer.getAnnotations().length);
 105     }
 106 
 107     public static void testNonGeneric() throws Exception {
 108         Field f = GetAnnotatedOwnerType.class.getField("nonGeneric");
 109 
 110         // make sure inner is correctly annotated
 111         AnnotatedType inner = f.getAnnotatedType();
 112         Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "non-generic");
 113         Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 114                 + inner.getAnnotations().length);
 115 
 116         // make sure owner is correctly annotated, on the correct type
 117         AnnotatedType outer = inner.getAnnotatedOwnerType();
 118         Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
 119         Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
 120         Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 121                 + outer.getAnnotations().length);
 122     }
 123 
 124     public static void testInnerGeneric() throws Exception {
 125         Field f = GetAnnotatedOwnerType.class.getField("innerGeneric");
 126 
 127         // make sure inner is correctly annotated
 128         AnnotatedType inner = f.getAnnotatedType();
 129         Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
 130         Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 131                 + inner.getAnnotations().length);
 132 
 133         // make sure owner is correctly annotated, on the correct type
 134         AnnotatedType outer = inner.getAnnotatedOwnerType();
 135         Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
 136         Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
 137         Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 138                 + outer.getAnnotations().length);
 139     }
 140 
 141     public static void testInnerRaw() throws Exception {
 142         Field f = GetAnnotatedOwnerType.class.getField("innerRaw");
 143 
 144         // make sure inner is correctly annotated
 145         AnnotatedType inner = f.getAnnotatedType();
 146         Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
 147         Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 148                 + inner.getAnnotations().length);
 149 
 150         // make sure owner is correctly annotated, on the correct type
 151         AnnotatedType outer = inner.getAnnotatedOwnerType();
 152         Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
 153         Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
 154         Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 155                 + outer.getAnnotations().length);
 156     }
 157 
 158     public static void testLocalClass() throws Exception {
 159         class ALocalClass {}
 160         class OneMore {
 161             public @TA("null") ALocalClass c;
 162         }
 163         testNegative(OneMore.class.getField("c").getAnnotatedType(), "Local class should return null");
 164     }
 165 
 166     public static void testAnonymousClass() throws Exception {
 167         testNegative(GetAnnotatedOwnerType.class.getField("anonymous").getAnnotatedType(),
 168                 "Anonymous class should return null");
 169     }
 170 
 171     public static void testArray() throws Exception {
 172         AnnotatedType t = GetAnnotatedOwnerType.class.getField("dummy").getAnnotatedType();
 173         Asserts.assertTrue((t instanceof AnnotatedArrayType),
 174                 "Was expecting an AnnotatedArrayType " + t);
 175         testNegative(t, "" + t + " should not have an annotated owner type");
 176     }
 177 
 178     public static void testWildcard() throws Exception {
 179         AnnotatedType tt = GetAnnotatedOwnerType.class.getField("wildcard").getAnnotatedType();
 180         AnnotatedType t = ((AnnotatedParameterizedType)tt).getAnnotatedActualTypeArguments()[0];
 181         Asserts.assertTrue((t instanceof AnnotatedWildcardType),
 182                 "Was expecting an AnnotatedWildcardType " + t);
 183         testNegative(t, "" + t + " should not have an annotated owner type");
 184     }
 185 
 186     public static void testTypeParameter() throws Exception {
 187         AnnotatedType t = GetAnnotatedOwnerType.class.getField("tv").getAnnotatedType();
 188         Asserts.assertTrue((t instanceof AnnotatedTypeVariable),
 189                 "Was expecting an AnnotatedTypeVariable " + t);
 190         testNegative(t, "" + t + " should not have an annotated owner type");
 191     }
 192 
 193     public static void testTypeArgument() throws Exception {
 194         AnnotatedType tt = GetAnnotatedOwnerType.class.getField("typeArgument").getAnnotatedType();
 195         Asserts.assertEquals(tt.getAnnotation(TA.class).value(), "bad");
 196         Asserts.assertTrue(tt.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 197                 + tt.getAnnotations().length);
 198 
 199         // make sure inner is correctly annotated
 200         AnnotatedType inner = ((AnnotatedParameterizedType)tt).getAnnotatedActualTypeArguments()[0];
 201         Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "tb");
 202         Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 203                 + inner.getAnnotations().length);
 204 
 205         // make sure owner is correctly annotated
 206         AnnotatedType outer = inner.getAnnotatedOwnerType();
 207         Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "good");
 208         Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 209                 + outer.getAnnotations().length);
 210     }
 211 
 212     public static void testComplicated() throws Exception {
 213         Field f = GetAnnotatedOwnerType.class.getField("complicated");
 214 
 215         // Outermost level
 216         AnnotatedType t = f.getAnnotatedType();
 217         Asserts.assertTrue((t instanceof AnnotatedArrayType),
 218                 "Was expecting an AnnotatedArrayType " + t);
 219         testNegative(t, "" + t + " should not have an annotated owner type");
 220         Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
 221                 + t.getAnnotations().length);
 222 
 223         // Component type
 224         t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType();
 225         testNegative(t, "" + t + " should not have an annotated owner type");
 226         Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
 227                 + t.getAnnotations().length);
 228 
 229         // Type arg GetAnnotatedOwnerType<String>...D<Number>
 230         t = ((AnnotatedParameterizedType)t).getAnnotatedActualTypeArguments()[0];
 231         Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
 232                 + t.getAnnotations().length);
 233 
 234         // C<Class<?>, ? extends ...>
 235         t = t.getAnnotatedOwnerType();
 236         Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
 237                 + t.getAnnotations().length);
 238 
 239         // ? extends
 240         t = ((AnnotatedParameterizedType)t).getAnnotatedActualTypeArguments()[1];
 241         testNegative(t, "" + t + " should not have an annotated owner type");
 242         Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
 243                 + t.getAnnotations().length);
 244 
 245         // @TA("complicated") Exception
 246         t = ((AnnotatedWildcardType)t).getAnnotatedUpperBounds()[0];
 247         testNegative(t, "" + t + " should not have an annotated owner type");
 248         Asserts.assertEquals(t.getAnnotation(TA.class).value(), "complicated");
 249         Asserts.assertTrue(t.getAnnotations().length == 1, "expecting one (1) annotation, got: "
 250                 + t.getAnnotations().length);
 251     }
 252 
 253     private static void testNegative(AnnotatedType t, String msg) {
 254         Asserts.assertNull(t.getAnnotatedOwnerType(), msg);
 255     }
 256 
 257     public class Nested<AlsoDummy> {}
 258     public class B {
 259         public class C<R, S> {
 260             public class D<T> {
 261             }
 262         }
 263     }
 264 
 265     @Target(ElementType.TYPE_USE)
 266     @Retention(RetentionPolicy.RUNTIME)
 267     public @interface TA {
 268         String value();
 269     }
 270 
 271     @Target(ElementType.TYPE_USE)
 272     @Retention(RetentionPolicy.RUNTIME)
 273     public @interface TB {
 274         String value();
 275     }
 276 }
 277 
 278 class GetAnnotatedOwnerTypeAuxilliary {
 279     class Inner {}
 280 
 281     class InnerGeneric<Dummy> {}
 282 }