001/*
002 * Copyright 2012-2017 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.core.annotation.AnnotationAwareOrderComparator;
030import org.springframework.util.Assert;
031
032/**
033 * {@link BeanPostProcessor} that applies all {@link ErrorPageRegistrar}s from the bean
034 * factory to {@link ErrorPageRegistry} beans.
035 *
036 * @author Phillip Webb
037 * @author Stephane Nicoll
038 * @since 2.0.0
039 */
040public class ErrorPageRegistrarBeanPostProcessor
041                implements BeanPostProcessor, BeanFactoryAware {
042
043        private ListableBeanFactory beanFactory;
044
045        private List<ErrorPageRegistrar> registrars;
046
047        @Override
048        public void setBeanFactory(BeanFactory beanFactory) {
049                Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
050                                "ErrorPageRegistrarBeanPostProcessor can only be used "
051                                                + "with a ListableBeanFactory");
052                this.beanFactory = (ListableBeanFactory) beanFactory;
053        }
054
055        @Override
056        public Object postProcessBeforeInitialization(Object bean, String beanName)
057                        throws BeansException {
058                if (bean instanceof ErrorPageRegistry) {
059                        postProcessBeforeInitialization((ErrorPageRegistry) bean);
060                }
061                return bean;
062        }
063
064        @Override
065        public Object postProcessAfterInitialization(Object bean, String beanName)
066                        throws BeansException {
067                return bean;
068        }
069
070        private void postProcessBeforeInitialization(ErrorPageRegistry registry) {
071                for (ErrorPageRegistrar registrar : getRegistrars()) {
072                        registrar.registerErrorPages(registry);
073                }
074        }
075
076        private Collection<ErrorPageRegistrar> getRegistrars() {
077                if (this.registrars == null) {
078                        // Look up does not include the parent context
079                        this.registrars = new ArrayList<>(this.beanFactory
080                                        .getBeansOfType(ErrorPageRegistrar.class, false, false).values());
081                        this.registrars.sort(AnnotationAwareOrderComparator.INSTANCE);
082                        this.registrars = Collections.unmodifiableList(this.registrars);
083                }
084                return this.registrars;
085        }
086
087}