Package org.grails.web.servlet.context.support

Source Code of org.grails.web.servlet.context.support.GrailsRuntimeConfigurator

/*
* Copyright 2004-2005 the original author or authors.
*
* 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.grails.web.servlet.context.support;

import grails.spring.BeanBuilder;
import grails.util.Environment;
import grails.util.Holders;

import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.grails.core.util.ClassPropertyFetcher;
import grails.core.GrailsApplication;
import org.grails.spring.DefaultRuntimeSpringConfiguration;
import org.grails.spring.GrailsApplicationContext;
import org.grails.spring.GrailsContextEvent;
import org.grails.spring.RuntimeSpringConfiguration;
import grails.plugins.DefaultGrailsPluginManager;
import grails.plugins.GrailsPluginManager;
import org.grails.spring.RuntimeSpringConfigUtilities;
import org.grails.spring.beans.factory.OptimizedAutowireCapableBeanFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.mock.web.MockServletContext;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.WebApplicationContext;

/**
* Handles the runtime configuration of the Grails ApplicationContext.
*
* @author Graeme Rocher
* @since 0.3
*/
public class GrailsRuntimeConfigurator implements ApplicationContextAware {

    public static final String BEAN_ID = "grailsConfigurator";
    public static final String GRAILS_URL_MAPPINGS = "grailsUrlMappings";
    public static final String SPRING_RESOURCES_XML = "/WEB-INF/spring/resources.xml";
    public static final String SPRING_RESOURCES_GROOVY = "/WEB-INF/spring/resources.groovy";
    public static final String SPRING_RESOURCES_CLASS = "resources";
    public static final String OPEN_SESSION_IN_VIEW_INTERCEPTOR_BEAN = "openSessionInViewInterceptor";
    public static final String TRANSACTION_MANAGER_BEAN = "transactionManager";
    public static final String HIBERNATE_PROPERTIES_BEAN = "hibernateProperties";
    public static final String DIALECT_DETECTOR_BEAN = "dialectDetector";
    public static final String SESSION_FACTORY_BEAN = "sessionFactory";
    public static final String DATA_SOURCE_BEAN = "dataSource";
    public static final String MESSAGE_SOURCE_BEAN = "messageSource";
    public static final String MULTIPART_RESOLVER_BEAN = "multipartResolver";
    public static final String EXCEPTION_HANDLER_BEAN = "exceptionHandler";
    public static final String CUSTOM_EDITORS_BEAN = "customEditors";
    public static final String CLASS_EDITOR_BEAN = "classEditor";
    public static final String CLASS_LOADER_BEAN = "classLoader";

    private static final Log LOG = LogFactory.getLog(GrailsRuntimeConfigurator.class);
    public static final String GRAILS_INITIALIZING = "org.grails.internal.INITIALIZING";

    protected GrailsApplication application;
    protected ApplicationContext parent;
    protected GrailsPluginManager pluginManager;
    protected WebRuntimeSpringConfiguration webSpringConfig;
    protected static final String DEVELOPMENT_SPRING_RESOURCES_XML = "file:./grails-app/conf/spring/resources.xml";


    public GrailsRuntimeConfigurator(GrailsApplication application) {
        this(application, null);
    }

    public GrailsRuntimeConfigurator(GrailsApplication application, ApplicationContext parent) {
        this.application = application;
        this.parent = parent;
        initializePluginManager();
    }

    public GrailsRuntimeConfigurator(GrailsApplication application, ApplicationContext parent, GrailsPluginManager pluginManager) {
        this.application = application;
        this.parent = parent;
        this.pluginManager = pluginManager;
    }

    protected void initializePluginManager() {
        try {
            pluginManager = parent == null ? null : parent.getBean(GrailsPluginManager.class);
        } catch (BeansException e) {
            // ignore
        }
        if (pluginManager == null) {
            pluginManager = Holders.getPluginManager();
        }
        if (pluginManager == null) {
            pluginManager = new DefaultGrailsPluginManager("**/plugins/*/**GrailsPlugin.groovy", application);
        }
        Holders.setPluginManager(pluginManager);
    }

    /**
     * Configures the Grails application context at runtime.
     *
     * @return A WebApplicationContext instance
     */
    public WebApplicationContext configure() {
        return configure(null);
    }

    /**
     * Configures the Grails application context at runtime
     *
     * @param context A ServletContext instance
     * @return An ApplicationContext instance
     */
    public WebApplicationContext configure(ServletContext context) {
        return configure(context, true);
    }

    public WebApplicationContext configure(ServletContext context, boolean loadExternalBeans) {
        Assert.notNull(application);

        // TODO GRAILS-720 this causes plugin beans to be re-created - should get getApplicationContext always call refresh?
        WebApplicationContext mainContext;
        try {
            webSpringConfig = createWebRuntimeSpringConfiguration(application, parent, application.getClassLoader());

            if (context != null) {
                webSpringConfig.setServletContext(context);
            }
            if (!pluginManager.isInitialised()) {
                pluginManager.loadPlugins();
            }

            if (!application.isInitialised()) {
                pluginManager.doArtefactConfiguration();
                application.initialise();
            }

            pluginManager.registerProvidedArtefacts(application);
            pluginManager.doRuntimeConfiguration(webSpringConfig);

            LOG.debug("[RuntimeConfiguration] Processing additional external configurations");

            if (loadExternalBeans) {
                doPostResourceConfiguration(application, webSpringConfig);
            }

            reset();

            mainContext = (WebApplicationContext)webSpringConfig.getUnrefreshedApplicationContext();
            application.setMainContext(mainContext);

            Environment.setInitializing(true);
            initializeContext(mainContext);
            Environment.setInitializing(false);

            pluginManager.setApplicationContext(mainContext);
            pluginManager.doDynamicMethods();

            mainContext.publishEvent(new GrailsContextEvent(mainContext, GrailsContextEvent.DYNAMIC_METHODS_REGISTERED));

            performPostProcessing(mainContext);

            application.refreshConstraints();
        }
        finally {
            ClassPropertyFetcher.clearClassPropertyFetcherCache();
        }

        return mainContext;
    }

    protected void initializeContext(ApplicationContext mainContext) {
        webSpringConfig.getApplicationContext();
    }

    protected WebRuntimeSpringConfiguration createWebRuntimeSpringConfiguration(GrailsApplication app,
            ApplicationContext parentCtx, ClassLoader classLoader) {
        WebRuntimeSpringConfiguration springConfig = new WebRuntimeSpringConfiguration(parentCtx, classLoader, app);
        springConfig.setBeanFactory(new OptimizedAutowireCapableBeanFactory());
        return springConfig;
    }

    @SuppressWarnings("rawtypes")
    protected void registerParentBeanFactoryPostProcessors(WebRuntimeSpringConfiguration springConfig) {
        if (parent == null) {
            return;
        }

        Map parentPostProcessors = parent.getBeansOfType(BeanFactoryPostProcessor.class);
        for (Object o : parentPostProcessors.values()) {
            BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor) o;
            ((ConfigurableApplicationContext) springConfig.getUnrefreshedApplicationContext())
                .addBeanFactoryPostProcessor(postProcessor);
        }
    }

    public void reconfigure(GrailsApplicationContext current, ServletContext servletContext, boolean loadExternalBeans) {
        RuntimeSpringConfiguration springConfig = parent != null ? new DefaultRuntimeSpringConfiguration(parent) : new DefaultRuntimeSpringConfiguration();
        Assert.state(pluginManager.isInitialised(),
                "Cannot re-configure Grails application when it hasn't even been configured yet!");

        pluginManager.doRuntimeConfiguration(springConfig);

        List<String> beanNames = springConfig.getBeanNames();
        for (Object beanName : beanNames) {
            String name = (String) beanName;
            if (LOG.isDebugEnabled()) {
                LOG.debug("Re-creating bean definition [" + name + "]");
            }
            current.registerBeanDefinition(name, springConfig.createBeanDefinition(name));
            // force initialisation
            current.getBean(name);
        }
        pluginManager.doDynamicMethods();
        pluginManager.doPostProcessing(current);

        if (loadExternalBeans) {
            doPostResourceConfiguration(application, springConfig);
        }

        reset();
    }

    protected void performPostProcessing(WebApplicationContext ctx) {
        pluginManager.doPostProcessing(ctx);
    }

    public WebApplicationContext configureDomainOnly() {
        WebRuntimeSpringConfiguration springConfig = new WebRuntimeSpringConfiguration(parent, application.getClassLoader());
        springConfig.setServletContext(new MockServletContext());

        if (!pluginManager.isInitialised()) {
            pluginManager.loadPlugins();
        }

        if (pluginManager.hasGrailsPlugin("hibernate")) {
            pluginManager.doRuntimeConfiguration("hibernate", springConfig);
        }
        else if (pluginManager.hasGrailsPlugin("hibernate4")) {
            pluginManager.doRuntimeConfiguration("hibernate4", springConfig);
        }

        WebApplicationContext ctx = (WebApplicationContext) springConfig.getApplicationContext();

        performPostProcessing(ctx);
        application.refreshConstraints();

        return ctx;
    }

    protected void doPostResourceConfiguration(GrailsApplication app, RuntimeSpringConfiguration springConfig) {
        ClassLoader classLoader = app.getClassLoader();
        String resourceName = null;
        try {
            Resource springResources;
            if (app.isWarDeployed()) {
                resourceName = GrailsRuntimeConfigurator.SPRING_RESOURCES_XML;
                springResources = parent.getResource(resourceName);
            }
            else {
                resourceName = DEVELOPMENT_SPRING_RESOURCES_XML;
                ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
                springResources = patternResolver.getResource(resourceName);
            }

            if (springResources != null && springResources.exists()) {
                if (LOG.isDebugEnabled()) LOG.debug("[RuntimeConfiguration] Configuring additional beans from " + springResources.getURL());
                DefaultListableBeanFactory xmlBf = new OptimizedAutowireCapableBeanFactory();
                new XmlBeanDefinitionReader(xmlBf).loadBeanDefinitions(springResources);
                xmlBf.setBeanClassLoader(classLoader);
                String[] beanNames = xmlBf.getBeanDefinitionNames();
                if (LOG.isDebugEnabled()) LOG.debug("[RuntimeConfiguration] Found [" + beanNames.length + "] beans to configure");
                for (String beanName : beanNames) {
                    BeanDefinition bd = xmlBf.getBeanDefinition(beanName);
                    final String beanClassName = bd.getBeanClassName();
                    Class<?> beanClass = beanClassName == null ? null : ClassUtils.forName(beanClassName, classLoader);

                    springConfig.addBeanDefinition(beanName, bd);
                    String[] aliases = xmlBf.getAliases(beanName);
                    for (String alias : aliases) {
                        springConfig.addAlias(alias, beanName);
                    }
                    if (beanClass != null) {
                        if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass)) {
                            ((ConfigurableApplicationContext) springConfig.getUnrefreshedApplicationContext())
                                .addBeanFactoryPostProcessor((BeanFactoryPostProcessor) xmlBf.getBean(beanName));
                        }
                    }
                }
            }
            else if (LOG.isDebugEnabled()) {
                LOG.debug("[RuntimeConfiguration] " + resourceName + " not found. Skipping configuration.");
            }
        }
        catch (Exception ex) {
            LOG.error("[RuntimeConfiguration] Unable to perform post initialization config: " + resourceName, ex);
        }

        GrailsRuntimeConfigurator.loadSpringGroovyResources(springConfig, app);
    }



    public void setLoadExternalPersistenceConfig(boolean b) {
        // do nothing
    }

    public void setPluginManager(GrailsPluginManager manager) {
        pluginManager = manager;
    }

    public GrailsPluginManager getPluginManager() {
        return pluginManager;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        parent = applicationContext;
    }

    /**
     * Loads any external Spring configuration into the given RuntimeSpringConfiguration object.
     * @param config The config instance
     */
    public static void loadExternalSpringConfig(RuntimeSpringConfiguration config, final GrailsApplication application) {
        RuntimeSpringConfigUtilities.loadExternalSpringConfig(config, application);
    }

    public static BeanBuilder reloadSpringResourcesConfig(RuntimeSpringConfiguration config, GrailsApplication application, Class<?> groovySpringResourcesClass) throws InstantiationException, IllegalAccessException {
        return RuntimeSpringConfigUtilities.reloadSpringResourcesConfig(config, application, groovySpringResourcesClass);
    }

    public static void loadSpringGroovyResources(RuntimeSpringConfiguration config, GrailsApplication application) {
        RuntimeSpringConfigUtilities.loadExternalSpringConfig(config, application);
    }

    public static void loadSpringGroovyResourcesIntoContext(RuntimeSpringConfiguration config, GrailsApplication application,
                                                            GenericApplicationContext context) {
        RuntimeSpringConfigUtilities.loadSpringGroovyResourcesIntoContext(config, application, context);
    }

    /**
     * Resets the GrailsRumtimeConfigurator.
     */
    public static void reset() {
        RuntimeSpringConfigUtilities.reset();
    }

    // for testing
    WebRuntimeSpringConfiguration getWebRuntimeSpringConfiguration() {
        return webSpringConfig;
    }
}
TOP

Related Classes of org.grails.web.servlet.context.support.GrailsRuntimeConfigurator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.