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.web.server;
018
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.List;
023
024import org.springframework.beans.BeansException;
025import org.springframework.beans.factory.BeanFactory;
026import org.springframework.beans.factory.BeanFactoryAware;
027import org.springframework.beans.factory.ListableBeanFactory;
028import org.springframework.beans.factory.config.BeanPostProcessor;
029import org.springframework.boot.util.LambdaSafe;
030import org.springframework.core.annotation.AnnotationAwareOrderComparator;
031import org.springframework.util.Assert;
032
033/**
034 * {@link BeanPostProcessor} that applies all {@link WebServerFactoryCustomizer} beans
035 * from the bean factory to {@link WebServerFactory} beans.
036 *
037 * @author Dave Syer
038 * @author Phillip Webb
039 * @author Stephane Nicoll
040 * @since 2.0.0
041 */
042public class WebServerFactoryCustomizerBeanPostProcessor
043                implements BeanPostProcessor, BeanFactoryAware {
044
045        private ListableBeanFactory beanFactory;
046
047        private List<WebServerFactoryCustomizer<?>> customizers;
048
049        @Override
050        public void setBeanFactory(BeanFactory beanFactory) {
051                Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
052                                "WebServerCustomizerBeanPostProcessor can only be used "
053                                                + "with a ListableBeanFactory");
054                this.beanFactory = (ListableBeanFactory) beanFactory;
055        }
056
057        @Override
058        public Object postProcessBeforeInitialization(Object bean, String beanName)
059                        throws BeansException {
060                if (bean instanceof WebServerFactory) {
061                        postProcessBeforeInitialization((WebServerFactory) bean);
062                }
063                return bean;
064        }
065
066        @Override
067        public Object postProcessAfterInitialization(Object bean, String beanName)
068                        throws BeansException {
069                return bean;
070        }
071
072        @SuppressWarnings("unchecked")
073        private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
074                LambdaSafe
075                                .callbacks(WebServerFactoryCustomizer.class, getCustomizers(),
076                                                webServerFactory)
077                                .withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
078                                .invoke((customizer) -> customizer.customize(webServerFactory));
079        }
080
081        private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
082                if (this.customizers == null) {
083                        // Look up does not include the parent context
084                        this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
085                        this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
086                        this.customizers = Collections.unmodifiableList(this.customizers);
087                }
088                return this.customizers;
089        }
090
091        @SuppressWarnings({ "unchecked", "rawtypes" })
092        private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
093                return (Collection) this.beanFactory
094                                .getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
095        }
096
097}