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