001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.internal; 014 015import static org.apache.juneau.internal.ClassFlags.*; 016import static org.apache.juneau.internal.CollectionUtils.*; 017 018import java.io.*; 019import java.lang.annotation.*; 020import java.lang.reflect.*; 021import java.util.*; 022import java.util.concurrent.*; 023 024import org.apache.juneau.*; 025import org.apache.juneau.utils.*; 026 027/** 028 * Class-related utility methods. 029 */ 030public final class ClassUtils { 031 032 private static final Map<Class<?>,ConstructorCacheEntry> CONSTRUCTOR_CACHE = new ConcurrentHashMap<>(); 033 034 /** 035 * Given the specified list of objects, return readable names for the class types of the objects. 036 * 037 * @param o The objects. 038 * @return An array of readable class type strings. 039 */ 040 public static ObjectList getReadableClassNames(Object[] o) { 041 ObjectList l = new ObjectList(); 042 for (int i = 0; i < o.length; i++) 043 l.add(o[i] == null ? "null" : getReadableClassName(o[i].getClass())); 044 return l; 045 } 046 047 /** 048 * Shortcut for calling <code><jsm>getReadableClassName</jsm>(c.getName())</code> 049 * 050 * @param c The class. 051 * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>. 052 */ 053 public static String getReadableClassName(Class<?> c) { 054 if (c == null) 055 return null; 056 return getReadableClassName(c.getName()); 057 } 058 059 /** 060 * Shortcut for calling <code><jsm>getReadableClassName</jsm>(c.getClass().getName())</code> 061 * 062 * @param o The object whose class we want to render. 063 * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>. 064 */ 065 public static String getReadableClassNameForObject(Object o) { 066 if (o == null) 067 return null; 068 return getReadableClassName(o.getClass().getName()); 069 } 070 071 /** 072 * Converts the specified class name to a readable form when class name is a special construct like <js>"[[Z"</js>. 073 * 074 * <h5 class='section'>Example:</h5> 075 * <p class='bcode w800'> 076 * <jsm>getReadableClassName</jsm>(<js>"java.lang.Object"</js>); <jc>// Returns "java.lang.Object"</jc> 077 * <jsm>getReadableClassName</jsm>(<js>"boolean"</js>); <jc>// Returns "boolean"</jc> 078 * <jsm>getReadableClassName</jsm>(<js>"[Z"</js>); <jc>// Returns "boolean[]"</jc> 079 * <jsm>getReadableClassName</jsm>(<js>"[[Z"</js>); <jc>// Returns "boolean[][]"</jc> 080 * <jsm>getReadableClassName</jsm>(<js>"[Ljava.lang.Object;"</js>); <jc>// Returns "java.lang.Object[]"</jc> 081 * <jsm>getReadableClassName</jsm>(<jk>null</jk>); <jc>// Returns null</jc> 082 * </p> 083 * 084 * @param className The class name. 085 * @return A readable class type name, or <jk>null</jk> if parameter is <jk>null</jk>. 086 */ 087 public static String getReadableClassName(String className) { 088 if (className == null) 089 return null; 090 if (! StringUtils.startsWith(className, '[')) 091 return className; 092 int depth = 0; 093 for (int i = 0; i < className.length(); i++) { 094 if (className.charAt(i) == '[') 095 depth++; 096 else 097 break; 098 } 099 char type = className.charAt(depth); 100 String c; 101 switch (type) { 102 case 'Z': c = "boolean"; break; 103 case 'B': c = "byte"; break; 104 case 'C': c = "char"; break; 105 case 'D': c = "double"; break; 106 case 'F': c = "float"; break; 107 case 'I': c = "int"; break; 108 case 'J': c = "long"; break; 109 case 'S': c = "short"; break; 110 default: c = className.substring(depth+1, className.length()-1); 111 } 112 StringBuilder sb = new StringBuilder(c.length() + 2*depth).append(c); 113 for (int i = 0; i < depth; i++) 114 sb.append("[]"); 115 return sb.toString(); 116 } 117 118 /** 119 * Converts the string generated by {@link #getReadableClassName(Class)} back into a {@link Class}. 120 * 121 * <p> 122 * Generics are stripped from the string since they cannot be converted to a class. 123 * 124 * @param cl The classloader to use to load the class. 125 * @param name The readable class name. 126 * @return The class object. 127 * @throws ClassNotFoundException 128 */ 129 public static Class<?> getClassFromReadableName(ClassLoader cl, String name) throws ClassNotFoundException { 130 return cl.loadClass(name); 131 } 132 133 /** 134 * Returns <jk>true</jk> if <code>parent</code> is a parent class of <code>child</code>. 135 * 136 * @param parent The parent class. 137 * @param child The child class. 138 * @param strict If <jk>true</jk> returns <jk>false</jk> if the classes are the same. 139 * @return <jk>true</jk> if <code>parent</code> is a parent class of <code>child</code>. 140 */ 141 public static boolean isParentClass(Class<?> parent, Class<?> child, boolean strict) { 142 return parent.isAssignableFrom(child) && ((!strict) || ! parent.equals(child)); 143 } 144 145 /** 146 * Returns <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>. 147 * 148 * @param parent The parent class. 149 * @param child The child class. 150 * @return <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>. 151 */ 152 public static boolean isParentClass(Class<?> parent, Class<?> child) { 153 return isParentClass(parent, child, false); 154 } 155 156 /** 157 * Returns <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>. 158 * 159 * @param parent The parent class. 160 * @param child The child class. 161 * @return <jk>true</jk> if <code>parent</code> is a parent class or the same as <code>child</code>. 162 */ 163 public static boolean isParentClass(Class<?> parent, Type child) { 164 if (child instanceof Class) 165 return isParentClass(parent, (Class<?>)child); 166 return false; 167 } 168 169 /** 170 * Returns the signature of the specified method. 171 * 172 * <p> 173 * For no-arg methods, the signature will be a simple string such as <js>"toString"</js>. 174 * For methods with one or more args, the arguments will be fully-qualified class names (e.g. 175 * <js>"append(java.util.StringBuilder,boolean)"</js>) 176 * 177 * @param m The methods to get the signature on. 178 * @return The methods signature. 179 */ 180 public static String getMethodSignature(Method m) { 181 StringBuilder sb = new StringBuilder(m.getName()); 182 Class<?>[] pt = m.getParameterTypes(); 183 if (pt.length > 0) { 184 sb.append('('); 185 for (int i = 0; i < pt.length; i++) { 186 if (i > 0) 187 sb.append(','); 188 sb.append(getReadableClassName(pt[i])); 189 } 190 sb.append(')'); 191 } 192 return sb.toString(); 193 } 194 195 private static final Map<Class<?>, Class<?>> 196 pmap1 = new HashMap<>(), 197 pmap2 = new HashMap<>(); 198 static { 199 pmap1.put(boolean.class, Boolean.class); 200 pmap1.put(byte.class, Byte.class); 201 pmap1.put(short.class, Short.class); 202 pmap1.put(char.class, Character.class); 203 pmap1.put(int.class, Integer.class); 204 pmap1.put(long.class, Long.class); 205 pmap1.put(float.class, Float.class); 206 pmap1.put(double.class, Double.class); 207 pmap2.put(Boolean.class, boolean.class); 208 pmap2.put(Byte.class, byte.class); 209 pmap2.put(Short.class, short.class); 210 pmap2.put(Character.class, char.class); 211 pmap2.put(Integer.class, int.class); 212 pmap2.put(Long.class, long.class); 213 pmap2.put(Float.class, float.class); 214 pmap2.put(Double.class, double.class); 215 } 216 217 /** 218 * Returns <jk>true</jk> if the {@link #getPrimitiveWrapper(Class)} class returns a value for the specified class. 219 * 220 * @param c The class. 221 * @return <jk>true</jk> if the {@link #getPrimitiveWrapper(Class)} class returns a value for the specified class. 222 */ 223 public static boolean hasPrimitiveWrapper(Class<?> c) { 224 return pmap1.containsKey(c); 225 } 226 227 /** 228 * If the specified class is a primitive (e.g. <code><jk>int</jk>.<jk>class</jk></code>) returns it's wrapper class 229 * (e.g. <code>Integer.<jk>class</jk></code>). 230 * 231 * @param c The class. 232 * @return The wrapper class, or <jk>null</jk> if class is not a primitive. 233 */ 234 public static Class<?> getPrimitiveWrapper(Class<?> c) { 235 return pmap1.get(c); 236 } 237 238 /** 239 * If the specified class is a primitive wrapper (e.g. <code><jk>Integer</jk>.<jk>class</jk></code>) returns it's 240 * primitive class (e.g. <code>int.<jk>class</jk></code>). 241 * 242 * @param c The class. 243 * @return The primitive class, or <jk>null</jk> if class is not a primitive wrapper. 244 */ 245 public static Class<?> getPrimitiveForWrapper(Class<?> c) { 246 return pmap2.get(c); 247 } 248 249 /** 250 * If the specified class is a primitive (e.g. <code><jk>int</jk>.<jk>class</jk></code>) returns it's wrapper class 251 * (e.g. <code>Integer.<jk>class</jk></code>). 252 * 253 * @param c The class. 254 * @return The wrapper class if it's primitive, or the same class if class is not a primitive. 255 */ 256 public static Class<?> getWrapperIfPrimitive(Class<?> c) { 257 if (! c.isPrimitive()) 258 return c; 259 return pmap1.get(c); 260 } 261 262 /** 263 * Returns <jk>true</jk> if all specified flags are applicable to the specified class. 264 * 265 * @param x The class to test. 266 * @param flags The flags to test for. 267 * @return <jk>true</jk> if all specified flags are applicable to the specified class. 268 */ 269 public static boolean isAll(Class<?> x, ClassFlags...flags) { 270 for (ClassFlags f : flags) { 271 switch (f) { 272 case DEPRECATED: 273 if (isNotDeprecated(x)) 274 return false; 275 break; 276 case NOT_DEPRECATED: 277 if (isDeprecated(x)) 278 return false; 279 break; 280 case PUBLIC: 281 if (isNotPublic(x)) 282 return false; 283 break; 284 case NOT_PUBLIC: 285 if (isPublic(x)) 286 return false; 287 break; 288 case STATIC: 289 if (isNotStatic(x)) 290 return false; 291 break; 292 case NOT_STATIC: 293 if (isStatic(x)) 294 return false; 295 break; 296 case ABSTRACT: 297 if (isNotAbstract(x)) 298 return false; 299 break; 300 case NOT_ABSTRACT: 301 if (isAbstract(x)) 302 return false; 303 break; 304 case HAS_ARGS: 305 case HAS_NO_ARGS: 306 case TRANSIENT: 307 case NOT_TRANSIENT: 308 default: 309 break; 310 311 } 312 } 313 return true; 314 } 315 316 /** 317 * Returns <jk>true</jk> if all specified flags are applicable to the specified method. 318 * 319 * @param x The method to test. 320 * @param flags The flags to test for. 321 * @return <jk>true</jk> if all specified flags are applicable to the specified method. 322 */ 323 public static boolean isAll(Method x, ClassFlags...flags) { 324 for (ClassFlags f : flags) { 325 switch (f) { 326 case DEPRECATED: 327 if (isNotDeprecated(x)) 328 return false; 329 break; 330 case NOT_DEPRECATED: 331 if (isDeprecated(x)) 332 return false; 333 break; 334 case HAS_ARGS: 335 if (hasNoArgs(x)) 336 return false; 337 break; 338 case HAS_NO_ARGS: 339 if (hasArgs(x)) 340 return false; 341 break; 342 case PUBLIC: 343 if (isNotPublic(x)) 344 return false; 345 break; 346 case NOT_PUBLIC: 347 if (isPublic(x)) 348 return false; 349 break; 350 case STATIC: 351 if (isNotStatic(x)) 352 return false; 353 break; 354 case NOT_STATIC: 355 if (isStatic(x)) 356 return false; 357 break; 358 case ABSTRACT: 359 if (isNotAbstract(x)) 360 return false; 361 break; 362 case NOT_ABSTRACT: 363 if (isAbstract(x)) 364 return false; 365 break; 366 case TRANSIENT: 367 case NOT_TRANSIENT: 368 default: 369 break; 370 371 } 372 } 373 return true; 374 } 375 376 /** 377 * Returns <jk>true</jk> if all specified flags are applicable to the specified constructor. 378 * 379 * @param x The constructor to test. 380 * @param flags The flags to test for. 381 * @return <jk>true</jk> if all specified flags are applicable to the specified constructor. 382 */ 383 public static boolean isAll(Constructor<?> x, ClassFlags...flags) { 384 for (ClassFlags f : flags) { 385 switch (f) { 386 case DEPRECATED: 387 if (isNotDeprecated(x)) 388 return false; 389 break; 390 case NOT_DEPRECATED: 391 if (isDeprecated(x)) 392 return false; 393 break; 394 case HAS_ARGS: 395 if (hasNoArgs(x)) 396 return false; 397 break; 398 case HAS_NO_ARGS: 399 if (hasArgs(x)) 400 return false; 401 break; 402 case PUBLIC: 403 if (isNotPublic(x)) 404 return false; 405 break; 406 case NOT_PUBLIC: 407 if (isPublic(x)) 408 return false; 409 break; 410 case STATIC: 411 case NOT_STATIC: 412 case ABSTRACT: 413 case NOT_ABSTRACT: 414 case TRANSIENT: 415 case NOT_TRANSIENT: 416 default: 417 break; 418 419 } 420 } 421 return true; 422 } 423 424 /** 425 * Returns <jk>true</jk> if all specified flags are applicable to the specified field. 426 * 427 * @param x The field to test. 428 * @param flags The flags to test for. 429 * @return <jk>true</jk> if all specified flags are applicable to the specified field. 430 */ 431 public static boolean isAll(Field x, ClassFlags...flags) { 432 for (ClassFlags f : flags) { 433 switch (f) { 434 case DEPRECATED: 435 if (isNotDeprecated(x)) 436 return false; 437 break; 438 case NOT_DEPRECATED: 439 if (isDeprecated(x)) 440 return false; 441 break; 442 case HAS_ARGS: 443 break; 444 case HAS_NO_ARGS: 445 break; 446 case PUBLIC: 447 if (isNotPublic(x)) 448 return false; 449 break; 450 case NOT_PUBLIC: 451 if (isPublic(x)) 452 return false; 453 break; 454 case STATIC: 455 if (isNotStatic(x)) 456 return false; 457 break; 458 case NOT_STATIC: 459 if (isStatic(x)) 460 return false; 461 break; 462 case TRANSIENT: 463 if (isNotTransient(x)) 464 return false; 465 break; 466 case NOT_TRANSIENT: 467 if (isTransient(x)) 468 return false; 469 break; 470 case ABSTRACT: 471 case NOT_ABSTRACT: 472 default: 473 break; 474 475 } 476 } 477 return true; 478 } 479 480 /** 481 * Returns <jk>true</jk> if all specified flags are applicable to the specified class. 482 * 483 * @param x The class to test. 484 * @param flags The flags to test for. 485 * @return <jk>true</jk> if all specified flags are applicable to the specified class. 486 */ 487 public static boolean isAny(Class<?> x, ClassFlags...flags) { 488 for (ClassFlags f : flags) { 489 switch (f) { 490 case DEPRECATED: 491 if (isDeprecated(x)) 492 return true; 493 break; 494 case NOT_DEPRECATED: 495 if (isNotDeprecated(x)) 496 return true; 497 break; 498 case PUBLIC: 499 if (isPublic(x)) 500 return true; 501 break; 502 case NOT_PUBLIC: 503 if (isNotPublic(x)) 504 return true; 505 break; 506 case STATIC: 507 if (isStatic(x)) 508 return true; 509 break; 510 case NOT_STATIC: 511 if (isNotStatic(x)) 512 return true; 513 break; 514 case ABSTRACT: 515 if (isAbstract(x)) 516 return true; 517 break; 518 case NOT_ABSTRACT: 519 if (isNotAbstract(x)) 520 return true; 521 break; 522 case TRANSIENT: 523 case NOT_TRANSIENT: 524 case HAS_ARGS: 525 case HAS_NO_ARGS: 526 default: 527 break; 528 529 } 530 } 531 return false; 532 } 533 534 /** 535 * Returns <jk>true</jk> if all specified flags are applicable to the specified method. 536 * 537 * @param x The method to test. 538 * @param flags The flags to test for. 539 * @return <jk>true</jk> if all specified flags are applicable to the specified method. 540 */ 541 public static boolean isAny(Method x, ClassFlags...flags) { 542 for (ClassFlags f : flags) { 543 switch (f) { 544 case DEPRECATED: 545 if (isDeprecated(x)) 546 return true; 547 break; 548 case NOT_DEPRECATED: 549 if (isNotDeprecated(x)) 550 return true; 551 break; 552 case HAS_ARGS: 553 if (hasArgs(x)) 554 return true; 555 break; 556 case HAS_NO_ARGS: 557 if (hasNoArgs(x)) 558 return true; 559 break; 560 case PUBLIC: 561 if (isPublic(x)) 562 return true; 563 break; 564 case NOT_PUBLIC: 565 if (isNotPublic(x)) 566 return true; 567 break; 568 case STATIC: 569 if (isStatic(x)) 570 return true; 571 break; 572 case NOT_STATIC: 573 if (isNotStatic(x)) 574 return true; 575 break; 576 case ABSTRACT: 577 if (isAbstract(x)) 578 return true; 579 break; 580 case NOT_ABSTRACT: 581 if (isNotAbstract(x)) 582 return true; 583 break; 584 case TRANSIENT: 585 case NOT_TRANSIENT: 586 default: 587 break; 588 589 } 590 } 591 return false; 592 } 593 594 /** 595 * Returns <jk>true</jk> if all specified flags are applicable to the specified constructor. 596 * 597 * @param x The constructor to test. 598 * @param flags The flags to test for. 599 * @return <jk>true</jk> if all specified flags are applicable to the specified constructor. 600 */ 601 public static boolean isAny(Constructor<?> x, ClassFlags...flags) { 602 for (ClassFlags f : flags) { 603 switch (f) { 604 case DEPRECATED: 605 if (isDeprecated(x)) 606 return true; 607 break; 608 case NOT_DEPRECATED: 609 if (isNotDeprecated(x)) 610 return true; 611 break; 612 case HAS_ARGS: 613 if (hasArgs(x)) 614 return true; 615 break; 616 case HAS_NO_ARGS: 617 if (hasNoArgs(x)) 618 return true; 619 break; 620 case PUBLIC: 621 if (isPublic(x)) 622 return true; 623 break; 624 case NOT_PUBLIC: 625 if (isNotPublic(x)) 626 return true; 627 break; 628 case STATIC: 629 case NOT_STATIC: 630 case ABSTRACT: 631 case NOT_ABSTRACT: 632 case TRANSIENT: 633 case NOT_TRANSIENT: 634 default: 635 break; 636 637 } 638 } 639 return false; 640 } 641 642 /** 643 * Returns <jk>true</jk> if all specified flags are applicable to the specified field. 644 * 645 * @param x The field to test. 646 * @param flags The flags to test for. 647 * @return <jk>true</jk> if all specified flags are applicable to the specified field. 648 */ 649 public static boolean isAny(Field x, ClassFlags...flags) { 650 for (ClassFlags f : flags) { 651 switch (f) { 652 case DEPRECATED: 653 if (isDeprecated(x)) 654 return true; 655 break; 656 case NOT_DEPRECATED: 657 if (isNotDeprecated(x)) 658 return true; 659 break; 660 case PUBLIC: 661 if (isPublic(x)) 662 return true; 663 break; 664 case NOT_PUBLIC: 665 if (isNotPublic(x)) 666 return true; 667 break; 668 case STATIC: 669 if (isStatic(x)) 670 return true; 671 break; 672 case NOT_STATIC: 673 if (isNotStatic(x)) 674 return true; 675 break; 676 case TRANSIENT: 677 if (isTransient(x)) 678 return true; 679 break; 680 case NOT_TRANSIENT: 681 if (isNotTransient(x)) 682 return true; 683 break; 684 case HAS_ARGS: 685 case HAS_NO_ARGS: 686 case ABSTRACT: 687 case NOT_ABSTRACT: 688 default: 689 break; 690 691 } 692 } 693 return false; 694 } 695 696 /** 697 * Returns <jk>true</jk> if the specified method has the specified arguments. 698 * 699 * @param x The method to test. 700 * @param args The arguments to test for. 701 * @return <jk>true</jk> if the specified method has the specified arguments in the exact order. 702 */ 703 public static boolean hasArgs(Method x, Class<?>...args) { 704 Class<?>[] pt = x.getParameterTypes(); 705 if (pt.length == args.length) { 706 for (int i = 0; i < pt.length; i++) 707 if (! pt[i].equals(args[i])) 708 return false; 709 return true; 710 } 711 return false; 712 } 713 714 /** 715 * Returns <jk>true</jk> if the specified constructor has the specified arguments. 716 * 717 * @param x The constructor to test. 718 * @param args The arguments to test for. 719 * @return <jk>true</jk> if the specified constructor has the specified arguments in the exact order. 720 */ 721 public static boolean hasArgs(Constructor<?> x, Class<?>...args) { 722 Class<?>[] pt = x.getParameterTypes(); 723 if (pt.length == args.length) { 724 for (int i = 0; i < pt.length; i++) 725 if (! pt[i].equals(args[i])) 726 return false; 727 return true; 728 } 729 return false; 730 } 731 732 /** 733 * Returns <jk>true</jk> if the specified constructor has one or more arguments. 734 * 735 * @param x The method to test. 736 * @return <jk>true</jk> if the specified constructor has one or more arguments. 737 */ 738 public static boolean hasArgs(Constructor<?> x) { 739 return x.getParameterTypes().length > 0; 740 } 741 742 /** 743 * Returns <jk>true</jk> if the specified constructor has zero arguments. 744 * 745 * @param x The method to test. 746 * @return <jk>true</jk> if the specified constructor has zero arguments. 747 */ 748 public static boolean hasNoArgs(Constructor<?> x) { 749 return x.getParameterTypes().length == 0; 750 } 751 752 /** 753 * Returns <jk>true</jk> if the specified constructor has the specified number of arguments. 754 * 755 * @param x The method to test. 756 * @param number The number of expected arguments. 757 * @return <jk>true</jk> if the specified method has the specified number of arguments. 758 */ 759 public static boolean hasNumArgs(Method x, int number) { 760 return x.getParameterTypes().length == number; 761 } 762 763 /** 764 * Returns <jk>true</jk> if the specified constructor has the specified number of arguments. 765 * 766 * @param x The constructor to test. 767 * @param number The number of expected arguments. 768 * @return <jk>true</jk> if the specified constructor has the specified number of arguments. 769 */ 770 public static boolean hasNumArgs(Constructor<?> x, int number) { 771 return x.getParameterTypes().length == number; 772 } 773 774 /** 775 * Returns <jk>true</jk> if the specified method has at most only the specified arguments in any order. 776 * 777 * @param x The method to test. 778 * @param args The arguments to test for. 779 * @return <jk>true</jk> if the specified method has at most only the specified arguments in any order. 780 */ 781 public static boolean hasFuzzyArgs(Method x, Class<?>...args) { 782 return fuzzyArgsMatch(x.getParameterTypes(), args) != -1; 783 } 784 785 /** 786 * Returns <jk>true</jk> if the specified constructor has at most only the specified arguments in any order. 787 * 788 * @param x The constructor to test. 789 * @param args The arguments to test for. 790 * @return <jk>true</jk> if the specified constructor has at most only the specified arguments in any order. 791 */ 792 public static boolean hasFuzzyArgs(Constructor<?> x, Class<?>...args) { 793 return fuzzyArgsMatch(x.getParameterTypes(), args) != -1; 794 } 795 796 /** 797 * Returns <jk>true</jk> if the specified class has the {@link Deprecated @Deprecated} annotation on it. 798 * 799 * @param c The class. 800 * @return <jk>true</jk> if the specified class has the {@link Deprecated @Deprecated} annotation on it. 801 */ 802 public static boolean isDeprecated(Class<?> c) { 803 return c.isAnnotationPresent(Deprecated.class); 804 } 805 806 /** 807 * Returns <jk>true</jk> if the specified method has the {@link Deprecated @Deprecated} annotation on it. 808 * 809 * @param m The method. 810 * @return <jk>true</jk> if the specified method has the {@link Deprecated @Deprecated} annotation on it. 811 */ 812 public static boolean isDeprecated(Method m) { 813 return m.isAnnotationPresent(Deprecated.class); 814 815 } 816 817 /** 818 * Returns <jk>true</jk> if the specified constructor has the {@link Deprecated @Deprecated} annotation on it. 819 * 820 * @param c The constructor. 821 * @return <jk>true</jk> if the specified constructor has the {@link Deprecated @Deprecated} annotation on it. 822 */ 823 public static boolean isDeprecated(Constructor<?> c) { 824 return c.isAnnotationPresent(Deprecated.class); 825 } 826 827 /** 828 * Returns <jk>true</jk> if the specified field has the {@link Deprecated @Deprecated} annotation on it. 829 * 830 * @param f The field. 831 * @return <jk>true</jk> if the specified field has the {@link Deprecated @Deprecated} annotation on it. 832 */ 833 public static boolean isDeprecated(Field f) { 834 return f.isAnnotationPresent(Deprecated.class); 835 } 836 837 /** 838 * Returns <jk>true</jk> if the specified class doesn't have the {@link Deprecated @Deprecated} annotation on it. 839 * 840 * @param c The class. 841 * @return <jk>true</jk> if the specified class doesn't have the {@link Deprecated @Deprecated} annotation on it. 842 */ 843 public static boolean isNotDeprecated(Class<?> c) { 844 return ! c.isAnnotationPresent(Deprecated.class); 845 } 846 847 /** 848 * Returns <jk>true</jk> if the specified method doesn't have the {@link Deprecated @Deprecated} annotation on it. 849 * 850 * @param m The method. 851 * @return <jk>true</jk> if the specified method doesn't have the {@link Deprecated @Deprecated} annotation on it. 852 */ 853 public static boolean isNotDeprecated(Method m) { 854 return ! m.isAnnotationPresent(Deprecated.class); 855 856 } 857 858 /** 859 * Returns <jk>true</jk> if the specified constructor doesn't have the {@link Deprecated @Deprecated} annotation on it. 860 * 861 * @param c The constructor. 862 * @return <jk>true</jk> if the specified constructor doesn't have the {@link Deprecated @Deprecated} annotation on it. 863 */ 864 public static boolean isNotDeprecated(Constructor<?> c) { 865 return ! c.isAnnotationPresent(Deprecated.class); 866 } 867 868 /** 869 * Returns <jk>true</jk> if the specified field doesn't have the {@link Deprecated @Deprecated} annotation on it. 870 * 871 * @param f The field. 872 * @return <jk>true</jk> if the specified field doesn't have the {@link Deprecated @Deprecated} annotation on it. 873 */ 874 public static boolean isNotDeprecated(Field f) { 875 return ! f.isAnnotationPresent(Deprecated.class); 876 } 877 878 /** 879 * Returns <jk>true</jk> if the specified class is public. 880 * 881 * @param c The class. 882 * @return <jk>true</jk> if the specified class is public. 883 */ 884 public static boolean isPublic(Class<?> c) { 885 return Modifier.isPublic(c.getModifiers()); 886 } 887 888 /** 889 * Returns <jk>true</jk> if the specified class is not public. 890 * 891 * @param c The class. 892 * @return <jk>true</jk> if the specified class is not public. 893 */ 894 public static boolean isNotPublic(Class<?> c) { 895 return ! Modifier.isPublic(c.getModifiers()); 896 } 897 898 /** 899 * Returns <jk>true</jk> if the specified class is public. 900 * 901 * @param c The class. 902 * @return <jk>true</jk> if the specified class is public. 903 */ 904 public static boolean isStatic(Class<?> c) { 905 return Modifier.isStatic(c.getModifiers()); 906 } 907 908 /** 909 * Returns <jk>true</jk> if the specified class is not static. 910 * 911 * @param c The class. 912 * @return <jk>true</jk> if the specified class is not static. 913 */ 914 public static boolean isNotStatic(Class<?> c) { 915 return ! Modifier.isStatic(c.getModifiers()); 916 } 917 918 /** 919 * Returns <jk>true</jk> if the specified class is abstract. 920 * 921 * @param c The class. 922 * @return <jk>true</jk> if the specified class is abstract. 923 */ 924 public static boolean isAbstract(Class<?> c) { 925 return Modifier.isAbstract(c.getModifiers()); 926 } 927 928 /** 929 * Returns <jk>true</jk> if the specified class is not abstract. 930 * 931 * @param c The class. 932 * @return <jk>true</jk> if the specified class is not abstract. 933 */ 934 public static boolean isNotAbstract(Class<?> c) { 935 return ! Modifier.isAbstract(c.getModifiers()); 936 } 937 938 /** 939 * Returns <jk>true</jk> if the specified method is abstract. 940 * 941 * @param m The method. 942 * @return <jk>true</jk> if the specified method is abstract. 943 */ 944 public static boolean isAbstract(Method m) { 945 return Modifier.isAbstract(m.getModifiers()); 946 } 947 948 /** 949 * Returns <jk>true</jk> if the specified method is not abstract. 950 * 951 * @param m The method. 952 * @return <jk>true</jk> if the specified method is not abstract. 953 */ 954 public static boolean isNotAbstract(Method m) { 955 return ! Modifier.isAbstract(m.getModifiers()); 956 } 957 958 /** 959 * Returns <jk>true</jk> if the specified method is public. 960 * 961 * @param m The method. 962 * @return <jk>true</jk> if the specified method is public. 963 */ 964 public static boolean isPublic(Method m) { 965 return Modifier.isPublic(m.getModifiers()); 966 } 967 968 /** 969 * Returns <jk>true</jk> if the specified method is not public. 970 * 971 * @param m The method. 972 * @return <jk>true</jk> if the specified method is not public. 973 */ 974 public static boolean isNotPublic(Method m) { 975 return ! Modifier.isPublic(m.getModifiers()); 976 } 977 978 /** 979 * Returns <jk>true</jk> if the specified field is public. 980 * 981 * @param f The field. 982 * @return <jk>true</jk> if the specified field is public. 983 */ 984 public static boolean isPublic(Field f) { 985 return Modifier.isPublic(f.getModifiers()); 986 } 987 988 /** 989 * Returns <jk>true</jk> if the specified field is not public. 990 * 991 * @param f The field. 992 * @return <jk>true</jk> if the specified field is not public. 993 */ 994 public static boolean isNotPublic(Field f) { 995 return ! Modifier.isPublic(f.getModifiers()); 996 } 997 998 /** 999 * Returns <jk>true</jk> if the specified method is static. 1000 * 1001 * @param m The method. 1002 * @return <jk>true</jk> if the specified method is static. 1003 */ 1004 public static boolean isStatic(Method m) { 1005 return Modifier.isStatic(m.getModifiers()); 1006 } 1007 1008 /** 1009 * Returns <jk>true</jk> if the specified method is not static. 1010 * 1011 * @param m The method. 1012 * @return <jk>true</jk> if the specified method is not static. 1013 */ 1014 public static boolean isNotStatic(Method m) { 1015 return ! Modifier.isStatic(m.getModifiers()); 1016 } 1017 1018 /** 1019 * Returns <jk>true</jk> if the specified field is static. 1020 * 1021 * @param f The field. 1022 * @return <jk>true</jk> if the specified field is static. 1023 */ 1024 public static boolean isStatic(Field f) { 1025 return Modifier.isStatic(f.getModifiers()); 1026 } 1027 1028 /** 1029 * Returns <jk>true</jk> if the specified field is not static. 1030 * 1031 * @param f The field. 1032 * @return <jk>true</jk> if the specified field is not static. 1033 */ 1034 public static boolean isNotStatic(Field f) { 1035 return ! Modifier.isStatic(f.getModifiers()); 1036 } 1037 1038 /** 1039 * Returns <jk>true</jk> if the specified constructor is public. 1040 * 1041 * @param c The constructor. 1042 * @return <jk>true</jk> if the specified constructor is public. 1043 */ 1044 public static boolean isPublic(Constructor<?> c) { 1045 return Modifier.isPublic(c.getModifiers()); 1046 } 1047 1048 /** 1049 * Returns <jk>true</jk> if the specified constructor is not public. 1050 * 1051 * @param c The constructor. 1052 * @return <jk>true</jk> if the specified constructor is not public. 1053 */ 1054 public static boolean isNotPublic(Constructor<?> c) { 1055 return ! Modifier.isPublic(c.getModifiers()); 1056 } 1057 1058 /** 1059 * Returns <jk>true</jk> if the specified field is transient. 1060 * 1061 * @param f The field. 1062 * @return <jk>true</jk> if the specified field is transient. 1063 */ 1064 public static boolean isTransient(Field f) { 1065 return Modifier.isTransient(f.getModifiers()); 1066 } 1067 1068 /** 1069 * Returns <jk>true</jk> if the specified field is not transient. 1070 * 1071 * @param f The field. 1072 * @return <jk>true</jk> if the specified field is not transient. 1073 */ 1074 public static boolean isNotTransient(Field f) { 1075 return ! Modifier.isTransient(f.getModifiers()); 1076 } 1077 1078 /** 1079 * Returns <jk>true</jk> if the specified method has one or more arguments. 1080 * 1081 * @param x The method to test. 1082 * @return <jk>true</jk> if the specified method has one or more arguments. 1083 */ 1084 public static boolean hasArgs(Method x) { 1085 return x.getParameterTypes().length > 0; 1086 } 1087 1088 /** 1089 * Returns <jk>true</jk> if the specified method has zero arguments. 1090 * 1091 * @param x The method to test. 1092 * @return <jk>true</jk> if the specified method has zero arguments. 1093 */ 1094 public static boolean hasNoArgs(Method x) { 1095 return x.getParameterTypes().length == 0; 1096 } 1097 1098 /** 1099 * Returns <jk>true</jk> if the specified method has the specified name. 1100 * 1101 * @param m The method to test. 1102 * @param name The name to test for. 1103 * @return <jk>true</jk> if the specified method has the specified name. 1104 */ 1105 public static boolean hasName(Method m, String name) { 1106 return m.getName().equals(name); 1107 } 1108 1109 /** 1110 * Returns <jk>true</jk> if the specified method has the specified return type. 1111 * 1112 * @param m The method to test. 1113 * @param c The return type to test for. 1114 * @return <jk>true</jk> if the specified method has the specified return type. 1115 */ 1116 public static boolean hasReturnType(Method m, Class<?> c) { 1117 return m.getReturnType() == c; 1118 } 1119 1120 /** 1121 * Returns <jk>true</jk> if the specified method has the specified parent return type. 1122 * 1123 * @param m The method to test. 1124 * @param c The return type to test for. 1125 * @return <jk>true</jk> if the specified method has the specified parent return type. 1126 */ 1127 public static boolean hasReturnTypeParent(Method m, Class<?> c) { 1128 return isParentClass(c, m.getReturnType()); 1129 } 1130 1131 /** 1132 * Returns the specified annotation on the specified method. 1133 * 1134 * <p> 1135 * Similar to {@link Method#getAnnotation(Class)}, but searches up the parent hierarchy for the annotation 1136 * defined on parent classes and interfaces. 1137 * 1138 * <p> 1139 * Normally, annotations defined on methods of parent classes and interfaces are not inherited by the child methods. 1140 * This utility method gets around that limitation by searching the class hierarchy for the "same" method 1141 * (i.e. the same name and arguments). 1142 * 1143 * @param a The annotation to search for. 1144 * @param m The method to search. 1145 * @return The annotation, or <jk>null</jk> if it wasn't found. 1146 */ 1147 public static <T extends Annotation> T getMethodAnnotation(Class<T> a, Method m) { 1148 return getMethodAnnotation(a, m.getDeclaringClass(), m); 1149 } 1150 1151 /** 1152 * Returns the specified annotation on the specified method. 1153 * 1154 * <p> 1155 * Similar to {@link Method#getAnnotation(Class)}, but searches up the parent hierarchy for the annotation defined 1156 * on parent classes and interfaces. 1157 * 1158 * <p> 1159 * Normally, annotations defined on methods of parent classes and interfaces are not inherited by the child methods. 1160 * This utility method gets around that limitation by searching the class hierarchy for the "same" method 1161 * (i.e. the same name and arguments). 1162 * 1163 * @param a The annotation to search for. 1164 * @param c 1165 * The child class to start searching from. 1166 * Note that it can be a descendant class of the actual declaring class of the method passed in. 1167 * This allows you to find annotations on methods overridden by the method passed in. 1168 * @param method The method to search. 1169 * @return The annotation, or <jk>null</jk> if it wasn't found. 1170 */ 1171 public static <T extends Annotation> T getMethodAnnotation(Class<T> a, Class<?> c, Method method) { 1172 for (Method m : c.getDeclaredMethods()) { 1173 if (isSameMethod(method, m)) { 1174 T t = m.getAnnotation(a); 1175 if (t != null) 1176 return t; 1177 } 1178 } 1179 Class<?> pc = c.getSuperclass(); 1180 if (pc != null) { 1181 T t = getMethodAnnotation(a, pc, method); 1182 if (t != null) 1183 return t; 1184 } 1185 for (Class<?> ic : c.getInterfaces()) { 1186 T t = getMethodAnnotation(a, ic, method); 1187 if (t != null) 1188 return t; 1189 } 1190 return null; 1191 } 1192 1193 /** 1194 * Given a specific method, finds all declared methods with the same name and arguments on all 1195 * superclasses and interfaces. 1196 * 1197 * @param m The method to find matches against. 1198 * @return All matching methods including the input method itself. 1199 */ 1200 public static List<Method> findMatchingMethods(Method m) { 1201 return findMatchingMethods(new ArrayList<Method>(), m); 1202 } 1203 1204 private static List<Method> findMatchingMethods(List<Method> l, Method m) { 1205 l.add(m); 1206 Class<?> c = m.getDeclaringClass(); 1207 Class<?> pc = c.getSuperclass(); 1208 if (pc != null) 1209 for (Method m2 : pc.getDeclaredMethods()) 1210 if (isSameMethod(m, m2)) 1211 findMatchingMethods(l, m2); 1212 for (Class<?> ic : c.getInterfaces()) 1213 for (Method m2 : ic.getDeclaredMethods()) 1214 if (isSameMethod(m, m2)) 1215 findMatchingMethods(l, m2); 1216 return l; 1217 } 1218 1219 private static boolean isSameMethod(Method m1, Method m2) { 1220 return m1.getName().equals(m2.getName()) && Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes()); 1221 } 1222 1223 /** 1224 * Locates the no-arg constructor for the specified class. 1225 * 1226 * <p> 1227 * Constructor must match the visibility requirements specified by parameter 'v'. 1228 * If class is abstract, always returns <jk>null</jk>. 1229 * Note that this also returns the 1-arg constructor for non-static member classes. 1230 * 1231 * @param c The class from which to locate the no-arg constructor. 1232 * @param v The minimum visibility. 1233 * @return The constructor, or <jk>null</jk> if no no-arg constructor exists with the required visibility. 1234 */ 1235 @SuppressWarnings({"rawtypes","unchecked"}) 1236 public static final <T> Constructor<T> findNoArgConstructor(Class<T> c, Visibility v) { 1237 int mod = c.getModifiers(); 1238 if (Modifier.isAbstract(mod)) 1239 return null; 1240 boolean isMemberClass = c.isMemberClass() && ! isStatic(c); 1241 for (Constructor cc : c.getConstructors()) { 1242 mod = cc.getModifiers(); 1243 if (hasNumArgs(cc, isMemberClass ? 1 : 0) && v.isVisible(mod) && isNotDeprecated(cc)) 1244 return v.transform(cc); 1245 } 1246 return null; 1247 } 1248 1249 /** 1250 * Finds the real parameter type of the specified class. 1251 * 1252 * @param c The class containing the parameters (e.g. PojoSwap<T,S>) 1253 * @param index The zero-based index of the parameter to resolve. 1254 * @param oc The class we're trying to resolve the parameter type for. 1255 * @return The resolved real class. 1256 */ 1257 public static Class<?> resolveParameterType(Class<?> c, int index, Class<?> oc) { 1258 1259 // We need to make up a mapping of type names. 1260 Map<Type,Type> typeMap = new HashMap<>(); 1261 while (c != oc.getSuperclass()) { 1262 extractTypes(typeMap, oc); 1263 oc = oc.getSuperclass(); 1264 } 1265 1266 Type gsc = oc.getGenericSuperclass(); 1267 1268 // Not actually a parameterized type. 1269 if (! (gsc instanceof ParameterizedType)) 1270 return Object.class; 1271 1272 ParameterizedType opt = (ParameterizedType)gsc; 1273 Type actualType = opt.getActualTypeArguments()[index]; 1274 1275 if (typeMap.containsKey(actualType)) 1276 actualType = typeMap.get(actualType); 1277 1278 if (actualType instanceof Class) { 1279 return (Class<?>)actualType; 1280 1281 } else if (actualType instanceof GenericArrayType) { 1282 Class<?> cmpntType = (Class<?>)((GenericArrayType)actualType).getGenericComponentType(); 1283 return Array.newInstance(cmpntType, 0).getClass(); 1284 1285 } else if (actualType instanceof TypeVariable) { 1286 TypeVariable<?> typeVariable = (TypeVariable<?>)actualType; 1287 List<Class<?>> nestedOuterTypes = new LinkedList<>(); 1288 for (Class<?> ec = oc.getEnclosingClass(); ec != null; ec = ec.getEnclosingClass()) { 1289 try { 1290 Class<?> outerClass = oc.getClass(); 1291 nestedOuterTypes.add(outerClass); 1292 Map<Type,Type> outerTypeMap = new HashMap<>(); 1293 extractTypes(outerTypeMap, outerClass); 1294 for (Map.Entry<Type,Type> entry : outerTypeMap.entrySet()) { 1295 Type key = entry.getKey(), value = entry.getValue(); 1296 if (key instanceof TypeVariable) { 1297 TypeVariable<?> keyType = (TypeVariable<?>)key; 1298 if (keyType.getName().equals(typeVariable.getName()) && isInnerClass(keyType.getGenericDeclaration(), typeVariable.getGenericDeclaration())) { 1299 if (value instanceof Class) 1300 return (Class<?>)value; 1301 typeVariable = (TypeVariable<?>)entry.getValue(); 1302 } 1303 } 1304 } 1305 } catch (Exception e) { 1306 throw new RuntimeException(e); 1307 } 1308 } 1309 throw new FormattedRuntimeException("Could not resolve type: {0}", actualType); 1310 } else { 1311 throw new FormattedRuntimeException("Invalid type found in resolveParameterType: {0}", actualType); 1312 } 1313 } 1314 1315 /** 1316 * Invokes the specified method using fuzzy-arg matching. 1317 * 1318 * <p> 1319 * Arguments will be matched to the parameters based on the parameter types. 1320 * <br>Arguments can be in any order. 1321 * <br>Extra arguments will be ignored. 1322 * <br>Missing arguments will be left <jk>null</jk>. 1323 * 1324 * <p> 1325 * Note that this only works for methods that have distinguishable argument types. 1326 * <br>It's not going to work on methods with generic argument types like <code>Object</code> 1327 * 1328 * @param m The method being called. 1329 * @param pojo 1330 * The POJO the method is being called on. 1331 * <br>Can be <jk>null</jk> for static methods. 1332 * @param args 1333 * The arguments to pass to the method. 1334 * @return 1335 * The results of the method invocation. 1336 * @throws Exception 1337 */ 1338 public static Object invokeMethodFuzzy(Method m, Object pojo, Object...args) throws Exception { 1339 return m.invoke(pojo, getMatchingArgs(m.getParameterTypes(), args)); 1340 } 1341 1342 /** 1343 * Invokes the specified constructor using fuzzy-arg matching. 1344 * 1345 * <p> 1346 * Arguments will be matched to the parameters based on the parameter types. 1347 * <br>Arguments can be in any order. 1348 * <br>Extra arguments will be ignored. 1349 * <br>Missing arguments will be left <jk>null</jk>. 1350 * 1351 * <p> 1352 * Note that this only works for constructors that have distinguishable argument types. 1353 * <br>It's not going to work on constructors with generic argument types like <code>Object</code> 1354 * 1355 * @param c The constructor being called. 1356 * @param args 1357 * The arguments to pass to the constructor. 1358 * @return 1359 * The results of the method invocation. 1360 * @throws Exception 1361 */ 1362 public static <T> T invokeConstructorFuzzy(Constructor<T> c, Object...args) throws Exception { 1363 return c.newInstance(getMatchingArgs(c.getParameterTypes(), args)); 1364 } 1365 1366 private static boolean isInnerClass(GenericDeclaration od, GenericDeclaration id) { 1367 if (od instanceof Class && id instanceof Class) { 1368 Class<?> oc = (Class<?>)od; 1369 Class<?> ic = (Class<?>)id; 1370 while ((ic = ic.getEnclosingClass()) != null) 1371 if (ic == oc) 1372 return true; 1373 } 1374 return false; 1375 } 1376 1377 private static void extractTypes(Map<Type,Type> typeMap, Class<?> c) { 1378 Type gs = c.getGenericSuperclass(); 1379 if (gs instanceof ParameterizedType) { 1380 ParameterizedType pt = (ParameterizedType)gs; 1381 Type[] typeParameters = ((Class<?>)pt.getRawType()).getTypeParameters(); 1382 Type[] actualTypeArguments = pt.getActualTypeArguments(); 1383 for (int i = 0; i < typeParameters.length; i++) { 1384 if (typeMap.containsKey(actualTypeArguments[i])) 1385 actualTypeArguments[i] = typeMap.get(actualTypeArguments[i]); 1386 typeMap.put(typeParameters[i], actualTypeArguments[i]); 1387 } 1388 } 1389 } 1390 1391 /** 1392 * Finds a public method with the specified parameters. 1393 * 1394 * @param c The class to look for the method. 1395 * @param name The method name. 1396 * @param returnType 1397 * The return type of the method. 1398 * Can be a super type of the actual return type. 1399 * For example, if the actual return type is <code>CharSequence</code>, then <code>Object</code> will match but 1400 * <code>String</code> will not. 1401 * @param argTypes 1402 * The argument types of the method. 1403 * Can be subtypes of the actual parameter types. 1404 * For example, if the parameter type is <code>CharSequence</code>, then <code>String</code> will match but 1405 * <code>Object</code> will not. 1406 * @return The matched method, or <jk>null</jk> if no match was found. 1407 */ 1408 public static Method findPublicMethod(Class<?> c, String name, Class<?> returnType, Class<?>...argTypes) { 1409 for (Method m : c.getMethods()) { 1410 if (isPublic(m) && hasName(m, name) && hasReturnTypeParent(m, returnType) && argsMatch(m.getParameterTypes(), argTypes)) 1411 return m; 1412 } 1413 return null; 1414 } 1415 1416 /** 1417 * Finds a public constructor with the specified parameters without throwing an exception. 1418 * 1419 * @param c The class to search for a constructor. 1420 * @param fuzzyArgs 1421 * Use fuzzy-arg matching. 1422 * Find a constructor that best matches the specified args. 1423 * @param argTypes 1424 * The argument types in the constructor. 1425 * Can be subtypes of the actual constructor argument types. 1426 * @return The matching constructor, or <jk>null</jk> if constructor could not be found. 1427 */ 1428 public static <T> Constructor<T> findPublicConstructor(Class<T> c, boolean fuzzyArgs, Class<?>...argTypes) { 1429 return findConstructor(c, Visibility.PUBLIC, fuzzyArgs, argTypes); 1430 } 1431 1432 /** 1433 * Finds a constructor with the specified parameters without throwing an exception. 1434 * 1435 * @param c The class to search for a constructor. 1436 * @param vis The minimum visibility. 1437 * @param fuzzyArgs 1438 * Use fuzzy-arg matching. 1439 * Find a constructor that best matches the specified args. 1440 * @param argTypes 1441 * The argument types in the constructor. 1442 * Can be subtypes of the actual constructor argument types. 1443 * @return The matching constructor, or <jk>null</jk> if constructor could not be found. 1444 */ 1445 @SuppressWarnings("unchecked") 1446 public static <T> Constructor<T> findConstructor(Class<T> c, Visibility vis, boolean fuzzyArgs, Class<?>...argTypes) { 1447 ConstructorCacheEntry cce = CONSTRUCTOR_CACHE.get(c); 1448 if (cce != null && argsMatch(cce.paramTypes, argTypes) && cce.isVisible(vis)) 1449 return (Constructor<T>)cce.constructor; 1450 1451 if (fuzzyArgs) { 1452 int bestCount = -1; 1453 Constructor<?> bestMatch = null; 1454 for (Constructor<?> n : c.getDeclaredConstructors()) { 1455 if (vis.isVisible(n)) { 1456 int m = fuzzyArgsMatch(n.getParameterTypes(), argTypes); 1457 if (m > bestCount) { 1458 bestCount = m; 1459 bestMatch = n; 1460 } 1461 } 1462 } 1463 if (bestCount >= 0) 1464 CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, bestMatch)); 1465 return (Constructor<T>)bestMatch; 1466 } 1467 1468 final boolean isMemberClass = c.isMemberClass() && ! isStatic(c); 1469 for (Constructor<?> n : c.getConstructors()) { 1470 Class<?>[] paramTypes = n.getParameterTypes(); 1471 if (isMemberClass) 1472 paramTypes = Arrays.copyOfRange(paramTypes, 1, paramTypes.length); 1473 if (argsMatch(paramTypes, argTypes) && vis.isVisible(n)) { 1474 CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, n)); 1475 return (Constructor<T>)n; 1476 } 1477 } 1478 1479 return null; 1480 } 1481 1482 1483 1484 private static final class ConstructorCacheEntry { 1485 final Constructor<?> constructor; 1486 final Class<?>[] paramTypes; 1487 1488 ConstructorCacheEntry(Class<?> forClass, Constructor<?> constructor) { 1489 this.constructor = constructor; 1490 this.paramTypes = constructor.getParameterTypes(); 1491 } 1492 1493 boolean isVisible(Visibility vis) { 1494 return vis.isVisible(constructor); 1495 } 1496 } 1497 1498 /** 1499 * Returns <jk>true</jk> if the specified argument types are valid for the specified parameter types. 1500 * 1501 * @param paramTypes The parameters types specified on a method. 1502 * @param argTypes The class types of the arguments being passed to the method. 1503 * @return <jk>true</jk> if the arguments match the parameters. 1504 */ 1505 public static boolean argsMatch(Class<?>[] paramTypes, Class<?>[] argTypes) { 1506 if (paramTypes.length == argTypes.length) { 1507 for (int i = 0; i < paramTypes.length; i++) 1508 if (! isParentClass(paramTypes[i], argTypes[i])) 1509 return false; 1510 return true; 1511 } 1512 return false; 1513 } 1514 1515 /** 1516 * Returns a number representing the number of arguments that match the specified parameters. 1517 * 1518 * @param paramTypes The parameters types specified on a method. 1519 * @param argTypes The class types of the arguments being passed to the method. 1520 * @return The number of matching arguments, or <code>-1</code> a parameter was found that isn't in the list of args. 1521 */ 1522 public static int fuzzyArgsMatch(Class<?>[] paramTypes, Class<?>... argTypes) { 1523 int matches = 0; 1524 outer: for (Class<?> p : paramTypes) { 1525 p = getWrapperIfPrimitive(p); 1526 for (Class<?> a : argTypes) { 1527 if (isParentClass(p, a)) { 1528 matches++; 1529 continue outer; 1530 } 1531 } 1532 return -1; 1533 } 1534 return matches; 1535 } 1536 1537 /** 1538 * Finds the public constructor that can take in the specified arguments. 1539 * 1540 * @param c The class we're trying to construct. 1541 * @param args The arguments we want to pass into the constructor. 1542 * @return 1543 * The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified 1544 * arguments. 1545 */ 1546 public static <T> Constructor<T> findPublicConstructor(Class<T> c, Object...args) { 1547 return findPublicConstructor(c, false, getClasses(args)); 1548 } 1549 1550 /** 1551 * Finds the public constructor that can take in the specified arguments. 1552 * 1553 * @param c The class we're trying to construct. 1554 * @param args The argument types we want to pass into the constructor. 1555 * @return 1556 * The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified 1557 * arguments. 1558 */ 1559 public static <T> Constructor<T> findPublicConstructor(Class<T> c, Class<?>...args) { 1560 return findPublicConstructor(c, false, args); 1561 } 1562 1563 /** 1564 * Finds the public constructor that can take in the specified arguments. 1565 * 1566 * @param c The class we're trying to construct. 1567 * @param fuzzyArgs 1568 * Use fuzzy-arg matching. 1569 * Find a constructor that best matches the specified args. 1570 * @param args The arguments we want to pass into the constructor. 1571 * @return 1572 * The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified 1573 * arguments. 1574 */ 1575 public static <T> Constructor<T> findPublicConstructor(Class<T> c, boolean fuzzyArgs, Object...args) { 1576 return findPublicConstructor(c, fuzzyArgs, getClasses(args)); 1577 } 1578 1579 /** 1580 * Returns the class types for the specified arguments. 1581 * 1582 * @param args The objects we're getting the classes of. 1583 * @return The classes of the arguments. 1584 */ 1585 public static Class<?>[] getClasses(Object...args) { 1586 Class<?>[] pt = new Class<?>[args.length]; 1587 for (int i = 0; i < args.length; i++) 1588 pt[i] = args[i] == null ? null : args[i].getClass(); 1589 return pt; 1590 } 1591 1592 /** 1593 * Returns a {@link MethodInfo} bean that describes the specified method. 1594 * 1595 * @param m The method to describe. 1596 * @return The bean with information about the method. 1597 */ 1598 public static MethodInfo getMethodInfo(Method m) { 1599 return new MethodInfo(m); 1600 } 1601 1602 /** 1603 * Returns {@link MethodInfo} beans that describe the specified methods. 1604 * 1605 * @param m The methods to describe. 1606 * @return The beans with information about the methods. 1607 */ 1608 public static MethodInfo[] getMethodInfo(Collection<Method> m) { 1609 MethodInfo[] mi = new MethodInfo[m.size()]; 1610 int i = 0; 1611 for (Method mm : m) 1612 mi[i++] = getMethodInfo(mm); 1613 return mi; 1614 } 1615 1616 /** 1617 * Simple bean that shows the name, parameter types, and return type of a method. 1618 */ 1619 @SuppressWarnings("javadoc") 1620 public static class MethodInfo { 1621 public final String methodName; 1622 public final String[] parameterTypes; 1623 public final String returnType; 1624 1625 MethodInfo(Method m) { 1626 methodName = m.getName(); 1627 Type[] pt = m.getGenericParameterTypes(); 1628 parameterTypes = new String[pt.length]; 1629 for (int i = 0; i < pt.length; i++) 1630 parameterTypes[i] = BeanContext.DEFAULT.getClassMeta(pt[i]).toString(); 1631 returnType = BeanContext.DEFAULT.getClassMeta(m.getGenericReturnType()).toString(); 1632 } 1633 } 1634 1635 /** 1636 * Creates an instance of the specified class. 1637 * 1638 * @param c 1639 * The class to cast to. 1640 * @param c2 1641 * The class to instantiate. 1642 * Can also be an instance of the class. 1643 * @return 1644 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1645 * @throws 1646 * RuntimeException if constructor could not be found or called. 1647 */ 1648 public static <T> T newInstance(Class<T> c, Object c2) { 1649 return newInstanceFromOuter(null, c, c2, false); 1650 } 1651 1652 /** 1653 * Creates an instance of the specified class. 1654 * 1655 * @param c 1656 * The class to cast to. 1657 * @param c2 1658 * The class to instantiate. 1659 * Can also be an instance of the class. 1660 * @param fuzzyArgs 1661 * Use fuzzy constructor arg matching. 1662 * <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored. 1663 * <br>No-arg constructors are also used if no other constructors are found. 1664 * @param args 1665 * The arguments to pass to the constructor. 1666 * @return 1667 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1668 * @throws 1669 * RuntimeException if constructor could not be found or called. 1670 */ 1671 public static <T> T newInstance(Class<T> c, Object c2, boolean fuzzyArgs, Object...args) { 1672 return newInstanceFromOuter(null, c, c2, fuzzyArgs, args); 1673 } 1674 1675 /** 1676 * Creates an instance of the specified class from within the context of another object. 1677 * 1678 * @param outer 1679 * The outer object. 1680 * Can be <jk>null</jk>. 1681 * @param c 1682 * The class to cast to. 1683 * @param c2 1684 * The class to instantiate. 1685 * Can also be an instance of the class. 1686 * @param fuzzyArgs 1687 * Use fuzzy constructor arg matching. 1688 * <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored. 1689 * <br>No-arg constructors are also used if no other constructors are found. 1690 * @param args 1691 * The arguments to pass to the constructor. 1692 * @return 1693 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1694 * @throws 1695 * RuntimeException if constructor could not be found or called. 1696 */ 1697 @SuppressWarnings("unchecked") 1698 public static <T> T newInstanceFromOuter(Object outer, Class<T> c, Object c2, boolean fuzzyArgs, Object...args) { 1699 if (c2 == null) 1700 return null; 1701 if (c2 instanceof Class) { 1702 try { 1703 Class<?> c3 = (Class<?>)c2; 1704 if (c3.isInterface() || isAbstract(c3)) 1705 return null; 1706 1707 // First look for an exact match. 1708 Constructor<?> con = findPublicConstructor(c3, false, args); 1709 if (con != null) 1710 return (T)con.newInstance(args); 1711 1712 // Next look for an exact match including the outer. 1713 if (outer != null) { 1714 args = new AList<>().append(outer).appendAll(args).toArray(); 1715 con = findPublicConstructor(c3, false, args); 1716 if (con != null) 1717 return (T)con.newInstance(args); 1718 } 1719 1720 // Finally use fuzzy matching. 1721 if (fuzzyArgs) { 1722 con = findPublicConstructor(c3, true, args); 1723 if (con != null) 1724 return (T)con.newInstance(getMatchingArgs(con.getParameterTypes(), args)); 1725 } 1726 1727 throw new FormattedRuntimeException("Could not instantiate class {0}/{1}. Constructor not found.", c.getName(), c2); 1728 } catch (Exception e) { 1729 throw new FormattedRuntimeException(e, "Could not instantiate class {0}", c.getName()); 1730 } 1731 } else if (isParentClass(c, c2.getClass())) { 1732 return (T)c2; 1733 } else { 1734 throw new FormattedRuntimeException("Object of type {0} found but was expecting {1}.", c2.getClass(), c.getClass()); 1735 } 1736 } 1737 1738 /** 1739 * Matches arguments to a list of parameter types. 1740 * 1741 * <p> 1742 * Extra parameters are ignored. 1743 * <br>Missing parameters are left null. 1744 * 1745 * @param paramTypes The parameter types. 1746 * @param args The arguments to match to the parameter types. 1747 * @return 1748 * An array of parameters. 1749 */ 1750 public static Object[] getMatchingArgs(Class<?>[] paramTypes, Object... args) { 1751 Object[] params = new Object[paramTypes.length]; 1752 for (int i = 0; i < paramTypes.length; i++) { 1753 Class<?> pt = getWrapperIfPrimitive(paramTypes[i]); 1754 for (int j = 0; j < args.length; j++) { 1755 if (isParentClass(pt, args[j].getClass())) { 1756 params[i] = args[j]; 1757 break; 1758 } 1759 } 1760 } 1761 return params; 1762 } 1763 1764 /** 1765 * Returns all the fields in the specified class and all parent classes. 1766 * 1767 * <p> 1768 * Fields are ordered in either parent-to-child, or child-to-parent order, then alphabetically. 1769 * 1770 * @param c The class to get all fields on. 1771 * @param parentFirst Order them in parent-class-to-child-class order, otherwise child-class-to-parent-class order. 1772 * @return An iterable of all fields in the specified class. 1773 */ 1774 @SuppressWarnings("rawtypes") 1775 public static Iterable<Field> getAllFields(final Class c, final boolean parentFirst) { 1776 return new Iterable<Field>() { 1777 @Override 1778 public Iterator<Field> iterator() { 1779 return new Iterator<Field>(){ 1780 final Iterator<Class<?>> classIterator = getParentClasses(c, parentFirst, false); 1781 Field[] fields = classIterator.hasNext() ? sort(classIterator.next().getDeclaredFields()) : new Field[0]; 1782 int fIndex = 0; 1783 Field next; 1784 1785 @Override 1786 public boolean hasNext() { 1787 prime(); 1788 return next != null; 1789 } 1790 1791 private void prime() { 1792 if (next == null) { 1793 while (fIndex >= fields.length) { 1794 if (classIterator.hasNext()) { 1795 fields = sort(classIterator.next().getDeclaredFields()); 1796 fIndex = 0; 1797 } else { 1798 fIndex = -1; 1799 } 1800 } 1801 if (fIndex != -1) 1802 next = fields[fIndex++]; 1803 } 1804 } 1805 1806 @Override 1807 public Field next() { 1808 prime(); 1809 Field f = next; 1810 next = null; 1811 return f; 1812 } 1813 1814 @Override 1815 public void remove() { 1816 } 1817 }; 1818 } 1819 }; 1820 } 1821 1822 /** 1823 * Returns all the methods in the specified class and all parent classes. 1824 * 1825 * <p> 1826 * Methods are ordered in either parent-to-child, or child-to-parent order, then alphabetically. 1827 * 1828 * @param c The class to get all methods on. 1829 * @param parentFirst Order them in parent-class-to-child-class order, otherwise child-class-to-parent-class order. 1830 * @return An iterable of all methods in the specified class. 1831 */ 1832 @SuppressWarnings("rawtypes") 1833 public static Iterable<Method> getAllMethods(final Class c, final boolean parentFirst) { 1834 return new Iterable<Method>() { 1835 @Override 1836 public Iterator<Method> iterator() { 1837 return new Iterator<Method>(){ 1838 final Iterator<Class<?>> classIterator = getParentClasses(c, parentFirst, true); 1839 Method[] methods = classIterator.hasNext() ? sort(classIterator.next().getDeclaredMethods()) : new Method[0]; 1840 int mIndex = 0; 1841 Method next; 1842 1843 @Override 1844 public boolean hasNext() { 1845 prime(); 1846 return next != null; 1847 } 1848 1849 private void prime() { 1850 if (next == null) { 1851 while (mIndex >= methods.length) { 1852 if (classIterator.hasNext()) { 1853 methods = sort(classIterator.next().getDeclaredMethods()); 1854 mIndex = 0; 1855 } else { 1856 mIndex = -1; 1857 } 1858 } 1859 if (mIndex != -1) 1860 next = methods[mIndex++]; 1861 } 1862 } 1863 1864 @Override 1865 public Method next() { 1866 prime(); 1867 Method m = next; 1868 next = null; 1869 return m; 1870 } 1871 1872 @Override 1873 public void remove() { 1874 } 1875 }; 1876 } 1877 }; 1878 } 1879 1880 private static Comparator<Method> METHOD_COMPARATOR = new Comparator<Method>() { 1881 1882 @Override 1883 public int compare(Method o1, Method o2) { 1884 int i = o1.getName().compareTo(o2.getName()); 1885 if (i == 0) { 1886 i = o1.getParameterTypes().length - o2.getParameterTypes().length; 1887 if (i == 0) { 1888 for (int j = 0; j < o1.getParameterTypes().length && i == 0; j++) { 1889 i = o1.getParameterTypes()[j].getName().compareTo(o2.getParameterTypes()[j].getName()); 1890 } 1891 } 1892 } 1893 return i; 1894 } 1895 }; 1896 1897 /** 1898 * Sorts methods in alphabetical order. 1899 * 1900 * @param m The methods to sort. 1901 * @return The same array, but with elements sorted. 1902 */ 1903 public static Method[] sort(Method[] m) { 1904 Arrays.sort(m, METHOD_COMPARATOR); 1905 return m; 1906 } 1907 1908 private static Comparator<Field> FIELD_COMPARATOR = new Comparator<Field>() { 1909 1910 @Override 1911 public int compare(Field o1, Field o2) { 1912 return o1.getName().compareTo(o2.getName()); 1913 } 1914 }; 1915 1916 /** 1917 * Sorts methods in alphabetical order. 1918 * 1919 * @param m The methods to sort. 1920 * @return The same array, but with elements sorted. 1921 */ 1922 public static Field[] sort(Field[] m) { 1923 Arrays.sort(m, FIELD_COMPARATOR); 1924 return m; 1925 } 1926 1927 /** 1928 * Returns a list of all the parent classes of the specified class including the class itself. 1929 * 1930 * @param c The class to retrieve the parent classes. 1931 * @param parentFirst In parent-to-child order, otherwise child-to-parent. 1932 * @param includeInterfaces Include interfaces. 1933 * @return An iterator of parent classes in the class hierarchy. 1934 */ 1935 public static Iterator<Class<?>> getParentClasses(final Class<?> c, boolean parentFirst, boolean includeInterfaces) { 1936 List<Class<?>> l = getParentClasses(new ArrayList<Class<?>>(), c, parentFirst, includeInterfaces); 1937 return l.iterator(); 1938 } 1939 1940 private static List<Class<?>> getParentClasses(List<Class<?>> l, Class<?> c, boolean parentFirst, boolean includeInterfaces) { 1941 if (parentFirst) { 1942 if (includeInterfaces) 1943 for (Class<?> i : c.getInterfaces()) 1944 l.add(i); 1945 if (c.getSuperclass() != Object.class && c.getSuperclass() != null) 1946 getParentClasses(l, c.getSuperclass(), parentFirst, includeInterfaces); 1947 l.add(c); 1948 } else { 1949 l.add(c); 1950 if (c.getSuperclass() != Object.class && c.getSuperclass() != null) 1951 getParentClasses(l, c.getSuperclass(), parentFirst, includeInterfaces); 1952 if (includeInterfaces) 1953 for (Class<?> i : c.getInterfaces()) 1954 l.add(i); 1955 } 1956 return l; 1957 } 1958 1959 /** 1960 * Returns the default value for the specified primitive class. 1961 * 1962 * @param primitiveClass The primitive class to get the default value for. 1963 * @return The default value, or <jk>null</jk> if the specified class is not a primitive class. 1964 */ 1965 public static Object getPrimitiveDefault(Class<?> primitiveClass) { 1966 return primitiveDefaultMap.get(primitiveClass); 1967 } 1968 1969 private static final Map<Class<?>,Object> primitiveDefaultMap = Collections.unmodifiableMap( 1970 new AMap<Class<?>,Object>() 1971 .append(Boolean.TYPE, false) 1972 .append(Character.TYPE, (char)0) 1973 .append(Short.TYPE, (short)0) 1974 .append(Integer.TYPE, 0) 1975 .append(Long.TYPE, 0l) 1976 .append(Float.TYPE, 0f) 1977 .append(Double.TYPE, 0d) 1978 .append(Byte.TYPE, (byte)0) 1979 .append(Boolean.class, false) 1980 .append(Character.class, (char)0) 1981 .append(Short.class, (short)0) 1982 .append(Integer.class, 0) 1983 .append(Long.class, 0l) 1984 .append(Float.class, 0f) 1985 .append(Double.class, 0d) 1986 .append(Byte.class, (byte)0) 1987 ); 1988 1989 /** 1990 * Returns a readable representation of the specified method. 1991 * 1992 * <p> 1993 * The format of the string is <js>"full-qualified-class.method-name(parameter-simple-class-names)"</js>. 1994 * 1995 * @param m The method to stringify. 1996 * @return The stringified method. 1997 */ 1998 public static String toString(Method m) { 1999 StringBuilder sb = new StringBuilder(m.getDeclaringClass().getName() + "." + m.getName() + "("); 2000 for (int i = 0; i < m.getParameterTypes().length; i++) { 2001 if (i > 0) 2002 sb.append(","); 2003 sb.append(m.getParameterTypes()[i].getSimpleName()); 2004 } 2005 sb.append(")"); 2006 return sb.toString(); 2007 } 2008 2009 /** 2010 * Returns a readable representation of the specified field. 2011 * 2012 * <p> 2013 * The format of the string is <js>"full-qualified-class.field-name"</js>. 2014 * 2015 * @param f The field to stringify. 2016 * @return The stringified field. 2017 */ 2018 public static String toString(Field f) { 2019 return f.getDeclaringClass().getName() + "." + f.getName(); 2020 } 2021 2022 /** 2023 * Throws an {@link IllegalArgumentException} if the parameters on the method are not in the specified list provided. 2024 * 2025 * @param m The method to test. 2026 * @param args The valid class types (exact) for the arguments. 2027 * @throws FormattedIllegalArgumentException If any of the parameters on the method weren't in the list. 2028 */ 2029 public static void assertArgsOfType(Method m, Class<?>...args) throws FormattedIllegalArgumentException { 2030 for (Class<?> c1 : m.getParameterTypes()) { 2031 boolean foundMatch = false; 2032 for (Class<?> c2 : args) 2033 if (c1 == c2) 2034 foundMatch = true; 2035 if (! foundMatch) 2036 throw new FormattedIllegalArgumentException("Invalid argument of type {0} passed in method {1}. Only arguments of type {2} are allowed.", c1, m, args); 2037 } 2038 } 2039 2040 /** 2041 * Finds the public static "fromString" method on the specified class. 2042 * 2043 * <p> 2044 * Looks for the following method names: 2045 * <ul> 2046 * <li><code>fromString</code> 2047 * <li><code>fromValue</code> 2048 * <li><code>valueOf</code> 2049 * <li><code>parse</code> 2050 * <li><code>parseString</code> 2051 * <li><code>forName</code> 2052 * <li><code>forString</code> 2053 * </ul> 2054 * 2055 * @param c The class to find the method on. 2056 * @return The static method, or <jk>null</jk> if it couldn't be found. 2057 */ 2058 public static Method findPublicFromStringMethod(Class<?> c) { 2059 for (String methodName : new String[]{"create","fromString","fromValue","valueOf","parse","parseString","forName","forString"}) 2060 for (Method m : c.getMethods()) 2061 if (isAll(m, STATIC, PUBLIC, NOT_DEPRECATED) && hasName(m, methodName) && hasReturnType(m, c) && hasArgs(m, String.class)) 2062 return m; 2063 return null; 2064 } 2065 2066 /** 2067 * Find the public static creator method on the specified class. 2068 * 2069 * @param oc The created type. 2070 * @param ic The argument type. 2071 * @param name The method name. 2072 * @return The static method, or <jk>null</jk> if it couldn't be found. 2073 */ 2074 public static Method findPublicStaticCreateMethod(Class<?> oc, Class<?> ic, String name) { 2075 for (Method m : oc.getMethods()) 2076 if (isAll(m, STATIC, PUBLIC, NOT_DEPRECATED) && hasName(m, name) && hasReturnType(m, oc) && hasArgs(m, ic)) 2077 return m; 2078 return null; 2079 } 2080 2081 /** 2082 * Constructs a new instance of the specified class from the specified string. 2083 * 2084 * <p> 2085 * Class must be one of the following: 2086 * <ul> 2087 * <li>Have a public constructor that takes in a single <code>String</code> argument. 2088 * <li>Have a static <code>fromString(String)</code> (or related) method. 2089 * <br>See {@link #findPublicFromStringMethod(Class)} for the list of possible static method names. 2090 * <li>Be an <code>enum</code>. 2091 * </ul> 2092 * 2093 * @param c The class. 2094 * @param s The string to create the instance from. 2095 * @return A new object instance, or <jk>null</jk> if a method for converting the string to an object could not be found. 2096 */ 2097 public static <T> T fromString(Class<T> c, String s) { 2098 Transform<String,T> t = TransformCache.get(String.class, c); 2099 return t == null ? null : t.transform(s); 2100 } 2101 2102 /** 2103 * Converts an object to a string. 2104 * 2105 * <p> 2106 * Normally, this is just going to call <code>toString()</code> on the object. 2107 * However, the {@link Locale} and {@link TimeZone} objects are treated special so that the returned value 2108 * works with the {@link #fromString(Class, String)} method. 2109 * 2110 * @param o The object to convert to a string. 2111 * @return The stringified object, or <jk>null</jk> if the object was <jk>null</jk>. 2112 */ 2113 @SuppressWarnings({ "unchecked" }) 2114 public static String toString(Object o) { 2115 if (o == null) 2116 return null; 2117 Transform<Object,String> t = (Transform<Object,String>)TransformCache.get(o.getClass(), String.class); 2118 return t == null ? o.toString() : t.transform(o); 2119 } 2120 2121 /** 2122 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 2123 * 2124 * @param x The constructor. 2125 * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown. 2126 * @return <jk>true</jk> if call was successful. 2127 */ 2128 public static boolean setAccessible(Constructor<?> x, boolean ignoreExceptions) { 2129 try { 2130 if (! (x == null || x.isAccessible())) 2131 x.setAccessible(true); 2132 return true; 2133 } catch (SecurityException e) { 2134 if (ignoreExceptions) 2135 return false; 2136 throw new ClassMetaRuntimeException("Could not set accessibility to true on constructor ''{0}''", x); 2137 } 2138 } 2139 2140 /** 2141 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 2142 * 2143 * @param x The method. 2144 * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown. 2145 * @return <jk>true</jk> if call was successful. 2146 */ 2147 public static boolean setAccessible(Method x, boolean ignoreExceptions) { 2148 try { 2149 if (! (x == null || x.isAccessible())) 2150 x.setAccessible(true); 2151 return true; 2152 } catch (SecurityException e) { 2153 if (ignoreExceptions) 2154 return false; 2155 throw new ClassMetaRuntimeException("Could not set accessibility to true on method ''{0}''", x); 2156 } 2157 } 2158 2159 /** 2160 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 2161 * 2162 * @param x The field. 2163 * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown. 2164 * @return <jk>true</jk> if call was successful. 2165 */ 2166 public static boolean setAccessible(Field x, boolean ignoreExceptions) { 2167 try { 2168 if (! (x == null || x.isAccessible())) 2169 x.setAccessible(true); 2170 return true; 2171 } catch (SecurityException e) { 2172 if (ignoreExceptions) 2173 return false; 2174 throw new ClassMetaRuntimeException("Could not set accessibility to true on field ''{0}''", x); 2175 } 2176 } 2177 2178 /** 2179 * Returns the simple name of a class. 2180 * 2181 * <p> 2182 * Similar to {@link Class#getSimpleName()}, but includes the simple name of an enclosing or declaring class. 2183 * 2184 * @param c The class to get the simple name on. 2185 * @return The simple name of a class. 2186 */ 2187 public static String getSimpleName(Class<?> c) { 2188 if (c.isLocalClass()) 2189 return getSimpleName(c.getEnclosingClass()) + '.' + c.getSimpleName(); 2190 if (c.isMemberClass()) 2191 return getSimpleName(c.getDeclaringClass()) + '.' + c.getSimpleName(); 2192 return c.getSimpleName(); 2193 } 2194 2195 /** 2196 * Returns the simple name of a class. 2197 * 2198 * <p> 2199 * Similar to {@link Class#getSimpleName()}, but includes the simple name of an enclosing or declaring class. 2200 * 2201 * @param t The class to get the simple name on. 2202 * @return The simple name of a class. 2203 */ 2204 public static String getSimpleName(Type t) { 2205 if (t instanceof Class) 2206 return getSimpleName((Class<?>)t); 2207 if (t instanceof ParameterizedType) { 2208 StringBuilder sb = new StringBuilder(); 2209 ParameterizedType pt = (ParameterizedType)t; 2210 sb.append(getSimpleName(pt.getRawType())); 2211 sb.append("<"); 2212 boolean first = true; 2213 for (Type t2 : pt.getActualTypeArguments()) { 2214 if (! first) 2215 sb.append(','); 2216 first = false; 2217 sb.append(getSimpleName(t2)); 2218 } 2219 sb.append(">"); 2220 return sb.toString(); 2221 } 2222 return null; 2223 } 2224 2225 /** 2226 * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value. 2227 * 2228 * @param a The annotation to check for. 2229 * @param m The method containing the parameter to check. 2230 * @param index The parameter index. 2231 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value. 2232 */ 2233 public static boolean hasAnnotation(Class<? extends Annotation> a, Method m, int index) { 2234 return getAnnotation(a, m, index) != null; 2235 } 2236 2237 /** 2238 * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Method)} returns a value. 2239 * 2240 * @param a The annotation to check for. 2241 * @param m The method to check. 2242 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method)} returns a value. 2243 */ 2244 public static boolean hasAnnotation(Class<? extends Annotation> a, Method m) { 2245 return getAnnotation(a, m) != null; 2246 } 2247 2248 /** 2249 * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Type)} returns a value. 2250 * 2251 * @param a The annotation to check for. 2252 * @param t The class to check. 2253 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Type)} returns a value. 2254 */ 2255 public static boolean hasAnnotation(Class<? extends Annotation> a, Type t) { 2256 return getAnnotation(a, t) != null; 2257 } 2258 2259 /** 2260 * Returns the specified annotation if it exists on the specified parameter or parameter type class. 2261 * 2262 * @param a The annotation to check for. 2263 * @param m The method containing the parameter to check. 2264 * @param index The parameter index. 2265 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value. 2266 */ 2267 @SuppressWarnings("unchecked") 2268 public static <T extends Annotation> T getAnnotation(Class<T> a, Method m, int index) { 2269 for (Annotation a2 : m.getParameterAnnotations()[index]) 2270 if (a.isInstance(a2)) 2271 return (T)a2; 2272 Type t = m.getGenericParameterTypes()[index]; 2273 if (Value.isType(t)) 2274 return getAnnotation(a, Value.getParameterType(t)); 2275 return getAnnotation(a, t); 2276 } 2277 2278 /** 2279 * Returns all annotations defined on the specified parameter and parameter type. 2280 * 2281 * <p> 2282 * Annotations are ordered parameter first, then class, then superclasses. 2283 * 2284 * @param a The annotation to look for. 2285 * @param m The method containing the parameter. 2286 * @param index The parameter index. 2287 * @return All instances of the annotation with the 2288 */ 2289 @SuppressWarnings("unchecked") 2290 public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m, int index) { 2291 List<T> l = new ArrayList<>(); 2292 for (Annotation a2 : m.getParameterAnnotations()[index]) 2293 if (a.isInstance(a2)) 2294 l.add((T)a2); 2295 Type t = m.getGenericParameterTypes()[index]; 2296 if (Value.isType(t)) 2297 appendAnnotations(a, Value.getParameterType(t), l); 2298 else 2299 appendAnnotations(a, t, l); 2300 return l; 2301 } 2302 2303 /** 2304 * Returns all annotations defined on the specified parameter and parameter type. 2305 * 2306 * <p> 2307 * Annotations are ordered parameter superclasses first, then class, then parameter. 2308 * 2309 * @param a The annotation to look for. 2310 * @param m The method containing the parameter. 2311 * @param index The parameter index. 2312 * @return All instances of the annotation with the 2313 */ 2314 public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Method m, int index) { 2315 List<T> l = getAnnotations(a, m, index); 2316 Collections.reverse(l); 2317 return l; 2318 } 2319 2320 /** 2321 * Returns all annotations defined on the specified method and return type. 2322 * 2323 * <p> 2324 * Annotations are ordered method first, then return class, then return superclasses. 2325 * 2326 * @param a The annotation to look for. 2327 * @param m The method being inspected. 2328 * @return All instances of the annotation with the 2329 */ 2330 @SuppressWarnings("unchecked") 2331 public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m) { 2332 List<T> l = new ArrayList<>(); 2333 for (Method m2 : findMatchingMethods(m)) 2334 for (Annotation a2 : m2.getAnnotations()) 2335 if (a.isInstance(a2)) 2336 l.add((T)a2); 2337 Type t = m.getGenericReturnType(); 2338 if (Value.isType(t)) 2339 appendAnnotations(a, Value.getParameterType(t), l); 2340 else 2341 appendAnnotations(a, t, l); 2342 return l; 2343 } 2344 2345 /** 2346 * Returns all annotations defined on the specified method and return type. 2347 * 2348 * <p> 2349 * Annotations are ordered return superclass first, then return class, then method. 2350 * 2351 * @param a The annotation to look for. 2352 * @param m The method being inspected. 2353 * @return All instances of the annotation with the 2354 */ 2355 public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Method m) { 2356 List<T> l = getAnnotations(a, m); 2357 Collections.reverse(l); 2358 return l; 2359 } 2360 2361 /** 2362 * Returns the specified annotation if it exists on the specified method or return type class. 2363 * 2364 * @param a The annotation to check for. 2365 * @param m The method to check. 2366 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value. 2367 */ 2368 @SuppressWarnings("unchecked") 2369 public static <T extends Annotation> T getAnnotation(Class<T> a, Method m) { 2370 for (Annotation a2 : m.getAnnotations()) 2371 if (a.isInstance(a2)) 2372 return (T)a2; 2373 return getAnnotation(a, m.getGenericReturnType()); 2374 } 2375 2376 /** 2377 * Similar to {@link Class#getAnnotation(Class)} except also searches annotations on interfaces. 2378 * 2379 * @param <T> The annotation class type. 2380 * @param a The annotation class. 2381 * @param t The annotated class. 2382 * @return The annotation, or <jk>null</jk> if not found. 2383 */ 2384 public static <T extends Annotation> T getAnnotation(Class<T> a, Type t) { 2385 Class<?> c = toClass(t); 2386 if (c != null) { 2387 T t2 = getDeclaredAnnotation(a, c); 2388 if (t2 != null) 2389 return t2; 2390 2391 t2 = getAnnotation(a, c.getSuperclass()); 2392 if (t2 != null) 2393 return t2; 2394 2395 for (Class<?> c2 : c.getInterfaces()) { 2396 t2 = getAnnotation(a, c2); 2397 if (t2 != null) 2398 return t2; 2399 } 2400 } 2401 return null; 2402 } 2403 2404 /** 2405 * Returns the specified annotation only if it's been declared on the specified class. 2406 * 2407 * <p> 2408 * More efficient than calling {@link Class#getAnnotation(Class)} since it doesn't recursively look for the class 2409 * up the parent chain. 2410 * 2411 * @param <T> The annotation class type. 2412 * @param a The annotation class. 2413 * @param t The annotated class. 2414 * @return The annotation, or <jk>null</jk> if not found. 2415 */ 2416 @SuppressWarnings("unchecked") 2417 public static <T extends Annotation> T getDeclaredAnnotation(Class<T> a, Type t) { 2418 Class<?> c = toClass(t); 2419 if (c != null) 2420 for (Annotation a2 : c.getDeclaredAnnotations()) 2421 if (a2.annotationType() == a) 2422 return (T)a2; 2423 return null; 2424 } 2425 2426 /** 2427 * Returns all instances of the specified annotation on the specified class. 2428 * 2429 * <p> 2430 * Searches all superclasses and superinterfaces. 2431 * Results are ordered child-to-parent. 2432 * 2433 * @param <T> The annotation class type. 2434 * @param a The annotation class type. 2435 * @param t The class being searched. 2436 * @return The found matches, or an empty array if annotation was not found. 2437 */ 2438 public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Type t) { 2439 List<T> l = new LinkedList<>(); 2440 appendAnnotations(a, t, l); 2441 return l; 2442 } 2443 2444 /** 2445 * Same as {@link #getAnnotations(Class, Type)} but returns the list in parent-to-child order. 2446 * 2447 * @param a The annotation class type. 2448 * @param t The class being searched. 2449 * @return The found matches, or an empty array if annotation was not found. 2450 */ 2451 public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Type t) { 2452 List<T> l = getAnnotations(a, t); 2453 Collections.reverse(l); 2454 return l; 2455 } 2456 2457 /** 2458 * Same as {@link #getAnnotations(Class, Type)} except returns the annotations as a map with the keys being the 2459 * class on which the annotation was found. 2460 * 2461 * <p> 2462 * Results are ordered child-to-parent. 2463 * 2464 * @param <T> The annotation class type. 2465 * @param a The annotation class type. 2466 * @param t The class being searched. 2467 * @return The found matches, or an empty map if annotation was not found. 2468 */ 2469 public static <T extends Annotation> LinkedHashMap<Class<?>,T> getAnnotationsMap(Class<T> a, Type t) { 2470 LinkedHashMap<Class<?>,T> m = new LinkedHashMap<>(); 2471 findAnnotationsMap(a, t, m); 2472 return m; 2473 } 2474 2475 /** 2476 * Same as {@link #getAnnotationsMap(Class, Type)} except returns results in parent-to-child order. 2477 * 2478 * @param <T> The annotation class type. 2479 * @param a The annotation class type. 2480 * @param t The class being searched. 2481 * @return The found matches, or an empty map if annotation was not found. 2482 */ 2483 public static <T extends Annotation> LinkedHashMap<Class<?>,T> getAnnotationsMapParentFirst(Class<T> a, Type t) { 2484 return CollectionUtils.reverse(getAnnotationsMap(a, t)); 2485 } 2486 2487 private static <T extends Annotation> void findAnnotationsMap(Class<T> a, Type t, Map<Class<?>,T> m) { 2488 Class<?> c = toClass(t); 2489 if (c != null) { 2490 2491 T t2 = getDeclaredAnnotation(a, c); 2492 if (t2 != null) 2493 m.put(c, t2); 2494 2495 findAnnotationsMap(a, c.getSuperclass(), m); 2496 2497 for (Class<?> c2 : c.getInterfaces()) 2498 findAnnotationsMap(a, c2, m); 2499 } 2500 } 2501 2502 /** 2503 * Finds and appends the specified annotation on the specified class and superclasses/interfaces to the specified 2504 * list. 2505 * 2506 * @param a The annotation. 2507 * @param t The class. 2508 * @param l The list of annotations. 2509 */ 2510 public static <T extends Annotation> void appendAnnotations(Class<T> a, Type t, List<T> l) { 2511 Class<?> c = toClass(t); 2512 if (c != null) { 2513 addIfNotNull(l, getDeclaredAnnotation(a, c)); 2514 2515 if (c.getPackage() != null) 2516 addIfNotNull(l, c.getPackage().getAnnotation(a)); 2517 2518 appendAnnotations(a, c.getSuperclass(), l); 2519 2520 for (Class<?> c2 : c.getInterfaces()) 2521 appendAnnotations(a, c2, l); 2522 } 2523 } 2524 2525 /** 2526 * Returns the specified type as a <code>Class</code>. 2527 * 2528 * <p> 2529 * If it's already a <code>Class</code>, it just does a cast. 2530 * <br>If it's a <code>ParameterizedType</code>, it returns the raw type. 2531 * 2532 * @param t The type to convert. 2533 * @return The type converted to a <code>Class</code>, or <jk>null</jk> if it could not be converted. 2534 */ 2535 public static Class<?> toClass(Type t) { 2536 if (t instanceof Class) 2537 return (Class<?>)t; 2538 if (t instanceof ParameterizedType) { 2539 ParameterizedType pt = (ParameterizedType)t; 2540 // The raw type should always be a class (right?) 2541 return (Class<?>)pt.getRawType(); 2542 } 2543 return null; 2544 } 2545 2546 /** 2547 * Similar to {@link Class#getResourceAsStream(String)} except looks up the parent hierarchy for the existence of 2548 * the specified resource. 2549 * 2550 * @param c The class to return the resource on. 2551 * @param name The resource name. 2552 * @return An input stream on the specified resource, or <jk>null</jk> if the resource could not be found. 2553 */ 2554 public static InputStream getResource(Class<?> c, String name) { 2555 if (name == null) 2556 return null; 2557 while (c != null) { 2558 InputStream is = c.getResourceAsStream(name); 2559 if (is != null) 2560 return is; 2561 c = c.getSuperclass(); 2562 } 2563 return null; 2564 } 2565}