Skip to content

Commit a424081

Browse files
ethanrubinsonwilkinsona
authored andcommitted
Copy conversion service when performing environment conversion
Previously, when a web environment was converted to a StandardEnvironment, any customizations of the source environment's ConversionService were lost. This commit updates the logic that performs the conversion to copy the source's ConversionService to the converted environment, thereby ensuring that any customizations are retained. Closes gh-9259 See gh-9246
1 parent 8472166 commit a424081

File tree

3 files changed

+205
-34
lines changed

3 files changed

+205
-34
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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.MutablePropertySources;
25+
import org.springframework.core.env.PropertySource;
26+
import org.springframework.core.env.StandardEnvironment;
27+
import org.springframework.web.context.support.StandardServletEnvironment;
28+
29+
/**
30+
* Utility class for converting one environment type to another.
31+
*
32+
* @author Ethan Rubinson
33+
* @since 1.5.4
34+
*/
35+
final class EnvironmentConverter {
36+
37+
private static final Set<String> SERVLET_ENVIRONMENT_SOURCE_NAMES;
38+
39+
static {
40+
final Set<String> names = new HashSet<String>();
41+
names.add(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME);
42+
names.add(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME);
43+
names.add(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME);
44+
SERVLET_ENVIRONMENT_SOURCE_NAMES = Collections.unmodifiableSet(names);
45+
}
46+
47+
private EnvironmentConverter() {
48+
49+
}
50+
51+
/**
52+
* Converts the specified environment to a {@link StandardEnvironment}.
53+
*
54+
* @param environment The environment to convert.
55+
* @return The converted environment.
56+
*/
57+
protected static ConfigurableEnvironment convertToStandardEnvironment(
58+
ConfigurableEnvironment environment) {
59+
final StandardEnvironment result = new StandardEnvironment();
60+
61+
/* Copy the profiles */
62+
result.setActiveProfiles(environment.getActiveProfiles());
63+
64+
/* Copy the conversion service */
65+
result.setConversionService(environment.getConversionService());
66+
67+
/*
68+
* Copy over all of the property sources except those unrelated to a standard
69+
* environment
70+
*/
71+
removeAllPropertySources(result.getPropertySources());
72+
for (PropertySource<?> propertySource : environment.getPropertySources()) {
73+
if (!SERVLET_ENVIRONMENT_SOURCE_NAMES.contains(propertySource.getName())) {
74+
result.getPropertySources().addLast(propertySource);
75+
}
76+
}
77+
78+
return result;
79+
}
80+
81+
private static void removeAllPropertySources(MutablePropertySources propertySources) {
82+
final Set<String> names = new HashSet<String>();
83+
for (PropertySource<?> propertySource : propertySources) {
84+
names.add(propertySource.getName());
85+
}
86+
for (String name : names) {
87+
propertySources.remove(name);
88+
}
89+
}
90+
91+
}

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

Lines changed: 2 additions & 34 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...)
@@ -177,16 +178,6 @@ public class SpringApplication {
177178

178179
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
179180

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-
190181
private static final Log logger = LogFactory.getLog(SpringApplication.class);
191182

192183
private final Set<Object> sources = new LinkedHashSet<Object>();
@@ -335,7 +326,7 @@ private ConfigurableEnvironment prepareEnvironment(
335326
configureEnvironment(environment, applicationArguments.getSourceArgs());
336327
listeners.environmentPrepared(environment);
337328
if (isWebEnvironment(environment) && !this.webEnvironment) {
338-
environment = convertToStandardEnvironment(environment);
329+
environment = EnvironmentConverter.convertToStandardEnvironment(environment);
339330
}
340331
return environment;
341332
}
@@ -465,29 +456,6 @@ private boolean isWebEnvironment(ConfigurableEnvironment environment) {
465456
}
466457
}
467458

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-
491459
/**
492460
* Add, remove or re-order any {@link PropertySource}s in this application's
493461
* environment.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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.bouncycastle.util.Arrays;
20+
import org.junit.Assert;
21+
import org.junit.Test;
22+
23+
import org.springframework.core.convert.TypeDescriptor;
24+
import org.springframework.core.convert.converter.Converter;
25+
import org.springframework.core.convert.converter.ConverterFactory;
26+
import org.springframework.core.convert.converter.GenericConverter;
27+
import org.springframework.core.convert.support.ConfigurableConversionService;
28+
import org.springframework.core.env.AbstractEnvironment;
29+
import org.springframework.core.env.ConfigurableEnvironment;
30+
import org.springframework.mock.env.MockEnvironment;
31+
32+
/**
33+
* Tests for the {@link EnvironmentConverter} methods
34+
*
35+
* @author Ethan Rubinson
36+
*/
37+
public class EnvironmentConverterTest {
38+
39+
@Test
40+
public void testConvertAbstractEnvironmentToStandardEnvironment() throws Exception {
41+
final AbstractEnvironment baseEnv = new MockEnvironment();
42+
final CustomConversionService customConverterServce = new CustomConversionService(
43+
baseEnv.getConversionService());
44+
final String[] activeProfiles = new String[] { "activeProfile1", "activeProfile2" };
45+
baseEnv.setActiveProfiles(activeProfiles);
46+
baseEnv.setConversionService(customConverterServce);
47+
48+
ConfigurableEnvironment convertedEnv = EnvironmentConverter
49+
.convertToStandardEnvironment(baseEnv);
50+
Assert.assertTrue(Arrays.areEqual(activeProfiles,
51+
convertedEnv.getActiveProfiles()));
52+
Assert.assertEquals(customConverterServce, convertedEnv.getConversionService());
53+
}
54+
55+
private class CustomConversionService implements ConfigurableConversionService {
56+
57+
private final ConfigurableConversionService delegate;
58+
59+
CustomConversionService(ConfigurableConversionService delegate) {
60+
this.delegate = delegate;
61+
}
62+
63+
@Override
64+
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
65+
return this.delegate.canConvert(sourceType, targetType);
66+
}
67+
68+
@Override
69+
public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
70+
return this.delegate.canConvert(sourceType, targetType);
71+
}
72+
73+
@Override
74+
public <T> T convert(Object source, Class<T> targetType) {
75+
return this.delegate.convert(source, targetType);
76+
}
77+
78+
@Override
79+
public Object convert(Object source, TypeDescriptor sourceType,
80+
TypeDescriptor targetType) {
81+
return this.delegate.convert(source, sourceType, targetType);
82+
}
83+
84+
@Override
85+
public void addConverter(Converter<?, ?> converter) {
86+
this.delegate.addConverter(converter);
87+
}
88+
89+
@Override
90+
public <S, T> void addConverter(Class<S> sourceType, Class<T> targetType,
91+
Converter<? super S, ? extends T> converter) {
92+
this.delegate.addConverter(sourceType, targetType, converter);
93+
}
94+
95+
@Override
96+
public void addConverter(GenericConverter converter) {
97+
this.delegate.addConverter(converter);
98+
}
99+
100+
@Override
101+
public void addConverterFactory(ConverterFactory<?, ?> factory) {
102+
this.delegate.addConverterFactory(factory);
103+
}
104+
105+
@Override
106+
public void removeConvertible(Class<?> sourceType, Class<?> targetType) {
107+
this.delegate.removeConvertible(sourceType, targetType);
108+
}
109+
110+
}
111+
112+
}

0 commit comments

Comments
 (0)