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 
  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 
  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<?>> {
 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 
 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 
 151         public Type[] getBounds() {
 152             return bounds.clone();
 153         }
 154 
 155         public D getGenericDeclaration() {
 156             return gd;
 157         }
 158 
 159         public String getName() {
 160             return name;
 161         }
 162 
 163         public String toString() {
 164             return name;
 165         }
 166 
 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 
 176         public int hashCode() {
 177             return hash(name) ^ hash(gd) ^ Arrays.hashCode(bounds);
 178         }
 179 
 180         public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
 181             return false; // not used
 182         }
 183 
 184         public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
 185             return null; // not used
 186         }
 187 
 188         public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
 189             return null; // not used
 190         }
 191 
 192         public Annotation[] getAnnotations() {
 193             return null; // not used
 194         }
 195 
 196         public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
 197             return null; // not used
 198         }
 199 
 200         public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
 201             return null; // not used
 202         }
 203 
 204         public Annotation[] getDeclaredAnnotations() {
 205             return null; // not used
 206         }
 207 
 208         public AnnotatedType[] getAnnotatedBounds() {
 209             return null; // not used
 210         }
 211 
 212         public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
 213             return null; // not used
 214         }
 215 
 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<?>> {
 223         ClassTypeVariable(String name, Class<?> gd, Type... bounds) {
 224             super(name, gd, bounds);
 225         }
 226     }
 227 
 228     private static class MethodTypeVariable extends TypeVariableImpl<Method> {
 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 
 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 
 247         public Type[] getUpperBounds() {
 248             return upperBounds.clone();
 249         }
 250 
 251         public Type[] getLowerBounds() {
 252             return lowerBounds.clone();
 253         }
 254 
 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 
 264         public int hashCode() {
 265             return Arrays.hashCode(upperBounds) ^ Arrays.hashCode(lowerBounds);
 266         }
 267 
 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 
 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 
 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 
 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 {
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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 }