001 /**
002 *
003 * Copyright 2004 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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.activemq.util;
018
019 import java.lang.reflect.Array;
020 import java.util.HashMap;
021 import java.util.Map;
022
023 /**
024 * Utilities for loading classes.
025 *
026 * @version $Rev: 109957 $ $Date: 2005/03/11 21:14:53 $
027 */
028 public class ClassLoading {
029
030 /**
031 * Load a class for the given name. <p/>
032 * <p>
033 * Handles loading primitive types as well as VM class and array syntax.
034 *
035 * @param className
036 * The name of the Class to be loaded.
037 * @param classLoader
038 * The class loader to load the Class object from.
039 * @return The Class object for the given name.
040 * @throws ClassNotFoundException
041 * Failed to load Class object.
042 */
043 public static Class loadClass(final String className, final ClassLoader classLoader) throws ClassNotFoundException {
044 if (className == null) {
045 throw new IllegalArgumentException("className is null");
046 }
047
048 // First just try to load
049 try {
050 return load(className, classLoader);
051 } catch (ClassNotFoundException ignore) {
052 // handle special cases below
053 }
054
055 Class type = null;
056
057 // Check if it is a primitive type
058 type = getPrimitiveType(className);
059 if (type != null)
060 return type;
061
062 // Check if it is a vm primitive
063 type = getVMPrimitiveType(className);
064 if (type != null)
065 return type;
066
067 // Handle VM class syntax (Lclassname;)
068 if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
069 String name = className.substring(1, className.length() - 1);
070 return load(name, classLoader);
071 }
072
073 // Handle VM array syntax ([type)
074 if (className.charAt(0) == '[') {
075 int arrayDimension = className.lastIndexOf('[') + 1;
076 String componentClassName = className.substring(arrayDimension, className.length());
077 type = loadClass(componentClassName, classLoader);
078
079 int dim[] = new int[arrayDimension];
080 java.util.Arrays.fill(dim, 0);
081 return Array.newInstance(type, dim).getClass();
082 }
083
084 // Handle user friendly type[] syntax
085 if (className.endsWith("[]")) {
086 // get the base component class name and the arrayDimensions
087 int arrayDimension = 0;
088 String componentClassName = className;
089 while (componentClassName.endsWith("[]")) {
090 componentClassName = componentClassName.substring(0, componentClassName.length() - 2);
091 arrayDimension++;
092 }
093
094 // load the base type
095 type = loadClass(componentClassName, classLoader);
096
097 // return the array type
098 int[] dim = new int[arrayDimension];
099 java.util.Arrays.fill(dim, 0);
100 return Array.newInstance(type, dim).getClass();
101 }
102
103 // Else we can not load (give up)
104 throw new ClassNotFoundException(className);
105 }
106
107 private static Class load(final String className, final ClassLoader classLoader) throws ClassNotFoundException {
108 if (classLoader == null)
109 return Class.forName(className);
110 else
111 return classLoader.loadClass(className);
112 }
113
114 public static String getClassName(Class clazz) {
115 StringBuffer rc = new StringBuffer();
116 while (clazz.isArray()) {
117 rc.append('[');
118 clazz = clazz.getComponentType();
119 }
120 if (!clazz.isPrimitive()) {
121 rc.append('L');
122 rc.append(clazz.getName());
123 rc.append(';');
124 } else {
125 rc.append(VM_PRIMITIVES_REVERSE.get(clazz));
126 }
127 return rc.toString();
128 }
129
130 /**
131 * Primitive type name -> class map.
132 */
133 private static final Map PRIMITIVES = new HashMap();
134
135 /** Setup the primitives map. */
136 static {
137 PRIMITIVES.put("boolean", Boolean.TYPE);
138 PRIMITIVES.put("byte", Byte.TYPE);
139 PRIMITIVES.put("char", Character.TYPE);
140 PRIMITIVES.put("short", Short.TYPE);
141 PRIMITIVES.put("int", Integer.TYPE);
142 PRIMITIVES.put("long", Long.TYPE);
143 PRIMITIVES.put("float", Float.TYPE);
144 PRIMITIVES.put("double", Double.TYPE);
145 PRIMITIVES.put("void", Void.TYPE);
146 }
147
148 /**
149 * Get the primitive type for the given primitive name.
150 *
151 * @param name
152 * Primitive type name (boolean, byte, int, ...)
153 * @return Primitive type or null.
154 */
155 private static Class getPrimitiveType(final String name) {
156 return (Class) PRIMITIVES.get(name);
157 }
158
159 /**
160 * VM primitive type name -> primitive type
161 */
162 private static final HashMap VM_PRIMITIVES = new HashMap();
163
164 /** Setup the vm primitives map. */
165 static {
166 VM_PRIMITIVES.put("B", byte.class);
167 VM_PRIMITIVES.put("C", char.class);
168 VM_PRIMITIVES.put("D", double.class);
169 VM_PRIMITIVES.put("F", float.class);
170 VM_PRIMITIVES.put("I", int.class);
171 VM_PRIMITIVES.put("J", long.class);
172 VM_PRIMITIVES.put("S", short.class);
173 VM_PRIMITIVES.put("Z", boolean.class);
174 VM_PRIMITIVES.put("V", void.class);
175 }
176
177 /**
178 * VM primitive type primitive type -> name
179 */
180 private static final HashMap VM_PRIMITIVES_REVERSE = new HashMap();
181
182 /** Setup the vm primitives reverse map. */
183 static {
184 VM_PRIMITIVES_REVERSE.put(byte.class, "B");
185 VM_PRIMITIVES_REVERSE.put(char.class, "C");
186 VM_PRIMITIVES_REVERSE.put(double.class, "D");
187 VM_PRIMITIVES_REVERSE.put(float.class, "F");
188 VM_PRIMITIVES_REVERSE.put(int.class, "I");
189 VM_PRIMITIVES_REVERSE.put(long.class, "J");
190 VM_PRIMITIVES_REVERSE.put(short.class, "S");
191 VM_PRIMITIVES_REVERSE.put(boolean.class, "Z");
192 VM_PRIMITIVES_REVERSE.put(void.class, "V");
193 }
194
195 /**
196 * Get the primitive type for the given VM primitive name. <p/>
197 * <p>
198 * Mapping:
199 *
200 * <pre>
201 *
202 * B - byte
203 * C - char
204 * D - double
205 * F - float
206 * I - int
207 * J - long
208 * S - short
209 * Z - boolean
210 * V - void
211 *
212 * </pre>
213 *
214 * @param name
215 * VM primitive type name (B, C, J, ...)
216 * @return Primitive type or null.
217 */
218 private static Class getVMPrimitiveType(final String name) {
219 return (Class) VM_PRIMITIVES.get(name);
220 }
221
222 /**
223 * Map of primitive types to their wrapper classes
224 */
225 private static final Map PRIMITIVE_WRAPPERS = new HashMap();
226
227 /** Setup the wrapper map. */
228 static {
229 PRIMITIVE_WRAPPERS.put(Boolean.TYPE, Boolean.class);
230 PRIMITIVE_WRAPPERS.put(Byte.TYPE, Byte.class);
231 PRIMITIVE_WRAPPERS.put(Character.TYPE, Character.class);
232 PRIMITIVE_WRAPPERS.put(Double.TYPE, Double.class);
233 PRIMITIVE_WRAPPERS.put(Float.TYPE, Float.class);
234 PRIMITIVE_WRAPPERS.put(Integer.TYPE, Integer.class);
235 PRIMITIVE_WRAPPERS.put(Long.TYPE, Long.class);
236 PRIMITIVE_WRAPPERS.put(Short.TYPE, Short.class);
237 PRIMITIVE_WRAPPERS.put(Void.TYPE, Void.class);
238 }
239 }