    001    // Copyright 2008, 2009, 2011 The Apache Software Foundation
    002    //
    003    // Licensed under the Apache License, Version 2.0 (the "License");
    004    // you may not use this file except in compliance with the License.
    005    // You may obtain a copy of the License at
    006    //
    007    //     http://www.apache.org/licenses/LICENSE-2.0
    008    //
    009    // Unless required by applicable law or agreed to in writing, software
    010    // distributed under the License is distributed on an "AS IS" BASIS,
    011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012    // See the License for the specific language governing permissions and
    013    // limitations under the License.
    014
    015    package org.apache.tapestry5.spring;
    016
    017    import org.apache.tapestry5.internal.spring.SymbolBeanFactoryPostProcessor;
    018    import org.apache.tapestry5.ioc.MappedConfiguration;
    019    import org.apache.tapestry5.ioc.OrderedConfiguration;
    020    import org.apache.tapestry5.ioc.annotations.Contribute;
    021    import org.apache.tapestry5.ioc.annotations.Marker;
    022    import org.apache.tapestry5.ioc.annotations.Primary;
    023    import org.apache.tapestry5.ioc.services.ChainBuilder;
    024    import org.apache.tapestry5.ioc.services.FactoryDefaults;
    025    import org.apache.tapestry5.ioc.services.SymbolProvider;
    026    import org.apache.tapestry5.ioc.services.SymbolSource;
    027    import org.apache.tapestry5.services.ApplicationInitializer;
    028    import org.apache.tapestry5.services.ApplicationInitializerFilter;
    029    import org.apache.tapestry5.services.Context;
    030    import org.slf4j.Logger;
    031    import org.springframework.context.ApplicationContext;
    032    import org.springframework.core.SpringVersion;
    033    import org.springframework.web.context.ConfigurableWebApplicationContext;
    034
    035    import javax.servlet.ServletContext;
    036    import java.util.List;
    037
    038    /**
    039     * Module for Tapestry/Spring Integration. This module exists to force the load of the Spring ApplicationContext as part
    040     * of Tapestry application initialization.
    041     *
    042     * @since 5.1.0.0
    043     */
    044    public class SpringModule
    045    {
    046        private final Logger logger;
    047
    048        public SpringModule(Logger logger)
    049        {
    050            this.logger = logger;
    051        }
    052
    053        @Contribute(ApplicationInitializer.class)
    054        public void reportSpringContextDetailsAtStartup(
    055                OrderedConfiguration<ApplicationInitializerFilter> configuration, final ApplicationContext springContext)
    056        {
    057            ApplicationInitializerFilter filter = new ApplicationInitializerFilter()
    058            {
    059                public void initializeApplication(Context context, ApplicationInitializer initializer)
    060                {
    061                    logger.info(String.format("Spring version %s with %,d defined beans.",
    062                            SpringVersion.getVersion(),
    063                            springContext.getBeanDefinitionCount()));
    064
    065                    initializer.initializeApplication(context);
    066                }
    067            };
    068
    069            configuration.add("SpringContextInitialization", filter);
    070        }
    071
    072        @Contribute(SymbolProvider.class)
    073        @FactoryDefaults
    074        public static void defaultExternalSpringContextOff(MappedConfiguration<String, Object> configuration)
    075        {
    076            configuration.add(SpringConstants.USE_EXTERNAL_SPRING_CONTEXT, false);
    077        }
    078
    079        /**
    080         * Defines a chain-of-command for handling application context customization. This allows the Spring context to be
    081         * configured before it is initially {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
    082         * refreshed}.
    083         */
    084        @Marker(Primary.class)
    085        public static ApplicationContextCustomizer buildApplicationContextCustomizer(
    086                List<ApplicationContextCustomizer> configuration,
    087                ChainBuilder builder)
    088        {
    089            return builder.build(ApplicationContextCustomizer.class, configuration);
    090        }
    091
    092        @Contribute(ApplicationContextCustomizer.class)
    093        public static void addSymbolSourceAsPropertyCustomizerForSpringBeans(
    094                OrderedConfiguration<ApplicationContextCustomizer> configuration,
    095                final SymbolSource symbolSource)
    096        {
    097            ApplicationContextCustomizer beanFactoryPostProcessorCustomizer = new ApplicationContextCustomizer()
    098            {
    099
    100                public void customizeApplicationContext(ServletContext servletContext,
    101                                                        ConfigurableWebApplicationContext applicationContext)
    102                {
    103                    applicationContext.addBeanFactoryPostProcessor(new SymbolBeanFactoryPostProcessor(symbolSource));
    104
    105                }
    106            };
    107
    108            configuration.add("BeanFactoryPostProcessorCustomizer", beanFactoryPostProcessorCustomizer);
    109        }
    110    }