1 /*
2  * Copyright (c) 2007, 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  * @summary Tests com.sun.beans.TypeResolver
27  * @author Eamonn McManus
28  * @modules java.base/sun.reflect.generics.reflectiveObjects
29  *          java.desktop/com.sun.beans
30  */
31 
32 import com.sun.beans.TypeResolver;
33 
34 import java.lang.annotation.Annotation;
35 import java.lang.reflect.AnnotatedType;
36 import java.lang.reflect.Field;
37 import java.lang.reflect.GenericDeclaration;
38 import java.lang.reflect.Method;
39 import java.lang.reflect.Type;
40 import java.lang.reflect.TypeVariable;
41 import java.lang.reflect.WildcardType;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Comparator;
45 import java.util.List;
46 import java.util.Map;
47 
48 import sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl;
49 import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
50 
51 public class TestTypeResolver {
52     static final List<Class<?>> failedCases = new ArrayList<Class<?>>();
53 
main(String[] args)54     public static void main(String[] args) throws Exception {
55         test(TestTypeResolver.class);
56         if (failedCases.isEmpty())
57             System.out.println("TEST PASSED");
58         else {
59             System.out.println("TEST FAILED: failed cases: " + failedCases);
60             throw new Error("TEST FAILED");
61         }
62     }
63 
test(Class<?> c)64     private static void test(Class<?> c) throws Exception {
65         /* Every public nested class represents a test.  In each case, either
66          * the class contains further nested classes, in which case we
67          * call this method recursively; or it declares or inherits a
68          * method called getThing() and it declares a static field
69          * called "expect" which
70          * is the Type of that method's return value.  The test consists
71          * of checking that the value returned by
72          * TypeResolver.resolveInClass is indeed this Type.
73          */
74         System.out.println("Test " + c);
75         Class<?>[] nested = c.getClasses();
76         Arrays.sort(nested, classNameComparator);
77         for (Class<?> n : nested)
78             test(n);
79         final Method m;
80         try {
81             m = c.getMethod("getThing");
82         } catch (NoSuchMethodException e) {
83             if (nested.length == 0) {
84                 System.out.println(
85                         "TEST ERROR: class " + c.getName() + " has neither " +
86                                 "nested classes nor getThing() method");
87                 failedCases.add(c);
88             }
89             return;
90         }
91         Object expect = null;
92         try {
93             Field f = c.getDeclaredField("expect");
94             expect = f.get(null);
95         } catch (NoSuchFieldException e) {
96             Class<?> outer = c.getDeclaringClass();
97             if (outer != null) {
98                 try {
99                     Field f = outer.getDeclaredField("expect" + c.getSimpleName());
100                     expect = f.get(null);
101                 } catch (NoSuchFieldException e1) {
102                 }
103             }
104         }
105         if (expect == null) {
106             System.out.println(
107                     "TEST ERROR: class " + c.getName() + " has getThing() method " +
108                             "but not expect field");
109             failedCases.add(c);
110             return;
111         }
112         Type t = m.getGenericReturnType();
113 //        t = FixType.fixType(t, c);
114         t = TypeResolver.resolveInClass(c, t);
115         System.out.print("..." + t);
116         // check expected value, and incidentally equals method defined
117         // by private implementations of the various Type interfaces
118         if (expect.equals(t) && t.equals(expect))
119             System.out.println(", as expected");
120         else if ((expect.equals(t) || t.equals(expect)) && expect.toString().equals(t.toString()))
121             System.out.println(", as workaround of the 8023301 bug");
122         else {
123             System.out.println(" BUT SHOULD BE " + expect);
124             failedCases.add(c);
125         }
126     }
127 
128     private static class ClassNameComparator implements Comparator<Class<?>> {
compare(Class<?> a, Class<?> b)129         public int compare(Class<?> a, Class<?> b) {
130             return a.getName().compareTo(b.getName());
131         }
132     }
133 
134     private static final Comparator<Class<?>> classNameComparator =
135             new ClassNameComparator();
136 
137     private static abstract class TypeVariableImpl<D extends GenericDeclaration>
138             implements TypeVariable<D> {
139         private final String name;
140         private final D gd;
141         private final Type[] bounds;
142 
TypeVariableImpl(String name, D gd, Type... bounds)143         TypeVariableImpl(String name, D gd, Type... bounds) {
144             this.name = name;
145             this.gd = gd;
146             if (bounds.length == 0)
147                 bounds = new Type[] {Object.class};
148             this.bounds = bounds.clone();
149         }
150 
getBounds()151         public Type[] getBounds() {
152             return bounds.clone();
153         }
154 
getGenericDeclaration()155         public D getGenericDeclaration() {
156             return gd;
157         }
158 
getName()159         public String getName() {
160             return name;
161         }
162 
toString()163         public String toString() {
164             return name;
165         }
166 
equals(Object o)167         public boolean equals(Object o) {
168             if (!(o instanceof TypeVariable))
169                 return false;
170             TypeVariable tv = (TypeVariable) o;
171             return equal(name, tv.getName()) &&
172                     equal(gd, tv.getGenericDeclaration()) &&
173                     Arrays.equals(bounds, tv.getBounds());
174         }
175 
hashCode()176         public int hashCode() {
177             return hash(name) ^ hash(gd) ^ Arrays.hashCode(bounds);
178         }
179 
isAnnotationPresent(Class<? extends Annotation> annotationClass)180         public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
181             return false; // not used
182         }
183 
getAnnotation(Class<T> annotationClass)184         public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
185             return null; // not used
186         }
187 
getAnnotations(Class<T> annotationClass)188         public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
189             return null; // not used
190         }
191 
getAnnotations()192         public Annotation[] getAnnotations() {
193             return null; // not used
194         }
195 
getDeclaredAnnotation(Class<T> annotationClass)196         public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
197             return null; // not used
198         }
199 
getDeclaredAnnotations(Class<T> annotationClass)200         public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
201             return null; // not used
202         }
203 
getDeclaredAnnotations()204         public Annotation[] getDeclaredAnnotations() {
205             return null; // not used
206         }
207 
getAnnotatedBounds()208         public AnnotatedType[] getAnnotatedBounds() {
209             return null; // not used
210         }
211 
getAnnotationsByType(Class<T> annotationClass)212         public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
213             return null; // not used
214         }
215 
getDeclaredAnnotationsByType(Class<T> annotationClass)216         public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
217             return null; // not used
218         }
219 
220     }
221 
222     private static class ClassTypeVariable extends TypeVariableImpl<Class<?>> {
ClassTypeVariable(String name, Class<?> gd, Type... bounds)223         ClassTypeVariable(String name, Class<?> gd, Type... bounds) {
224             super(name, gd, bounds);
225         }
226     }
227 
228     private static class MethodTypeVariable extends TypeVariableImpl<Method> {
MethodTypeVariable(String name, Method gd, Type... bounds)229         MethodTypeVariable(String name, Method gd, Type... bounds) {
230             super(name, gd, bounds);
231         }
232     }
233 
234     private static class WildcardTypeImpl implements WildcardType {
235         private final Type[] upperBounds;
236         private final Type[] lowerBounds;
237 
WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds)238         WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
239             if (upperBounds == null || upperBounds.length == 0)
240                 upperBounds = new Type[] {Object.class};
241             if (lowerBounds == null)
242                 lowerBounds = new Type[0];
243             this.upperBounds = upperBounds.clone();
244             this.lowerBounds = lowerBounds.clone();
245         }
246 
getUpperBounds()247         public Type[] getUpperBounds() {
248             return upperBounds.clone();
249         }
250 
getLowerBounds()251         public Type[] getLowerBounds() {
252             return lowerBounds.clone();
253         }
254 
equals(Object o)255         public boolean equals(Object o) {
256             if (o instanceof WildcardType) {
257                 WildcardType wt = (WildcardType) o;
258                 return Arrays.equals(upperBounds, wt.getUpperBounds()) &&
259                         Arrays.equals(lowerBounds, wt.getLowerBounds());
260             } else
261                 return false;
262         }
263 
hashCode()264         public int hashCode() {
265             return Arrays.hashCode(upperBounds) ^ Arrays.hashCode(lowerBounds);
266         }
267 
toString()268         public String toString() {
269             StringBuilder sb = new StringBuilder("?");
270             if (upperBounds.length > 1 || upperBounds[0] != Object.class) {
271                 sb.append(" extends");
272                 appendBounds(sb, upperBounds);
273             }
274             if (lowerBounds.length > 0) {
275                 sb.append(" super");
276                 appendBounds(sb, lowerBounds);
277             }
278             return sb.toString();
279         }
280 
appendBounds(StringBuilder sb, Type[] bounds)281         private static void appendBounds(StringBuilder sb, Type[] bounds) {
282             boolean and = false;
283             for (Type bound : bounds) {
284                 if (and)
285                     sb.append(" &");
286                 sb.append(" ");
287                 if (bound instanceof Class)
288                     sb.append(((Class<?>) bound).getName());
289                 else
290                     sb.append(bound);
291                 and = true;
292             }
293         }
294     }
295 
equal(Object x, Object y)296     static boolean equal(Object x, Object y) {
297         if (x == y)
298             return true;
299         if (x == null || y == null)
300             return false;
301         return x.equals(y);
302     }
303 
hash(Object x)304     static int hash(Object x) {
305         return (x == null) ? null : x.hashCode();
306     }
307 
308 
309     public static class Outer<T> {
310         public class Inner {
getThing()311             public T getThing() {
312                 return null;
313             }
314         }
315 
316         static final Type expectInner = new ClassTypeVariable("T", Outer.class);
317     }
318 
319     public static class Super<T> {
320         static final Type expect = new ClassTypeVariable("T", Super.class);
321 
getThing()322         public T getThing() {
323             return null;
324         }
325     }
326 
327     public static class Int extends Super<Integer> {
328         static final Type expect = Integer.class;
329     }
330 
331     public static class IntOverride extends Int {
332         static final Type expect = Integer.class;
333 
getThing()334         public Integer getThing() {
335             return null;
336         }
337     }
338 
339     public static class Mid<X> extends Super<X> {
340         static final Type expect = new ClassTypeVariable("X", Mid.class);
341     }
342 
343     public static class Str extends Mid<String> {
344         static final Type expect = String.class;
345     }
346 
347     public static class ListInt extends Super<List<Integer>> {
348         static final Type expect = ParameterizedTypeImpl.make(
349                 List.class, new Type[] {Integer.class}, null);
350     }
351 
352     public static class ListIntSub extends ListInt {
353         static final Type expect = ParameterizedTypeImpl.make(
354                 List.class, new Type[] {Integer.class}, null);
355 
getThing()356         public List<Integer> getThing() {
357             return null;
358         }
359     }
360 
361     public static class ListU<U> extends Super<List<U>> {
362         static final Type expect = ParameterizedTypeImpl.make(
363                 List.class, new Type[] {new ClassTypeVariable("U", ListU.class)}, null);
364     }
365 
366     public static class ListUInt extends ListU<Integer> {
367         static final Type expect = ParameterizedTypeImpl.make(
368                 List.class, new Type[] {Integer.class}, null);
369     }
370 
371     public static class ListUSub<V> extends ListU<V> {
372         static final Type expect = ParameterizedTypeImpl.make(
373                 List.class, new Type[] {new ClassTypeVariable("V", ListUSub.class)}, null);
374 
getThing()375         public List<V> getThing() {
376             return null;
377         }
378     }
379 
380     public static class ListUSubInt extends ListUSub<Integer> {
381         static final Type expect = ParameterizedTypeImpl.make(
382                 List.class, new Type[] {Integer.class}, null);
383     }
384 
385     public static class TwoParams<S, T> extends Super<S> {
386         static final Type expect = new ClassTypeVariable("S", TwoParams.class);
387     }
388 
389     public static class TwoParamsSub<T> extends TwoParams<T, Integer> {
390         static final Type expect = new ClassTypeVariable("T", TwoParamsSub.class);
391     }
392 
393     public static class TwoParamsSubSub extends TwoParamsSub<String> {
394         static final Type expect = String.class;
395     }
396 
397     public static interface Intf<T> {
398         static final Type expect = new ClassTypeVariable("T", Intf.class);
399 
getThing()400         public T getThing();
401     }
402 
403     public static abstract class Impl implements Intf<String> {
404         static final Type expect = String.class;
405     }
406 
407     public static class Impl2 extends Super<String> implements Intf<String> {
408         static final Type expect = String.class;
409     }
410 
411     public static class Bound<T extends Number> extends Super<T> {
412         static final Type expect = new ClassTypeVariable("T", Bound.class, Number.class);
413     }
414 
415     public static class BoundInt extends Bound<Integer> {
416         static final Type expect = Integer.class;
417     }
418 
419     public static class RawBound extends Bound {
420         static final Type expect = Number.class;
421     }
422 
423     public static class RawBoundInt extends BoundInt {
424         static final Type expect = Integer.class;
425     }
426 
427     public static class MethodParam<T> {
428         private static final Method m;
429 
430         static {
431             try {
432                 m = MethodParam.class.getMethod("getThing");
433             } catch (Exception e) {
434                 throw new AssertionError(e);
435             }
436         }
437 
438         static final Type expect = new MethodTypeVariable("T", m);
439 
getThing()440         public <T> T getThing() {
441             return null;
442         }
443     }
444 
445     public static class Raw extends Super {
446         static final Type expect = Object.class;
447     }
448 
449     public static class RawSub extends Raw {
450         static final Type expect = Object.class;
451     }
452 
453     public static class SimpleArray extends Super<String[]> {
454         static final Type expect = String[].class;
455     }
456 
457     public static class GenericArray extends Super<List<String>[]> {
458         static final Type expect = GenericArrayTypeImpl.make(
459                 ParameterizedTypeImpl.make(List.class, new Type[] {String.class}, null));
460     }
461 
462     public static class GenericArrayT<T> extends Super<T[]> {
463         static final Type expect = GenericArrayTypeImpl.make(
464                 new ClassTypeVariable("T", GenericArrayT.class));
465     }
466 
467     public static class GenericArrayTSub extends GenericArrayT<String[]> {
468         static final Type expect = String[][].class;
469     }
470 
471     public static class Wildcard extends Super<List<?>> {
472         static final Type expect = ParameterizedTypeImpl.make(
473                 List.class, new Type[] {new WildcardTypeImpl(null, null)}, null);
474     }
475 
476     public static class WildcardT<T> extends Super<List<? extends T>> {
477         static final Type expect = ParameterizedTypeImpl.make(
478                 List.class,
479                 new Type[] {
480                         new WildcardTypeImpl(
481                                 new Type[] {new ClassTypeVariable("T", WildcardT.class)},
482                                 null)},
483                 null);
484     }
485 
486     public static class WildcardTSub extends WildcardT<Integer> {
487         static final Type expect = ParameterizedTypeImpl.make(
488                 List.class,
489                 new Type[] {
490                         new WildcardTypeImpl(
491                                 new Type[] {Integer.class},
492                                 null)},
493                 null);
494     }
495 
496     public static class WildcardTSubSub<X> extends WildcardTSub {
497         // X is just so we can have a raw subclass
498         static final Type expect = WildcardTSub.expect;
499     }
500 
501     public static class RawWildcardTSubSub extends WildcardTSubSub {
502         static final Type expect = List.class;
503     }
504 
505     public static class WildcardTSuper<T> extends Super<List<? super T>> {
506         static final Type expect = ParameterizedTypeImpl.make(
507                 List.class,
508                 new Type[] {
509                         new WildcardTypeImpl(
510                                 null,
511                                 new Type[] {new ClassTypeVariable("T", WildcardTSuper.class)})},
512                 null);
513     }
514 
515     public static class WildcardTSuperSub extends WildcardTSuper<Integer> {
516         static final Type expect = ParameterizedTypeImpl.make(
517                 List.class,
518                 new Type[] {
519                         new WildcardTypeImpl(
520                                 null,
521                                 new Type[] {Integer.class})},
522                 null);
523     }
524 
525     public static class SuperMap<K, V> {
526         static final Type expect = ParameterizedTypeImpl.make(
527                 Map.class,
528                 new Type[] {
529                         new ClassTypeVariable("K", SuperMap.class),
530                         new ClassTypeVariable("V", SuperMap.class)},
531                 null);
532 
getThing()533         public Map<K, V> getThing() {
534             return null;
535         }
536     }
537 
538     public static class SubMap extends SuperMap<String, Integer> {
539         static final Type expect = ParameterizedTypeImpl.make(
540                 Map.class,
541                 new Type[] {String.class, Integer.class},
542                 null);
543     }
544 
545     public static class ListListT<T> extends Super<List<List<T>>> {
546         static final Type expect = ParameterizedTypeImpl.make(
547                 List.class,
548                 new Type[] {
549                         ParameterizedTypeImpl.make(
550                                 List.class,
551                                 new Type[] {new ClassTypeVariable("T", ListListT.class)},
552                                 null)},
553                 null);
554     }
555 
556     public static class ListListString extends ListListT<String> {
557         static final Type expect = ParameterizedTypeImpl.make(
558                 List.class,
559                 new Type[] {
560                         ParameterizedTypeImpl.make(
561                                 List.class,
562                                 new Type[] {String.class},
563                                 null)},
564                 null);
565     }
566 
567     public static class UExtendsT<T, U extends T> extends Super<U> {
568         static final Type expect = new ClassTypeVariable(
569                 "U", UExtendsT.class, new ClassTypeVariable("T", UExtendsT.class));
570     }
571 
572     public static class UExtendsTSub extends UExtendsT<Number, Integer> {
573         static final Type expect = Integer.class;
574     }
575 
576     public static class SelfRef<T extends SelfRef<T>> extends Super<T> {
577         static final Type expect =
578                 SelfRef.class.getTypeParameters()[0];
579     }
580 
581     public static class SelfRefSub extends SelfRef<SelfRefSub> {
582         static final Type expect = SelfRefSub.class;
583     }
584 }
585