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 */ 017package org.apache.commons.jxpath.util; 018 019import java.util.HashMap; 020import java.util.Map; 021 022/** 023 * Port of class loading methods from <code>org.apache.commons.lang.ClassUtils</code> from 024 * the Apache Commons Lang Component. Some adjustments made to remove dependency on 025 * <code>org.apache.commons.lang.StringUtils</code>. Also modified to fall back on the 026 * current class loader when an attempt to load a class with the context class loader 027 * results in a <code>java.lang.ClassNotFoundException</code>. 028 * 029 * @see org.apache.commons.lang.ClassUtils 030 * 031 * @author Stephen Colebourne 032 * @author Gary Gregory 033 * @author Norm Deane 034 * @author Alban Peignier 035 * @author Tomasz Blachowicz 036 * @author John Trimble 037 */ 038public class ClassLoaderUtil { 039 /** 040 * Maps a primitive class name to its corresponding abbreviation used in array class names. 041 */ 042 private static Map abbreviationMap = new HashMap(); 043 044 /** 045 * Add primitive type abbreviation to maps of abbreviations. 046 * 047 * @param primitive Canonical name of primitive type 048 * @param abbreviation Corresponding abbreviation of primitive type 049 */ 050 private static void addAbbreviation(String primitive, String abbreviation) { 051 abbreviationMap.put(primitive, abbreviation); 052 } 053 054 /** 055 * Feed abbreviation maps 056 */ 057 static { 058 addAbbreviation("int", "I"); 059 addAbbreviation("boolean", "Z"); 060 addAbbreviation("float", "F"); 061 addAbbreviation("long", "J"); 062 addAbbreviation("short", "S"); 063 addAbbreviation("byte", "B"); 064 addAbbreviation("double", "D"); 065 addAbbreviation("char", "C"); 066 } 067 068 // Class loading 069 // ---------------------------------------------------------------------- 070 /** 071 * Returns the class represented by <code>className</code> using the 072 * <code>classLoader</code>. This implementation supports names like 073 * "<code>java.lang.String[]</code>" as well as "<code>[Ljava.lang.String;</code>". 074 * 075 * @param classLoader the class loader to use to load the class 076 * @param className the class name 077 * @param initialize whether the class must be initialized 078 * @return the class represented by <code>className</code> using the <code>classLoader</code> 079 * @throws ClassNotFoundException if the class is not found 080 */ 081 public static Class getClass(ClassLoader classLoader, String className, boolean initialize) 082 throws ClassNotFoundException { 083 Class clazz; 084 if (abbreviationMap.containsKey(className)) { 085 String clsName = "[" + abbreviationMap.get(className); 086 clazz = Class.forName(clsName, initialize, classLoader).getComponentType(); 087 } 088 else { 089 clazz = Class.forName(toCanonicalName(className), initialize, classLoader); 090 } 091 return clazz; 092 } 093 094 /** 095 * Returns the (initialized) class represented by <code>className</code> 096 * using the <code>classLoader</code>. This implementation supports names 097 * like "<code>java.lang.String[]</code>" as well as 098 * "<code>[Ljava.lang.String;</code>". 099 * 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}