• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.util;
2 
3 import java.io.Closeable;
4 import java.io.IOException;
5 import java.lang.annotation.Annotation;
6 import java.lang.reflect.*;
7 import java.util.*;
8 
9 import com.fasterxml.jackson.core.JsonGenerator;
10 import com.fasterxml.jackson.core.JsonProcessingException;
11 import com.fasterxml.jackson.databind.DeserializationContext;
12 import com.fasterxml.jackson.databind.JavaType;
13 import com.fasterxml.jackson.databind.JsonMappingException;
14 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
15 
16 public final class ClassUtil
17 {
18     private final static Class<?> CLS_OBJECT = Object.class;
19 
20     private final static Annotation[] NO_ANNOTATIONS = new Annotation[0];
21     private final static Ctor[] NO_CTORS = new Ctor[0];
22 
23     private final static Iterator<?> EMPTY_ITERATOR = Collections.emptyIterator();
24 
25     /*
26     /**********************************************************
27     /* Simple factory methods
28     /**********************************************************
29      */
30 
31     /**
32      * @since 2.7
33      */
34     @SuppressWarnings("unchecked")
emptyIterator()35     public static <T> Iterator<T> emptyIterator() {
36         return (Iterator<T>) EMPTY_ITERATOR;
37     }
38 
39     /*
40     /**********************************************************
41     /* Methods that deal with inheritance
42     /**********************************************************
43      */
44 
45     /**
46      * Method that will find all sub-classes and implemented interfaces
47      * of a given class or interface. Classes are listed in order of
48      * precedence, starting with the immediate super-class, followed by
49      * interfaces class directly declares to implemented, and then recursively
50      * followed by parent of super-class and so forth.
51      * Note that <code>Object.class</code> is not included in the list
52      * regardless of whether <code>endBefore</code> argument is defined or not.
53      *
54      * @param endBefore Super-type to NOT include in results, if any; when
55      *    encountered, will be ignored (and no super types are checked).
56      *
57      * @since 2.7
58      */
findSuperTypes(JavaType type, Class<?> endBefore, boolean addClassItself)59     public static List<JavaType> findSuperTypes(JavaType type, Class<?> endBefore,
60             boolean addClassItself) {
61         if ((type == null) || type.hasRawClass(endBefore) || type.hasRawClass(Object.class)) {
62             return Collections.emptyList();
63         }
64         List<JavaType> result = new ArrayList<JavaType>(8);
65         _addSuperTypes(type, endBefore, result, addClassItself);
66         return result;
67     }
68 
69     /**
70      * @since 2.7
71      */
findRawSuperTypes(Class<?> cls, Class<?> endBefore, boolean addClassItself)72     public static List<Class<?>> findRawSuperTypes(Class<?> cls, Class<?> endBefore, boolean addClassItself) {
73         if ((cls == null) || (cls == endBefore) || (cls == Object.class)) {
74             return Collections.emptyList();
75         }
76         List<Class<?>> result = new ArrayList<Class<?>>(8);
77         _addRawSuperTypes(cls, endBefore, result, addClassItself);
78         return result;
79     }
80 
81     /**
82      * Method for finding all super classes (but not super interfaces) of given class,
83      * starting with the immediate super class and ending in the most distant one.
84      * Class itself is included if <code>addClassItself</code> is true.
85      *<p>
86      * NOTE: mostly/only called to resolve mix-ins as that's where we do not care
87      * about fully-resolved types, just associated annotations.
88      *
89      * @since 2.7
90      */
findSuperClasses(Class<?> cls, Class<?> endBefore, boolean addClassItself)91     public static List<Class<?>> findSuperClasses(Class<?> cls, Class<?> endBefore,
92             boolean addClassItself) {
93         List<Class<?>> result = new ArrayList<Class<?>>(8);
94         if ((cls != null) && (cls != endBefore))  {
95             if (addClassItself) {
96                 result.add(cls);
97             }
98             while ((cls = cls.getSuperclass()) != null) {
99                 if (cls == endBefore) {
100                     break;
101                 }
102                 result.add(cls);
103             }
104         }
105         return result;
106     }
107 
108     @Deprecated // since 2.7
findSuperTypes(Class<?> cls, Class<?> endBefore)109     public static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore) {
110         return findSuperTypes(cls, endBefore, new ArrayList<Class<?>>(8));
111     }
112 
113     @Deprecated // since 2.7
findSuperTypes(Class<?> cls, Class<?> endBefore, List<Class<?>> result)114     public static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore, List<Class<?>> result) {
115         _addRawSuperTypes(cls, endBefore, result, false);
116         return result;
117     }
118 
_addSuperTypes(JavaType type, Class<?> endBefore, Collection<JavaType> result, boolean addClassItself)119     private static void _addSuperTypes(JavaType type, Class<?> endBefore, Collection<JavaType> result,
120             boolean addClassItself)
121     {
122         if (type == null) {
123             return;
124         }
125         final Class<?> cls = type.getRawClass();
126         if (cls == endBefore || cls == Object.class) { return; }
127         if (addClassItself) {
128             if (result.contains(type)) { // already added, no need to check supers
129                 return;
130             }
131             result.add(type);
132         }
133         for (JavaType intCls : type.getInterfaces()) {
134             _addSuperTypes(intCls, endBefore, result, true);
135         }
136         _addSuperTypes(type.getSuperClass(), endBefore, result, true);
137     }
138 
_addRawSuperTypes(Class<?> cls, Class<?> endBefore, Collection<Class<?>> result, boolean addClassItself)139     private static void _addRawSuperTypes(Class<?> cls, Class<?> endBefore, Collection<Class<?>> result, boolean addClassItself) {
140         if (cls == endBefore || cls == null || cls == Object.class) { return; }
141         if (addClassItself) {
142             if (result.contains(cls)) { // already added, no need to check supers
143                 return;
144             }
145             result.add(cls);
146         }
147         for (Class<?> intCls : _interfaces(cls)) {
148             _addRawSuperTypes(intCls, endBefore, result, true);
149         }
150         _addRawSuperTypes(cls.getSuperclass(), endBefore, result, true);
151     }
152 
153     /*
154     /**********************************************************
155     /* Class type detection methods
156     /**********************************************************
157      */
158 
159     /**
160      * @return Null if class might be a bean; type String (that identifies
161      *   why it's not a bean) if not
162      */
canBeABeanType(Class<?> type)163     public static String canBeABeanType(Class<?> type)
164     {
165         // First: language constructs that ain't beans:
166         if (type.isAnnotation()) {
167             return "annotation";
168         }
169         if (type.isArray()) {
170             return "array";
171         }
172         if (Enum.class.isAssignableFrom(type)) {
173             return "enum";
174         }
175         if (type.isPrimitive()) {
176             return "primitive";
177         }
178 
179         // Anything else? Seems valid, then
180         return null;
181     }
182 
isLocalType(Class<?> type, boolean allowNonStatic)183     public static String isLocalType(Class<?> type, boolean allowNonStatic)
184     {
185         /* As per [JACKSON-187], GAE seems to throw SecurityExceptions
186          * here and there... and GAE itself has a bug, too
187          * Bah. So we need to catch some wayward exceptions on GAE
188          */
189         try {
190             final boolean isStatic = Modifier.isStatic(type.getModifiers());
191 
192             // one more: method locals, anonymous, are not good:
193             // 23-Jun-2020, tatu: [databind#2758] With JDK14+ should allow
194             //    local Record types, however
195             if (!isStatic && hasEnclosingMethod(type)) {
196                 return "local/anonymous";
197             }
198             /* But how about non-static inner classes? Can't construct
199              * easily (theoretically, we could try to check if parent
200              * happens to be enclosing... but that gets convoluted)
201              */
202             if (!allowNonStatic) {
203                 if (!isStatic && getEnclosingClass(type) != null) {
204                     return "non-static member class";
205                 }
206             }
207         }
208         catch (SecurityException e) { }
209         catch (NullPointerException e) { }
210         return null;
211     }
212 
213     /**
214      * Method for finding enclosing class for non-static inner classes
215      */
getOuterClass(Class<?> type)216     public static Class<?> getOuterClass(Class<?> type)
217     {
218         // as above, GAE has some issues...
219         if (!Modifier.isStatic(type.getModifiers())) {
220             try {
221                 // one more: method locals, anonymous, are not good:
222                 if (hasEnclosingMethod(type)) {
223                     return null;
224                 }
225                 return getEnclosingClass(type);
226             } catch (SecurityException e) { }
227         }
228         return null;
229     }
230 
231     /**
232      * Helper method used to weed out dynamic Proxy types; types that do
233      * not expose concrete method API that we could use to figure out
234      * automatic Bean (property) based serialization.
235      */
isProxyType(Class<?> type)236     public static boolean isProxyType(Class<?> type)
237     {
238         // As per [databind#57], should NOT disqualify JDK proxy:
239         /*
240         // Then: well-known proxy (etc) classes
241         if (Proxy.isProxyClass(type)) {
242             return true;
243         }
244         */
245         String name = type.getName();
246         // Hibernate uses proxies heavily as well:
247         if (name.startsWith("net.sf.cglib.proxy.")
248             || name.startsWith("org.hibernate.proxy.")) {
249             return true;
250         }
251         // Not one of known proxies, nope:
252         return false;
253     }
254 
255     /**
256      * Helper method that checks if given class is a concrete one;
257      * that is, not an interface or abstract class.
258      */
isConcrete(Class<?> type)259     public static boolean isConcrete(Class<?> type)
260     {
261         int mod = type.getModifiers();
262         return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0;
263     }
264 
isConcrete(Member member)265     public static boolean isConcrete(Member member)
266     {
267         int mod = member.getModifiers();
268         return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0;
269     }
270 
isCollectionMapOrArray(Class<?> type)271     public static boolean isCollectionMapOrArray(Class<?> type)
272     {
273         if (type.isArray()) return true;
274         if (Collection.class.isAssignableFrom(type)) return true;
275         if (Map.class.isAssignableFrom(type)) return true;
276         return false;
277     }
278 
isBogusClass(Class<?> cls)279     public static boolean isBogusClass(Class<?> cls) {
280         return (cls == Void.class || cls == Void.TYPE
281                 || cls == com.fasterxml.jackson.databind.annotation.NoClass.class);
282     }
283 
284     /**
285      * @since 2.7
286      */
isObjectOrPrimitive(Class<?> cls)287     public static boolean isObjectOrPrimitive(Class<?> cls) {
288         return (cls == CLS_OBJECT) || cls.isPrimitive();
289     }
290 
291     /**
292      * @since 2.9
293      */
hasClass(Object inst, Class<?> raw)294     public static boolean hasClass(Object inst, Class<?> raw) {
295         // 10-Nov-2016, tatu: Could use `Class.isInstance()` if we didn't care
296         //    about being exactly that type
297         return (inst != null) && (inst.getClass() == raw);
298     }
299 
300     /**
301      * @since 2.9
302      */
verifyMustOverride(Class<?> expType, Object instance, String method)303     public static void verifyMustOverride(Class<?> expType, Object instance,
304             String method)
305     {
306         if (instance.getClass() != expType) {
307             throw new IllegalStateException(String.format(
308                     "Sub-class %s (of class %s) must override method '%s'",
309                 instance.getClass().getName(), expType.getName(), method));
310         }
311     }
312 
313     /*
314     /**********************************************************
315     /* Method type detection methods
316     /**********************************************************
317      */
318 
319     /**
320      * @deprecated Since 2.6 not used; may be removed before 3.x
321      */
322     @Deprecated // since 2.6
hasGetterSignature(Method m)323     public static boolean hasGetterSignature(Method m)
324     {
325         // First: static methods can't be getters
326         if (Modifier.isStatic(m.getModifiers())) {
327             return false;
328         }
329         // Must take no args
330         Class<?>[] pts = m.getParameterTypes();
331         if (pts != null && pts.length != 0) {
332             return false;
333         }
334         // Can't be a void method
335         if (Void.TYPE == m.getReturnType()) {
336             return false;
337         }
338         // Otherwise looks ok:
339         return true;
340     }
341 
342     /*
343     /**********************************************************
344     /* Exception handling; simple re-throw
345     /**********************************************************
346      */
347 
348     /**
349      * Helper method that will check if argument is an {@link Error},
350      * and if so, (re)throw it; otherwise just return
351      *
352      * @since 2.9
353      */
throwIfError(Throwable t)354     public static Throwable throwIfError(Throwable t) {
355         if (t instanceof Error) {
356             throw (Error) t;
357         }
358         return t;
359     }
360 
361     /**
362      * Helper method that will check if argument is an {@link RuntimeException},
363      * and if so, (re)throw it; otherwise just return
364      *
365      * @since 2.9
366      */
throwIfRTE(Throwable t)367     public static Throwable throwIfRTE(Throwable t) {
368         if (t instanceof RuntimeException) {
369             throw (RuntimeException) t;
370         }
371         return t;
372     }
373 
374     /**
375      * Helper method that will check if argument is an {@link IOException},
376      * and if so, (re)throw it; otherwise just return
377      *
378      * @since 2.9
379      */
throwIfIOE(Throwable t)380     public static Throwable throwIfIOE(Throwable t) throws IOException {
381         if (t instanceof IOException) {
382             throw (IOException) t;
383         }
384         return t;
385     }
386 
387     /*
388     /**********************************************************
389     /* Exception handling; other
390     /**********************************************************
391      */
392 
393     /**
394      * Method that can be used to find the "root cause", innermost
395      * of chained (wrapped) exceptions.
396      */
getRootCause(Throwable t)397     public static Throwable getRootCause(Throwable t)
398     {
399         while (t.getCause() != null) {
400             t = t.getCause();
401         }
402         return t;
403     }
404 
405     /**
406      * Method that works like by calling {@link #getRootCause} and then
407      * either throwing it (if instanceof {@link IOException}), or
408      * return.
409      *
410      * @since 2.8
411      */
throwRootCauseIfIOE(Throwable t)412     public static Throwable throwRootCauseIfIOE(Throwable t) throws IOException {
413         return throwIfIOE(getRootCause(t));
414     }
415 
416     /**
417      * Method that will wrap 't' as an {@link IllegalArgumentException} if it
418      * is a checked exception; otherwise (runtime exception or error) throw as is
419      */
throwAsIAE(Throwable t)420     public static void throwAsIAE(Throwable t) {
421         throwAsIAE(t, t.getMessage());
422     }
423 
424     /**
425      * Method that will wrap 't' as an {@link IllegalArgumentException} (and with
426      * specified message) if it
427      * is a checked exception; otherwise (runtime exception or error) throw as is
428      */
throwAsIAE(Throwable t, String msg)429     public static void throwAsIAE(Throwable t, String msg)
430     {
431         throwIfRTE(t);
432         throwIfError(t);
433         throw new IllegalArgumentException(msg, t);
434     }
435 
436     /**
437      * @since 2.9
438      */
throwAsMappingException(DeserializationContext ctxt, IOException e0)439     public static <T> T throwAsMappingException(DeserializationContext ctxt,
440             IOException e0) throws JsonMappingException {
441         if (e0 instanceof JsonMappingException) {
442             throw (JsonMappingException) e0;
443         }
444         JsonMappingException e = JsonMappingException.from(ctxt, e0.getMessage());
445         e.initCause(e0);
446         throw e;
447     }
448 
449     /**
450      * Method that will locate the innermost exception for given Throwable;
451      * and then wrap it as an {@link IllegalArgumentException} if it
452      * is a checked exception; otherwise (runtime exception or error) throw as is
453      */
unwrapAndThrowAsIAE(Throwable t)454     public static void unwrapAndThrowAsIAE(Throwable t)
455     {
456         throwAsIAE(getRootCause(t));
457     }
458 
459     /**
460      * Method that will locate the innermost exception for given Throwable;
461      * and then wrap it as an {@link IllegalArgumentException} if it
462      * is a checked exception; otherwise (runtime exception or error) throw as is
463      */
unwrapAndThrowAsIAE(Throwable t, String msg)464     public static void unwrapAndThrowAsIAE(Throwable t, String msg)
465     {
466         throwAsIAE(getRootCause(t), msg);
467     }
468 
469     /**
470      * Helper method that encapsulate logic in trying to close output generator
471      * in case of failure; useful mostly in forcing flush()ing as otherwise
472      * error conditions tend to be hard to diagnose. However, it is often the
473      * case that output state may be corrupt so we need to be prepared for
474      * secondary exception without masking original one.
475      *
476      * @since 2.8
477      */
closeOnFailAndThrowAsIOE(JsonGenerator g, Exception fail)478     public static void closeOnFailAndThrowAsIOE(JsonGenerator g, Exception fail)
479         throws IOException
480     {
481         /* 04-Mar-2014, tatu: Let's try to prevent auto-closing of
482          *    structures, which typically causes more damage.
483          */
484         g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
485         try {
486             g.close();
487         } catch (Exception e) {
488             fail.addSuppressed(e);
489         }
490         throwIfIOE(fail);
491         throwIfRTE(fail);
492         throw new RuntimeException(fail);
493     }
494 
495     /**
496      * Helper method that encapsulate logic in trying to close given {@link Closeable}
497      * in case of failure; useful mostly in forcing flush()ing as otherwise
498      * error conditions tend to be hard to diagnose. However, it is often the
499      * case that output state may be corrupt so we need to be prepared for
500      * secondary exception without masking original one.
501      *
502      * @since 2.8
503      */
closeOnFailAndThrowAsIOE(JsonGenerator g, Closeable toClose, Exception fail)504     public static void closeOnFailAndThrowAsIOE(JsonGenerator g,
505             Closeable toClose, Exception fail)
506         throws IOException
507     {
508         if (g != null) {
509             g.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
510             try {
511                 g.close();
512             } catch (Exception e) {
513                 fail.addSuppressed(e);
514             }
515         }
516         if (toClose != null) {
517             try {
518                 toClose.close();
519             } catch (Exception e) {
520                 fail.addSuppressed(e);
521             }
522         }
523         throwIfIOE(fail);
524         throwIfRTE(fail);
525         throw new RuntimeException(fail);
526     }
527 
528     /*
529     /**********************************************************
530     /* Instantiation
531     /**********************************************************
532      */
533 
534     /**
535      * Method that can be called to try to create an instantiate of
536      * specified type. Instantiation is done using default no-argument
537      * constructor.
538      *
539      * @param canFixAccess Whether it is possible to try to change access
540      *   rights of the default constructor (in case it is not publicly
541      *   accessible) or not.
542      *
543      * @throws IllegalArgumentException If instantiation fails for any reason;
544      *    except for cases where constructor throws an unchecked exception
545      *    (which will be passed as is)
546      */
createInstance(Class<T> cls, boolean canFixAccess)547     public static <T> T createInstance(Class<T> cls, boolean canFixAccess)
548         throws IllegalArgumentException
549     {
550         Constructor<T> ctor = findConstructor(cls, canFixAccess);
551         if (ctor == null) {
552             throw new IllegalArgumentException("Class "+cls.getName()+" has no default (no arg) constructor");
553         }
554         try {
555             return ctor.newInstance();
556         } catch (Exception e) {
557             ClassUtil.unwrapAndThrowAsIAE(e, "Failed to instantiate class "+cls.getName()+", problem: "+e.getMessage());
558             return null;
559         }
560     }
561 
findConstructor(Class<T> cls, boolean forceAccess)562     public static <T> Constructor<T> findConstructor(Class<T> cls, boolean forceAccess)
563         throws IllegalArgumentException
564     {
565         try {
566             Constructor<T> ctor = cls.getDeclaredConstructor();
567             if (forceAccess) {
568                 checkAndFixAccess(ctor, forceAccess);
569             } else {
570                 // Has to be public...
571                 if (!Modifier.isPublic(ctor.getModifiers())) {
572                     throw new IllegalArgumentException("Default constructor for "+cls.getName()+" is not accessible (non-public?): not allowed to try modify access via Reflection: cannot instantiate type");
573                 }
574             }
575             return ctor;
576         } catch (NoSuchMethodException e) {
577             ;
578         } catch (Exception e) {
579             ClassUtil.unwrapAndThrowAsIAE(e, "Failed to find default constructor of class "+cls.getName()+", problem: "+e.getMessage());
580         }
581         return null;
582     }
583 
584     /*
585     /**********************************************************
586     /* Class name, description access
587     /**********************************************************
588      */
589 
590     /**
591      * @since 2.9
592      */
classOf(Object inst)593     public static Class<?> classOf(Object inst) {
594         if (inst == null) {
595             return null;
596         }
597         return inst.getClass();
598     }
599 
600     /**
601      * @since 2.9
602      */
rawClass(JavaType t)603     public static Class<?> rawClass(JavaType t) {
604         if (t == null) {
605             return null;
606         }
607         return t.getRawClass();
608     }
609 
610     /**
611      * @since 2.9
612      */
nonNull(T valueOrNull, T defaultValue)613     public static <T> T nonNull(T valueOrNull, T defaultValue) {
614         return (valueOrNull == null) ? defaultValue : valueOrNull;
615     }
616 
617     /**
618      * @since 2.9
619      */
nullOrToString(Object value)620     public static String nullOrToString(Object value) {
621         if (value == null) {
622             return null;
623         }
624         return value.toString();
625     }
626 
627     /**
628      * @since 2.9
629      */
nonNullString(String str)630     public static String nonNullString(String str) {
631         if (str == null) {
632             return "";
633         }
634         return str;
635     }
636 
637     /**
638      * Returns either quoted value (with double-quotes) -- if argument non-null
639      * String -- or String NULL (no quotes) (if null).
640      *
641      * @since 2.9
642      */
quotedOr(Object str, String forNull)643     public static String quotedOr(Object str, String forNull) {
644         if (str == null) {
645             return forNull;
646         }
647         return String.format("\"%s\"", str);
648     }
649 
650     /*
651     /**********************************************************
652     /* Type name, name, desc handling methods
653     /**********************************************************
654      */
655 
656     /**
657      * Helper method used to construct appropriate description
658      * when passed either type (Class) or an instance; in latter
659      * case, class of instance is to be used.
660      */
getClassDescription(Object classOrInstance)661     public static String getClassDescription(Object classOrInstance)
662     {
663         if (classOrInstance == null) {
664             return "unknown";
665         }
666         Class<?> cls = (classOrInstance instanceof Class<?>) ?
667             (Class<?>) classOrInstance : classOrInstance.getClass();
668         return nameOf(cls);
669     }
670 
671     /**
672      * Helper method to create and return "backticked" description of given
673      * resolved type (or, {@code "null"} if {@code null} passed), similar
674      * to return vaue of {@link #getClassDescription(Object)}.
675      *
676      * @param fullType Fully resolved type or null
677      * @return String description of type including generic type parameters, surrounded
678      *   by backticks, if type passed; or string "null" if {code null} passed
679      *
680      * @since 2.10
681      */
getTypeDescription(JavaType fullType)682     public static String getTypeDescription(JavaType fullType)
683     {
684         if (fullType == null) {
685             return "[null]";
686         }
687         StringBuilder sb = new StringBuilder(80).append('`');
688         sb.append(fullType.toCanonical());
689         return sb.append('`').toString();
690     }
691 
692     /**
693      * Helper method used to construct appropriate description
694      * when passed either type (Class) or an instance; in latter
695      * case, class of instance is to be used.
696      *
697      * @since 2.9
698      */
classNameOf(Object inst)699     public static String classNameOf(Object inst) {
700         if (inst == null) {
701             return "[null]";
702         }
703         Class<?> raw = (inst instanceof Class<?>) ? (Class<?>) inst : inst.getClass();
704         return nameOf(raw);
705     }
706 
707     /**
708      * Returns either `cls.getName()` (if `cls` not null),
709      * or "[null]" if `cls` is null.
710      *
711      * @since 2.9
712      */
nameOf(Class<?> cls)713     public static String nameOf(Class<?> cls) {
714         if (cls == null) {
715             return "[null]";
716         }
717         int index = 0;
718         while (cls.isArray()) {
719             ++index;
720             cls = cls.getComponentType();
721         }
722         String base = cls.isPrimitive() ? cls.getSimpleName() : cls.getName();
723         if (index > 0) {
724             StringBuilder sb = new StringBuilder(base);
725             do {
726                 sb.append("[]");
727             } while (--index > 0);
728             base = sb.toString();
729         }
730         return backticked(base);
731     }
732 
733     /**
734      * Returns either backtick-quoted `named.getName()` (if `named` not null),
735      * or "[null]" if `named` is null.
736      *
737      * @since 2.9
738      */
nameOf(Named named)739     public static String nameOf(Named named) {
740         if (named == null) {
741             return "[null]";
742         }
743         return backticked(named.getName());
744     }
745 
746     /*
747     /**********************************************************
748     /* Other escaping, description access
749     /**********************************************************
750      */
751 
752     /**
753      * Returns either `text` or [null].
754      *
755      * @since 2.9
756      */
backticked(String text)757     public static String backticked(String text) {
758         if (text == null) {
759             return "[null]";
760         }
761         return new StringBuilder(text.length()+2).append('`').append(text).append('`').toString();
762     }
763 
764     /**
765      * Helper method that returns {@link Throwable#getMessage()} for all other exceptions
766      * except for {@link JsonProcessingException}, for which {@code getOriginalMessage()} is
767      * returned instead.
768      * Method is used to avoid accidentally including trailing location information twice
769      * in message when wrapping exceptions.
770      *
771      * @since 2.9.7
772      */
exceptionMessage(Throwable t)773     public static String exceptionMessage(Throwable t) {
774         if (t instanceof JsonProcessingException) {
775             return ((JsonProcessingException) t).getOriginalMessage();
776         }
777         return t.getMessage();
778     }
779 
780     /*
781     /**********************************************************
782     /* Primitive type support
783     /**********************************************************
784      */
785 
786     /**
787      * Helper method used to get default value for wrappers used for primitive types
788      * (0 for Integer etc)
789      */
defaultValue(Class<?> cls)790     public static Object defaultValue(Class<?> cls)
791     {
792         if (cls == Integer.TYPE) {
793             return Integer.valueOf(0);
794         }
795         if (cls == Long.TYPE) {
796             return Long.valueOf(0L);
797         }
798         if (cls == Boolean.TYPE) {
799             return Boolean.FALSE;
800         }
801         if (cls == Double.TYPE) {
802             return Double.valueOf(0.0);
803         }
804         if (cls == Float.TYPE) {
805             return Float.valueOf(0.0f);
806         }
807         if (cls == Byte.TYPE) {
808             return Byte.valueOf((byte) 0);
809         }
810         if (cls == Short.TYPE) {
811             return Short.valueOf((short) 0);
812         }
813         if (cls == Character.TYPE) {
814             return '\0';
815         }
816         throw new IllegalArgumentException("Class "+cls.getName()+" is not a primitive type");
817     }
818 
819     /**
820      * Helper method for finding wrapper type for given primitive type (why isn't
821      * there one in JDK?)
822      */
wrapperType(Class<?> primitiveType)823     public static Class<?> wrapperType(Class<?> primitiveType)
824     {
825         if (primitiveType == Integer.TYPE) {
826             return Integer.class;
827         }
828         if (primitiveType == Long.TYPE) {
829             return Long.class;
830         }
831         if (primitiveType == Boolean.TYPE) {
832             return Boolean.class;
833         }
834         if (primitiveType == Double.TYPE) {
835             return Double.class;
836         }
837         if (primitiveType == Float.TYPE) {
838             return Float.class;
839         }
840         if (primitiveType == Byte.TYPE) {
841             return Byte.class;
842         }
843         if (primitiveType == Short.TYPE) {
844             return Short.class;
845         }
846         if (primitiveType == Character.TYPE) {
847             return Character.class;
848         }
849         throw new IllegalArgumentException("Class "+primitiveType.getName()+" is not a primitive type");
850     }
851 
852     /**
853      * Method that can be used to find primitive type for given class if (but only if)
854      * it is either wrapper type or primitive type; returns `null` if type is neither.
855      *
856      * @since 2.7
857      */
primitiveType(Class<?> type)858     public static Class<?> primitiveType(Class<?> type)
859     {
860         if (type.isPrimitive()) {
861             return type;
862         }
863 
864         if (type == Integer.class) {
865             return Integer.TYPE;
866         }
867         if (type == Long.class) {
868             return Long.TYPE;
869         }
870         if (type == Boolean.class) {
871             return Boolean.TYPE;
872         }
873         if (type == Double.class) {
874             return Double.TYPE;
875         }
876         if (type == Float.class) {
877             return Float.TYPE;
878         }
879         if (type == Byte.class) {
880             return Byte.TYPE;
881         }
882         if (type == Short.class) {
883             return Short.TYPE;
884         }
885         if (type == Character.class) {
886             return Character.TYPE;
887         }
888         return null;
889     }
890 
891     /*
892     /**********************************************************
893     /* Access checking/handling methods
894     /**********************************************************
895      */
896 
897     /**
898      * Equivalent to call:
899      *<pre>
900      *   checkAndFixAccess(member, false);
901      *</pre>
902      *
903      * @deprecated Since 2.7 call variant that takes boolean flag.
904      */
905     @Deprecated
checkAndFixAccess(Member member)906     public static void checkAndFixAccess(Member member) {
907         checkAndFixAccess(member, false);
908     }
909 
910     /**
911      * Method that is called if a {@link Member} may need forced access,
912      * to force a field, method or constructor to be accessible: this
913      * is done by calling {@link AccessibleObject#setAccessible(boolean)}.
914      *
915      * @param member Accessor to call <code>setAccessible()</code> on.
916      * @param force Whether to always try to make accessor accessible (true),
917      *   or only if needed as per access rights (false)
918      *
919      * @since 2.7
920      */
checkAndFixAccess(Member member, boolean force)921     public static void checkAndFixAccess(Member member, boolean force)
922     {
923         // We know all members are also accessible objects...
924         AccessibleObject ao = (AccessibleObject) member;
925 
926         /* 14-Jan-2009, tatu: It seems safe and potentially beneficial to
927          *   always to make it accessible (latter because it will force
928          *   skipping checks we have no use for...), so let's always call it.
929          */
930         try {
931             if (force ||
932                     (!Modifier.isPublic(member.getModifiers())
933                             || !Modifier.isPublic(member.getDeclaringClass().getModifiers()))) {
934                 ao.setAccessible(true);
935             }
936         } catch (SecurityException se) {
937             // 17-Apr-2009, tatu: Related to [JACKSON-101]: this can fail on platforms like
938             // Google App Engine); so let's only fail if we really needed it...
939             if (!ao.isAccessible()) {
940                 Class<?> declClass = member.getDeclaringClass();
941                 throw new IllegalArgumentException("Cannot access "+member+" (from class "+declClass.getName()+"; failed to set access: "+se.getMessage());
942             }
943         }
944     }
945 
946     /*
947     /**********************************************************
948     /* Enum type detection
949     /**********************************************************
950      */
951 
952     /**
953      * Helper method that encapsulates reliable check on whether
954      * given raw type "is an Enum", that is, is or extends {@link java.lang.Enum}.
955      *
956      * @since 2.10.1
957      */
isEnumType(Class<?> rawType)958     public static boolean isEnumType(Class<?> rawType) {
959         return Enum.class.isAssignableFrom(rawType);
960     }
961 
962     /**
963      * Helper method that can be used to dynamically figure out
964      * enumeration type of given {@link EnumSet}, without having
965      * access to its declaration.
966      * Code is needed to work around design flaw in JDK.
967      */
findEnumType(EnumSet<?> s)968     public static Class<? extends Enum<?>> findEnumType(EnumSet<?> s)
969     {
970         // First things first: if not empty, easy to determine
971         if (!s.isEmpty()) {
972             return findEnumType(s.iterator().next());
973         }
974         // Otherwise need to locate using an internal field
975         return EnumTypeLocator.instance.enumTypeFor(s);
976     }
977 
978     /**
979      * Helper method that can be used to dynamically figure out
980      * enumeration type of given {@link EnumSet}, without having
981      * access to its declaration.
982      * Code is needed to work around design flaw in JDK.
983      */
findEnumType(EnumMap<?,?> m)984     public static Class<? extends Enum<?>> findEnumType(EnumMap<?,?> m)
985     {
986         if (!m.isEmpty()) {
987             return findEnumType(m.keySet().iterator().next());
988         }
989         // Otherwise need to locate using an internal field
990         return EnumTypeLocator.instance.enumTypeFor(m);
991     }
992 
993     /**
994      * Helper method that can be used to dynamically figure out formal
995      * enumeration type (class) for given enumeration. This is either
996      * class of enum instance (for "simple" enumerations), or its
997      * superclass (for enums with instance fields or methods)
998      */
999     @SuppressWarnings("unchecked")
findEnumType(Enum<?> en)1000     public static Class<? extends Enum<?>> findEnumType(Enum<?> en)
1001     {
1002         // enums with "body" are sub-classes of the formal type
1003     	Class<?> ec = en.getClass();
1004     	if (ec.getSuperclass() != Enum.class) {
1005     	    ec = ec.getSuperclass();
1006     	}
1007     	return (Class<? extends Enum<?>>) ec;
1008     }
1009 
1010     /**
1011      * Helper method that can be used to dynamically figure out formal
1012      * enumeration type (class) for given class of an enumeration value.
1013      * This is either class of enum instance (for "simple" enumerations),
1014      * or its superclass (for enums with instance fields or methods)
1015      */
1016     @SuppressWarnings("unchecked")
findEnumType(Class<?> cls)1017     public static Class<? extends Enum<?>> findEnumType(Class<?> cls)
1018     {
1019         // enums with "body" are sub-classes of the formal type
1020         if (cls.getSuperclass() != Enum.class) {
1021             cls = cls.getSuperclass();
1022         }
1023         return (Class<? extends Enum<?>>) cls;
1024     }
1025 
1026     /**
1027      * A method that will look for the first Enum value annotated with the given Annotation.
1028      * <p>
1029      * If there's more than one value annotated, the first one found will be returned. Which one exactly is used is undetermined.
1030      *
1031      * @param enumClass The Enum class to scan for a value with the given annotation
1032      * @param annotationClass The annotation to look for.
1033      * @return the Enum value annotated with the given Annotation or {@code null} if none is found.
1034      * @throws IllegalArgumentException if there's a reflection issue accessing the Enum
1035      * @since 2.8
1036      */
findFirstAnnotatedEnumValue(Class<Enum<?>> enumClass, Class<T> annotationClass)1037     public static <T extends Annotation> Enum<?> findFirstAnnotatedEnumValue(Class<Enum<?>> enumClass, Class<T> annotationClass)
1038     {
1039         Field[] fields = enumClass.getDeclaredFields();
1040         for (Field field : fields) {
1041             if (field.isEnumConstant()) {
1042                 Annotation defaultValueAnnotation = field.getAnnotation(annotationClass);
1043                 if (defaultValueAnnotation != null) {
1044                     final String name = field.getName();
1045                     for (Enum<?> enumValue : enumClass.getEnumConstants()) {
1046                         if (name.equals(enumValue.name())) {
1047                             return enumValue;
1048                         }
1049                     }
1050                 }
1051             }
1052         }
1053         return null;
1054     }
1055 
1056     /*
1057     /**********************************************************************
1058     /* Methods for detecting special class categories
1059     /**********************************************************************
1060      */
1061 
1062     /**
1063      * Method that can be called to determine if given Object is the default
1064      * implementation Jackson uses; as opposed to a custom serializer installed by
1065      * a module or calling application. Determination is done using
1066      * {@link JacksonStdImpl} annotation on handler (serializer, deserializer etc)
1067      * class.
1068      *<p>
1069      * NOTE: passing `null` is legal, and will result in <code>true</code>
1070      * being returned.
1071      */
isJacksonStdImpl(Object impl)1072     public static boolean isJacksonStdImpl(Object impl) {
1073         return (impl == null) || isJacksonStdImpl(impl.getClass());
1074     }
1075 
isJacksonStdImpl(Class<?> implClass)1076     public static boolean isJacksonStdImpl(Class<?> implClass) {
1077         return (implClass.getAnnotation(JacksonStdImpl.class) != null);
1078     }
1079 
1080     /**
1081      * Some aspects of handling need to be changed for JDK types (and possibly
1082      * some extensions under {@code javax.}?): for example, forcing of access
1083      * will not work well for future JDKs (12 and later).
1084      *
1085      * @since 2.11
1086      */
isJDKClass(Class<?> rawType)1087     public static boolean isJDKClass(Class<?> rawType) {
1088         return rawType.getName().startsWith("java.");
1089     }
1090 
1091     /*
1092     /**********************************************************
1093     /* Access to various Class definition aspects; possibly
1094     /* cacheable; and attempts was made in 2.7.0 - 2.7.7; however
1095     /* unintented retention (~= memory leak) wrt [databind#1363]
1096     /* resulted in removal of caching
1097     /**********************************************************
1098      */
1099 
isNonStaticInnerClass(Class<?> cls)1100     public static boolean isNonStaticInnerClass(Class<?> cls) {
1101         return !Modifier.isStatic(cls.getModifiers())
1102                 && (getEnclosingClass(cls) != null);
1103     }
1104 
1105     /**
1106      * @since 2.7
1107      */
getPackageName(Class<?> cls)1108     public static String getPackageName(Class<?> cls) {
1109         Package pkg = cls.getPackage();
1110         return (pkg == null) ? null : pkg.getName();
1111     }
1112 
1113     /**
1114      * @since 2.7
1115      */
hasEnclosingMethod(Class<?> cls)1116     public static boolean hasEnclosingMethod(Class<?> cls) {
1117         return !isObjectOrPrimitive(cls) && (cls.getEnclosingMethod() != null);
1118     }
1119 
1120     /**
1121      * @deprecated since 2.11 (just call Class method directly)
1122      */
1123     @Deprecated
getDeclaredFields(Class<?> cls)1124     public static Field[] getDeclaredFields(Class<?> cls) {
1125         return cls.getDeclaredFields();
1126     }
1127 
1128     /**
1129      * @deprecated since 2.11 (just call Class method directly)
1130      */
1131     @Deprecated
getDeclaredMethods(Class<?> cls)1132     public static Method[] getDeclaredMethods(Class<?> cls) {
1133         return cls.getDeclaredMethods();
1134     }
1135 
1136     /**
1137      * @since 2.7
1138      */
findClassAnnotations(Class<?> cls)1139     public static Annotation[] findClassAnnotations(Class<?> cls) {
1140         if (isObjectOrPrimitive(cls)) {
1141             return NO_ANNOTATIONS;
1142         }
1143         return cls.getDeclaredAnnotations();
1144     }
1145 
1146     /**
1147      * Helper method that gets methods declared in given class; usually a simple thing,
1148      * but sometimes (as per [databind#785]) more complicated, depending on classloader
1149      * setup.
1150      *
1151      * @since 2.9
1152      */
getClassMethods(Class<?> cls)1153     public static Method[] getClassMethods(Class<?> cls)
1154     {
1155         try {
1156             return cls.getDeclaredMethods();
1157         } catch (final NoClassDefFoundError ex) {
1158             // One of the methods had a class that was not found in the cls.getClassLoader.
1159             // Maybe the developer was nice and has a different class loader for this context.
1160             final ClassLoader loader = Thread.currentThread().getContextClassLoader();
1161             if (loader == null){
1162                 // Nope... this is going to end poorly
1163                 throw ex;
1164             }
1165             final Class<?> contextClass;
1166             try {
1167                 contextClass = loader.loadClass(cls.getName());
1168             } catch (ClassNotFoundException e) {
1169                 ex.addSuppressed(e);
1170                 throw ex;
1171             }
1172             return contextClass.getDeclaredMethods(); // Cross fingers
1173         }
1174     }
1175 
1176     /**
1177      * @since 2.7
1178      */
getConstructors(Class<?> cls)1179     public static Ctor[] getConstructors(Class<?> cls) {
1180         // Note: can NOT skip abstract classes as they may be used with mix-ins
1181         // and for regular use shouldn't really matter.
1182         if (cls.isInterface() || isObjectOrPrimitive(cls)) {
1183             return NO_CTORS;
1184         }
1185         Constructor<?>[] rawCtors = cls.getDeclaredConstructors();
1186         final int len = rawCtors.length;
1187         Ctor[] result = new Ctor[len];
1188         for (int i = 0; i < len; ++i) {
1189             result[i] = new Ctor(rawCtors[i]);
1190         }
1191         return result;
1192     }
1193 
1194     // // // Then methods that do NOT cache access but were considered
1195     // // // (and could be added to do caching if it was proven effective)
1196 
1197     /**
1198      * @since 2.7
1199      */
getDeclaringClass(Class<?> cls)1200     public static Class<?> getDeclaringClass(Class<?> cls) {
1201         return isObjectOrPrimitive(cls) ? null : cls.getDeclaringClass();
1202     }
1203 
1204     /**
1205      * @since 2.7
1206      */
getGenericSuperclass(Class<?> cls)1207     public static Type getGenericSuperclass(Class<?> cls) {
1208         return cls.getGenericSuperclass();
1209     }
1210 
1211     /**
1212      * @since 2.7
1213      */
getGenericInterfaces(Class<?> cls)1214     public static Type[] getGenericInterfaces(Class<?> cls) {
1215         return cls.getGenericInterfaces();
1216     }
1217 
1218     /**
1219      * @since 2.7
1220      */
getEnclosingClass(Class<?> cls)1221     public static Class<?> getEnclosingClass(Class<?> cls) {
1222         // Caching does not seem worthwhile, as per profiling
1223         return isObjectOrPrimitive(cls) ? null : cls.getEnclosingClass();
1224     }
1225 
_interfaces(Class<?> cls)1226     private static Class<?>[] _interfaces(Class<?> cls) {
1227         return cls.getInterfaces();
1228     }
1229 
1230     /*
1231     /**********************************************************
1232     /* Helper classes
1233     /**********************************************************
1234      */
1235 
1236     /**
1237      * Inner class used to contain gory details of how we can determine
1238      * details of instances of common JDK types like {@link EnumMap}s.
1239      */
1240     private static class EnumTypeLocator
1241     {
1242         final static EnumTypeLocator instance = new EnumTypeLocator();
1243 
1244         private final Field enumSetTypeField;
1245         private final Field enumMapTypeField;
1246 
EnumTypeLocator()1247         private EnumTypeLocator() {
1248             //JDK uses following fields to store information about actual Enumeration
1249             // type for EnumSets, EnumMaps...
1250     	        enumSetTypeField = locateField(EnumSet.class, "elementType", Class.class);
1251     	        enumMapTypeField = locateField(EnumMap.class, "elementType", Class.class);
1252         }
1253 
1254         @SuppressWarnings("unchecked")
enumTypeFor(EnumSet<?> set)1255         public Class<? extends Enum<?>> enumTypeFor(EnumSet<?> set)
1256         {
1257             if (enumSetTypeField != null) {
1258                 return (Class<? extends Enum<?>>) get(set, enumSetTypeField);
1259             }
1260             throw new IllegalStateException("Cannot figure out type for EnumSet (odd JDK platform?)");
1261         }
1262 
1263         @SuppressWarnings("unchecked")
enumTypeFor(EnumMap<?,?> set)1264         public Class<? extends Enum<?>> enumTypeFor(EnumMap<?,?> set)
1265         {
1266             if (enumMapTypeField != null) {
1267                 return (Class<? extends Enum<?>>) get(set, enumMapTypeField);
1268             }
1269             throw new IllegalStateException("Cannot figure out type for EnumMap (odd JDK platform?)");
1270         }
1271 
get(Object bean, Field field)1272         private Object get(Object bean, Field field)
1273         {
1274             try {
1275                 return field.get(bean);
1276             } catch (Exception e) {
1277                 throw new IllegalArgumentException(e);
1278             }
1279         }
1280 
locateField(Class<?> fromClass, String expectedName, Class<?> type)1281         private static Field locateField(Class<?> fromClass, String expectedName, Class<?> type)
1282         {
1283             Field found = null;
1284     	        // First: let's see if we can find exact match:
1285             Field[] fields = fromClass.getDeclaredFields();
1286     	        for (Field f : fields) {
1287     	            if (expectedName.equals(f.getName()) && f.getType() == type) {
1288     	                found = f;
1289     	                break;
1290     	            }
1291     	        }
1292     	        // And if not, if there is just one field with the type, that field
1293     	        if (found == null) {
1294     	            for (Field f : fields) {
1295     	                if (f.getType() == type) {
1296     	                    // If more than one, can't choose
1297     	                    if (found != null) return null;
1298     	                    found = f;
1299     	                }
1300     	            }
1301     	        }
1302     	        if (found != null) { // it's non-public, need to force accessible
1303     	            try {
1304     	                found.setAccessible(true);
1305     	            } catch (Throwable t) { }
1306     	        }
1307     	        return found;
1308         }
1309     }
1310 
1311     /*
1312     /**********************************************************
1313     /* Helper classed used for caching
1314     /**********************************************************
1315      */
1316 
1317     /**
1318      * Value class used for caching Constructor declarations; used because
1319      * caching done by JDK appears to be somewhat inefficient for some use cases.
1320      *
1321      * @since 2.7
1322      */
1323     public final static class Ctor
1324     {
1325         public final Constructor<?> _ctor;
1326 
1327         private transient Annotation[] _annotations;
1328 
1329         private transient Annotation[][] _paramAnnotations;
1330 
1331         private int _paramCount = -1;
1332 
Ctor(Constructor<?> ctor)1333         public Ctor(Constructor<?> ctor) {
1334             _ctor = ctor;
1335         }
1336 
getConstructor()1337         public Constructor<?> getConstructor() {
1338             return _ctor;
1339         }
1340 
getParamCount()1341         public int getParamCount() {
1342             int c = _paramCount;
1343             if (c < 0) {
1344                 c = _ctor.getParameterTypes().length;
1345                 _paramCount = c;
1346             }
1347             return c;
1348         }
1349 
getDeclaringClass()1350         public Class<?> getDeclaringClass() {
1351             return _ctor.getDeclaringClass();
1352         }
1353 
getDeclaredAnnotations()1354         public Annotation[] getDeclaredAnnotations() {
1355             Annotation[] result = _annotations;
1356             if (result == null) {
1357                 result = _ctor.getDeclaredAnnotations();
1358                 _annotations = result;
1359             }
1360             return result;
1361         }
1362 
getParameterAnnotations()1363         public  Annotation[][] getParameterAnnotations() {
1364             Annotation[][] result = _paramAnnotations;
1365             if (result == null) {
1366                 result = _ctor.getParameterAnnotations();
1367                 _paramAnnotations = result;
1368             }
1369             return result;
1370         }
1371     }
1372 }
1373