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 
main(String[] args)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 
testGeneric()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 
testRaw()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 
testNonGeneric()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 
testInnerGeneric()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 
testInnerRaw()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 
testLocalClass()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 
testAnonymousClass()166     public static void testAnonymousClass() throws Exception {
167         testNegative(GetAnnotatedOwnerType.class.getField("anonymous").getAnnotatedType(),
168                 "Anonymous class should return null");
169     }
170 
testArray()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 
testWildcard()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 
testTypeParameter()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 
testTypeArgument()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 
testComplicated()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 
testNegative(AnnotatedType t, String msg)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 {
value()268         String value();
269     }
270 
271     @Target(ElementType.TYPE_USE)
272     @Retention(RetentionPolicy.RUNTIME)
273     public @interface TB {
value()274         String value();
275     }
276 }
277 
278 class GetAnnotatedOwnerTypeAuxilliary {
279     class Inner {}
280 
281     class InnerGeneric<Dummy> {}
282 }
283