001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.autoconfigure.web.servlet;
018
019import javax.servlet.ServletRequest;
020
021import org.springframework.beans.BeansException;
022import org.springframework.beans.factory.BeanFactory;
023import org.springframework.beans.factory.BeanFactoryAware;
024import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
025import org.springframework.beans.factory.support.BeanDefinitionRegistry;
026import org.springframework.beans.factory.support.RootBeanDefinition;
027import org.springframework.boot.autoconfigure.AutoConfigureOrder;
028import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
029import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
030import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
031import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
032import org.springframework.boot.autoconfigure.web.ServerProperties;
033import org.springframework.boot.context.properties.EnableConfigurationProperties;
034import org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor;
035import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
036import org.springframework.context.annotation.Bean;
037import org.springframework.context.annotation.Configuration;
038import org.springframework.context.annotation.Import;
039import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
040import org.springframework.core.Ordered;
041import org.springframework.core.type.AnnotationMetadata;
042import org.springframework.util.ObjectUtils;
043
044/**
045 * {@link EnableAutoConfiguration Auto-configuration} for servlet web servers.
046 *
047 * @author Phillip Webb
048 * @author Dave Syer
049 * @author Ivan Sopov
050 * @author Brian Clozel
051 * @author Stephane Nicoll
052 */
053@Configuration
054@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
055@ConditionalOnClass(ServletRequest.class)
056@ConditionalOnWebApplication(type = Type.SERVLET)
057@EnableConfigurationProperties(ServerProperties.class)
058@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
059                ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
060                ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
061                ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
062public class ServletWebServerFactoryAutoConfiguration {
063
064        @Bean
065        public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(
066                        ServerProperties serverProperties) {
067                return new ServletWebServerFactoryCustomizer(serverProperties);
068        }
069
070        @Bean
071        @ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
072        public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
073                        ServerProperties serverProperties) {
074                return new TomcatServletWebServerFactoryCustomizer(serverProperties);
075        }
076
077        /**
078         * Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via
079         * {@link ImportBeanDefinitionRegistrar} for early registration.
080         */
081        public static class BeanPostProcessorsRegistrar
082                        implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
083
084                private ConfigurableListableBeanFactory beanFactory;
085
086                @Override
087                public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
088                        if (beanFactory instanceof ConfigurableListableBeanFactory) {
089                                this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
090                        }
091                }
092
093                @Override
094                public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
095                                BeanDefinitionRegistry registry) {
096                        if (this.beanFactory == null) {
097                                return;
098                        }
099                        registerSyntheticBeanIfMissing(registry,
100                                        "webServerFactoryCustomizerBeanPostProcessor",
101                                        WebServerFactoryCustomizerBeanPostProcessor.class);
102                        registerSyntheticBeanIfMissing(registry,
103                                        "errorPageRegistrarBeanPostProcessor",
104                                        ErrorPageRegistrarBeanPostProcessor.class);
105                }
106
107                private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry,
108                                String name, Class<?> beanClass) {
109                        if (ObjectUtils.isEmpty(
110                                        this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
111                                RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
112                                beanDefinition.setSynthetic(true);
113                                registry.registerBeanDefinition(name, beanDefinition);
114                        }
115                }
116
117        }
118
119}