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.jxpath.util;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  /**
23   * Port of class loading methods from <code>org.apache.commons.lang.ClassUtils</code> from
24   * the Apache Commons Lang Component. Some adjustments made to remove dependency on
25   * <code>org.apache.commons.lang.StringUtils</code>. Also modified to fall back on the
26   * current class loader when an attempt to load a class with the context class loader
27   * results in a <code>java.lang.ClassNotFoundException</code>.
28   *
29   * @see org.apache.commons.lang.ClassUtils
30   *
31   * @author Stephen Colebourne
32   * @author Gary Gregory
33   * @author Norm Deane
34   * @author Alban Peignier
35   * @author Tomasz Blachowicz
36   * @author John Trimble
37   */
38  public class ClassLoaderUtil {
39      /**
40       * Maps a primitive class name to its corresponding abbreviation used in array class names.
41       */
42      private static Map abbreviationMap = new HashMap();
43  
44      /**
45       * Add primitive type abbreviation to maps of abbreviations.
46       *
47       * @param primitive Canonical name of primitive type
48       * @param abbreviation Corresponding abbreviation of primitive type
49       */
50      private static void addAbbreviation(String primitive, String abbreviation) {
51          abbreviationMap.put(primitive, abbreviation);
52      }
53  
54      /**
55       * Feed abbreviation maps
56       */
57      static {
58          addAbbreviation("int", "I");
59          addAbbreviation("boolean", "Z");
60          addAbbreviation("float", "F");
61          addAbbreviation("long", "J");
62          addAbbreviation("short", "S");
63          addAbbreviation("byte", "B");
64          addAbbreviation("double", "D");
65          addAbbreviation("char", "C");
66      }
67  
68      // Class loading
69      // ----------------------------------------------------------------------
70      /**
71       * Returns the class represented by <code>className</code> using the
72       * <code>classLoader</code>.  This implementation supports names like
73       * "<code>java.lang.String[]</code>" as well as "<code>[Ljava.lang.String;</code>".
74       *
75       * @param classLoader  the class loader to use to load the class
76       * @param className  the class name
77       * @param initialize  whether the class must be initialized
78       * @return the class represented by <code>className</code> using the <code>classLoader</code>
79       * @throws ClassNotFoundException if the class is not found
80       */
81      public static Class getClass(ClassLoader classLoader, String className, boolean initialize)
82          throws ClassNotFoundException {
83          Class clazz;
84          if (abbreviationMap.containsKey(className)) {
85              String clsName = "[" + abbreviationMap.get(className);
86              clazz = Class.forName(clsName, initialize, classLoader).getComponentType();
87          }
88          else {
89              clazz = Class.forName(toCanonicalName(className), initialize, classLoader);
90          }
91          return clazz;
92      }
93  
94      /**
95       * Returns the (initialized) class represented by <code>className</code>
96       * using the <code>classLoader</code>.  This implementation supports names
97       * like "<code>java.lang.String[]</code>" as well as
98       * "<code>[Ljava.lang.String;</code>".
99       *
100      * @param classLoader  the class loader to use to load the class
101      * @param className  the class name
102      * @return the class represented by <code>className</code> using the <code>classLoader</code>
103      * @throws ClassNotFoundException if the class is not found
104      */
105     public static Class getClass(ClassLoader classLoader, String className) throws ClassNotFoundException {
106         return getClass(classLoader, className, true);
107     }
108 
109     /**
110      * Returns the (initialized) class represented by <code>className</code>
111      * using the current thread's context class loader. This implementation
112      * supports names like "<code>java.lang.String[]</code>" as well as
113      * "<code>[Ljava.lang.String;</code>".
114      *
115      * @param className  the class name
116      * @return the class represented by <code>className</code> using the current thread's context class loader
117      * @throws ClassNotFoundException if the class is not found
118      */
119     public static Class getClass(String className) throws ClassNotFoundException {
120         return getClass(className, true);
121     }
122 
123     /**
124      * Returns the class represented by <code>className</code> using the
125      * current thread's context class loader. This implementation supports
126      * names like "<code>java.lang.String[]</code>" as well as
127      * "<code>[Ljava.lang.String;</code>".
128      *
129      * @param className  the class name
130      * @param initialize  whether the class must be initialized
131      * @return the class represented by <code>className</code> using the current thread's context class loader
132      * @throws ClassNotFoundException if the class is not found
133      */
134     public static Class getClass(String className, boolean initialize) throws ClassNotFoundException {
135         ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
136         ClassLoader currentCL = ClassLoaderUtil.class.getClassLoader();
137         if (contextCL != null) {
138             try {
139                 return getClass(contextCL, className, initialize);
140             }
141             catch (ClassNotFoundException e) {//NOPMD
142                 // ignore this exception and try the current class loader.
143             }
144         }
145         return getClass(currentCL, className, initialize);
146     }
147 
148     /**
149      * Converts a class name to a JLS style class name.
150      *
151      * @param className  the class name
152      * @return the converted name
153      */
154     private static String toCanonicalName(String className) {
155         if (className == null) {
156             throw new RuntimeException("Argument className was null.");
157         }
158         else if (className.endsWith("[]")) {
159             StringBuffer classNameBuffer = new StringBuffer();
160             while (className.endsWith("[]")) {
161                 className = className.substring(0, className.length() - 2);
162                 classNameBuffer.append("[");
163             }
164             String abbreviation = (String) abbreviationMap.get(className);
165             if (abbreviation != null) {
166                 classNameBuffer.append(abbreviation);
167             }
168             else {
169                 classNameBuffer.append("L").append(className).append(";");
170             }
171             className = classNameBuffer.toString();
172         }
173         return className;
174     }
175 }