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")
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 */
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 */
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 */
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
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
114 public static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore, List<Class<?>> result) {
115 _addRawSuperTypes(cls, endBefore, result, false);
116 return result;
117 }
118
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
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 */
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
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 */
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 */
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 */
259 public static boolean isConcrete(Class<?> type)
260 {
261 int mod = type.getModifiers();
262 return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0;
263 }
264
265 public static boolean isConcrete(Member member)
266 {
267 int mod = member.getModifiers();
268 return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0;
269 }
270
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
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 */
287 public static boolean isObjectOrPrimitive(Class<?> cls) {
288 return (cls == CLS_OBJECT) || cls.isPrimitive();
289 }
290
291 /**
292 * @since 2.9
293 */
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 */
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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 */
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 */
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 */
613 public static <T> T nonNull(T valueOrNull, T defaultValue) {
614 return (valueOrNull == null) ? defaultValue : valueOrNull;
615 }
616
617 /**
618 * @since 2.9
619 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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 */
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 */
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 */
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 */
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")
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")
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 */
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 */
1072 public static boolean isJacksonStdImpl(Object impl) {
1073 return (impl == null) || isJacksonStdImpl(impl.getClass());
1074 }
1075
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 */
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
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 */
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 */
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
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
1132 public static Method[] getDeclaredMethods(Class<?> cls) {
1133 return cls.getDeclaredMethods();
1134 }
1135
1136 /**
1137 * @since 2.7
1138 */
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 */
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 */
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 */
1200 public static Class<?> getDeclaringClass(Class<?> cls) {
1201 return isObjectOrPrimitive(cls) ? null : cls.getDeclaringClass();
1202 }
1203
1204 /**
1205 * @since 2.7
1206 */
1207 public static Type getGenericSuperclass(Class<?> cls) {
1208 return cls.getGenericSuperclass();
1209 }
1210
1211 /**
1212 * @since 2.7
1213 */
1214 public static Type[] getGenericInterfaces(Class<?> cls) {
1215 return cls.getGenericInterfaces();
1216 }
1217
1218 /**
1219 * @since 2.7
1220 */
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
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
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")
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")
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
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
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
1333 public Ctor(Constructor<?> ctor) {
1334 _ctor = ctor;
1335 }
1336
1337 public Constructor<?> getConstructor() {
1338 return _ctor;
1339 }
1340
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
1350 public Class<?> getDeclaringClass() {
1351 return _ctor.getDeclaringClass();
1352 }
1353
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
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