001 /* 002 * Created on Jan 28, 2009 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 * 014 * Copyright @2009 the original author or authors. 015 */ 016 package org.fest.reflect.type; 017 018 import org.fest.reflect.exception.ReflectionError; 019 020 import static org.fest.util.Strings.quote; 021 022 /** 023 * Understands loading a class dynamically using a specific <code>{@link ClassLoader}</code>. 024 * 025 * @author Alex Ruiz 026 * 027 * @since 1.1 028 */ 029 public final class TypeLoader { 030 031 static TypeLoader newLoader(String name, ClassLoader classLoader) { 032 if (classLoader == null) throw new NullPointerException("The given class loader should not be null"); 033 return new TypeLoader(name, classLoader); 034 } 035 036 private final String name; 037 private final ClassLoader classLoader; 038 039 private TypeLoader(String name, ClassLoader classLoader) { 040 this.name = name; 041 this.classLoader = classLoader; 042 } 043 044 /** 045 * Loads the class with the name specified in this type, using this class' <code>ClassLoader</code>. 046 * <p> 047 * Example: 048 * <pre> 049 * Class<?> type = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#withClassLoader(ClassLoader) withClassLoader}(myClassLoader).{@link TypeLoader#load() load}(); 050 * </pre> 051 * </p> 052 * @return the loaded class. 053 * @throws ReflectionError wrapping any error that occurred during class loading. 054 */ 055 public Class<?> load() { 056 try { 057 return loadType(); 058 } catch (Exception e) { 059 throw new ReflectionError(unableToLoadClassMessage(null), e); 060 } 061 } 062 063 /** 064 * Loads the class with the name specified in this type, as the given type, using this class' 065 * <code>ClassLoader</code>. 066 * <p> 067 * The following example shows how to use this method. Let's assume that we have the class <code>Jedi</code> that 068 * extends the class <code>Person</code>: 069 * <pre> 070 * Class<Person> type = {@link org.fest.reflect.core.Reflection#type(String) type}("org.republic.Jedi").{@link Type#withClassLoader(ClassLoader) withClassLoader}(myClassLoader).{@link TypeLoader#loadAs(Class) loadAs}(Person.class); 071 * </pre> 072 * </p> 073 * @param type the given type. 074 * @param <T> the generic type of the type. 075 * @return the loaded class. 076 * @throws NullPointerException if the given type is <code>null</code>. 077 * @throws ReflectionError wrapping any error that occurred during class loading. 078 */ 079 public <T> Class<? extends T> loadAs(Class<T> type) { 080 if (type == null) throw new NullPointerException("The given type should not be null"); 081 try { 082 return loadType().asSubclass(type); 083 } catch (Exception e) { 084 throw new ReflectionError(unableToLoadClassMessage(type), e); 085 } 086 } 087 088 private String unableToLoadClassMessage(Class<?> asType) { 089 StringBuilder msg = new StringBuilder(); 090 msg.append("Unable to load class ").append(quote(name)); 091 if (asType != null) msg.append(" as ").append(asType.getName()); 092 msg.append(" using class loader ").append(classLoader); 093 return msg.toString(); 094 } 095 096 private Class<?> loadType() throws ClassNotFoundException { 097 return classLoader.loadClass(name); 098 } 099 }