001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2005-2005 Julian Hyde 008// Copyright (C) 2005-2012 Pentaho 009// All Rights Reserved. 010*/ 011package mondrian.util; 012 013import org.apache.commons.collections.iterators.EnumerationIterator; 014 015import java.io.IOException; 016import java.lang.reflect.*; 017import java.net.URL; 018import java.util.*; 019 020/** 021 * Instantiates a class. 022 * 023 * <p>Has same effect as calling {@link Class#forName(String)}, but uses the 024 * appropriate {@link ClassLoader}.</p> 025 */ 026public interface ClassResolver { 027 028 /** Equivalent of {@link Class#forName(String, boolean, ClassLoader)}. */ 029 <T> Class<T> forName(String className, boolean initialize) 030 throws ClassNotFoundException; 031 032 /** 033 * Instantiates a class and constructs an instance using the given 034 * arguments. 035 * 036 * @param className Class name 037 * @param args Arguments 038 * @param <T> Desired type 039 * @throws ClassCastException if resulting object is not an instance of T 040 */ 041 <T> T instantiateSafe(String className, Object... args); 042 043 /** Equivalent of {@link ClassLoader#getResources(String)}. */ 044 Iterable<URL> getResources(String lookupName) throws IOException; 045 046 /** Default resolver. */ 047 ClassResolver INSTANCE = new ThreadContextClassResolver(); 048 049 /** Implementation of {@link ClassResolver} that calls 050 * {@link Thread#getContextClassLoader()} on the current thread. */ 051 class ThreadContextClassResolver extends AbstractClassResolver { 052 protected ClassLoader getClassLoader() { 053 return Thread.currentThread().getContextClassLoader(); 054 } 055 } 056 057 /** Partial implementation of {@link ClassResolver}. Derived class just 058 * needs to implement {@link #getClassLoader()}. */ 059 abstract class AbstractClassResolver implements ClassResolver { 060 public <T> T instantiateSafe(String className, Object... args) { 061 try { 062 final Class<T> clazz = forName(className, true); 063 if (args.length == 0) { 064 return clazz.newInstance(); 065 } else { 066 Class[] types = new Class[args.length]; 067 for (int i = 0; i < args.length; i++) { 068 types[i] = args[i].getClass(); 069 } 070 final Constructor<T> constructor = 071 clazz.getConstructor(types); 072 return constructor.newInstance(args); 073 } 074 } catch (InstantiationException e) { 075 throw new RuntimeException(e); 076 } catch (IllegalAccessException e) { 077 throw new RuntimeException(e); 078 } catch (NoSuchMethodException e) { 079 throw new RuntimeException(e); 080 } catch (InvocationTargetException e) { 081 throw new RuntimeException(e); 082 } catch (ClassNotFoundException e) { 083 throw new RuntimeException(e); 084 } 085 } 086 087 public <T> Class<T> forName(String className, boolean initialize) 088 throws ClassNotFoundException 089 { 090 //noinspection unchecked 091 return (Class<T>) Class.forName( 092 className, 093 initialize, 094 getClassLoader()); 095 } 096 097 /** Returns the class loader to use for the current operation. May be 098 * null. */ 099 protected abstract ClassLoader getClassLoader(); 100 101 /** Returns the class loader to use for the current operation, never 102 * null. */ 103 protected ClassLoader getClassLoaderNotNull() { 104 final ClassLoader classLoader = getClassLoader(); 105 return classLoader != null 106 ? classLoader 107 : getClass().getClassLoader(); 108 } 109 110 public Iterable<URL> getResources(String name) throws IOException { 111 final Enumeration<URL> resources = 112 getClassLoaderNotNull().getResources(name); 113 //noinspection unchecked 114 return new IteratorIterable<URL>( 115 new EnumerationIterator(resources)); 116 } 117 } 118} 119 120// End ClassResolver.java