Merge branch '2.0.x'
This commit is contained in:
		
						commit
						727e9c6b0f
					
				|  | @ -26,7 +26,6 @@ import org.springframework.core.env.MutablePropertySources; | |||
| import org.springframework.core.env.PropertySource; | ||||
| import org.springframework.core.env.StandardEnvironment; | ||||
| import org.springframework.util.ClassUtils; | ||||
| import org.springframework.web.context.ConfigurableWebEnvironment; | ||||
| import org.springframework.web.context.support.StandardServletEnvironment; | ||||
| 
 | ||||
| /** | ||||
|  | @ -34,6 +33,7 @@ import org.springframework.web.context.support.StandardServletEnvironment; | |||
|  * | ||||
|  * @author Ethan Rubinson | ||||
|  * @author Andy Wilkinson | ||||
|  * @author Madhura Bhave | ||||
|  */ | ||||
| final class EnvironmentConverter { | ||||
| 
 | ||||
|  | @ -61,46 +61,44 @@ final class EnvironmentConverter { | |||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Converts the given {@code environment} to a {@link StandardEnvironment}. If the | ||||
| 	 * environment is already a {@code StandardEnvironment} and is not a | ||||
| 	 * {@link ConfigurableWebEnvironment} no conversion is performed and it is returned | ||||
| 	 * unchanged. | ||||
| 	 * Converts the given {@code environment} to the given {@link StandardEnvironment} | ||||
| 	 * type. If the environment is already of the same type, no conversion is performed | ||||
| 	 * and it is returned unchanged. | ||||
| 	 * @param environment the Environment to convert | ||||
| 	 * @param conversionType the type to convert the Environment to | ||||
| 	 * @return the converted Environment | ||||
| 	 */ | ||||
| 	StandardEnvironment convertToStandardEnvironmentIfNecessary( | ||||
| 			ConfigurableEnvironment environment) { | ||||
| 		if (environment instanceof StandardEnvironment | ||||
| 				&& !isWebEnvironment(environment, this.classLoader)) { | ||||
| 	StandardEnvironment convertEnvironmentIfNecessary(ConfigurableEnvironment environment, | ||||
| 			Class<? extends StandardEnvironment> conversionType) { | ||||
| 		if (conversionType.equals(environment.getClass())) { | ||||
| 			return (StandardEnvironment) environment; | ||||
| 		} | ||||
| 		return convertToStandardEnvironment(environment); | ||||
| 		return convertEnvironment(environment, conversionType); | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean isWebEnvironment(ConfigurableEnvironment environment, | ||||
| 			ClassLoader classLoader) { | ||||
| 		try { | ||||
| 			Class<?> webEnvironmentClass = ClassUtils | ||||
| 					.forName(CONFIGURABLE_WEB_ENVIRONMENT_CLASS, classLoader); | ||||
| 			return (webEnvironmentClass.isInstance(environment)); | ||||
| 		} | ||||
| 		catch (Throwable ex) { | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private StandardEnvironment convertToStandardEnvironment( | ||||
| 			ConfigurableEnvironment environment) { | ||||
| 		StandardEnvironment result = new StandardEnvironment(); | ||||
| 	private StandardEnvironment convertEnvironment(ConfigurableEnvironment environment, | ||||
| 			Class<? extends StandardEnvironment> conversionType) { | ||||
| 		StandardEnvironment result = createEnvironment(conversionType); | ||||
| 		result.setActiveProfiles(environment.getActiveProfiles()); | ||||
| 		result.setConversionService(environment.getConversionService()); | ||||
| 		copyNonServletPropertySources(environment, result); | ||||
| 		copyPropertySources(environment, result); | ||||
| 		return result; | ||||
| 	} | ||||
| 
 | ||||
| 	private void copyNonServletPropertySources(ConfigurableEnvironment source, | ||||
| 	private StandardEnvironment createEnvironment( | ||||
| 			Class<? extends StandardEnvironment> conversionType) { | ||||
| 		try { | ||||
| 			return conversionType.newInstance(); | ||||
| 		} | ||||
| 		catch (Exception ex) { | ||||
| 			return new StandardEnvironment(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void copyPropertySources(ConfigurableEnvironment source, | ||||
| 			StandardEnvironment target) { | ||||
| 		removeAllPropertySources(target.getPropertySources()); | ||||
| 		removePropertySources(target.getPropertySources(), | ||||
| 				isServletEnvironment(target.getClass(), this.classLoader)); | ||||
| 		for (PropertySource<?> propertySource : source.getPropertySources()) { | ||||
| 			if (!SERVLET_ENVIRONMENT_SOURCE_NAMES.contains(propertySource.getName())) { | ||||
| 				target.getPropertySources().addLast(propertySource); | ||||
|  | @ -108,13 +106,31 @@ final class EnvironmentConverter { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void removeAllPropertySources(MutablePropertySources propertySources) { | ||||
| 	private boolean isServletEnvironment(Class<?> conversionType, | ||||
| 			ClassLoader classLoader) { | ||||
| 		try { | ||||
| 			Class<?> webEnvironmentClass = ClassUtils | ||||
| 					.forName(CONFIGURABLE_WEB_ENVIRONMENT_CLASS, classLoader); | ||||
| 			return webEnvironmentClass.isAssignableFrom(conversionType); | ||||
| 		} | ||||
| 		catch (Throwable ex) { | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	private void removePropertySources(MutablePropertySources propertySources, | ||||
| 			boolean isServletEnvironment) { | ||||
| 		Set<String> names = new HashSet<>(); | ||||
| 		for (PropertySource<?> propertySource : propertySources) { | ||||
| 			names.add(propertySource.getName()); | ||||
| 		} | ||||
| 		for (String name : names) { | ||||
| 			propertySources.remove(name); | ||||
| 			if (!isServletEnvironment) { | ||||
| 				propertySources.remove(name); | ||||
| 			} | ||||
| 			else if (!SERVLET_ENVIRONMENT_SOURCE_NAMES.contains(name)) { | ||||
| 				propertySources.remove(name); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -45,6 +45,7 @@ import org.springframework.boot.Banner.Mode; | |||
| import org.springframework.boot.context.properties.bind.Bindable; | ||||
| import org.springframework.boot.context.properties.bind.Binder; | ||||
| import org.springframework.boot.context.properties.source.ConfigurationPropertySources; | ||||
| import org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment; | ||||
| import org.springframework.context.ApplicationContext; | ||||
| import org.springframework.context.ApplicationContextInitializer; | ||||
| import org.springframework.context.ApplicationListener; | ||||
|  | @ -239,6 +240,8 @@ public class SpringApplication { | |||
| 
 | ||||
| 	private boolean allowBeanDefinitionOverriding; | ||||
| 
 | ||||
| 	private boolean isCustomEnvironment = false; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Create a new {@link SpringApplication} instance. The application context will load | ||||
| 	 * beans from the specified primary sources (see {@link SpringApplication class-level} | ||||
|  | @ -364,14 +367,24 @@ public class SpringApplication { | |||
| 		configureEnvironment(environment, applicationArguments.getSourceArgs()); | ||||
| 		listeners.environmentPrepared(environment); | ||||
| 		bindToSpringApplication(environment); | ||||
| 		if (this.webApplicationType == WebApplicationType.NONE) { | ||||
| 		if (!this.isCustomEnvironment) { | ||||
| 			environment = new EnvironmentConverter(getClassLoader()) | ||||
| 					.convertToStandardEnvironmentIfNecessary(environment); | ||||
| 					.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); | ||||
| 		} | ||||
| 		ConfigurationPropertySources.attach(environment); | ||||
| 		return environment; | ||||
| 	} | ||||
| 
 | ||||
| 	private Class<? extends StandardEnvironment> deduceEnvironmentClass() { | ||||
| 		if (this.webApplicationType == WebApplicationType.SERVLET) { | ||||
| 			return StandardServletEnvironment.class; | ||||
| 		} | ||||
| 		if (this.webApplicationType == WebApplicationType.REACTIVE) { | ||||
| 			return StandardReactiveWebEnvironment.class; | ||||
| 		} | ||||
| 		return StandardEnvironment.class; | ||||
| 	} | ||||
| 
 | ||||
| 	private void prepareContext(ConfigurableApplicationContext context, | ||||
| 			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, | ||||
| 			ApplicationArguments applicationArguments, Banner printedBanner) { | ||||
|  | @ -469,6 +482,9 @@ public class SpringApplication { | |||
| 		if (this.webApplicationType == WebApplicationType.SERVLET) { | ||||
| 			return new StandardServletEnvironment(); | ||||
| 		} | ||||
| 		if (this.webApplicationType == WebApplicationType.REACTIVE) { | ||||
| 			return new StandardReactiveWebEnvironment(); | ||||
| 		} | ||||
| 		return new StandardEnvironment(); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1071,6 +1087,7 @@ public class SpringApplication { | |||
| 	 * @param environment the environment | ||||
| 	 */ | ||||
| 	public void setEnvironment(ConfigurableEnvironment environment) { | ||||
| 		this.isCustomEnvironment = true; | ||||
| 		this.environment = environment; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -16,10 +16,14 @@ | |||
| 
 | ||||
| package org.springframework.boot; | ||||
| 
 | ||||
| import java.util.HashSet; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import org.springframework.core.convert.support.ConfigurableConversionService; | ||||
| import org.springframework.core.env.AbstractEnvironment; | ||||
| import org.springframework.core.env.PropertySource; | ||||
| import org.springframework.core.env.StandardEnvironment; | ||||
| import org.springframework.mock.env.MockEnvironment; | ||||
| import org.springframework.web.context.support.StandardServletEnvironment; | ||||
|  | @ -32,6 +36,7 @@ import static org.mockito.Mockito.mock; | |||
|  * | ||||
|  * @author Ethan Rubinson | ||||
|  * @author Andy Wilkinson | ||||
|  * @author Madhura Bhave | ||||
|  */ | ||||
| public class EnvironmentConverterTests { | ||||
| 
 | ||||
|  | @ -43,7 +48,8 @@ public class EnvironmentConverterTests { | |||
| 		AbstractEnvironment originalEnvironment = new MockEnvironment(); | ||||
| 		originalEnvironment.setActiveProfiles("activeProfile1", "activeProfile2"); | ||||
| 		StandardEnvironment convertedEnvironment = this.environmentConverter | ||||
| 				.convertToStandardEnvironmentIfNecessary(originalEnvironment); | ||||
| 				.convertEnvironmentIfNecessary(originalEnvironment, | ||||
| 						StandardEnvironment.class); | ||||
| 		assertThat(convertedEnvironment.getActiveProfiles()) | ||||
| 				.containsExactly("activeProfile1", "activeProfile2"); | ||||
| 	} | ||||
|  | @ -55,16 +61,18 @@ public class EnvironmentConverterTests { | |||
| 				ConfigurableConversionService.class); | ||||
| 		originalEnvironment.setConversionService(conversionService); | ||||
| 		StandardEnvironment convertedEnvironment = this.environmentConverter | ||||
| 				.convertToStandardEnvironmentIfNecessary(originalEnvironment); | ||||
| 				.convertEnvironmentIfNecessary(originalEnvironment, | ||||
| 						StandardEnvironment.class); | ||||
| 		assertThat(convertedEnvironment.getConversionService()) | ||||
| 				.isEqualTo(conversionService); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void standardEnvironmentIsReturnedUnconverted() { | ||||
| 	public void envClassSameShouldReturnEnvironmentUnconverted() { | ||||
| 		StandardEnvironment standardEnvironment = new StandardEnvironment(); | ||||
| 		StandardEnvironment convertedEnvironment = this.environmentConverter | ||||
| 				.convertToStandardEnvironmentIfNecessary(standardEnvironment); | ||||
| 				.convertEnvironmentIfNecessary(standardEnvironment, | ||||
| 						StandardEnvironment.class); | ||||
| 		assertThat(convertedEnvironment).isSameAs(standardEnvironment); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -72,8 +80,53 @@ public class EnvironmentConverterTests { | |||
| 	public void standardServletEnvironmentIsConverted() { | ||||
| 		StandardServletEnvironment standardServletEnvironment = new StandardServletEnvironment(); | ||||
| 		StandardEnvironment convertedEnvironment = this.environmentConverter | ||||
| 				.convertToStandardEnvironmentIfNecessary(standardServletEnvironment); | ||||
| 				.convertEnvironmentIfNecessary(standardServletEnvironment, | ||||
| 						StandardEnvironment.class); | ||||
| 		assertThat(convertedEnvironment).isNotSameAs(standardServletEnvironment); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void servletPropertySourcesAreNotCopiedOverIfNotWebEnvironment() { | ||||
| 		StandardServletEnvironment standardServletEnvironment = new StandardServletEnvironment(); | ||||
| 		StandardEnvironment convertedEnvironment = this.environmentConverter | ||||
| 				.convertEnvironmentIfNecessary(standardServletEnvironment, | ||||
| 						StandardEnvironment.class); | ||||
| 		assertThat(convertedEnvironment).isNotSameAs(standardServletEnvironment); | ||||
| 		Set<String> names = new HashSet<>(); | ||||
| 		for (PropertySource<?> propertySource : convertedEnvironment | ||||
| 				.getPropertySources()) { | ||||
| 			names.add(propertySource.getName()); | ||||
| 		} | ||||
| 		assertThat(names).doesNotContain( | ||||
| 				StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, | ||||
| 				StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, | ||||
| 				StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void envClassSameShouldReturnEnvironmentUnconvertedEvenForWeb() { | ||||
| 		StandardServletEnvironment standardServletEnvironment = new StandardServletEnvironment(); | ||||
| 		StandardEnvironment convertedEnvironment = this.environmentConverter | ||||
| 				.convertEnvironmentIfNecessary(standardServletEnvironment, | ||||
| 						StandardServletEnvironment.class); | ||||
| 		assertThat(convertedEnvironment).isSameAs(standardServletEnvironment); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void servletPropertySourcesArePresentWhenTypeToConvertIsWeb() { | ||||
| 		StandardEnvironment standardEnvironment = new StandardEnvironment(); | ||||
| 		StandardEnvironment convertedEnvironment = this.environmentConverter | ||||
| 				.convertEnvironmentIfNecessary(standardEnvironment, | ||||
| 						StandardServletEnvironment.class); | ||||
| 		assertThat(convertedEnvironment).isNotSameAs(standardEnvironment); | ||||
| 		Set<String> names = new HashSet<>(); | ||||
| 		for (PropertySource<?> propertySource : convertedEnvironment | ||||
| 				.getPropertySources()) { | ||||
| 			names.add(propertySource.getName()); | ||||
| 		} | ||||
| 		assertThat(names).contains( | ||||
| 				StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, | ||||
| 				StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -61,6 +61,7 @@ import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory | |||
| import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; | ||||
| import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext; | ||||
| import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext; | ||||
| import org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment; | ||||
| import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; | ||||
| import org.springframework.context.ApplicationContext; | ||||
| import org.springframework.context.ApplicationContextAware; | ||||
|  | @ -415,6 +416,25 @@ public class SpringApplicationTests { | |||
| 				.isInstanceOf(AnnotationConfigReactiveWebServerApplicationContext.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void environmentForWeb() { | ||||
| 		SpringApplication application = new SpringApplication(ExampleWebConfig.class); | ||||
| 		application.setWebApplicationType(WebApplicationType.SERVLET); | ||||
| 		this.context = application.run(); | ||||
| 		assertThat(this.context.getEnvironment()) | ||||
| 				.isInstanceOf(StandardServletEnvironment.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void environmentForReactiveWeb() { | ||||
| 		SpringApplication application = new SpringApplication( | ||||
| 				ExampleReactiveWebConfig.class); | ||||
| 		application.setWebApplicationType(WebApplicationType.REACTIVE); | ||||
| 		this.context = application.run(); | ||||
| 		assertThat(this.context.getEnvironment()) | ||||
| 				.isInstanceOf(StandardReactiveWebEnvironment.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void customEnvironment() { | ||||
| 		TestSpringApplication application = new TestSpringApplication( | ||||
|  | @ -1100,6 +1120,35 @@ public class SpringApplicationTests { | |||
| 				.isNotInstanceOfAny(ConfigurableWebEnvironment.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void webApplicationConfiguredViaAPropertyHasTheCorrectTypeOfContextAndEnvironment() { | ||||
| 		ConfigurableApplicationContext context = new SpringApplication( | ||||
| 				ExampleWebConfig.class).run("--spring.main.web-application-type=servlet"); | ||||
| 		assertThat(context).isInstanceOfAny(WebApplicationContext.class); | ||||
| 		assertThat(context.getEnvironment()) | ||||
| 				.isInstanceOfAny(StandardServletEnvironment.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void reactiveApplicationConfiguredViaAPropertyHasTheCorrectTypeOfContextAndEnvironment() { | ||||
| 		ConfigurableApplicationContext context = new SpringApplication( | ||||
| 				ExampleReactiveWebConfig.class) | ||||
| 						.run("--spring.main.web-application-type=reactive"); | ||||
| 		assertThat(context).isInstanceOfAny(ReactiveWebApplicationContext.class); | ||||
| 		assertThat(context.getEnvironment()) | ||||
| 				.isInstanceOfAny(StandardReactiveWebEnvironment.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void environmentIsConvertedIfTypeDoesNotMatch() { | ||||
| 		ConfigurableApplicationContext context = new SpringApplication( | ||||
| 				ExampleReactiveWebConfig.class) | ||||
| 						.run("--spring.profiles.active=withwebapplicationtype"); | ||||
| 		assertThat(context).isInstanceOfAny(ReactiveWebApplicationContext.class); | ||||
| 		assertThat(context.getEnvironment()) | ||||
| 				.isInstanceOfAny(StandardReactiveWebEnvironment.class); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void failureResultsInSingleStackTrace() throws Exception { | ||||
| 		ThreadGroup group = new ThreadGroup("main"); | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| spring.main.web-application-type: reactive | ||||
		Loading…
	
		Reference in New Issue