Skip to content

Commit

Permalink
Merge branch '2.1.x'
Browse files Browse the repository at this point in the history
Closes gh-18912
  • Loading branch information
wilkinsona committed Nov 7, 2019
2 parents 93b7baf + d1ead88 commit dd4377e
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 54 deletions.
Expand Up @@ -20,8 +20,8 @@
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
Expand Down Expand Up @@ -68,15 +68,15 @@ protected final Map<String, String> extractInitParameters(Map<String, Object> at
return initParameters;
}

void handle(ScannedGenericBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
void handle(AnnotatedBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
Map<String, Object> attributes = beanDefinition.getMetadata()
.getAnnotationAttributes(this.annotationType.getName());
if (attributes != null) {
doHandle(attributes, beanDefinition, registry);
}
}

protected abstract void doHandle(Map<String, Object> attributes, ScannedGenericBeanDefinition beanDefinition,
protected abstract void doHandle(Map<String, Object> attributes, AnnotatedBeanDefinition beanDefinition,
BeanDefinitionRegistry registry);

}
Expand Up @@ -22,14 +22,14 @@
import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.web.context.WebApplicationContext;

/**
Expand Down Expand Up @@ -72,9 +72,9 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

private void scanPackage(ClassPathScanningCandidateComponentProvider componentProvider, String packageToScan) {
for (BeanDefinition candidate : componentProvider.findCandidateComponents(packageToScan)) {
if (candidate instanceof ScannedGenericBeanDefinition) {
if (candidate instanceof AnnotatedBeanDefinition) {
for (ServletComponentHandler handler : HANDLERS) {
handler.handle(((ScannedGenericBeanDefinition) candidate),
handler.handle(((AnnotatedBeanDefinition) candidate),
(BeanDefinitionRegistry) this.applicationContext);
}
}
Expand Down
Expand Up @@ -23,10 +23,10 @@
import javax.servlet.DispatcherType;
import javax.servlet.annotation.WebFilter;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.util.StringUtils;

/**
Expand All @@ -41,7 +41,7 @@ class WebFilterHandler extends ServletComponentHandler {
}

@Override
public void doHandle(Map<String, Object> attributes, ScannedGenericBeanDefinition beanDefinition,
public void doHandle(Map<String, Object> attributes, AnnotatedBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterRegistrationBean.class);
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
Expand Down
Expand Up @@ -20,9 +20,9 @@

import javax.servlet.annotation.WebListener;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;

/**
* Handler for {@link WebListener @WebListener}-annotated classes.
Expand All @@ -36,7 +36,7 @@ class WebListenerHandler extends ServletComponentHandler {
}

@Override
protected void doHandle(Map<String, Object> attributes, ScannedGenericBeanDefinition beanDefinition,
protected void doHandle(Map<String, Object> attributes, AnnotatedBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ServletListenerRegistrationBean.class);
builder.addPropertyValue("listener", beanDefinition);
Expand Down
Expand Up @@ -22,10 +22,10 @@
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.util.StringUtils;

/**
Expand All @@ -40,7 +40,7 @@ class WebServletHandler extends ServletComponentHandler {
}

@Override
public void doHandle(Map<String, Object> attributes, ScannedGenericBeanDefinition beanDefinition,
public void doHandle(Map<String, Object> attributes, AnnotatedBeanDefinition beanDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ServletRegistrationBean.class);
builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
Expand All @@ -59,7 +59,7 @@ private String determineName(Map<String, Object> attributes, BeanDefinition bean
: beanDefinition.getBeanClassName());
}

private MultipartConfigElement determineMultipartConfig(ScannedGenericBeanDefinition beanDefinition) {
private MultipartConfigElement determineMultipartConfig(AnnotatedBeanDefinition beanDefinition) {
Map<String, Object> attributes = beanDefinition.getMetadata()
.getAnnotationAttributes(MultipartConfig.class.getName());
if (attributes == null) {
Expand Down
Expand Up @@ -16,12 +16,22 @@

package org.springframework.boot.web.servlet;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Map;
import java.util.Properties;

import javax.servlet.MultipartConfigElement;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebListener;
import javax.servlet.annotation.WebServlet;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
Expand Down Expand Up @@ -60,6 +70,22 @@ void componentsAreRegistered() {
assertThat(response).isEqualTo("alpha bravo");
}

@Test
void indexedComponentsAreRegistered(@TempDir File temp) throws IOException {
writeIndex(temp);
this.context = new AnnotationConfigServletWebServerApplicationContext();
try (URLClassLoader classLoader = new URLClassLoader(new URL[] { temp.toURI().toURL() },
getClass().getClassLoader())) {
this.context.setClassLoader(classLoader);
this.context.register(TestConfiguration.class);
new ServerPortInfoApplicationContextInitializer().initialize(this.context);
this.context.refresh();
String port = this.context.getEnvironment().getProperty("local.server.port");
String response = new RestTemplate().getForObject("http://localhost:" + port + "/test", String.class);
assertThat(response).isEqualTo("alpha bravo");
}
}

@Test
void multipartConfigIsHonoured() {
this.context = new AnnotationConfigServletWebServerApplicationContext();
Expand All @@ -78,6 +104,20 @@ void multipartConfigIsHonoured() {
assertThat(multipartConfig.getFileSizeThreshold()).isEqualTo(512);
}

private void writeIndex(File temp) throws IOException {
File metaInf = new File(temp, "META-INF");
metaInf.mkdirs();
Properties index = new Properties();
index.setProperty("org.springframework.boot.web.servlet.testcomponents.TestFilter", WebFilter.class.getName());
index.setProperty("org.springframework.boot.web.servlet.testcomponents.TestListener",
WebListener.class.getName());
index.setProperty("org.springframework.boot.web.servlet.testcomponents.TestServlet",
WebServlet.class.getName());
try (FileWriter writer = new FileWriter(new File(metaInf, "spring.components"))) {
index.store(writer, null);
}
}

@Configuration(proxyBeanMethods = false)
@ServletComponentScan(basePackages = "org.springframework.boot.web.servlet.testcomponents")
static class TestConfiguration {
Expand Down
Expand Up @@ -33,13 +33,15 @@
import org.junit.jupiter.api.Test;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;

/**
* Tests for {@link WebFilterHandler}
Expand All @@ -55,9 +57,8 @@ class WebFilterHandlerTests {
@SuppressWarnings("unchecked")
@Test
void defaultFilterConfiguration() throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(DefaultConfigurationFilter.class.getName()));
this.handler.handle(scanned, this.registry);
AnnotatedBeanDefinition definition = createBeanDefinition(DefaultConfigurationFilter.class);
this.handler.handle(definition, this.registry);
BeanDefinition filterRegistrationBean = this.registry
.getBeanDefinition(DefaultConfigurationFilter.class.getName());
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
Expand All @@ -68,30 +69,29 @@ void defaultFilterConfiguration() throws IOException {
assertThat((String[]) propertyValues.get("servletNames")).isEmpty();
assertThat((String[]) propertyValues.get("urlPatterns")).isEmpty();
assertThat(propertyValues.get("name")).isEqualTo(DefaultConfigurationFilter.class.getName());
assertThat(propertyValues.get("filter")).isEqualTo(scanned);
assertThat(propertyValues.get("filter")).isEqualTo(definition);
}

@Test
void filterWithCustomName() throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(CustomNameFilter.class.getName()));
this.handler.handle(scanned, this.registry);
AnnotatedBeanDefinition definition = createBeanDefinition(CustomNameFilter.class);
this.handler.handle(definition, this.registry);
BeanDefinition filterRegistrationBean = this.registry.getBeanDefinition("custom");
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat(propertyValues.get("name")).isEqualTo("custom");
}

@Test
void asyncSupported() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(AsyncSupportedFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(AsyncSupportedFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat(propertyValues.get("asyncSupported")).isEqualTo(true);
}

@Test
@SuppressWarnings("unchecked")
void dispatcherTypes() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(DispatcherTypesFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(DispatcherTypesFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((Set<DispatcherType>) propertyValues.get("dispatcherTypes")).containsExactly(DispatcherType.FORWARD,
DispatcherType.INCLUDE, DispatcherType.REQUEST);
Expand All @@ -100,43 +100,50 @@ void dispatcherTypes() throws IOException {
@SuppressWarnings("unchecked")
@Test
void initParameters() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(InitParametersFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(InitParametersFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((Map<String, String>) propertyValues.get("initParameters")).containsEntry("a", "alpha")
.containsEntry("b", "bravo");
}

@Test
void servletNames() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(ServletNamesFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(ServletNamesFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((String[]) propertyValues.get("servletNames")).contains("alpha", "bravo");
}

@Test
void urlPatterns() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(UrlPatternsFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(UrlPatternsFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((String[]) propertyValues.get("urlPatterns")).contains("alpha", "bravo");
}

@Test
void urlPatternsFromValue() throws IOException {
BeanDefinition filterRegistrationBean = getBeanDefinition(UrlPatternsFromValueFilter.class);
BeanDefinition filterRegistrationBean = handleBeanDefinitionForClass(UrlPatternsFromValueFilter.class);
MutablePropertyValues propertyValues = filterRegistrationBean.getPropertyValues();
assertThat((String[]) propertyValues.get("urlPatterns")).contains("alpha", "bravo");
}

@Test
void urlPatternsDeclaredTwice() throws IOException {
assertThatIllegalStateException().isThrownBy(() -> getBeanDefinition(UrlPatternsDeclaredTwiceFilter.class))
assertThatIllegalStateException()
.isThrownBy(() -> handleBeanDefinitionForClass(UrlPatternsDeclaredTwiceFilter.class))
.withMessageContaining("The urlPatterns and value attributes are mutually exclusive.");
}

BeanDefinition getBeanDefinition(Class<?> filterClass) throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(filterClass.getName()));
this.handler.handle(scanned, this.registry);
private AnnotatedBeanDefinition createBeanDefinition(Class<?> filterClass) throws IOException {
AnnotatedBeanDefinition definition = mock(AnnotatedBeanDefinition.class);
given(definition.getBeanClassName()).willReturn(filterClass.getName());
given(definition.getMetadata()).willReturn(
new SimpleMetadataReaderFactory().getMetadataReader(filterClass.getName()).getAnnotationMetadata());
return definition;
}

private BeanDefinition handleBeanDefinitionForClass(Class<?> filterClass) throws IOException {
this.handler.handle(createBeanDefinition(filterClass), this.registry);
return this.registry.getBeanDefinition(filterClass.getName());
}

Expand Down
Expand Up @@ -24,10 +24,13 @@

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;

import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;

/**
* Tests for {@link WebListenerHandler}.
*
Expand All @@ -41,9 +44,11 @@ class WebListenerHandlerTests {

@Test
void listener() throws IOException {
ScannedGenericBeanDefinition scanned = new ScannedGenericBeanDefinition(
new SimpleMetadataReaderFactory().getMetadataReader(TestListener.class.getName()));
this.handler.handle(scanned, this.registry);
AnnotatedBeanDefinition definition = mock(AnnotatedBeanDefinition.class);
given(definition.getBeanClassName()).willReturn(TestListener.class.getName());
given(definition.getMetadata()).willReturn(new SimpleMetadataReaderFactory()
.getMetadataReader(TestListener.class.getName()).getAnnotationMetadata());
this.handler.handle(definition, this.registry);
this.registry.getBeanDefinition(TestListener.class.getName());
}

Expand Down

0 comments on commit dd4377e

Please sign in to comment.