Allow PropertyResolvers to ignore unresolvable ${placeholders}

Prior to this commit, the PropertyResolver API (and therefore the
Environment API) allowed callers a choice between
 #resolvePlaceholders and #resolveRequiredPlaceholders for low-level
${placeholder} resolution. However, when calling the higher level
 #getProperty variants, users had no control over whether property
values returned with unresolvable ${placeholders} would result in an
exception or simply be passed through.

This commit introduces a #setIgnoreUnresolvableNestedPlaceholders
property via ConfigurablePropertyResolver, defaulting to false, the
value of which is respected by AbstractPropertyResolver#getProperty
method implementations. See the new test in
PropertySourcesPropertyResolverTests for usage examples.

Issue: SPR-9569, SPR-9473
This commit is contained in:
Chris Beams
2012-10-26 19:23:47 +02:00
parent 01272fb0e6
commit 06e34f05a6
5 changed files with 83 additions and 6 deletions

View File

@@ -464,6 +464,10 @@ public abstract class AbstractEnvironment implements ConfigurableEnvironment {
return this.propertyResolver.resolveRequiredPlaceholders(text);
}
public void setIgnoreUnresolvableNestedPlaceholders(boolean ignoreUnresolvableNestedPlaceholders) {
this.propertyResolver.setIgnoreUnresolvableNestedPlaceholders(ignoreUnresolvableNestedPlaceholders);
}
public void setConversionService(ConfigurableConversionService conversionService) {
this.propertyResolver.setConversionService(conversionService);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
@@ -45,6 +45,7 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
private PropertyPlaceholderHelper nonStrictHelper;
private PropertyPlaceholderHelper strictHelper;
private boolean ignoreUnresolvableNestedPlaceholders = false;
private String placeholderPrefix = PLACEHOLDER_PREFIX;
private String placeholderSuffix = PLACEHOLDER_SUFFIX;
@@ -142,6 +143,28 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
return doResolvePlaceholders(text, strictHelper);
}
/**
* {@inheritDoc}
* <p>The default value for this implementation is {@code false}.
* @since 3.2
*/
public void setIgnoreUnresolvableNestedPlaceholders(boolean ignoreUnresolvableNestedPlaceholders) {
this.ignoreUnresolvableNestedPlaceholders = ignoreUnresolvableNestedPlaceholders;
}
/**
* Resolve placeholders within the given string, deferring to the value of
* {@link #setIgnoreUnresolvableNestedPlaceholders(boolean)} to determine whether any
* unresolvable placeholders should raise an exception or be ignored.
* @since 3.2
* @see #setIgnoreUnresolvableNestedPlaceholders(boolean)
*/
protected String resolveNestedPlaceholders(String value) {
return this.ignoreUnresolvableNestedPlaceholders ?
this.resolvePlaceholders(value) :
this.resolveRequiredPlaceholders(value);
}
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
return new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix,
this.valueSeparator, ignoreUnresolvablePlaceholders);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
@@ -87,4 +87,17 @@ public interface ConfigurablePropertyResolver extends PropertyResolver {
* properties are not resolvable.
*/
void validateRequiredProperties() throws MissingRequiredPropertiesException;
/**
* Set whether to throw an exception when encountering an unresolvable placeholder
* nested within the value of a given property. A {@code false} value indicates strict
* resolution, i.e. that an exception will be thrown. A {@code true} value indicates
* that unresolvable nested placeholders should be passed through in their unresolved
* ${...} form.
* <p>Implementations of {@link #getProperty(String)} and its variants must inspect
* the value set here to determine correct behavior when property values contain
* unresolvable placeholders.
* @since 3.2
*/
void setIgnoreUnresolvableNestedPlaceholders(boolean ignoreUnresolvableNestedPlaceholders);
}

View File

@@ -73,7 +73,7 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
if ((value = propertySource.getProperty(key)) != null) {
Class<?> valueType = value.getClass();
if (String.class.equals(valueType)) {
value = this.resolveRequiredPlaceholders((String) value);
value = this.resolveNestedPlaceholders((String) value);
}
if (debugEnabled) {
logger.debug(