1 package com.fasterxml.classmate;
2
3 import java.io.Serializable;
4 import java.lang.reflect.*;
5 import java.util.*;
6
7 import com.fasterxml.classmate.types.*;
8 import com.fasterxml.classmate.util.ClassKey;
9 import com.fasterxml.classmate.util.ClassStack;
10 import com.fasterxml.classmate.util.LRUTypeCache;
11 import com.fasterxml.classmate.util.ResolvedTypeCache;
12 import com.fasterxml.classmate.util.ResolvedTypeKey;
13
14 /**
15  * Object that is used for resolving generic type information of a class
16  * so that it is accessible using simple API. Resolved types are also starting
17  * point for accessing resolved (generics aware) return and argument types
18  * of class members (methods, fields, constructors).
19  *<p>
20  * Note that resolver instances are stateful in that resolvers cache resolved
21  * types for efficiency. Since this is internal state and not directly visible
22  * to callers, access to state is fully synchronized so that access from
23  * multiple threads is safe.
24  */

25 @SuppressWarnings("serial")
26 public class TypeResolver implements Serializable
27 {
28     private final static ResolvedType[] NO_TYPES = new ResolvedType[0];
29     
30     /*
31     /**********************************************************************
32     /* Pre-created instances
33     /**********************************************************************
34      */

35
36     /**
37      * We will also need to return "unknown" type for cases where type variable binding
38      * is not found ('raw' instances of generic types); easiest way is to
39      * pre-create type for <code>java.lang.Object</code>
40      */

41     private final static ResolvedObjectType sJavaLangObject =
42         ResolvedObjectType.create(Object.classnullnullnull);
43
44     /**
45      * Since number of primitive types is small, and they are frequently needed,
46      * let's actually pre-create them for efficient reuse. Same goes for limited number
47      * of other "standard" types...
48      */

49     protected final static HashMap<ClassKey, ResolvedType> _primitiveTypes;
50     static {
51         _primitiveTypes = new HashMap<ClassKey, ResolvedType>(16);
52         for (ResolvedPrimitiveType type : ResolvedPrimitiveType.all()) {
53             _primitiveTypes.put(new ClassKey(type.getErasedType()), type);
54         }
55         // should we include "void"? might as well...
56         _primitiveTypes.put(new ClassKey(Void.TYPE), ResolvedPrimitiveType.voidType());
57         // and at least java.lang.Object should be added too.
58         _primitiveTypes.put(new ClassKey(Object.class), sJavaLangObject);
59         // but most other types can be added dynamically
60     }
61
62     /*
63     /**********************************************************************
64     /* Caching
65     /**********************************************************************
66      */

67     
68     /**
69      * Simple cache of types resolved by this resolver.
70      * Caching works because type instances themselves are mostly immutable;
71      * and properly synchronized in cases where transient data (raw members) are
72      * accessed.
73      */

74     protected final ResolvedTypeCache _resolvedTypes;
75
76     /*
77     /**********************************************************************
78     /* Life cycle
79     /**********************************************************************
80      */

81
82     /**
83      * Constructs type cache; equivalent to:
84      *<pre> 
85      *   TypeResolver(ResolvedTypeCache.lruCache(200));
86      *</pre>
87      */

88     public TypeResolver() {
89         this(ResolvedTypeCache.lruCache(200));
90     }
91
92     /**
93      * Constructor that specifies type cache to use.
94      *
95      * @param typeCache Cache to use for avoiding repeated resolution of already resolved
96      *    types
97      *
98      * @since 1.4
99      */

100     public TypeResolver(ResolvedTypeCache typeCache) {
101         _resolvedTypes = typeCache;
102     }
103
104     /*
105     /**********************************************************************
106     /* Factory methods, with explicit parameterization
107     /**********************************************************************
108      */

109     
110     /**
111      * Factory method for resolving given base type
112      * using specified types as type parameters.
113      * Sample usage would be:
114      *<pre>
115      *  ResolvedType type = TypeResolver.resolve(List.class, Integer.class);
116      *</pre>
117      * which would be equivalent to
118      *<pre>
119      *  ResolvedType type = TypeResolver.resolve(new GenericType&lt;List&lt;Integer&gt;&gt;() { });
120      *</pre>
121      * Note that you can mix different types of type parameters, whether already
122      * resolved ({@link ResolvedType}), type-erased ({@link java.lang.Class}) or
123      * generic type reference ({@link GenericType}).
124      */

125     public ResolvedType resolve(Type type, Type... typeParameters)
126     {
127         boolean noParams = (typeParameters == null || typeParameters.length == 0);
128         TypeBindings bindings;
129         Class<?> rawBase;
130
131         if (type instanceof Class<?>) {
132             bindings = TypeBindings.emptyBindings();
133             if (noParams) {
134                 return _fromClass(null, (Class<?>) type, bindings);
135             }
136             rawBase = (Class<?>) type;
137         } else if (type instanceof GenericType<?>) {
138             bindings = TypeBindings.emptyBindings();
139             if (noParams) {
140                 return _fromGenericType(null, (GenericType<?>) type, bindings);
141             }
142             ResolvedType rt = _fromAny(null, type, bindings);
143             rawBase = rt.getErasedType();
144         } else if (type instanceof ResolvedType) {
145             ResolvedType rt = (ResolvedType) type;
146             if (noParams) {
147                 return rt;
148             }
149             bindings = rt.getTypeBindings();
150             rawBase = rt.getErasedType();
151         } else {
152             bindings = TypeBindings.emptyBindings();
153             if (noParams) {
154                 return resolve(bindings, type);
155             }
156             // Quite convoluted... but necessary to find Class<?> underlying it all
157             ResolvedType rt = _fromAny(null, type, bindings);
158             rawBase = rt.getErasedType();
159         }
160
161         // Next: resolve type parameters
162         int len = typeParameters.length;
163         ResolvedType[] resolvedParams = new ResolvedType[len];
164         for (int i = 0; i < len; ++i) {
165             resolvedParams[i] = _fromAny(null, typeParameters[i], bindings);
166         }
167         return _fromClass(null, rawBase, TypeBindings.create(rawBase, resolvedParams));
168     }
169
170     /**
171      * Factory method for constructing array type of given element type.
172      */

173     public ResolvedArrayType arrayType(Type elementType)
174     {
175         ResolvedType resolvedElementType = resolve(TypeBindings.emptyBindings(), elementType);
176         // Arrays are cumbersome for some reason:
177         Object emptyArray = Array.newInstance(resolvedElementType.getErasedType(), 0);
178         // Should we try to use cache? It's bit tricky, so let's not bother yet
179         return new ResolvedArrayType(emptyArray.getClass(), TypeBindings.emptyBindings(),
180                 resolvedElementType);
181     }
182
183     /**
184      * Factory method for resolving specified Java {@link java.lang.reflect.Type}, given
185      * {@link TypeBindings} needed to resolve any type variables.
186      *<p>
187      * Use of this method is discouraged (use if and only if you really know what you
188      * are doing!); but if used, type bindings passed should come from {@link ResolvedType}
189      * instance of declaring class (or interface).
190      *<p>
191      * NOTE: order of arguments was reversed for 0.8, to avoid problems with
192      * overload varargs method.
193      */

194     public ResolvedType resolve(TypeBindings typeBindings, Type jdkType)
195     {
196         return _fromAny(null, jdkType, typeBindings);
197     }
198
199     /**
200      * Factory method for constructing sub-classing specified type; class specified
201      * as sub-class must be compatible according to basic Java inheritance rules
202      * (subtype must properly extend or implement specified supertype).
203      *<p>
204      * A typical use case here is to refine a generic type; for example, given
205      * that we have generic type like <code>List&lt;Integer&gt;</code>, but we want
206      * a more specific implementation type like
207      * class <code>ArrayList</code> but with same parameterization (here just <code>Integer</code>),
208      * we could achieve it by:
209      *<pre>
210      *  ResolvedType mapType = typeResolver.resolve(List.class, Integer.class);
211      *  ResolveType concreteMapType = typeResolver.resolveSubType(mapType, ArrayList.class);
212      *</pre>
213      * (in this case, it would have been simpler to resolve directly; but in some
214      * cases we are handled supertype and want to refine it, in which case steps
215      * would be the same but separated by other code)
216      *<p>
217      * Note that this method will fail if extension can not succeed; either because
218      * this type is not extendable (sub-classable) -- which is true for primitive
219      * and array types -- or because given class is not a subtype of this type.
220      * To check whether subtyping could succeed, you can call
221      * {@link ResolvedType#canCreateSubtypes()} to see if supertype can ever
222      * be extended.
223      *
224      * @param supertype Type to subtype (extend)
225      * @param subtype Type-erased sub-class or sub-interface
226      * 
227      * @return Resolved subtype
228      * 
229      * @throws IllegalArgumentException If this type can be extended in general, but not into specified sub-class
230      * @throws UnsupportedOperationException If this type can not be sub-classed
231      */

232     public ResolvedType resolveSubtype(ResolvedType supertype, final Class<?> subtype)
233         throws IllegalArgumentException, UnsupportedOperationException
234     {
235         // first: if it's a recursive reference, find out referred-to type
236         ResolvedType refType = supertype.getSelfReferencedType();
237         if (refType != null) {
238             supertype = refType;
239         }
240         // Then, trivial check for case where subtype is supertype...
241         final Class<?> superclass = supertype.getErasedType();
242         if (superclass == subtype) { // unlikely but cheap check so let's just do it
243             return supertype;
244         }
245         // First: can not sub-class primitives, or array types
246         if (!supertype.canCreateSubtypes()) {
247             throw new UnsupportedOperationException("Can not subtype primitive or array types (type "+supertype.getFullDescription()+")");
248         }
249         // And in general must be able to subtype as per JVM rules:
250         if (!superclass.isAssignableFrom(subtype)) {
251             throw new IllegalArgumentException("Can not sub-class "+supertype.getBriefDescription()
252                     +" into "+subtype.getName());
253         }
254         // Ok, then, let us instantiate type with placeholders
255         ResolvedType resolvedSubtype;
256         int paramCount = subtype.getTypeParameters().length;
257         TypePlaceHolder[] placeholders;
258         TypeBindings tbForPlaceholders;
259
260         if (paramCount == 0) { // no generics
261             placeholders = null;
262             // 26-Oct-2015, tatu: Used to do "full" call:
263 //            resolvedSubtype = resolve(subtype);
264             // but should be able to streamline
265             tbForPlaceholders = TypeBindings.emptyBindings();
266         } else {
267             placeholders = new TypePlaceHolder[paramCount];
268             ResolvedType[] resolvedParams = new ResolvedType[paramCount];
269             for (int i = 0; i < paramCount; ++i) {
270                 resolvedParams[i] = placeholders[i] = new TypePlaceHolder(i);
271             }
272             tbForPlaceholders = TypeBindings.create(subtype, resolvedParams);
273         }
274         resolvedSubtype = _fromClass(null, subtype, tbForPlaceholders);
275         ResolvedType resolvedSupertype = resolvedSubtype.findSupertype(superclass);
276         if (resolvedSupertype == null) { // sanity check, should never occur
277             throw new IllegalArgumentException("Internal error: unable to locate supertype ("+subtype.getName()+") for type "+supertype.getBriefDescription());
278         }
279         // Ok, then, let's find and verify type assignments; resolve type holders if any
280         // (and yes, even for no-type-parameters case)
281         _resolveTypePlaceholders(supertype, resolvedSupertype);
282         // And then re-construct, if necessary
283         if (paramCount == 0) { // if no type parameters, fine as is
284             return resolvedSubtype;
285         }
286         // but with type parameters, need to reconstruct
287         final ResolvedType[] typeParams = new ResolvedType[paramCount];
288         for (int i = 0; i < paramCount; ++i) {
289             ResolvedType t = placeholders[i].actualType();
290             // Is it ok for it to be left unassigned? For now let's not allow that
291             // 18-Oct-2017, tatu: Highly likely that we'll need to allow this, substitute with "unknown" --
292             //    had to do that in Jackson. Occurs when subtype is generic, with "bogus" type declared
293             //    but not bound in supertype(s). But leaving checking in for now.
294             if (t == null) {
295                 throw new IllegalArgumentException("Failed to find type parameter #"+(i+1)+"/"
296                         +paramCount+for "+subtype.getName());
297             }
298             typeParams[i] = t;
299         }
300         return resolve(subtype, typeParams);
301     }
302
303     /*
304     /**********************************************************************
305     /* Misc other methods
306     /**********************************************************************
307      */

308
309     /**
310      * Convenience method that can be used to checked whether given resolved type
311      * (with erased type of <code>java.lang.Object</code>) is a placeholder
312      * for "self-reference"; these are nasty recursive ("self") types
313      * needed with some interfaces
314      *
315      * @param type Type to check
316      */

317     public static boolean isSelfReference(ResolvedType type)
318     {
319         return (type instanceof ResolvedRecursiveType);
320     }
321
322     /*
323     /**********************************************************************
324     /* Internal methods, second-level factory methods
325     /**********************************************************************
326      */

327
328     private ResolvedType _fromAny(ClassStack context, Type mainType, TypeBindings typeBindings)
329     {
330         if (mainType instanceof Class<?>) {
331             return _fromClass(context, (Class<?>) mainType, typeBindings);
332         }
333         if (mainType instanceof ParameterizedType) {
334             return _fromParamType(context, (ParameterizedType) mainType, typeBindings);
335         }
336         if (mainType instanceof ResolvedType) { // Esp. TypePlaceHolder
337             return (ResolvedType) mainType;
338         }
339         if (mainType instanceof GenericType<?>) {
340             return _fromGenericType(context, (GenericType<?>) mainType, typeBindings);
341         }
342         if (mainType instanceof GenericArrayType) {
343             return _fromArrayType(context, (GenericArrayType) mainType, typeBindings);
344         }
345         if (mainType instanceof TypeVariable<?>) {
346             return _fromVariable(context, (TypeVariable<?>) mainType, typeBindings);
347         }
348         if (mainType instanceof WildcardType) {
349             return _fromWildcard(context, (WildcardType) mainType, typeBindings);
350         }
351         // should never get here...
352         throw new IllegalArgumentException("Unrecognized type class: "+mainType.getClass().getName());
353     }
354
355     private ResolvedType _fromClass(ClassStack context, Class<?> rawType, TypeBindings typeBindings)
356     {
357         // First: a primitive type perhaps?
358         ResolvedType type = _primitiveTypes.get(new ClassKey(rawType));
359         if (type != null) {
360             return type;
361         }
362         // Second: recursive reference?
363         if (context == null) {
364             context = new ClassStack(rawType);
365         } else {
366             ClassStack prev = context.find(rawType);
367             if (prev != null) {
368                 // Self-reference: needs special handling, then...
369                 ResolvedRecursiveType selfRef = new ResolvedRecursiveType(rawType, typeBindings);
370                 prev.addSelfReference(selfRef);
371                 return selfRef;
372             }
373             // no, can just add
374             context = context.child(rawType);
375         }
376
377         // If not, already recently resolved?
378         ResolvedType[] typeParameters = typeBindings.typeParameterArray();
379         ResolvedTypeKey key = _resolvedTypes.key(rawType, typeParameters);
380         // 25-Oct-2015, tatu: one twist; if any TypePlaceHolders included, key will NOT be created,
381         //   which means that caching should not be used (since type is mutable)
382         if (key == null) {
383             type = _constructType(context, rawType, typeBindings);
384         } else {
385             type = _resolvedTypes.find(key);
386             if (type == null) {
387                 type = _constructType(context, rawType, typeBindings);
388                 _resolvedTypes.put(key, type);
389             }
390         }
391         context.resolveSelfReferences(type);
392         return type;
393     }
394
395     /**
396      * Factory method for resolving given generic type, defined by using sub-class
397      * instance of {@link GenericType}
398      */

399     private ResolvedType _fromGenericType(ClassStack context, GenericType<?> generic, TypeBindings typeBindings)
400     {
401         /* To allow multiple levels of inheritance (just in case someone
402          * wants to go to town with inheritance of GenericType),
403          * we better resolve the whole thing; then dig out
404          * type parameterization...
405          */

406         ResolvedType type = _fromClass(context, generic.getClass(), typeBindings);
407         ResolvedType genType = type.findSupertype(GenericType.class);
408         if (genType == null) { // sanity check; shouldn't occur
409             throw new IllegalArgumentException("Unparameterized GenericType instance ("+generic.getClass().getName()+")");
410         }
411         TypeBindings b = genType.getTypeBindings();
412         ResolvedType[] params = b.typeParameterArray();
413         if (params.length == 0) {
414             throw new IllegalArgumentException("Unparameterized GenericType instance ("+generic.getClass().getName()+")");
415         }
416         return params[0];
417     }
418
419     private ResolvedType _constructType(ClassStack context, Class<?> rawType, TypeBindings typeBindings)
420     {
421         // Ok: no easy shortcut, let's figure out type of type...
422         if (rawType.isArray()) {
423             ResolvedType elementType = _fromAny(context, rawType.getComponentType(), typeBindings);
424             return new ResolvedArrayType(rawType, typeBindings, elementType);
425         }
426         // Work-around/fix for [#33]: if the type has no type parameters, don't include
427         // typeBindings in the ResolvedType
428         if (!typeBindings.isEmpty() && rawType.getTypeParameters().length == 0) {
429             typeBindings = TypeBindings.emptyBindings();
430         }
431         // For other types super interfaces are needed...
432         if (rawType.isInterface()) {
433             return new ResolvedInterfaceType(rawType, typeBindings,
434                     _resolveSuperInterfaces(context, rawType, typeBindings));
435             
436         }
437         return new ResolvedObjectType(rawType, typeBindings,
438                 _resolveSuperClass(context, rawType, typeBindings),
439                 _resolveSuperInterfaces(context, rawType, typeBindings));
440     }
441
442     private ResolvedType[] _resolveSuperInterfaces(ClassStack context, Class<?> rawType, TypeBindings typeBindings)
443     {
444         Type[] types = rawType.getGenericInterfaces();
445         if (types == null || types.length == 0) {
446             return NO_TYPES;
447         }
448         int len = types.length;
449         ResolvedType[] resolved = new ResolvedType[len];
450         for (int i = 0; i < len; ++i) {
451             resolved[i] = _fromAny(context, types[i], typeBindings);
452         }
453         return resolved;
454     }
455
456     /**
457      * NOTE: return type changed in 1.0.1 from {@link ResolvedObjectType} to
458      *    {@link ResolvedType}, since it was found that other types may
459      *    be returned...
460      * 
461      * @return Usually a {@link ResolvedObjectType}, but possibly also
462      *    {@link ResolvedRecursiveType}
463      */

464     private ResolvedType _resolveSuperClass(ClassStack context, Class<?> rawType, TypeBindings typeBindings)
465     {
466         Type parent = rawType.getGenericSuperclass();
467         if (parent == null) {
468             return null;
469         }
470         return _fromAny(context, parent, typeBindings);
471     }
472     
473     private ResolvedType _fromParamType(ClassStack context, ParameterizedType ptype, TypeBindings parentBindings)
474     {
475         /* First: what is the actual base type? One odd thing is that 'getRawType'
476          * returns Type, not Class<?> as one might expect. But let's assume it is
477          * always of type Class: if not, need to add more code to resolve it...
478          */

479         Class<?> rawType = (Class<?>) ptype.getRawType();
480         Type[] params = ptype.getActualTypeArguments();
481         int len = params.length;
482         ResolvedType[] types = new ResolvedType[len];
483
484         for (int i = 0; i < len; ++i) {
485             types[i] = _fromAny(context, params[i], parentBindings);
486         }
487         // Ok: this gives us current bindings for this type:
488         TypeBindings newBindings = TypeBindings.create(rawType, types);
489         return _fromClass(context, rawType, newBindings);
490     }
491
492     private ResolvedType _fromArrayType(ClassStack context, GenericArrayType arrayType, TypeBindings typeBindings)
493     {
494         ResolvedType elementType = _fromAny(context, arrayType.getGenericComponentType(), typeBindings);
495         // Figuring out raw class for generic array is actually bit tricky...
496         Object emptyArray = Array.newInstance(elementType.getErasedType(), 0);
497         return new ResolvedArrayType(emptyArray.getClass(), typeBindings, elementType);
498     }
499
500     private ResolvedType _fromWildcard(ClassStack context, WildcardType wildType, TypeBindings typeBindings)
501     {
502         /* Similar to challenges with TypeVariable, we may have multiple upper bounds.
503          * But it is also possible that if upper bound defaults to Object, we might want to
504          * consider lower bounds instead?
505          * For now, we won't try anything more advanced; above is just for future reference.
506          */

507         return _fromAny(context, wildType.getUpperBounds()[0], typeBindings);
508     }
509     
510     private ResolvedType _fromVariable(ClassStack context, TypeVariable<?> variable, TypeBindings typeBindings)
511     {
512         // ideally should find it via bindings:
513         String name = variable.getName();
514         ResolvedType type = typeBindings.findBoundType(name);
515
516         if (type != null) {
517             return type;
518         }
519         
520         /* but if not, use bounds... note that approach here is simplistic; not taking
521          * into account possible multiple bounds, nor consider upper bounds.
522          */

523         /* 02-Mar-2011, tatu: As per issue#4, need to avoid self-reference cycles here;
524          *   can be handled by (temporarily) adding binding:
525          */

526         if (typeBindings.hasUnbound(name)) {
527             return sJavaLangObject;
528         }
529         typeBindings = typeBindings.withUnboundVariable(name);
530
531         Type[] bounds = variable.getBounds();
532         return _fromAny(context, bounds[0], typeBindings);
533     }
534
535     /*
536     /**********************************************************************
537     /* Internal methods, replacing and verifying type placeholders
538     /**********************************************************************
539      */

540
541     /**
542      * Method called to verify that types match; and if there are any placeholders,
543      * replace them in <code>actualType</code>.
544      *
545      * @param sourceType Original base type used for specification/refinement
546      * @param actualType Base type instance after re-resolving, possibly containing type placeholders
547      */

548     private void _resolveTypePlaceholders(ResolvedType sourceType, ResolvedType actualType)
549         throws IllegalArgumentException
550     {
551         List<ResolvedType> expectedTypes = sourceType.getTypeParameters();
552         List<ResolvedType> actualTypes = actualType.getTypeParameters();
553         for (int i = 0, len = expectedTypes.size(); i < len; ++i) {
554             ResolvedType exp = expectedTypes.get(i);
555             ResolvedType act = actualTypes.get(i);
556             if (!_verifyAndResolve(exp, act)) {
557                 throw new IllegalArgumentException("Type parameter #"+(i+1)+"/"+len+" differs; expected "
558                         +exp.getBriefDescription()+", got "+act.getBriefDescription());
559             }
560         }
561     }
562
563     private boolean _verifyAndResolve(ResolvedType exp, ResolvedType act)
564     {
565         // See if we have an actual type placeholder to resolve; if yes, replace
566         if (act instanceof TypePlaceHolder) {
567             ((TypePlaceHolder) act).actualType(exp);
568             return true;
569         }
570         // if not, try to verify compatibility. But note that we can not
571         // use simple equality as we need to resolve recursively
572         if (exp.getErasedType() != act.getErasedType()) {
573             return false;
574         }
575         // But we can check type parameters "blindly"
576         List<ResolvedType> expectedTypes = exp.getTypeParameters();
577         List<ResolvedType> actualTypes = act.getTypeParameters();
578         for (int i = 0, len = expectedTypes.size(); i < len; ++i) {
579             ResolvedType exp2 = expectedTypes.get(i);
580             ResolvedType act2 = actualTypes.get(i);
581             if (!_verifyAndResolve(exp2, act2)) {
582                 return false;
583             }
584         }
585         return true;
586     }
587 }
588