001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.lang3;
018    
019    import java.lang.reflect.Method;
020    import java.lang.reflect.Modifier;
021    import java.util.ArrayList;
022    import java.util.HashMap;
023    import java.util.HashSet;
024    import java.util.LinkedHashSet;
025    import java.util.List;
026    import java.util.Map;
027    
028    
029    /**
030     * <p>Operates on classes without using reflection.</p>
031     *
032     * <p>This class handles invalid {@code null} inputs as best it can.
033     * Each method documents its behaviour in more detail.</p>
034     *
035     * <p>The notion of a {@code canonical name} includes the human
036     * readable name for the type, for example {@code int[]}. The
037     * non-canonical method variants work with the JVM names, such as
038     * {@code [I}. </p>
039     *
040     * @since 2.0
041     * @version $Id: ClassUtils.java 1199894 2011-11-09 17:53:59Z ggregory $
042     */
043    public class ClassUtils {
044    
045        /**
046         * <p>The package separator character: <code>'&#x2e;' == {@value}</code>.</p>
047         */
048        public static final char PACKAGE_SEPARATOR_CHAR = '.';
049    
050        /**
051         * <p>The package separator String: {@code "&#x2e;"}.</p>
052         */
053        public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
054    
055        /**
056         * <p>The inner class separator character: <code>'$' == {@value}</code>.</p>
057         */
058        public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
059    
060        /**
061         * <p>The inner class separator String: {@code "$"}.</p>
062         */
063        public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
064    
065        /**
066         * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}.
067         */
068        private static final Map<Class<?>, Class<?>> primitiveWrapperMap = new HashMap<Class<?>, Class<?>>();
069        static {
070             primitiveWrapperMap.put(Boolean.TYPE, Boolean.class);
071             primitiveWrapperMap.put(Byte.TYPE, Byte.class);
072             primitiveWrapperMap.put(Character.TYPE, Character.class);
073             primitiveWrapperMap.put(Short.TYPE, Short.class);
074             primitiveWrapperMap.put(Integer.TYPE, Integer.class);
075             primitiveWrapperMap.put(Long.TYPE, Long.class);
076             primitiveWrapperMap.put(Double.TYPE, Double.class);
077             primitiveWrapperMap.put(Float.TYPE, Float.class);
078             primitiveWrapperMap.put(Void.TYPE, Void.TYPE);
079        }
080    
081        /**
082         * Maps wrapper {@code Class}es to their corresponding primitive types.
083         */
084        private static final Map<Class<?>, Class<?>> wrapperPrimitiveMap = new HashMap<Class<?>, Class<?>>();
085        static {
086            for (Class<?> primitiveClass : primitiveWrapperMap.keySet()) {
087                Class<?> wrapperClass = primitiveWrapperMap.get(primitiveClass);
088                if (!primitiveClass.equals(wrapperClass)) {
089                    wrapperPrimitiveMap.put(wrapperClass, primitiveClass);
090                }
091            }
092        }
093    
094        /**
095         * Maps a primitive class name to its corresponding abbreviation used in array class names.
096         */
097        private static final Map<String, String> abbreviationMap = new HashMap<String, String>();
098    
099        /**
100         * Maps an abbreviation used in array class names to corresponding primitive class name.
101         */
102        private static final Map<String, String> reverseAbbreviationMap = new HashMap<String, String>();
103    
104        /**
105         * Add primitive type abbreviation to maps of abbreviations.
106         *
107         * @param primitive Canonical name of primitive type
108         * @param abbreviation Corresponding abbreviation of primitive type
109         */
110        private static void addAbbreviation(String primitive, String abbreviation) {
111            abbreviationMap.put(primitive, abbreviation);
112            reverseAbbreviationMap.put(abbreviation, primitive);
113        }
114    
115        /**
116         * Feed abbreviation maps
117         */
118        static {
119            addAbbreviation("int", "I");
120            addAbbreviation("boolean", "Z");
121            addAbbreviation("float", "F");
122            addAbbreviation("long", "J");
123            addAbbreviation("short", "S");
124            addAbbreviation("byte", "B");
125            addAbbreviation("double", "D");
126            addAbbreviation("char", "C");
127        }
128    
129        /**
130         * <p>ClassUtils instances should NOT be constructed in standard programming.
131         * Instead, the class should be used as
132         * {@code ClassUtils.getShortClassName(cls)}.</p>
133         *
134         * <p>This constructor is public to permit tools that require a JavaBean
135         * instance to operate.</p>
136         */
137        public ClassUtils() {
138          super();
139        }
140    
141        // Short class name
142        // ----------------------------------------------------------------------
143        /**
144         * <p>Gets the class name minus the package name for an {@code Object}.</p>
145         *
146         * @param object  the class to get the short name for, may be null
147         * @param valueIfNull  the value to return if null
148         * @return the class name of the object without the package name, or the null value
149         */
150        public static String getShortClassName(Object object, String valueIfNull) {
151            if (object == null) {
152                return valueIfNull;
153            }
154            return getShortClassName(object.getClass());
155        }
156    
157        /**
158         * <p>Gets the class name minus the package name from a {@code Class}.</p>
159         * 
160         * <p>Consider using the Java 5 API {@link Class#getSimpleName()} instead. 
161         * The one known difference is that this code will return {@code "Map.Entry"} while 
162         * the {@code java.lang.Class} variant will simply return {@code "Entry"}. </p>
163         *
164         * @param cls  the class to get the short name for.
165         * @return the class name without the package name or an empty string
166         */
167        public static String getShortClassName(Class<?> cls) {
168            if (cls == null) {
169                return StringUtils.EMPTY;
170            }
171            return getShortClassName(cls.getName());
172        }
173    
174        /**
175         * <p>Gets the class name minus the package name from a String.</p>
176         *
177         * <p>The string passed in is assumed to be a class name - it is not checked.</p>
178    
179         * <p>Note that this method differs from Class.getSimpleName() in that this will 
180         * return {@code "Map.Entry"} whilst the {@code java.lang.Class} variant will simply 
181         * return {@code "Entry"}. </p>
182         *
183         * @param className  the className to get the short name for
184         * @return the class name of the class without the package name or an empty string
185         */
186        public static String getShortClassName(String className) {
187            if (className == null) {
188                return StringUtils.EMPTY;
189            }
190            if (className.length() == 0) {
191                return StringUtils.EMPTY;
192            }
193    
194            StringBuilder arrayPrefix = new StringBuilder();
195    
196            // Handle array encoding
197            if (className.startsWith("[")) {
198                while (className.charAt(0) == '[') {
199                    className = className.substring(1);
200                    arrayPrefix.append("[]");
201                }
202                // Strip Object type encoding
203                if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
204                    className = className.substring(1, className.length() - 1);
205                }
206            }
207    
208            if (reverseAbbreviationMap.containsKey(className)) {
209                className = reverseAbbreviationMap.get(className);
210            }
211    
212            int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
213            int innerIdx = className.indexOf(
214                    INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1);
215            String out = className.substring(lastDotIdx + 1);
216            if (innerIdx != -1) {
217                out = out.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR);
218            }
219            return out + arrayPrefix;
220        }
221    
222        /**
223         * <p>Null-safe version of <code>aClass.getSimpleName()</code></p>
224         *
225         * @param cls the class for which to get the simple name.
226         * @return the simple class name.
227         * @since 3.0
228         * @see Class#getSimpleName()
229         */
230        public static String getSimpleName(Class<?> cls) {
231            if (cls == null) {
232                return StringUtils.EMPTY;
233            }
234            return cls.getSimpleName();
235        }
236    
237        /**
238         * <p>Null-safe version of <code>aClass.getSimpleName()</code></p>
239         *
240         * @param object the object for which to get the simple class name.
241         * @param valueIfNull the value to return if <code>object</code> is <code>null</code>
242         * @return the simple class name.
243         * @since 3.0
244         * @see Class#getSimpleName()
245         */
246        public static String getSimpleName(Object object, String valueIfNull) {
247            if (object == null) {
248                return valueIfNull;
249            }
250            return getSimpleName(object.getClass());
251        }
252    
253        // Package name
254        // ----------------------------------------------------------------------
255        /**
256         * <p>Gets the package name of an {@code Object}.</p>
257         *
258         * @param object  the class to get the package name for, may be null
259         * @param valueIfNull  the value to return if null
260         * @return the package name of the object, or the null value
261         */
262        public static String getPackageName(Object object, String valueIfNull) {
263            if (object == null) {
264                return valueIfNull;
265            }
266            return getPackageName(object.getClass());
267        }
268    
269        /**
270         * <p>Gets the package name of a {@code Class}.</p>
271         *
272         * @param cls  the class to get the package name for, may be {@code null}.
273         * @return the package name or an empty string
274         */
275        public static String getPackageName(Class<?> cls) {
276            if (cls == null) {
277                return StringUtils.EMPTY;
278            }
279            return getPackageName(cls.getName());
280        }
281    
282        /**
283         * <p>Gets the package name from a {@code String}.</p>
284         *
285         * <p>The string passed in is assumed to be a class name - it is not checked.</p>
286         * <p>If the class is unpackaged, return an empty string.</p>
287         *
288         * @param className  the className to get the package name for, may be {@code null}
289         * @return the package name or an empty string
290         */
291        public static String getPackageName(String className) {
292            if (className == null || className.length() == 0) {
293                return StringUtils.EMPTY;
294            }
295    
296            // Strip array encoding
297            while (className.charAt(0) == '[') {
298                className = className.substring(1);
299            }
300            // Strip Object type encoding
301            if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
302                className = className.substring(1);
303            }
304    
305            int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
306            if (i == -1) {
307                return StringUtils.EMPTY;
308            }
309            return className.substring(0, i);
310        }
311    
312        // Superclasses/Superinterfaces
313        // ----------------------------------------------------------------------
314        /**
315         * <p>Gets a {@code List} of superclasses for the given class.</p>
316         *
317         * @param cls  the class to look up, may be {@code null}
318         * @return the {@code List} of superclasses in order going up from this one
319         *  {@code null} if null input
320         */
321        public static List<Class<?>> getAllSuperclasses(Class<?> cls) {
322            if (cls == null) {
323                return null;
324            }
325            List<Class<?>> classes = new ArrayList<Class<?>>();
326            Class<?> superclass = cls.getSuperclass();
327            while (superclass != null) {
328                classes.add(superclass);
329                superclass = superclass.getSuperclass();
330            }
331            return classes;
332        }
333    
334        /**
335         * <p>Gets a {@code List} of all interfaces implemented by the given
336         * class and its superclasses.</p>
337         *
338         * <p>The order is determined by looking through each interface in turn as
339         * declared in the source file and following its hierarchy up. Then each
340         * superclass is considered in the same way. Later duplicates are ignored,
341         * so the order is maintained.</p>
342         *
343         * @param cls  the class to look up, may be {@code null}
344         * @return the {@code List} of interfaces in order,
345         *  {@code null} if null input
346         */
347        public static List<Class<?>> getAllInterfaces(Class<?> cls) {
348            if (cls == null) {
349                return null;
350            }
351    
352            LinkedHashSet<Class<?>> interfacesFound = new LinkedHashSet<Class<?>>();
353            getAllInterfaces(cls, interfacesFound);
354    
355            return new ArrayList<Class<?>>(interfacesFound);
356        }
357    
358        /**
359         * Get the interfaces for the specified class.
360         *
361         * @param cls  the class to look up, may be {@code null}
362         * @param interfacesFound the {@code Set} of interfaces for the class
363         */
364        private static void getAllInterfaces(Class<?> cls, HashSet<Class<?>> interfacesFound) {
365            while (cls != null) {
366                Class<?>[] interfaces = cls.getInterfaces();
367    
368                for (Class<?> i : interfaces) {
369                    if (interfacesFound.add(i)) {
370                        getAllInterfaces(i, interfacesFound);
371                    }
372                }
373    
374                cls = cls.getSuperclass();
375             }
376         }
377    
378        // Convert list
379        // ----------------------------------------------------------------------
380        /**
381         * <p>Given a {@code List} of class names, this method converts them into classes.</p>
382         *
383         * <p>A new {@code List} is returned. If the class name cannot be found, {@code null}
384         * is stored in the {@code List}. If the class name in the {@code List} is
385         * {@code null}, {@code null} is stored in the output {@code List}.</p>
386         *
387         * @param classNames  the classNames to change
388         * @return a {@code List} of Class objects corresponding to the class names,
389         *  {@code null} if null input
390         * @throws ClassCastException if classNames contains a non String entry
391         */
392        public static List<Class<?>> convertClassNamesToClasses(List<String> classNames) {
393            if (classNames == null) {
394                return null;
395            }
396            List<Class<?>> classes = new ArrayList<Class<?>>(classNames.size());
397            for (String className : classNames) {
398                try {
399                    classes.add(Class.forName(className));
400                } catch (Exception ex) {
401                    classes.add(null);
402                }
403            }
404            return classes;
405        }
406    
407        /**
408         * <p>Given a {@code List} of {@code Class} objects, this method converts
409         * them into class names.</p>
410         *
411         * <p>A new {@code List} is returned. {@code null} objects will be copied into
412         * the returned list as {@code null}.</p>
413         *
414         * @param classes  the classes to change
415         * @return a {@code List} of class names corresponding to the Class objects,
416         *  {@code null} if null input
417         * @throws ClassCastException if {@code classes} contains a non-{@code Class} entry
418         */
419        public static List<String> convertClassesToClassNames(List<Class<?>> classes) {
420            if (classes == null) {
421                return null;
422            }
423            List<String> classNames = new ArrayList<String>(classes.size());
424            for (Class<?> cls : classes) {
425                if (cls == null) {
426                    classNames.add(null);
427                } else {
428                    classNames.add(cls.getName());
429                }
430            }
431            return classNames;
432        }
433    
434        // Is assignable
435        // ----------------------------------------------------------------------
436        /**
437         * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
438         *
439         * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each
440         * Class pair in the input arrays. It can be used to check if a set of arguments
441         * (the first parameter) are suitably compatible with a set of method parameter types
442         * (the second parameter).</p>
443         *
444         * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
445         * method takes into account widenings of primitive classes and
446         * {@code null}s.</p>
447         *
448         * <p>Primitive widenings allow an int to be assigned to a {@code long},
449         * {@code float} or {@code double}. This method returns the correct
450         * result for these cases.</p>
451         *
452         * <p>{@code Null} may be assigned to any reference type. This method will
453         * return {@code true} if {@code null} is passed in and the toClass is
454         * non-primitive.</p>
455         *
456         * <p>Specifically, this method tests whether the type represented by the
457         * specified {@code Class} parameter can be converted to the type
458         * represented by this {@code Class} object via an identity conversion
459         * widening primitive or widening reference conversion. See
460         * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
461         * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
462         *
463         * <p><strong>Since Lang 3.0,</strong> this method will default behavior for
464         * calculating assignability between primitive and wrapper types <em>corresponding
465         * to the running Java version</em>; i.e. autoboxing will be the default
466         * behavior in VMs running Java versions >= 1.5.</p>
467         *
468         * @param classArray  the array of Classes to check, may be {@code null}
469         * @param toClassArray  the array of Classes to try to assign into, may be {@code null}
470         * @return {@code true} if assignment possible
471         */
472        public static boolean isAssignable(Class<?>[] classArray, Class<?>... toClassArray) {
473            return isAssignable(classArray, toClassArray, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_5));
474        }
475    
476        /**
477         * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
478         *
479         * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each
480         * Class pair in the input arrays. It can be used to check if a set of arguments
481         * (the first parameter) are suitably compatible with a set of method parameter types
482         * (the second parameter).</p>
483         *
484         * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
485         * method takes into account widenings of primitive classes and
486         * {@code null}s.</p>
487         *
488         * <p>Primitive widenings allow an int to be assigned to a {@code long},
489         * {@code float} or {@code double}. This method returns the correct
490         * result for these cases.</p>
491         *
492         * <p>{@code Null} may be assigned to any reference type. This method will
493         * return {@code true} if {@code null} is passed in and the toClass is
494         * non-primitive.</p>
495         *
496         * <p>Specifically, this method tests whether the type represented by the
497         * specified {@code Class} parameter can be converted to the type
498         * represented by this {@code Class} object via an identity conversion
499         * widening primitive or widening reference conversion. See
500         * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
501         * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
502         *
503         * @param classArray  the array of Classes to check, may be {@code null}
504         * @param toClassArray  the array of Classes to try to assign into, may be {@code null}
505         * @param autoboxing  whether to use implicit autoboxing/unboxing between primitives and wrappers
506         * @return {@code true} if assignment possible
507         */
508        public static boolean isAssignable(Class<?>[] classArray, Class<?>[] toClassArray, boolean autoboxing) {
509            if (ArrayUtils.isSameLength(classArray, toClassArray) == false) {
510                return false;
511            }
512            if (classArray == null) {
513                classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
514            }
515            if (toClassArray == null) {
516                toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
517            }
518            for (int i = 0; i < classArray.length; i++) {
519                if (isAssignable(classArray[i], toClassArray[i], autoboxing) == false) {
520                    return false;
521                }
522            }
523            return true;
524        }
525    
526        /**
527         * Returns whether the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character},
528         * {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
529         * 
530         * @param type
531         *            The class to query or null.
532         * @return true if the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character},
533         *         {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
534         * @since 3.1
535         */
536        public static boolean isPrimitiveOrWrapper(Class<?> type) {
537            if (type == null) {
538                return false;
539            }
540            return type.isPrimitive() || isPrimitiveWrapper(type);
541        }
542    
543        /**
544         * Returns whether the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short},
545         * {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
546         * 
547         * @param type
548         *            The class to query or null.
549         * @return true if the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short},
550         *         {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
551         * @since 3.1
552         */
553        public static boolean isPrimitiveWrapper(Class<?> type) {
554            return wrapperPrimitiveMap.containsKey(type);
555        }
556    
557        /**
558         * <p>Checks if one {@code Class} can be assigned to a variable of
559         * another {@code Class}.</p>
560         *
561         * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
562         * this method takes into account widenings of primitive classes and
563         * {@code null}s.</p>
564         *
565         * <p>Primitive widenings allow an int to be assigned to a long, float or
566         * double. This method returns the correct result for these cases.</p>
567         *
568         * <p>{@code Null} may be assigned to any reference type. This method
569         * will return {@code true} if {@code null} is passed in and the
570         * toClass is non-primitive.</p>
571         *
572         * <p>Specifically, this method tests whether the type represented by the
573         * specified {@code Class} parameter can be converted to the type
574         * represented by this {@code Class} object via an identity conversion
575         * widening primitive or widening reference conversion. See
576         * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
577         * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
578         *
579         * <p><strong>Since Lang 3.0,</strong> this method will default behavior for
580         * calculating assignability between primitive and wrapper types <em>corresponding
581         * to the running Java version</em>; i.e. autoboxing will be the default
582         * behavior in VMs running Java versions >= 1.5.</p>
583         *
584         * @param cls  the Class to check, may be null
585         * @param toClass  the Class to try to assign into, returns false if null
586         * @return {@code true} if assignment possible
587         */
588        public static boolean isAssignable(Class<?> cls, Class<?> toClass) {
589            return isAssignable(cls, toClass, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_5));
590        }
591    
592        /**
593         * <p>Checks if one {@code Class} can be assigned to a variable of
594         * another {@code Class}.</p>
595         *
596         * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
597         * this method takes into account widenings of primitive classes and
598         * {@code null}s.</p>
599         *
600         * <p>Primitive widenings allow an int to be assigned to a long, float or
601         * double. This method returns the correct result for these cases.</p>
602         *
603         * <p>{@code Null} may be assigned to any reference type. This method
604         * will return {@code true} if {@code null} is passed in and the
605         * toClass is non-primitive.</p>
606         *
607         * <p>Specifically, this method tests whether the type represented by the
608         * specified {@code Class} parameter can be converted to the type
609         * represented by this {@code Class} object via an identity conversion
610         * widening primitive or widening reference conversion. See
611         * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
612         * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
613         *
614         * @param cls  the Class to check, may be null
615         * @param toClass  the Class to try to assign into, returns false if null
616         * @param autoboxing  whether to use implicit autoboxing/unboxing between primitives and wrappers
617         * @return {@code true} if assignment possible
618         */
619        public static boolean isAssignable(Class<?> cls, Class<?> toClass, boolean autoboxing) {
620            if (toClass == null) {
621                return false;
622            }
623            // have to check for null, as isAssignableFrom doesn't
624            if (cls == null) {
625                return !toClass.isPrimitive();
626            }
627            //autoboxing:
628            if (autoboxing) {
629                if (cls.isPrimitive() && !toClass.isPrimitive()) {
630                    cls = primitiveToWrapper(cls);
631                    if (cls == null) {
632                        return false;
633                    }
634                }
635                if (toClass.isPrimitive() && !cls.isPrimitive()) {
636                    cls = wrapperToPrimitive(cls);
637                    if (cls == null) {
638                        return false;
639                    }
640                }
641            }
642            if (cls.equals(toClass)) {
643                return true;
644            }
645            if (cls.isPrimitive()) {
646                if (toClass.isPrimitive() == false) {
647                    return false;
648                }
649                if (Integer.TYPE.equals(cls)) {
650                    return Long.TYPE.equals(toClass)
651                        || Float.TYPE.equals(toClass)
652                        || Double.TYPE.equals(toClass);
653                }
654                if (Long.TYPE.equals(cls)) {
655                    return Float.TYPE.equals(toClass)
656                        || Double.TYPE.equals(toClass);
657                }
658                if (Boolean.TYPE.equals(cls)) {
659                    return false;
660                }
661                if (Double.TYPE.equals(cls)) {
662                    return false;
663                }
664                if (Float.TYPE.equals(cls)) {
665                    return Double.TYPE.equals(toClass);
666                }
667                if (Character.TYPE.equals(cls)) {
668                    return Integer.TYPE.equals(toClass)
669                        || Long.TYPE.equals(toClass)
670                        || Float.TYPE.equals(toClass)
671                        || Double.TYPE.equals(toClass);
672                }
673                if (Short.TYPE.equals(cls)) {
674                    return Integer.TYPE.equals(toClass)
675                        || Long.TYPE.equals(toClass)
676                        || Float.TYPE.equals(toClass)
677                        || Double.TYPE.equals(toClass);
678                }
679                if (Byte.TYPE.equals(cls)) {
680                    return Short.TYPE.equals(toClass)
681                        || Integer.TYPE.equals(toClass)
682                        || Long.TYPE.equals(toClass)
683                        || Float.TYPE.equals(toClass)
684                        || Double.TYPE.equals(toClass);
685                }
686                // should never get here
687                return false;
688            }
689            return toClass.isAssignableFrom(cls);
690        }
691    
692        /**
693         * <p>Converts the specified primitive Class object to its corresponding
694         * wrapper Class object.</p>
695         *
696         * <p>NOTE: From v2.2, this method handles {@code Void.TYPE},
697         * returning {@code Void.TYPE}.</p>
698         *
699         * @param cls  the class to convert, may be null
700         * @return the wrapper class for {@code cls} or {@code cls} if
701         * {@code cls} is not a primitive. {@code null} if null input.
702         * @since 2.1
703         */
704        public static Class<?> primitiveToWrapper(Class<?> cls) {
705            Class<?> convertedClass = cls;
706            if (cls != null && cls.isPrimitive()) {
707                convertedClass = primitiveWrapperMap.get(cls);
708            }
709            return convertedClass;
710        }
711    
712        /**
713         * <p>Converts the specified array of primitive Class objects to an array of
714         * its corresponding wrapper Class objects.</p>
715         *
716         * @param classes  the class array to convert, may be null or empty
717         * @return an array which contains for each given class, the wrapper class or
718         * the original class if class is not a primitive. {@code null} if null input.
719         * Empty array if an empty array passed in.
720         * @since 2.1
721         */
722        public static Class<?>[] primitivesToWrappers(Class<?>... classes) {
723            if (classes == null) {
724                return null;
725            }
726    
727            if (classes.length == 0) {
728                return classes;
729            }
730    
731            Class<?>[] convertedClasses = new Class[classes.length];
732            for (int i = 0; i < classes.length; i++) {
733                convertedClasses[i] = primitiveToWrapper(classes[i]);
734            }
735            return convertedClasses;
736        }
737    
738        /**
739         * <p>Converts the specified wrapper class to its corresponding primitive
740         * class.</p>
741         *
742         * <p>This method is the counter part of {@code primitiveToWrapper()}.
743         * If the passed in class is a wrapper class for a primitive type, this
744         * primitive type will be returned (e.g. {@code Integer.TYPE} for
745         * {@code Integer.class}). For other classes, or if the parameter is
746         * <b>null</b>, the return value is <b>null</b>.</p>
747         *
748         * @param cls the class to convert, may be <b>null</b>
749         * @return the corresponding primitive type if {@code cls} is a
750         * wrapper class, <b>null</b> otherwise
751         * @see #primitiveToWrapper(Class)
752         * @since 2.4
753         */
754        public static Class<?> wrapperToPrimitive(Class<?> cls) {
755            return wrapperPrimitiveMap.get(cls);
756        }
757    
758        /**
759         * <p>Converts the specified array of wrapper Class objects to an array of
760         * its corresponding primitive Class objects.</p>
761         *
762         * <p>This method invokes {@code wrapperToPrimitive()} for each element
763         * of the passed in array.</p>
764         *
765         * @param classes  the class array to convert, may be null or empty
766         * @return an array which contains for each given class, the primitive class or
767         * <b>null</b> if the original class is not a wrapper class. {@code null} if null input.
768         * Empty array if an empty array passed in.
769         * @see #wrapperToPrimitive(Class)
770         * @since 2.4
771         */
772        public static Class<?>[] wrappersToPrimitives(Class<?>... classes) {
773            if (classes == null) {
774                return null;
775            }
776    
777            if (classes.length == 0) {
778                return classes;
779            }
780    
781            Class<?>[] convertedClasses = new Class[classes.length];
782            for (int i = 0; i < classes.length; i++) {
783                convertedClasses[i] = wrapperToPrimitive(classes[i]);
784            }
785            return convertedClasses;
786        }
787    
788        // Inner class
789        // ----------------------------------------------------------------------
790        /**
791         * <p>Is the specified class an inner class or static nested class.</p>
792         *
793         * @param cls  the class to check, may be null
794         * @return {@code true} if the class is an inner or static nested class,
795         *  false if not or {@code null}
796         */
797        public static boolean isInnerClass(Class<?> cls) {
798            return cls != null && cls.getEnclosingClass() != null;
799        }
800    
801        // Class loading
802        // ----------------------------------------------------------------------
803        /**
804         * Returns the class represented by {@code className} using the
805         * {@code classLoader}.  This implementation supports the syntaxes
806         * "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
807         * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
808         *
809         * @param classLoader  the class loader to use to load the class
810         * @param className  the class name
811         * @param initialize  whether the class must be initialized
812         * @return the class represented by {@code className} using the {@code classLoader}
813         * @throws ClassNotFoundException if the class is not found
814         */
815        public static Class<?> getClass(
816                ClassLoader classLoader, String className, boolean initialize) throws ClassNotFoundException {
817            try {
818                Class<?> clazz;
819                if (abbreviationMap.containsKey(className)) {
820                    String clsName = "[" + abbreviationMap.get(className);
821                    clazz = Class.forName(clsName, initialize, classLoader).getComponentType();
822                } else {
823                    clazz = Class.forName(toCanonicalName(className), initialize, classLoader);
824                }
825                return clazz;
826            } catch (ClassNotFoundException ex) {
827                // allow path separators (.) as inner class name separators
828                int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
829    
830                if (lastDotIndex != -1) {
831                    try {
832                        return getClass(classLoader, className.substring(0, lastDotIndex) +
833                                INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1),
834                                initialize);
835                    } catch (ClassNotFoundException ex2) { // NOPMD
836                        // ignore exception
837                    }
838                }
839    
840                throw ex;
841            }
842        }
843    
844        /**
845         * Returns the (initialized) class represented by {@code className}
846         * using the {@code classLoader}.  This implementation supports
847         * the syntaxes "{@code java.util.Map.Entry[]}",
848         * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}",
849         * and "{@code [Ljava.util.Map$Entry;}".
850         *
851         * @param classLoader  the class loader to use to load the class
852         * @param className  the class name
853         * @return the class represented by {@code className} using the {@code classLoader}
854         * @throws ClassNotFoundException if the class is not found
855         */
856        public static Class<?> getClass(ClassLoader classLoader, String className) throws ClassNotFoundException {
857            return getClass(classLoader, className, true);
858        }
859    
860        /**
861         * Returns the (initialized) class represented by {@code className}
862         * using the current thread's context class loader. This implementation
863         * supports the syntaxes "{@code java.util.Map.Entry[]}",
864         * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}",
865         * and "{@code [Ljava.util.Map$Entry;}".
866         *
867         * @param className  the class name
868         * @return the class represented by {@code className} using the current thread's context class loader
869         * @throws ClassNotFoundException if the class is not found
870         */
871        public static Class<?> getClass(String className) throws ClassNotFoundException {
872            return getClass(className, true);
873        }
874    
875        /**
876         * Returns the class represented by {@code className} using the
877         * current thread's context class loader. This implementation supports the
878         * syntaxes "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
879         * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
880         *
881         * @param className  the class name
882         * @param initialize  whether the class must be initialized
883         * @return the class represented by {@code className} using the current thread's context class loader
884         * @throws ClassNotFoundException if the class is not found
885         */
886        public static Class<?> getClass(String className, boolean initialize) throws ClassNotFoundException {
887            ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
888            ClassLoader loader = contextCL == null ? ClassUtils.class.getClassLoader() : contextCL;
889            return getClass(loader, className, initialize);
890        }
891    
892        // Public method
893        // ----------------------------------------------------------------------
894        /**
895         * <p>Returns the desired Method much like {@code Class.getMethod}, however
896         * it ensures that the returned Method is from a public class or interface and not
897         * from an anonymous inner class. This means that the Method is invokable and
898         * doesn't fall foul of Java bug
899         * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957">4071957</a>).
900         *
901         *  <code><pre>Set set = Collections.unmodifiableSet(...);
902         *  Method method = ClassUtils.getPublicMethod(set.getClass(), "isEmpty",  new Class[0]);
903         *  Object result = method.invoke(set, new Object[]);</pre></code>
904         * </p>
905         *
906         * @param cls  the class to check, not null
907         * @param methodName  the name of the method
908         * @param parameterTypes  the list of parameters
909         * @return the method
910         * @throws NullPointerException if the class is null
911         * @throws SecurityException if a a security violation occured
912         * @throws NoSuchMethodException if the method is not found in the given class
913         *  or if the metothod doen't conform with the requirements
914         */
915        public static Method getPublicMethod(Class<?> cls, String methodName, Class<?>... parameterTypes)
916                throws SecurityException, NoSuchMethodException {
917    
918            Method declaredMethod = cls.getMethod(methodName, parameterTypes);
919            if (Modifier.isPublic(declaredMethod.getDeclaringClass().getModifiers())) {
920                return declaredMethod;
921            }
922    
923            List<Class<?>> candidateClasses = new ArrayList<Class<?>>();
924            candidateClasses.addAll(getAllInterfaces(cls));
925            candidateClasses.addAll(getAllSuperclasses(cls));
926    
927            for (Class<?> candidateClass : candidateClasses) {
928                if (!Modifier.isPublic(candidateClass.getModifiers())) {
929                    continue;
930                }
931                Method candidateMethod;
932                try {
933                    candidateMethod = candidateClass.getMethod(methodName, parameterTypes);
934                } catch (NoSuchMethodException ex) {
935                    continue;
936                }
937                if (Modifier.isPublic(candidateMethod.getDeclaringClass().getModifiers())) {
938                    return candidateMethod;
939                }
940            }
941    
942            throw new NoSuchMethodException("Can't find a public method for " +
943                    methodName + " " + ArrayUtils.toString(parameterTypes));
944        }
945    
946        // ----------------------------------------------------------------------
947        /**
948         * Converts a class name to a JLS style class name.
949         *
950         * @param className  the class name
951         * @return the converted name
952         */
953        private static String toCanonicalName(String className) {
954            className = StringUtils.deleteWhitespace(className);
955            if (className == null) {
956                throw new NullPointerException("className must not be null.");
957            } else if (className.endsWith("[]")) {
958                StringBuilder classNameBuffer = new StringBuilder();
959                while (className.endsWith("[]")) {
960                    className = className.substring(0, className.length() - 2);
961                    classNameBuffer.append("[");
962                }
963                String abbreviation = abbreviationMap.get(className);
964                if (abbreviation != null) {
965                    classNameBuffer.append(abbreviation);
966                } else {
967                    classNameBuffer.append("L").append(className).append(";");
968                }
969                className = classNameBuffer.toString();
970            }
971            return className;
972        }
973    
974        /**
975         * <p>Converts an array of {@code Object} in to an array of {@code Class} objects.
976         * If any of these objects is null, a null element will be inserted into the array.</p>
977         *
978         * <p>This method returns {@code null} for a {@code null} input array.</p>
979         *
980         * @param array an {@code Object} array
981         * @return a {@code Class} array, {@code null} if null array input
982         * @since 2.4
983         */
984        public static Class<?>[] toClass(Object... array) {
985            if (array == null) {
986                return null;
987            } else if (array.length == 0) {
988                return ArrayUtils.EMPTY_CLASS_ARRAY;
989            }
990            Class<?>[] classes = new Class[array.length];
991            for (int i = 0; i < array.length; i++) {
992                classes[i] = array[i] == null ? null : array[i].getClass();
993            }
994            return classes;
995        }
996    
997        // Short canonical name
998        // ----------------------------------------------------------------------
999        /**
1000         * <p>Gets the canonical name minus the package name for an {@code Object}.</p>
1001         *
1002         * @param object  the class to get the short name for, may be null
1003         * @param valueIfNull  the value to return if null
1004         * @return the canonical name of the object without the package name, or the null value
1005         * @since 2.4
1006         */
1007        public static String getShortCanonicalName(Object object, String valueIfNull) {
1008            if (object == null) {
1009                return valueIfNull;
1010            }
1011            return getShortCanonicalName(object.getClass().getName());
1012        }
1013    
1014        /**
1015         * <p>Gets the canonical name minus the package name from a {@code Class}.</p>
1016         *
1017         * @param cls  the class to get the short name for.
1018         * @return the canonical name without the package name or an empty string
1019         * @since 2.4
1020         */
1021        public static String getShortCanonicalName(Class<?> cls) {
1022            if (cls == null) {
1023                return StringUtils.EMPTY;
1024            }
1025            return getShortCanonicalName(cls.getName());
1026        }
1027    
1028        /**
1029         * <p>Gets the canonical name minus the package name from a String.</p>
1030         *
1031         * <p>The string passed in is assumed to be a canonical name - it is not checked.</p>
1032         *
1033         * @param canonicalName  the class name to get the short name for
1034         * @return the canonical name of the class without the package name or an empty string
1035         * @since 2.4
1036         */
1037        public static String getShortCanonicalName(String canonicalName) {
1038            return ClassUtils.getShortClassName(getCanonicalName(canonicalName));
1039        }
1040    
1041        // Package name
1042        // ----------------------------------------------------------------------
1043        /**
1044         * <p>Gets the package name from the canonical name of an {@code Object}.</p>
1045         *
1046         * @param object  the class to get the package name for, may be null
1047         * @param valueIfNull  the value to return if null
1048         * @return the package name of the object, or the null value
1049         * @since 2.4
1050         */
1051        public static String getPackageCanonicalName(Object object, String valueIfNull) {
1052            if (object == null) {
1053                return valueIfNull;
1054            }
1055            return getPackageCanonicalName(object.getClass().getName());
1056        }
1057    
1058        /**
1059         * <p>Gets the package name from the canonical name of a {@code Class}.</p>
1060         *
1061         * @param cls  the class to get the package name for, may be {@code null}.
1062         * @return the package name or an empty string
1063         * @since 2.4
1064         */
1065        public static String getPackageCanonicalName(Class<?> cls) {
1066            if (cls == null) {
1067                return StringUtils.EMPTY;
1068            }
1069            return getPackageCanonicalName(cls.getName());
1070        }
1071    
1072        /**
1073         * <p>Gets the package name from the canonical name. </p>
1074         *
1075         * <p>The string passed in is assumed to be a canonical name - it is not checked.</p>
1076         * <p>If the class is unpackaged, return an empty string.</p>
1077         *
1078         * @param canonicalName  the canonical name to get the package name for, may be {@code null}
1079         * @return the package name or an empty string
1080         * @since 2.4
1081         */
1082        public static String getPackageCanonicalName(String canonicalName) {
1083            return ClassUtils.getPackageName(getCanonicalName(canonicalName));
1084        }
1085    
1086        /**
1087         * <p>Converts a given name of class into canonical format.
1088         * If name of class is not a name of array class it returns
1089         * unchanged name.</p>
1090         * <p>Example:
1091         * <ul>
1092         * <li>{@code getCanonicalName("[I") = "int[]"}</li>
1093         * <li>{@code getCanonicalName("[Ljava.lang.String;") = "java.lang.String[]"}</li>
1094         * <li>{@code getCanonicalName("java.lang.String") = "java.lang.String"}</li>
1095         * </ul>
1096         * </p>
1097         *
1098         * @param className the name of class
1099         * @return canonical form of class name
1100         * @since 2.4
1101         */
1102        private static String getCanonicalName(String className) {
1103            className = StringUtils.deleteWhitespace(className);
1104            if (className == null) {
1105                return null;
1106            } else {
1107                int dim = 0;
1108                while (className.startsWith("[")) {
1109                    dim++;
1110                    className = className.substring(1);
1111                }
1112                if (dim < 1) {
1113                    return className;
1114                } else {
1115                    if (className.startsWith("L")) {
1116                        className = className.substring(
1117                            1,
1118                            className.endsWith(";")
1119                                ? className.length() - 1
1120                                : className.length());
1121                    } else {
1122                        if (className.length() > 0) {
1123                            className = reverseAbbreviationMap.get(className.substring(0, 1));
1124                        }
1125                    }
1126                    StringBuilder canonicalClassNameBuffer = new StringBuilder(className);
1127                    for (int i = 0; i < dim; i++) {
1128                        canonicalClassNameBuffer.append("[]");
1129                    }
1130                    return canonicalClassNameBuffer.toString();
1131                }
1132            }
1133        }
1134    
1135    }