Fix circular placeholder prevention

A set of resolved placeholder references is used for circular
placeholder prevention. For complex property definitions this mechanism
would put property values with unresolved inner placeholder references
in the set, but would try to remove property values with placeholders
resolved, leaving the set in an invalid state and the mechanism broken.

This fix makes sure that the value that is put in the set is same one
that is removed from it, and by doing so avoids false positives in
reporting circular placeholders.

Issue: SPR-5369
master
Stevo Slavic 13 years ago committed by Chris Beams
parent f667db56b1
commit 18006c72b0
  1. 9
      spring-core/src/main/java/org/springframework/util/PropertyPlaceholderHelper.java
  2. 11
      spring-core/src/test/java/org/springframework/util/PropertyPlaceholderHelperTests.java

@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 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.
@ -135,9 +135,10 @@ public class PropertyPlaceholderHelper {
int endIndex = findPlaceholderEndIndex(buf, startIndex);
if (endIndex != -1) {
String placeholder = buf.substring(startIndex + this.placeholderPrefix.length(), endIndex);
if (!visitedPlaceholders.add(placeholder)) {
String originalPlaceholder = placeholder;
if (!visitedPlaceholders.add(originalPlaceholder)) {
throw new IllegalArgumentException(
"Circular placeholder reference '" + placeholder + "' in property definitions");
"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
}
// Recursive invocation, parsing placeholders contained in the placeholder key.
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
@ -173,7 +174,7 @@ public class PropertyPlaceholderHelper {
throw new IllegalArgumentException("Could not resolve placeholder '" + placeholder + "'");
}
visitedPlaceholders.remove(placeholder);
visitedPlaceholders.remove(originalPlaceholder);
}
else {
startIndex = -1;

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 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.
@ -65,6 +65,15 @@ public class PropertyPlaceholderHelperTests {
props.setProperty("inner", "ar");
assertEquals("foo=bar", this.helper.replacePlaceholders(text, props));
text = "${top}";
props = new Properties();
props.setProperty("top", "${child}+${child}");
props.setProperty("child", "${${differentiator}.grandchild}");
props.setProperty("differentiator", "first");
props.setProperty("first.grandchild", "actualValue");
assertEquals("actualValue+actualValue", this.helper.replacePlaceholders(text, props));
}
@Test

Loading…
Cancel
Save