diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBean.java new file mode 100644 index 0000000000..22712091b6 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBean.java @@ -0,0 +1,278 @@ +/* + * Copyright 2012-2015 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.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.LinkedHashSet; +import java.util.Set; + +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.util.Assert; + +/** + * Abstract base {@link ServletContextInitializer} to register {@link Filter}s in a + * Servlet 3.0+ container. + * + * @author Phillip Webb + */ +abstract class AbstractFilterRegistrationBean extends RegistrationBean { + + /** + * Filters that wrap the servlet request should be ordered less than or equal to this. + */ + protected static final int REQUEST_WRAPPER_FILTER_MAX_ORDER = 0; + + private final Log logger = LogFactory.getLog(getClass()); + + static final EnumSet ASYNC_DISPATCHER_TYPES = EnumSet.of( + DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST, + DispatcherType.ASYNC); + + static final EnumSet NON_ASYNC_DISPATCHER_TYPES = EnumSet + .of(DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST); + + private static final String[] DEFAULT_URL_MAPPINGS = { "/*" }; + + private Set servletRegistrationBeans = new LinkedHashSet(); + + private Set servletNames = new LinkedHashSet(); + + private Set urlPatterns = new LinkedHashSet(); + + private EnumSet dispatcherTypes; + + private boolean matchAfter = false; + + /** + * Create a new instance to be registered with the specified + * {@link ServletRegistrationBean}s. + * @param servletRegistrationBeans associate {@link ServletRegistrationBean}s + */ + AbstractFilterRegistrationBean(ServletRegistrationBean... servletRegistrationBeans) { + Assert.notNull(servletRegistrationBeans, + "ServletRegistrationBeans must not be null"); + Collections.addAll(this.servletRegistrationBeans, servletRegistrationBeans); + } + + /** + * Set {@link ServletRegistrationBean}s that the filter will be registered against. + * @param servletRegistrationBeans the Servlet registration beans + */ + public void setServletRegistrationBeans( + Collection servletRegistrationBeans) { + Assert.notNull(servletRegistrationBeans, + "ServletRegistrationBeans must not be null"); + this.servletRegistrationBeans = new LinkedHashSet( + servletRegistrationBeans); + } + + /** + * Return a mutable collection of the {@link ServletRegistrationBean} that the filter + * will be registered against. {@link ServletRegistrationBean}s. + * @return the Servlet registration beans + * @see #setServletNames + * @see #setUrlPatterns + */ + public Collection getServletRegistrationBeans() { + return this.servletRegistrationBeans; + } + + /** + * Add {@link ServletRegistrationBean}s for the filter. + * @param servletRegistrationBeans the servlet registration beans to add + * @see #setServletRegistrationBeans + */ + public void addServletRegistrationBeans( + ServletRegistrationBean... servletRegistrationBeans) { + Assert.notNull(servletRegistrationBeans, + "ServletRegistrationBeans must not be null"); + Collections.addAll(this.servletRegistrationBeans, servletRegistrationBeans); + } + + /** + * Set servlet names that the filter will be registered against. This will replace any + * previously specified servlet names. + * @param servletNames the servlet names + * @see #setServletRegistrationBeans + * @see #setUrlPatterns + */ + public void setServletNames(Collection servletNames) { + Assert.notNull(servletNames, "ServletNames must not be null"); + this.servletNames = new LinkedHashSet(servletNames); + } + + /** + * Return a mutable collection of servlet names that the filter will be registered + * against. + * @return the servlet names + */ + public Collection getServletNames() { + return this.servletNames; + } + + /** + * Add servlet names for the filter. + * @param servletNames the servlet names to add + */ + public void addServletNames(String... servletNames) { + Assert.notNull(servletNames, "ServletNames must not be null"); + this.servletNames.addAll(Arrays.asList(servletNames)); + } + + /** + * Set the URL patterns that the filter will be registered against. This will replace + * any previously specified URL patterns. + * @param urlPatterns the URL patterns + * @see #setServletRegistrationBeans + * @see #setServletNames + */ + public void setUrlPatterns(Collection urlPatterns) { + Assert.notNull(urlPatterns, "UrlPatterns must not be null"); + this.urlPatterns = new LinkedHashSet(urlPatterns); + } + + /** + * Return a mutable collection of URL patterns that the filter will be registered + * against. + * @return the URL patterns + */ + public Collection getUrlPatterns() { + return this.urlPatterns; + } + + /** + * Add URL patterns that the filter will be registered against. + * @param urlPatterns the URL patterns + */ + public void addUrlPatterns(String... urlPatterns) { + Assert.notNull(urlPatterns, "UrlPatterns must not be null"); + Collections.addAll(this.urlPatterns, urlPatterns); + } + + /** + * Convenience method to {@link #setDispatcherTypes(EnumSet) set dispatcher types} + * using the specified elements. + * @param first the first dispatcher type + * @param rest additional dispatcher types + */ + public void setDispatcherTypes(DispatcherType first, DispatcherType... rest) { + this.dispatcherTypes = EnumSet.of(first, rest); + } + + /** + * Sets the dispatcher types that should be used with the registration. If not + * specified the types will be deduced based on the value of + * {@link #isAsyncSupported()}. + * @param dispatcherTypes the dispatcher types + */ + public void setDispatcherTypes(EnumSet dispatcherTypes) { + this.dispatcherTypes = dispatcherTypes; + } + + /** + * Set if the filter mappings should be matched after any declared filter mappings of + * the ServletContext. Defaults to {@code false} indicating the filters are supposed + * to be matched before any declared filter mappings of the ServletContext. + * @param matchAfter if filter mappings are matched after + */ + public void setMatchAfter(boolean matchAfter) { + this.matchAfter = matchAfter; + } + + /** + * Return if filter mappings should be matched after any declared Filter mappings of + * the ServletContext. + * @return if filter mappings are matched after + */ + public boolean isMatchAfter() { + return this.matchAfter; + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + Filter filter = getFilter(); + Assert.notNull(filter, "Filter must not be null"); + String name = getOrDeduceName(filter); + if (!isEnabled()) { + this.logger.info("Filter " + name + " was not registered (disabled)"); + return; + } + FilterRegistration.Dynamic added = servletContext.addFilter(name, filter); + if (added == null) { + this.logger.info("Filter " + name + " was not registered " + + "(possibly already registered?)"); + return; + } + configure(added); + } + + /** + * Return the {@link Filter} to be registered. + * @return the filter + */ + protected abstract Filter getFilter(); + + /** + * Configure registration settings. Subclasses can override this method to perform + * additional configuration if required. + * @param registration the registration + */ + protected void configure(FilterRegistration.Dynamic registration) { + super.configure(registration); + EnumSet dispatcherTypes = this.dispatcherTypes; + if (dispatcherTypes == null) { + dispatcherTypes = (isAsyncSupported() ? ASYNC_DISPATCHER_TYPES + : NON_ASYNC_DISPATCHER_TYPES); + } + Set servletNames = new LinkedHashSet(); + for (ServletRegistrationBean servletRegistrationBean : this.servletRegistrationBeans) { + servletNames.add(servletRegistrationBean.getServletName()); + } + servletNames.addAll(this.servletNames); + if (servletNames.isEmpty() && this.urlPatterns.isEmpty()) { + this.logger.info("Mapping filter: '" + registration.getName() + "' to: " + + Arrays.asList(DEFAULT_URL_MAPPINGS)); + registration.addMappingForUrlPatterns(dispatcherTypes, this.matchAfter, + DEFAULT_URL_MAPPINGS); + } + else { + if (servletNames.size() > 0) { + this.logger.info("Mapping filter: '" + registration.getName() + + "' to servlets: " + servletNames); + registration.addMappingForServletNames(dispatcherTypes, this.matchAfter, + servletNames.toArray(new String[servletNames.size()])); + } + if (this.urlPatterns.size() > 0) { + this.logger.info("Mapping filter: '" + registration.getName() + + "' to urls: " + this.urlPatterns); + registration.addMappingForUrlPatterns(dispatcherTypes, this.matchAfter, + this.urlPatterns.toArray(new String[this.urlPatterns.size()])); + } + } + } + +} 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 new file mode 100644 index 0000000000..6b9099ec82 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBean.java @@ -0,0 +1,96 @@ +/* + * Copyright 2012-2015 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 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.3.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 + protected 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/context/embedded/FilterRegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/FilterRegistrationBean.java index b27aff4fd5..4090b3e6b9 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 @@ -16,21 +16,9 @@ package org.springframework.boot.context.embedded; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.LinkedHashSet; -import java.util.Set; - -import javax.servlet.DispatcherType; import javax.servlet.Filter; -import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; /** @@ -48,37 +36,17 @@ import org.springframework.util.Assert; * @author Phillip Webb * @see ServletContextInitializer * @see ServletContext#addFilter(String, Filter) + * @see DelegatingFilterProxyRegistrationBean */ -public class FilterRegistrationBean extends RegistrationBean { +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 = 0; - - private static Log logger = LogFactory.getLog(FilterRegistrationBean.class); - - static final EnumSet ASYNC_DISPATCHER_TYPES = EnumSet.of( - DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST, - DispatcherType.ASYNC); - - static final EnumSet NON_ASYNC_DISPATCHER_TYPES = EnumSet - .of(DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST); - - private static final String[] DEFAULT_URL_MAPPINGS = { "/*" }; + public static final int REQUEST_WRAPPER_FILTER_MAX_ORDER = AbstractFilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER; private Filter filter; - private Set servletRegistrationBeans = new LinkedHashSet(); - - private Set servletNames = new LinkedHashSet(); - - private Set urlPatterns = new LinkedHashSet(); - - private EnumSet dispatcherTypes; - - private boolean matchAfter = false; - /** * Create a new {@link FilterRegistrationBean} instance. */ @@ -93,17 +61,12 @@ public class FilterRegistrationBean extends RegistrationBean { */ public FilterRegistrationBean(Filter filter, ServletRegistrationBean... servletRegistrationBeans) { + super(servletRegistrationBeans); Assert.notNull(filter, "Filter must not be null"); - Assert.notNull(servletRegistrationBeans, - "ServletRegistrationBeans must not be null"); this.filter = filter; - Collections.addAll(this.servletRegistrationBeans, servletRegistrationBeans); } - /** - * Returns the filter being registered. - * @return the filter - */ + @Override protected Filter getFilter() { return this.filter; } @@ -117,196 +80,4 @@ public class FilterRegistrationBean extends RegistrationBean { this.filter = filter; } - /** - * Set {@link ServletRegistrationBean}s that the filter will be registered against. - * @param servletRegistrationBeans the Servlet registration beans - */ - public void setServletRegistrationBeans( - Collection servletRegistrationBeans) { - Assert.notNull(servletRegistrationBeans, - "ServletRegistrationBeans must not be null"); - this.servletRegistrationBeans = new LinkedHashSet( - servletRegistrationBeans); - } - - /** - * Return a mutable collection of the {@link ServletRegistrationBean} that the filter - * will be registered against. {@link ServletRegistrationBean}s. - * @return the Servlet registration beans - * @see #setServletNames - * @see #setUrlPatterns - */ - public Collection getServletRegistrationBeans() { - return this.servletRegistrationBeans; - } - - /** - * Add {@link ServletRegistrationBean}s for the filter. - * @param servletRegistrationBeans the servlet registration beans to add - * @see #setServletRegistrationBeans - */ - public void addServletRegistrationBeans( - ServletRegistrationBean... servletRegistrationBeans) { - Assert.notNull(servletRegistrationBeans, - "ServletRegistrationBeans must not be null"); - Collections.addAll(this.servletRegistrationBeans, servletRegistrationBeans); - } - - /** - * Set servlet names that the filter will be registered against. This will replace any - * previously specified servlet names. - * @param servletNames the servlet names - * @see #setServletRegistrationBeans - * @see #setUrlPatterns - */ - public void setServletNames(Collection servletNames) { - Assert.notNull(servletNames, "ServletNames must not be null"); - this.servletNames = new LinkedHashSet(servletNames); - } - - /** - * Return a mutable collection of servlet names that the filter will be registered - * against. - * @return the servlet names - */ - public Collection getServletNames() { - return this.servletNames; - } - - /** - * Add servlet names for the filter. - * @param servletNames the servlet names to add - */ - public void addServletNames(String... servletNames) { - Assert.notNull(servletNames, "ServletNames must not be null"); - this.servletNames.addAll(Arrays.asList(servletNames)); - } - - /** - * Set the URL patterns that the filter will be registered against. This will replace - * any previously specified URL patterns. - * @param urlPatterns the URL patterns - * @see #setServletRegistrationBeans - * @see #setServletNames - */ - public void setUrlPatterns(Collection urlPatterns) { - Assert.notNull(urlPatterns, "UrlPatterns must not be null"); - this.urlPatterns = new LinkedHashSet(urlPatterns); - } - - /** - * Return a mutable collection of URL patterns that the filter will be registered - * against. - * @return the URL patterns - */ - public Collection getUrlPatterns() { - return this.urlPatterns; - } - - /** - * Add URL patterns that the filter will be registered against. - * @param urlPatterns the URL patterns - */ - public void addUrlPatterns(String... urlPatterns) { - Assert.notNull(urlPatterns, "UrlPatterns must not be null"); - Collections.addAll(this.urlPatterns, urlPatterns); - } - - /** - * Convenience method to {@link #setDispatcherTypes(EnumSet) set dispatcher types} - * using the specified elements. - * @param first the first dispatcher type - * @param rest additional dispatcher types - */ - public void setDispatcherTypes(DispatcherType first, DispatcherType... rest) { - this.dispatcherTypes = EnumSet.of(first, rest); - } - - /** - * Sets the dispatcher types that should be used with the registration. If not - * specified the types will be deduced based on the value of - * {@link #isAsyncSupported()}. - * @param dispatcherTypes the dispatcher types - */ - public void setDispatcherTypes(EnumSet dispatcherTypes) { - this.dispatcherTypes = dispatcherTypes; - } - - /** - * Set if the filter mappings should be matched after any declared filter mappings of - * the ServletContext. Defaults to {@code false} indicating the filters are supposed - * to be matched before any declared filter mappings of the ServletContext. - * @param matchAfter if filter mappings are matched after - */ - public void setMatchAfter(boolean matchAfter) { - this.matchAfter = matchAfter; - } - - /** - * Return if filter mappings should be matched after any declared Filter mappings of - * the ServletContext. - * @return if filter mappings are matched after - */ - public boolean isMatchAfter() { - return this.matchAfter; - } - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - Assert.notNull(this.filter, "Filter must not be null"); - String name = getOrDeduceName(this.filter); - if (!isEnabled()) { - logger.info("Filter " + name + " was not registered (disabled)"); - return; - } - FilterRegistration.Dynamic added = servletContext.addFilter(name, this.filter); - if (added == null) { - logger.info("Filter " + 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(FilterRegistration.Dynamic registration) { - super.configure(registration); - EnumSet dispatcherTypes = this.dispatcherTypes; - if (dispatcherTypes == null) { - dispatcherTypes = (isAsyncSupported() ? ASYNC_DISPATCHER_TYPES - : NON_ASYNC_DISPATCHER_TYPES); - } - - Set servletNames = new LinkedHashSet(); - for (ServletRegistrationBean servletRegistrationBean : this.servletRegistrationBeans) { - servletNames.add(servletRegistrationBean.getServletName()); - } - servletNames.addAll(this.servletNames); - - if (servletNames.isEmpty() && this.urlPatterns.isEmpty()) { - logger.info("Mapping filter: '" + registration.getName() + "' to: " - + Arrays.asList(DEFAULT_URL_MAPPINGS)); - registration.addMappingForUrlPatterns(dispatcherTypes, this.matchAfter, - DEFAULT_URL_MAPPINGS); - } - else { - if (servletNames.size() > 0) { - logger.info("Mapping filter: '" + registration.getName() - + "' to servlets: " + servletNames); - registration.addMappingForServletNames(dispatcherTypes, this.matchAfter, - servletNames.toArray(new String[servletNames.size()])); - } - if (this.urlPatterns.size() > 0) { - logger.info("Mapping filter: '" + registration.getName() + "' to urls: " - + this.urlPatterns); - registration.addMappingForUrlPatterns(dispatcherTypes, this.matchAfter, - this.urlPatterns.toArray(new String[this.urlPatterns.size()])); - } - } - } - } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/RegistrationBean.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/RegistrationBean.java index c6273a5590..64435ed653 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/RegistrationBean.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/RegistrationBean.java @@ -31,6 +31,7 @@ import org.springframework.util.Assert; * @author Phillip Webb * @see ServletRegistrationBean * @see FilterRegistrationBean + * @see DelegatingFilterProxyRegistrationBean * @see ServletListenerRegistrationBean */ public abstract class RegistrationBean implements ServletContextInitializer, Ordered { diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializerBeans.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializerBeans.java index d545ed7951..edbd2c9972 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializerBeans.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/ServletContextInitializerBeans.java @@ -62,6 +62,9 @@ class ServletContextInitializerBeans private final Log log = LogFactory.getLog(getClass()); + /** + * Seen bean instances or bean names. + */ private final Set seen = new HashSet(); private final MultiValueMap, ServletContextInitializer> initializers; @@ -92,17 +95,26 @@ class ServletContextInitializerBeans private void addServletContextInitializerBean(String beanName, ServletContextInitializer initializer, ListableBeanFactory beanFactory) { if (initializer instanceof ServletRegistrationBean) { + Servlet source = ((ServletRegistrationBean) initializer).getServlet(); addServletContextInitializerBean(Servlet.class, beanName, initializer, - beanFactory, ((ServletRegistrationBean) initializer).getServlet()); + beanFactory, source); } else if (initializer instanceof FilterRegistrationBean) { + Filter source = ((FilterRegistrationBean) initializer).getFilter(); addServletContextInitializerBean(Filter.class, beanName, initializer, - beanFactory, ((FilterRegistrationBean) initializer).getFilter()); + beanFactory, source); + } + else if (initializer instanceof DelegatingFilterProxyRegistrationBean) { + String source = ((DelegatingFilterProxyRegistrationBean) initializer) + .getTargetBeanName(); + addServletContextInitializerBean(Filter.class, beanName, initializer, + beanFactory, source); } else if (initializer instanceof ServletListenerRegistrationBean) { + EventListener source = ((ServletListenerRegistrationBean) initializer) + .getListener(); addServletContextInitializerBean(EventListener.class, beanName, initializer, - beanFactory, - ((ServletListenerRegistrationBean) initializer).getListener()); + beanFactory, source); } else { addServletContextInitializerBean(ServletContextInitializer.class, beanName, @@ -164,7 +176,8 @@ class ServletContextInitializerBeans private void addAsRegistrationBean(ListableBeanFactory beanFactory, Class type, Class beanType, RegistrationBeanAdapter adapter) { - List> beans = getOrderedBeansOfType(beanFactory, beanType); + List> beans = getOrderedBeansOfType(beanFactory, beanType, + this.seen); for (Entry bean : beans) { if (this.seen.add(bean.getValue())) { int order = getOrder(bean.getValue()); @@ -175,7 +188,6 @@ class ServletContextInitializerBeans registration.setName(beanName); registration.setOrder(order); this.initializers.add(type, registration); - if (this.log.isDebugEnabled()) { this.log.debug( "Created " + type.getSimpleName() + " initializer for bean '" @@ -197,18 +209,30 @@ class ServletContextInitializerBeans private List> getOrderedBeansOfType( ListableBeanFactory beanFactory, Class type) { + return getOrderedBeansOfType(beanFactory, type, Collections.emptySet()); + } + + private List> getOrderedBeansOfType( + ListableBeanFactory beanFactory, Class type, Set excludes) { List> beans = new ArrayList>(); Comparator> comparator = new Comparator>() { + @Override public int compare(Entry o1, Entry o2) { return AnnotationAwareOrderComparator.INSTANCE.compare(o1.getValue(), o2.getValue()); } + }; String[] names = beanFactory.getBeanNamesForType(type, true, false); Map map = new LinkedHashMap(); for (String name : names) { - map.put(name, beanFactory.getBean(name, type)); + if (!excludes.contains(name)) { + T bean = beanFactory.getBean(name, type); + if (!excludes.contains(bean)) { + map.put(name, bean); + } + } } beans.addAll(map.entrySet()); Collections.sort(beans, comparator); diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBeanTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBeanTests.java new file mode 100644 index 0000000000..5121bbb64a --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractFilterRegistrationBeanTests.java @@ -0,0 +1,230 @@ +/* + * Copyright 2012-2015 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.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; + +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; +import javax.servlet.ServletContext; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * Abstract base for {@link AbstractFilterRegistrationBean} tests. + * + * @author Phillip Webb + */ +public abstract class AbstractFilterRegistrationBeanTests { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Mock + ServletContext servletContext; + + @Mock + FilterRegistration.Dynamic registration; + + @Before + public void setupMocks() { + MockitoAnnotations.initMocks(this); + given(this.servletContext.addFilter(anyString(), (Filter) anyObject())) + .willReturn(this.registration); + } + + @Test + public void startupWithDefaults() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + 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, "/*"); + } + + @Test + public void startupWithSpecifiedValues() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + bean.setName("test"); + bean.setAsyncSupported(false); + bean.setInitParameters(Collections.singletonMap("a", "b")); + bean.addInitParameter("c", "d"); + bean.setUrlPatterns(new LinkedHashSet(Arrays.asList("/a", "/b"))); + bean.addUrlPatterns("/c"); + bean.setServletNames(new LinkedHashSet(Arrays.asList("s1", "s2"))); + bean.addServletNames("s3"); + bean.setServletRegistrationBeans( + Collections.singleton(mockServletRegistation("s4"))); + bean.addServletRegistrationBeans(mockServletRegistation("s5")); + bean.setMatchAfter(true); + bean.onStartup(this.servletContext); + verify(this.servletContext).addFilter(eq("test"), getExpectedFilter()); + verify(this.registration).setAsyncSupported(false); + Map expectedInitParameters = new HashMap(); + 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"); + } + + @Test + public void specificName() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + bean.setName("specificName"); + bean.onStartup(this.servletContext); + verify(this.servletContext).addFilter(eq("specificName"), getExpectedFilter()); + } + + @Test + public void deducedName() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + bean.onStartup(this.servletContext); + verify(this.servletContext).addFilter(eq("mockFilter"), getExpectedFilter()); + } + + @Test + public void disable() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + bean.setEnabled(false); + bean.onStartup(this.servletContext); + verify(this.servletContext, times(0)).addFilter(eq("mockFilter"), + getExpectedFilter()); + } + + @Test + public void setServletRegistrationBeanMustNotBeNull() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("ServletRegistrationBeans must not be null"); + bean.setServletRegistrationBeans(null); + } + + @Test + public void addServletRegistrationBeanMustNotBeNull() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("ServletRegistrationBeans must not be null"); + bean.addServletRegistrationBeans((ServletRegistrationBean[]) null); + } + + @Test + public void setServletRegistrationBeanReplacesValue() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean( + mockServletRegistation("a")); + bean.setServletRegistrationBeans(new LinkedHashSet( + Arrays.asList(mockServletRegistation("b")))); + bean.onStartup(this.servletContext); + verify(this.registration).addMappingForServletNames( + AbstractFilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "b"); + } + + @Test + public void modifyInitParameters() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + bean.addInitParameter("a", "b"); + bean.getInitParameters().put("a", "c"); + bean.onStartup(this.servletContext); + verify(this.registration).setInitParameters(Collections.singletonMap("a", "c")); + } + + @Test + public void setUrlPatternMustNotBeNull() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("UrlPatterns must not be null"); + bean.setUrlPatterns(null); + } + + @Test + public void addUrlPatternMustNotBeNull() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("UrlPatterns must not be null"); + bean.addUrlPatterns((String[]) null); + } + + @Test + public void setServletNameMustNotBeNull() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("ServletNames must not be null"); + bean.setServletNames(null); + } + + @Test + public void addServletNameMustNotBeNull() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("ServletNames must not be null"); + bean.addServletNames((String[]) null); + } + + @Test + public void withSpecificDispatcherTypes() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + bean.setDispatcherTypes(DispatcherType.INCLUDE, DispatcherType.FORWARD); + bean.onStartup(this.servletContext); + verify(this.registration).addMappingForUrlPatterns( + EnumSet.of(DispatcherType.INCLUDE, DispatcherType.FORWARD), false, "/*"); + } + + @Test + public void withSpecificDispatcherTypesEnumSet() throws Exception { + AbstractFilterRegistrationBean bean = createFilterRegistrationBean(); + EnumSet types = EnumSet.of(DispatcherType.INCLUDE, + DispatcherType.FORWARD); + bean.setDispatcherTypes(types); + bean.onStartup(this.servletContext); + verify(this.registration).addMappingForUrlPatterns(types, false, "/*"); + } + + protected abstract Filter getExpectedFilter(); + + protected abstract AbstractFilterRegistrationBean createFilterRegistrationBean( + ServletRegistrationBean... servletRegistrationBeans); + + protected final ServletRegistrationBean mockServletRegistation(String name) { + ServletRegistrationBean bean = new ServletRegistrationBean(); + bean.setName(name); + return bean; + } + +} diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBeanTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBeanTests.java new file mode 100644 index 0000000000..d7a4606325 --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/DelegatingFilterProxyRegistrationBeanTests.java @@ -0,0 +1,97 @@ +/* + * Copyright 2012-2015 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 javax.servlet.Filter; + +import org.junit.Test; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.filter.DelegatingFilterProxy; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.isA; + +/** + * Tests for {@link DelegatingFilterProxyRegistrationBean}. + * + * @author Phillip Webb + */ +public class DelegatingFilterProxyRegistrationBeanTests + extends AbstractFilterRegistrationBeanTests { + + private WebApplicationContext applicationContext = new GenericWebApplicationContext( + new MockServletContext());; + + @Test + public void targetBeanNameMustNotBeNull() throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("TargetBeanName must not be null or empty"); + new DelegatingFilterProxyRegistrationBean(null); + } + + @Test + public void targetBeanNameMustNotBeEmpty() throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("TargetBeanName must not be null or empty"); + new DelegatingFilterProxyRegistrationBean(""); + } + + @Test + public void nameDefaultsToTargetBeanName() throws Exception { + assertThat(new DelegatingFilterProxyRegistrationBean("myFilter") + .getOrDeduceName(null), equalTo("myFilter")); + } + + @Test + public void getFilterUsesDelegatingFilterProxy() throws Exception { + AbstractFilterRegistrationBean registrationBean = createFilterRegistrationBean(); + Filter filter = registrationBean.getFilter(); + assertThat(filter, instanceOf(DelegatingFilterProxy.class)); + assertThat(ReflectionTestUtils.getField(filter, "webApplicationContext"), + equalTo((Object) this.applicationContext)); + assertThat(ReflectionTestUtils.getField(filter, "targetBeanName"), + equalTo((Object) "mockFilter")); + } + + @Test + public void createServletRegistrationBeanMustNotBeNull() throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("ServletRegistrationBeans must not be null"); + new DelegatingFilterProxyRegistrationBean("mockFilter", + (ServletRegistrationBean[]) null); + } + + @Override + protected AbstractFilterRegistrationBean createFilterRegistrationBean( + ServletRegistrationBean... servletRegistrationBeans) { + DelegatingFilterProxyRegistrationBean bean = new DelegatingFilterProxyRegistrationBean( + "mockFilter", servletRegistrationBeans); + bean.setApplicationContext(this.applicationContext); + return bean; + } + + @Override + protected Filter getExpectedFilter() { + return isA(DelegatingFilterProxy.class); + } + +} 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 999a0d3173..c0dde15fde 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 @@ -29,13 +29,19 @@ import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import org.apache.struts.mock.MockHttpServletRequest; +import org.apache.struts.mock.MockHttpServletResponse; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InOrder; +import org.mockito.MockitoAnnotations; import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -52,6 +58,8 @@ import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.mock.web.MockFilterChain; +import org.springframework.mock.web.MockFilterConfig; import org.springframework.web.context.ServletContextAware; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.request.SessionScope; @@ -88,8 +96,12 @@ public class EmbeddedWebApplicationContextTests { private EmbeddedWebApplicationContext context; + @Captor + private ArgumentCaptor filterCaptor; + @Before public void setup() { + MockitoAnnotations.initMocks(this); this.context = new EmbeddedWebApplicationContext(); } @@ -302,9 +314,9 @@ public class EmbeddedWebApplicationContextTests { ordered.verify(escf.getServletContext()).addFilter("filterBean1", filter1); ordered.verify(escf.getServletContext()).addFilter("filterBean2", filter2); verify(escf.getRegisteredFilter(0).getRegistration()).addMappingForUrlPatterns( - FilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "/*"); + AbstractFilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "/*"); verify(escf.getRegisteredFilter(1).getRegistration()).addMappingForUrlPatterns( - FilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "/*"); + AbstractFilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "/*"); } @Test @@ -395,7 +407,7 @@ public class EmbeddedWebApplicationContextTests { } @Test - public void filterReegistrationBeansSkipsRegisteredFilters() throws Exception { + public void filterRegistrationBeansSkipsRegisteredFilters() throws Exception { addEmbeddedServletContainerFactoryBean(); Filter filter = mock(Filter.class); FilterRegistrationBean initializer = new FilterRegistrationBean(filter); @@ -408,6 +420,32 @@ public class EmbeddedWebApplicationContextTests { verify(servletContext, atMost(1)).addFilter(anyString(), (Filter) anyObject()); } + @Test + public void delegatingFilterProxyRegistrationBeansSkipsTargetBeanNames() + throws Exception { + addEmbeddedServletContainerFactoryBean(); + DelegatingFilterProxyRegistrationBean initializer = new DelegatingFilterProxyRegistrationBean( + "filterBean"); + this.context.registerBeanDefinition("initializerBean", + beanDefinition(initializer)); + BeanDefinition filterBeanDefinition = beanDefinition( + new IllegalStateException("Create FilterBean Failure")); + filterBeanDefinition.setLazyInit(true); + this.context.registerBeanDefinition("filterBean", filterBeanDefinition); + this.context.refresh(); + ServletContext servletContext = getEmbeddedServletContainerFactory() + .getServletContext(); + verify(servletContext, atMost(1)).addFilter(anyString(), + this.filterCaptor.capture()); + // Up to this point the filterBean should not have been created, calling + // the delegate proxy will trigger creation and an exception + this.thrown.expect(BeanCreationException.class); + this.thrown.expectMessage("Create FilterBean Failure"); + this.filterCaptor.getValue().init(new MockFilterConfig()); + this.filterCaptor.getValue().doFilter(new MockHttpServletRequest(), + new MockHttpServletResponse(), new MockFilterChain()); + } + @Test public void postProcessEmbeddedServletContainerFactory() throws Exception { RootBeanDefinition bd = new RootBeanDefinition( @@ -459,7 +497,6 @@ public class EmbeddedWebApplicationContextTests { this.context.close(); assertThat(validator.destroyed, is(true)); assertThat(validator.containerStoppedFirst, is(true)); - } private void addEmbeddedServletContainerFactoryBean() { @@ -482,6 +519,9 @@ public class EmbeddedWebApplicationContextTests { } public static T getBean(T object) { + if (object instanceof RuntimeException) { + throw (RuntimeException) object; + } return object; } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/FilterRegistrationBeanTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/FilterRegistrationBeanTests.java index 692c31a5ed..679d7f4927 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/FilterRegistrationBeanTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/FilterRegistrationBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2015 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,29 +16,11 @@ package org.springframework.boot.context.embedded; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; - -import javax.servlet.DispatcherType; import javax.servlet.Filter; -import javax.servlet.FilterRegistration; -import javax.servlet.ServletContext; -import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.times; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.verify; /** @@ -46,93 +28,18 @@ import static org.mockito.Mockito.verify; * * @author Phillip Webb */ -public class FilterRegistrationBeanTests { - - @Rule - public ExpectedException thrown = ExpectedException.none(); +public class FilterRegistrationBeanTests extends AbstractFilterRegistrationBeanTests { private final MockFilter filter = new MockFilter(); - @Mock - private ServletContext servletContext; - - @Mock - private FilterRegistration.Dynamic registration; - - @Before - public void setupMocks() { - MockitoAnnotations.initMocks(this); - given(this.servletContext.addFilter(anyString(), (Filter) anyObject())) - .willReturn(this.registration); - } - @Test - public void startupWithDefaults() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - bean.onStartup(this.servletContext); - verify(this.servletContext).addFilter("mockFilter", this.filter); - verify(this.registration).setAsyncSupported(true); - verify(this.registration).addMappingForUrlPatterns( - FilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "/*"); - } - - @Test - public void startupWithSpecifiedValues() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(); - bean.setName("test"); - bean.setFilter(this.filter); - bean.setAsyncSupported(false); - bean.setInitParameters(Collections.singletonMap("a", "b")); - bean.addInitParameter("c", "d"); - bean.setUrlPatterns(new LinkedHashSet(Arrays.asList("/a", "/b"))); - bean.addUrlPatterns("/c"); - bean.setServletNames(new LinkedHashSet(Arrays.asList("s1", "s2"))); - bean.addServletNames("s3"); - bean.setServletRegistrationBeans( - Collections.singleton(mockServletRegistation("s4"))); - bean.addServletRegistrationBeans(mockServletRegistation("s5")); - bean.setMatchAfter(true); - bean.onStartup(this.servletContext); - verify(this.servletContext).addFilter("test", this.filter); - verify(this.registration).setAsyncSupported(false); - Map expectedInitParameters = new HashMap(); - expectedInitParameters.put("a", "b"); - expectedInitParameters.put("c", "d"); - verify(this.registration).setInitParameters(expectedInitParameters); - verify(this.registration).addMappingForUrlPatterns( - FilterRegistrationBean.NON_ASYNC_DISPATCHER_TYPES, true, "/a", "/b", - "/c"); - verify(this.registration).addMappingForServletNames( - FilterRegistrationBean.NON_ASYNC_DISPATCHER_TYPES, true, "s4", "s5", "s1", - "s2", "s3"); - } - - @Test - public void specificName() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(); - bean.setName("specificName"); - bean.setFilter(this.filter); - bean.onStartup(this.servletContext); - verify(this.servletContext).addFilter("specificName", this.filter); - } - - @Test - public void deducedName() throws Exception { + public void setFilter() throws Exception { FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(this.filter); bean.onStartup(this.servletContext); verify(this.servletContext).addFilter("mockFilter", this.filter); } - @Test - public void disable() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(); - bean.setFilter(this.filter); - bean.setEnabled(false); - bean.onStartup(this.servletContext); - verify(this.servletContext, times(0)).addFilter("mockFilter", this.filter); - } - @Test public void setFilterMustNotBeNull() throws Exception { FilterRegistrationBean bean = new FilterRegistrationBean(); @@ -142,20 +49,12 @@ public class FilterRegistrationBeanTests { } @Test - public void createServletMustNotBeNull() throws Exception { + public void constructFilterMustNotBeNull() throws Exception { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("Filter must not be null"); new FilterRegistrationBean(null); } - @Test - public void setServletRegistrationBeanMustNotBeNull() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("ServletRegistrationBeans must not be null"); - bean.setServletRegistrationBeans(null); - } - @Test public void createServletRegistrationBeanMustNotBeNull() throws Exception { this.thrown.expect(IllegalArgumentException.class); @@ -163,88 +62,15 @@ public class FilterRegistrationBeanTests { new FilterRegistrationBean(this.filter, (ServletRegistrationBean[]) null); } - @Test - public void addServletRegistrationBeanMustNotBeNull() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("ServletRegistrationBeans must not be null"); - bean.addServletRegistrationBeans((ServletRegistrationBean[]) null); + @Override + protected AbstractFilterRegistrationBean createFilterRegistrationBean( + ServletRegistrationBean... servletRegistrationBeans) { + return new FilterRegistrationBean(this.filter, servletRegistrationBeans); } - @Test - public void setServletRegistrationBeanReplacesValue() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter, - mockServletRegistation("a")); - bean.setServletRegistrationBeans(new LinkedHashSet( - Arrays.asList(mockServletRegistation("b")))); - bean.onStartup(this.servletContext); - verify(this.registration).addMappingForServletNames( - FilterRegistrationBean.ASYNC_DISPATCHER_TYPES, false, "b"); + @Override + protected Filter getExpectedFilter() { + return eq(this.filter); } - @Test - public void modifyInitParameters() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - bean.addInitParameter("a", "b"); - bean.getInitParameters().put("a", "c"); - bean.onStartup(this.servletContext); - verify(this.registration).setInitParameters(Collections.singletonMap("a", "c")); - } - - @Test - public void setUrlPatternMustNotBeNull() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("UrlPatterns must not be null"); - bean.setUrlPatterns(null); - } - - @Test - public void addUrlPatternMustNotBeNull() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("UrlPatterns must not be null"); - bean.addUrlPatterns((String[]) null); - } - - @Test - public void setServletNameMustNotBeNull() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("ServletNames must not be null"); - bean.setServletNames(null); - } - - @Test - public void addServletNameMustNotBeNull() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - this.thrown.expect(IllegalArgumentException.class); - this.thrown.expectMessage("ServletNames must not be null"); - bean.addServletNames((String[]) null); - } - - @Test - public void withSpecificDispatcherTypes() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - bean.setDispatcherTypes(DispatcherType.INCLUDE, DispatcherType.FORWARD); - bean.onStartup(this.servletContext); - verify(this.registration).addMappingForUrlPatterns( - EnumSet.of(DispatcherType.INCLUDE, DispatcherType.FORWARD), false, "/*"); - } - - @Test - public void withSpecificDispatcherTypesEnumSet() throws Exception { - FilterRegistrationBean bean = new FilterRegistrationBean(this.filter); - EnumSet types = EnumSet.of(DispatcherType.INCLUDE, - DispatcherType.FORWARD); - bean.setDispatcherTypes(types); - bean.onStartup(this.servletContext); - verify(this.registration).addMappingForUrlPatterns(types, false, "/*"); - } - - private ServletRegistrationBean mockServletRegistation(String name) { - ServletRegistrationBean bean = new ServletRegistrationBean(); - bean.setName(name); - return bean; - } }