diff --git a/spring-boot/src/main/java/org/springframework/boot/EnvironmentConverter.java b/spring-boot/src/main/java/org/springframework/boot/EnvironmentConverter.java new file mode 100644 index 0000000000..8501759b41 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/EnvironmentConverter.java @@ -0,0 +1,122 @@ +/* + * Copyright 2012-2017 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; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +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; + +/** + * Utility class for converting one type of {@link Environment} to another. + * + * @author Ethan Rubinson + * @author Andy Wilkinson + */ +final class EnvironmentConverter { + + private static final String CONFIGURABLE_WEB_ENVIRONMENT_CLASS = "org.springframework.web.context.ConfigurableWebEnvironment"; + + private static final Set SERVLET_ENVIRONMENT_SOURCE_NAMES; + + static { + final Set names = new HashSet(); + names.add(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME); + names.add(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME); + names.add(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME); + SERVLET_ENVIRONMENT_SOURCE_NAMES = Collections.unmodifiableSet(names); + } + + private final ClassLoader classLoader; + + /** + * Creates a new {@link EnvironmentConverter} that will use the given + * {@code classLoader} during conversion. + * @param classLoader the class loader to use + */ + EnvironmentConverter(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** + * 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. + * + * @param environment The Environment to convert + * @return The converted Environment + */ + StandardEnvironment convertToStandardEnvironmentIfNecessary( + ConfigurableEnvironment environment) { + if (environment instanceof StandardEnvironment + && !isWebEnvironment(environment, this.classLoader)) { + return (StandardEnvironment) environment; + } + return convertToStandardEnvironment(environment); + } + + 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(); + result.setActiveProfiles(environment.getActiveProfiles()); + result.setConversionService(environment.getConversionService()); + copyNonServletPropertySources(environment, result); + return result; + } + + private void copyNonServletPropertySources(ConfigurableEnvironment source, + StandardEnvironment target) { + removeAllPropertySources(target.getPropertySources()); + for (PropertySource propertySource : source.getPropertySources()) { + if (!SERVLET_ENVIRONMENT_SOURCE_NAMES.contains(propertySource.getName())) { + target.getPropertySources().addLast(propertySource); + } + } + } + + private void removeAllPropertySources(MutablePropertySources propertySources) { + Set names = new HashSet(); + for (PropertySource propertySource : propertySources) { + names.add(propertySource.getName()); + } + for (String name : names) { + propertySources.remove(name); + } + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index a7234a97ef..eb33939e4f 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -140,6 +140,7 @@ import org.springframework.web.context.support.StandardServletEnvironment; * @author Jeremy Rickard * @author Craig Burke * @author Michael Simons + * @author Ethan Rubinson * @see #run(Object, String[]) * @see #run(Object[], String[]) * @see #SpringApplication(Object...) @@ -173,20 +174,8 @@ public class SpringApplication { */ public static final String BANNER_LOCATION_PROPERTY = SpringApplicationBannerPrinter.BANNER_LOCATION_PROPERTY; - private static final String CONFIGURABLE_WEB_ENVIRONMENT_CLASS = "org.springframework.web.context.ConfigurableWebEnvironment"; - private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless"; - private static final Set SERVLET_ENVIRONMENT_SOURCE_NAMES; - - static { - Set names = new HashSet(); - names.add(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME); - names.add(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME); - names.add(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME); - SERVLET_ENVIRONMENT_SOURCE_NAMES = Collections.unmodifiableSet(names); - } - private static final Log logger = LogFactory.getLog(SpringApplication.class); private final Set sources = new LinkedHashSet(); @@ -334,8 +323,9 @@ public class SpringApplication { ConfigurableEnvironment environment = getOrCreateEnvironment(); configureEnvironment(environment, applicationArguments.getSourceArgs()); listeners.environmentPrepared(environment); - if (isWebEnvironment(environment) && !this.webEnvironment) { - environment = convertToStandardEnvironment(environment); + if (!this.webEnvironment) { + environment = new EnvironmentConverter(getClassLoader()) + .convertToStandardEnvironmentIfNecessary(environment); } return environment; } @@ -454,40 +444,6 @@ public class SpringApplication { configureProfiles(environment, args); } - private boolean isWebEnvironment(ConfigurableEnvironment environment) { - try { - Class webEnvironmentClass = ClassUtils - .forName(CONFIGURABLE_WEB_ENVIRONMENT_CLASS, getClassLoader()); - return (webEnvironmentClass.isInstance(environment)); - } - catch (Throwable ex) { - return false; - } - } - - private ConfigurableEnvironment convertToStandardEnvironment( - ConfigurableEnvironment environment) { - StandardEnvironment result = new StandardEnvironment(); - removeAllPropertySources(result.getPropertySources()); - result.setActiveProfiles(environment.getActiveProfiles()); - for (PropertySource propertySource : environment.getPropertySources()) { - if (!SERVLET_ENVIRONMENT_SOURCE_NAMES.contains(propertySource.getName())) { - result.getPropertySources().addLast(propertySource); - } - } - return result; - } - - private void removeAllPropertySources(MutablePropertySources propertySources) { - Set names = new HashSet(); - for (PropertySource propertySource : propertySources) { - names.add(propertySource.getName()); - } - for (String name : names) { - propertySources.remove(name); - } - } - /** * Add, remove or re-order any {@link PropertySource}s in this application's * environment. diff --git a/spring-boot/src/test/java/org/springframework/boot/EnvironmentConverterTests.java b/spring-boot/src/test/java/org/springframework/boot/EnvironmentConverterTests.java new file mode 100644 index 0000000000..d65ef80211 --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/EnvironmentConverterTests.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012-2017 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; + +import org.junit.Test; + +import org.springframework.core.convert.support.ConfigurableConversionService; +import org.springframework.core.env.AbstractEnvironment; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.mock.env.MockEnvironment; +import org.springframework.web.context.support.StandardServletEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link EnvironmentConverter}. + * + * @author Ethan Rubinson + * @author Andy Wilkinson + */ +public class EnvironmentConverterTests { + + private final EnvironmentConverter environmentConverter = new EnvironmentConverter( + getClass().getClassLoader()); + + @Test + public void convertedEnvironmentHasSameActiveProfiles() { + AbstractEnvironment originalEnvironment = new MockEnvironment(); + originalEnvironment.setActiveProfiles("activeProfile1", "activeProfile2"); + StandardEnvironment convertedEnvironment = this.environmentConverter + .convertToStandardEnvironmentIfNecessary(originalEnvironment); + assertThat(convertedEnvironment.getActiveProfiles()) + .containsExactly("activeProfile1", "activeProfile2"); + } + + @Test + public void convertedEnvironmentHasSameConversionService() { + AbstractEnvironment originalEnvironment = new MockEnvironment(); + ConfigurableConversionService conversionService = mock( + ConfigurableConversionService.class); + originalEnvironment.setConversionService(conversionService); + StandardEnvironment convertedEnvironment = this.environmentConverter + .convertToStandardEnvironmentIfNecessary(originalEnvironment); + assertThat(convertedEnvironment.getConversionService()) + .isEqualTo(conversionService); + } + + @Test + public void standardEnvironmentIsReturnedUnconverted() { + StandardEnvironment standardEnvironment = new StandardEnvironment(); + StandardEnvironment convertedEnvironment = this.environmentConverter + .convertToStandardEnvironmentIfNecessary(standardEnvironment); + assertThat(convertedEnvironment).isSameAs(standardEnvironment); + } + + @Test + public void standardServletEnvironmentIsConverted() { + StandardServletEnvironment standardServletEnvironment = new StandardServletEnvironment(); + StandardEnvironment convertedEnvironment = this.environmentConverter + .convertToStandardEnvironmentIfNecessary(standardServletEnvironment); + assertThat(convertedEnvironment).isNotSameAs(standardServletEnvironment); + } + +}