package org.togglz.spring.util;
import org.springframework.context.ApplicationContext;
import java.util.concurrent.ConcurrentHashMap;
/**
* Stores the {@link ApplicationContext} for the current context class loader.
*
* @author Christian Kaltepoth
*/
public class ContextClassLoaderApplicationContextHolder {
private static final ConcurrentHashMap<ClassLoader, ApplicationContext> contextMap = new ConcurrentHashMap<ClassLoader, ApplicationContext>();
/**
* Returns the {@link ApplicationContext} bound to the current context class loader or any of
* its parent class loaders. Walking up the class loader hierarchy is required to support
* special class loader scenarios like Spring Boot's reloading mechanism.
*/
public static ApplicationContext get() {
ClassLoader classLoader = getContextClassLoader();
while (classLoader != null) {
ApplicationContext applicationContext = contextMap.get(classLoader);
if (applicationContext != null) {
return applicationContext;
}
classLoader = classLoader.getParent();
}
return null;
}
/**
* Binds the {@link ApplicationContext} to the current context class loader .
*/
public static void bind(ApplicationContext context) {
Object old = contextMap.putIfAbsent(getContextClassLoader(), context);
if (old != null) {
throw new IllegalStateException(
"There is already a ApplicationContext associated with the context ClassLoader of the current thread!");
}
}
/**
* Releases the {@link ApplicationContext} associated with the current context class loader.
*/
public static void release() {
contextMap.remove(getContextClassLoader());
}
private static ClassLoader getContextClassLoader() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
throw new IllegalStateException("Unable to get the context class loader for the current thread!");
}
return classLoader;
}
}