/* * Copyright 1999-2010 University of Chicago * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. * * See the License for the specific language governing permissions and limitations under the License. */ package org.globus.util; import java.io.InputStream; /** * Various classloader utils. Extends the standard ways of loading classes or * resources with a fallback mechanism to the thread context classloader. */ public class ClassLoaderUtils { private static DummySecurityManager MANAGER = new DummySecurityManager(); private static class DummySecurityManager extends SecurityManager { public Class[] getClassContext() { return super.getClassContext(); } } /** * Returns the current execution stack as an array of classes. * <p> * The length of the array is the number of methods on the execution stack. * The element at index <code>0</code> is the class of the currently * executing method, the element at index <code>1</code> is the class of * that method's caller, and so on. * * @return the execution stack. */ public static Class[] getClassContext() { return MANAGER.getClassContext(); } /** * Returns a class at specified depth of the current execution stack. * * @return the class at the specified depth of the current execution stack. * Migth return null if depth is out of range. */ public static Class getClassContextAt(int i) { Class[] classes = MANAGER.getClassContext(); if (classes != null && classes.length > i) { return classes[i]; } return null; } /** * Returns a classloader at specified depth of the current execution stack. * * @return the classloader at the specified depth of the current execution * stack. Migth return null if depth is out of range. */ public static ClassLoader getClassLoaderContextAt(int i) { Class[] classes = MANAGER.getClassContext(); if (classes != null && classes.length > i) { return classes[i].getClassLoader(); } return null; } /** * Gets an InputStream to a resource of a specified name. First, the * caller's classloader is used to load the resource and if it fails the * thread's context classloader is used to load the resource. */ public static InputStream getResourceAsStream(String name) { // try with caller classloader ClassLoader loader = getClassLoaderContextAt(3); InputStream in = (loader == null) ? null : loader.getResourceAsStream(name); if (in == null) { // try with context classloader if set & different ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); if (contextLoader != null && contextLoader != loader) { in = contextLoader.getResourceAsStream(name); } } return in; } /** * Loads a specified class. First, the caller's classloader is used to load * the class and if it fails the thread's context classloader is used to * load the specified class. */ public static Class forName(String name) throws ClassNotFoundException { // try with caller classloader ClassLoader loader = getClassLoaderContextAt(3); try { return Class.forName(name, true, loader); } catch (ClassNotFoundException e) { // try with context classloader if set & different ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); if (contextLoader == null || contextLoader == loader) { throw e; } else { return Class.forName(name, true, contextLoader); } } } public static Class<?> loadClass(String className, Class<?> callingClass) throws ClassNotFoundException { try { ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl != null) { return cl.loadClass(className); } } catch (ClassNotFoundException e) { // ignore } return loadClass2(className, callingClass); } private static Class<?> loadClass2(String className, Class<?> callingClass) throws ClassNotFoundException { try { return Class.forName(className); } catch (ClassNotFoundException ex) { try { if (ClassLoaderUtils.class.getClassLoader() != null) { return ClassLoaderUtils.class.getClassLoader().loadClass(className); } } catch (ClassNotFoundException exc) { if (callingClass != null && callingClass.getClassLoader() != null) { return callingClass.getClassLoader().loadClass(className); } } throw ex; } } }