1 16 17 package org.springframework.util; 18 19 import java.beans.Introspector ; 20 import java.lang.reflect.Array ; 21 import java.lang.reflect.Constructor ; 22 import java.lang.reflect.Method ; 23 import java.lang.reflect.Modifier ; 24 import java.lang.reflect.Proxy ; 25 import java.util.ArrayList ; 26 import java.util.Arrays ; 27 import java.util.Collection ; 28 import java.util.Collections ; 29 import java.util.HashMap ; 30 import java.util.HashSet ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.Set ; 35 36 import org.apache.commons.logging.Log; 37 import org.apache.commons.logging.LogFactory; 38 39 49 public abstract class ClassUtils { 50 51 52 public static final String ARRAY_SUFFIX = "[]"; 53 54 55 private static final char PACKAGE_SEPARATOR = '.'; 56 57 58 private static final char INNER_CLASS_SEPARATOR = '$'; 59 60 61 private static final String CGLIB_CLASS_SEPARATOR = "$$"; 62 63 64 private static final String CLASS_FILE_SUFFIX = ".class"; 65 66 67 private static final Log logger = LogFactory.getLog(ClassUtils.class); 68 69 73 private static final Map primitiveWrapperTypeMap = new HashMap (8); 74 75 79 private static final Map primitiveTypeNameMap = new HashMap (8); 80 81 static { 82 primitiveWrapperTypeMap.put(Boolean .class, boolean.class); 83 primitiveWrapperTypeMap.put(Byte .class, byte.class); 84 primitiveWrapperTypeMap.put(Character .class, char.class); 85 primitiveWrapperTypeMap.put(Double .class, double.class); 86 primitiveWrapperTypeMap.put(Float .class, float.class); 87 primitiveWrapperTypeMap.put(Integer .class, int.class); 88 primitiveWrapperTypeMap.put(Long .class, long.class); 89 primitiveWrapperTypeMap.put(Short .class, short.class); 90 91 for (Iterator it = primitiveWrapperTypeMap.values().iterator(); it.hasNext();) { 92 Class primitiveClass = (Class ) it.next(); 93 primitiveTypeNameMap.put(primitiveClass.getName(), primitiveClass); 94 } 95 } 96 97 98 110 public static ClassLoader getDefaultClassLoader() { 111 ClassLoader cl = null; 112 try { 113 cl = Thread.currentThread().getContextClassLoader(); 114 } 115 catch (Throwable ex) { 116 logger.debug("Cannot access thread context ClassLoader - falling back to system class loader", ex); 117 } 118 if (cl == null) { 119 cl = ClassUtils.class.getClassLoader(); 121 } 122 return cl; 123 } 124 125 132 public static boolean isPresent(String className) { 133 return isPresent(className, getDefaultClassLoader()); 134 } 135 136 145 public static boolean isPresent(String className, ClassLoader classLoader) { 146 try { 147 forName(className, classLoader); 148 return true; 149 } 150 catch (Throwable ex) { 151 if (logger.isDebugEnabled()) { 152 logger.debug("Class [" + className + "] or one of its dependencies is not present: " + ex); 153 } 154 return false; 155 } 156 } 157 158 170 public static Class forName(String name) throws ClassNotFoundException , LinkageError { 171 return forName(name, getDefaultClassLoader()); 172 } 173 174 185 public static Class forName(String name, ClassLoader classLoader) throws ClassNotFoundException , LinkageError { 186 Assert.notNull(name, "Name must not be null"); 187 Class clazz = resolvePrimitiveClassName(name); 188 if (clazz != null) { 189 return clazz; 190 } 191 if (name.endsWith(ARRAY_SUFFIX)) { 192 String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length()); 194 Class elementClass = forName(elementClassName, classLoader); 195 return Array.newInstance(elementClass, 0).getClass(); 196 } 197 ClassLoader classLoaderToUse = classLoader; 198 if (classLoaderToUse == null) { 199 classLoaderToUse = getDefaultClassLoader(); 200 } 201 return classLoaderToUse.loadClass(name); 202 } 203 204 218 public static Class resolveClassName(String className, ClassLoader classLoader) throws IllegalArgumentException { 219 try { 220 return forName(className, classLoader); 221 } 222 catch (ClassNotFoundException ex) { 223 throw new IllegalArgumentException ("Cannot find class [" + className + "]. Root cause: " + ex); 224 } 225 catch (LinkageError ex) { 226 throw new IllegalArgumentException ("Error loading class [" + className + 227 "]: problem with class file or dependent class. Root cause: " + ex); 228 } 229 } 230 231 237 public static Class resolvePrimitiveClassName(String name) { 238 Class result = null; 239 if (name != null && name.length() <= 8) { 242 result = (Class ) primitiveTypeNameMap.get(name); 244 } 245 return result; 246 } 247 248 255 public static Class getUserClass(Object instance) { 256 Assert.notNull(instance, "Instance must not be null"); 257 return getUserClass(instance.getClass()); 258 } 259 260 266 public static Class getUserClass(Class clazz) { 267 return (clazz != null && clazz.getName().indexOf(CGLIB_CLASS_SEPARATOR) != -1 ? 268 clazz.getSuperclass() : clazz); 269 } 270 271 272 278 public static String getShortName(String className) { 279 Assert.hasLength(className, "Class name must not be empty"); 280 int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR); 281 int nameEndIndex = className.indexOf(CGLIB_CLASS_SEPARATOR); 282 if (nameEndIndex == -1) { 283 nameEndIndex = className.length(); 284 } 285 String shortName = className.substring(lastDotIndex + 1, nameEndIndex); 286 shortName = shortName.replace(INNER_CLASS_SEPARATOR, PACKAGE_SEPARATOR); 287 return shortName; 288 } 289 290 295 public static String getShortName(Class clazz) { 296 return getShortName(getQualifiedName(clazz)); 297 } 298 299 306 public static String getShortNameAsProperty(Class clazz) { 307 return Introspector.decapitalize(getShortName(clazz)); 308 } 309 310 316 public static String getClassFileName(Class clazz) { 317 Assert.notNull(clazz, "Class must not be null"); 318 String className = clazz.getName(); 319 int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR); 320 return className.substring(lastDotIndex + 1) + CLASS_FILE_SUFFIX; 321 } 322 323 329 public static String getQualifiedName(Class clazz) { 330 Assert.notNull(clazz, "Class must not be null"); 331 if (clazz.isArray()) { 332 return getQualifiedNameForArray(clazz); 333 } 334 else { 335 return clazz.getName(); 336 } 337 } 338 339 345 private static String getQualifiedNameForArray(Class clazz) { 346 StringBuffer buffer = new StringBuffer (); 347 while (clazz.isArray()) { 348 clazz = clazz.getComponentType(); 349 buffer.append(ClassUtils.ARRAY_SUFFIX); 350 } 351 buffer.insert(0, clazz.getName()); 352 return buffer.toString(); 353 } 354 355 361 public static String getQualifiedMethodName(Method method) { 362 Assert.notNull(method, "Method must not be null"); 363 return method.getDeclaringClass().getName() + "." + method.getName(); 364 } 365 366 367 375 public static boolean hasConstructor(Class clazz, Class [] paramTypes) { 376 return (getConstructorIfAvailable(clazz, paramTypes) != null); 377 } 378 379 388 public static Constructor getConstructorIfAvailable(Class clazz, Class [] paramTypes) { 389 Assert.notNull(clazz, "Class must not be null"); 390 try { 391 return clazz.getConstructor(paramTypes); 392 } 393 catch (NoSuchMethodException ex) { 394 return null; 395 } 396 } 397 398 407 public static boolean hasMethod(Class clazz, String methodName, Class [] paramTypes) { 408 return (getMethodIfAvailable(clazz, methodName, paramTypes) != null); 409 } 410 411 421 public static Method getMethodIfAvailable(Class clazz, String methodName, Class [] paramTypes) { 422 Assert.notNull(clazz, "Class must not be null"); 423 Assert.notNull(methodName, "Method name must not be null"); 424 try { 425 return clazz.getMethod(methodName, paramTypes); 426 } 427 catch (NoSuchMethodException ex) { 428 return null; 429 } 430 } 431 432 439 public static int getMethodCountForName(Class clazz, String methodName) { 440 Assert.notNull(clazz, "Class must not be null"); 441 Assert.notNull(methodName, "Method name must not be null"); 442 int count = 0; 443 for (int i = 0; i < clazz.getDeclaredMethods().length; i++) { 444 Method method = clazz.getDeclaredMethods()[i]; 445 if (methodName.equals(method.getName())) { 446 count++; 447 } 448 } 449 Class [] ifcs = clazz.getInterfaces(); 450 for (int i = 0; i < ifcs.length; i++) { 451 count += getMethodCountForName(ifcs[i], methodName); 452 } 453 if (clazz.getSuperclass() != null) { 454 count += getMethodCountForName(clazz.getSuperclass(), methodName); 455 } 456 return count; 457 } 458 459 466 public static boolean hasAtLeastOneMethodWithName(Class clazz, String methodName) { 467 Assert.notNull(clazz, "Class must not be null"); 468 Assert.notNull(methodName, "Method name must not be null"); 469 for (int i = 0; i < clazz.getDeclaredMethods().length; i++) { 470 Method method = clazz.getDeclaredMethods()[i]; 471 if (method.getName().equals(methodName)) { 472 return true; 473 } 474 } 475 Class [] ifcs = clazz.getInterfaces(); 476 for (int i = 0; i < ifcs.length; i++) { 477 if (hasAtLeastOneMethodWithName(ifcs[i], methodName)) { 478 return true; 479 } 480 } 481 return (clazz.getSuperclass() != null && hasAtLeastOneMethodWithName(clazz.getSuperclass(), methodName)); 482 } 483 484 492 public static Method getStaticMethod(Class clazz, String methodName, Class [] args) { 493 Assert.notNull(clazz, "Class must not be null"); 494 Assert.notNull(methodName, "Method name must not be null"); 495 try { 496 Method method = clazz.getDeclaredMethod(methodName, args); 497 if ((method.getModifiers() & Modifier.STATIC) != 0) { 498 return method; 499 } 500 } 501 catch (NoSuchMethodException ex) { 502 } 503 return null; 504 } 505 506 507 511 public static boolean isPrimitiveWrapper(Class clazz) { 512 Assert.notNull(clazz, "Class must not be null"); 513 return primitiveWrapperTypeMap.containsKey(clazz); 514 } 515 516 521 public static boolean isPrimitiveOrWrapper(Class clazz) { 522 Assert.notNull(clazz, "Class must not be null"); 523 return (clazz.isPrimitive() || isPrimitiveWrapper(clazz)); 524 } 525 526 530 public static boolean isPrimitiveArray(Class clazz) { 531 Assert.notNull(clazz, "Class must not be null"); 532 return (clazz.isArray() && clazz.getComponentType().isPrimitive()); 533 } 534 535 539 public static boolean isPrimitiveWrapperArray(Class clazz) { 540 Assert.notNull(clazz, "Class must not be null"); 541 return (clazz.isArray() && isPrimitiveWrapper(clazz.getComponentType())); 542 } 543 544 552 public static boolean isAssignable(Class targetType, Class valueType) { 553 Assert.notNull(targetType, "Target type must not be null"); 554 Assert.notNull(valueType, "Value type must not be null"); 555 return (targetType.isAssignableFrom(valueType) || 556 targetType.equals(primitiveWrapperTypeMap.get(valueType))); 557 } 558 559 567 public static boolean isAssignableValue(Class type, Object value) { 568 Assert.notNull(type, "Type must not be null"); 569 return (value != null ? isAssignable(type, value.getClass()) : !type.isPrimitive()); 570 } 571 572 573 589 public static String addResourcePathToPackagePath(Class clazz, String resourceName) { 590 Assert.notNull(resourceName, "Resource name must not be null"); 591 if (!resourceName.startsWith("/")) { 592 return classPackageAsResourcePath(clazz) + "/" + resourceName; 593 } 594 return classPackageAsResourcePath(clazz) + resourceName; 595 } 596 597 611 public static String classPackageAsResourcePath(Class clazz) { 612 if (clazz == null) { 613 return ""; 614 } 615 String className = clazz.getName(); 616 int packageEndIndex = className.lastIndexOf('.'); 617 if (packageEndIndex == -1) { 618 return ""; 619 } 620 String packageName = className.substring(0, packageEndIndex); 621 return packageName.replace('.', '/'); 622 } 623 624 633 public static String classNamesToString(Class [] classes) { 634 return classNamesToString(Arrays.asList(classes)); 635 } 636 637 646 public static String classNamesToString(Collection classes) { 647 if (CollectionUtils.isEmpty(classes)) { 648 return "[]"; 649 } 650 StringBuffer sb = new StringBuffer ("["); 651 for (Iterator it = classes.iterator(); it.hasNext(); ) { 652 Class clazz = (Class ) it.next(); 653 sb.append(clazz.getName()); 654 if (it.hasNext()) { 655 sb.append(", "); 656 } 657 } 658 sb.append("]"); 659 return sb.toString(); 660 } 661 662 663 669 public static Class [] getAllInterfaces(Object instance) { 670 Assert.notNull(instance, "Instance must not be null"); 671 return getAllInterfacesForClass(instance.getClass()); 672 } 673 674 681 public static Class [] getAllInterfacesForClass(Class clazz) { 682 Assert.notNull(clazz, "Class must not be null"); 683 if (clazz.isInterface()) { 684 return new Class [] {clazz}; 685 } 686 List interfaces = new ArrayList (); 687 while (clazz != null) { 688 for (int i = 0; i < clazz.getInterfaces().length; i++) { 689 Class ifc = clazz.getInterfaces()[i]; 690 if (!interfaces.contains(ifc)) { 691 interfaces.add(ifc); 692 } 693 } 694 clazz = clazz.getSuperclass(); 695 } 696 return (Class []) interfaces.toArray(new Class [interfaces.size()]); 697 } 698 699 705 public static Set getAllInterfacesAsSet(Object instance) { 706 Assert.notNull(instance, "Instance must not be null"); 707 return getAllInterfacesForClassAsSet(instance.getClass()); 708 } 709 710 717 public static Set getAllInterfacesForClassAsSet(Class clazz) { 718 Assert.notNull(clazz, "Class must not be null"); 719 if (clazz.isInterface()) { 720 return Collections.singleton(clazz); 721 } 722 Set interfaces = new HashSet (); 723 while (clazz != null) { 724 for (int i = 0; i < clazz.getInterfaces().length; i++) { 725 Class ifc = clazz.getInterfaces()[i]; 726 interfaces.add(ifc); 727 } 728 clazz = clazz.getSuperclass(); 729 } 730 return interfaces; 731 } 732 733 742 public static Class createCompositeInterface(Class [] interfaces, ClassLoader classLoader) { 743 Assert.notEmpty(interfaces, "Interfaces must not be empty"); 744 Assert.notNull(classLoader, "ClassLoader must not be null"); 745 return Proxy.getProxyClass(classLoader, interfaces); 746 } 747 748 } 749 | Popular Tags |