From aea18671c10658b449e4644d47092a953f9abb86 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 27 Apr 2016 10:28:34 -0700 Subject: [PATCH] Restructure web related classes Reorganize web related classes for better separation of concerns. Mainly this involves moving classes from `o.s.b.context.embedded` that aren't directly tied to embedded servlet containers to `o.s.b.web` and relocating everything from `o.s.b.context.web`. See gh-5822 --- .../EndpointWebMvcAutoConfiguration.java | 2 +- .../jersey/JerseyAutoConfiguration.java | 6 +- .../web/ServerPropertiesTests.java | 2 +- .../CityRepositoryIntegrationTests.java | 1 - .../HotelRepositoryIntegrationTests.java | 2 - .../SpringBootMockMvcBuilderCustomizer.java | 8 +- ...tConfigurableEmbeddedServletContainer.java | 4 +- .../ConfigurableEmbeddedServletContainer.java | 5 +- ...DelegatingFilterProxyRegistrationBean.java | 51 +-- .../EmbeddedServletContainerFactory.java | 3 +- .../EmbeddedWebApplicationContext.java | 10 +- .../boot/context/embedded/ErrorPage.java | 110 +----- .../embedded/FilterRegistrationBean.java | 45 +-- ...rConfiguringServletContextInitializer.java | 4 +- .../embedded/MultipartConfigFactory.java | 103 +----- ...PortInfoApplicationContextInitializer.java | 106 ++++++ .../embedded/ServletContextInitializer.java | 18 +- .../ServletListenerRegistrationBean.java | 98 +---- .../embedded/ServletRegistrationBean.java | 183 +--------- .../JettyEmbeddedServletContainerFactory.java | 4 +- ...ervletContextInitializerConfiguration.java | 4 +- .../boot/context/embedded/package-info.java | 5 +- ...TomcatEmbeddedServletContainerFactory.java | 4 +- .../embedded/tomcat/TomcatStarter.java | 4 +- ...dertowEmbeddedServletContainerFactory.java | 4 +- .../boot/context/web/ErrorPageFilter.java | 299 +--------------- .../web/OrderedCharacterEncodingFilter.java | 24 +- .../web/OrderedHiddenHttpMethodFilter.java | 28 +- .../web/OrderedHttpPutFormContentFilter.java | 28 +- .../web/OrderedRequestContextFilter.java | 25 +- ...PortInfoApplicationContextInitializer.java | 71 +--- ...tContextApplicationContextInitializer.java | 57 +-- .../web/SpringBootServletInitializer.java | 133 +------ .../ApplicationContextHeaderFilter.java | 2 +- .../OrderedCharacterEncodingFilter.java | 46 +++ .../filter/OrderedHiddenHttpMethodFilter.java | 53 +++ .../OrderedHttpPutFormContentFilter.java | 53 +++ .../filter/OrderedRequestContextFilter.java | 47 +++ .../boot/web/filter/package-info.java | 20 ++ .../AbstractFilterRegistrationBean.java | 6 +- ...DelegatingFilterProxyRegistrationBean.java | 96 +++++ .../boot/web/servlet/ErrorPage.java | 137 +++++++ .../web/servlet/FilterRegistrationBean.java | 84 +++++ .../web/servlet/MultipartConfigFactory.java | 132 +++++++ .../servlet}/RegistrationBean.java | 5 +- .../servlet/ServletContextInitializer.java | 52 +++ .../ServletContextInitializerBeans.java | 4 +- .../ServletListenerRegistrationBean.java | 149 ++++++++ .../web/servlet/ServletRegistrationBean.java | 221 ++++++++++++ .../boot/web/servlet/WebFilterHandler.java | 3 +- .../boot/web/servlet/WebListenerHandler.java | 3 +- .../boot/web/servlet/WebServletHandler.java | 3 +- .../boot/web/servlet/package-info.java | 20 ++ .../boot/web/support/ErrorPageFilter.java | 336 ++++++++++++++++++ ...tContextApplicationContextInitializer.java | 84 +++++ .../support/SpringBootServletInitializer.java | 176 +++++++++ ...tEmbeddedServletContainerFactoryTests.java | 4 + ...figEmbeddedWebApplicationContextTests.java | 1 + ...edServletContainerMvcIntegrationTests.java | 1 + .../EmbeddedWebApplicationContextTests.java | 22 +- .../MockEmbeddedServletContainerFactory.java | 4 +- ...leEmbeddedWebApplicationConfiguration.java | 4 +- ...yEmbeddedServletContainerFactoryTests.java | 2 +- ...wEmbeddedServletContainerFactoryTests.java | 4 +- .../embedded => testutil}/MockFilter.java | 4 +- .../embedded => testutil}/MockServlet.java | 4 +- .../AbstractFilterRegistrationBeanTests.java | 29 +- ...atingFilterProxyRegistrationBeanTests.java | 2 +- .../servlet}/FilterRegistrationBeanTests.java | 6 +- .../servlet}/MultipartConfigFactoryTests.java | 2 +- .../ServletComponentScanIntegrationTests.java | 2 +- .../ServletListenerRegistrationBeanTests.java | 4 +- .../ServletRegistrationBeanTests.java | 6 +- .../ErrorPageFilterIntegrationTests.java | 7 +- .../support}/ErrorPageFilterTests.java | 4 +- .../SpringBootServletInitializerTests.java | 2 +- ...pleEmbeddedWebApplicationConfiguration.xml | 2 +- 77 files changed, 2047 insertions(+), 1252 deletions(-) create mode 100644 spring-boot/src/main/java/org/springframework/boot/context/embedded/ServerPortInfoApplicationContextInitializer.java rename spring-boot/src/main/java/org/springframework/boot/{context/web => web/filter}/ApplicationContextHeaderFilter.java (97%) create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedCharacterEncodingFilter.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedHiddenHttpMethodFilter.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedHttpPutFormContentFilter.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedRequestContextFilter.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/filter/package-info.java rename spring-boot/src/main/java/org/springframework/boot/{context/embedded => web/servlet}/AbstractFilterRegistrationBean.java (97%) create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/servlet/ErrorPage.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/servlet/FilterRegistrationBean.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/servlet/MultipartConfigFactory.java rename spring-boot/src/main/java/org/springframework/boot/{context/embedded => web/servlet}/RegistrationBean.java (97%) create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializer.java rename spring-boot/src/main/java/org/springframework/boot/{context/embedded => web/servlet}/ServletContextInitializerBeans.java (98%) create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBean.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistrationBean.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/servlet/package-info.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/support/ServletContextApplicationContextInitializer.java create mode 100644 spring-boot/src/main/java/org/springframework/boot/web/support/SpringBootServletInitializer.java rename spring-boot/src/test/java/org/springframework/boot/{context/embedded => testutil}/MockFilter.java (91%) rename spring-boot/src/test/java/org/springframework/boot/{context/embedded => testutil}/MockServlet.java (90%) rename spring-boot/src/test/java/org/springframework/boot/{context/embedded => web/servlet}/AbstractFilterRegistrationBeanTests.java (89%) rename spring-boot/src/test/java/org/springframework/boot/{context/embedded => web/servlet}/DelegatingFilterProxyRegistrationBeanTests.java (98%) rename spring-boot/src/test/java/org/springframework/boot/{context/embedded => web/servlet}/FilterRegistrationBeanTests.java (93%) rename spring-boot/src/test/java/org/springframework/boot/{context/embedded => web/servlet}/MultipartConfigFactoryTests.java (97%) rename spring-boot/src/test/java/org/springframework/boot/{context/embedded => web/servlet}/ServletListenerRegistrationBeanTests.java (95%) rename spring-boot/src/test/java/org/springframework/boot/{context/embedded => web/servlet}/ServletRegistrationBeanTests.java (97%) rename spring-boot/src/test/java/org/springframework/boot/{context/web => web/support}/ErrorPageFilterIntegrationTests.java (95%) rename spring-boot/src/test/java/org/springframework/boot/{context/web => web/support}/ErrorPageFilterTests.java (99%) rename spring-boot/src/test/java/org/springframework/boot/{context/web => web/support}/SpringBootServletInitializerTests.java (99%) diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java index e240b99105..02c6c35035 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfiguration.java @@ -54,7 +54,7 @@ import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; -import org.springframework.boot.context.web.ApplicationContextHeaderFilter; +import org.springframework.boot.web.filter.ApplicationContextHeaderFilter; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfiguration.java index a3a18bc9c8..1ad876886e 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jersey/JerseyAutoConfiguration.java @@ -53,10 +53,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandi import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration; -import org.springframework.boot.context.embedded.FilterRegistrationBean; -import org.springframework.boot.context.embedded.RegistrationBean; -import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.RegistrationBean; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java index 81e8b4f26c..b91a5ad199 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ServerPropertiesTests.java @@ -40,10 +40,10 @@ import org.mockito.MockitoAnnotations; import org.springframework.beans.MutablePropertyValues; import org.springframework.boot.bind.RelaxedDataBinder; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; -import org.springframework.boot.context.embedded.ServletContextInitializer; import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory; +import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot-samples/spring-boot-sample-hibernate4/src/test/java/sample/hibernate4/service/CityRepositoryIntegrationTests.java b/spring-boot-samples/spring-boot-sample-hibernate4/src/test/java/sample/hibernate4/service/CityRepositoryIntegrationTests.java index cb4e5a49d1..7e45da7ef3 100644 --- a/spring-boot-samples/spring-boot-sample-hibernate4/src/test/java/sample/hibernate4/service/CityRepositoryIntegrationTests.java +++ b/spring-boot-samples/spring-boot-sample-hibernate4/src/test/java/sample/hibernate4/service/CityRepositoryIntegrationTests.java @@ -18,7 +18,6 @@ package sample.hibernate4.service; import org.junit.Test; import org.junit.runner.RunWith; import sample.hibernate4.domain.City; -import sample.hibernate4.service.CityRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; diff --git a/spring-boot-samples/spring-boot-sample-hibernate4/src/test/java/sample/hibernate4/service/HotelRepositoryIntegrationTests.java b/spring-boot-samples/spring-boot-sample-hibernate4/src/test/java/sample/hibernate4/service/HotelRepositoryIntegrationTests.java index 05365ce953..be76a41ff5 100644 --- a/spring-boot-samples/spring-boot-sample-hibernate4/src/test/java/sample/hibernate4/service/HotelRepositoryIntegrationTests.java +++ b/spring-boot-samples/spring-boot-sample-hibernate4/src/test/java/sample/hibernate4/service/HotelRepositoryIntegrationTests.java @@ -24,8 +24,6 @@ import sample.hibernate4.domain.Hotel; import sample.hibernate4.domain.HotelSummary; import sample.hibernate4.domain.Rating; import sample.hibernate4.domain.RatingCount; -import sample.hibernate4.service.CityRepository; -import sample.hibernate4.service.HotelRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/SpringBootMockMvcBuilderCustomizer.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/SpringBootMockMvcBuilderCustomizer.java index ba7b07b919..4f942386d5 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/SpringBootMockMvcBuilderCustomizer.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/web/servlet/SpringBootMockMvcBuilderCustomizer.java @@ -20,10 +20,10 @@ import java.util.Collection; import javax.servlet.Filter; -import org.springframework.boot.context.embedded.DelegatingFilterProxyRegistrationBean; -import org.springframework.boot.context.embedded.FilterRegistrationBean; -import org.springframework.boot.context.embedded.ServletContextInitializer; -import org.springframework.boot.context.embedded.ServletContextInitializerBeans; +import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.servlet.ServletContextInitializerBeans; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder; import org.springframework.util.Assert; diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractConfigurableEmbeddedServletContainer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractConfigurableEmbeddedServletContainer.java index 4c40cdc003..c22785bd61 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractConfigurableEmbeddedServletContainer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractConfigurableEmbeddedServletContainer.java @@ -25,6 +25,8 @@ import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -234,7 +236,7 @@ public abstract class AbstractConfigurableEmbeddedServletContainer } @Override - public void setErrorPages(Set errorPages) { + public void setErrorPages(Set errorPages) { Assert.notNull(errorPages, "ErrorPages must not be null"); this.errorPages = new LinkedHashSet(errorPages); } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ConfigurableEmbeddedServletContainer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ConfigurableEmbeddedServletContainer.java index 9429cb34c5..72e6720d9d 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ConfigurableEmbeddedServletContainer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ConfigurableEmbeddedServletContainer.java @@ -22,6 +22,9 @@ import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.boot.web.servlet.ServletContextInitializer; + /** * Simple interface that represents customizations to an * {@link EmbeddedServletContainerFactory}. @@ -109,7 +112,7 @@ public interface ConfigurableEmbeddedServletContainer { * Sets the error pages that will be used when handling exceptions. * @param errorPages the error pages */ - void setErrorPages(Set errorPages); + void setErrorPages(Set errorPages); /** * Sets the mime-type mappings. diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBean.java index a311c3e5f7..2d5342125a 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBean.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBean.java @@ -19,11 +19,7 @@ package org.springframework.boot.context.embedded; import javax.servlet.Filter; import javax.servlet.ServletContext; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.util.Assert; -import org.springframework.web.context.WebApplicationContext; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.web.filter.DelegatingFilterProxy; /** @@ -49,48 +45,17 @@ import org.springframework.web.filter.DelegatingFilterProxy; * @see ServletContext#addFilter(String, Filter) * @see FilterRegistrationBean * @see DelegatingFilterProxy + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.DelegatingFilterProxyRegistrationBean */ -public class DelegatingFilterProxyRegistrationBean extends AbstractFilterRegistrationBean - implements ApplicationContextAware { +@Deprecated +public class DelegatingFilterProxyRegistrationBean + extends org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean + implements org.springframework.boot.context.embedded.ServletContextInitializer { - private ApplicationContext applicationContext; - - private final String targetBeanName; - - /** - * Create a new {@link DelegatingFilterProxyRegistrationBean} instance to be - * registered with the specified {@link ServletRegistrationBean}s. - * @param targetBeanName name of the target filter bean to look up in the Spring - * application context (must not be {@code null}). - * @param servletRegistrationBeans associate {@link ServletRegistrationBean}s - */ public DelegatingFilterProxyRegistrationBean(String targetBeanName, ServletRegistrationBean... servletRegistrationBeans) { - super(servletRegistrationBeans); - Assert.hasLength(targetBeanName, "TargetBeanName must not be null or empty"); - this.targetBeanName = targetBeanName; - setName(targetBeanName); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - - protected String getTargetBeanName() { - return this.targetBeanName; - } - - @Override - public Filter getFilter() { - return new DelegatingFilterProxy(this.targetBeanName, getWebApplicationContext()); - } - - private WebApplicationContext getWebApplicationContext() { - Assert.notNull(this.applicationContext, "ApplicationContext be injected"); - Assert.isInstanceOf(WebApplicationContext.class, this.applicationContext); - return (WebApplicationContext) this.applicationContext; + super(targetBeanName, servletRegistrationBeans); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedServletContainerFactory.java index 1567f113b3..b459eadebb 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedServletContainerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import org.apache.catalina.core.ApplicationContext; import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; +import org.springframework.boot.web.servlet.ServletContextInitializer; /** * Factory interface that can be used to create {@link EmbeddedServletContainer}s. diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java index 1f1ae9be04..436f3fc60e 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,10 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.Scope; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.servlet.ServletContextInitializerBeans; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextException; import org.springframework.core.io.Resource; @@ -93,7 +97,7 @@ public class EmbeddedWebApplicationContext extends GenericWebApplicationContext * default. To change the default behaviour you can use a * {@link ServletRegistrationBean} or a different bean name. */ - public static final String DISPATCHER_SERVLET_NAME = ServletContextInitializerBeans.DISPATCHER_SERVLET_NAME; + public static final String DISPATCHER_SERVLET_NAME = "dispatcherServlet"; private volatile EmbeddedServletContainer embeddedServletContainer; @@ -202,7 +206,7 @@ public class EmbeddedWebApplicationContext extends GenericWebApplicationContext * @return the self initializer * @see #prepareEmbeddedWebApplicationContext(ServletContext) */ - private ServletContextInitializer getSelfInitializer() { + private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() { return new ServletContextInitializer() { @Override public void onStartup(ServletContext servletContext) throws ServletException { diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ErrorPage.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ErrorPage.java index 64f0be3e48..9789c8cdf5 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ErrorPage.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ErrorPage.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,119 +17,27 @@ package org.springframework.boot.context.embedded; import org.springframework.http.HttpStatus; -import org.springframework.util.ObjectUtils; /** * Simple container-independent abstraction for servlet error pages. Roughly equivalent to * the {@literal <error-page>} element traditionally found in web.xml. * * @author Dave Syer + * @deprecated as of 1.4 in favor of org.springframework.boot.web.ErrorPage */ -public class ErrorPage { +@Deprecated +public class ErrorPage extends org.springframework.boot.web.servlet.ErrorPage { - private final HttpStatus status; - - private final Class exception; - - private final String path; - - public ErrorPage(String path) { - this.status = null; - this.exception = null; - this.path = path; + public ErrorPage(Class exception, String path) { + super(exception, path); } public ErrorPage(HttpStatus status, String path) { - this.status = status; - this.exception = null; - this.path = path; + super(status, path); } - public ErrorPage(Class exception, String path) { - this.status = null; - this.exception = exception; - this.path = path; - } - - /** - * The path to render (usually implemented as a forward), starting with "/". A custom - * controller or servlet path can be used, or if the container supports it, a template - * path (e.g. "/error.jsp"). - * @return the path that will be rendered for this error - */ - public String getPath() { - return this.path; - } - - /** - * Returns the exception type (or {@code null} for a page that matches by status). - * @return the exception type or {@code null} - */ - public Class getException() { - return this.exception; - } - - /** - * The HTTP status value that this error page matches (or {@code null} for a page that - * matches by exception). - * @return the status or {@code null} - */ - public HttpStatus getStatus() { - return this.status; - } - - /** - * The HTTP status value that this error page matches. - * @return the status value (or 0 for a page that matches any status) - */ - public int getStatusCode() { - return (this.status == null ? 0 : this.status.value()); - } - - /** - * The exception type name. - * @return the exception type name (or {@code null} if there is none) - */ - public String getExceptionName() { - return (this.exception == null ? null : this.exception.getName()); - } - - /** - * Return if this error page is a global one (matches all unmatched status and - * exception types). - * @return if this is a global error page - */ - public boolean isGlobal() { - return (this.status == null && this.exception == null); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ObjectUtils.nullSafeHashCode(getExceptionName()); - result = prime * result + ObjectUtils.nullSafeHashCode(this.path); - result = prime * result + this.getStatusCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ErrorPage other = (ErrorPage) obj; - boolean rtn = true; - rtn &= ObjectUtils.nullSafeEquals(getExceptionName(), other.getExceptionName()); - rtn &= ObjectUtils.nullSafeEquals(this.path, other.path); - rtn &= this.status == other.status; - return rtn; + public ErrorPage(String path) { + super(path); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/FilterRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/FilterRegistrationBean.java index 8b75c23b76..5a9cf77e5f 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/FilterRegistrationBean.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/FilterRegistrationBean.java @@ -19,7 +19,9 @@ package org.springframework.boot.context.embedded; import javax.servlet.Filter; import javax.servlet.ServletContext; -import org.springframework.util.Assert; +import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.servlet.ServletRegistrationBean; /** * A {@link ServletContextInitializer} to register {@link Filter}s in a Servlet 3.0+ @@ -37,47 +39,20 @@ import org.springframework.util.Assert; * @see ServletContextInitializer * @see ServletContext#addFilter(String, Filter) * @see DelegatingFilterProxyRegistrationBean + * @deprecated as of 1.4 in favor of org.springframework.boot.web.FilterRegistrationBean */ -public class FilterRegistrationBean extends AbstractFilterRegistrationBean { +@Deprecated +public class FilterRegistrationBean + extends org.springframework.boot.web.servlet.FilterRegistrationBean + implements org.springframework.boot.context.embedded.ServletContextInitializer { - /** - * Filters that wrap the servlet request should be ordered less than or equal to this. - */ - public static final int REQUEST_WRAPPER_FILTER_MAX_ORDER = AbstractFilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER; - - private Filter filter; - - /** - * Create a new {@link FilterRegistrationBean} instance. - */ public FilterRegistrationBean() { + super(); } - /** - * Create a new {@link FilterRegistrationBean} instance to be registered with the - * specified {@link ServletRegistrationBean}s. - * @param filter the filter to register - * @param servletRegistrationBeans associate {@link ServletRegistrationBean}s - */ public FilterRegistrationBean(Filter filter, ServletRegistrationBean... servletRegistrationBeans) { - super(servletRegistrationBeans); - Assert.notNull(filter, "Filter must not be null"); - this.filter = filter; - } - - @Override - public Filter getFilter() { - return this.filter; - } - - /** - * Set the filter to be registered. - * @param filter the filter - */ - public void setFilter(Filter filter) { - Assert.notNull(filter, "Filter must not be null"); - this.filter = filter; + super(filter, servletRegistrationBeans); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/InitParameterConfiguringServletContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/InitParameterConfiguringServletContextInitializer.java index 6a0ce625b6..ad757713d5 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/InitParameterConfiguringServletContextInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/InitParameterConfiguringServletContextInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,8 @@ import java.util.Map.Entry; import javax.servlet.ServletContext; import javax.servlet.ServletException; +import org.springframework.boot.web.servlet.ServletContextInitializer; + /** * A {@code ServletContextInitializer} that configures init parameters on the * {@code ServletContext}. diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/MultipartConfigFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/MultipartConfigFactory.java index 328367944b..ad981980ae 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/MultipartConfigFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/MultipartConfigFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,6 @@ package org.springframework.boot.context.embedded; import javax.servlet.MultipartConfigElement; -import org.springframework.util.Assert; - /** * Factory that can be used to create a {@link MultipartConfigElement}. Size values can be * set using traditional {@literal long} values which are set in bytes or using more @@ -31,101 +29,10 @@ import org.springframework.util.Assert; * * * @author Phillip Webb + * @deprecated as of 1.4 in favor of org.springframework.boot.web.MultipartConfigFactory */ -public class MultipartConfigFactory { - - private String location; - - private long maxFileSize = -1; - - private long maxRequestSize = -1; - - private int fileSizeThreshold = 0; - - /** - * Sets the directory location where files will be stored. - * @param location the location - */ - public void setLocation(String location) { - this.location = location; - } - - /** - * Sets the maximum size in bytes allowed for uploaded files. - * @param maxFileSize the maximum file size - * @see #setMaxFileSize(String) - */ - public void setMaxFileSize(long maxFileSize) { - this.maxFileSize = maxFileSize; - } - - /** - * Sets the maximum size allowed for uploaded files. Values can use the suffixed "MB" - * or "KB" to indicate a Megabyte or Kilobyte size. - * @param maxFileSize the maximum file size - * @see #setMaxFileSize(long) - */ - public void setMaxFileSize(String maxFileSize) { - this.maxFileSize = parseSize(maxFileSize); - } - - /** - * Sets the maximum size allowed in bytes for multipart/form-data requests. - * @param maxRequestSize the maximum request size - * @see #setMaxRequestSize(String) - */ - public void setMaxRequestSize(long maxRequestSize) { - this.maxRequestSize = maxRequestSize; - } - - /** - * Sets the maximum size allowed for multipart/form-data requests. Values can use the - * suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. - * @param maxRequestSize the maximum request size - * @see #setMaxRequestSize(long) - */ - public void setMaxRequestSize(String maxRequestSize) { - this.maxRequestSize = parseSize(maxRequestSize); - } - - /** - * Sets the size threshold in bytes after which files will be written to disk. - * @param fileSizeThreshold the file size threshold - * @see #setFileSizeThreshold(String) - */ - public void setFileSizeThreshold(int fileSizeThreshold) { - this.fileSizeThreshold = fileSizeThreshold; - } - - /** - * Sets the size threshold after which files will be written to disk. Values can use - * the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. - * @param fileSizeThreshold the file size threshold - * @see #setFileSizeThreshold(int) - */ - public void setFileSizeThreshold(String fileSizeThreshold) { - this.fileSizeThreshold = (int) parseSize(fileSizeThreshold); - } - - private long parseSize(String size) { - Assert.hasLength(size, "Size must not be empty"); - size = size.toUpperCase(); - if (size.endsWith("KB")) { - return Long.valueOf(size.substring(0, size.length() - 2)) * 1024; - } - if (size.endsWith("MB")) { - return Long.valueOf(size.substring(0, size.length() - 2)) * 1024 * 1024; - } - return Long.valueOf(size); - } - - /** - * Create a new {@link MultipartConfigElement} instance. - * @return the multipart config element - */ - public MultipartConfigElement createMultipartConfig() { - return new MultipartConfigElement(this.location, this.maxFileSize, - this.maxRequestSize, this.fileSizeThreshold); - } +@Deprecated +public class MultipartConfigFactory + extends org.springframework.boot.web.servlet.MultipartConfigFactory { } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServerPortInfoApplicationContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServerPortInfoApplicationContextInitializer.java new file mode 100644 index 0000000000..e03179e1eb --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServerPortInfoApplicationContextInitializer.java @@ -0,0 +1,106 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.context.embedded; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ApplicationListener; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.util.StringUtils; + +/** + * {@link ApplicationContextInitializer} that sets {@link Environment} properties for the + * ports that {@link EmbeddedServletContainer} servers are actually listening on. The + * property {@literal "local.server.port"} can be injected directly into tests using + * {@link Value @Value} or obtained via the {@link Environment}. + *

+ * If the {@link EmbeddedWebApplicationContext} has a + * {@link EmbeddedWebApplicationContext#setNamespace(String) namespace} set, it will be + * used to construct the property name. For example, the "management" actuator context + * will have the property name {@literal "local.management.port"}. + *

+ * Properties are automatically propagated up to any parent context. + * + * @author Dave Syer + * @author Phillip Webb + * @since 1.4.0 + */ +public class ServerPortInfoApplicationContextInitializer + implements ApplicationContextInitializer { + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + applicationContext.addApplicationListener( + new ApplicationListener() { + + @Override + public void onApplicationEvent( + EmbeddedServletContainerInitializedEvent event) { + ServerPortInfoApplicationContextInitializer.this + .onApplicationEvent(event); + } + + }); + } + + protected void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { + String propertyName = getPropertyName(event.getApplicationContext()); + setPortProperty(event.getApplicationContext(), propertyName, + event.getEmbeddedServletContainer().getPort()); + } + + protected String getPropertyName(EmbeddedWebApplicationContext context) { + String name = context.getNamespace(); + if (StringUtils.isEmpty(name)) { + name = "server"; + } + return "local." + name + ".port"; + } + + private void setPortProperty(ApplicationContext context, String propertyName, + int port) { + if (context instanceof ConfigurableApplicationContext) { + setPortProperty(((ConfigurableApplicationContext) context).getEnvironment(), + propertyName, port); + } + if (context.getParent() != null) { + setPortProperty(context.getParent(), propertyName, port); + } + } + + @SuppressWarnings("unchecked") + private void setPortProperty(ConfigurableEnvironment environment, String propertyName, + int port) { + MutablePropertySources sources = environment.getPropertySources(); + PropertySource source = sources.get("server.ports"); + if (source == null) { + source = new MapPropertySource("server.ports", new HashMap()); + sources.addFirst(source); + } + ((Map) source.getSource()).put(propertyName, port); + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializer.java index e9e851dc26..bc736599ba 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package org.springframework.boot.context.embedded; import javax.servlet.ServletContext; -import javax.servlet.ServletException; import org.springframework.web.SpringServletContainerInitializer; import org.springframework.web.WebApplicationInitializer; @@ -36,16 +35,11 @@ import org.springframework.web.WebApplicationInitializer; * * @author Phillip Webb * @see WebApplicationInitializer + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.ServletContextInitializer */ -public interface ServletContextInitializer { - - /** - * Configure the given {@link ServletContext} with any servlets, filters, listeners - * context-params and attributes necessary for initialization. - * @param servletContext the {@code ServletContext} to initialize - * @throws ServletException if any call against the given {@code ServletContext} - * throws a {@code ServletException} - */ - void onStartup(ServletContext servletContext) throws ServletException; +@Deprecated +public interface ServletContextInitializer + extends org.springframework.boot.web.servlet.ServletContextInitializer { } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletListenerRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletListenerRegistrationBean.java index 9afa99c4a6..4d4057af2a 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletListenerRegistrationBean.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletListenerRegistrationBean.java @@ -16,25 +16,17 @@ package org.springframework.boot.context.embedded; -import java.util.Collections; import java.util.EventListener; -import java.util.HashSet; -import java.util.Set; import javax.servlet.ServletContext; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextListener; -import javax.servlet.ServletException; import javax.servlet.ServletRequestAttributeListener; import javax.servlet.ServletRequestListener; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionListener; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; +import org.springframework.boot.web.servlet.ServletContextInitializer; /** * A {@link ServletContextInitializer} to register {@link EventListener}s in a Servlet @@ -55,94 +47,20 @@ import org.springframework.util.ClassUtils; * @param the type of listener * @author Dave Syer * @author Phillip Webb + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.ServletListenerRegistrationBean */ +@Deprecated public class ServletListenerRegistrationBean - extends RegistrationBean { + extends org.springframework.boot.web.servlet.ServletListenerRegistrationBean + implements org.springframework.boot.context.embedded.ServletContextInitializer { - private static final Log logger = LogFactory - .getLog(ServletListenerRegistrationBean.class); - - private static final Set> SUPPORTED_TYPES; - - static { - Set> types = new HashSet>(); - types.add(ServletContextAttributeListener.class); - types.add(ServletRequestListener.class); - types.add(ServletRequestAttributeListener.class); - types.add(HttpSessionAttributeListener.class); - types.add(HttpSessionListener.class); - types.add(ServletContextListener.class); - SUPPORTED_TYPES = Collections.unmodifiableSet(types); - } - - private T listener; - - /** - * Create a new {@link ServletListenerRegistrationBean} instance. - */ public ServletListenerRegistrationBean() { + super(); } - /** - * Create a new {@link ServletListenerRegistrationBean} instance. - * @param listener the listener to register - */ public ServletListenerRegistrationBean(T listener) { - Assert.notNull(listener, "Listener must not be null"); - Assert.isTrue(isSupportedType(listener), "Listener is not of a supported type"); - this.listener = listener; - } - - /** - * Set the listener that will be registered. - * @param listener the listener to register - */ - public void setListener(T listener) { - Assert.notNull(listener, "Listener must not be null"); - Assert.isTrue(isSupportedType(listener), "Listener is not of a supported type"); - this.listener = listener; - } - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - if (!isEnabled()) { - logger.info("Listener " + this.listener + " was not registered (disabled)"); - return; - } - try { - servletContext.addListener(this.listener); - } - catch (RuntimeException ex) { - throw new IllegalStateException( - "Failed to add listener '" + this.listener + "' to servlet context", - ex); - } - } - - public T getListener() { - return this.listener; - } - - /** - * Returns {@code true} if the specified listener is one of the supported types. - * @param listener the listener to test - * @return if the listener is of a supported type - */ - public static boolean isSupportedType(EventListener listener) { - for (Class type : SUPPORTED_TYPES) { - if (ClassUtils.isAssignableValue(type, listener)) { - return true; - } - } - return false; - } - - /** - * Return the supported types for this registration. - * @return the supported types - */ - public static Set> getSupportedTypes() { - return SUPPORTED_TYPES; + super(listener); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletRegistrationBean.java index fcd5ce1a80..05912dc4ad 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletRegistrationBean.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletRegistrationBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,23 +16,10 @@ package org.springframework.boot.context.embedded; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Set; - -import javax.servlet.MultipartConfigElement; import javax.servlet.Servlet; import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; -import javax.servlet.ServletRegistration.Dynamic; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; +import org.springframework.boot.web.servlet.ServletContextInitializer; /** * A {@link ServletContextInitializer} to register {@link Servlet}s in a Servlet 3.0+ @@ -49,172 +36,24 @@ import org.springframework.util.ObjectUtils; * @author Phillip Webb * @see ServletContextInitializer * @see ServletContext#addServlet(String, Servlet) + * @deprecated as of 1.4 in favor of org.springframework.boot.web.ServletRegistrationBean */ -public class ServletRegistrationBean extends RegistrationBean { +@Deprecated +public class ServletRegistrationBean + extends org.springframework.boot.web.servlet.ServletRegistrationBean + implements org.springframework.boot.context.embedded.ServletContextInitializer { - private static final Log logger = LogFactory.getLog(ServletRegistrationBean.class); - - private static final String[] DEFAULT_MAPPINGS = { "/*" }; - - private Servlet servlet; - - private Set urlMappings = new LinkedHashSet(); - - private boolean alwaysMapUrl = true; - - private int loadOnStartup = -1; - - private MultipartConfigElement multipartConfig; - - /** - * Create a new {@link ServletRegistrationBean} instance. - */ public ServletRegistrationBean() { + super(); } - /** - * Create a new {@link ServletRegistrationBean} instance with the specified - * {@link Servlet} and URL mappings. - * @param servlet the servlet being mapped - * @param urlMappings the URLs being mapped - */ - public ServletRegistrationBean(Servlet servlet, String... urlMappings) { - this(servlet, true, urlMappings); - } - - /** - * Create a new {@link ServletRegistrationBean} instance with the specified - * {@link Servlet} and URL mappings. - * @param servlet the servlet being mapped - * @param alwaysMapUrl if omitted URL mappings should be replaced with '/*' - * @param urlMappings the URLs being mapped - */ public ServletRegistrationBean(Servlet servlet, boolean alwaysMapUrl, String... urlMappings) { - Assert.notNull(servlet, "Servlet must not be null"); - Assert.notNull(urlMappings, "UrlMappings must not be null"); - this.servlet = servlet; - this.alwaysMapUrl = alwaysMapUrl; - this.urlMappings.addAll(Arrays.asList(urlMappings)); + super(servlet, alwaysMapUrl, urlMappings); } - /** - * Returns the servlet being registered. - * @return the servlet - */ - protected Servlet getServlet() { - return this.servlet; - } - - /** - * Sets the servlet to be registered. - * @param servlet the servlet - */ - public void setServlet(Servlet servlet) { - Assert.notNull(servlet, "Servlet must not be null"); - this.servlet = servlet; - } - - /** - * Set the URL mappings for the servlet. If not specified the mapping will default to - * '/'. This will replace any previously specified mappings. - * @param urlMappings the mappings to set - * @see #addUrlMappings(String...) - */ - public void setUrlMappings(Collection urlMappings) { - Assert.notNull(urlMappings, "UrlMappings must not be null"); - this.urlMappings = new LinkedHashSet(urlMappings); - } - - /** - * Return a mutable collection of the URL mappings for the servlet. - * @return the urlMappings - */ - public Collection getUrlMappings() { - return this.urlMappings; - } - - /** - * Add URL mappings for the servlet. - * @param urlMappings the mappings to add - * @see #setUrlMappings(Collection) - */ - public void addUrlMappings(String... urlMappings) { - Assert.notNull(urlMappings, "UrlMappings must not be null"); - this.urlMappings.addAll(Arrays.asList(urlMappings)); - } - - /** - * Sets the {@code loadOnStartup} priority. See - * {@link ServletRegistration.Dynamic#setLoadOnStartup} for details. - * @param loadOnStartup if load on startup is enabled - */ - public void setLoadOnStartup(int loadOnStartup) { - this.loadOnStartup = loadOnStartup; - } - - /** - * Set the {@link MultipartConfigElement multi-part configuration}. - * @param multipartConfig the multi-part configuration to set or {@code null} - */ - public void setMultipartConfig(MultipartConfigElement multipartConfig) { - this.multipartConfig = multipartConfig; - } - - /** - * Returns the {@link MultipartConfigElement multi-part configuration} to be applied - * or {@code null}. - * @return the multipart config - */ - public MultipartConfigElement getMultipartConfig() { - return this.multipartConfig; - } - - /** - * Returns the servlet name that will be registered. - * @return the servlet name - */ - public String getServletName() { - return getOrDeduceName(this.servlet); - } - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - Assert.notNull(this.servlet, "Servlet must not be null"); - String name = getServletName(); - if (!isEnabled()) { - logger.info("Servlet " + name + " was not registered (disabled)"); - return; - } - logger.info("Mapping servlet: '" + name + "' to " + this.urlMappings); - Dynamic added = servletContext.addServlet(name, this.servlet); - if (added == null) { - logger.info("Servlet " + name + " was not registered " - + "(possibly already registered?)"); - return; - } - configure(added); - } - - /** - * Configure registration settings. Subclasses can override this method to perform - * additional configuration if required. - * @param registration the registration - */ - protected void configure(ServletRegistration.Dynamic registration) { - super.configure(registration); - String[] urlMapping = this.urlMappings - .toArray(new String[this.urlMappings.size()]); - if (urlMapping.length == 0 && this.alwaysMapUrl) { - urlMapping = DEFAULT_MAPPINGS; - } - if (!ObjectUtils.isEmpty(urlMapping)) { - registration.addMapping(urlMapping); - } - registration.setLoadOnStartup(this.loadOnStartup); - if (this.multipartConfig != null) { - registration.setMultipartConfig(this.multipartConfig); - } + public ServletRegistrationBean(Servlet servlet, String... urlMappings) { + super(servlet, urlMappings); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java index 3111359f98..1467107439 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java @@ -66,11 +66,11 @@ import org.springframework.boot.context.embedded.Compression; import org.springframework.boot.context.embedded.EmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerException; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; -import org.springframework.boot.context.embedded.ErrorPage; import org.springframework.boot.context.embedded.MimeMappings; -import org.springframework.boot.context.embedded.ServletContextInitializer; import org.springframework.boot.context.embedded.Ssl; import org.springframework.boot.context.embedded.Ssl.ClientAuth; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/ServletContextInitializerConfiguration.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/ServletContextInitializerConfiguration.java index f418835a35..53694f8824 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/ServletContextInitializerConfiguration.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/ServletContextInitializerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.WebAppContext; -import org.springframework.boot.context.embedded.ServletContextInitializer; +import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.util.Assert; /** diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/package-info.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/package-info.java index db16b077aa..541c5801ae 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/package-info.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,8 @@ */ /** - * Support for embedded servlet containers. + * Specialized {@link org.springframework.context.ApplicationContext} that supports + * embedded servlet containers. * * @see org.springframework.boot.context.embedded.EmbeddedServletContainerFactory * @see org.springframework.boot.context.embedded.EmbeddedWebApplicationContext diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index 44a9410043..e31a6a13c8 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -59,12 +59,12 @@ import org.springframework.boot.context.embedded.Compression; import org.springframework.boot.context.embedded.EmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerException; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; -import org.springframework.boot.context.embedded.ErrorPage; import org.springframework.boot.context.embedded.MimeMappings; -import org.springframework.boot.context.embedded.ServletContextInitializer; import org.springframework.boot.context.embedded.Ssl; import org.springframework.boot.context.embedded.Ssl.ClientAuth; import org.springframework.boot.context.embedded.SslStoreProvider; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatStarter.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatStarter.java index 8217c59c48..7a6b5fba21 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatStarter.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatStarter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import javax.servlet.ServletException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.boot.context.embedded.ServletContextInitializer; +import org.springframework.boot.web.servlet.ServletContextInitializer; /** * {@link ServletContainerInitializer} used to trigger {@link ServletContextInitializer diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java index bf3376c2de..c21f876e88 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactory.java @@ -70,11 +70,11 @@ import org.xnio.XnioWorker; import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.EmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; -import org.springframework.boot.context.embedded.ErrorPage; import org.springframework.boot.context.embedded.MimeMappings.Mapping; -import org.springframework.boot.context.embedded.ServletContextInitializer; import org.springframework.boot.context.embedded.Ssl; import org.springframework.boot.context.embedded.Ssl.ClientAuth; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/ErrorPageFilter.java b/spring-boot/src/main/java/org/springframework/boot/context/web/ErrorPageFilter.java index 11f67ea281..f0309a364d 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/ErrorPageFilter.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/ErrorPageFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,31 +16,11 @@ package org.springframework.boot.context.web; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; -import org.springframework.boot.context.embedded.ErrorPage; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.util.NestedServletException; /** * A special {@link AbstractConfigurableEmbeddedServletContainer} for non-embedded @@ -55,280 +35,13 @@ import org.springframework.web.util.NestedServletException; * @author Dave Syer * @author Phillip Webb * @author Andy Wilkinson + * @since 1.4.0 + * @deprecated as of 1.4 in favor of org.springframework.boot.web.support.ErrorPageFilter */ @Component @Order(Ordered.HIGHEST_PRECEDENCE) -public class ErrorPageFilter extends AbstractConfigurableEmbeddedServletContainer - implements Filter, NonEmbeddedServletContainerFactory { - - private static final Log logger = LogFactory.getLog(ErrorPageFilter.class); - - // From RequestDispatcher but not referenced to remain compatible with Servlet 2.5 - - private static final String ERROR_EXCEPTION = "javax.servlet.error.exception"; - - private static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type"; - - private static final String ERROR_MESSAGE = "javax.servlet.error.message"; - - /** - * The name of the servlet attribute containing request URI. - */ - public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri"; - - private static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code"; - - private String global; - - private final Map statuses = new HashMap(); - - private final Map, String> exceptions = new HashMap, String>(); - - private final Map, Class> subtypes = new HashMap, Class>(); - - private final OncePerRequestFilter delegate = new OncePerRequestFilter() { - - @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, FilterChain chain) - throws ServletException, IOException { - ErrorPageFilter.this.doFilter(request, response, chain); - } - - @Override - protected boolean shouldNotFilterAsyncDispatch() { - return false; - } - - }; - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - this.delegate.init(filterConfig); - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain chain) throws IOException, ServletException { - this.delegate.doFilter(request, response, chain); - } - - private void doFilter(HttpServletRequest request, HttpServletResponse response, - FilterChain chain) throws IOException, ServletException { - ErrorWrapperResponse wrapped = new ErrorWrapperResponse(response); - try { - chain.doFilter(request, wrapped); - if (wrapped.hasErrorToSend()) { - handleErrorStatus(request, response, wrapped.getStatus(), - wrapped.getMessage()); - response.flushBuffer(); - } - else if (!request.isAsyncStarted() && !response.isCommitted()) { - response.flushBuffer(); - } - } - catch (Throwable ex) { - Throwable exceptionToHandle = ex; - if (ex instanceof NestedServletException) { - exceptionToHandle = ((NestedServletException) ex).getRootCause(); - } - handleException(request, response, wrapped, exceptionToHandle); - response.flushBuffer(); - } - } - - private void handleErrorStatus(HttpServletRequest request, - HttpServletResponse response, int status, String message) - throws ServletException, IOException { - if (response.isCommitted()) { - handleCommittedResponse(request, null); - return; - } - String errorPath = getErrorPath(this.statuses, status); - if (errorPath == null) { - response.sendError(status, message); - return; - } - response.setStatus(status); - setErrorAttributes(request, status, message); - request.getRequestDispatcher(errorPath).forward(request, response); - } - - private void handleException(HttpServletRequest request, HttpServletResponse response, - ErrorWrapperResponse wrapped, Throwable ex) - throws IOException, ServletException { - Class type = ex.getClass(); - String errorPath = getErrorPath(type); - if (errorPath == null) { - rethrow(ex); - return; - } - if (response.isCommitted()) { - handleCommittedResponse(request, ex); - return; - } - - forwardToErrorPage(errorPath, request, wrapped, ex); - } - - private void forwardToErrorPage(String path, HttpServletRequest request, - HttpServletResponse response, Throwable ex) - throws ServletException, IOException { - if (logger.isErrorEnabled()) { - String message = "Forwarding to error page from request " - + getDescription(request) + " due to exception [" + ex.getMessage() - + "]"; - logger.error(message, ex); - } - setErrorAttributes(request, 500, ex.getMessage()); - request.setAttribute(ERROR_EXCEPTION, ex); - request.setAttribute(ERROR_EXCEPTION_TYPE, ex.getClass().getName()); - response.reset(); - response.sendError(500, ex.getMessage()); - request.getRequestDispatcher(path).forward(request, response); - } - - private String getDescription(HttpServletRequest request) { - return "[" + request.getServletPath() - + (request.getPathInfo() == null ? "" : request.getPathInfo()) + "]"; - } - - private void handleCommittedResponse(HttpServletRequest request, Throwable ex) { - String message = "Cannot forward to error page for request " - + getDescription(request) + " as the response has already been" - + " committed. As a result, the response may have the wrong status" - + " code. If your application is running on WebSphere Application" - + " Server you may be able to resolve this problem by setting" - + " com.ibm.ws.webcontainer.invokeFlushAfterService to false"; - if (ex == null) { - logger.error(message); - } - else { - // User might see the error page without all the data here but throwing the - // exception isn't going to help anyone (we'll log it to be on the safe side) - logger.error(message, ex); - } - } - - private String getErrorPath(Map map, Integer status) { - if (map.containsKey(status)) { - return map.get(status); - } - return this.global; - } - - private String getErrorPath(Class type) { - if (this.exceptions.containsKey(type)) { - return this.exceptions.get(type); - } - if (this.subtypes.containsKey(type)) { - return this.exceptions.get(this.subtypes.get(type)); - } - Class subtype = type; - while (subtype != Object.class) { - subtype = subtype.getSuperclass(); - if (this.exceptions.containsKey(subtype)) { - this.subtypes.put(subtype, type); - return this.exceptions.get(subtype); - } - } - return this.global; - } - - private void setErrorAttributes(HttpServletRequest request, int status, - String message) { - request.setAttribute(ERROR_STATUS_CODE, status); - request.setAttribute(ERROR_MESSAGE, message); - request.setAttribute(ERROR_REQUEST_URI, request.getRequestURI()); - } - - private void rethrow(Throwable ex) throws IOException, ServletException { - if (ex instanceof RuntimeException) { - throw (RuntimeException) ex; - } - if (ex instanceof Error) { - throw (Error) ex; - } - if (ex instanceof IOException) { - throw (IOException) ex; - } - if (ex instanceof ServletException) { - throw (ServletException) ex; - } - throw new IllegalStateException(ex); - } - - @Override - public void addErrorPages(ErrorPage... errorPages) { - for (ErrorPage errorPage : errorPages) { - if (errorPage.isGlobal()) { - this.global = errorPage.getPath(); - } - else if (errorPage.getStatus() != null) { - this.statuses.put(errorPage.getStatus().value(), errorPage.getPath()); - } - else { - this.exceptions.put(errorPage.getException(), errorPage.getPath()); - } - } - } - - @Override - public void destroy() { - } - - private static class ErrorWrapperResponse extends HttpServletResponseWrapper { - - private int status; - - private String message; - - private boolean hasErrorToSend = false; - - ErrorWrapperResponse(HttpServletResponse response) { - super(response); - } - - @Override - public void sendError(int status) throws IOException { - sendError(status, null); - } - - @Override - public void sendError(int status, String message) throws IOException { - this.status = status; - this.message = message; - this.hasErrorToSend = true; - // Do not call super because the container may prevent us from handling the - // error ourselves - } - - @Override - public int getStatus() { - if (this.hasErrorToSend) { - return this.status; - } - // If there was no error we need to trust the wrapped response - return super.getStatus(); - } - - @Override - public void flushBuffer() throws IOException { - if (this.hasErrorToSend && !isCommitted()) { - ((HttpServletResponse) getResponse()).sendError(this.status, - this.message); - } - super.flushBuffer(); - } - - public String getMessage() { - return this.message; - } - - public boolean hasErrorToSend() { - return this.hasErrorToSend; - } - - } +@Deprecated +public class ErrorPageFilter + extends org.springframework.boot.web.support.ErrorPageFilter { } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedCharacterEncodingFilter.java b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedCharacterEncodingFilter.java index a220e8846e..b93963bf8f 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedCharacterEncodingFilter.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedCharacterEncodingFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,23 +24,11 @@ import org.springframework.web.filter.CharacterEncodingFilter; * * @author Phillip Webb * @since 1.2.1 + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.filter.OrderedCharacterEncodingFilter */ -public class OrderedCharacterEncodingFilter extends CharacterEncodingFilter - implements Ordered { - - private int order = Ordered.HIGHEST_PRECEDENCE; - - @Override - public int getOrder() { - return this.order; - } - - /** - * Set the order for this filter. - * @param order the order to set - */ - public void setOrder(int order) { - this.order = order; - } +@Deprecated +public class OrderedCharacterEncodingFilter + extends org.springframework.boot.web.filter.OrderedCharacterEncodingFilter { } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedHiddenHttpMethodFilter.java b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedHiddenHttpMethodFilter.java index 782a660fb1..eec70d5b1b 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedHiddenHttpMethodFilter.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedHiddenHttpMethodFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package org.springframework.boot.context.web; -import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.core.Ordered; import org.springframework.web.filter.HiddenHttpMethodFilter; @@ -25,29 +24,16 @@ import org.springframework.web.filter.HiddenHttpMethodFilter; * * @author Phillip Webb * @since 1.2.4 + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter */ -public class OrderedHiddenHttpMethodFilter extends HiddenHttpMethodFilter - implements Ordered { +@Deprecated +public class OrderedHiddenHttpMethodFilter + extends org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter { /** * The default order is high to ensure the filter is applied before Spring Security. */ - public static final int DEFAULT_ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - - 10000; - - private int order = DEFAULT_ORDER; - - @Override - public int getOrder() { - return this.order; - } - - /** - * Set the order for this filter. - * @param order the order to set - */ - public void setOrder(int order) { - this.order = order; - } + public static final int DEFAULT_ORDER = org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter.DEFAULT_ORDER; } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedHttpPutFormContentFilter.java b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedHttpPutFormContentFilter.java index e8f594d892..af3aa87c61 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedHttpPutFormContentFilter.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedHttpPutFormContentFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package org.springframework.boot.context.web; -import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.core.Ordered; import org.springframework.web.filter.HttpPutFormContentFilter; @@ -25,29 +24,16 @@ import org.springframework.web.filter.HttpPutFormContentFilter; * * @author Joao Pedro Evangelista * @since 1.3.0 + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.filter.OrderedHttpPutFormContentFilter */ -public class OrderedHttpPutFormContentFilter extends HttpPutFormContentFilter - implements Ordered { +@Deprecated +public class OrderedHttpPutFormContentFilter + extends org.springframework.boot.web.filter.OrderedHttpPutFormContentFilter { /** * Higher order to ensure the filter is applied before Spring Security. */ - public static final int DEFAULT_ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - - 9900; - - private int order = DEFAULT_ORDER; - - @Override - public int getOrder() { - return this.order; - } - - /** - * Set the order for this filter. - * @param order the order to set - */ - public void setOrder(int order) { - this.order = order; - } + public static final int DEFAULT_ORDER = org.springframework.boot.web.filter.OrderedHttpPutFormContentFilter.DEFAULT_ORDER; } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedRequestContextFilter.java b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedRequestContextFilter.java index 40ed97e14b..8d33a3d1e4 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedRequestContextFilter.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/OrderedRequestContextFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package org.springframework.boot.context.web; -import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.core.Ordered; import org.springframework.web.filter.RequestContextFilter; @@ -25,23 +24,11 @@ import org.springframework.web.filter.RequestContextFilter; * * @author Phillip Webb * @since 1.3.0 + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.filter.OrderedRequestContextFilter */ -public class OrderedRequestContextFilter extends RequestContextFilter implements Ordered { - - // Order defaults to after Spring Session filter - private int order = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 105; - - @Override - public int getOrder() { - return this.order; - } - - /** - * Set the order for this filter. - * @param order the order to set - */ - public void setOrder(int order) { - this.order = order; - } +@Deprecated +public class OrderedRequestContextFilter + extends org.springframework.boot.web.filter.OrderedRequestContextFilter { } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/ServerPortInfoApplicationContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/web/ServerPortInfoApplicationContextInitializer.java index cfbb7c4665..69ab23e811 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/ServerPortInfoApplicationContextInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/ServerPortInfoApplicationContextInitializer.java @@ -16,23 +16,11 @@ package org.springframework.boot.context.web; -import java.util.HashMap; -import java.util.Map; - import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.embedded.EmbeddedServletContainer; -import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; -import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ApplicationListener; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertySource; -import org.springframework.util.StringUtils; /** * {@link ApplicationContextInitializer} that sets {@link Environment} properties for the @@ -50,60 +38,11 @@ import org.springframework.util.StringUtils; * @author Dave Syer * @author Phillip Webb * @since 1.3.0 + * @deprecated as of 1.4 in favor of + * org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer */ -public class ServerPortInfoApplicationContextInitializer - implements ApplicationContextInitializer { - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - applicationContext.addApplicationListener( - new ApplicationListener() { - - @Override - public void onApplicationEvent( - EmbeddedServletContainerInitializedEvent event) { - ServerPortInfoApplicationContextInitializer.this - .onApplicationEvent(event); - } - - }); - } - - protected void onApplicationEvent(EmbeddedServletContainerInitializedEvent event) { - String propertyName = getPropertyName(event.getApplicationContext()); - setPortProperty(event.getApplicationContext(), propertyName, - event.getEmbeddedServletContainer().getPort()); - } - - protected String getPropertyName(EmbeddedWebApplicationContext context) { - String name = context.getNamespace(); - if (StringUtils.isEmpty(name)) { - name = "server"; - } - return "local." + name + ".port"; - } - - private void setPortProperty(ApplicationContext context, String propertyName, - int port) { - if (context instanceof ConfigurableApplicationContext) { - setPortProperty(((ConfigurableApplicationContext) context).getEnvironment(), - propertyName, port); - } - if (context.getParent() != null) { - setPortProperty(context.getParent(), propertyName, port); - } - } - - @SuppressWarnings("unchecked") - private void setPortProperty(ConfigurableEnvironment environment, String propertyName, - int port) { - MutablePropertySources sources = environment.getPropertySources(); - PropertySource source = sources.get("server.ports"); - if (source == null) { - source = new MapPropertySource("server.ports", new HashMap()); - sources.addFirst(source); - } - ((Map) source.getSource()).put(propertyName, port); - } +@Deprecated +public class ServerPortInfoApplicationContextInitializer extends + org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer { } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/ServletContextApplicationContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/web/ServletContextApplicationContextInitializer.java index 57f1810ca0..f3876d9032 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/ServletContextApplicationContextInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/ServletContextApplicationContextInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,66 +18,27 @@ package org.springframework.boot.context.web; import javax.servlet.ServletContext; -import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; -import org.springframework.core.Ordered; -import org.springframework.web.context.ConfigurableWebApplicationContext; -import org.springframework.web.context.WebApplicationContext; /** * {@link ApplicationContextInitializer} for setting the servlet context. * * @author Dave Syer * @author Phillip Webb + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.support.ServletContextApplicationContextInitializer */ -public class ServletContextApplicationContextInitializer implements - ApplicationContextInitializer, Ordered { +@Deprecated +public class ServletContextApplicationContextInitializer extends + org.springframework.boot.web.support.ServletContextApplicationContextInitializer { - private int order = Ordered.HIGHEST_PRECEDENCE; - - private final ServletContext servletContext; - - private final boolean addApplicationContextAttribute; - - /** - * Create a new {@link ServletContextApplicationContextInitializer} instance. - * @param servletContext the servlet that should be ultimately set. - */ - public ServletContextApplicationContextInitializer(ServletContext servletContext) { - this(servletContext, false); - } - - /** - * Create a new {@link ServletContextApplicationContextInitializer} instance. - * @param servletContext the servlet that should be ultimately set. - * @param addApplicationContextAttribute if the {@link ApplicationContext} should be - * stored as an attribute in the {@link ServletContext} - * @since 1.3.4 - */ public ServletContextApplicationContextInitializer(ServletContext servletContext, boolean addApplicationContextAttribute) { - this.servletContext = servletContext; - this.addApplicationContextAttribute = addApplicationContextAttribute; + super(servletContext, addApplicationContextAttribute); } - public void setOrder(int order) { - this.order = order; - } - - @Override - public int getOrder() { - return this.order; - } - - @Override - public void initialize(ConfigurableWebApplicationContext applicationContext) { - applicationContext.setServletContext(this.servletContext); - if (this.addApplicationContextAttribute) { - this.servletContext.setAttribute( - WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, - applicationContext); - } - + public ServletContextApplicationContextInitializer(ServletContext servletContext) { + super(servletContext); } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/SpringBootServletInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/web/SpringBootServletInitializer.java index 39221005b1..a7b15b5296 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/SpringBootServletInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/SpringBootServletInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,25 +18,11 @@ package org.springframework.boot.context.web; import javax.servlet.Filter; import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.boot.SpringApplication; -import org.springframework.boot.builder.ParentContextApplicationContextInitializer; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; -import org.springframework.boot.context.embedded.ServletContextInitializer; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.util.Assert; +import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.web.WebApplicationInitializer; -import org.springframework.web.context.ContextLoaderListener; -import org.springframework.web.context.WebApplicationContext; /** * An opinionated {@link WebApplicationInitializer} to run a {@link SpringApplication} @@ -60,116 +46,11 @@ import org.springframework.web.context.WebApplicationContext; * @author Phillip Webb * @author Andy Wilkinson * @see #configure(SpringApplicationBuilder) + * @deprecated as of 1.4 in favor of + * org.springframework.boot.web.support.SpringBootServletInitializer */ -public abstract class SpringBootServletInitializer implements WebApplicationInitializer { - - protected Log logger; // Don't initialize early - - private boolean registerErrorPageFilter = true; - - /** - * Set if the {@link ErrorPageFilter} should be registered. Set to {@code false} if - * error page mappings should be handled via the Servlet container and not Spring - * Boot. - * @param registerErrorPageFilter if the {@link ErrorPageFilter} should be registered. - */ - protected final void setRegisterErrorPageFilter(boolean registerErrorPageFilter) { - this.registerErrorPageFilter = registerErrorPageFilter; - } - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - // Logger initialization is deferred in case a ordered - // LogServletContextInitializer is being used - this.logger = LogFactory.getLog(getClass()); - WebApplicationContext rootAppContext = createRootApplicationContext( - servletContext); - if (rootAppContext != null) { - servletContext.addListener(new ContextLoaderListener(rootAppContext) { - @Override - public void contextInitialized(ServletContextEvent event) { - // no-op because the application context is already initialized - } - }); - } - else { - this.logger.debug("No ContextLoaderListener registered, as " - + "createRootApplicationContext() did not " - + "return an application context"); - } - } - - protected WebApplicationContext createRootApplicationContext( - ServletContext servletContext) { - SpringApplicationBuilder builder = createSpringApplicationBuilder(); - builder.main(getClass()); - ApplicationContext parent = getExistingRootWebApplicationContext(servletContext); - if (parent != null) { - this.logger.info("Root context already created (using as parent)."); - servletContext.setAttribute( - WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null); - builder.initializers(new ParentContextApplicationContextInitializer(parent)); - } - builder.initializers( - new ServletContextApplicationContextInitializer(servletContext)); - builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class); - builder = configure(builder); - SpringApplication application = builder.build(); - if (application.getSources().isEmpty() && AnnotationUtils - .findAnnotation(getClass(), Configuration.class) != null) { - application.getSources().add(getClass()); - } - Assert.state(!application.getSources().isEmpty(), - "No SpringApplication sources have been defined. Either override the " - + "configure method or add an @Configuration annotation"); - // Ensure error pages are registered - if (this.registerErrorPageFilter) { - application.getSources().add(ErrorPageFilter.class); - } - return run(application); - } - - /** - * Returns the {@code SpringApplicationBuilder} that is used to configure and create - * the {@link SpringApplication}. The default implementation returns a new - * {@code SpringApplicationBuilder} in its default state. - * @return the {@code SpringApplicationBuilder}. - * @since 1.3.0 - */ - protected SpringApplicationBuilder createSpringApplicationBuilder() { - return new SpringApplicationBuilder(); - } - - /** - * Called to run a fully configured {@link SpringApplication}. - * @param application the application to run - * @return the {@link WebApplicationContext} - */ - protected WebApplicationContext run(SpringApplication application) { - return (WebApplicationContext) application.run(); - } - - private ApplicationContext getExistingRootWebApplicationContext( - ServletContext servletContext) { - Object context = servletContext.getAttribute( - WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); - if (context instanceof ApplicationContext) { - return (ApplicationContext) context; - } - return null; - } - - /** - * Configure the application. Normally all you would need to do it add sources (e.g. - * config classes) because other settings have sensible defaults. You might choose - * (for instance) to add default command line arguments, or set an active Spring - * profile. - * @param builder a builder for the application context - * @return the application builder - * @see SpringApplicationBuilder - */ - protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { - return builder; - } +@Deprecated +public abstract class SpringBootServletInitializer + extends org.springframework.boot.web.support.SpringBootServletInitializer { } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/ApplicationContextHeaderFilter.java b/spring-boot/src/main/java/org/springframework/boot/web/filter/ApplicationContextHeaderFilter.java similarity index 97% rename from spring-boot/src/main/java/org/springframework/boot/context/web/ApplicationContextHeaderFilter.java rename to spring-boot/src/main/java/org/springframework/boot/web/filter/ApplicationContextHeaderFilter.java index e8ed412643..56b06180b4 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/ApplicationContextHeaderFilter.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/filter/ApplicationContextHeaderFilter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.web; +package org.springframework.boot.web.filter; import java.io.IOException; diff --git a/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedCharacterEncodingFilter.java b/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedCharacterEncodingFilter.java new file mode 100644 index 0000000000..3597d9efe2 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedCharacterEncodingFilter.java @@ -0,0 +1,46 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.filter; + +import org.springframework.core.Ordered; +import org.springframework.web.filter.CharacterEncodingFilter; + +/** + * {@link CharacterEncodingFilter} that also implements {@link Ordered}. + * + * @author Phillip Webb + * @since 1.4.0 + */ +public class OrderedCharacterEncodingFilter extends CharacterEncodingFilter + implements Ordered { + + private int order = Ordered.HIGHEST_PRECEDENCE; + + @Override + public int getOrder() { + return this.order; + } + + /** + * Set the order for this filter. + * @param order the order to set + */ + public void setOrder(int order) { + this.order = order; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedHiddenHttpMethodFilter.java b/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedHiddenHttpMethodFilter.java new file mode 100644 index 0000000000..2089654fac --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedHiddenHttpMethodFilter.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.filter; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.core.Ordered; +import org.springframework.web.filter.HiddenHttpMethodFilter; + +/** + * {@link HiddenHttpMethodFilter} that also implements {@link Ordered}. + * + * @author Phillip Webb + * @since 1.4.0 + */ +public class OrderedHiddenHttpMethodFilter extends HiddenHttpMethodFilter + implements Ordered { + + /** + * The default order is high to ensure the filter is applied before Spring Security. + */ + public static final int DEFAULT_ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER + - 10000; + + private int order = DEFAULT_ORDER; + + @Override + public int getOrder() { + return this.order; + } + + /** + * Set the order for this filter. + * @param order the order to set + */ + public void setOrder(int order) { + this.order = order; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedHttpPutFormContentFilter.java b/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedHttpPutFormContentFilter.java new file mode 100644 index 0000000000..bb2bf3ab3d --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedHttpPutFormContentFilter.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.filter; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.core.Ordered; +import org.springframework.web.filter.HttpPutFormContentFilter; + +/** + * {@link HttpPutFormContentFilter} that also implements {@link Ordered}. + * + * @author Joao Pedro Evangelista + * @since 1.4.0 + */ +public class OrderedHttpPutFormContentFilter extends HttpPutFormContentFilter + implements Ordered { + + /** + * Higher order to ensure the filter is applied before Spring Security. + */ + public static final int DEFAULT_ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER + - 9900; + + private int order = DEFAULT_ORDER; + + @Override + public int getOrder() { + return this.order; + } + + /** + * Set the order for this filter. + * @param order the order to set + */ + public void setOrder(int order) { + this.order = order; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedRequestContextFilter.java b/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedRequestContextFilter.java new file mode 100644 index 0000000000..ae853a0817 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/filter/OrderedRequestContextFilter.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.filter; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.core.Ordered; +import org.springframework.web.filter.RequestContextFilter; + +/** + * {@link RequestContextFilter} that also implements {@link Ordered}. + * + * @author Phillip Webb + * @since 1.4.0 + */ +public class OrderedRequestContextFilter extends RequestContextFilter implements Ordered { + + // Order defaults to after Spring Session filter + private int order = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 105; + + @Override + public int getOrder() { + return this.order; + } + + /** + * Set the order for this filter. + * @param order the order to set + */ + public void setOrder(int order) { + this.order = order; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/filter/package-info.java b/spring-boot/src/main/java/org/springframework/boot/web/filter/package-info.java new file mode 100644 index 0000000000..ed8d21092c --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/filter/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Spring Boot specific {@link javax.servlet.Filter} implementations. + */ +package org.springframework.boot.web.filter; diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBean.java similarity index 97% rename from spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBean.java rename to spring-boot/src/main/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBean.java index 79d87c8a82..563e2468b9 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBean.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBean.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import java.util.Arrays; import java.util.Collection; @@ -49,11 +49,11 @@ abstract class AbstractFilterRegistrationBean extends RegistrationBean { private final Log logger = LogFactory.getLog(getClass()); - static final EnumSet ASYNC_DISPATCHER_TYPES = EnumSet.of( + private static final EnumSet ASYNC_DISPATCHER_TYPES = EnumSet.of( DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST, DispatcherType.ASYNC); - static final EnumSet NON_ASYNC_DISPATCHER_TYPES = EnumSet + private static final EnumSet NON_ASYNC_DISPATCHER_TYPES = EnumSet .of(DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST); private static final String[] DEFAULT_URL_MAPPINGS = { "/*" }; diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java new file mode 100644 index 0000000000..9da12a0d68 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java @@ -0,0 +1,96 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.servlet; + +import javax.servlet.Filter; +import javax.servlet.ServletContext; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.util.Assert; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.filter.DelegatingFilterProxy; + +/** + * A {@link ServletContextInitializer} to register {@link DelegatingFilterProxy}s in a + * Servlet 3.0+ container. Similar to the {@link ServletContext#addFilter(String, Filter) + * registration} features provided by {@link ServletContext} but with a Spring Bean + * friendly design. + *

+ * The bean name of the actual delegate {@link Filter} should be specified using the + * {@code targetBeanName} constructor argument. Unlike the {@link FilterRegistrationBean}, + * referenced filters are not instantiated early. In fact, if the delegate filter bean is + * marked {@code @Lazy} it won't be instantiated at all until the filter is called. + *

+ * Registrations can be associated with {@link #setUrlPatterns URL patterns} and/or + * servlets (either by {@link #setServletNames name} or via a + * {@link #setServletRegistrationBeans ServletRegistrationBean}s. When no URL pattern or + * servlets are specified the filter will be associated to '/*'. The targetBeanName will + * be used as the filter name if not otherwise specified. + * + * @author Phillip Webb + * @since 1.4.0 + * @see ServletContextInitializer + * @see ServletContext#addFilter(String, Filter) + * @see FilterRegistrationBean + * @see DelegatingFilterProxy + */ +public class DelegatingFilterProxyRegistrationBean extends AbstractFilterRegistrationBean + implements ApplicationContextAware { + + private ApplicationContext applicationContext; + + private final String targetBeanName; + + /** + * Create a new {@link DelegatingFilterProxyRegistrationBean} instance to be + * registered with the specified {@link ServletRegistrationBean}s. + * @param targetBeanName name of the target filter bean to look up in the Spring + * application context (must not be {@code null}). + * @param servletRegistrationBeans associate {@link ServletRegistrationBean}s + */ + public DelegatingFilterProxyRegistrationBean(String targetBeanName, + ServletRegistrationBean... servletRegistrationBeans) { + super(servletRegistrationBeans); + Assert.hasLength(targetBeanName, "TargetBeanName must not be null or empty"); + this.targetBeanName = targetBeanName; + setName(targetBeanName); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + + protected String getTargetBeanName() { + return this.targetBeanName; + } + + @Override + public Filter getFilter() { + return new DelegatingFilterProxy(this.targetBeanName, getWebApplicationContext()); + } + + private WebApplicationContext getWebApplicationContext() { + Assert.notNull(this.applicationContext, "ApplicationContext be injected"); + Assert.isInstanceOf(WebApplicationContext.class, this.applicationContext); + return (WebApplicationContext) this.applicationContext; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/ErrorPage.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ErrorPage.java new file mode 100644 index 0000000000..b9c15047de --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ErrorPage.java @@ -0,0 +1,137 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.servlet; + +import org.springframework.http.HttpStatus; +import org.springframework.util.ObjectUtils; + +/** + * Simple container-independent abstraction for servlet error pages. Roughly equivalent to + * the {@literal <error-page>} element traditionally found in web.xml. + * + * @author Dave Syer + * @since 1.4.0 + */ +public class ErrorPage { + + private final HttpStatus status; + + private final Class exception; + + private final String path; + + public ErrorPage(String path) { + this.status = null; + this.exception = null; + this.path = path; + } + + public ErrorPage(HttpStatus status, String path) { + this.status = status; + this.exception = null; + this.path = path; + } + + public ErrorPage(Class exception, String path) { + this.status = null; + this.exception = exception; + this.path = path; + } + + /** + * The path to render (usually implemented as a forward), starting with "/". A custom + * controller or servlet path can be used, or if the container supports it, a template + * path (e.g. "/error.jsp"). + * @return the path that will be rendered for this error + */ + public String getPath() { + return this.path; + } + + /** + * Returns the exception type (or {@code null} for a page that matches by status). + * @return the exception type or {@code null} + */ + public Class getException() { + return this.exception; + } + + /** + * The HTTP status value that this error page matches (or {@code null} for a page that + * matches by exception). + * @return the status or {@code null} + */ + public HttpStatus getStatus() { + return this.status; + } + + /** + * The HTTP status value that this error page matches. + * @return the status value (or 0 for a page that matches any status) + */ + public int getStatusCode() { + return (this.status == null ? 0 : this.status.value()); + } + + /** + * The exception type name. + * @return the exception type name (or {@code null} if there is none) + */ + public String getExceptionName() { + return (this.exception == null ? null : this.exception.getName()); + } + + /** + * Return if this error page is a global one (matches all unmatched status and + * exception types). + * @return if this is a global error page + */ + public boolean isGlobal() { + return (this.status == null && this.exception == null); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ObjectUtils.nullSafeHashCode(getExceptionName()); + result = prime * result + ObjectUtils.nullSafeHashCode(this.path); + result = prime * result + this.getStatusCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (obj instanceof ErrorPage) { + ErrorPage other = (ErrorPage) obj; + boolean rtn = true; + rtn &= ObjectUtils.nullSafeEquals(getExceptionName(), + other.getExceptionName()); + rtn &= ObjectUtils.nullSafeEquals(this.path, other.path); + rtn &= this.status == other.status; + return rtn; + } + return false; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/FilterRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/FilterRegistrationBean.java new file mode 100644 index 0000000000..392ef8e21e --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/FilterRegistrationBean.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.servlet; + +import javax.servlet.Filter; +import javax.servlet.ServletContext; + +import org.springframework.util.Assert; + +/** + * A {@link ServletContextInitializer} to register {@link Filter}s in a Servlet 3.0+ + * container. Similar to the {@link ServletContext#addFilter(String, Filter) registration} + * features provided by {@link ServletContext} but with a Spring Bean friendly design. + *

+ * The {@link #setFilter(Filter) Filter} must be specified before calling + * {@link #onStartup(ServletContext)}. Registrations can be associated with + * {@link #setUrlPatterns URL patterns} and/or servlets (either by {@link #setServletNames + * name} or via a {@link #setServletRegistrationBeans ServletRegistrationBean}s. When no + * URL pattern or servlets are specified the filter will be associated to '/*'. The filter + * name will be deduced if not specified. + * + * @author Phillip Webb + * @since 1.4.0 + * @see ServletContextInitializer + * @see ServletContext#addFilter(String, Filter) + * @see DelegatingFilterProxyRegistrationBean + */ +public class FilterRegistrationBean extends AbstractFilterRegistrationBean { + + /** + * Filters that wrap the servlet request should be ordered less than or equal to this. + */ + public static final int REQUEST_WRAPPER_FILTER_MAX_ORDER = AbstractFilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER; + + private Filter filter; + + /** + * Create a new {@link FilterRegistrationBean} instance. + */ + public FilterRegistrationBean() { + } + + /** + * Create a new {@link FilterRegistrationBean} instance to be registered with the + * specified {@link ServletRegistrationBean}s. + * @param filter the filter to register + * @param servletRegistrationBeans associate {@link ServletRegistrationBean}s + */ + public FilterRegistrationBean(Filter filter, + ServletRegistrationBean... servletRegistrationBeans) { + super(servletRegistrationBeans); + Assert.notNull(filter, "Filter must not be null"); + this.filter = filter; + } + + @Override + public Filter getFilter() { + return this.filter; + } + + /** + * Set the filter to be registered. + * @param filter the filter + */ + public void setFilter(Filter filter) { + Assert.notNull(filter, "Filter must not be null"); + this.filter = filter; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/MultipartConfigFactory.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/MultipartConfigFactory.java new file mode 100644 index 0000000000..85eb0e459c --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/MultipartConfigFactory.java @@ -0,0 +1,132 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.servlet; + +import javax.servlet.MultipartConfigElement; + +import org.springframework.util.Assert; + +/** + * Factory that can be used to create a {@link MultipartConfigElement}. Size values can be + * set using traditional {@literal long} values which are set in bytes or using more + * readable {@literal String} variants that accept KB or MB suffixes, for example: + * + *

+ * factory.setMaxFileSize("10Mb");
+ * factory.setMaxRequestSize("100Kb");
+ * 
+ * + * @author Phillip Webb + * @since 1.4.0 + */ +public class MultipartConfigFactory { + + private String location; + + private long maxFileSize = -1; + + private long maxRequestSize = -1; + + private int fileSizeThreshold = 0; + + /** + * Sets the directory location where files will be stored. + * @param location the location + */ + public void setLocation(String location) { + this.location = location; + } + + /** + * Sets the maximum size in bytes allowed for uploaded files. + * @param maxFileSize the maximum file size + * @see #setMaxFileSize(String) + */ + public void setMaxFileSize(long maxFileSize) { + this.maxFileSize = maxFileSize; + } + + /** + * Sets the maximum size allowed for uploaded files. Values can use the suffixed "MB" + * or "KB" to indicate a Megabyte or Kilobyte size. + * @param maxFileSize the maximum file size + * @see #setMaxFileSize(long) + */ + public void setMaxFileSize(String maxFileSize) { + this.maxFileSize = parseSize(maxFileSize); + } + + /** + * Sets the maximum size allowed in bytes for multipart/form-data requests. + * @param maxRequestSize the maximum request size + * @see #setMaxRequestSize(String) + */ + public void setMaxRequestSize(long maxRequestSize) { + this.maxRequestSize = maxRequestSize; + } + + /** + * Sets the maximum size allowed for multipart/form-data requests. Values can use the + * suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. + * @param maxRequestSize the maximum request size + * @see #setMaxRequestSize(long) + */ + public void setMaxRequestSize(String maxRequestSize) { + this.maxRequestSize = parseSize(maxRequestSize); + } + + /** + * Sets the size threshold in bytes after which files will be written to disk. + * @param fileSizeThreshold the file size threshold + * @see #setFileSizeThreshold(String) + */ + public void setFileSizeThreshold(int fileSizeThreshold) { + this.fileSizeThreshold = fileSizeThreshold; + } + + /** + * Sets the size threshold after which files will be written to disk. Values can use + * the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. + * @param fileSizeThreshold the file size threshold + * @see #setFileSizeThreshold(int) + */ + public void setFileSizeThreshold(String fileSizeThreshold) { + this.fileSizeThreshold = (int) parseSize(fileSizeThreshold); + } + + private long parseSize(String size) { + Assert.hasLength(size, "Size must not be empty"); + size = size.toUpperCase(); + if (size.endsWith("KB")) { + return Long.valueOf(size.substring(0, size.length() - 2)) * 1024; + } + if (size.endsWith("MB")) { + return Long.valueOf(size.substring(0, size.length() - 2)) * 1024 * 1024; + } + return Long.valueOf(size); + } + + /** + * Create a new {@link MultipartConfigElement} instance. + * @return the multipart config element + */ + public MultipartConfigElement createMultipartConfig() { + return new MultipartConfigElement(this.location, this.maxFileSize, + this.maxRequestSize, this.fileSizeThreshold); + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/RegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/RegistrationBean.java similarity index 97% rename from spring-boot/src/main/java/org/springframework/boot/context/embedded/RegistrationBean.java rename to spring-boot/src/main/java/org/springframework/boot/web/servlet/RegistrationBean.java index 7f48f5a28c..1f2f25082b 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/RegistrationBean.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/RegistrationBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import java.util.LinkedHashMap; import java.util.Map; @@ -29,6 +29,7 @@ import org.springframework.util.Assert; * Base class for Servlet 3.0+ based registration beans. * * @author Phillip Webb + * @since 1.4.0 * @see ServletRegistrationBean * @see FilterRegistrationBean * @see DelegatingFilterProxyRegistrationBean diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializer.java new file mode 100644 index 0000000000..ea4c2546d2 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializer.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.servlet; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.springframework.web.SpringServletContainerInitializer; +import org.springframework.web.WebApplicationInitializer; + +/** + * Interface used to configure a Servlet 3.0+ {@link ServletContext context} + * programmatically. Unlike {@link WebApplicationInitializer}, classes that implement this + * interface (and do not implement {@link WebApplicationInitializer}) will not be + * detected by {@link SpringServletContainerInitializer} and hence will not be + * automatically bootstrapped by the Servlet container. + *

+ * This interface is primarily designed to allow {@link ServletContextInitializer}s to be + * managed by Spring and not the Servlet container. + *

+ * For configuration examples see {@link WebApplicationInitializer}. + * + * @author Phillip Webb + * @since 1.4.0 + * @see WebApplicationInitializer + */ +public interface ServletContextInitializer { + + /** + * Configure the given {@link ServletContext} with any servlets, filters, listeners + * context-params and attributes necessary for initialization. + * @param servletContext the {@code ServletContext} to initialize + * @throws ServletException if any call against the given {@code ServletContext} + * throws a {@code ServletException} + */ + void onStartup(ServletContext servletContext) throws ServletException; + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializerBeans.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java similarity index 98% rename from spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializerBeans.java rename to spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index e7b5ba1bef..ffafe68630 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializerBeans.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import java.util.AbstractCollection; import java.util.ArrayList; @@ -59,7 +59,7 @@ import org.springframework.util.MultiValueMap; public class ServletContextInitializerBeans extends AbstractCollection { - static final String DISPATCHER_SERVLET_NAME = "dispatcherServlet"; + private static final String DISPATCHER_SERVLET_NAME = "dispatcherServlet"; private static final Log logger = LogFactory .getLog(ServletContextInitializerBeans.class); diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBean.java new file mode 100644 index 0000000000..35ef5ce576 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBean.java @@ -0,0 +1,149 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.servlet; + +import java.util.Collections; +import java.util.EventListener; +import java.util.HashSet; +import java.util.Set; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextAttributeListener; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletException; +import javax.servlet.ServletRequestAttributeListener; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpSessionAttributeListener; +import javax.servlet.http.HttpSessionListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; + +/** + * A {@link ServletContextInitializer} to register {@link EventListener}s in a Servlet + * 3.0+ container. Similar to the {@link ServletContext#addListener(EventListener) + * registration} features provided by {@link ServletContext} but with a Spring Bean + * friendly design. + * + * This bean can be used to register the following types of listener: + *

    + *
  • {@link ServletContextAttributeListener}
  • + *
  • {@link ServletRequestListener}
  • + *
  • {@link ServletRequestAttributeListener}
  • + *
  • {@link HttpSessionAttributeListener}
  • + *
  • {@link HttpSessionListener}
  • + *
  • {@link ServletContextListener}
  • + *
+ * + * @param the type of listener + * @author Dave Syer + * @author Phillip Webb + * @since 1.4.0 + */ +public class ServletListenerRegistrationBean + extends RegistrationBean { + + private static final Log logger = LogFactory + .getLog(ServletListenerRegistrationBean.class); + + private static final Set> SUPPORTED_TYPES; + + static { + Set> types = new HashSet>(); + types.add(ServletContextAttributeListener.class); + types.add(ServletRequestListener.class); + types.add(ServletRequestAttributeListener.class); + types.add(HttpSessionAttributeListener.class); + types.add(HttpSessionListener.class); + types.add(ServletContextListener.class); + SUPPORTED_TYPES = Collections.unmodifiableSet(types); + } + + private T listener; + + /** + * Create a new {@link ServletListenerRegistrationBean} instance. + */ + public ServletListenerRegistrationBean() { + } + + /** + * Create a new {@link ServletListenerRegistrationBean} instance. + * @param listener the listener to register + */ + public ServletListenerRegistrationBean(T listener) { + Assert.notNull(listener, "Listener must not be null"); + Assert.isTrue(isSupportedType(listener), "Listener is not of a supported type"); + this.listener = listener; + } + + /** + * Set the listener that will be registered. + * @param listener the listener to register + */ + public void setListener(T listener) { + Assert.notNull(listener, "Listener must not be null"); + Assert.isTrue(isSupportedType(listener), "Listener is not of a supported type"); + this.listener = listener; + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + if (!isEnabled()) { + logger.info("Listener " + this.listener + " was not registered (disabled)"); + return; + } + try { + servletContext.addListener(this.listener); + } + catch (RuntimeException ex) { + throw new IllegalStateException( + "Failed to add listener '" + this.listener + "' to servlet context", + ex); + } + } + + public T getListener() { + return this.listener; + } + + /** + * Returns {@code true} if the specified listener is one of the supported types. + * @param listener the listener to test + * @return if the listener is of a supported type + */ + public static boolean isSupportedType(EventListener listener) { + for (Class type : SUPPORTED_TYPES) { + if (ClassUtils.isAssignableValue(type, listener)) { + return true; + } + } + return false; + } + + /** + * Return the supported types for this registration. + * @return the supported types + */ + public static Set> getSupportedTypes() { + return SUPPORTED_TYPES; + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistrationBean.java new file mode 100644 index 0000000000..4da9bcceec --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletRegistrationBean.java @@ -0,0 +1,221 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.servlet; + +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; + +import javax.servlet.MultipartConfigElement; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import javax.servlet.ServletRegistration.Dynamic; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; + +/** + * A {@link ServletContextInitializer} to register {@link Servlet}s in a Servlet 3.0+ + * container. Similar to the {@link ServletContext#addServlet(String, Servlet) + * registration} features provided by {@link ServletContext} but with a Spring Bean + * friendly design. + *

+ * The {@link #setServlet(Servlet) servlet} must be specified before calling + * {@link #onStartup}. URL mapping can be configured used {@link #setUrlMappings} or + * omitted when mapping to '/*' (unless + * {@link #ServletRegistrationBean(Servlet, boolean, String...) alwaysMapUrl} is set to + * {@code false}). The servlet name will be deduced if not specified. + * + * @author Phillip Webb + * @since 1.4.0 + * @see ServletContextInitializer + * @see ServletContext#addServlet(String, Servlet) + */ +public class ServletRegistrationBean extends RegistrationBean { + + private static final Log logger = LogFactory.getLog(ServletRegistrationBean.class); + + private static final String[] DEFAULT_MAPPINGS = { "/*" }; + + private Servlet servlet; + + private Set urlMappings = new LinkedHashSet(); + + private boolean alwaysMapUrl = true; + + private int loadOnStartup = -1; + + private MultipartConfigElement multipartConfig; + + /** + * Create a new {@link ServletRegistrationBean} instance. + */ + public ServletRegistrationBean() { + } + + /** + * Create a new {@link ServletRegistrationBean} instance with the specified + * {@link Servlet} and URL mappings. + * @param servlet the servlet being mapped + * @param urlMappings the URLs being mapped + */ + public ServletRegistrationBean(Servlet servlet, String... urlMappings) { + this(servlet, true, urlMappings); + } + + /** + * Create a new {@link ServletRegistrationBean} instance with the specified + * {@link Servlet} and URL mappings. + * @param servlet the servlet being mapped + * @param alwaysMapUrl if omitted URL mappings should be replaced with '/*' + * @param urlMappings the URLs being mapped + */ + public ServletRegistrationBean(Servlet servlet, boolean alwaysMapUrl, + String... urlMappings) { + Assert.notNull(servlet, "Servlet must not be null"); + Assert.notNull(urlMappings, "UrlMappings must not be null"); + this.servlet = servlet; + this.alwaysMapUrl = alwaysMapUrl; + this.urlMappings.addAll(Arrays.asList(urlMappings)); + } + + /** + * Returns the servlet being registered. + * @return the servlet + */ + protected Servlet getServlet() { + return this.servlet; + } + + /** + * Sets the servlet to be registered. + * @param servlet the servlet + */ + public void setServlet(Servlet servlet) { + Assert.notNull(servlet, "Servlet must not be null"); + this.servlet = servlet; + } + + /** + * Set the URL mappings for the servlet. If not specified the mapping will default to + * '/'. This will replace any previously specified mappings. + * @param urlMappings the mappings to set + * @see #addUrlMappings(String...) + */ + public void setUrlMappings(Collection urlMappings) { + Assert.notNull(urlMappings, "UrlMappings must not be null"); + this.urlMappings = new LinkedHashSet(urlMappings); + } + + /** + * Return a mutable collection of the URL mappings for the servlet. + * @return the urlMappings + */ + public Collection getUrlMappings() { + return this.urlMappings; + } + + /** + * Add URL mappings for the servlet. + * @param urlMappings the mappings to add + * @see #setUrlMappings(Collection) + */ + public void addUrlMappings(String... urlMappings) { + Assert.notNull(urlMappings, "UrlMappings must not be null"); + this.urlMappings.addAll(Arrays.asList(urlMappings)); + } + + /** + * Sets the {@code loadOnStartup} priority. See + * {@link ServletRegistration.Dynamic#setLoadOnStartup} for details. + * @param loadOnStartup if load on startup is enabled + */ + public void setLoadOnStartup(int loadOnStartup) { + this.loadOnStartup = loadOnStartup; + } + + /** + * Set the {@link MultipartConfigElement multi-part configuration}. + * @param multipartConfig the multi-part configuration to set or {@code null} + */ + public void setMultipartConfig(MultipartConfigElement multipartConfig) { + this.multipartConfig = multipartConfig; + } + + /** + * Returns the {@link MultipartConfigElement multi-part configuration} to be applied + * or {@code null}. + * @return the multipart config + */ + public MultipartConfigElement getMultipartConfig() { + return this.multipartConfig; + } + + /** + * Returns the servlet name that will be registered. + * @return the servlet name + */ + public String getServletName() { + return getOrDeduceName(this.servlet); + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + Assert.notNull(this.servlet, "Servlet must not be null"); + String name = getServletName(); + if (!isEnabled()) { + logger.info("Servlet " + name + " was not registered (disabled)"); + return; + } + logger.info("Mapping servlet: '" + name + "' to " + this.urlMappings); + Dynamic added = servletContext.addServlet(name, this.servlet); + if (added == null) { + logger.info("Servlet " + name + " was not registered " + + "(possibly already registered?)"); + return; + } + configure(added); + } + + /** + * Configure registration settings. Subclasses can override this method to perform + * additional configuration if required. + * @param registration the registration + */ + protected void configure(ServletRegistration.Dynamic registration) { + super.configure(registration); + String[] urlMapping = this.urlMappings + .toArray(new String[this.urlMappings.size()]); + if (urlMapping.length == 0 && this.alwaysMapUrl) { + urlMapping = DEFAULT_MAPPINGS; + } + if (!ObjectUtils.isEmpty(urlMapping)) { + registration.addMapping(urlMapping); + } + registration.setLoadOnStartup(this.loadOnStartup); + if (this.multipartConfig != null) { + registration.setMultipartConfig(this.multipartConfig); + } + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebFilterHandler.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebFilterHandler.java index 31a85f5c90..e503081025 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebFilterHandler.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebFilterHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ import javax.servlet.annotation.WebFilter; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.util.StringUtils; /** diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerHandler.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerHandler.java index f34a3f935a..d9922b1326 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerHandler.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebListenerHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ import javax.servlet.annotation.WebListener; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.boot.context.embedded.ServletListenerRegistrationBean; /** * Handler for {@link WebListener}-annotated classes. diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebServletHandler.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebServletHandler.java index a4e8ff0b0a..d078ae2934 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebServletHandler.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/WebServletHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ import javax.servlet.annotation.WebServlet; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.util.StringUtils; /** diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/package-info.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/package-info.java new file mode 100644 index 0000000000..35dc89b3a2 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Classes and utilities designed to work with the `javax.servlet` specification. + */ +package org.springframework.boot.web.servlet; diff --git a/spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java b/spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java new file mode 100644 index 0000000000..28d8ed8627 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java @@ -0,0 +1,336 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.support; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.boot.context.embedded.AbstractConfigurableEmbeddedServletContainer; +import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; +import org.springframework.boot.context.web.NonEmbeddedServletContainerFactory; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.NestedServletException; + +/** + * A special {@link AbstractConfigurableEmbeddedServletContainer} for non-embedded + * applications (i.e. deployed WAR files). It registers error pages and handles + * application errors by filtering requests and forwarding to the error pages instead of + * letting the container handle them. Error pages are a feature of the servlet spec but + * there is no Java API for registering them in the spec. This filter works around that by + * accepting error page registrations from Spring Boot's + * {@link EmbeddedServletContainerCustomizer} (any beans of that type in the context will + * be applied to this container). + * + * @author Dave Syer + * @author Phillip Webb + * @author Andy Wilkinson + * @since 1.4.0 + */ +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class ErrorPageFilter extends AbstractConfigurableEmbeddedServletContainer + implements Filter, NonEmbeddedServletContainerFactory { + + private static final Log logger = LogFactory.getLog(ErrorPageFilter.class); + + // From RequestDispatcher but not referenced to remain compatible with Servlet 2.5 + + private static final String ERROR_EXCEPTION = "javax.servlet.error.exception"; + + private static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type"; + + private static final String ERROR_MESSAGE = "javax.servlet.error.message"; + + /** + * The name of the servlet attribute containing request URI. + */ + public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri"; + + private static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code"; + + private String global; + + private final Map statuses = new HashMap(); + + private final Map, String> exceptions = new HashMap, String>(); + + private final Map, Class> subtypes = new HashMap, Class>(); + + private final OncePerRequestFilter delegate = new OncePerRequestFilter() { + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, FilterChain chain) + throws ServletException, IOException { + ErrorPageFilter.this.doFilter(request, response, chain); + } + + @Override + protected boolean shouldNotFilterAsyncDispatch() { + return false; + } + + }; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + this.delegate.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + this.delegate.doFilter(request, response, chain); + } + + private void doFilter(HttpServletRequest request, HttpServletResponse response, + FilterChain chain) throws IOException, ServletException { + ErrorWrapperResponse wrapped = new ErrorWrapperResponse(response); + try { + chain.doFilter(request, wrapped); + if (wrapped.hasErrorToSend()) { + handleErrorStatus(request, response, wrapped.getStatus(), + wrapped.getMessage()); + response.flushBuffer(); + } + else if (!request.isAsyncStarted() && !response.isCommitted()) { + response.flushBuffer(); + } + } + catch (Throwable ex) { + Throwable exceptionToHandle = ex; + if (ex instanceof NestedServletException) { + exceptionToHandle = ((NestedServletException) ex).getRootCause(); + } + handleException(request, response, wrapped, exceptionToHandle); + response.flushBuffer(); + } + } + + private void handleErrorStatus(HttpServletRequest request, + HttpServletResponse response, int status, String message) + throws ServletException, IOException { + if (response.isCommitted()) { + handleCommittedResponse(request, null); + return; + } + String errorPath = getErrorPath(this.statuses, status); + if (errorPath == null) { + response.sendError(status, message); + return; + } + response.setStatus(status); + setErrorAttributes(request, status, message); + request.getRequestDispatcher(errorPath).forward(request, response); + } + + private void handleException(HttpServletRequest request, HttpServletResponse response, + ErrorWrapperResponse wrapped, Throwable ex) + throws IOException, ServletException { + Class type = ex.getClass(); + String errorPath = getErrorPath(type); + if (errorPath == null) { + rethrow(ex); + return; + } + if (response.isCommitted()) { + handleCommittedResponse(request, ex); + return; + } + + forwardToErrorPage(errorPath, request, wrapped, ex); + } + + private void forwardToErrorPage(String path, HttpServletRequest request, + HttpServletResponse response, Throwable ex) + throws ServletException, IOException { + if (logger.isErrorEnabled()) { + String message = "Forwarding to error page from request " + + getDescription(request) + " due to exception [" + ex.getMessage() + + "]"; + logger.error(message, ex); + } + setErrorAttributes(request, 500, ex.getMessage()); + request.setAttribute(ERROR_EXCEPTION, ex); + request.setAttribute(ERROR_EXCEPTION_TYPE, ex.getClass().getName()); + response.reset(); + response.sendError(500, ex.getMessage()); + request.getRequestDispatcher(path).forward(request, response); + } + + private String getDescription(HttpServletRequest request) { + return "[" + request.getServletPath() + + (request.getPathInfo() == null ? "" : request.getPathInfo()) + "]"; + } + + private void handleCommittedResponse(HttpServletRequest request, Throwable ex) { + String message = "Cannot forward to error page for request " + + getDescription(request) + " as the response has already been" + + " committed. As a result, the response may have the wrong status" + + " code. If your application is running on WebSphere Application" + + " Server you may be able to resolve this problem by setting" + + " com.ibm.ws.webcontainer.invokeFlushAfterService to false"; + if (ex == null) { + logger.error(message); + } + else { + // User might see the error page without all the data here but throwing the + // exception isn't going to help anyone (we'll log it to be on the safe side) + logger.error(message, ex); + } + } + + private String getErrorPath(Map map, Integer status) { + if (map.containsKey(status)) { + return map.get(status); + } + return this.global; + } + + private String getErrorPath(Class type) { + if (this.exceptions.containsKey(type)) { + return this.exceptions.get(type); + } + if (this.subtypes.containsKey(type)) { + return this.exceptions.get(this.subtypes.get(type)); + } + Class subtype = type; + while (subtype != Object.class) { + subtype = subtype.getSuperclass(); + if (this.exceptions.containsKey(subtype)) { + this.subtypes.put(subtype, type); + return this.exceptions.get(subtype); + } + } + return this.global; + } + + private void setErrorAttributes(HttpServletRequest request, int status, + String message) { + request.setAttribute(ERROR_STATUS_CODE, status); + request.setAttribute(ERROR_MESSAGE, message); + request.setAttribute(ERROR_REQUEST_URI, request.getRequestURI()); + } + + private void rethrow(Throwable ex) throws IOException, ServletException { + if (ex instanceof RuntimeException) { + throw (RuntimeException) ex; + } + if (ex instanceof Error) { + throw (Error) ex; + } + if (ex instanceof IOException) { + throw (IOException) ex; + } + if (ex instanceof ServletException) { + throw (ServletException) ex; + } + throw new IllegalStateException(ex); + } + + @Override + public void addErrorPages(ErrorPage... errorPages) { + for (ErrorPage errorPage : errorPages) { + if (errorPage.isGlobal()) { + this.global = errorPage.getPath(); + } + else if (errorPage.getStatus() != null) { + this.statuses.put(errorPage.getStatus().value(), errorPage.getPath()); + } + else { + this.exceptions.put(errorPage.getException(), errorPage.getPath()); + } + } + } + + @Override + public void destroy() { + } + + private static class ErrorWrapperResponse extends HttpServletResponseWrapper { + + private int status; + + private String message; + + private boolean hasErrorToSend = false; + + ErrorWrapperResponse(HttpServletResponse response) { + super(response); + } + + @Override + public void sendError(int status) throws IOException { + sendError(status, null); + } + + @Override + public void sendError(int status, String message) throws IOException { + this.status = status; + this.message = message; + this.hasErrorToSend = true; + // Do not call super because the container may prevent us from handling the + // error ourselves + } + + @Override + public int getStatus() { + if (this.hasErrorToSend) { + return this.status; + } + // If there was no error we need to trust the wrapped response + return super.getStatus(); + } + + @Override + public void flushBuffer() throws IOException { + if (this.hasErrorToSend && !isCommitted()) { + ((HttpServletResponse) getResponse()).sendError(this.status, + this.message); + } + super.flushBuffer(); + } + + public String getMessage() { + return this.message; + } + + public boolean hasErrorToSend() { + return this.hasErrorToSend; + } + + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/support/ServletContextApplicationContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/web/support/ServletContextApplicationContextInitializer.java new file mode 100644 index 0000000000..3771fc8365 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/support/ServletContextApplicationContextInitializer.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.support; + +import javax.servlet.ServletContext; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.core.Ordered; +import org.springframework.web.context.ConfigurableWebApplicationContext; +import org.springframework.web.context.WebApplicationContext; + +/** + * {@link ApplicationContextInitializer} for setting the servlet context. + * + * @author Dave Syer + * @author Phillip Webb + * @since 1.4.0 + */ +public class ServletContextApplicationContextInitializer implements + ApplicationContextInitializer, Ordered { + + private int order = Ordered.HIGHEST_PRECEDENCE; + + private final ServletContext servletContext; + + private final boolean addApplicationContextAttribute; + + /** + * Create a new {@link ServletContextApplicationContextInitializer} instance. + * @param servletContext the servlet that should be ultimately set. + */ + public ServletContextApplicationContextInitializer(ServletContext servletContext) { + this(servletContext, false); + } + + /** + * Create a new {@link ServletContextApplicationContextInitializer} instance. + * @param servletContext the servlet that should be ultimately set. + * @param addApplicationContextAttribute if the {@link ApplicationContext} should be + * stored as an attribute in the {@link ServletContext} + * @since 1.3.4 + */ + public ServletContextApplicationContextInitializer(ServletContext servletContext, + boolean addApplicationContextAttribute) { + this.servletContext = servletContext; + this.addApplicationContextAttribute = addApplicationContextAttribute; + } + + public void setOrder(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return this.order; + } + + @Override + public void initialize(ConfigurableWebApplicationContext applicationContext) { + applicationContext.setServletContext(this.servletContext); + if (this.addApplicationContextAttribute) { + this.servletContext.setAttribute( + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, + applicationContext); + } + + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/web/support/SpringBootServletInitializer.java b/spring-boot/src/main/java/org/springframework/boot/web/support/SpringBootServletInitializer.java new file mode 100644 index 0000000000..31fccf8399 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/web/support/SpringBootServletInitializer.java @@ -0,0 +1,176 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.support; + +import javax.servlet.Filter; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.builder.ParentContextApplicationContextInitializer; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.util.Assert; +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.WebApplicationContext; + +/** + * An opinionated {@link WebApplicationInitializer} to run a {@link SpringApplication} + * from a traditional WAR deployment. Binds {@link Servlet}, {@link Filter} and + * {@link ServletContextInitializer} beans from the application context to the servlet + * container. + *

+ * To configure the application either override the + * {@link #configure(SpringApplicationBuilder)} method (calling + * {@link SpringApplicationBuilder#sources(Object...)}) or make the initializer itself a + * {@code @Configuration}. If you are using {@link SpringBootServletInitializer} in + * combination with other {@link WebApplicationInitializer WebApplicationInitializers} you + * might also want to add an {@code @Ordered} annotation to configure a specific startup + * order. + *

+ * Note that a WebApplicationInitializer is only needed if you are building a war file and + * deploying it. If you prefer to run an embedded container then you won't need this at + * all. + * + * @author Dave Syer + * @author Phillip Webb + * @author Andy Wilkinson + * @since 1.4.0 + * @see #configure(SpringApplicationBuilder) + */ +public abstract class SpringBootServletInitializer implements WebApplicationInitializer { + + protected Log logger; // Don't initialize early + + private boolean registerErrorPageFilter = true; + + /** + * Set if the {@link ErrorPageFilter} should be registered. Set to {@code false} if + * error page mappings should be handled via the Servlet container and not Spring + * Boot. + * @param registerErrorPageFilter if the {@link ErrorPageFilter} should be registered. + */ + protected final void setRegisterErrorPageFilter(boolean registerErrorPageFilter) { + this.registerErrorPageFilter = registerErrorPageFilter; + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + // Logger initialization is deferred in case a ordered + // LogServletContextInitializer is being used + this.logger = LogFactory.getLog(getClass()); + WebApplicationContext rootAppContext = createRootApplicationContext( + servletContext); + if (rootAppContext != null) { + servletContext.addListener(new ContextLoaderListener(rootAppContext) { + @Override + public void contextInitialized(ServletContextEvent event) { + // no-op because the application context is already initialized + } + }); + } + else { + this.logger.debug("No ContextLoaderListener registered, as " + + "createRootApplicationContext() did not " + + "return an application context"); + } + } + + protected WebApplicationContext createRootApplicationContext( + ServletContext servletContext) { + SpringApplicationBuilder builder = createSpringApplicationBuilder(); + builder.main(getClass()); + ApplicationContext parent = getExistingRootWebApplicationContext(servletContext); + if (parent != null) { + this.logger.info("Root context already created (using as parent)."); + servletContext.setAttribute( + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null); + builder.initializers(new ParentContextApplicationContextInitializer(parent)); + } + builder.initializers( + new ServletContextApplicationContextInitializer(servletContext)); + builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class); + builder = configure(builder); + SpringApplication application = builder.build(); + if (application.getSources().isEmpty() && AnnotationUtils + .findAnnotation(getClass(), Configuration.class) != null) { + application.getSources().add(getClass()); + } + Assert.state(!application.getSources().isEmpty(), + "No SpringApplication sources have been defined. Either override the " + + "configure method or add an @Configuration annotation"); + // Ensure error pages are registered + if (this.registerErrorPageFilter) { + application.getSources().add(ErrorPageFilter.class); + } + return run(application); + } + + /** + * Returns the {@code SpringApplicationBuilder} that is used to configure and create + * the {@link SpringApplication}. The default implementation returns a new + * {@code SpringApplicationBuilder} in its default state. + * @return the {@code SpringApplicationBuilder}. + * @since 1.3.0 + */ + protected SpringApplicationBuilder createSpringApplicationBuilder() { + return new SpringApplicationBuilder(); + } + + /** + * Called to run a fully configured {@link SpringApplication}. + * @param application the application to run + * @return the {@link WebApplicationContext} + */ + protected WebApplicationContext run(SpringApplication application) { + return (WebApplicationContext) application.run(); + } + + private ApplicationContext getExistingRootWebApplicationContext( + ServletContext servletContext) { + Object context = servletContext.getAttribute( + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); + if (context instanceof ApplicationContext) { + return (ApplicationContext) context; + } + return null; + } + + /** + * Configure the application. Normally all you would need to do it add sources (e.g. + * config classes) because other settings have sensible defaults. You might choose + * (for instance) to add default command line arguments, or set an active Spring + * profile. + * @param builder a builder for the application context + * @return the application builder + * @see SpringApplicationBuilder + */ + protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { + return builder; + } + +} diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java index 3c3a48b372..a91d2828fc 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java @@ -74,6 +74,10 @@ import org.mockito.InOrder; import org.springframework.boot.ApplicationHome; import org.springframework.boot.ApplicationTemp; import org.springframework.boot.context.embedded.Ssl.ClientAuth; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpMethod; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AnnotationConfigEmbeddedWebApplicationContextTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AnnotationConfigEmbeddedWebApplicationContextTests.java index 6c3f710bd7..e344f189a0 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AnnotationConfigEmbeddedWebApplicationContextTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AnnotationConfigEmbeddedWebApplicationContextTests.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.config.ExampleEmbeddedWebApplicationConfiguration; +import org.springframework.boot.testutil.MockServlet; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerMvcIntegrationTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerMvcIntegrationTests.java index bb0dfe3737..531fa5f062 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerMvcIntegrationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedServletContainerMvcIntegrationTests.java @@ -25,6 +25,7 @@ import org.junit.Test; import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java index 9374b75cd4..4d5cb13084 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java @@ -18,8 +18,10 @@ package org.springframework.boot.context.embedded; import java.io.IOException; import java.lang.reflect.Field; +import java.util.EnumSet; import java.util.Properties; +import javax.servlet.DispatcherType; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.Servlet; @@ -48,7 +50,10 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.Scope; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer; +import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.ApplicationContextException; import org.springframework.context.ApplicationListener; import org.springframework.context.support.AbstractApplicationContext; @@ -81,6 +86,13 @@ import static org.mockito.Mockito.withSettings; */ public class EmbeddedWebApplicationContextTests { + private static final EnumSet ASYNC_DISPATCHER_TYPES = EnumSet.of( + DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST, + DispatcherType.ASYNC); + + private static final EnumSet NON_ASYNC_DISPATCHER_TYPES = EnumSet + .of(DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST); + @Rule public ExpectedException thrown = ExpectedException.none(); @@ -302,10 +314,10 @@ public class EmbeddedWebApplicationContextTests { verify(escf.getRegisteredServlet(0).getRegistration()).addMapping("/"); ordered.verify(escf.getServletContext()).addFilter("filterBean1", filter1); ordered.verify(escf.getServletContext()).addFilter("filterBean2", filter2); - verify(escf.getRegisteredFilter(0).getRegistration()).addMappingForUrlPatterns( - AbstractFilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "/*"); - verify(escf.getRegisteredFilter(1).getRegistration()).addMappingForUrlPatterns( - AbstractFilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "/*"); + verify(escf.getRegisteredFilter(0).getRegistration()) + .addMappingForUrlPatterns(ASYNC_DISPATCHER_TYPES, false, "/*"); + verify(escf.getRegisteredFilter(1).getRegistration()) + .addMappingForUrlPatterns(ASYNC_DISPATCHER_TYPES, false, "/*"); } @Test diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockEmbeddedServletContainerFactory.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockEmbeddedServletContainerFactory.java index 4e3b78b593..b3101ab16d 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockEmbeddedServletContainerFactory.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockEmbeddedServletContainerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,8 @@ import javax.servlet.ServletRegistration; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.springframework.boot.web.servlet.ServletContextInitializer; + import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/config/ExampleEmbeddedWebApplicationConfiguration.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/config/ExampleEmbeddedWebApplicationConfiguration.java index 4613278e65..7ebd6597ca 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/config/ExampleEmbeddedWebApplicationConfiguration.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/config/ExampleEmbeddedWebApplicationConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import javax.servlet.Servlet; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContextTests; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory; -import org.springframework.boot.context.embedded.MockServlet; +import org.springframework.boot.testutil.MockServlet; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java index 12f085dfe1..e09cea7a68 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java @@ -43,8 +43,8 @@ import org.mockito.InOrder; import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests; import org.springframework.boot.context.embedded.Compression; -import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.embedded.Ssl; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.http.HttpHeaders; import static org.assertj.core.api.Assertions.assertThat; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java index c29cb462d9..3d4532e712 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainerFactoryTests.java @@ -37,10 +37,10 @@ import org.mockito.InOrder; import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests; -import org.springframework.boot.context.embedded.ErrorPage; import org.springframework.boot.context.embedded.ExampleServlet; import org.springframework.boot.context.embedded.MimeMappings.Mapping; -import org.springframework.boot.context.embedded.ServletRegistrationBean; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.http.HttpStatus; import org.springframework.test.util.ReflectionTestUtils; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockFilter.java b/spring-boot/src/test/java/org/springframework/boot/testutil/MockFilter.java similarity index 91% rename from spring-boot/src/test/java/org/springframework/boot/context/embedded/MockFilter.java rename to spring-boot/src/test/java/org/springframework/boot/testutil/MockFilter.java index 37f877c475..3029c3e306 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockFilter.java +++ b/spring-boot/src/test/java/org/springframework/boot/testutil/MockFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.testutil; import java.io.IOException; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockServlet.java b/spring-boot/src/test/java/org/springframework/boot/testutil/MockServlet.java similarity index 90% rename from spring-boot/src/test/java/org/springframework/boot/context/embedded/MockServlet.java rename to spring-boot/src/test/java/org/springframework/boot/testutil/MockServlet.java index 9f48ba3ac5..0cb083a4f2 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockServlet.java +++ b/spring-boot/src/test/java/org/springframework/boot/testutil/MockServlet.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.testutil; import java.io.IOException; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBeanTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBeanTests.java similarity index 89% rename from spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBeanTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBeanTests.java index 29100f86c3..0cfd8a4499 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBeanTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import java.util.Arrays; import java.util.Collections; @@ -49,6 +49,13 @@ import static org.mockito.Mockito.verify; */ public abstract class AbstractFilterRegistrationBeanTests { + private static final EnumSet ASYNC_DISPATCHER_TYPES = EnumSet.of( + DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST, + DispatcherType.ASYNC); + + private static final EnumSet NON_ASYNC_DISPATCHER_TYPES = EnumSet + .of(DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST); + @Rule public ExpectedException thrown = ExpectedException.none(); @@ -71,8 +78,8 @@ public abstract class AbstractFilterRegistrationBeanTests { bean.onStartup(this.servletContext); verify(this.servletContext).addFilter(eq("mockFilter"), getExpectedFilter()); verify(this.registration).setAsyncSupported(true); - verify(this.registration).addMappingForUrlPatterns( - AbstractFilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "/*"); + verify(this.registration).addMappingForUrlPatterns(ASYNC_DISPATCHER_TYPES, false, + "/*"); } @Test @@ -97,12 +104,10 @@ public abstract class AbstractFilterRegistrationBeanTests { expectedInitParameters.put("a", "b"); expectedInitParameters.put("c", "d"); verify(this.registration).setInitParameters(expectedInitParameters); - verify(this.registration).addMappingForUrlPatterns( - AbstractFilterRegistrationBean.NON_ASYNC_DISPATCHER_TYPES, true, "/a", - "/b", "/c"); - verify(this.registration).addMappingForServletNames( - AbstractFilterRegistrationBean.NON_ASYNC_DISPATCHER_TYPES, true, "s4", - "s5", "s1", "s2", "s3"); + verify(this.registration).addMappingForUrlPatterns(NON_ASYNC_DISPATCHER_TYPES, + true, "/a", "/b", "/c"); + verify(this.registration).addMappingForServletNames(NON_ASYNC_DISPATCHER_TYPES, + true, "s4", "s5", "s1", "s2", "s3"); } @Test @@ -152,8 +157,8 @@ public abstract class AbstractFilterRegistrationBeanTests { bean.setServletRegistrationBeans(new LinkedHashSet( Arrays.asList(mockServletRegistration("b")))); bean.onStartup(this.servletContext); - verify(this.registration).addMappingForServletNames( - AbstractFilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "b"); + verify(this.registration).addMappingForServletNames(ASYNC_DISPATCHER_TYPES, false, + "b"); } @Test diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBeanTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBeanTests.java similarity index 98% rename from spring-boot/src/test/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBeanTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBeanTests.java index ca72a682ec..9a3a5041e0 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBeanTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBeanTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import javax.servlet.Filter; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/FilterRegistrationBeanTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationBeanTests.java similarity index 93% rename from spring-boot/src/test/java/org/springframework/boot/context/embedded/FilterRegistrationBeanTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationBeanTests.java index 679d7f4927..dd6bcbf78e 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/FilterRegistrationBeanTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,14 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import javax.servlet.Filter; import org.junit.Test; +import org.springframework.boot.testutil.MockFilter; + import static org.mockito.Matchers.eq; import static org.mockito.Mockito.verify; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MultipartConfigFactoryTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/MultipartConfigFactoryTests.java similarity index 97% rename from spring-boot/src/test/java/org/springframework/boot/context/embedded/MultipartConfigFactoryTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/servlet/MultipartConfigFactoryTests.java index fe896f6cdf..cdde49ecd7 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MultipartConfigFactoryTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/MultipartConfigFactoryTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import javax.servlet.MultipartConfigElement; diff --git a/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanIntegrationTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanIntegrationTests.java index f096d8e887..1248b6d26b 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanIntegrationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanIntegrationTests.java @@ -20,8 +20,8 @@ import org.junit.After; import org.junit.Test; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; +import org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; -import org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/ServletListenerRegistrationBeanTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBeanTests.java similarity index 95% rename from spring-boot/src/test/java/org/springframework/boot/context/embedded/ServletListenerRegistrationBeanTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBeanTests.java index d61f60263f..be908363ea 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/ServletListenerRegistrationBeanTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletListenerRegistrationBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import java.util.EventListener; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/ServletRegistrationBeanTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletRegistrationBeanTests.java similarity index 97% rename from spring-boot/src/test/java/org/springframework/boot/context/embedded/ServletRegistrationBeanTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletRegistrationBeanTests.java index 1570fc04de..78582570ff 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/ServletRegistrationBeanTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletRegistrationBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.embedded; +package org.springframework.boot.web.servlet; import java.util.Arrays; import java.util.Collections; @@ -35,6 +35,8 @@ import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.springframework.boot.testutil.MockServlet; + import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyObject; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/web/ErrorPageFilterIntegrationTests.java b/spring-boot/src/test/java/org/springframework/boot/web/support/ErrorPageFilterIntegrationTests.java similarity index 95% rename from spring-boot/src/test/java/org/springframework/boot/context/web/ErrorPageFilterIntegrationTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/support/ErrorPageFilterIntegrationTests.java index 41bef0711b..0beb5d6163 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/web/ErrorPageFilterIntegrationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/support/ErrorPageFilterIntegrationTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.web; +package org.springframework.boot.web.support; import java.net.URI; import java.util.concurrent.CountDownLatch; @@ -32,8 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; -import org.springframework.boot.context.web.ErrorPageFilterIntegrationTests.EmbeddedWebContextLoader; -import org.springframework.boot.context.web.ErrorPageFilterIntegrationTests.TomcatConfig; +import org.springframework.boot.web.support.ErrorPageFilterIntegrationTests.EmbeddedWebContextLoader; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -66,7 +65,7 @@ import static org.assertj.core.api.Assertions.assertThat; */ @RunWith(SpringRunner.class) @DirtiesContext -@ContextConfiguration(classes = TomcatConfig.class, loader = EmbeddedWebContextLoader.class) +@ContextConfiguration(classes = ErrorPageFilterIntegrationTests.TomcatConfig.class, loader = EmbeddedWebContextLoader.class) public class ErrorPageFilterIntegrationTests { @Autowired diff --git a/spring-boot/src/test/java/org/springframework/boot/context/web/ErrorPageFilterTests.java b/spring-boot/src/test/java/org/springframework/boot/web/support/ErrorPageFilterTests.java similarity index 99% rename from spring-boot/src/test/java/org/springframework/boot/context/web/ErrorPageFilterTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/support/ErrorPageFilterTests.java index da44ab3fb8..f5c03a76d8 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/web/ErrorPageFilterTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/support/ErrorPageFilterTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.web; +package org.springframework.boot.web.support; import java.io.IOException; @@ -28,8 +28,8 @@ import javax.servlet.http.HttpServletResponseWrapper; import org.junit.Rule; import org.junit.Test; -import org.springframework.boot.context.embedded.ErrorPage; import org.springframework.boot.testutil.InternalOutputCapture; +import org.springframework.boot.web.servlet.ErrorPage; import org.springframework.http.HttpStatus; import org.springframework.mock.web.MockFilterChain; import org.springframework.mock.web.MockFilterConfig; diff --git a/spring-boot/src/test/java/org/springframework/boot/context/web/SpringBootServletInitializerTests.java b/spring-boot/src/test/java/org/springframework/boot/web/support/SpringBootServletInitializerTests.java similarity index 99% rename from spring-boot/src/test/java/org/springframework/boot/context/web/SpringBootServletInitializerTests.java rename to spring-boot/src/test/java/org/springframework/boot/web/support/SpringBootServletInitializerTests.java index 4077d8b679..159839b87b 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/web/SpringBootServletInitializerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/support/SpringBootServletInitializerTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.boot.context.web; +package org.springframework.boot.web.support; import javax.servlet.ServletContext; diff --git a/spring-boot/src/test/resources/org/springframework/boot/context/embedded/exampleEmbeddedWebApplicationConfiguration.xml b/spring-boot/src/test/resources/org/springframework/boot/context/embedded/exampleEmbeddedWebApplicationConfiguration.xml index 5dc0d4e3c4..a03e06c9cf 100644 --- a/spring-boot/src/test/resources/org/springframework/boot/context/embedded/exampleEmbeddedWebApplicationConfiguration.xml +++ b/spring-boot/src/test/resources/org/springframework/boot/context/embedded/exampleEmbeddedWebApplicationConfiguration.xml @@ -6,6 +6,6 @@ - +