/* Name: - ClassLoaderResolver Description: - Requires: - Provides: - Part of: ProcessPuzzle Framework, Domain and Business Model Ready Architecture. Provides content, workflow and social networking functionality. http://www.processpuzzle.com ProcessPuzzle - Content and Workflow Management Integration Business Platform Author(s): - Zsolt Zsuffa Copyright: (C) 2011 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.processpuzzle.application.configuration.domain; // ---------------------------------------------------------------------------- /** * This non-instantiable non-subclassable class acts as the global point for choosing a ClassLoader for dynamic * class/resource loading at any point in an application. * * @see ResourceLoader * @see IClassLoadStrategy * @see DefaultClassLoadStrategy * @author (C) <a href="http://www.javaworld.com/columns/jw-qna-index.shtml">Vlad Roubtsov</a>, 2003 */ public abstract class ClassLoaderResolver { // public: ................................................................ /** * This method selects the "best" classloader instance to be used for class/resource loading by whoever calls this * method. The decision typically involves choosing between the caller's current, thread context, system, and other * classloaders in the JVM and is made by the {@link IClassLoadStrategy} instance established by the last call to * {@link #setStrategy}. * * @return classloader to be used by the caller ['null' indicates the primordial loader] */ public static synchronized ClassLoader getClassLoader() { final Class<?> caller = getCallerClass( 0 ); final ClassLoadContext ctx = new ClassLoadContext( caller ); return s_strategy.getClassLoader( ctx ); } /** * Gets the current classloader selection strategy setting. */ public static synchronized IClassLoadStrategy getStrategy() { return s_strategy; } /** * Sets the classloader selection strategy to be used by subsequent calls to {@link #getClassLoader()}. An instance * of {@link DefaultClassLoadStrategy} is in effect if this method is never called. * * @param new strategy [may not be null] * @return previous setting */ public static synchronized IClassLoadStrategy setStrategy( final IClassLoadStrategy strategy ) { if( strategy == null ) throw new IllegalArgumentException( "null input: strategy" ); final IClassLoadStrategy old = s_strategy; s_strategy = strategy; return old; } // protected: ............................................................. // package: ............................................................... /** * A package-private version of {@link #getClassLoader()} with adjustable caller offset (useful for embedding this * method in other library classes in this package). * * @param callerOffset * extra call context depth offset to pass into getCallerClass(). */ static synchronized ClassLoader getClassLoader( final int callerOffset ) { final Class<?> caller = getCallerClass( callerOffset ); final ClassLoadContext ctx = new ClassLoadContext( caller ); return s_strategy.getClassLoader( ctx ); } // private: ............................................................... /** * A helper class to get the call context. It subclasses SecurityManager to make getClassContext() accessible. An * instance of CallerResolver only needs to be created, not installed as an actual security manager. */ private static final class CallerResolver extends SecurityManager { protected Class<?>[] getClassContext() { return super.getClassContext(); } } // end of nested class private ClassLoaderResolver() {} // prevent subclassing /* * Indexes into the current method call context with a given offset. */ private static Class<?> getCallerClass( final int callerOffset ) { return CALLER_RESOLVER.getClassContext()[CALL_CONTEXT_OFFSET + callerOffset]; } private static IClassLoadStrategy s_strategy; // initialized in <clinit> private static final int CALL_CONTEXT_OFFSET = 3; // may need to change if this class is redesigned private static final CallerResolver CALLER_RESOLVER; // set in <clinit> static{ try{ // this can fail if the current SecurityManager does not allow // RuntimePermission ("createSecurityManager"): CALLER_RESOLVER = new CallerResolver(); }catch( SecurityException se ){ throw new RuntimeException( "ClassLoaderResolver: could not create CallerResolver: " + se ); } s_strategy = new DefaultClassLoadStrategy(); } } // end of class // ----------------------------------------------------------------------------