Skip to content

Commit 26a90c1

Browse files
author
Dave Syer
committed
Add flag to PropertiesConfigurationFactory to switch off placeholder resolution
The default behaviour is unchanged, but it is useful for some applications to be able to bind without placeholder resolution (e.g. to prevent exposing system environment variables, if the bound object is being sent over the wire).
1 parent d1fd79c commit 26a90c1

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

spring-boot/src/main/java/org/springframework/boot/bind/PropertiesConfigurationFactory.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ public class PropertiesConfigurationFactory<T>
8686

8787
private ConversionService conversionService;
8888

89+
private boolean resolvePlaceholders = true;
90+
8991
/**
9092
* Create a new {@link PropertiesConfigurationFactory} instance.
9193
* @param target the target object to bind too
@@ -203,6 +205,16 @@ public void setExceptionIfInvalid(boolean exceptionIfInvalid) {
203205
this.exceptionIfInvalid = exceptionIfInvalid;
204206
}
205207

208+
/**
209+
* Flag to indicate that placeholders should be replaced during binding. Default is
210+
* true.
211+
*
212+
* @param resolvePlaceholders flag value
213+
*/
214+
public void setResolvePlaceholders(boolean resolvePlaceholders) {
215+
this.resolvePlaceholders = resolvePlaceholders;
216+
}
217+
206218
@Override
207219
public void afterPropertiesSet() throws Exception {
208220
bindPropertiesToTarget();
@@ -322,7 +334,8 @@ private PropertyValues getPropertySourcesPropertyValues(Set<String> names,
322334
Iterable<String> relaxedTargetNames) {
323335
PropertyNamePatternsMatcher includes = getPropertyNamePatternsMatcher(names,
324336
relaxedTargetNames);
325-
return new PropertySourcesPropertyValues(this.propertySources, names, includes);
337+
return new PropertySourcesPropertyValues(this.propertySources, names, includes,
338+
this.resolvePlaceholders);
326339
}
327340

328341
private PropertyNamePatternsMatcher getPropertyNamePatternsMatcher(Set<String> names,

spring-boot/src/main/java/org/springframework/boot/bind/PropertySourcesPropertyValues.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,15 @@ public class PropertySourcesPropertyValues implements PropertyValues {
5656

5757
private final ConcurrentHashMap<String, PropertySource<?>> collectionOwners = new ConcurrentHashMap<String, PropertySource<?>>();
5858

59+
private boolean resolvePlaceholders = true;
60+
5961
/**
6062
* Create a new PropertyValues from the given PropertySources.
6163
* @param propertySources a PropertySources instance
6264
*/
6365
public PropertySourcesPropertyValues(PropertySources propertySources) {
64-
this(propertySources, (Collection<String>) null, PropertyNamePatternsMatcher.ALL);
66+
this(propertySources, (Collection<String>) null, PropertyNamePatternsMatcher.ALL,
67+
true);
6568
}
6669

6770
/**
@@ -76,7 +79,7 @@ public PropertySourcesPropertyValues(PropertySources propertySources,
7679
Collection<String> includePatterns,
7780
Collection<String> nonEnumerableFallbackNames) {
7881
this(propertySources, nonEnumerableFallbackNames,
79-
new PatternPropertyNamePatternsMatcher(includePatterns));
82+
new PatternPropertyNamePatternsMatcher(includePatterns), true);
8083
}
8184

8285
/**
@@ -85,22 +88,34 @@ public PropertySourcesPropertyValues(PropertySources propertySources,
8588
* @param nonEnumerableFallbackNames the property names to try in lieu of an
8689
* {@link EnumerablePropertySource}.
8790
* @param includes the property name patterns to include
91+
* @param resolvePlaceholders flag to indicate the placeholders should be resolved
8892
*/
8993
PropertySourcesPropertyValues(PropertySources propertySources,
9094
Collection<String> nonEnumerableFallbackNames,
91-
PropertyNamePatternsMatcher includes) {
95+
PropertyNamePatternsMatcher includes, boolean resolvePlaceholders) {
9296
Assert.notNull(propertySources, "PropertySources must not be null");
9397
Assert.notNull(includes, "Includes must not be null");
9498
this.propertySources = propertySources;
9599
this.nonEnumerableFallbackNames = nonEnumerableFallbackNames;
96100
this.includes = includes;
101+
this.resolvePlaceholders = resolvePlaceholders;
97102
PropertySourcesPropertyResolver resolver = new PropertySourcesPropertyResolver(
98103
propertySources);
99104
for (PropertySource<?> source : propertySources) {
100105
processPropertySource(source, resolver);
101106
}
102107
}
103108

109+
/**
110+
* Flag to indicate that placeholders should be replaced during binding. Default is
111+
* true.
112+
*
113+
* @param resolvePlaceholders flag value
114+
*/
115+
public void setResolvePlaceholders(boolean resolvePlaceholders) {
116+
this.resolvePlaceholders = resolvePlaceholders;
117+
}
118+
104119
private void processPropertySource(PropertySource<?> source,
105120
PropertySourcesPropertyResolver resolver) {
106121
if (source instanceof CompositePropertySource) {
@@ -138,12 +153,14 @@ private void processEnumerablePropertySource(EnumerablePropertySource<?> source,
138153
private Object getEnumerableProperty(EnumerablePropertySource<?> source,
139154
PropertySourcesPropertyResolver resolver, String propertyName) {
140155
try {
141-
return resolver.getProperty(propertyName, Object.class);
156+
if (this.resolvePlaceholders) {
157+
return resolver.getProperty(propertyName, Object.class);
158+
}
142159
}
143160
catch (RuntimeException ex) {
144161
// Probably could not resolve placeholders, ignore it here
145-
return source.getProperty(propertyName);
146162
}
163+
return source.getProperty(propertyName);
147164
}
148165

149166
private void processNonEnumerablePropertySource(PropertySource<?> source,

spring-boot/src/test/java/org/springframework/boot/bind/PropertiesConfigurationFactoryTests.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,35 @@ public void systemEnvironmentBindingFailuresAreIgnored() throws Exception {
105105
assertThat(foo.name).isEqualTo("bar");
106106
}
107107

108+
@Test
109+
public void systemEnvironmentBindingWithDefaults() throws Exception {
110+
setupFactory();
111+
MutablePropertySources propertySources = new MutablePropertySources();
112+
MockPropertySource propertySource = new MockPropertySource(
113+
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
114+
propertySource.setProperty("name", "${foo.name:bar}");
115+
propertySources.addFirst(propertySource);
116+
this.factory.setPropertySources(propertySources);
117+
this.factory.afterPropertiesSet();
118+
Foo foo = this.factory.getObject();
119+
assertThat(foo.name).isEqualTo("bar");
120+
}
121+
122+
@Test
123+
public void systemEnvironmentNoResolvePlaceholders() throws Exception {
124+
setupFactory();
125+
MutablePropertySources propertySources = new MutablePropertySources();
126+
MockPropertySource propertySource = new MockPropertySource(
127+
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
128+
propertySource.setProperty("name", "${foo.name:bar}");
129+
propertySources.addFirst(propertySource);
130+
this.factory.setPropertySources(propertySources);
131+
this.factory.setResolvePlaceholders(false);
132+
this.factory.afterPropertiesSet();
133+
Foo foo = this.factory.getObject();
134+
assertThat(foo.name).isEqualTo("${foo.name:bar}");
135+
}
136+
108137
@Test
109138
public void systemPropertyBindingFailuresAreIgnored() throws Exception {
110139
setupFactory();

0 commit comments

Comments
 (0)