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 // Method annotations. 1133 //----------------------------------------------------------------------------------------------------------------- 1134 1135 /** 1136 * Returns all annotations of the specified type defined on the specified method. 1137 * 1138 * @param a 1139 * The annotation to search for. 1140 * @param m 1141 * The method to find the annotation on. 1142 * @param searchParentMethods 1143 * If <jk>true</jk>, searches methods with the same signature on the parent classes or interfaces. 1144 * @param searchReturnType 1145 * If <jk>true</jk>, searches the return type on the method for the specified annotation. 1146 * @param parentFirst 1147 * If <jk>true</jk>, returns the results in parent-to-child order. 1148 * @return 1149 * A list of all matching annotations found, or an empty list if none found. 1150 */ 1151 @SuppressWarnings("unchecked") 1152 public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m, boolean searchParentMethods, boolean searchReturnType, boolean parentFirst) { 1153 List<T> l = new ArrayList<>(); 1154 List<Method> methods = searchParentMethods ? findMatchingMethods(m) : Collections.singletonList(m); 1155 for (Method m2 : methods) 1156 for (Annotation a2 : m2.getAnnotations()) 1157 if (a.isInstance(a2)) 1158 l.add((T)a2); 1159 if (searchReturnType) { 1160 Type t = m.getGenericReturnType(); 1161 if (Value.isType(t)) 1162 appendAnnotations(a, Value.getParameterType(t), l); 1163 else 1164 appendAnnotations(a, t, l); 1165 } 1166 if (parentFirst) 1167 Collections.reverse(l); 1168 return l; 1169 } 1170 1171 /** 1172 * Shortcut for calling <code>getAnnotations(a, m, <jk>true</jk>, <jk>true</jk>, <jk>false</jk>);</code> 1173 * 1174 * <p> 1175 * Annotations are ordered method first, then return class, then return superclasses. 1176 * 1177 * @param a The annotation to look for. 1178 * @param m The method being inspected. 1179 * @return All instances of the annotation with the 1180 */ 1181 public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m) { 1182 return getAnnotations(a, m, true, true, false); 1183 } 1184 1185 /** 1186 * Shortcut for calling <code>getAnnotations(a, m, <jk>true</jk>, <jk>true</jk>, <jk>true</jk>);</code> 1187 * 1188 * @param a The annotation to look for. 1189 * @param m The method being inspected. 1190 * @return All instances of the annotation with the 1191 */ 1192 public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Method m) { 1193 return getAnnotations(a, m, true, true, true); 1194 } 1195 1196 /** 1197 * Finds the annotation of the specified type defined on the specified method. 1198 * 1199 * @param a 1200 * The annotation to search for. 1201 * @param m 1202 * The method to find the annotation on. 1203 * @param searchParentMethods 1204 * If <jk>true</jk>, searches methods with the same signature on the parent classes or interfaces. 1205 * <br>The search is performed in child-to-parent order. 1206 * @param searchReturnType 1207 * If <jk>true</jk>, searches the return type on the method for the specified annotation. 1208 * @return 1209 * The annotation if found, or <jk>null</jk> if not. 1210 */ 1211 @SuppressWarnings("unchecked") 1212 public static <T extends Annotation> T getAnnotation(Class<T> a, Method m, boolean searchParentMethods, boolean searchReturnType) { 1213 List<Method> methods = searchParentMethods ? findMatchingMethods(m) : Collections.singletonList(m); 1214 for (Method m2 : methods) 1215 for (Annotation a2 : m2.getAnnotations()) 1216 if (a.isInstance(a2)) 1217 return (T)a2; 1218 if (searchReturnType) { 1219 Type t = m.getGenericReturnType(); 1220 if (Value.isType(t)) 1221 return getAnnotation(a, Value.getParameterType(t)); 1222 return getAnnotation(a, t); 1223 } 1224 return null; 1225 } 1226 1227 /** 1228 * Shortcut for calling <code>getAnnotation(a, m, true, true); 1229 * 1230 * @param a 1231 * The annotation to search for. 1232 * @param m 1233 * The method to find the annotation on. 1234 * @return 1235 * The annotation if found, or <jk>null</jk> if not. 1236 */ 1237 public static <T extends Annotation> T getAnnotation(Class<T> a, Method m) { 1238 return getAnnotation(a, m, true, true); 1239 } 1240 1241 //----------------------------------------------------------------------------------------------------------------- 1242 // Method argument annotations. 1243 //----------------------------------------------------------------------------------------------------------------- 1244 1245 /** 1246 * Returns all annotations of the specified type defined on the specified method argument. 1247 * 1248 * @param a 1249 * The annotation to search for. 1250 * @param m 1251 * The method containing the argument to find the annotation on. 1252 * @param index 1253 * The argument index position. 1254 * @param searchParentMethods 1255 * If <jk>true</jk>, searches methods with the same signature on the parent classes or interfaces. 1256 * @param searchArgType 1257 * If <jk>true</jk>, searches the argument type for the specified annotation. 1258 * @param parentFirst 1259 * If <jk>true</jk>, returns the results in parent-to-child order. 1260 * @return 1261 * A list of all matching annotations found, or an empty list if none found. 1262 */ 1263 @SuppressWarnings("unchecked") 1264 public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m, int index, boolean searchParentMethods, boolean searchArgType, boolean parentFirst) { 1265 List<T> l = new ArrayList<>(); 1266 List<Method> methods = searchParentMethods ? findMatchingMethods(m) : Collections.singletonList(m); 1267 for (Method m2 : methods) 1268 for (Annotation a2 : m2.getParameterAnnotations()[index]) 1269 if (a.isInstance(a2)) 1270 l.add((T)a2); 1271 if (searchArgType) { 1272 Type t = m.getGenericParameterTypes()[index]; 1273 if (Value.isType(t)) 1274 appendAnnotations(a, Value.getParameterType(t), l); 1275 else 1276 appendAnnotations(a, t, l); 1277 } 1278 if (parentFirst) 1279 Collections.reverse(l); 1280 return l; 1281 } 1282 1283 /** 1284 * Finds the annotation of the specified type defined on the specified method argument. 1285 * 1286 * @param a 1287 * The annotation to search for. 1288 * @param m 1289 * The method containing the argument to find the annotation on. 1290 * @param index 1291 * The argument index position. 1292 * @param searchParentMethods 1293 * If <jk>true</jk>, searches methods with the same signature on the parent classes or interfaces. 1294 * <br>The search is performed in child-to-parent order. 1295 * @param searchArgType 1296 * If <jk>true</jk>, searches the argument type for the specified annotation. 1297 * @return 1298 * The annotation if found, or <jk>null</jk> if not. 1299 */ 1300 @SuppressWarnings("unchecked") 1301 public static <T extends Annotation> T getAnnotation(Class<T> a, Method m, int index, boolean searchParentMethods, boolean searchArgType) { 1302 List<Method> methods = searchParentMethods ? findMatchingMethods(m) : Collections.singletonList(m); 1303 for (Method m2 : methods) 1304 for (Annotation a2 : m2.getParameterAnnotations()[index]) 1305 if (a.isInstance(a2)) 1306 return (T)a2; 1307 if (searchArgType) { 1308 Type t = m.getGenericParameterTypes()[index]; 1309 if (Value.isType(t)) 1310 return getAnnotation(a, Value.getParameterType(t)); 1311 return getAnnotation(a, t); 1312 } 1313 return null; 1314 } 1315 1316 /** 1317 * Shortcut for calling <code>getAnnotation(a, m, index, <jk>true</jk>, <jk>true</jk>);</code> 1318 * 1319 * @param a The annotation to check for. 1320 * @param m The method containing the parameter to check. 1321 * @param index The parameter index. 1322 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value. 1323 */ 1324 public static <T extends Annotation> T getAnnotation(Class<T> a, Method m, int index) { 1325 return getAnnotation(a, m, index, true, true); 1326 } 1327 1328 /** 1329 * Shortcut for calling <code>getAnnotations(a, m, index, <jk>true</jk>, <jk>true</jk>, <jk>false</jk>);</code> 1330 * 1331 * @param a The annotation to look for. 1332 * @param m The method containing the parameter. 1333 * @param index The parameter index. 1334 * @return All instances of the annotation with the 1335 */ 1336 public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Method m, int index) { 1337 return getAnnotations(a, m, index, true, true, false); 1338 } 1339 1340 /** 1341 * Shortcut for calling <code>getAnnotations(a, m, index, <jk>true</jk>, <jk>true</jk>, <jk>true</jk>);</code> 1342 * 1343 * @param a The annotation to look for. 1344 * @param m The method containing the parameter. 1345 * @param index The parameter index. 1346 * @return All instances of the annotation with the 1347 */ 1348 public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Method m, int index) { 1349 return getAnnotations(a, m, index, true, true, true); 1350 } 1351 1352 /** 1353 * Given a specific method, finds all declared methods with the same name and arguments on all 1354 * superclasses and interfaces. 1355 * 1356 * @param m The method to find matches against. 1357 * @return 1358 * All matching methods including the input method itself. 1359 * Methods are ordered from child-to-parent order. 1360 */ 1361 public static List<Method> findMatchingMethods(Method m) { 1362 return findMatchingMethods(new ArrayList<Method>(), m); 1363 } 1364 1365 private static List<Method> findMatchingMethods(List<Method> l, Method m) { 1366 l.add(m); 1367 Class<?> c = m.getDeclaringClass(); 1368 Class<?> pc = c.getSuperclass(); 1369 if (pc != null) 1370 for (Method m2 : pc.getDeclaredMethods()) 1371 if (isSameMethod(m, m2)) 1372 findMatchingMethods(l, m2); 1373 for (Class<?> ic : c.getInterfaces()) 1374 for (Method m2 : ic.getDeclaredMethods()) 1375 if (isSameMethod(m, m2)) 1376 findMatchingMethods(l, m2); 1377 return l; 1378 } 1379 1380 private static boolean isSameMethod(Method m1, Method m2) { 1381 return m1.getName().equals(m2.getName()) && Arrays.equals(m1.getParameterTypes(), m2.getParameterTypes()); 1382 } 1383 1384 /** 1385 * Locates the no-arg constructor for the specified class. 1386 * 1387 * <p> 1388 * Constructor must match the visibility requirements specified by parameter 'v'. 1389 * If class is abstract, always returns <jk>null</jk>. 1390 * Note that this also returns the 1-arg constructor for non-static member classes. 1391 * 1392 * @param c The class from which to locate the no-arg constructor. 1393 * @param v The minimum visibility. 1394 * @return The constructor, or <jk>null</jk> if no no-arg constructor exists with the required visibility. 1395 */ 1396 @SuppressWarnings({"rawtypes","unchecked"}) 1397 public static final <T> Constructor<T> findNoArgConstructor(Class<T> c, Visibility v) { 1398 int mod = c.getModifiers(); 1399 if (Modifier.isAbstract(mod)) 1400 return null; 1401 boolean isMemberClass = c.isMemberClass() && ! isStatic(c); 1402 for (Constructor cc : c.getConstructors()) { 1403 mod = cc.getModifiers(); 1404 if (hasNumArgs(cc, isMemberClass ? 1 : 0) && v.isVisible(mod) && isNotDeprecated(cc)) 1405 return v.transform(cc); 1406 } 1407 return null; 1408 } 1409 1410 /** 1411 * Finds the real parameter type of the specified class. 1412 * 1413 * @param c The class containing the parameters (e.g. PojoSwap<T,S>) 1414 * @param index The zero-based index of the parameter to resolve. 1415 * @param oc The class we're trying to resolve the parameter type for. 1416 * @return The resolved real class. 1417 */ 1418 public static Class<?> resolveParameterType(Class<?> c, int index, Class<?> oc) { 1419 1420 // We need to make up a mapping of type names. 1421 Map<Type,Type> typeMap = new HashMap<>(); 1422 while (c != oc.getSuperclass()) { 1423 extractTypes(typeMap, oc); 1424 oc = oc.getSuperclass(); 1425 } 1426 1427 Type gsc = oc.getGenericSuperclass(); 1428 1429 // Not actually a parameterized type. 1430 if (! (gsc instanceof ParameterizedType)) 1431 return Object.class; 1432 1433 ParameterizedType opt = (ParameterizedType)gsc; 1434 Type actualType = opt.getActualTypeArguments()[index]; 1435 1436 if (typeMap.containsKey(actualType)) 1437 actualType = typeMap.get(actualType); 1438 1439 if (actualType instanceof Class) { 1440 return (Class<?>)actualType; 1441 1442 } else if (actualType instanceof GenericArrayType) { 1443 Class<?> cmpntType = (Class<?>)((GenericArrayType)actualType).getGenericComponentType(); 1444 return Array.newInstance(cmpntType, 0).getClass(); 1445 1446 } else if (actualType instanceof TypeVariable) { 1447 TypeVariable<?> typeVariable = (TypeVariable<?>)actualType; 1448 List<Class<?>> nestedOuterTypes = new LinkedList<>(); 1449 for (Class<?> ec = oc.getEnclosingClass(); ec != null; ec = ec.getEnclosingClass()) { 1450 try { 1451 Class<?> outerClass = oc.getClass(); 1452 nestedOuterTypes.add(outerClass); 1453 Map<Type,Type> outerTypeMap = new HashMap<>(); 1454 extractTypes(outerTypeMap, outerClass); 1455 for (Map.Entry<Type,Type> entry : outerTypeMap.entrySet()) { 1456 Type key = entry.getKey(), value = entry.getValue(); 1457 if (key instanceof TypeVariable) { 1458 TypeVariable<?> keyType = (TypeVariable<?>)key; 1459 if (keyType.getName().equals(typeVariable.getName()) && isInnerClass(keyType.getGenericDeclaration(), typeVariable.getGenericDeclaration())) { 1460 if (value instanceof Class) 1461 return (Class<?>)value; 1462 typeVariable = (TypeVariable<?>)entry.getValue(); 1463 } 1464 } 1465 } 1466 } catch (Exception e) { 1467 throw new RuntimeException(e); 1468 } 1469 } 1470 throw new FormattedRuntimeException("Could not resolve type: {0}", actualType); 1471 } else { 1472 throw new FormattedRuntimeException("Invalid type found in resolveParameterType: {0}", actualType); 1473 } 1474 } 1475 1476 /** 1477 * Invokes the specified method using fuzzy-arg matching. 1478 * 1479 * <p> 1480 * Arguments will be matched to the parameters based on the parameter types. 1481 * <br>Arguments can be in any order. 1482 * <br>Extra arguments will be ignored. 1483 * <br>Missing arguments will be left <jk>null</jk>. 1484 * 1485 * <p> 1486 * Note that this only works for methods that have distinguishable argument types. 1487 * <br>It's not going to work on methods with generic argument types like <code>Object</code> 1488 * 1489 * @param m The method being called. 1490 * @param pojo 1491 * The POJO the method is being called on. 1492 * <br>Can be <jk>null</jk> for static methods. 1493 * @param args 1494 * The arguments to pass to the method. 1495 * @return 1496 * The results of the method invocation. 1497 * @throws Exception 1498 */ 1499 public static Object invokeMethodFuzzy(Method m, Object pojo, Object...args) throws Exception { 1500 return m.invoke(pojo, getMatchingArgs(m.getParameterTypes(), args)); 1501 } 1502 1503 /** 1504 * Invokes the specified constructor using fuzzy-arg matching. 1505 * 1506 * <p> 1507 * Arguments will be matched to the parameters based on the parameter types. 1508 * <br>Arguments can be in any order. 1509 * <br>Extra arguments will be ignored. 1510 * <br>Missing arguments will be left <jk>null</jk>. 1511 * 1512 * <p> 1513 * Note that this only works for constructors that have distinguishable argument types. 1514 * <br>It's not going to work on constructors with generic argument types like <code>Object</code> 1515 * 1516 * @param c The constructor being called. 1517 * @param args 1518 * The arguments to pass to the constructor. 1519 * @return 1520 * The results of the method invocation. 1521 * @throws Exception 1522 */ 1523 public static <T> T invokeConstructorFuzzy(Constructor<T> c, Object...args) throws Exception { 1524 return c.newInstance(getMatchingArgs(c.getParameterTypes(), args)); 1525 } 1526 1527 private static boolean isInnerClass(GenericDeclaration od, GenericDeclaration id) { 1528 if (od instanceof Class && id instanceof Class) { 1529 Class<?> oc = (Class<?>)od; 1530 Class<?> ic = (Class<?>)id; 1531 while ((ic = ic.getEnclosingClass()) != null) 1532 if (ic == oc) 1533 return true; 1534 } 1535 return false; 1536 } 1537 1538 private static void extractTypes(Map<Type,Type> typeMap, Class<?> c) { 1539 Type gs = c.getGenericSuperclass(); 1540 if (gs instanceof ParameterizedType) { 1541 ParameterizedType pt = (ParameterizedType)gs; 1542 Type[] typeParameters = ((Class<?>)pt.getRawType()).getTypeParameters(); 1543 Type[] actualTypeArguments = pt.getActualTypeArguments(); 1544 for (int i = 0; i < typeParameters.length; i++) { 1545 if (typeMap.containsKey(actualTypeArguments[i])) 1546 actualTypeArguments[i] = typeMap.get(actualTypeArguments[i]); 1547 typeMap.put(typeParameters[i], actualTypeArguments[i]); 1548 } 1549 } 1550 } 1551 1552 /** 1553 * Finds a public method with the specified parameters. 1554 * 1555 * @param c The class to look for the method. 1556 * @param name The method name. 1557 * @param returnType 1558 * The return type of the method. 1559 * Can be a super type of the actual return type. 1560 * For example, if the actual return type is <code>CharSequence</code>, then <code>Object</code> will match but 1561 * <code>String</code> will not. 1562 * @param argTypes 1563 * The argument types of the method. 1564 * Can be subtypes of the actual parameter types. 1565 * For example, if the parameter type is <code>CharSequence</code>, then <code>String</code> will match but 1566 * <code>Object</code> will not. 1567 * @return The matched method, or <jk>null</jk> if no match was found. 1568 */ 1569 public static Method findPublicMethod(Class<?> c, String name, Class<?> returnType, Class<?>...argTypes) { 1570 for (Method m : c.getMethods()) { 1571 if (isPublic(m) && hasName(m, name) && hasReturnTypeParent(m, returnType) && argsMatch(m.getParameterTypes(), argTypes)) 1572 return m; 1573 } 1574 return null; 1575 } 1576 1577 /** 1578 * Finds a public constructor with the specified parameters without throwing an exception. 1579 * 1580 * @param c The class to search for a constructor. 1581 * @param fuzzyArgs 1582 * Use fuzzy-arg matching. 1583 * Find a constructor that best matches the specified args. 1584 * @param argTypes 1585 * The argument types in the constructor. 1586 * Can be subtypes of the actual constructor argument types. 1587 * @return The matching constructor, or <jk>null</jk> if constructor could not be found. 1588 */ 1589 public static <T> Constructor<T> findPublicConstructor(Class<T> c, boolean fuzzyArgs, Class<?>...argTypes) { 1590 return findConstructor(c, Visibility.PUBLIC, fuzzyArgs, argTypes); 1591 } 1592 1593 /** 1594 * Finds a constructor with the specified parameters without throwing an exception. 1595 * 1596 * @param c The class to search for a constructor. 1597 * @param vis The minimum visibility. 1598 * @param fuzzyArgs 1599 * Use fuzzy-arg matching. 1600 * Find a constructor that best matches the specified args. 1601 * @param argTypes 1602 * The argument types in the constructor. 1603 * Can be subtypes of the actual constructor argument types. 1604 * @return The matching constructor, or <jk>null</jk> if constructor could not be found. 1605 */ 1606 @SuppressWarnings("unchecked") 1607 public static <T> Constructor<T> findConstructor(Class<T> c, Visibility vis, boolean fuzzyArgs, Class<?>...argTypes) { 1608 ConstructorCacheEntry cce = CONSTRUCTOR_CACHE.get(c); 1609 if (cce != null && argsMatch(cce.paramTypes, argTypes) && cce.isVisible(vis)) 1610 return (Constructor<T>)cce.constructor; 1611 1612 if (fuzzyArgs) { 1613 int bestCount = -1; 1614 Constructor<?> bestMatch = null; 1615 for (Constructor<?> n : c.getDeclaredConstructors()) { 1616 if (vis.isVisible(n)) { 1617 int m = fuzzyArgsMatch(n.getParameterTypes(), argTypes); 1618 if (m > bestCount) { 1619 bestCount = m; 1620 bestMatch = n; 1621 } 1622 } 1623 } 1624 if (bestCount >= 0) 1625 CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, bestMatch)); 1626 return (Constructor<T>)bestMatch; 1627 } 1628 1629 final boolean isMemberClass = c.isMemberClass() && ! isStatic(c); 1630 for (Constructor<?> n : c.getConstructors()) { 1631 Class<?>[] paramTypes = n.getParameterTypes(); 1632 if (isMemberClass) 1633 paramTypes = Arrays.copyOfRange(paramTypes, 1, paramTypes.length); 1634 if (argsMatch(paramTypes, argTypes) && vis.isVisible(n)) { 1635 CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, n)); 1636 return (Constructor<T>)n; 1637 } 1638 } 1639 1640 return null; 1641 } 1642 1643 1644 1645 private static final class ConstructorCacheEntry { 1646 final Constructor<?> constructor; 1647 final Class<?>[] paramTypes; 1648 1649 ConstructorCacheEntry(Class<?> forClass, Constructor<?> constructor) { 1650 this.constructor = constructor; 1651 this.paramTypes = constructor.getParameterTypes(); 1652 } 1653 1654 boolean isVisible(Visibility vis) { 1655 return vis.isVisible(constructor); 1656 } 1657 } 1658 1659 /** 1660 * Returns <jk>true</jk> if the specified argument types are valid for the specified parameter types. 1661 * 1662 * @param paramTypes The parameters types specified on a method. 1663 * @param argTypes The class types of the arguments being passed to the method. 1664 * @return <jk>true</jk> if the arguments match the parameters. 1665 */ 1666 public static boolean argsMatch(Class<?>[] paramTypes, Class<?>[] argTypes) { 1667 if (paramTypes.length == argTypes.length) { 1668 for (int i = 0; i < paramTypes.length; i++) 1669 if (! isParentClass(paramTypes[i], argTypes[i])) 1670 return false; 1671 return true; 1672 } 1673 return false; 1674 } 1675 1676 /** 1677 * Returns a number representing the number of arguments that match the specified parameters. 1678 * 1679 * @param paramTypes The parameters types specified on a method. 1680 * @param argTypes The class types of the arguments being passed to the method. 1681 * @return The number of matching arguments, or <code>-1</code> a parameter was found that isn't in the list of args. 1682 */ 1683 public static int fuzzyArgsMatch(Class<?>[] paramTypes, Class<?>... argTypes) { 1684 int matches = 0; 1685 outer: for (Class<?> p : paramTypes) { 1686 p = getWrapperIfPrimitive(p); 1687 for (Class<?> a : argTypes) { 1688 if (isParentClass(p, a)) { 1689 matches++; 1690 continue outer; 1691 } 1692 } 1693 return -1; 1694 } 1695 return matches; 1696 } 1697 1698 /** 1699 * Finds the public constructor that can take in the specified arguments. 1700 * 1701 * @param c The class we're trying to construct. 1702 * @param args The arguments we want to pass into the constructor. 1703 * @return 1704 * The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified 1705 * arguments. 1706 */ 1707 public static <T> Constructor<T> findPublicConstructor(Class<T> c, Object...args) { 1708 return findPublicConstructor(c, false, getClasses(args)); 1709 } 1710 1711 /** 1712 * Finds the public constructor that can take in the specified arguments. 1713 * 1714 * @param c The class we're trying to construct. 1715 * @param args The argument types we want to pass into the constructor. 1716 * @return 1717 * The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified 1718 * arguments. 1719 */ 1720 public static <T> Constructor<T> findPublicConstructor(Class<T> c, Class<?>...args) { 1721 return findPublicConstructor(c, false, args); 1722 } 1723 1724 /** 1725 * Finds the public constructor that can take in the specified arguments. 1726 * 1727 * @param c The class we're trying to construct. 1728 * @param fuzzyArgs 1729 * Use fuzzy-arg matching. 1730 * Find a constructor that best matches the specified args. 1731 * @param args The arguments we want to pass into the constructor. 1732 * @return 1733 * The constructor, or <jk>null</jk> if a public constructor could not be found that takes in the specified 1734 * arguments. 1735 */ 1736 public static <T> Constructor<T> findPublicConstructor(Class<T> c, boolean fuzzyArgs, Object...args) { 1737 return findPublicConstructor(c, fuzzyArgs, getClasses(args)); 1738 } 1739 1740 /** 1741 * Returns the class types for the specified arguments. 1742 * 1743 * @param args The objects we're getting the classes of. 1744 * @return The classes of the arguments. 1745 */ 1746 public static Class<?>[] getClasses(Object...args) { 1747 Class<?>[] pt = new Class<?>[args.length]; 1748 for (int i = 0; i < args.length; i++) 1749 pt[i] = args[i] == null ? null : args[i].getClass(); 1750 return pt; 1751 } 1752 1753 /** 1754 * Returns a {@link MethodInfo} bean that describes the specified method. 1755 * 1756 * @param m The method to describe. 1757 * @return The bean with information about the method. 1758 */ 1759 public static MethodInfo getMethodInfo(Method m) { 1760 return new MethodInfo(m); 1761 } 1762 1763 /** 1764 * Returns {@link MethodInfo} beans that describe the specified methods. 1765 * 1766 * @param m The methods to describe. 1767 * @return The beans with information about the methods. 1768 */ 1769 public static MethodInfo[] getMethodInfo(Collection<Method> m) { 1770 MethodInfo[] mi = new MethodInfo[m.size()]; 1771 int i = 0; 1772 for (Method mm : m) 1773 mi[i++] = getMethodInfo(mm); 1774 return mi; 1775 } 1776 1777 /** 1778 * Simple bean that shows the name, parameter types, and return type of a method. 1779 */ 1780 @SuppressWarnings("javadoc") 1781 public static class MethodInfo { 1782 public final String methodName; 1783 public final String[] parameterTypes; 1784 public final String returnType; 1785 1786 MethodInfo(Method m) { 1787 methodName = m.getName(); 1788 Type[] pt = m.getGenericParameterTypes(); 1789 parameterTypes = new String[pt.length]; 1790 for (int i = 0; i < pt.length; i++) 1791 parameterTypes[i] = BeanContext.DEFAULT.getClassMeta(pt[i]).toString(); 1792 returnType = BeanContext.DEFAULT.getClassMeta(m.getGenericReturnType()).toString(); 1793 } 1794 } 1795 1796 /** 1797 * Creates an instance of the specified class. 1798 * 1799 * @param c 1800 * The class to cast to. 1801 * @param c2 1802 * The class to instantiate. 1803 * Can also be an instance of the class. 1804 * @return 1805 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1806 * @throws 1807 * RuntimeException if constructor could not be found or called. 1808 */ 1809 public static <T> T newInstance(Class<T> c, Object c2) { 1810 return newInstanceFromOuter(null, c, c2, false); 1811 } 1812 1813 /** 1814 * Creates an instance of the specified class. 1815 * 1816 * @param c 1817 * The class to cast to. 1818 * @param c2 1819 * The class to instantiate. 1820 * Can also be an instance of the class. 1821 * @param fuzzyArgs 1822 * Use fuzzy constructor arg matching. 1823 * <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored. 1824 * <br>No-arg constructors are also used if no other constructors are found. 1825 * @param args 1826 * The arguments to pass to the constructor. 1827 * @return 1828 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1829 * @throws 1830 * RuntimeException if constructor could not be found or called. 1831 */ 1832 public static <T> T newInstance(Class<T> c, Object c2, boolean fuzzyArgs, Object...args) { 1833 return newInstanceFromOuter(null, c, c2, fuzzyArgs, args); 1834 } 1835 1836 /** 1837 * Creates an instance of the specified class from within the context of another object. 1838 * 1839 * @param outer 1840 * The outer object. 1841 * Can be <jk>null</jk>. 1842 * @param c 1843 * The class to cast to. 1844 * @param c2 1845 * The class to instantiate. 1846 * Can also be an instance of the class. 1847 * @param fuzzyArgs 1848 * Use fuzzy constructor arg matching. 1849 * <br>When <jk>true</jk>, constructor args can be in any order and extra args are ignored. 1850 * <br>No-arg constructors are also used if no other constructors are found. 1851 * @param args 1852 * The arguments to pass to the constructor. 1853 * @return 1854 * The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface. 1855 * @throws 1856 * RuntimeException if constructor could not be found or called. 1857 */ 1858 @SuppressWarnings("unchecked") 1859 public static <T> T newInstanceFromOuter(Object outer, Class<T> c, Object c2, boolean fuzzyArgs, Object...args) { 1860 if (c2 == null) 1861 return null; 1862 if (c2 instanceof Class) { 1863 try { 1864 Class<?> c3 = (Class<?>)c2; 1865 if (c3.isInterface() || isAbstract(c3)) 1866 return null; 1867 1868 // First look for an exact match. 1869 Constructor<?> con = findPublicConstructor(c3, false, args); 1870 if (con != null) 1871 return (T)con.newInstance(args); 1872 1873 // Next look for an exact match including the outer. 1874 if (outer != null) { 1875 args = new AList<>().append(outer).appendAll(args).toArray(); 1876 con = findPublicConstructor(c3, false, args); 1877 if (con != null) 1878 return (T)con.newInstance(args); 1879 } 1880 1881 // Finally use fuzzy matching. 1882 if (fuzzyArgs) { 1883 con = findPublicConstructor(c3, true, args); 1884 if (con != null) 1885 return (T)con.newInstance(getMatchingArgs(con.getParameterTypes(), args)); 1886 } 1887 1888 throw new FormattedRuntimeException("Could not instantiate class {0}/{1}. Constructor not found.", c.getName(), c2); 1889 } catch (Exception e) { 1890 throw new FormattedRuntimeException(e, "Could not instantiate class {0}", c.getName()); 1891 } 1892 } else if (isParentClass(c, c2.getClass())) { 1893 return (T)c2; 1894 } else { 1895 throw new FormattedRuntimeException("Object of type {0} found but was expecting {1}.", c2.getClass(), c.getClass()); 1896 } 1897 } 1898 1899 /** 1900 * Matches arguments to a list of parameter types. 1901 * 1902 * <p> 1903 * Extra parameters are ignored. 1904 * <br>Missing parameters are left null. 1905 * 1906 * @param paramTypes The parameter types. 1907 * @param args The arguments to match to the parameter types. 1908 * @return 1909 * An array of parameters. 1910 */ 1911 public static Object[] getMatchingArgs(Class<?>[] paramTypes, Object... args) { 1912 Object[] params = new Object[paramTypes.length]; 1913 for (int i = 0; i < paramTypes.length; i++) { 1914 Class<?> pt = getWrapperIfPrimitive(paramTypes[i]); 1915 for (int j = 0; j < args.length; j++) { 1916 if (isParentClass(pt, args[j].getClass())) { 1917 params[i] = args[j]; 1918 break; 1919 } 1920 } 1921 } 1922 return params; 1923 } 1924 1925 /** 1926 * Returns all the fields in the specified class and all parent classes. 1927 * 1928 * <p> 1929 * Fields are ordered in either parent-to-child, or child-to-parent order, then alphabetically. 1930 * 1931 * @param c The class to get all fields on. 1932 * @param parentFirst Order them in parent-class-to-child-class order, otherwise child-class-to-parent-class order. 1933 * @return An iterable of all fields in the specified class. 1934 */ 1935 @SuppressWarnings("rawtypes") 1936 public static Iterable<Field> getAllFields(final Class c, final boolean parentFirst) { 1937 return new Iterable<Field>() { 1938 @Override 1939 public Iterator<Field> iterator() { 1940 return new Iterator<Field>(){ 1941 final Iterator<Class<?>> classIterator = getParentClasses(c, parentFirst, false); 1942 Field[] fields = classIterator.hasNext() ? sort(classIterator.next().getDeclaredFields()) : new Field[0]; 1943 int fIndex = 0; 1944 Field next; 1945 1946 @Override 1947 public boolean hasNext() { 1948 prime(); 1949 return next != null; 1950 } 1951 1952 private void prime() { 1953 if (next == null) { 1954 while (fIndex >= fields.length) { 1955 if (classIterator.hasNext()) { 1956 fields = sort(classIterator.next().getDeclaredFields()); 1957 fIndex = 0; 1958 } else { 1959 fIndex = -1; 1960 } 1961 } 1962 if (fIndex != -1) 1963 next = fields[fIndex++]; 1964 } 1965 } 1966 1967 @Override 1968 public Field next() { 1969 prime(); 1970 Field f = next; 1971 next = null; 1972 return f; 1973 } 1974 1975 @Override 1976 public void remove() { 1977 } 1978 }; 1979 } 1980 }; 1981 } 1982 1983 /** 1984 * Returns all the methods in the specified class and all parent classes. 1985 * 1986 * <p> 1987 * Methods are ordered in either parent-to-child, or child-to-parent order, then alphabetically. 1988 * 1989 * @param c The class to get all methods on. 1990 * @param parentFirst Order them in parent-class-to-child-class order, otherwise child-class-to-parent-class order. 1991 * @return An iterable of all methods in the specified class. 1992 */ 1993 @SuppressWarnings("rawtypes") 1994 public static Iterable<Method> getAllMethods(final Class c, final boolean parentFirst) { 1995 return new Iterable<Method>() { 1996 @Override 1997 public Iterator<Method> iterator() { 1998 return new Iterator<Method>(){ 1999 final Iterator<Class<?>> classIterator = getParentClasses(c, parentFirst, true); 2000 Method[] methods = classIterator.hasNext() ? sort(classIterator.next().getDeclaredMethods()) : new Method[0]; 2001 int mIndex = 0; 2002 Method next; 2003 2004 @Override 2005 public boolean hasNext() { 2006 prime(); 2007 return next != null; 2008 } 2009 2010 private void prime() { 2011 if (next == null) { 2012 while (mIndex >= methods.length) { 2013 if (classIterator.hasNext()) { 2014 methods = sort(classIterator.next().getDeclaredMethods()); 2015 mIndex = 0; 2016 } else { 2017 mIndex = -1; 2018 } 2019 } 2020 if (mIndex != -1) 2021 next = methods[mIndex++]; 2022 } 2023 } 2024 2025 @Override 2026 public Method next() { 2027 prime(); 2028 Method m = next; 2029 next = null; 2030 return m; 2031 } 2032 2033 @Override 2034 public void remove() { 2035 } 2036 }; 2037 } 2038 }; 2039 } 2040 2041 private static Comparator<Method> METHOD_COMPARATOR = new Comparator<Method>() { 2042 2043 @Override 2044 public int compare(Method o1, Method o2) { 2045 int i = o1.getName().compareTo(o2.getName()); 2046 if (i == 0) { 2047 i = o1.getParameterTypes().length - o2.getParameterTypes().length; 2048 if (i == 0) { 2049 for (int j = 0; j < o1.getParameterTypes().length && i == 0; j++) { 2050 i = o1.getParameterTypes()[j].getName().compareTo(o2.getParameterTypes()[j].getName()); 2051 } 2052 } 2053 } 2054 return i; 2055 } 2056 }; 2057 2058 /** 2059 * Sorts methods in alphabetical order. 2060 * 2061 * @param m The methods to sort. 2062 * @return The same array, but with elements sorted. 2063 */ 2064 public static Method[] sort(Method[] m) { 2065 Arrays.sort(m, METHOD_COMPARATOR); 2066 return m; 2067 } 2068 2069 private static Comparator<Field> FIELD_COMPARATOR = new Comparator<Field>() { 2070 2071 @Override 2072 public int compare(Field o1, Field o2) { 2073 return o1.getName().compareTo(o2.getName()); 2074 } 2075 }; 2076 2077 /** 2078 * Sorts methods in alphabetical order. 2079 * 2080 * @param m The methods to sort. 2081 * @return The same array, but with elements sorted. 2082 */ 2083 public static Field[] sort(Field[] m) { 2084 Arrays.sort(m, FIELD_COMPARATOR); 2085 return m; 2086 } 2087 2088 /** 2089 * Returns a list of all the parent classes of the specified class including the class itself. 2090 * 2091 * @param c The class to retrieve the parent classes. 2092 * @param parentFirst In parent-to-child order, otherwise child-to-parent. 2093 * @param includeInterfaces Include interfaces. 2094 * @return An iterator of parent classes in the class hierarchy. 2095 */ 2096 public static Iterator<Class<?>> getParentClasses(final Class<?> c, boolean parentFirst, boolean includeInterfaces) { 2097 List<Class<?>> l = getParentClasses(new ArrayList<Class<?>>(), c, parentFirst, includeInterfaces); 2098 return l.iterator(); 2099 } 2100 2101 private static List<Class<?>> getParentClasses(List<Class<?>> l, Class<?> c, boolean parentFirst, boolean includeInterfaces) { 2102 if (parentFirst) { 2103 if (includeInterfaces) 2104 for (Class<?> i : c.getInterfaces()) 2105 l.add(i); 2106 if (c.getSuperclass() != Object.class && c.getSuperclass() != null) 2107 getParentClasses(l, c.getSuperclass(), parentFirst, includeInterfaces); 2108 l.add(c); 2109 } else { 2110 l.add(c); 2111 if (c.getSuperclass() != Object.class && c.getSuperclass() != null) 2112 getParentClasses(l, c.getSuperclass(), parentFirst, includeInterfaces); 2113 if (includeInterfaces) 2114 for (Class<?> i : c.getInterfaces()) 2115 l.add(i); 2116 } 2117 return l; 2118 } 2119 2120 /** 2121 * Returns the default value for the specified primitive class. 2122 * 2123 * @param primitiveClass The primitive class to get the default value for. 2124 * @return The default value, or <jk>null</jk> if the specified class is not a primitive class. 2125 */ 2126 public static Object getPrimitiveDefault(Class<?> primitiveClass) { 2127 return primitiveDefaultMap.get(primitiveClass); 2128 } 2129 2130 private static final Map<Class<?>,Object> primitiveDefaultMap = Collections.unmodifiableMap( 2131 new AMap<Class<?>,Object>() 2132 .append(Boolean.TYPE, false) 2133 .append(Character.TYPE, (char)0) 2134 .append(Short.TYPE, (short)0) 2135 .append(Integer.TYPE, 0) 2136 .append(Long.TYPE, 0l) 2137 .append(Float.TYPE, 0f) 2138 .append(Double.TYPE, 0d) 2139 .append(Byte.TYPE, (byte)0) 2140 .append(Boolean.class, false) 2141 .append(Character.class, (char)0) 2142 .append(Short.class, (short)0) 2143 .append(Integer.class, 0) 2144 .append(Long.class, 0l) 2145 .append(Float.class, 0f) 2146 .append(Double.class, 0d) 2147 .append(Byte.class, (byte)0) 2148 ); 2149 2150 /** 2151 * Returns a readable representation of the specified method. 2152 * 2153 * <p> 2154 * The format of the string is <js>"full-qualified-class.method-name(parameter-simple-class-names)"</js>. 2155 * 2156 * @param m The method to stringify. 2157 * @return The stringified method. 2158 */ 2159 public static String toString(Method m) { 2160 StringBuilder sb = new StringBuilder(m.getDeclaringClass().getName() + "." + m.getName() + "("); 2161 for (int i = 0; i < m.getParameterTypes().length; i++) { 2162 if (i > 0) 2163 sb.append(","); 2164 sb.append(m.getParameterTypes()[i].getSimpleName()); 2165 } 2166 sb.append(")"); 2167 return sb.toString(); 2168 } 2169 2170 /** 2171 * Returns a readable representation of the specified field. 2172 * 2173 * <p> 2174 * The format of the string is <js>"full-qualified-class.field-name"</js>. 2175 * 2176 * @param f The field to stringify. 2177 * @return The stringified field. 2178 */ 2179 public static String toString(Field f) { 2180 return f.getDeclaringClass().getName() + "." + f.getName(); 2181 } 2182 2183 /** 2184 * Throws an {@link IllegalArgumentException} if the parameters on the method are not in the specified list provided. 2185 * 2186 * @param m The method to test. 2187 * @param args The valid class types (exact) for the arguments. 2188 * @throws FormattedIllegalArgumentException If any of the parameters on the method weren't in the list. 2189 */ 2190 public static void assertArgsOfType(Method m, Class<?>...args) throws FormattedIllegalArgumentException { 2191 for (Class<?> c1 : m.getParameterTypes()) { 2192 boolean foundMatch = false; 2193 for (Class<?> c2 : args) 2194 if (c1 == c2) 2195 foundMatch = true; 2196 if (! foundMatch) 2197 throw new FormattedIllegalArgumentException("Invalid argument of type {0} passed in method {1}. Only arguments of type {2} are allowed.", c1, m, args); 2198 } 2199 } 2200 2201 /** 2202 * Finds the public static "fromString" method on the specified class. 2203 * 2204 * <p> 2205 * Looks for the following method names: 2206 * <ul> 2207 * <li><code>fromString</code> 2208 * <li><code>fromValue</code> 2209 * <li><code>valueOf</code> 2210 * <li><code>parse</code> 2211 * <li><code>parseString</code> 2212 * <li><code>forName</code> 2213 * <li><code>forString</code> 2214 * </ul> 2215 * 2216 * @param c The class to find the method on. 2217 * @return The static method, or <jk>null</jk> if it couldn't be found. 2218 */ 2219 public static Method findPublicFromStringMethod(Class<?> c) { 2220 for (String methodName : new String[]{"create","fromString","fromValue","valueOf","parse","parseString","forName","forString"}) 2221 for (Method m : c.getMethods()) 2222 if (isAll(m, STATIC, PUBLIC, NOT_DEPRECATED) && hasName(m, methodName) && hasReturnType(m, c) && hasArgs(m, String.class)) 2223 return m; 2224 return null; 2225 } 2226 2227 /** 2228 * Find the public static creator method on the specified class. 2229 * 2230 * @param oc The created type. 2231 * @param ic The argument type. 2232 * @param name The method name. 2233 * @return The static method, or <jk>null</jk> if it couldn't be found. 2234 */ 2235 public static Method findPublicStaticCreateMethod(Class<?> oc, Class<?> ic, String name) { 2236 for (Method m : oc.getMethods()) 2237 if (isAll(m, STATIC, PUBLIC, NOT_DEPRECATED) && hasName(m, name) && hasReturnType(m, oc) && hasArgs(m, ic)) 2238 return m; 2239 return null; 2240 } 2241 2242 /** 2243 * Constructs a new instance of the specified class from the specified string. 2244 * 2245 * <p> 2246 * Class must be one of the following: 2247 * <ul> 2248 * <li>Have a public constructor that takes in a single <code>String</code> argument. 2249 * <li>Have a static <code>fromString(String)</code> (or related) method. 2250 * <br>See {@link #findPublicFromStringMethod(Class)} for the list of possible static method names. 2251 * <li>Be an <code>enum</code>. 2252 * </ul> 2253 * 2254 * @param c The class. 2255 * @param s The string to create the instance from. 2256 * @return A new object instance, or <jk>null</jk> if a method for converting the string to an object could not be found. 2257 */ 2258 public static <T> T fromString(Class<T> c, String s) { 2259 Transform<String,T> t = TransformCache.get(String.class, c); 2260 return t == null ? null : t.transform(s); 2261 } 2262 2263 /** 2264 * Converts an object to a string. 2265 * 2266 * <p> 2267 * Normally, this is just going to call <code>toString()</code> on the object. 2268 * However, the {@link Locale} and {@link TimeZone} objects are treated special so that the returned value 2269 * works with the {@link #fromString(Class, String)} method. 2270 * 2271 * @param o The object to convert to a string. 2272 * @return The stringified object, or <jk>null</jk> if the object was <jk>null</jk>. 2273 */ 2274 @SuppressWarnings({ "unchecked" }) 2275 public static String toString(Object o) { 2276 if (o == null) 2277 return null; 2278 Transform<Object,String> t = (Transform<Object,String>)TransformCache.get(o.getClass(), String.class); 2279 return t == null ? o.toString() : t.transform(o); 2280 } 2281 2282 /** 2283 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 2284 * 2285 * @param x The constructor. 2286 * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown. 2287 * @return <jk>true</jk> if call was successful. 2288 */ 2289 public static boolean setAccessible(Constructor<?> x, boolean ignoreExceptions) { 2290 try { 2291 if (! (x == null || x.isAccessible())) 2292 x.setAccessible(true); 2293 return true; 2294 } catch (SecurityException e) { 2295 if (ignoreExceptions) 2296 return false; 2297 throw new ClassMetaRuntimeException("Could not set accessibility to true on constructor ''{0}''", x); 2298 } 2299 } 2300 2301 /** 2302 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 2303 * 2304 * @param x The method. 2305 * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown. 2306 * @return <jk>true</jk> if call was successful. 2307 */ 2308 public static boolean setAccessible(Method x, boolean ignoreExceptions) { 2309 try { 2310 if (! (x == null || x.isAccessible())) 2311 x.setAccessible(true); 2312 return true; 2313 } catch (SecurityException e) { 2314 if (ignoreExceptions) 2315 return false; 2316 throw new ClassMetaRuntimeException("Could not set accessibility to true on method ''{0}''", x); 2317 } 2318 } 2319 2320 /** 2321 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 2322 * 2323 * @param x The field. 2324 * @param ignoreExceptions Ignore {@link SecurityException SecurityExceptions} and just return <jk>false</jk> if thrown. 2325 * @return <jk>true</jk> if call was successful. 2326 */ 2327 public static boolean setAccessible(Field x, boolean ignoreExceptions) { 2328 try { 2329 if (! (x == null || x.isAccessible())) 2330 x.setAccessible(true); 2331 return true; 2332 } catch (SecurityException e) { 2333 if (ignoreExceptions) 2334 return false; 2335 throw new ClassMetaRuntimeException("Could not set accessibility to true on field ''{0}''", x); 2336 } 2337 } 2338 2339 /** 2340 * Returns the simple name of a class. 2341 * 2342 * <p> 2343 * Similar to {@link Class#getSimpleName()}, but includes the simple name of an enclosing or declaring class. 2344 * 2345 * @param c The class to get the simple name on. 2346 * @return The simple name of a class. 2347 */ 2348 public static String getSimpleName(Class<?> c) { 2349 if (c.isLocalClass()) 2350 return getSimpleName(c.getEnclosingClass()) + '.' + c.getSimpleName(); 2351 if (c.isMemberClass()) 2352 return getSimpleName(c.getDeclaringClass()) + '.' + c.getSimpleName(); 2353 return c.getSimpleName(); 2354 } 2355 2356 /** 2357 * Returns the simple name of a class. 2358 * 2359 * <p> 2360 * Similar to {@link Class#getSimpleName()}, but includes the simple name of an enclosing or declaring class. 2361 * 2362 * @param t The class to get the simple name on. 2363 * @return The simple name of a class. 2364 */ 2365 public static String getSimpleName(Type t) { 2366 if (t instanceof Class) 2367 return getSimpleName((Class<?>)t); 2368 if (t instanceof ParameterizedType) { 2369 StringBuilder sb = new StringBuilder(); 2370 ParameterizedType pt = (ParameterizedType)t; 2371 sb.append(getSimpleName(pt.getRawType())); 2372 sb.append("<"); 2373 boolean first = true; 2374 for (Type t2 : pt.getActualTypeArguments()) { 2375 if (! first) 2376 sb.append(','); 2377 first = false; 2378 sb.append(getSimpleName(t2)); 2379 } 2380 sb.append(">"); 2381 return sb.toString(); 2382 } 2383 return null; 2384 } 2385 2386 /** 2387 * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value. 2388 * 2389 * @param a The annotation to check for. 2390 * @param m The method containing the parameter to check. 2391 * @param index The parameter index. 2392 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method, int)} returns a value. 2393 */ 2394 public static boolean hasAnnotation(Class<? extends Annotation> a, Method m, int index) { 2395 return getAnnotation(a, m, index) != null; 2396 } 2397 2398 /** 2399 * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Method)} returns a value. 2400 * 2401 * @param a The annotation to check for. 2402 * @param m The method to check. 2403 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Method)} returns a value. 2404 */ 2405 public static boolean hasAnnotation(Class<? extends Annotation> a, Method m) { 2406 return getAnnotation(a, m) != null; 2407 } 2408 2409 /** 2410 * Returns <jk>true</jk> if the {@link #getAnnotation(Class, Type)} returns a value. 2411 * 2412 * @param a The annotation to check for. 2413 * @param t The class to check. 2414 * @return <jk>true</jk> if the {@link #getAnnotation(Class, Type)} returns a value. 2415 */ 2416 public static boolean hasAnnotation(Class<? extends Annotation> a, Type t) { 2417 return getAnnotation(a, t) != null; 2418 } 2419 2420 /** 2421 * Similar to {@link Class#getAnnotation(Class)} except also searches annotations on interfaces. 2422 * 2423 * @param <T> The annotation class type. 2424 * @param a The annotation class. 2425 * @param t The annotated class. 2426 * @return The annotation, or <jk>null</jk> if not found. 2427 */ 2428 public static <T extends Annotation> T getAnnotation(Class<T> a, Type t) { 2429 Class<?> c = toClass(t); 2430 if (c != null) { 2431 T t2 = getDeclaredAnnotation(a, c); 2432 if (t2 != null) 2433 return t2; 2434 2435 t2 = getAnnotation(a, c.getSuperclass()); 2436 if (t2 != null) 2437 return t2; 2438 2439 for (Class<?> c2 : c.getInterfaces()) { 2440 t2 = getAnnotation(a, c2); 2441 if (t2 != null) 2442 return t2; 2443 } 2444 } 2445 return null; 2446 } 2447 2448 /** 2449 * Returns the specified annotation only if it's been declared on the specified class. 2450 * 2451 * <p> 2452 * More efficient than calling {@link Class#getAnnotation(Class)} since it doesn't recursively look for the class 2453 * up the parent chain. 2454 * 2455 * @param <T> The annotation class type. 2456 * @param a The annotation class. 2457 * @param t The annotated class. 2458 * @return The annotation, or <jk>null</jk> if not found. 2459 */ 2460 @SuppressWarnings("unchecked") 2461 public static <T extends Annotation> T getDeclaredAnnotation(Class<T> a, Type t) { 2462 Class<?> c = toClass(t); 2463 if (c != null) 2464 for (Annotation a2 : c.getDeclaredAnnotations()) 2465 if (a2.annotationType() == a) 2466 return (T)a2; 2467 return null; 2468 } 2469 2470 /** 2471 * Returns all instances of the specified annotation on the specified class. 2472 * 2473 * <p> 2474 * Searches all superclasses and superinterfaces. 2475 * Results are ordered child-to-parent. 2476 * 2477 * @param <T> The annotation class type. 2478 * @param a The annotation class type. 2479 * @param t The class being searched. 2480 * @return The found matches, or an empty array if annotation was not found. 2481 */ 2482 public static <T extends Annotation> List<T> getAnnotations(Class<T> a, Type t) { 2483 List<T> l = new LinkedList<>(); 2484 appendAnnotations(a, t, l); 2485 return l; 2486 } 2487 2488 /** 2489 * Same as {@link #getAnnotations(Class, Type)} but returns the list in parent-to-child order. 2490 * 2491 * @param a The annotation class type. 2492 * @param t The class being searched. 2493 * @return The found matches, or an empty array if annotation was not found. 2494 */ 2495 public static <T extends Annotation> List<T> getAnnotationsParentFirst(Class<T> a, Type t) { 2496 List<T> l = getAnnotations(a, t); 2497 Collections.reverse(l); 2498 return l; 2499 } 2500 2501 /** 2502 * Same as {@link #getAnnotations(Class, Type)} except returns the annotations as a map with the keys being the 2503 * class on which the annotation was found. 2504 * 2505 * <p> 2506 * Results are ordered child-to-parent. 2507 * 2508 * @param <T> The annotation class type. 2509 * @param a The annotation class type. 2510 * @param t The class being searched. 2511 * @return The found matches, or an empty map if annotation was not found. 2512 */ 2513 public static <T extends Annotation> LinkedHashMap<Class<?>,T> getAnnotationsMap(Class<T> a, Type t) { 2514 LinkedHashMap<Class<?>,T> m = new LinkedHashMap<>(); 2515 findAnnotationsMap(a, t, m); 2516 return m; 2517 } 2518 2519 /** 2520 * Same as {@link #getAnnotationsMap(Class, Type)} except returns results in parent-to-child order. 2521 * 2522 * @param <T> The annotation class type. 2523 * @param a The annotation class type. 2524 * @param t The class being searched. 2525 * @return The found matches, or an empty map if annotation was not found. 2526 */ 2527 public static <T extends Annotation> LinkedHashMap<Class<?>,T> getAnnotationsMapParentFirst(Class<T> a, Type t) { 2528 return CollectionUtils.reverse(getAnnotationsMap(a, t)); 2529 } 2530 2531 private static <T extends Annotation> void findAnnotationsMap(Class<T> a, Type t, Map<Class<?>,T> m) { 2532 Class<?> c = toClass(t); 2533 if (c != null) { 2534 2535 T t2 = getDeclaredAnnotation(a, c); 2536 if (t2 != null) 2537 m.put(c, t2); 2538 2539 findAnnotationsMap(a, c.getSuperclass(), m); 2540 2541 for (Class<?> c2 : c.getInterfaces()) 2542 findAnnotationsMap(a, c2, m); 2543 } 2544 } 2545 2546 /** 2547 * Finds and appends the specified annotation on the specified class and superclasses/interfaces to the specified 2548 * list. 2549 * 2550 * @param a The annotation. 2551 * @param t The class. 2552 * @param l The list of annotations. 2553 */ 2554 public static <T extends Annotation> void appendAnnotations(Class<T> a, Type t, List<T> l) { 2555 Class<?> c = toClass(t); 2556 if (c != null) { 2557 addIfNotNull(l, getDeclaredAnnotation(a, c)); 2558 2559 if (c.getPackage() != null) 2560 addIfNotNull(l, c.getPackage().getAnnotation(a)); 2561 2562 appendAnnotations(a, c.getSuperclass(), l); 2563 2564 for (Class<?> c2 : c.getInterfaces()) 2565 appendAnnotations(a, c2, l); 2566 } 2567 } 2568 2569 /** 2570 * Returns the specified type as a <code>Class</code>. 2571 * 2572 * <p> 2573 * If it's already a <code>Class</code>, it just does a cast. 2574 * <br>If it's a <code>ParameterizedType</code>, it returns the raw type. 2575 * 2576 * @param t The type to convert. 2577 * @return The type converted to a <code>Class</code>, or <jk>null</jk> if it could not be converted. 2578 */ 2579 public static Class<?> toClass(Type t) { 2580 if (t instanceof Class) 2581 return (Class<?>)t; 2582 if (t instanceof ParameterizedType) { 2583 ParameterizedType pt = (ParameterizedType)t; 2584 // The raw type should always be a class (right?) 2585 return (Class<?>)pt.getRawType(); 2586 } 2587 return null; 2588 } 2589 2590 /** 2591 * Similar to {@link Class#getResourceAsStream(String)} except looks up the parent hierarchy for the existence of 2592 * the specified resource. 2593 * 2594 * @param c The class to return the resource on. 2595 * @param name The resource name. 2596 * @return An input stream on the specified resource, or <jk>null</jk> if the resource could not be found. 2597 */ 2598 public static InputStream getResource(Class<?> c, String name) { 2599 if (name == null) 2600 return null; 2601 while (c != null) { 2602 InputStream is = c.getResourceAsStream(name); 2603 if (is != null) 2604 return is; 2605 c = c.getSuperclass(); 2606 } 2607 return null; 2608 } 2609}