valueType) throws IllegalStateException {
T value = getProperty(key, valueType);
if (value == null) {
- throw new IllegalStateException(format("required key [%s] not found", key));
+ throw new IllegalStateException(String.format("required key [%s] not found", key));
}
return value;
}
@@ -130,17 +132,17 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
}
public String resolvePlaceholders(String text) {
- if (nonStrictHelper == null) {
- nonStrictHelper = createPlaceholderHelper(true);
+ if (this.nonStrictHelper == null) {
+ this.nonStrictHelper = createPlaceholderHelper(true);
}
- return doResolvePlaceholders(text, nonStrictHelper);
+ return doResolvePlaceholders(text, this.nonStrictHelper);
}
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
- if (strictHelper == null) {
- strictHelper = createPlaceholderHelper(false);
+ if (this.strictHelper == null) {
+ this.strictHelper = createPlaceholderHelper(false);
}
- return doResolvePlaceholders(text, strictHelper);
+ return doResolvePlaceholders(text, this.strictHelper);
}
/**
@@ -154,15 +156,19 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
/**
* Resolve placeholders within the given string, deferring to the value of
- * {@link #setIgnoreUnresolvableNestedPlaceholders(boolean)} to determine whether any
+ * {@link #setIgnoreUnresolvableNestedPlaceholders} to determine whether any
* unresolvable placeholders should raise an exception or be ignored.
+ * Invoked from {@link #getProperty} and its variants, implicitly resolving
+ * nested placeholders. In contrast, {@link #resolvePlaceholders} and
+ * {@link #resolveRequiredPlaceholders} do not delegate
+ * to this method but rather perform their own handling of unresolvable
+ * placeholders, as specified by each of those methods.
* @since 3.2
- * @see #setIgnoreUnresolvableNestedPlaceholders(boolean)
+ * @see #setIgnoreUnresolvableNestedPlaceholders
*/
protected String resolveNestedPlaceholders(String value) {
return this.ignoreUnresolvableNestedPlaceholders ?
- this.resolvePlaceholders(value) :
- this.resolveRequiredPlaceholders(value);
+ resolvePlaceholders(value) : resolveRequiredPlaceholders(value);
}
private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
@@ -171,11 +177,19 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
}
private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
- return helper.replacePlaceholders(text, new PlaceholderResolver() {
+ return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
public String resolvePlaceholder(String placeholderName) {
- return getProperty(placeholderName);
+ return getPropertyAsRawString(placeholderName);
}
});
}
+ /**
+ * Retrieve the specified property as a raw String,
+ * i.e. without resolution of nested placeholders.
+ * @param key the property name to resolve
+ * @return the property value or {@code null} if none found
+ */
+ protected abstract String getPropertyAsRawString(String key);
+
}
diff --git a/spring-core/src/main/java/org/springframework/core/env/PropertyResolver.java b/spring-core/src/main/java/org/springframework/core/env/PropertyResolver.java
index cf94472c0c..b3ce15b6f6 100644
--- a/spring-core/src/main/java/org/springframework/core/env/PropertyResolver.java
+++ b/spring-core/src/main/java/org/springframework/core/env/PropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -74,8 +74,9 @@ public interface PropertyResolver {
/**
* Convert the property value associated with the given key to a {@code Class}
* of type {@code T} or {@code null} if the key cannot be resolved.
- * @throws ConversionException if class specified by property value cannot be found
- * or loaded or if targetType is not assignable from class specified by property value
+ * @throws org.springframework.core.convert.ConversionException if class specified
+ * by property value cannot be found or loaded or if targetType is not assignable
+ * from class specified by property value
* @see #getProperty(String, Class)
*/
Class getPropertyAsClass(String key, Class targetType);
@@ -113,8 +114,9 @@ public interface PropertyResolver {
* no default value will cause an IllegalArgumentException to be thrown.
* @return the resolved String (never {@code null})
* @throws IllegalArgumentException if given text is {@code null}
- * @throws IllegalArgumentException if any placeholders are unresolvable
+ * or if any placeholders are unresolvable
* @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders(String, boolean)
*/
String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;
+
}
diff --git a/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java b/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java
index 1f5998c0c8..9e33628448 100644
--- a/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java
+++ b/spring-core/src/main/java/org/springframework/core/env/PropertySourcesPropertyResolver.java
@@ -57,11 +57,20 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
@Override
public String getProperty(String key) {
- return getProperty(key, String.class);
+ return getProperty(key, String.class, true);
}
@Override
public T getProperty(String key, Class targetValueType) {
+ return getProperty(key, targetValueType, true);
+ }
+
+ @Override
+ protected String getPropertyAsRawString(String key) {
+ return getProperty(key, String.class, false);
+ }
+
+ protected T getProperty(String key, Class targetValueType, boolean resolveNestedPlaceholders) {
boolean debugEnabled = logger.isDebugEnabled();
if (logger.isTraceEnabled()) {
logger.trace(String.format("getProperty(\"%s\", %s)", key, targetValueType.getSimpleName()));
@@ -74,8 +83,8 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
Object value;
if ((value = propertySource.getProperty(key)) != null) {
Class> valueType = value.getClass();
- if (String.class.equals(valueType)) {
- value = this.resolveNestedPlaceholders((String) value);
+ if (resolveNestedPlaceholders && value instanceof String) {
+ value = resolveNestedPlaceholders((String) value);
}
if (debugEnabled) {
logger.debug(String.format("Found key '%s' in [%s] with type [%s] and value '%s'",
@@ -86,7 +95,7 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
"Cannot convert value [%s] from source type [%s] to target type [%s]",
value, valueType.getSimpleName(), targetValueType.getSimpleName()));
}
- return conversionService.convert(value, targetValueType);
+ return this.conversionService.convert(value, targetValueType);
}
}
}
@@ -115,10 +124,10 @@ public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
Class> clazz;
if (value instanceof String) {
try {
- clazz = ClassUtils.forName((String)value, null);
+ clazz = ClassUtils.forName((String) value, null);
}
catch (Exception ex) {
- throw new ClassConversionException((String)value, targetValueType, ex);
+ throw new ClassConversionException((String) value, targetValueType, ex);
}
}
else if (value instanceof Class) {
diff --git a/spring-core/src/main/java/org/springframework/util/PropertyPlaceholderHelper.java b/spring-core/src/main/java/org/springframework/util/PropertyPlaceholderHelper.java
index 5728b28604..fca0f997f8 100644
--- a/spring-core/src/main/java/org/springframework/util/PropertyPlaceholderHelper.java
+++ b/spring-core/src/main/java/org/springframework/util/PropertyPlaceholderHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -98,8 +98,8 @@ public class PropertyPlaceholderHelper {
/**
- * Replaces all placeholders of format {@code ${name}} with the corresponding property
- * from the supplied {@link Properties}.
+ * Replaces all placeholders of format {@code ${name}} with the corresponding
+ * property from the supplied {@link Properties}.
* @param value the value containing the placeholders to be replaced.
* @param properties the {@code Properties} to use for replacement.
* @return the supplied value with placeholders replaced inline.
@@ -114,8 +114,8 @@ public class PropertyPlaceholderHelper {
}
/**
- * Replaces all placeholders of format {@code ${name}} with the value returned from the supplied
- * {@link PlaceholderResolver}.
+ * Replaces all placeholders of format {@code ${name}} with the value returned
+ * from the supplied {@link PlaceholderResolver}.
* @param value the value containing the placeholders to be replaced.
* @param placeholderResolver the {@code PlaceholderResolver} to use for replacement.
* @return the supplied value with placeholders replaced inline.
@@ -216,8 +216,8 @@ public class PropertyPlaceholderHelper {
/**
* Resolves the supplied placeholder name into the replacement value.
- * @param placeholderName the name of the placeholder to resolve.
- * @return the replacement value or {@code null} if no replacement is to be made.
+ * @param placeholderName the name of the placeholder to resolve
+ * @return the replacement value or {@code null} if no replacement is to be made
*/
String resolvePlaceholder(String placeholderName);
}
diff --git a/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java b/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java
index f998cc5366..84f6fce08a 100644
--- a/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java
+++ b/spring-core/src/test/java/org/springframework/core/env/PropertySourcesPropertyResolverTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -30,8 +30,6 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
- * Unit tests for {@link PropertySourcesPropertyResolver}.
- *
* @author Chris Beams
* @since 3.1
*/
@@ -387,8 +385,8 @@ public class PropertySourcesPropertyResolverTests {
try {
pr.getProperty("pL");
}
- catch (StackOverflowError ex) {
- // no explicit handling for cyclic references for now
+ catch (IllegalArgumentException ex) {
+ assertTrue(ex.getMessage().toLowerCase().contains("circular"));
}
}