    001// Copyright 2008-2013 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
    015package org.apache.tapestry5.spring.modules;
    016
    017import org.apache.tapestry5.internal.spring.SymbolBeanFactoryPostProcessor;
    018import org.apache.tapestry5.ioc.MappedConfiguration;
    019import org.apache.tapestry5.ioc.OrderedConfiguration;
    020import org.apache.tapestry5.ioc.annotations.Contribute;
    021import org.apache.tapestry5.ioc.annotations.Marker;
    022import org.apache.tapestry5.ioc.annotations.Primary;
    023import org.apache.tapestry5.ioc.services.ChainBuilder;
    024import org.apache.tapestry5.ioc.services.FactoryDefaults;
    025import org.apache.tapestry5.ioc.services.SymbolProvider;
    026import org.apache.tapestry5.ioc.services.SymbolSource;
    027import org.apache.tapestry5.services.ApplicationInitializer;
    028import org.apache.tapestry5.services.ApplicationInitializerFilter;
    029import org.apache.tapestry5.services.Context;
    030import org.apache.tapestry5.spring.ApplicationContextCustomizer;
    031import org.apache.tapestry5.spring.SpringConstants;
    032import org.slf4j.Logger;
    033import org.springframework.context.ApplicationContext;
    034import org.springframework.core.SpringVersion;
    035import org.springframework.web.context.ConfigurableWebApplicationContext;
    036
    037import javax.servlet.ServletContext;
    038import java.util.List;
    039
    040/**
    041 * Module for Tapestry/Spring Integration. This module exists to force the load of the Spring ApplicationContext as part
    042 * of Tapestry application initialization.
    043 *
    044 * @since 5.1.0.0
    045 */
    046public class SpringModule
    047{
    048    private final Logger logger;
    049
    050    public SpringModule(Logger logger)
    051    {
    052        this.logger = logger;
    053    }
    054
    055    @Contribute(ApplicationInitializer.class)
    056    public void reportSpringContextDetailsAtStartup(
    057            OrderedConfiguration<ApplicationInitializerFilter> configuration, final ApplicationContext springContext)
    058    {
    059        ApplicationInitializerFilter filter = new ApplicationInitializerFilter()
    060        {
    061            @Override
    062            public void initializeApplication(Context context, ApplicationInitializer initializer)
    063            {
    064                logger.info(String.format("Spring version %s with %,d defined beans.",
    065                        SpringVersion.getVersion(),
    066                        springContext.getBeanDefinitionCount()));
    067
    068                initializer.initializeApplication(context);
    069            }
    070        };
    071
    072        configuration.add("SpringContextInitialization", filter);
    073    }
    074
    075    @Contribute(SymbolProvider.class)
    076    @FactoryDefaults
    077    public static void defaultExternalSpringContextOff(MappedConfiguration<String, Object> configuration)
    078    {
    079        configuration.add(SpringConstants.USE_EXTERNAL_SPRING_CONTEXT, false);
    080    }
    081
    082    /**
    083     * Defines a chain-of-command for handling application context customization. This allows the Spring context to be
    084     * configured before it is initially {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
    085     * refreshed}.
    086     */
    087    @Marker(Primary.class)
    088    public static ApplicationContextCustomizer buildApplicationContextCustomizer(
    089            List<ApplicationContextCustomizer> configuration,
    090            ChainBuilder builder)
    091    {
    092        return builder.build(ApplicationContextCustomizer.class, configuration);
    093    }
    094
    095    @Contribute(ApplicationContextCustomizer.class)
    096    public static void addSymbolSourceAsPropertyCustomizerForSpringBeans(
    097            OrderedConfiguration<ApplicationContextCustomizer> configuration,
    098            final SymbolSource symbolSource)
    099    {
    100        ApplicationContextCustomizer beanFactoryPostProcessorCustomizer = new ApplicationContextCustomizer()
    101        {
    102
    103            @Override
    104            public void customizeApplicationContext(ServletContext servletContext,
    105                                                    ConfigurableWebApplicationContext applicationContext)
    106            {
    107                applicationContext.addBeanFactoryPostProcessor(new SymbolBeanFactoryPostProcessor(symbolSource));
    108
    109            }
    110        };
    111
    112        configuration.add("BeanFactoryPostProcessorCustomizer", beanFactoryPostProcessorCustomizer);
    113    }
    114}