View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3;
18  
19  import java.lang.reflect.Method;
20  import java.lang.reflect.Modifier;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.LinkedHashSet;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Set;
30  
31  import org.apache.commons.lang3.mutable.MutableObject;
32  
33  /**
34   * <p>Operates on classes without using reflection.</p>
35   *
36   * <p>This class handles invalid {@code null} inputs as best it can.
37   * Each method documents its behaviour in more detail.</p>
38   *
39   * <p>The notion of a {@code canonical name} includes the human
40   * readable name for the type, for example {@code int[]}. The
41   * non-canonical method variants work with the JVM names, such as
42   * {@code [I}. </p>
43   *
44   * @since 2.0
45   */
46  public class ClassUtils {
47  
48      /**
49       * Inclusivity literals for {@link #hierarchy(Class, Interfaces)}.
50       * @since 3.2
51       */
52      public enum Interfaces {
53          INCLUDE, EXCLUDE
54      }
55  
56      /**
57       * The package separator character: <code>'&#x2e;' == {@value}</code>.
58       */
59      public static final char PACKAGE_SEPARATOR_CHAR = '.';
60  
61      /**
62       * The package separator String: <code>"&#x2e;"</code>.
63       */
64      public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
65  
66      /**
67       * The inner class separator character: <code>'$' == {@value}</code>.
68       */
69      public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
70  
71      /**
72       * The inner class separator String: {@code "$"}.
73       */
74      public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
75  
76      /**
77       * Maps names of primitives to their corresponding primitive {@code Class}es.
78       */
79      private static final Map<String, Class<?>> namePrimitiveMap = new HashMap<>();
80      static {
81           namePrimitiveMap.put("boolean", Boolean.TYPE);
82           namePrimitiveMap.put("byte", Byte.TYPE);
83           namePrimitiveMap.put("char", Character.TYPE);
84           namePrimitiveMap.put("short", Short.TYPE);
85           namePrimitiveMap.put("int", Integer.TYPE);
86           namePrimitiveMap.put("long", Long.TYPE);
87           namePrimitiveMap.put("double", Double.TYPE);
88           namePrimitiveMap.put("float", Float.TYPE);
89           namePrimitiveMap.put("void", Void.TYPE);
90      }
91  
92      /**
93       * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}.
94       */
95      private static final Map<Class<?>, Class<?>> primitiveWrapperMap = new HashMap<>();
96      static {
97           primitiveWrapperMap.put(Boolean.TYPE, Boolean.class);
98           primitiveWrapperMap.put(Byte.TYPE, Byte.class);
99           primitiveWrapperMap.put(Character.TYPE, Character.class);
100          primitiveWrapperMap.put(Short.TYPE, Short.class);
101          primitiveWrapperMap.put(Integer.TYPE, Integer.class);
102          primitiveWrapperMap.put(Long.TYPE, Long.class);
103          primitiveWrapperMap.put(Double.TYPE, Double.class);
104          primitiveWrapperMap.put(Float.TYPE, Float.class);
105          primitiveWrapperMap.put(Void.TYPE, Void.TYPE);
106     }
107 
108     /**
109      * Maps wrapper {@code Class}es to their corresponding primitive types.
110      */
111     private static final Map<Class<?>, Class<?>> wrapperPrimitiveMap = new HashMap<>();
112     static {
113         for (final Map.Entry<Class<?>, Class<?>> entry : primitiveWrapperMap.entrySet()) {
114             final Class<?> primitiveClass = entry.getKey();
115             final Class<?> wrapperClass = entry.getValue();
116             if (!primitiveClass.equals(wrapperClass)) {
117                 wrapperPrimitiveMap.put(wrapperClass, primitiveClass);
118             }
119         }
120     }
121 
122     /**
123      * Maps a primitive class name to its corresponding abbreviation used in array class names.
124      */
125     private static final Map<String, String> abbreviationMap;
126 
127     /**
128      * Maps an abbreviation used in array class names to corresponding primitive class name.
129      */
130     private static final Map<String, String> reverseAbbreviationMap;
131 
132     /**
133      * Feed abbreviation maps
134      */
135     static {
136         final Map<String, String> m = new HashMap<>();
137         m.put("int", "I");
138         m.put("boolean", "Z");
139         m.put("float", "F");
140         m.put("long", "J");
141         m.put("short", "S");
142         m.put("byte", "B");
143         m.put("double", "D");
144         m.put("char", "C");
145         final Map<String, String> r = new HashMap<>();
146         for (final Map.Entry<String, String> e : m.entrySet()) {
147             r.put(e.getValue(), e.getKey());
148         }
149         abbreviationMap = Collections.unmodifiableMap(m);
150         reverseAbbreviationMap = Collections.unmodifiableMap(r);
151     }
152 
153     /**
154      * <p>ClassUtils instances should NOT be constructed in standard programming.
155      * Instead, the class should be used as
156      * {@code ClassUtils.getShortClassName(cls)}.</p>
157      *
158      * <p>This constructor is public to permit tools that require a JavaBean
159      * instance to operate.</p>
160      */
161     public ClassUtils() {
162       super();
163     }
164 
165     // Short class name
166     // ----------------------------------------------------------------------
167     /**
168      * <p>Gets the class name minus the package name for an {@code Object}.</p>
169      *
170      * @param object  the class to get the short name for, may be null
171      * @param valueIfNull  the value to return if null
172      * @return the class name of the object without the package name, or the null value
173      */
174     public static String getShortClassName(final Object object, final String valueIfNull) {
175         if (object == null) {
176             return valueIfNull;
177         }
178         return getShortClassName(object.getClass());
179     }
180 
181     /**
182      * <p>Gets the class name minus the package name from a {@code Class}.</p>
183      *
184      * <p>Consider using the Java 5 API {@link Class#getSimpleName()} instead.
185      * The one known difference is that this code will return {@code "Map.Entry"} while
186      * the {@code java.lang.Class} variant will simply return {@code "Entry"}. </p>
187      *
188      * @param cls  the class to get the short name for.
189      * @return the class name without the package name or an empty string
190      */
191     public static String getShortClassName(final Class<?> cls) {
192         if (cls == null) {
193             return StringUtils.EMPTY;
194         }
195         return getShortClassName(cls.getName());
196     }
197 
198     /**
199      * <p>Gets the class name minus the package name from a String.</p>
200      *
201      * <p>The string passed in is assumed to be a class name - it is not checked.</p>
202 
203      * <p>Note that this method differs from Class.getSimpleName() in that this will
204      * return {@code "Map.Entry"} whilst the {@code java.lang.Class} variant will simply
205      * return {@code "Entry"}. </p>
206      *
207      * @param className  the className to get the short name for
208      * @return the class name of the class without the package name or an empty string
209      */
210     public static String getShortClassName(String className) {
211         if (StringUtils.isEmpty(className)) {
212             return StringUtils.EMPTY;
213         }
214 
215         final StringBuilder arrayPrefix = new StringBuilder();
216 
217         // Handle array encoding
218         if (className.startsWith("[")) {
219             while (className.charAt(0) == '[') {
220                 className = className.substring(1);
221                 arrayPrefix.append("[]");
222             }
223             // Strip Object type encoding
224             if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
225                 className = className.substring(1, className.length() - 1);
226             }
227 
228             if (reverseAbbreviationMap.containsKey(className)) {
229                 className = reverseAbbreviationMap.get(className);
230             }
231         }
232 
233         final int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
234         final int innerIdx = className.indexOf(
235                 INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1);
236         String out = className.substring(lastDotIdx + 1);
237         if (innerIdx != -1) {
238             out = out.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR);
239         }
240         return out + arrayPrefix;
241     }
242 
243     /**
244      * <p>Null-safe version of <code>aClass.getSimpleName()</code></p>
245      *
246      * @param cls the class for which to get the simple name; may be null
247      * @return the simple class name.
248      * @since 3.0
249      * @see Class#getSimpleName()
250      */
251     public static String getSimpleName(final Class<?> cls) {
252         return getSimpleName(cls, StringUtils.EMPTY);
253     }
254 
255     /**
256      * <p>Null-safe version of <code>aClass.getSimpleName()</code></p>
257      *
258      * @param cls the class for which to get the simple name; may be null
259      * @param valueIfNull  the value to return if null
260      * @return the simple class name or {@code valueIfNull}
261      * @since 3.0
262      * @see Class#getSimpleName()
263      */
264     public static String getSimpleName(final Class<?> cls, String valueIfNull) {
265         return cls == null ? valueIfNull : cls.getSimpleName();
266     }
267 
268     /**
269      * <p>Null-safe version of <code>aClass.getSimpleName()</code></p>
270      *
271      * @param object the object for which to get the simple class name; may be null
272      * @return the simple class name or the empty String
273      * @since 3.7
274      * @see Class#getSimpleName()
275      */
276     public static String getSimpleName(final Object object) {
277         return getSimpleName(object, StringUtils.EMPTY);
278     }
279 
280     /**
281      * <p>Null-safe version of <code>aClass.getSimpleName()</code></p>
282      *
283      * @param object the object for which to get the simple class name; may be null
284      * @param valueIfNull the value to return if <code>object</code> is <code>null</code>
285      * @return the simple class name or {@code valueIfNull}
286      * @since 3.0
287      * @see Class#getSimpleName()
288      */
289     public static String getSimpleName(final Object object, final String valueIfNull) {
290         return object == null ? valueIfNull : object.getClass().getSimpleName();
291     }
292 
293     /**
294      * <p>Null-safe version of <code>Class.getName()</code></p>
295      *
296      * @param cls the class for which to get the class name; may be null
297      * @return the class name or the empty String.
298      * @since 3.7
299      * @see Class#getSimpleName()
300      */
301     public static String getName(final Class<?> cls) {
302         return getName(cls, StringUtils.EMPTY);
303     }
304 
305     /**
306      * <p>Null-safe version of <code>aClass.getName()</code></p>
307      *
308      * @param cls the class for which to get the class name; may be null
309      * @param valueIfNull the return value if <code>cls</code> is <code>null</code>
310      * @return the class name or {@code valueIfNull}
311      * @since 3.7
312      * @see Class#getName()
313      */
314     public static String getName(final Class<?> cls, final String valueIfNull) {
315         return cls == null ? valueIfNull : cls.getName();
316     }
317 
318     /**
319      * <p>Null-safe version of <code>Class.getName()</code></p>
320      *
321      * @param object the object for which to get the class name; may be null
322      * @return the class name or the empty String
323      * @since 3.7
324      * @see Class#getSimpleName()
325      */
326     public static String getName(final Object object) {
327         return getName(object, StringUtils.EMPTY);
328     }
329 
330     /**
331      * <p>Null-safe version of <code>aClass.getSimpleName()</code></p>
332      *
333      * @param object the object for which to get the class name; may be null
334      * @param valueIfNull the value to return if <code>object</code> is <code>null</code>
335      * @return the class name or {@code valueIfNull}
336      * @since 3.0
337      * @see Class#getName()
338      */
339     public static String getName(final Object object, final String valueIfNull) {
340         return object == null ? valueIfNull : object.getClass().getName();
341     }
342 
343     // Package name
344     // ----------------------------------------------------------------------
345     /**
346      * <p>Gets the package name of an {@code Object}.</p>
347      *
348      * @param object  the class to get the package name for, may be null
349      * @param valueIfNull  the value to return if null
350      * @return the package name of the object, or the null value
351      */
352     public static String getPackageName(final Object object, final String valueIfNull) {
353         if (object == null) {
354             return valueIfNull;
355         }
356         return getPackageName(object.getClass());
357     }
358 
359     /**
360      * <p>Gets the package name of a {@code Class}.</p>
361      *
362      * @param cls  the class to get the package name for, may be {@code null}.
363      * @return the package name or an empty string
364      */
365     public static String getPackageName(final Class<?> cls) {
366         if (cls == null) {
367             return StringUtils.EMPTY;
368         }
369         return getPackageName(cls.getName());
370     }
371 
372     /**
373      * <p>Gets the package name from a {@code String}.</p>
374      *
375      * <p>The string passed in is assumed to be a class name - it is not checked.</p>
376      * <p>If the class is unpackaged, return an empty string.</p>
377      *
378      * @param className  the className to get the package name for, may be {@code null}
379      * @return the package name or an empty string
380      */
381     public static String getPackageName(String className) {
382         if (StringUtils.isEmpty(className)) {
383             return StringUtils.EMPTY;
384         }
385 
386         // Strip array encoding
387         while (className.charAt(0) == '[') {
388             className = className.substring(1);
389         }
390         // Strip Object type encoding
391         if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
392             className = className.substring(1);
393         }
394 
395         final int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
396         if (i == -1) {
397             return StringUtils.EMPTY;
398         }
399         return className.substring(0, i);
400     }
401 
402     // Abbreviated name
403     // ----------------------------------------------------------------------
404     /**
405      * <p>Gets the abbreviated name of a {@code Class}.</p>
406      *
407      * @param cls  the class to get the abbreviated name for, may be {@code null}
408      * @param len  the desired length of the abbreviated name
409      * @return the abbreviated name or an empty string
410      * @throws IllegalArgumentException if len &lt;= 0
411      * @see #getAbbreviatedName(String, int)
412      * @since 3.4
413      */
414     public static String getAbbreviatedName(final Class<?> cls, final int len) {
415       if (cls == null) {
416         return StringUtils.EMPTY;
417       }
418       return getAbbreviatedName(cls.getName(), len);
419     }
420 
421     /**
422      * <p>Gets the abbreviated class name from a {@code String}.</p>
423      *
424      * <p>The string passed in is assumed to be a class name - it is not checked.</p>
425      *
426      * <p>The abbreviation algorithm will shorten the class name, usually without
427      * significant loss of meaning.</p>
428      * <p>The abbreviated class name will always include the complete package hierarchy.
429      * If enough space is available, rightmost sub-packages will be displayed in full
430      * length.</p>
431      *
432      * <p>The following table illustrates the algorithm:</p>
433      * <table summary="abbreviation examples">
434      * <tr><td>className</td><td>len</td><td>return</td></tr>
435      * <tr><td>              null</td><td> 1</td><td>""</td></tr>
436      * <tr><td>"java.lang.String"</td><td> 5</td><td>"j.l.String"</td></tr>
437      * <tr><td>"java.lang.String"</td><td>15</td><td>"j.lang.String"</td></tr>
438      * <tr><td>"java.lang.String"</td><td>30</td><td>"java.lang.String"</td></tr>
439      * </table>
440      * @param className  the className to get the abbreviated name for, may be {@code null}
441      * @param len  the desired length of the abbreviated name
442      * @return the abbreviated name or an empty string
443      * @throws IllegalArgumentException if len &lt;= 0
444      * @since 3.4
445      */
446     public static String getAbbreviatedName(final String className, final int len) {
447       if (len <= 0) {
448         throw new IllegalArgumentException("len must be > 0");
449       }
450       if (className == null) {
451         return StringUtils.EMPTY;
452       }
453 
454       int availableSpace = len;
455       final int packageLevels = StringUtils.countMatches(className, '.');
456       final String[] output = new String[packageLevels + 1];
457       int endIndex = className.length() - 1;
458       for (int level = packageLevels; level >= 0; level--) {
459         final int startIndex = className.lastIndexOf('.', endIndex);
460         final String part = className.substring(startIndex + 1, endIndex + 1);
461         availableSpace -= part.length();
462         if (level > 0) {
463           // all elements except top level require an additional char space
464           availableSpace--;
465         }
466         if (level == packageLevels) {
467           // ClassName is always complete
468           output[level] = part;
469         } else {
470           if (availableSpace > 0) {
471             output[level] = part;
472           } else {
473             // if no space is left still the first char is used
474             output[level] = part.substring(0, 1);
475           }
476         }
477         endIndex = startIndex - 1;
478       }
479 
480       return StringUtils.join(output, '.');
481     }
482 
483     // Superclasses/Superinterfaces
484     // ----------------------------------------------------------------------
485     /**
486      * <p>Gets a {@code List} of superclasses for the given class.</p>
487      *
488      * @param cls  the class to look up, may be {@code null}
489      * @return the {@code List} of superclasses in order going up from this one
490      *  {@code null} if null input
491      */
492     public static List<Class<?>> getAllSuperclasses(final Class<?> cls) {
493         if (cls == null) {
494             return null;
495         }
496         final List<Class<?>> classes = new ArrayList<>();
497         Class<?> superclass = cls.getSuperclass();
498         while (superclass != null) {
499             classes.add(superclass);
500             superclass = superclass.getSuperclass();
501         }
502         return classes;
503     }
504 
505     /**
506      * <p>Gets a {@code List} of all interfaces implemented by the given
507      * class and its superclasses.</p>
508      *
509      * <p>The order is determined by looking through each interface in turn as
510      * declared in the source file and following its hierarchy up. Then each
511      * superclass is considered in the same way. Later duplicates are ignored,
512      * so the order is maintained.</p>
513      *
514      * @param cls  the class to look up, may be {@code null}
515      * @return the {@code List} of interfaces in order,
516      *  {@code null} if null input
517      */
518     public static List<Class<?>> getAllInterfaces(final Class<?> cls) {
519         if (cls == null) {
520             return null;
521         }
522 
523         final LinkedHashSet<Class<?>> interfacesFound = new LinkedHashSet<>();
524         getAllInterfaces(cls, interfacesFound);
525 
526         return new ArrayList<>(interfacesFound);
527     }
528 
529     /**
530      * Get the interfaces for the specified class.
531      *
532      * @param cls  the class to look up, may be {@code null}
533      * @param interfacesFound the {@code Set} of interfaces for the class
534      */
535     private static void getAllInterfaces(Class<?> cls, final HashSet<Class<?>> interfacesFound) {
536         while (cls != null) {
537             final Class<?>[] interfaces = cls.getInterfaces();
538 
539             for (final Class<?> i : interfaces) {
540                 if (interfacesFound.add(i)) {
541                     getAllInterfaces(i, interfacesFound);
542                 }
543             }
544 
545             cls = cls.getSuperclass();
546          }
547      }
548 
549     // Convert list
550     // ----------------------------------------------------------------------
551     /**
552      * <p>Given a {@code List} of class names, this method converts them into classes.</p>
553      *
554      * <p>A new {@code List} is returned. If the class name cannot be found, {@code null}
555      * is stored in the {@code List}. If the class name in the {@code List} is
556      * {@code null}, {@code null} is stored in the output {@code List}.</p>
557      *
558      * @param classNames  the classNames to change
559      * @return a {@code List} of Class objects corresponding to the class names,
560      *  {@code null} if null input
561      * @throws ClassCastException if classNames contains a non String entry
562      */
563     public static List<Class<?>> convertClassNamesToClasses(final List<String> classNames) {
564         if (classNames == null) {
565             return null;
566         }
567         final List<Class<?>> classes = new ArrayList<>(classNames.size());
568         for (final String className : classNames) {
569             try {
570                 classes.add(Class.forName(className));
571             } catch (final Exception ex) {
572                 classes.add(null);
573             }
574         }
575         return classes;
576     }
577 
578     /**
579      * <p>Given a {@code List} of {@code Class} objects, this method converts
580      * them into class names.</p>
581      *
582      * <p>A new {@code List} is returned. {@code null} objects will be copied into
583      * the returned list as {@code null}.</p>
584      *
585      * @param classes  the classes to change
586      * @return a {@code List} of class names corresponding to the Class objects,
587      *  {@code null} if null input
588      * @throws ClassCastException if {@code classes} contains a non-{@code Class} entry
589      */
590     public static List<String> convertClassesToClassNames(final List<Class<?>> classes) {
591         if (classes == null) {
592             return null;
593         }
594         final List<String> classNames = new ArrayList<>(classes.size());
595         for (final Class<?> cls : classes) {
596             if (cls == null) {
597                 classNames.add(null);
598             } else {
599                 classNames.add(cls.getName());
600             }
601         }
602         return classNames;
603     }
604 
605     // Is assignable
606     // ----------------------------------------------------------------------
607     /**
608      * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
609      *
610      * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each
611      * Class pair in the input arrays. It can be used to check if a set of arguments
612      * (the first parameter) are suitably compatible with a set of method parameter types
613      * (the second parameter).</p>
614      *
615      * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
616      * method takes into account widenings of primitive classes and
617      * {@code null}s.</p>
618      *
619      * <p>Primitive widenings allow an int to be assigned to a {@code long},
620      * {@code float} or {@code double}. This method returns the correct
621      * result for these cases.</p>
622      *
623      * <p>{@code Null} may be assigned to any reference type. This method will
624      * return {@code true} if {@code null} is passed in and the toClass is
625      * non-primitive.</p>
626      *
627      * <p>Specifically, this method tests whether the type represented by the
628      * specified {@code Class} parameter can be converted to the type
629      * represented by this {@code Class} object via an identity conversion
630      * widening primitive or widening reference conversion. See
631      * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>,
632      * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
633      *
634      * <p><strong>Since Lang 3.0,</strong> this method will default behavior for
635      * calculating assignability between primitive and wrapper types <em>corresponding
636      * to the running Java version</em>; i.e. autoboxing will be the default
637      * behavior in VMs running Java versions &gt; 1.5.</p>
638      *
639      * @param classArray  the array of Classes to check, may be {@code null}
640      * @param toClassArray  the array of Classes to try to assign into, may be {@code null}
641      * @return {@code true} if assignment possible
642      */
643     public static boolean isAssignable(final Class<?>[] classArray, final Class<?>... toClassArray) {
644         return isAssignable(classArray, toClassArray, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_5));
645     }
646 
647     /**
648      * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
649      *
650      * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each
651      * Class pair in the input arrays. It can be used to check if a set of arguments
652      * (the first parameter) are suitably compatible with a set of method parameter types
653      * (the second parameter).</p>
654      *
655      * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
656      * method takes into account widenings of primitive classes and
657      * {@code null}s.</p>
658      *
659      * <p>Primitive widenings allow an int to be assigned to a {@code long},
660      * {@code float} or {@code double}. This method returns the correct
661      * result for these cases.</p>
662      *
663      * <p>{@code Null} may be assigned to any reference type. This method will
664      * return {@code true} if {@code null} is passed in and the toClass is
665      * non-primitive.</p>
666      *
667      * <p>Specifically, this method tests whether the type represented by the
668      * specified {@code Class} parameter can be converted to the type
669      * represented by this {@code Class} object via an identity conversion
670      * widening primitive or widening reference conversion. See
671      * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>,
672      * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
673      *
674      * @param classArray  the array of Classes to check, may be {@code null}
675      * @param toClassArray  the array of Classes to try to assign into, may be {@code null}
676      * @param autoboxing  whether to use implicit autoboxing/unboxing between primitives and wrappers
677      * @return {@code true} if assignment possible
678      */
679     public static boolean isAssignable(Class<?>[] classArray, Class<?>[] toClassArray, final boolean autoboxing) {
680         if (!ArrayUtils.isSameLength(classArray, toClassArray)) {
681             return false;
682         }
683         if (classArray == null) {
684             classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
685         }
686         if (toClassArray == null) {
687             toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
688         }
689         for (int i = 0; i < classArray.length; i++) {
690             if (!isAssignable(classArray[i], toClassArray[i], autoboxing)) {
691                 return false;
692             }
693         }
694         return true;
695     }
696 
697     /**
698      * Returns whether the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character},
699      * {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
700      *
701      * @param type
702      *            The class to query or null.
703      * @return true if the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character},
704      *         {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
705      * @since 3.1
706      */
707     public static boolean isPrimitiveOrWrapper(final Class<?> type) {
708         if (type == null) {
709             return false;
710         }
711         return type.isPrimitive() || isPrimitiveWrapper(type);
712     }
713 
714     /**
715      * Returns whether the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short},
716      * {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
717      *
718      * @param type
719      *            The class to query or null.
720      * @return true if the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short},
721      *         {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
722      * @since 3.1
723      */
724     public static boolean isPrimitiveWrapper(final Class<?> type) {
725         return wrapperPrimitiveMap.containsKey(type);
726     }
727 
728     /**
729      * <p>Checks if one {@code Class} can be assigned to a variable of
730      * another {@code Class}.</p>
731      *
732      * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
733      * this method takes into account widenings of primitive classes and
734      * {@code null}s.</p>
735      *
736      * <p>Primitive widenings allow an int to be assigned to a long, float or
737      * double. This method returns the correct result for these cases.</p>
738      *
739      * <p>{@code Null} may be assigned to any reference type. This method
740      * will return {@code true} if {@code null} is passed in and the
741      * toClass is non-primitive.</p>
742      *
743      * <p>Specifically, this method tests whether the type represented by the
744      * specified {@code Class} parameter can be converted to the type
745      * represented by this {@code Class} object via an identity conversion
746      * widening primitive or widening reference conversion. See
747      * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>,
748      * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
749      *
750      * <p><strong>Since Lang 3.0,</strong> this method will default behavior for
751      * calculating assignability between primitive and wrapper types <em>corresponding
752      * to the running Java version</em>; i.e. autoboxing will be the default
753      * behavior in VMs running Java versions &gt; 1.5.</p>
754      *
755      * @param cls  the Class to check, may be null
756      * @param toClass  the Class to try to assign into, returns false if null
757      * @return {@code true} if assignment possible
758      */
759     public static boolean isAssignable(final Class<?> cls, final Class<?> toClass) {
760         return isAssignable(cls, toClass, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_5));
761     }
762 
763     /**
764      * <p>Checks if one {@code Class} can be assigned to a variable of
765      * another {@code Class}.</p>
766      *
767      * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
768      * this method takes into account widenings of primitive classes and
769      * {@code null}s.</p>
770      *
771      * <p>Primitive widenings allow an int to be assigned to a long, float or
772      * double. This method returns the correct result for these cases.</p>
773      *
774      * <p>{@code Null} may be assigned to any reference type. This method
775      * will return {@code true} if {@code null} is passed in and the
776      * toClass is non-primitive.</p>
777      *
778      * <p>Specifically, this method tests whether the type represented by the
779      * specified {@code Class} parameter can be converted to the type
780      * represented by this {@code Class} object via an identity conversion
781      * widening primitive or widening reference conversion. See
782      * <em><a href="http://docs.oracle.com/javase/specs/">The Java Language Specification</a></em>,
783      * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
784      *
785      * @param cls  the Class to check, may be null
786      * @param toClass  the Class to try to assign into, returns false if null
787      * @param autoboxing  whether to use implicit autoboxing/unboxing between primitives and wrappers
788      * @return {@code true} if assignment possible
789      */
790     public static boolean isAssignable(Class<?> cls, final Class<?> toClass, final boolean autoboxing) {
791         if (toClass == null) {
792             return false;
793         }
794         // have to check for null, as isAssignableFrom doesn't
795         if (cls == null) {
796             return !toClass.isPrimitive();
797         }
798         //autoboxing:
799         if (autoboxing) {
800             if (cls.isPrimitive() && !toClass.isPrimitive()) {
801                 cls = primitiveToWrapper(cls);
802                 if (cls == null) {
803                     return false;
804                 }
805             }
806             if (toClass.isPrimitive() && !cls.isPrimitive()) {
807                 cls = wrapperToPrimitive(cls);
808                 if (cls == null) {
809                     return false;
810                 }
811             }
812         }
813         if (cls.equals(toClass)) {
814             return true;
815         }
816         if (cls.isPrimitive()) {
817             if (!toClass.isPrimitive()) {
818                 return false;
819             }
820             if (Integer.TYPE.equals(cls)) {
821                 return Long.TYPE.equals(toClass)
822                     || Float.TYPE.equals(toClass)
823                     || Double.TYPE.equals(toClass);
824             }
825             if (Long.TYPE.equals(cls)) {
826                 return Float.TYPE.equals(toClass)
827                     || Double.TYPE.equals(toClass);
828             }
829             if (Boolean.TYPE.equals(cls)) {
830                 return false;
831             }
832             if (Double.TYPE.equals(cls)) {
833                 return false;
834             }
835             if (Float.TYPE.equals(cls)) {
836                 return Double.TYPE.equals(toClass);
837             }
838             if (Character.TYPE.equals(cls)) {
839                 return Integer.TYPE.equals(toClass)
840                     || Long.TYPE.equals(toClass)
841                     || Float.TYPE.equals(toClass)
842                     || Double.TYPE.equals(toClass);
843             }
844             if (Short.TYPE.equals(cls)) {
845                 return Integer.TYPE.equals(toClass)
846                     || Long.TYPE.equals(toClass)
847                     || Float.TYPE.equals(toClass)
848                     || Double.TYPE.equals(toClass);
849             }
850             if (Byte.TYPE.equals(cls)) {
851                 return Short.TYPE.equals(toClass)
852                     || Integer.TYPE.equals(toClass)
853                     || Long.TYPE.equals(toClass)
854                     || Float.TYPE.equals(toClass)
855                     || Double.TYPE.equals(toClass);
856             }
857             // should never get here
858             return false;
859         }
860         return toClass.isAssignableFrom(cls);
861     }
862 
863     /**
864      * <p>Converts the specified primitive Class object to its corresponding
865      * wrapper Class object.</p>
866      *
867      * <p>NOTE: From v2.2, this method handles {@code Void.TYPE},
868      * returning {@code Void.TYPE}.</p>
869      *
870      * @param cls  the class to convert, may be null
871      * @return the wrapper class for {@code cls} or {@code cls} if
872      * {@code cls} is not a primitive. {@code null} if null input.
873      * @since 2.1
874      */
875     public static Class<?> primitiveToWrapper(final Class<?> cls) {
876         Class<?> convertedClass = cls;
877         if (cls != null && cls.isPrimitive()) {
878             convertedClass = primitiveWrapperMap.get(cls);
879         }
880         return convertedClass;
881     }
882 
883     /**
884      * <p>Converts the specified array of primitive Class objects to an array of
885      * its corresponding wrapper Class objects.</p>
886      *
887      * @param classes  the class array to convert, may be null or empty
888      * @return an array which contains for each given class, the wrapper class or
889      * the original class if class is not a primitive. {@code null} if null input.
890      * Empty array if an empty array passed in.
891      * @since 2.1
892      */
893     public static Class<?>[] primitivesToWrappers(final Class<?>... classes) {
894         if (classes == null) {
895             return null;
896         }
897 
898         if (classes.length == 0) {
899             return classes;
900         }
901 
902         final Class<?>[] convertedClasses = new Class[classes.length];
903         for (int i = 0; i < classes.length; i++) {
904             convertedClasses[i] = primitiveToWrapper(classes[i]);
905         }
906         return convertedClasses;
907     }
908 
909     /**
910      * <p>Converts the specified wrapper class to its corresponding primitive
911      * class.</p>
912      *
913      * <p>This method is the counter part of {@code primitiveToWrapper()}.
914      * If the passed in class is a wrapper class for a primitive type, this
915      * primitive type will be returned (e.g. {@code Integer.TYPE} for
916      * {@code Integer.class}). For other classes, or if the parameter is
917      * <b>null</b>, the return value is <b>null</b>.</p>
918      *
919      * @param cls the class to convert, may be <b>null</b>
920      * @return the corresponding primitive type if {@code cls} is a
921      * wrapper class, <b>null</b> otherwise
922      * @see #primitiveToWrapper(Class)
923      * @since 2.4
924      */
925     public static Class<?> wrapperToPrimitive(final Class<?> cls) {
926         return wrapperPrimitiveMap.get(cls);
927     }
928 
929     /**
930      * <p>Converts the specified array of wrapper Class objects to an array of
931      * its corresponding primitive Class objects.</p>
932      *
933      * <p>This method invokes {@code wrapperToPrimitive()} for each element
934      * of the passed in array.</p>
935      *
936      * @param classes  the class array to convert, may be null or empty
937      * @return an array which contains for each given class, the primitive class or
938      * <b>null</b> if the original class is not a wrapper class. {@code null} if null input.
939      * Empty array if an empty array passed in.
940      * @see #wrapperToPrimitive(Class)
941      * @since 2.4
942      */
943     public static Class<?>[] wrappersToPrimitives(final Class<?>... classes) {
944         if (classes == null) {
945             return null;
946         }
947 
948         if (classes.length == 0) {
949             return classes;
950         }
951 
952         final Class<?>[] convertedClasses = new Class[classes.length];
953         for (int i = 0; i < classes.length; i++) {
954             convertedClasses[i] = wrapperToPrimitive(classes[i]);
955         }
956         return convertedClasses;
957     }
958 
959     // Inner class
960     // ----------------------------------------------------------------------
961     /**
962      * <p>Is the specified class an inner class or static nested class.</p>
963      *
964      * @param cls  the class to check, may be null
965      * @return {@code true} if the class is an inner or static nested class,
966      *  false if not or {@code null}
967      */
968     public static boolean isInnerClass(final Class<?> cls) {
969         return cls != null && cls.getEnclosingClass() != null;
970     }
971 
972     // Class loading
973     // ----------------------------------------------------------------------
974     /**
975      * Returns the class represented by {@code className} using the
976      * {@code classLoader}.  This implementation supports the syntaxes
977      * "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
978      * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
979      *
980      * @param classLoader  the class loader to use to load the class
981      * @param className  the class name
982      * @param initialize  whether the class must be initialized
983      * @return the class represented by {@code className} using the {@code classLoader}
984      * @throws ClassNotFoundException if the class is not found
985      */
986     public static Class<?> getClass(
987             final ClassLoader classLoader, final String className, final boolean initialize) throws ClassNotFoundException {
988         try {
989             Class<?> clazz;
990             if (namePrimitiveMap.containsKey(className)) {
991                 clazz = namePrimitiveMap.get(className);
992             } else {
993                 clazz = Class.forName(toCanonicalName(className), initialize, classLoader);
994             }
995             return clazz;
996         } catch (final ClassNotFoundException ex) {
997             // allow path separators (.) as inner class name separators
998             final int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
999 
1000             if (lastDotIndex != -1) {
1001                 try {
1002                     return getClass(classLoader, className.substring(0, lastDotIndex) +
1003                             INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1),
1004                             initialize);
1005                 } catch (final ClassNotFoundException ex2) { // NOPMD
1006                     // ignore exception
1007                 }
1008             }
1009 
1010             throw ex;
1011         }
1012     }
1013 
1014     /**
1015      * Returns the (initialized) class represented by {@code className}
1016      * using the {@code classLoader}.  This implementation supports
1017      * the syntaxes "{@code java.util.Map.Entry[]}",
1018      * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}",
1019      * and "{@code [Ljava.util.Map$Entry;}".
1020      *
1021      * @param classLoader  the class loader to use to load the class
1022      * @param className  the class name
1023      * @return the class represented by {@code className} using the {@code classLoader}
1024      * @throws ClassNotFoundException if the class is not found
1025      */
1026     public static Class<?> getClass(final ClassLoader classLoader, final String className) throws ClassNotFoundException {
1027         return getClass(classLoader, className, true);
1028     }
1029 
1030     /**
1031      * Returns the (initialized) class represented by {@code className}
1032      * using the current thread's context class loader. This implementation
1033      * supports the syntaxes "{@code java.util.Map.Entry[]}",
1034      * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}",
1035      * and "{@code [Ljava.util.Map$Entry;}".
1036      *
1037      * @param className  the class name
1038      * @return the class represented by {@code className} using the current thread's context class loader
1039      * @throws ClassNotFoundException if the class is not found
1040      */
1041     public static Class<?> getClass(final String className) throws ClassNotFoundException {
1042         return getClass(className, true);
1043     }
1044 
1045     /**
1046      * Returns the class represented by {@code className} using the
1047      * current thread's context class loader. This implementation supports the
1048      * syntaxes "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
1049      * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
1050      *
1051      * @param className  the class name
1052      * @param initialize  whether the class must be initialized
1053      * @return the class represented by {@code className} using the current thread's context class loader
1054      * @throws ClassNotFoundException if the class is not found
1055      */
1056     public static Class<?> getClass(final String className, final boolean initialize) throws ClassNotFoundException {
1057         final ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
1058         final ClassLoader loader = contextCL == null ? ClassUtils.class.getClassLoader() : contextCL;
1059         return getClass(loader, className, initialize);
1060     }
1061 
1062     // Public method
1063     // ----------------------------------------------------------------------
1064     /**
1065      * <p>Returns the desired Method much like {@code Class.getMethod}, however
1066      * it ensures that the returned Method is from a public class or interface and not
1067      * from an anonymous inner class. This means that the Method is invokable and
1068      * doesn't fall foul of Java bug
1069      * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957">4071957</a>).</p>
1070      *
1071      *  <pre>
1072      *  <code>Set set = Collections.unmodifiableSet(...);
1073      *  Method method = ClassUtils.getPublicMethod(set.getClass(), "isEmpty",  new Class[0]);
1074      *  Object result = method.invoke(set, new Object[]);</code>
1075      *  </pre>
1076      *
1077      * @param cls  the class to check, not null
1078      * @param methodName  the name of the method
1079      * @param parameterTypes  the list of parameters
1080      * @return the method
1081      * @throws NullPointerException if the class is null
1082      * @throws SecurityException if a security violation occurred
1083      * @throws NoSuchMethodException if the method is not found in the given class
1084      *  or if the method doesn't conform with the requirements
1085      */
1086     public static Method getPublicMethod(final Class<?> cls, final String methodName, final Class<?>... parameterTypes)
1087             throws SecurityException, NoSuchMethodException {
1088 
1089         final Method declaredMethod = cls.getMethod(methodName, parameterTypes);
1090         if (Modifier.isPublic(declaredMethod.getDeclaringClass().getModifiers())) {
1091             return declaredMethod;
1092         }
1093 
1094         final List<Class<?>> candidateClasses = new ArrayList<>();
1095         candidateClasses.addAll(getAllInterfaces(cls));
1096         candidateClasses.addAll(getAllSuperclasses(cls));
1097 
1098         for (final Class<?> candidateClass : candidateClasses) {
1099             if (!Modifier.isPublic(candidateClass.getModifiers())) {
1100                 continue;
1101             }
1102             Method candidateMethod;
1103             try {
1104                 candidateMethod = candidateClass.getMethod(methodName, parameterTypes);
1105             } catch (final NoSuchMethodException ex) {
1106                 continue;
1107             }
1108             if (Modifier.isPublic(candidateMethod.getDeclaringClass().getModifiers())) {
1109                 return candidateMethod;
1110             }
1111         }
1112 
1113         throw new NoSuchMethodException("Can't find a public method for " +
1114                 methodName + " " + ArrayUtils.toString(parameterTypes));
1115     }
1116 
1117     // ----------------------------------------------------------------------
1118     /**
1119      * Converts a class name to a JLS style class name.
1120      *
1121      * @param className  the class name
1122      * @return the converted name
1123      */
1124     private static String toCanonicalName(String className) {
1125         className = StringUtils.deleteWhitespace(className);
1126         Validate.notNull(className, "className must not be null.");
1127         if (className.endsWith("[]")) {
1128             final StringBuilder classNameBuffer = new StringBuilder();
1129             while (className.endsWith("[]")) {
1130                 className = className.substring(0, className.length() - 2);
1131                 classNameBuffer.append("[");
1132             }
1133             final String abbreviation = abbreviationMap.get(className);
1134             if (abbreviation != null) {
1135                 classNameBuffer.append(abbreviation);
1136             } else {
1137                 classNameBuffer.append("L").append(className).append(";");
1138             }
1139             className = classNameBuffer.toString();
1140         }
1141         return className;
1142     }
1143 
1144     /**
1145      * <p>Converts an array of {@code Object} in to an array of {@code Class} objects.
1146      * If any of these objects is null, a null element will be inserted into the array.</p>
1147      *
1148      * <p>This method returns {@code null} for a {@code null} input array.</p>
1149      *
1150      * @param array an {@code Object} array
1151      * @return a {@code Class} array, {@code null} if null array input
1152      * @since 2.4
1153      */
1154     public static Class<?>[] toClass(final Object... array) {
1155         if (array == null) {
1156             return null;
1157         } else if (array.length == 0) {
1158             return ArrayUtils.EMPTY_CLASS_ARRAY;
1159         }
1160         final Class<?>[] classes = new Class[array.length];
1161         for (int i = 0; i < array.length; i++) {
1162             classes[i] = array[i] == null ? null : array[i].getClass();
1163         }
1164         return classes;
1165     }
1166 
1167     // Short canonical name
1168     // ----------------------------------------------------------------------
1169     /**
1170      * <p>Gets the canonical name minus the package name for an {@code Object}.</p>
1171      *
1172      * @param object  the class to get the short name for, may be null
1173      * @param valueIfNull  the value to return if null
1174      * @return the canonical name of the object without the package name, or the null value
1175      * @since 2.4
1176      */
1177     public static String getShortCanonicalName(final Object object, final String valueIfNull) {
1178         if (object == null) {
1179             return valueIfNull;
1180         }
1181         return getShortCanonicalName(object.getClass().getName());
1182     }
1183 
1184     /**
1185      * <p>Gets the canonical class name for a {@code Class}.</p>
1186      *
1187      * @param cls the class for which to get the canonical class name; may be null
1188      * @return the canonical name of the class, or the empty String
1189      * @since 3.7
1190      * @see Class#getCanonicalName()
1191      */
1192     public static String getCanonicalName(final Class<?> cls) {
1193         return getCanonicalName(cls, StringUtils.EMPTY);
1194     }
1195 
1196     /**
1197      * <p>Gets the canonical name for a {@code Class}.</p>
1198      *
1199      * @param cls the class for which to get the canonical class name; may be null
1200      * @param valueIfNull  the return value if null
1201      * @return the canonical name of the class, or {@code valueIfNull}
1202      * @since 3.7
1203      * @see Class#getCanonicalName()
1204      */
1205     public static String getCanonicalName(final Class<?> cls, final String valueIfNull) {
1206         if (cls == null) {
1207             return valueIfNull;
1208         }
1209         final String canonicalName = cls.getCanonicalName();
1210         return canonicalName == null ? valueIfNull : canonicalName;
1211     }
1212 
1213     /**
1214      * <p>Gets the canonical name for an {@code Object}.</p>
1215      *
1216      * @param object the object for which to get the canonical class name; may be null
1217      * @return the canonical name of the object, or the empty String
1218      * @since 3.7
1219      * @see Class#getCanonicalName()
1220      */
1221     public static String getCanonicalName(final Object object) {
1222         return getCanonicalName(object, StringUtils.EMPTY);
1223     }
1224 
1225     /**
1226      * <p>Gets the canonical name for an {@code Object}.</p>
1227      *
1228      * @param object the object for which to get the canonical class name; may be null
1229      * @param valueIfNull  the return value if null
1230      * @return the canonical name of the object or {@code valueIfNull}
1231      * @since 3.7
1232      * @see Class#getCanonicalName()
1233      */
1234     public static String getCanonicalName(final Object object, final String valueIfNull) {
1235         if (object == null) {
1236             return valueIfNull;
1237         }
1238         final String canonicalName = object.getClass().getCanonicalName();
1239         return canonicalName == null ? valueIfNull : canonicalName;
1240     }
1241 
1242     /**
1243      * <p>Gets the canonical name minus the package name from a {@code Class}.</p>
1244      *
1245      * @param cls the class for which to get the short canonical class name; may be null
1246      * @return the canonical name without the package name or an empty string
1247      * @since 2.4
1248      */
1249     public static String getShortCanonicalName(final Class<?> cls) {
1250         if (cls == null) {
1251             return StringUtils.EMPTY;
1252         }
1253         return getShortCanonicalName(cls.getName());
1254     }
1255 
1256     /**
1257      * <p>Gets the canonical name minus the package name from a String.</p>
1258      *
1259      * <p>The string passed in is assumed to be a canonical name - it is not checked.</p>
1260      *
1261      * @param canonicalName  the class name to get the short name for
1262      * @return the canonical name of the class without the package name or an empty string
1263      * @since 2.4
1264      */
1265     public static String getShortCanonicalName(final String canonicalName) {
1266         return ClassUtils.getShortClassName(getCanonicalName(canonicalName));
1267     }
1268 
1269     // Package name
1270     // ----------------------------------------------------------------------
1271     /**
1272      * <p>Gets the package name from the canonical name of an {@code Object}.</p>
1273      *
1274      * @param object  the class to get the package name for, may be null
1275      * @param valueIfNull  the value to return if null
1276      * @return the package name of the object, or the null value
1277      * @since 2.4
1278      */
1279     public static String getPackageCanonicalName(final Object object, final String valueIfNull) {
1280         if (object == null) {
1281             return valueIfNull;
1282         }
1283         return getPackageCanonicalName(object.getClass().getName());
1284     }
1285 
1286     /**
1287      * <p>Gets the package name from the canonical name of a {@code Class}.</p>
1288      *
1289      * @param cls  the class to get the package name for, may be {@code null}.
1290      * @return the package name or an empty string
1291      * @since 2.4
1292      */
1293     public static String getPackageCanonicalName(final Class<?> cls) {
1294         if (cls == null) {
1295             return StringUtils.EMPTY;
1296         }
1297         return getPackageCanonicalName(cls.getName());
1298     }
1299 
1300     /**
1301      * <p>Gets the package name from the canonical name. </p>
1302      *
1303      * <p>The string passed in is assumed to be a canonical name - it is not checked.</p>
1304      * <p>If the class is unpackaged, return an empty string.</p>
1305      *
1306      * @param canonicalName  the canonical name to get the package name for, may be {@code null}
1307      * @return the package name or an empty string
1308      * @since 2.4
1309      */
1310     public static String getPackageCanonicalName(final String canonicalName) {
1311         return ClassUtils.getPackageName(getCanonicalName(canonicalName));
1312     }
1313 
1314     /**
1315      * <p>Converts a given name of class into canonical format.
1316      * If name of class is not a name of array class it returns
1317      * unchanged name.</p>
1318      * <p>Example:
1319      * <ul>
1320      * <li>{@code getCanonicalName("[I") = "int[]"}</li>
1321      * <li>{@code getCanonicalName("[Ljava.lang.String;") = "java.lang.String[]"}</li>
1322      * <li>{@code getCanonicalName("java.lang.String") = "java.lang.String"}</li>
1323      * </ul>
1324      * </p>
1325      *
1326      * @param className the name of class
1327      * @return canonical form of class name
1328      * @since 2.4
1329      */
1330     private static String getCanonicalName(String className) {
1331         className = StringUtils.deleteWhitespace(className);
1332         if (className == null) {
1333             return null;
1334         }
1335         int dim = 0;
1336         while (className.startsWith("[")) {
1337             dim++;
1338             className = className.substring(1);
1339         }
1340         if (dim < 1) {
1341             return className;
1342         }
1343         if (className.startsWith("L")) {
1344             className = className.substring(
1345                 1,
1346                 className.endsWith(";")
1347                     ? className.length() - 1
1348                     : className.length());
1349         } else {
1350             if (className.length() > 0) {
1351                 className = reverseAbbreviationMap.get(className.substring(0, 1));
1352             }
1353         }
1354         final StringBuilder canonicalClassNameBuffer = new StringBuilder(className);
1355         for (int i = 0; i < dim; i++) {
1356             canonicalClassNameBuffer.append("[]");
1357         }
1358         return canonicalClassNameBuffer.toString();
1359     }
1360 
1361     /**
1362      * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order,
1363      * excluding interfaces.
1364      *
1365      * @param type the type to get the class hierarchy from
1366      * @return Iterable an Iterable over the class hierarchy of the given class
1367      * @since 3.2
1368      */
1369     public static Iterable<Class<?>> hierarchy(final Class<?> type) {
1370         return hierarchy(type, Interfaces.EXCLUDE);
1371     }
1372 
1373     /**
1374      * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order.
1375      *
1376      * @param type the type to get the class hierarchy from
1377      * @param interfacesBehavior switch indicating whether to include or exclude interfaces
1378      * @return Iterable an Iterable over the class hierarchy of the given class
1379      * @since 3.2
1380      */
1381     public static Iterable<Class<?>> hierarchy(final Class<?> type, final Interfaces interfacesBehavior) {
1382         final Iterable<Class<?>> classes = new Iterable<Class<?>>() {
1383 
1384             @Override
1385             public Iterator<Class<?>> iterator() {
1386                 final MutableObject<Class<?>> next = new MutableObject<Class<?>>(type);
1387                 return new Iterator<Class<?>>() {
1388 
1389                     @Override
1390                     public boolean hasNext() {
1391                         return next.getValue() != null;
1392                     }
1393 
1394                     @Override
1395                     public Class<?> next() {
1396                         final Class<?> result = next.getValue();
1397                         next.setValue(result.getSuperclass());
1398                         return result;
1399                     }
1400 
1401                     @Override
1402                     public void remove() {
1403                         throw new UnsupportedOperationException();
1404                     }
1405 
1406                 };
1407             }
1408 
1409         };
1410         if (interfacesBehavior != Interfaces.INCLUDE) {
1411             return classes;
1412         }
1413         return new Iterable<Class<?>>() {
1414 
1415             @Override
1416             public Iterator<Class<?>> iterator() {
1417                 final Set<Class<?>> seenInterfaces = new HashSet<>();
1418                 final Iterator<Class<?>> wrapped = classes.iterator();
1419 
1420                 return new Iterator<Class<?>>() {
1421                     Iterator<Class<?>> interfaces = Collections.<Class<?>> emptySet().iterator();
1422 
1423                     @Override
1424                     public boolean hasNext() {
1425                         return interfaces.hasNext() || wrapped.hasNext();
1426                     }
1427 
1428                     @Override
1429                     public Class<?> next() {
1430                         if (interfaces.hasNext()) {
1431                             final Class<?> nextInterface = interfaces.next();
1432                             seenInterfaces.add(nextInterface);
1433                             return nextInterface;
1434                         }
1435                         final Class<?> nextSuperclass = wrapped.next();
1436                         final Set<Class<?>> currentInterfaces = new LinkedHashSet<>();
1437                         walkInterfaces(currentInterfaces, nextSuperclass);
1438                         interfaces = currentInterfaces.iterator();
1439                         return nextSuperclass;
1440                     }
1441 
1442                     private void walkInterfaces(final Set<Class<?>> addTo, final Class<?> c) {
1443                         for (final Class<?> iface : c.getInterfaces()) {
1444                             if (!seenInterfaces.contains(iface)) {
1445                                 addTo.add(iface);
1446                             }
1447                             walkInterfaces(addTo, iface);
1448                         }
1449                     }
1450 
1451                     @Override
1452                     public void remove() {
1453                         throw new UnsupportedOperationException();
1454                     }
1455 
1456                 };
1457             }
1458         };
1459     }
1460 
1461 }