Skip to content

Commit 197c0ce

Browse files
committed
Merge pull request #9259 from Ethan Rubinson
* gh-9259: Polish "Copy conversion service when performing environment conversion" Copy conversion service when performing environment conversion
2 parents 8472166 + 5b30269 commit 197c0ce

File tree

3 files changed

+205
-48
lines changed

3 files changed

+205
-48
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2012-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot;
18+
19+
import java.util.Collections;
20+
import java.util.HashSet;
21+
import java.util.Set;
22+
23+
import org.springframework.core.env.ConfigurableEnvironment;
24+
import org.springframework.core.env.Environment;
25+
import org.springframework.core.env.MutablePropertySources;
26+
import org.springframework.core.env.PropertySource;
27+
import org.springframework.core.env.StandardEnvironment;
28+
import org.springframework.util.ClassUtils;
29+
import org.springframework.web.context.ConfigurableWebEnvironment;
30+
import org.springframework.web.context.support.StandardServletEnvironment;
31+
32+
/**
33+
* Utility class for converting one type of {@link Environment} to another.
34+
*
35+
* @author Ethan Rubinson
36+
* @author Andy Wilkinson
37+
*/
38+
final class EnvironmentConverter {
39+
40+
private static final String CONFIGURABLE_WEB_ENVIRONMENT_CLASS = "org.springframework.web.context.ConfigurableWebEnvironment";
41+
42+
private static final Set<String> SERVLET_ENVIRONMENT_SOURCE_NAMES;
43+
44+
static {
45+
final Set<String> names = new HashSet<String>();
46+
names.add(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME);
47+
names.add(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME);
48+
names.add(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME);
49+
SERVLET_ENVIRONMENT_SOURCE_NAMES = Collections.unmodifiableSet(names);
50+
}
51+
52+
private final ClassLoader classLoader;
53+
54+
/**
55+
* Creates a new {@link EnvironmentConverter} that will use the given
56+
* {@code classLoader} during conversion.
57+
* @param classLoader the class loader to use
58+
*/
59+
EnvironmentConverter(ClassLoader classLoader) {
60+
this.classLoader = classLoader;
61+
}
62+
63+
/**
64+
* Converts the given {@code environment} to a {@link StandardEnvironment}. If the
65+
* environment is already a {@code StandardEnvironment} and is not a
66+
* {@link ConfigurableWebEnvironment} no conversion is performed and it is returned
67+
* unchanged.
68+
*
69+
* @param environment The Environment to convert
70+
* @return The converted Environment
71+
*/
72+
StandardEnvironment convertToStandardEnvironmentIfNecessary(
73+
ConfigurableEnvironment environment) {
74+
if (environment instanceof StandardEnvironment
75+
&& !isWebEnvironment(environment, this.classLoader)) {
76+
return (StandardEnvironment) environment;
77+
}
78+
return convertToStandardEnvironment(environment);
79+
}
80+
81+
private boolean isWebEnvironment(ConfigurableEnvironment environment,
82+
ClassLoader classLoader) {
83+
try {
84+
Class<?> webEnvironmentClass = ClassUtils
85+
.forName(CONFIGURABLE_WEB_ENVIRONMENT_CLASS, classLoader);
86+
return (webEnvironmentClass.isInstance(environment));
87+
}
88+
catch (Throwable ex) {
89+
return false;
90+
}
91+
}
92+
93+
private StandardEnvironment convertToStandardEnvironment(
94+
ConfigurableEnvironment environment) {
95+
StandardEnvironment result = new StandardEnvironment();
96+
result.setActiveProfiles(environment.getActiveProfiles());
97+
result.setConversionService(environment.getConversionService());
98+
copyNonServletPropertySources(environment, result);
99+
return result;
100+
}
101+
102+
private void copyNonServletPropertySources(ConfigurableEnvironment source,
103+
StandardEnvironment target) {
104+
removeAllPropertySources(target.getPropertySources());
105+
for (PropertySource<?> propertySource : source.getPropertySources()) {
106+
if (!SERVLET_ENVIRONMENT_SOURCE_NAMES.contains(propertySource.getName())) {
107+
target.getPropertySources().addLast(propertySource);
108+
}
109+
}
110+
}
111+
112+
private void removeAllPropertySources(MutablePropertySources propertySources) {
113+
Set<String> names = new HashSet<String>();
114+
for (PropertySource<?> propertySource : propertySources) {
115+
names.add(propertySource.getName());
116+
}
117+
for (String name : names) {
118+
propertySources.remove(name);
119+
}
120+
}
121+
122+
}

spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

Lines changed: 4 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
* @author Jeremy Rickard
141141
* @author Craig Burke
142142
* @author Michael Simons
143+
* @author Ethan Rubinson
143144
* @see #run(Object, String[])
144145
* @see #run(Object[], String[])
145146
* @see #SpringApplication(Object...)
@@ -173,20 +174,8 @@ public class SpringApplication {
173174
*/
174175
public static final String BANNER_LOCATION_PROPERTY = SpringApplicationBannerPrinter.BANNER_LOCATION_PROPERTY;
175176

176-
private static final String CONFIGURABLE_WEB_ENVIRONMENT_CLASS = "org.springframework.web.context.ConfigurableWebEnvironment";
177-
178177
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
179178

180-
private static final Set<String> SERVLET_ENVIRONMENT_SOURCE_NAMES;
181-
182-
static {
183-
Set<String> names = new HashSet<String>();
184-
names.add(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME);
185-
names.add(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME);
186-
names.add(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME);
187-
SERVLET_ENVIRONMENT_SOURCE_NAMES = Collections.unmodifiableSet(names);
188-
}
189-
190179
private static final Log logger = LogFactory.getLog(SpringApplication.class);
191180

192181
private final Set<Object> sources = new LinkedHashSet<Object>();
@@ -334,8 +323,9 @@ private ConfigurableEnvironment prepareEnvironment(
334323
ConfigurableEnvironment environment = getOrCreateEnvironment();
335324
configureEnvironment(environment, applicationArguments.getSourceArgs());
336325
listeners.environmentPrepared(environment);
337-
if (isWebEnvironment(environment) && !this.webEnvironment) {
338-
environment = convertToStandardEnvironment(environment);
326+
if (!this.webEnvironment) {
327+
environment = new EnvironmentConverter(getClassLoader())
328+
.convertToStandardEnvironmentIfNecessary(environment);
339329
}
340330
return environment;
341331
}
@@ -454,40 +444,6 @@ protected void configureEnvironment(ConfigurableEnvironment environment,
454444
configureProfiles(environment, args);
455445
}
456446

457-
private boolean isWebEnvironment(ConfigurableEnvironment environment) {
458-
try {
459-
Class<?> webEnvironmentClass = ClassUtils
460-
.forName(CONFIGURABLE_WEB_ENVIRONMENT_CLASS, getClassLoader());
461-
return (webEnvironmentClass.isInstance(environment));
462-
}
463-
catch (Throwable ex) {
464-
return false;
465-
}
466-
}
467-
468-
private ConfigurableEnvironment convertToStandardEnvironment(
469-
ConfigurableEnvironment environment) {
470-
StandardEnvironment result = new StandardEnvironment();
471-
removeAllPropertySources(result.getPropertySources());
472-
result.setActiveProfiles(environment.getActiveProfiles());
473-
for (PropertySource<?> propertySource : environment.getPropertySources()) {
474-
if (!SERVLET_ENVIRONMENT_SOURCE_NAMES.contains(propertySource.getName())) {
475-
result.getPropertySources().addLast(propertySource);
476-
}
477-
}
478-
return result;
479-
}
480-
481-
private void removeAllPropertySources(MutablePropertySources propertySources) {
482-
Set<String> names = new HashSet<String>();
483-
for (PropertySource<?> propertySource : propertySources) {
484-
names.add(propertySource.getName());
485-
}
486-
for (String name : names) {
487-
propertySources.remove(name);
488-
}
489-
}
490-
491447
/**
492448
* Add, remove or re-order any {@link PropertySource}s in this application's
493449
* environment.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2012-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot;
18+
19+
import org.junit.Test;
20+
21+
import org.springframework.core.convert.support.ConfigurableConversionService;
22+
import org.springframework.core.env.AbstractEnvironment;
23+
import org.springframework.core.env.StandardEnvironment;
24+
import org.springframework.mock.env.MockEnvironment;
25+
import org.springframework.web.context.support.StandardServletEnvironment;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.mockito.Mockito.mock;
29+
30+
/**
31+
* Tests for {@link EnvironmentConverter}.
32+
*
33+
* @author Ethan Rubinson
34+
* @author Andy Wilkinson
35+
*/
36+
public class EnvironmentConverterTests {
37+
38+
private final EnvironmentConverter environmentConverter = new EnvironmentConverter(
39+
getClass().getClassLoader());
40+
41+
@Test
42+
public void convertedEnvironmentHasSameActiveProfiles() {
43+
AbstractEnvironment originalEnvironment = new MockEnvironment();
44+
originalEnvironment.setActiveProfiles("activeProfile1", "activeProfile2");
45+
StandardEnvironment convertedEnvironment = this.environmentConverter
46+
.convertToStandardEnvironmentIfNecessary(originalEnvironment);
47+
assertThat(convertedEnvironment.getActiveProfiles())
48+
.containsExactly("activeProfile1", "activeProfile2");
49+
}
50+
51+
@Test
52+
public void convertedEnvironmentHasSameConversionService() {
53+
AbstractEnvironment originalEnvironment = new MockEnvironment();
54+
ConfigurableConversionService conversionService = mock(
55+
ConfigurableConversionService.class);
56+
originalEnvironment.setConversionService(conversionService);
57+
StandardEnvironment convertedEnvironment = this.environmentConverter
58+
.convertToStandardEnvironmentIfNecessary(originalEnvironment);
59+
assertThat(convertedEnvironment.getConversionService())
60+
.isEqualTo(conversionService);
61+
}
62+
63+
@Test
64+
public void standardEnvironmentIsReturnedUnconverted() {
65+
StandardEnvironment standardEnvironment = new StandardEnvironment();
66+
StandardEnvironment convertedEnvironment = this.environmentConverter
67+
.convertToStandardEnvironmentIfNecessary(standardEnvironment);
68+
assertThat(convertedEnvironment).isSameAs(standardEnvironment);
69+
}
70+
71+
@Test
72+
public void standardServletEnvironmentIsConverted() {
73+
StandardServletEnvironment standardServletEnvironment = new StandardServletEnvironment();
74+
StandardEnvironment convertedEnvironment = this.environmentConverter
75+
.convertToStandardEnvironmentIfNecessary(standardServletEnvironment);
76+
assertThat(convertedEnvironment).isNotSameAs(standardServletEnvironment);
77+
}
78+
79+
}

0 commit comments

Comments
 (0)