diff --git a/org.springframework.core/src/main/java/org/springframework/util/PropertyPlaceholderUtils.java b/org.springframework.core/src/main/java/org/springframework/util/PropertyPlaceholderHelper.java similarity index 55% rename from org.springframework.core/src/main/java/org/springframework/util/PropertyPlaceholderUtils.java rename to org.springframework.core/src/main/java/org/springframework/util/PropertyPlaceholderHelper.java index 51d50f10de1..4e61033f3f3 100644 --- a/org.springframework.core/src/main/java/org/springframework/util/PropertyPlaceholderUtils.java +++ b/org.springframework.core/src/main/java/org/springframework/util/PropertyPlaceholderHelper.java @@ -20,6 +20,9 @@ import java.util.Properties; import java.util.Set; import java.util.HashSet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + /** * Utility class for working with Strings that have placeholder values in them. A placeholder takes the form * ${name}. Using PropertyPlaceholderUtils these placeholders can be substituted for @@ -30,13 +33,43 @@ import java.util.HashSet; * @author Rob Harrop * @since 3.0 */ -public class PropertyPlaceholderUtils { +public class PropertyPlaceholderHelper { + + private static final Log LOGGER = LogFactory.getLog(PropertyPlaceholderHelper.class); + + private final String placeholderPrefix; + + private final String placeholderSuffix; - /** Prefix for property placeholders: "${" */ - public static final String PLACEHOLDER_PREFIX = "${"; + private final boolean ignoreUnresolvablePlaceholders; - /** Suffix for property placeholders: "}" */ - public static final String PLACEHOLDER_SUFFIX = "}"; + /** + * Creates a new PropertyPlaceholderHelper that uses the supplied prefix and suffix. Unresolvable + * placeholders are ignored. + * + * @param placeholderPrefix the prefix that denotes the start of a placeholder. + * @param placeholderSuffix the suffix that denotes the end of a placeholder. + */ + public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix) { + this(placeholderPrefix, placeholderSuffix, true); + } + + /** + * Creates a new PropertyPlaceholderHelper that uses the supplied prefix and suffix. + * + * @param placeholderPrefix the prefix that denotes the start of a placeholder. + * @param placeholderSuffix the suffix that denotes the end of a placeholder. + * @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should be ignored + * (true) or cause an exception (false). + */ + public PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix, + boolean ignoreUnresolvablePlaceholders) { + Assert.notNull(placeholderPrefix, "Argument 'placeholderPrefix' must not be null."); + Assert.notNull(placeholderSuffix, "Argument 'placeholderSuffix' must not be null."); + this.placeholderPrefix = placeholderPrefix; + this.placeholderSuffix = placeholderSuffix; + this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders; + } /** * Replaces all placeholders of format ${name} with the corresponding property from the supplied {@link @@ -46,7 +79,7 @@ public class PropertyPlaceholderUtils { * @param properties the Properties to use for replacement. * @return the supplied value with placeholders replaced inline. */ - public static String replacePlaceholders(String value, final Properties properties) { + public String replacePlaceholders(String value, final Properties properties) { Assert.notNull(properties, "Argument 'properties' must not be null."); return replacePlaceholders(value, new PlaceholderResolver() { @@ -64,18 +97,20 @@ public class PropertyPlaceholderUtils { * @param placeholderResolver the PlaceholderResolver to use for replacement. * @return the supplied value with placeholders replaced inline. */ - public static String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) { + public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) { + Assert.notNull(value, "Argument 'value' must not be null."); return parseStringValue(value, placeholderResolver, new HashSet()); } - protected static String parseStringValue(String strVal, PlaceholderResolver placeholderResolver, Set visitedPlaceholders) { + protected String parseStringValue(String strVal, PlaceholderResolver placeholderResolver, + Set visitedPlaceholders) { StringBuilder buf = new StringBuilder(strVal); - int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX); + int startIndex = strVal.indexOf(this.placeholderPrefix); while (startIndex != -1) { int endIndex = findPlaceholderEndIndex(buf, startIndex); if (endIndex != -1) { - String placeholder = buf.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); + String placeholder = buf.substring(startIndex + this.placeholderPrefix.length(), endIndex); if (!visitedPlaceholders.add(placeholder)) { throw new IllegalArgumentException( "Circular placeholder reference '" + placeholder + "' in property definitions"); @@ -89,17 +124,20 @@ public class PropertyPlaceholderUtils { // Recursive invocation, parsing placeholders contained in the // previously resolved placeholder value. propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders); - buf.replace(startIndex, endIndex + PLACEHOLDER_SUFFIX.length(), propVal); + buf.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal); - //if (logger.isTraceEnabled()) { - // logger.trace("Resolved placeholder '" + placeholder + "'"); - //} + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Resolved placeholder '" + placeholder + "'"); + } - startIndex = buf.indexOf(PLACEHOLDER_PREFIX, startIndex + propVal.length()); + startIndex = buf.indexOf(this.placeholderPrefix, startIndex + propVal.length()); } - else { + else if (this.ignoreUnresolvablePlaceholders) { // Proceed with unprocessed value. - startIndex = buf.indexOf(PLACEHOLDER_PREFIX, endIndex + PLACEHOLDER_SUFFIX.length()); + startIndex = buf.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length()); + } + else { + throw new IllegalArgumentException("Could not resolve placeholder '" + placeholder + "'"); } visitedPlaceholders.remove(placeholder); @@ -112,22 +150,22 @@ public class PropertyPlaceholderUtils { return buf.toString(); } - private static int findPlaceholderEndIndex(CharSequence buf, int startIndex) { - int index = startIndex + PLACEHOLDER_PREFIX.length(); + private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { + int index = startIndex + this.placeholderPrefix.length(); int withinNestedPlaceholder = 0; while (index < buf.length()) { - if (StringUtils.substringMatch(buf, index, PLACEHOLDER_SUFFIX)) { + if (StringUtils.substringMatch(buf, index, this.placeholderSuffix)) { if (withinNestedPlaceholder > 0) { withinNestedPlaceholder--; - index = index + PLACEHOLDER_PREFIX.length() - 1; + index = index + this.placeholderPrefix.length() - 1; } else { return index; } } - else if (StringUtils.substringMatch(buf, index, PLACEHOLDER_PREFIX)) { + else if (StringUtils.substringMatch(buf, index, this.placeholderPrefix)) { withinNestedPlaceholder++; - index = index + PLACEHOLDER_PREFIX.length(); + index = index + this.placeholderPrefix.length(); } else { index++; @@ -139,7 +177,7 @@ public class PropertyPlaceholderUtils { /** * Strategy interface used to resolve replacement values for placeholders contained in Strings. * - * @see org.springframework.util.PropertyPlaceholderUtils + * @see PropertyPlaceholderHelper */ public static interface PlaceholderResolver { diff --git a/org.springframework.core/src/main/java/org/springframework/util/SystemPropertyUtils.java b/org.springframework.core/src/main/java/org/springframework/util/SystemPropertyUtils.java index 9cd11537ac5..1ae56c1c07a 100644 --- a/org.springframework.core/src/main/java/org/springframework/util/SystemPropertyUtils.java +++ b/org.springframework.core/src/main/java/org/springframework/util/SystemPropertyUtils.java @@ -16,7 +16,7 @@ package org.springframework.util; -import org.springframework.util.PropertyPlaceholderUtils.PlaceholderResolver; +import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; /** * Helper class for resolving placeholders in texts. Usually applied to file paths. @@ -38,6 +38,7 @@ public abstract class SystemPropertyUtils { /** Suffix for system property placeholders: "}" */ public static final String PLACEHOLDER_SUFFIX = "}"; + private static final PropertyPlaceholderHelper HELPER = new PropertyPlaceholderHelper(PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX); /** * Resolve ${...} placeholders in the given text, replacing them with corresponding system property values. * @@ -47,7 +48,7 @@ public abstract class SystemPropertyUtils { * @see #PLACEHOLDER_SUFFIX */ public static String resolvePlaceholders(final String text) { - return PropertyPlaceholderUtils.replacePlaceholders(text, new PlaceholderResolver() { + return HELPER.replacePlaceholders(text, new PlaceholderResolver() { public String resolvePlaceholder(String placeholderName) { String propVal = null; diff --git a/org.springframework.core/src/test/java/org/springframework/util/PropertyPlaceholderUtilsTests.java b/org.springframework.core/src/test/java/org/springframework/util/PropertyPlaceholderHelperTests.java similarity index 66% rename from org.springframework.core/src/test/java/org/springframework/util/PropertyPlaceholderUtilsTests.java rename to org.springframework.core/src/test/java/org/springframework/util/PropertyPlaceholderHelperTests.java index 50ca7f0eed4..c4dd9b77cf0 100644 --- a/org.springframework.core/src/test/java/org/springframework/util/PropertyPlaceholderUtilsTests.java +++ b/org.springframework.core/src/test/java/org/springframework/util/PropertyPlaceholderHelperTests.java @@ -22,7 +22,9 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; /** @author Rob Harrop */ -public class PropertyPlaceholderUtilsTests { +public class PropertyPlaceholderHelperTests { + + private final PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}"); @Test public void testWithProperties() { @@ -30,7 +32,7 @@ public class PropertyPlaceholderUtilsTests { Properties props = new Properties(); props.setProperty("foo", "bar"); - assertEquals("foo=bar", PropertyPlaceholderUtils.replacePlaceholders(text, props)); + assertEquals("foo=bar", this.helper.replacePlaceholders(text, props)); } @Test @@ -40,7 +42,7 @@ public class PropertyPlaceholderUtilsTests { props.setProperty("foo", "bar"); props.setProperty("bar", "baz"); - assertEquals("foo=bar,bar=baz", PropertyPlaceholderUtils.replacePlaceholders(text, props)); + assertEquals("foo=bar,bar=baz", this.helper.replacePlaceholders(text, props)); } @Test @@ -50,7 +52,7 @@ public class PropertyPlaceholderUtilsTests { props.setProperty("bar", "${baz}"); props.setProperty("baz", "bar"); - assertEquals("foo=bar", PropertyPlaceholderUtils.replacePlaceholders(text, props)); + assertEquals("foo=bar", this.helper.replacePlaceholders(text, props)); } @Test @@ -60,7 +62,7 @@ public class PropertyPlaceholderUtilsTests { props.setProperty("bar", "bar"); props.setProperty("inner", "ar"); - assertEquals("foo=bar", PropertyPlaceholderUtils.replacePlaceholders(text, props)); + assertEquals("foo=bar", this.helper.replacePlaceholders(text, props)); } @Test @@ -68,7 +70,7 @@ public class PropertyPlaceholderUtilsTests { String text = "foo=${foo}"; assertEquals("foo=bar", - PropertyPlaceholderUtils.replacePlaceholders(text, new PropertyPlaceholderUtils.PlaceholderResolver() { + this.helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() { public String resolvePlaceholder(String placeholderName) { if ("foo".equals(placeholderName)) { @@ -87,6 +89,16 @@ public class PropertyPlaceholderUtilsTests { Properties props = new Properties(); props.setProperty("foo", "bar"); - assertEquals("foo=bar,bar=${bar}", PropertyPlaceholderUtils.replacePlaceholders(text, props)); + assertEquals("foo=bar,bar=${bar}", this.helper.replacePlaceholders(text, props)); + } + + @Test(expected=IllegalArgumentException.class) + public void testUnresolvedPlaceholderAsError() { + String text = "foo=${foo},bar=${bar}"; + Properties props = new Properties(); + props.setProperty("foo", "bar"); + + PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}", false); + assertEquals("foo=bar,bar=${bar}", helper.replacePlaceholders(text, props)); } } diff --git a/spring-framework.ipr b/spring-framework.ipr index 7b73466b11a..da8147cc8c8 100644 --- a/spring-framework.ipr +++ b/spring-framework.ipr @@ -1,979 +1,961 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +