/*
* Copyright 2011 SpringSource.
*
* 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 grails.util;
import grails.config.Config;
import grails.core.GrailsApplication;
import grails.plugins.GrailsPluginManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.grails.core.io.support.GrailsFactoriesLoader;
import org.grails.core.support.GrailsApplicationDiscoveryStrategy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.Lifecycle;
import org.springframework.util.Assert;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Allows looking up key classes in a static context
*
*
* @author Burt Beckwith
* @author Graeme Rocher
*
* @since 2.0
*/
public class Holders {
private static final Log LOG = LogFactory.getLog(Holders.class);
private static Holder<GrailsPluginManager> pluginManagers = new Holder<GrailsPluginManager>("PluginManager");
private static Holder<Boolean> pluginManagersInCreation = new Holder<Boolean>("PluginManagers in creation");
private static Holder<Config> configs = new Holder<Config>("config");
private static Holder<Map<?, ?>> flatConfigs = new Holder<Map<?, ?>>("flat config");
private static List<GrailsApplicationDiscoveryStrategy> applicationDiscoveryStrategies = GrailsFactoriesLoader.loadFactories(GrailsApplicationDiscoveryStrategy.class, Holders.class.getClassLoader());
private static Holder servletContexts;
static {
createServletContextsHolder();
}
private static GrailsApplication applicationSingleton; // TODO remove
private Holders() {
// static only
}
public static void addApplicationDiscoveryStrategy(GrailsApplicationDiscoveryStrategy strategy) {
applicationDiscoveryStrategies.add(strategy);
}
public static void clear() {
pluginManagers.set(null);
pluginManagersInCreation.set(null);
configs.set(null);
flatConfigs.set(null);
if (servletContexts != null) {
servletContexts.set(null);
}
applicationDiscoveryStrategies.clear();
applicationSingleton = null;
}
public static void setServletContext(final Object servletContext) {
servletContexts.set(servletContext);
}
public static Object getServletContext() {
return get(servletContexts, "servletContext");
}
public static ApplicationContext getApplicationContext() {
for(GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) {
ApplicationContext applicationContext = strategy.findApplicationContext();
if(applicationContext != null ) {
boolean running = ((Lifecycle) applicationContext).isRunning();
if(running) {
return applicationContext;
}
}
}
throw new IllegalStateException("Could not find ApplicationContext, configure Grails correctly first");
}
/**
*
* @return The ApplicationContext or null if it doesn't exist
*/
public static ApplicationContext findApplicationContext() {
for(GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) {
ApplicationContext applicationContext = strategy.findApplicationContext();
if(applicationContext != null) {
return applicationContext;
}
}
return null;
}
/**
*
* @return The ApplicationContext or null if it doesn't exist
*/
public static GrailsApplication findApplication() {
for(GrailsApplicationDiscoveryStrategy strategy : applicationDiscoveryStrategies) {
GrailsApplication grailsApplication = strategy.findGrailsApplication();
if(grailsApplication != null) {
return grailsApplication;
}
}
return applicationSingleton;
}
public static GrailsApplication getGrailsApplication() {
GrailsApplication grailsApplication = findApplication();
Assert.notNull(grailsApplication, "GrailsApplication not found");
return grailsApplication;
}
public static void setGrailsApplication(GrailsApplication application) {
applicationSingleton = application;
}
public static void setConfig(Config config) {
configs.set(config);
// reset flat config
flatConfigs.set(config == null ? null : config);
}
public static Config getConfig() {
return get(configs, "config");
}
public static Map<?, ?> getFlatConfig() {
Map<?, ?> flatConfig = get(flatConfigs, "flatConfig");
return flatConfig == null ? Collections.emptyMap() : flatConfig;
}
public static void setPluginManagerInCreation(boolean inCreation) {
pluginManagersInCreation.set(inCreation);
}
public static void setPluginManager(GrailsPluginManager pluginManager) {
if (pluginManager != null) {
pluginManagersInCreation.set(false);
}
pluginManagers.set(pluginManager);
}
public static GrailsPluginManager getPluginManager() {
return getPluginManager(false);
}
public static GrailsPluginManager getPluginManager(boolean mappedOnly) {
while (true) {
Boolean inCreation = get(pluginManagersInCreation, "PluginManager in creation", mappedOnly);
if (inCreation == null) {
inCreation = false;
}
if (!inCreation) {
break;
}
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
break;
}
}
return get(pluginManagers, "PluginManager", mappedOnly);
}
public static GrailsPluginManager currentPluginManager() {
GrailsPluginManager current = getPluginManager();
Assert.notNull(current, "No PluginManager set");
return current;
}
public static void reset() {
setPluginManager(null);
setGrailsApplication(null);
setServletContext(null);
setPluginManager(null);
setPluginManagerInCreation(false);
setConfig(null);
}
private static <T> T get(Holder<T> holder, String type) {
return get(holder, type, false);
}
private static <T> T get(Holder<T> holder, String type, boolean mappedOnly) {
return holder.get(mappedOnly);
}
@SuppressWarnings("unchecked")
private static void createServletContextsHolder() {
try {
Class<?> clazz = Holders.class.getClassLoader().loadClass("grails.web.context.WebRequestServletHolder");
servletContexts = (Holder)clazz.newInstance();
}
catch (ClassNotFoundException e) {
// shouldn't happen
LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e);
}
catch (InstantiationException e) {
// shouldn't happen
LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e);
}
catch (IllegalAccessException e) {
// shouldn't happen
LOG.debug("Error initializing servlet context holder, not running in Servlet environment: " + e.getMessage(), e);
}
}
}