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).
This commit is contained in:
Dave Syer 2016-09-20 10:13:50 +01:00
parent d1fd79cfa3
commit 26a90c1d24
Notes: Phillip Webb 2016-09-20 14:14:52 -07:00
gh-6964
3 changed files with 65 additions and 6 deletions

View File

@ -86,6 +86,8 @@ public class PropertiesConfigurationFactory<T>
private ConversionService conversionService;
private boolean resolvePlaceholders = true;
/**
* Create a new {@link PropertiesConfigurationFactory} instance.
* @param target the target object to bind too
@ -203,6 +205,16 @@ public class PropertiesConfigurationFactory<T>
this.exceptionIfInvalid = exceptionIfInvalid;
}
/**
* Flag to indicate that placeholders should be replaced during binding. Default is
* true.
*
* @param resolvePlaceholders flag value
*/
public void setResolvePlaceholders(boolean resolvePlaceholders) {
this.resolvePlaceholders = resolvePlaceholders;
}
@Override
public void afterPropertiesSet() throws Exception {
bindPropertiesToTarget();
@ -322,7 +334,8 @@ public class PropertiesConfigurationFactory<T>
Iterable<String> relaxedTargetNames) {
PropertyNamePatternsMatcher includes = getPropertyNamePatternsMatcher(names,
relaxedTargetNames);
return new PropertySourcesPropertyValues(this.propertySources, names, includes);
return new PropertySourcesPropertyValues(this.propertySources, names, includes,
this.resolvePlaceholders);
}
private PropertyNamePatternsMatcher getPropertyNamePatternsMatcher(Set<String> names,

View File

@ -56,12 +56,15 @@ public class PropertySourcesPropertyValues implements PropertyValues {
private final ConcurrentHashMap<String, PropertySource<?>> collectionOwners = new ConcurrentHashMap<String, PropertySource<?>>();
private boolean resolvePlaceholders = true;
/**
* Create a new PropertyValues from the given PropertySources.
* @param propertySources a PropertySources instance
*/
public PropertySourcesPropertyValues(PropertySources propertySources) {
this(propertySources, (Collection<String>) null, PropertyNamePatternsMatcher.ALL);
this(propertySources, (Collection<String>) null, PropertyNamePatternsMatcher.ALL,
true);
}
/**
@ -76,7 +79,7 @@ public class PropertySourcesPropertyValues implements PropertyValues {
Collection<String> includePatterns,
Collection<String> nonEnumerableFallbackNames) {
this(propertySources, nonEnumerableFallbackNames,
new PatternPropertyNamePatternsMatcher(includePatterns));
new PatternPropertyNamePatternsMatcher(includePatterns), true);
}
/**
@ -85,15 +88,17 @@ public class PropertySourcesPropertyValues implements PropertyValues {
* @param nonEnumerableFallbackNames the property names to try in lieu of an
* {@link EnumerablePropertySource}.
* @param includes the property name patterns to include
* @param resolvePlaceholders flag to indicate the placeholders should be resolved
*/
PropertySourcesPropertyValues(PropertySources propertySources,
Collection<String> nonEnumerableFallbackNames,
PropertyNamePatternsMatcher includes) {
PropertyNamePatternsMatcher includes, boolean resolvePlaceholders) {
Assert.notNull(propertySources, "PropertySources must not be null");
Assert.notNull(includes, "Includes must not be null");
this.propertySources = propertySources;
this.nonEnumerableFallbackNames = nonEnumerableFallbackNames;
this.includes = includes;
this.resolvePlaceholders = resolvePlaceholders;
PropertySourcesPropertyResolver resolver = new PropertySourcesPropertyResolver(
propertySources);
for (PropertySource<?> source : propertySources) {
@ -101,6 +106,16 @@ public class PropertySourcesPropertyValues implements PropertyValues {
}
}
/**
* Flag to indicate that placeholders should be replaced during binding. Default is
* true.
*
* @param resolvePlaceholders flag value
*/
public void setResolvePlaceholders(boolean resolvePlaceholders) {
this.resolvePlaceholders = resolvePlaceholders;
}
private void processPropertySource(PropertySource<?> source,
PropertySourcesPropertyResolver resolver) {
if (source instanceof CompositePropertySource) {
@ -138,12 +153,14 @@ public class PropertySourcesPropertyValues implements PropertyValues {
private Object getEnumerableProperty(EnumerablePropertySource<?> source,
PropertySourcesPropertyResolver resolver, String propertyName) {
try {
return resolver.getProperty(propertyName, Object.class);
if (this.resolvePlaceholders) {
return resolver.getProperty(propertyName, Object.class);
}
}
catch (RuntimeException ex) {
// Probably could not resolve placeholders, ignore it here
return source.getProperty(propertyName);
}
return source.getProperty(propertyName);
}
private void processNonEnumerablePropertySource(PropertySource<?> source,

View File

@ -105,6 +105,35 @@ public class PropertiesConfigurationFactoryTests {
assertThat(foo.name).isEqualTo("bar");
}
@Test
public void systemEnvironmentBindingWithDefaults() throws Exception {
setupFactory();
MutablePropertySources propertySources = new MutablePropertySources();
MockPropertySource propertySource = new MockPropertySource(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
propertySource.setProperty("name", "${foo.name:bar}");
propertySources.addFirst(propertySource);
this.factory.setPropertySources(propertySources);
this.factory.afterPropertiesSet();
Foo foo = this.factory.getObject();
assertThat(foo.name).isEqualTo("bar");
}
@Test
public void systemEnvironmentNoResolvePlaceholders() throws Exception {
setupFactory();
MutablePropertySources propertySources = new MutablePropertySources();
MockPropertySource propertySource = new MockPropertySource(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);
propertySource.setProperty("name", "${foo.name:bar}");
propertySources.addFirst(propertySource);
this.factory.setPropertySources(propertySources);
this.factory.setResolvePlaceholders(false);
this.factory.afterPropertiesSet();
Foo foo = this.factory.getObject();
assertThat(foo.name).isEqualTo("${foo.name:bar}");
}
@Test
public void systemPropertyBindingFailuresAreIgnored() throws Exception {
setupFactory();