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.embedded.jetty;
018
019import javax.servlet.ServletException;
020
021import org.eclipse.jetty.util.component.AbstractLifeCycle;
022import org.eclipse.jetty.webapp.AbstractConfiguration;
023import org.eclipse.jetty.webapp.Configuration;
024import org.eclipse.jetty.webapp.WebAppContext;
025
026import org.springframework.boot.web.servlet.ServletContextInitializer;
027import org.springframework.util.Assert;
028
029/**
030 * Jetty {@link Configuration} that calls {@link ServletContextInitializer}s.
031 *
032 * @author Phillip Webb
033 * @author Andy Wilkinson
034 * @since 2.0.0
035 */
036public class ServletContextInitializerConfiguration extends AbstractConfiguration {
037
038        private final ServletContextInitializer[] initializers;
039
040        /**
041         * Create a new {@link ServletContextInitializerConfiguration}.
042         * @param initializers the initializers that should be invoked
043         * @since 1.2.1
044         */
045        public ServletContextInitializerConfiguration(
046                        ServletContextInitializer... initializers) {
047                Assert.notNull(initializers, "Initializers must not be null");
048                this.initializers = initializers;
049        }
050
051        @Override
052        public void configure(WebAppContext context) throws Exception {
053                context.addBean(new Initializer(context), true);
054        }
055
056        /**
057         * Jetty {@link AbstractLifeCycle} to call the {@link ServletContextInitializer
058         * ServletContextInitializers}.
059         */
060        private class Initializer extends AbstractLifeCycle {
061
062                private final WebAppContext context;
063
064                Initializer(WebAppContext context) {
065                        this.context = context;
066                }
067
068                @Override
069                protected void doStart() throws Exception {
070                        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
071                        Thread.currentThread().setContextClassLoader(this.context.getClassLoader());
072                        try {
073                                callInitializers();
074                        }
075                        finally {
076                                Thread.currentThread().setContextClassLoader(classLoader);
077                        }
078                }
079
080                private void callInitializers() throws ServletException {
081                        try {
082                                setExtendedListenerTypes(true);
083                                for (ServletContextInitializer initializer : ServletContextInitializerConfiguration.this.initializers) {
084                                        initializer.onStartup(this.context.getServletContext());
085                                }
086                        }
087                        finally {
088                                setExtendedListenerTypes(false);
089                        }
090                }
091
092                private void setExtendedListenerTypes(boolean extended) {
093                        try {
094                                this.context.getServletContext().setExtendedListenerTypes(extended);
095                        }
096                        catch (NoSuchMethodError ex) {
097                                // Not available on Jetty 8
098                        }
099                }
100
101        }
102
103}