Coverage Report - org.mule.util.ClassUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassUtils
0%
0/218
0%
0/174
0
ClassUtils$1
0%
0/3
0%
0/2
0
ClassUtils$10
0%
0/4
N/A
0
ClassUtils$2
0%
0/2
N/A
0
ClassUtils$3
0%
0/2
N/A
0
ClassUtils$4
0%
0/5
0%
0/2
0
ClassUtils$5
0%
0/4
N/A
0
ClassUtils$6
0%
0/4
N/A
0
ClassUtils$7
0%
0/5
0%
0/2
0
ClassUtils$8
0%
0/4
N/A
0
ClassUtils$9
0%
0/4
N/A
0
 
 1  
 /*
 2  
  * $Id: ClassUtils.java 19191 2010-08-25 21:05:23Z tcarlson $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.util;
 12  
 
 13  
 import org.mule.routing.filters.WildcardFilter;
 14  
 
 15  
 import java.io.BufferedReader;
 16  
 import java.io.CharArrayReader;
 17  
 import java.io.IOException;
 18  
 import java.io.Reader;
 19  
 import java.lang.reflect.Constructor;
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.lang.reflect.Method;
 22  
 import java.lang.reflect.Modifier;
 23  
 import java.net.URL;
 24  
 import java.net.URLClassLoader;
 25  
 import java.security.AccessController;
 26  
 import java.security.CodeSource;
 27  
 import java.security.PrivilegedAction;
 28  
 import java.util.ArrayList;
 29  
 import java.util.Collection;
 30  
 import java.util.Collections;
 31  
 import java.util.Enumeration;
 32  
 import java.util.HashMap;
 33  
 import java.util.Iterator;
 34  
 import java.util.List;
 35  
 import java.util.Map;
 36  
 import java.util.Set;
 37  
 
 38  
 /**
 39  
  * Extend the Apache Commons ClassUtils to provide additional functionality.
 40  
  * <p/>
 41  
  * <p>This class is useful for loading resources and classes in a fault tolerant manner
 42  
  * that works across different applications servers. The resource and classloading
 43  
  * methods are SecurityManager friendly.</p>
 44  
  */
 45  
 // @ThreadSafe
 46  0
 public class ClassUtils extends org.apache.commons.lang.ClassUtils
 47  
 {
 48  0
     public static final Object[] NO_ARGS = new Object[]{};
 49  0
     public static final Class<?>[] NO_ARGS_TYPE = new Class<?>[]{};
 50  
 
 51  0
     private static final Map<Class<?>, Class<?>> wrapperToPrimitiveMap = new HashMap<Class<?>, Class<?>>();
 52  
 
 53  
     static
 54  
     {
 55  0
         wrapperToPrimitiveMap.put(Boolean.class, Boolean.TYPE);
 56  0
         wrapperToPrimitiveMap.put(Byte.class, Byte.TYPE);
 57  0
         wrapperToPrimitiveMap.put(Character.class, Character.TYPE);
 58  0
         wrapperToPrimitiveMap.put(Short.class, Short.TYPE);
 59  0
         wrapperToPrimitiveMap.put(Integer.class, Integer.TYPE);
 60  0
         wrapperToPrimitiveMap.put(Long.class, Long.TYPE);
 61  0
         wrapperToPrimitiveMap.put(Double.class, Double.TYPE);
 62  0
         wrapperToPrimitiveMap.put(Float.class, Float.TYPE);
 63  0
         wrapperToPrimitiveMap.put(Void.TYPE, Void.TYPE);
 64  0
     }
 65  
 
 66  
     public static boolean isConcrete(Class<?> clazz)
 67  
     {
 68  0
         if (clazz == null)
 69  
         {
 70  0
             throw new IllegalArgumentException("clazz may not be null");
 71  
         }
 72  0
         return !(clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers()));
 73  
     }
 74  
 
 75  
     /**
 76  
      * Load a given resource. <p/> This method will try to load the resource using
 77  
      * the following methods (in order):
 78  
      * <ul>
 79  
      * <li>From
 80  
      * {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
 81  
      * <li>From
 82  
      * {@link Class#getClassLoader() ClassUtils.class.getClassLoader()}
 83  
      * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
 84  
      * </ul>
 85  
      *
 86  
      * @param resourceName The name of the resource to load
 87  
      * @param callingClass The Class object of the calling object
 88  
      *
 89  
      * @return A URL pointing to the resource to load or null if the resource is not found
 90  
      */
 91  
     public static URL getResource(final String resourceName, final Class<?> callingClass)
 92  
     {
 93  0
         URL url = AccessController.doPrivileged(new PrivilegedAction<URL>()
 94  0
         {
 95  
             public URL run()
 96  
             {
 97  0
                 final ClassLoader cl = Thread.currentThread().getContextClassLoader();
 98  0
                 return cl != null ? cl.getResource(resourceName) : null;
 99  
             }
 100  
         });
 101  
 
 102  0
         if (url == null)
 103  
         {
 104  0
             url = AccessController.doPrivileged(new PrivilegedAction<URL>()
 105  0
             {
 106  
                 public URL run()
 107  
                 {
 108  0
                     return ClassUtils.class.getClassLoader().getResource(resourceName);
 109  
                 }
 110  
             });
 111  
         }
 112  
 
 113  0
         if (url == null)
 114  
         {
 115  0
             url = AccessController.doPrivileged(new PrivilegedAction<URL>()
 116  0
             {
 117  
                 public URL run()
 118  
                 {
 119  0
                     return callingClass.getClassLoader().getResource(resourceName);
 120  
                 }
 121  
             });
 122  
         }
 123  
 
 124  0
         return url;
 125  
     }
 126  
 
 127  
     public static Enumeration<URL> getResources(final String resourceName, final Class<?> callingClass)
 128  
     {
 129  0
         Enumeration<URL> enumeration = AccessController.doPrivileged(new PrivilegedAction<Enumeration<URL>>()
 130  0
         {
 131  
             public Enumeration<URL> run()
 132  
             {
 133  
                 try
 134  
                 {
 135  0
                     final ClassLoader cl = Thread.currentThread().getContextClassLoader();
 136  0
                     return cl != null ? cl.getResources(resourceName) : null;
 137  
                 }
 138  0
                 catch (IOException e)
 139  
                 {
 140  0
                     return null;
 141  
                 }
 142  
             }
 143  
         });
 144  
 
 145  0
         if (enumeration == null)
 146  
         {
 147  0
             enumeration = AccessController.doPrivileged(new PrivilegedAction<Enumeration<URL>>()
 148  0
             {
 149  
                 public Enumeration<URL> run()
 150  
                 {
 151  
                     try
 152  
                     {
 153  0
                         return ClassUtils.class.getClassLoader().getResources(resourceName);
 154  
                     }
 155  0
                     catch (IOException e)
 156  
                     {
 157  0
                         return null;
 158  
                     }
 159  
                 }
 160  
             });
 161  
         }
 162  
 
 163  0
         if (enumeration == null)
 164  
         {
 165  0
             enumeration = AccessController.doPrivileged(new PrivilegedAction<Enumeration<URL>>()
 166  0
             {
 167  
                 public Enumeration<URL> run()
 168  
                 {
 169  
                     try
 170  
                     {
 171  0
                         return callingClass.getClassLoader().getResources(resourceName);
 172  
                     }
 173  0
                     catch (IOException e)
 174  
                     {
 175  0
                         return null;
 176  
                     }
 177  
                 }
 178  
             });
 179  
         }
 180  
 
 181  0
         return enumeration;
 182  
     }
 183  
 
 184  
     /**
 185  
      * Load a class with a given name. <p/> It will try to load the class in the
 186  
      * following order:
 187  
      * <ul>
 188  
      * <li>From
 189  
      * {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
 190  
      * <li>Using the basic {@link Class#forName(java.lang.String) }
 191  
      * <li>From
 192  
      * {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
 193  
      * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
 194  
      * </ul>
 195  
      *
 196  
      * @param className    The name of the class to load
 197  
      * @param callingClass The Class object of the calling object
 198  
      * @return The Class instance
 199  
      * @throws ClassNotFoundException If the class cannot be found anywhere.
 200  
      */
 201  
     public static Class loadClass(final String className, final Class<?> callingClass) throws ClassNotFoundException
 202  
     {
 203  0
         return loadClass(className, callingClass, Object.class);
 204  
     }
 205  
     /**
 206  
      * Load a class with a given name. <p/> It will try to load the class in the
 207  
      * following order:
 208  
      * <ul>
 209  
      * <li>From
 210  
      * {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}
 211  
      * <li>Using the basic {@link Class#forName(java.lang.String) }
 212  
      * <li>From
 213  
      * {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}
 214  
      * <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }
 215  
      * </ul>
 216  
      *
 217  
      * @param className    The name of the class to load
 218  
      * @param callingClass The Class object of the calling object
 219  
      * @param type the class type to expect to load
 220  
      * @return The Class instance
 221  
      * @throws ClassNotFoundException If the class cannot be found anywhere.
 222  
      */
 223  
     public static <T extends Class> T loadClass(final String className, final Class<?> callingClass, T type) throws ClassNotFoundException
 224  
     {
 225  0
         Class<?> clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
 226  0
         {
 227  
             public Class<?> run()
 228  
             {
 229  
                 try
 230  
                 {
 231  0
                     final ClassLoader cl = Thread.currentThread().getContextClassLoader();
 232  0
                     return cl != null ? cl.loadClass(className) : null;
 233  
 
 234  
                 }
 235  0
                 catch (ClassNotFoundException e)
 236  
                 {
 237  0
                     return null;
 238  
                 }
 239  
             }
 240  
         });
 241  
 
 242  0
         if (clazz == null)
 243  
         {
 244  0
             clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
 245  0
             {
 246  
                 public Class<?> run()
 247  
                 {
 248  
                     try
 249  
                     {
 250  0
                         return Class.forName(className);
 251  
                     }
 252  0
                     catch (ClassNotFoundException e)
 253  
                     {
 254  0
                         return null;
 255  
                     }
 256  
                 }
 257  
             });
 258  
         }
 259  
 
 260  0
         if (clazz == null)
 261  
         {
 262  0
             clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
 263  0
             {
 264  
                 public Class<?> run()
 265  
                 {
 266  
                     try
 267  
                     {
 268  0
                         return ClassUtils.class.getClassLoader().loadClass(className);
 269  
                     }
 270  0
                     catch (ClassNotFoundException e)
 271  
                     {
 272  0
                         return null;
 273  
                     }
 274  
                 }
 275  
             });
 276  
         }
 277  
 
 278  0
         if (clazz == null)
 279  
         {
 280  0
             clazz = AccessController.doPrivileged(new PrivilegedAction<Class<?>>()
 281  0
             {
 282  
                 public Class<?> run()
 283  
                 {
 284  
                     try
 285  
                     {
 286  0
                         return callingClass.getClassLoader().loadClass(className);
 287  
                     }
 288  0
                     catch (ClassNotFoundException e)
 289  
                     {
 290  0
                         return null;
 291  
                     }
 292  
                 }
 293  
             });
 294  
         }
 295  
 
 296  0
         if (clazz == null)
 297  
         {
 298  0
             throw new ClassNotFoundException(className);
 299  
         }
 300  
 
 301  0
         if(type.isAssignableFrom(clazz))
 302  
         {
 303  0
             return (T)clazz;
 304  
         }
 305  
         else
 306  
         {
 307  0
             throw new IllegalArgumentException(String.format("Loaded class '%s' is not assignable from type '%s'", clazz.getName(), type.getName()));
 308  
         }
 309  
     }
 310  
 
 311  
     /**
 312  
      * Load a class with a given name from the given classloader.
 313  
      *
 314  
      * @param className the name of the class to load
 315  
      * @param classLoader the loader to load it from
 316  
      * @return the instance of the class
 317  
      * @throws ClassNotFoundException if the class is not available in the class loader
 318  
      */
 319  
     public static Class loadClass(final String className, final ClassLoader classLoader)
 320  
             throws ClassNotFoundException
 321  
     {
 322  0
         return classLoader.loadClass(className);
 323  
     }
 324  
 
 325  
 
 326  
     /**
 327  
      * Ensure that the given class is properly initialized when the argument is passed in
 328  
      * as .class literal. This method can never fail unless the bytecode is corrupted or
 329  
      * the VM is otherwise seriously confused.
 330  
      *
 331  
      * @param clazz the Class to be initialized
 332  
      * @return the same class but initialized
 333  
      */
 334  
     public static Class<?> initializeClass(Class<?> clazz)
 335  
     {
 336  
         try
 337  
         {
 338  0
             return getClass(clazz.getName(), true);
 339  
         }
 340  0
         catch (ClassNotFoundException e)
 341  
         {
 342  0
             IllegalStateException ise = new IllegalStateException();
 343  0
             ise.initCause(e);
 344  0
             throw ise;
 345  
         }
 346  
     }
 347  
 
 348  
     public static <T> T instanciateClass(Class<? extends T> clazz, Object... constructorArgs)
 349  
             throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException,
 350  
             IllegalAccessException, InvocationTargetException
 351  
     {
 352  
         Class<?>[] args;
 353  0
         if (constructorArgs != null)
 354  
         {
 355  0
             args = new Class[constructorArgs.length];
 356  0
             for (int i = 0; i < constructorArgs.length; i++)
 357  
             {
 358  0
                 if (constructorArgs[i] == null)
 359  
                 {
 360  0
                     args[i] = null;
 361  
                 }
 362  
                 else
 363  
                 {
 364  0
                     args[i] = constructorArgs[i].getClass();
 365  
                 }
 366  
             }
 367  
         }
 368  
         else
 369  
         {
 370  0
             args = new Class[0];
 371  
         }
 372  
 
 373  
         // try the arguments as given
 374  
         //Constructor ctor = clazz.getConstructor(args);
 375  0
         Constructor<?> ctor = getConstructor(clazz, args);
 376  
 
 377  0
         if (ctor == null)
 378  
         {
 379  
             // try again but adapt value classes to primitives
 380  0
             ctor = getConstructor(clazz, wrappersToPrimitives(args));
 381  
         }
 382  
 
 383  0
         if (ctor == null)
 384  
         {
 385  0
             StringBuffer argsString = new StringBuffer(100);
 386  0
             for (Class<?> arg : args)
 387  
             {
 388  0
                 argsString.append(arg.getName()).append(", ");
 389  
             }
 390  0
             throw new NoSuchMethodException("could not find constructor on class: " + clazz + ", with matching arg params: "
 391  
                     + argsString);
 392  
         }
 393  
 
 394  0
         return (T)ctor.newInstance(constructorArgs);
 395  
     }
 396  
 
 397  
     public static Object instanciateClass(String name, Object... constructorArgs)
 398  
             throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
 399  
             InstantiationException, IllegalAccessException, InvocationTargetException
 400  
     {
 401  0
         return instanciateClass(name, constructorArgs, (ClassLoader) null);
 402  
     }
 403  
 
 404  
     public static Object instanciateClass(String name, Object[] constructorArgs, Class<?> callingClass)
 405  
             throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
 406  
             InstantiationException, IllegalAccessException, InvocationTargetException
 407  
     {
 408  0
         Class<?> clazz = loadClass(name, callingClass);
 409  0
         return instanciateClass(clazz, constructorArgs);
 410  
     }
 411  
 
 412  
     public static Object instanciateClass(String name, Object[] constructorArgs, ClassLoader classLoader)
 413  
             throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
 414  
             InstantiationException, IllegalAccessException, InvocationTargetException
 415  
     {
 416  
         Class<?> clazz;
 417  0
         if (classLoader != null)
 418  
         {
 419  0
             clazz = loadClass(name, classLoader);
 420  
         }
 421  
         else
 422  
         {
 423  0
             clazz = loadClass(name, ClassUtils.class);
 424  
         }
 425  0
         if (clazz == null)
 426  
         {
 427  0
             throw new ClassNotFoundException(name);
 428  
         }
 429  0
         return instanciateClass(clazz, constructorArgs);
 430  
     }
 431  
 
 432  
     public static Class<?>[] getParameterTypes(Object bean, String methodName)
 433  
     {
 434  0
         if (!methodName.startsWith("set"))
 435  
         {
 436  0
             methodName = "set" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
 437  
         }
 438  
 
 439  0
         Method methods[] = bean.getClass().getMethods();
 440  
 
 441  0
         for (int i = 0; i < methods.length; i++)
 442  
         {
 443  0
             if (methods[i].getName().equals(methodName))
 444  
             {
 445  0
                 return methods[i].getParameterTypes();
 446  
             }
 447  
         }
 448  
 
 449  0
         return new Class[]{};
 450  
     }
 451  
 
 452  
     /**
 453  
      * Returns a matching method for the given name and parameters on the given class
 454  
      * If the parameterTypes arguments is null it will return the first matching
 455  
      * method on the class.
 456  
      *
 457  
      * @param clazz          the class to find the method on
 458  
      * @param name           the method name to find
 459  
      * @param parameterTypes an array of argument types or null
 460  
      * @return the Method object or null if none was found
 461  
      */
 462  
     public static Method getMethod(Class<?> clazz, String name, Class<?>[] parameterTypes)
 463  
     {
 464  0
         Method[] methods = clazz.getMethods();
 465  0
         for (int i = 0; i < methods.length; i++)
 466  
         {
 467  0
             if (methods[i].getName().equals(name))
 468  
             {
 469  0
                 if (parameterTypes == null)
 470  
                 {
 471  0
                     return methods[i];
 472  
                 }
 473  0
                 else if (compare(methods[i].getParameterTypes(), parameterTypes, true))
 474  
                 {
 475  0
                     return methods[i];
 476  
                 }
 477  
             }
 478  
         }
 479  0
         return null;
 480  
     }
 481  
 
 482  
     public static Constructor getConstructor(Class clazz, Class[] paramTypes)
 483  
     {
 484  0
         return getConstructor(clazz, paramTypes, false);
 485  
     }
 486  
     
 487  
     /**
 488  
      *  Returns available constructor in the target class that as the parameters specified.
 489  
      *
 490  
      * @param clazz the class to search
 491  
      * @param paramTypes the param types to match against
 492  
      * @param exactMatch should exact types be used (i.e. equals rather than isAssignableFrom.)
 493  
      * @return The matching constructor or null if no matching constructor is found
 494  
      */
 495  
     public static Constructor getConstructor(Class clazz, Class[] paramTypes, boolean exactMatch)
 496  
     {
 497  0
         Constructor[] ctors = clazz.getConstructors();
 498  0
         for (int i = 0; i < ctors.length; i++)
 499  
         {
 500  0
             Class[] types = ctors[i].getParameterTypes();
 501  0
             if (types.length == paramTypes.length)
 502  
             {
 503  0
                 int matchCount = 0;
 504  0
                 for (int x = 0; x < types.length; x++)
 505  
                 {
 506  0
                     if (paramTypes[x] == null)
 507  
                     {
 508  0
                         matchCount++;
 509  
                     }
 510  
                     else
 511  
                     {
 512  0
                         if (exactMatch)
 513  
                         {
 514  0
                             if (paramTypes[x].equals(types[x]) || types[x].equals(paramTypes[x]))
 515  
                             {
 516  0
                                 matchCount++;
 517  
                             }
 518  
                         }
 519  
                         else
 520  
                         {
 521  0
                             if (paramTypes[x].isAssignableFrom(types[x])
 522  
                                 || types[x].isAssignableFrom(paramTypes[x]))
 523  
                             {
 524  0
                                 matchCount++;
 525  
                             }
 526  
                         }
 527  
                     }
 528  
                 }
 529  0
                 if (matchCount == types.length)
 530  
                 {
 531  0
                     return ctors[i];
 532  
                 }
 533  
             }
 534  
         }
 535  0
         return null;
 536  
     }
 537  
 
 538  
     /**
 539  
      * A helper method that will find all matching methods on a class with the given
 540  
      * parameter type
 541  
      *
 542  
      * @param implementation     the class to build methods on
 543  
      * @param parameterTypes     the argument param types to look for
 544  
      * @param voidOk             whether void methods shouldbe included in the found list
 545  
      * @param matchOnObject      determines whether parameters of Object type are matched
 546  
      *                           when they are of Object.class type
 547  
      * @param ignoredMethodNames a Set of method names to ignore. Often 'equals' is
 548  
      *                           not a desired match. This argument can be null.
 549  
      * @return a List of methods on the class that match the criteria. If there are
 550  
      *         none, an empty list is returned
 551  
      */
 552  
     public static List<Method> getSatisfiableMethods(Class<?> implementation,
 553  
                                              Class<?>[] parameterTypes,
 554  
                                              boolean voidOk,
 555  
                                              boolean matchOnObject,
 556  
                                              Set<String> ignoredMethodNames)
 557  
     {
 558  0
         return getSatisfiableMethods(implementation, parameterTypes, voidOk, matchOnObject, ignoredMethodNames, null);
 559  
     }
 560  
 
 561  
     /**
 562  
      * A helper method that will find all matching methods on a class with the given
 563  
      * parameter type
 564  
      *
 565  
      * @param implementation     the class to build methods on
 566  
      * @param parameterTypes     the argument param types to look for
 567  
      * @param voidOk             whether void methods shouldbe included in the found list
 568  
      * @param matchOnObject      determines whether parameters of Object type are matched
 569  
      *                           when they are of Object.class type
 570  
      * @param ignoredMethodNames a Set of method names to ignore. Often 'equals' is
 571  
      *                           not a desired match. This argument can be null.
 572  
      * @param filter             Wildcard expression filter that allows methods to be matched using wildcards i.e. 'get*'
 573  
      * @return a List of methods on the class that match the criteria. If there are
 574  
      *         none, an empty list is returned
 575  
      */
 576  
     public static List<Method> getSatisfiableMethods(Class<?> implementation,
 577  
                                              Class<?>[] parameterTypes,
 578  
                                              boolean voidOk,
 579  
                                              boolean matchOnObject,
 580  
                                              Collection<String> ignoredMethodNames,
 581  
                                              WildcardFilter filter)
 582  
     {
 583  0
         List<Method> result = new ArrayList<Method>();
 584  
 
 585  0
         if (ignoredMethodNames == null)
 586  
         {
 587  0
             ignoredMethodNames = Collections.emptySet();
 588  
         }
 589  
 
 590  0
         Method[] methods = implementation.getMethods();
 591  0
         for (int i = 0; i < methods.length; i++)
 592  
         {
 593  0
             Method method = methods[i];
 594  
             //supporting wildcards
 595  0
             if (filter != null && filter.accept(method.getName()))
 596  
             {
 597  0
                 continue;
 598  
             }
 599  0
             Class<?>[] methodParams = method.getParameterTypes();
 600  
 
 601  0
             if (compare(methodParams, parameterTypes, matchOnObject))
 602  
             {
 603  0
                 if (!ignoredMethodNames.contains(method.getName()))
 604  
                 {
 605  0
                     String returnType = method.getReturnType().getName();
 606  0
                     if ((returnType.equals("void") && voidOk) || !returnType.equals("void"))
 607  
                     {
 608  0
                         result.add(method);
 609  
                     }
 610  
                 }
 611  
             }
 612  
         }
 613  
 
 614  0
         return result;
 615  
     }
 616  
 
 617  
     /**
 618  
      * Match all method son a class with a defined return type
 619  
      * @param implementation the class to search
 620  
      * @param returnType the return type to match
 621  
      * @param matchOnObject whether {@link Object} methods should be matched
 622  
      * @param ignoredMethodNames a set of method names to ignore
 623  
      * @return the list of methods that matched the return type and criteria. If none are found an empty result is returned
 624  
      */
 625  
     public static List<Method> getSatisfiableMethodsWithReturnType(Class implementation,
 626  
                                                            Class returnType,
 627  
                                                            boolean matchOnObject,
 628  
                                                            Set<String> ignoredMethodNames)
 629  
     {
 630  0
         List<Method> result = new ArrayList<Method>();
 631  
 
 632  0
         if (ignoredMethodNames == null)
 633  
         {
 634  0
             ignoredMethodNames = Collections.emptySet();
 635  
         }
 636  
 
 637  0
         Method[] methods = implementation.getMethods();
 638  0
         for (int i = 0; i < methods.length; i++)
 639  
         {
 640  0
             Method method = methods[i];
 641  0
             Class returns = method.getReturnType();
 642  
 
 643  0
             if (compare(new Class[]{returns}, new Class[]{returnType}, matchOnObject))
 644  
             {
 645  0
                 if (!ignoredMethodNames.contains(method.getName()))
 646  
                 {
 647  0
                     result.add(method);
 648  
                 }
 649  
             }
 650  
         }
 651  
 
 652  0
         return result;
 653  
     }
 654  
 
 655  
     /**
 656  
      * Can be used by serice endpoints to select which service to use based on what's
 657  
      * loaded on the classpath
 658  
      *
 659  
      * @param className    The class name to look for
 660  
      * @param currentClass the calling class
 661  
      * @return true if the class is on the path
 662  
      */
 663  
     public static boolean isClassOnPath(String className, Class currentClass)
 664  
     {
 665  
         try
 666  
         {
 667  0
             return (loadClass(className, currentClass) != null);
 668  
         }
 669  0
         catch (ClassNotFoundException e)
 670  
         {
 671  0
             return false;
 672  
         }
 673  
     }
 674  
 
 675  
     /**
 676  
      * Used for creating an array of class types for an array or single object
 677  
      *
 678  
      * @param object single object or array. If this parameter is null or a zero length
 679  
      *               array then {@link #NO_ARGS_TYPE} is returned
 680  
      * @return an array of class types for the object
 681  
      */
 682  
     public static Class<?>[] getClassTypes(Object object)
 683  
     {
 684  0
         if (object == null)
 685  
         {
 686  0
             return NO_ARGS_TYPE;
 687  
         }
 688  
 
 689  
         Class<?>[] types;
 690  
 
 691  0
         if (object instanceof Object[])
 692  
         {
 693  0
             Object[] objects = (Object[]) object;
 694  0
             if (objects.length == 0)
 695  
             {
 696  0
                 return NO_ARGS_TYPE;
 697  
             }
 698  0
             types = new Class[objects.length];
 699  0
             for (int i = 0; i < objects.length; i++)
 700  
             {
 701  0
                 Object o = objects[i];
 702  0
                 if (o != null)
 703  
                 {
 704  0
                     types[i] = o.getClass();
 705  
                 }
 706  
             }
 707  0
         }
 708  
         else
 709  
         {
 710  0
             types = new Class[]{object.getClass()};
 711  
         }
 712  
 
 713  0
         return types;
 714  
     }
 715  
 
 716  
     public static String getClassName(Class clazz)
 717  
     {
 718  0
         if (clazz == null)
 719  
         {
 720  0
             return null;
 721  
         }
 722  0
         String name = clazz.getName();
 723  0
         return name.substring(name.lastIndexOf(".") + 1);
 724  
     }
 725  
 
 726  
     public static boolean compare(Class[] c1, Class[] c2, boolean matchOnObject)
 727  
     {
 728  0
         if (c1.length != c2.length)
 729  
         {
 730  0
             return false;
 731  
         }
 732  0
         for (int i = 0; i < c1.length; i++)
 733  
         {
 734  0
             if ((c1[i] == null) || (c2[i] == null))
 735  
             {
 736  0
                 return false;
 737  
             }
 738  0
             if (c1[i].equals(Object.class) && !matchOnObject)
 739  
             {
 740  0
                 return false;
 741  
             }
 742  0
             if (!c1[i].isAssignableFrom(c2[i]))
 743  
             {
 744  0
                 return false;
 745  
             }
 746  
         }
 747  0
         return true;
 748  
     }
 749  
 
 750  
     public static Class wrapperToPrimitive(Class wrapper)
 751  
     {
 752  0
         return (Class) MapUtils.getObject(wrapperToPrimitiveMap, wrapper, wrapper);
 753  
     }
 754  
 
 755  
     public static Class[] wrappersToPrimitives(Class[] wrappers)
 756  
     {
 757  0
         if (wrappers == null)
 758  
         {
 759  0
             return null;
 760  
         }
 761  
 
 762  0
         if (wrappers.length == 0)
 763  
         {
 764  0
             return wrappers;
 765  
         }
 766  
 
 767  0
         Class[] primitives = new Class[wrappers.length];
 768  
 
 769  0
         for (int i = 0; i < wrappers.length; i++)
 770  
         {
 771  0
             primitives[i] = (Class) MapUtils.getObject(wrapperToPrimitiveMap, wrappers[i], wrappers[i]);
 772  
         }
 773  
 
 774  0
         return primitives;
 775  
     }
 776  
 
 777  
     /**
 778  
      * Provide a simple-to-understand class name (with access to only Java 1.4 API).
 779  
      *
 780  
      * @param clazz The class whose name we will generate
 781  
      * @return A readable name for the class
 782  
      */
 783  
     public static String getSimpleName(Class clazz)
 784  
     {
 785  0
         if (null == clazz)
 786  
         {
 787  0
             return "null";
 788  
         }
 789  
         else
 790  
         {
 791  0
             return classNameHelper(new BufferedReader(new CharArrayReader(clazz.getName().toCharArray())));
 792  
         }
 793  
     }
 794  
 
 795  
     private static String classNameHelper(Reader encodedName)
 796  
     {
 797  
         // I did consider separating this data from the code, but I could not find a
 798  
         // solution that was as clear to read, or clearly motivated (these data are not
 799  
         // used elsewhere).
 800  
 
 801  
         try
 802  
         {
 803  0
             encodedName.mark(1);
 804  0
             switch (encodedName.read())
 805  
             {
 806  
                 case -1:
 807  0
                     return "null";
 808  
                 case 'Z':
 809  0
                     return "boolean";
 810  
                 case 'B':
 811  0
                     return "byte";
 812  
                 case 'C':
 813  0
                     return "char";
 814  
                 case 'D':
 815  0
                     return "double";
 816  
                 case 'F':
 817  0
                     return "float";
 818  
                 case 'I':
 819  0
                     return "int";
 820  
                 case 'J':
 821  0
                     return "long";
 822  
                 case 'S':
 823  0
                     return "short";
 824  
                 case '[':
 825  0
                     return classNameHelper(encodedName) + "[]";
 826  
                 case 'L':
 827  0
                     return shorten(new BufferedReader(encodedName).readLine());
 828  
                 default:
 829  0
                     encodedName.reset();
 830  0
                     return shorten(new BufferedReader(encodedName).readLine());
 831  
             }
 832  
         }
 833  0
         catch (IOException e)
 834  
         {
 835  0
             return "unknown type: " + e.getMessage();
 836  
         }
 837  
     }
 838  
 
 839  
     /**
 840  
      * @param clazz A class name (with possible package and trailing semicolon)
 841  
      * @return The short name for the class
 842  
      */
 843  
     private static String shorten(String clazz)
 844  
     {
 845  0
         if (null != clazz && clazz.endsWith(";"))
 846  
         {
 847  0
             clazz = clazz.substring(0, clazz.length() - 1);
 848  
         }
 849  0
         if (null != clazz && clazz.lastIndexOf(".") > -1)
 850  
         {
 851  0
             clazz = clazz.substring(clazz.lastIndexOf(".") + 1, clazz.length());
 852  
         }
 853  0
         return clazz;
 854  
     }
 855  
 
 856  
     /**
 857  
      * Simple helper for writing object equalities.
 858  
      *
 859  
      * TODO Is there a better place for this?
 860  
      * @param a object to compare
 861  
      * @param b object to be compared to
 862  
      * @return true if the objects are equal (value or reference), false otherwise
 863  
      */
 864  
     public static boolean equal(Object a, Object b)
 865  
     {
 866  0
         if (null == a)
 867  
         {
 868  0
             return null == b;
 869  
         }
 870  
         else
 871  
         {
 872  0
             return null != b && a.equals(b);
 873  
         }
 874  
     }
 875  
 
 876  
     public static int hash(Object[] state)
 877  
     {
 878  0
         int hash = 0;
 879  0
         for (int i = 0; i < state.length; ++i)
 880  
         {
 881  0
             hash = hash * 31 + (null == state[i] ? 0 : state[i].hashCode());
 882  
         }
 883  0
         return hash;
 884  
     }
 885  
 
 886  
     public static void addLibrariesToClasspath(List urls) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
 887  
     {
 888  0
         ClassLoader sys = ClassLoader.getSystemClassLoader();
 889  0
         if (!(sys instanceof URLClassLoader))
 890  
         {
 891  0
             throw new IllegalArgumentException(
 892  
                     "PANIC: Mule has been started with an unsupported classloader: " + sys.getClass().getName()
 893  
                             + ". " + "Please report this error to user<at>mule<dot>codehaus<dot>org");
 894  
         }
 895  
 
 896  
         // system classloader is in this case the one that launched the application,
 897  
         // which is usually something like a JDK-vendor proprietary AppClassLoader
 898  0
         URLClassLoader sysCl = (URLClassLoader) sys;
 899  
 
 900  
         /*
 901  
         * IMPORTANT NOTE: The more 'natural' way would be to create a custom
 902  
         * URLClassLoader and configure it, but then there's a chicken-and-egg
 903  
         * problem, as all classes MuleBootstrap depends on would have been loaded by
 904  
         * a parent classloader, and not ours. There's no straightforward way to
 905  
         * change this, and is documented in a Sun's classloader guide. The solution
 906  
         * would've involved overriding the ClassLoader.findClass() method and
 907  
         * modifying the semantics to be child-first, but that way we are calling for
 908  
         * trouble. Hacking the primordial classloader is a bit brutal, but works
 909  
         * perfectly in case of running from the command-line as a standalone app.
 910  
         * All Mule embedding options then delegate the classpath config to the
 911  
         * embedder (a developer embedding Mule in the app), thus classloaders are
 912  
         * not modified in those scenarios.
 913  
         */
 914  
 
 915  
         // get a Method ref from the normal class, but invoke on a proprietary parent
 916  
         // object,
 917  
         // as this method is usually protected in those classloaders
 918  0
         Class refClass = URLClassLoader.class;
 919  0
         Method methodAddUrl = refClass.getDeclaredMethod("addURL", new Class[]{URL.class});
 920  0
         methodAddUrl.setAccessible(true);
 921  0
         for (Iterator it = urls.iterator(); it.hasNext();)
 922  
         {
 923  0
             URL url = (URL) it.next();
 924  0
             methodAddUrl.invoke(sysCl, url);
 925  0
         }
 926  0
     }
 927  
 
 928  
     // this is a shorter version of the snippet from:
 929  
     // http://www.davidflanagan.com/blog/2005_06.html#000060
 930  
     // (see comments; DF's "manual" version works fine too)
 931  
     public static URL getClassPathRoot(Class clazz)
 932  
     {
 933  0
         CodeSource cs = clazz.getProtectionDomain().getCodeSource();
 934  0
         return (cs != null ? cs.getLocation() : null);
 935  
     }
 936  
 }