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 }