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