Skip to content

Commit eb045f1

Browse files
committed
Fix value of property in PropertySource descriptor
Prior to this commit, if a key was present in multiple PropertySources, all descriptors shared the same common value. This commit makes sure that each PropertySource descriptor shows the value it defines rather than the one that is promoted in the Environment. Closes gh-10428
1 parent f52c081 commit eb045f1

File tree

3 files changed

+27
-27
lines changed

3 files changed

+27
-27
lines changed

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,20 @@
3131
import org.springframework.boot.actuate.endpoint.annotation.Selector;
3232
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor;
3333
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor.PropertyValueDescriptor;
34+
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
35+
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
3436
import org.springframework.boot.origin.OriginLookup;
3537
import org.springframework.core.env.CompositePropertySource;
3638
import org.springframework.core.env.ConfigurableEnvironment;
3739
import org.springframework.core.env.EnumerablePropertySource;
3840
import org.springframework.core.env.Environment;
3941
import org.springframework.core.env.MutablePropertySources;
40-
import org.springframework.core.env.PropertyResolver;
4142
import org.springframework.core.env.PropertySource;
42-
import org.springframework.core.env.PropertySources;
43-
import org.springframework.core.env.PropertySourcesPropertyResolver;
4443
import org.springframework.core.env.StandardEnvironment;
4544
import org.springframework.http.HttpStatus;
45+
import org.springframework.util.PropertyPlaceholderHelper;
4646
import org.springframework.util.StringUtils;
47+
import org.springframework.util.SystemPropertyUtils;
4748
import org.springframework.web.bind.annotation.ResponseStatus;
4849

4950
/**
@@ -85,7 +86,7 @@ public EnvironmentDescriptor environmentEntry(@Selector String toMatch) {
8586

8687
private EnvironmentDescriptor getEnvironmentDescriptor(
8788
Predicate<String> propertyNamePredicate) {
88-
PropertyResolver resolver = getResolver();
89+
PlaceholdersResolver resolver = getResolver();
8990
List<PropertySourceDescriptor> propertySources = new ArrayList<>();
9091
getPropertySourcesAsMap().forEach((sourceName, source) -> {
9192
if (source instanceof EnumerablePropertySource) {
@@ -99,7 +100,7 @@ private EnvironmentDescriptor getEnvironmentDescriptor(
99100
}
100101

101102
private PropertySourceDescriptor describeSource(String sourceName,
102-
EnumerablePropertySource<?> source, PropertyResolver resolver,
103+
EnumerablePropertySource<?> source, PlaceholdersResolver resolver,
103104
Predicate<String> namePredicate) {
104105
Map<String, PropertyValueDescriptor> properties = new LinkedHashMap<>();
105106
Stream.of(source.getPropertyNames()).filter(namePredicate).forEach(
@@ -108,19 +109,17 @@ private PropertySourceDescriptor describeSource(String sourceName,
108109
}
109110

110111
private PropertyValueDescriptor describeValueOf(String name,
111-
EnumerablePropertySource<?> source, PropertyResolver resolver) {
112-
Object resolved = resolver.getProperty(name, Object.class);
112+
EnumerablePropertySource<?> source, PlaceholdersResolver resolver) {
113+
Object resolved = resolver.resolvePlaceholders(source.getProperty(name));
113114
@SuppressWarnings("unchecked")
114115
String origin = (source instanceof OriginLookup)
115116
? ((OriginLookup<Object>) source).getOrigin(name).toString() : null;
116117
return new PropertyValueDescriptor(sanitize(name, resolved), origin);
117118
}
118119

119-
private PropertyResolver getResolver() {
120-
PlaceholderSanitizingPropertyResolver resolver = new PlaceholderSanitizingPropertyResolver(
120+
private PlaceholdersResolver getResolver() {
121+
return new PropertySourcesPlaceholdersSanitizingResolver(
121122
getPropertySources(), this.sanitizer);
122-
resolver.setIgnoreUnresolvableNestedPlaceholders(true);
123-
return resolver;
124123
}
125124

126125
private Map<String, PropertySource<?>> getPropertySourcesAsMap() {
@@ -160,29 +159,28 @@ public Object sanitize(String name, Object object) {
160159
}
161160

162161
/**
163-
* {@link PropertySourcesPropertyResolver} that sanitizes sensitive placeholders if
164-
* present.
162+
* {@link PropertySourcesPlaceholdersResolver} that sanitizes sensitive placeholders
163+
* if present.
165164
*/
166-
private class PlaceholderSanitizingPropertyResolver
167-
extends PropertySourcesPropertyResolver {
165+
private static class PropertySourcesPlaceholdersSanitizingResolver
166+
extends PropertySourcesPlaceholdersResolver {
168167

169168
private final Sanitizer sanitizer;
170169

171-
/**
172-
* Create a new resolver against the given property sources.
173-
* @param propertySources the set of {@link PropertySource} objects to use
174-
* @param sanitizer the sanitizer used to sanitize sensitive values
175-
*/
176-
PlaceholderSanitizingPropertyResolver(PropertySources propertySources,
177-
Sanitizer sanitizer) {
178-
super(propertySources);
170+
public PropertySourcesPlaceholdersSanitizingResolver(
171+
Iterable<PropertySource<?>> sources, Sanitizer sanitizer) {
172+
super(sources, new PropertyPlaceholderHelper(
173+
SystemPropertyUtils.PLACEHOLDER_PREFIX,
174+
SystemPropertyUtils.PLACEHOLDER_SUFFIX,
175+
SystemPropertyUtils.VALUE_SEPARATOR, true));
179176
this.sanitizer = sanitizer;
180177
}
181178

182179
@Override
183-
protected String getPropertyAsRawString(String key) {
184-
String value = super.getPropertyAsRawString(key);
185-
return (String) this.sanitizer.sanitize(key, value);
180+
protected String resolvePlaceholder(String placeholder) {
181+
String value = super.resolvePlaceholder(placeholder);
182+
return (value != null ?
183+
(String) this.sanitizer.sanitize(placeholder, value) : null);
186184
}
187185

188186
}

spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ public void compositeSourceIsHandledCorrectly() {
7676
.environment(null);
7777
assertThat(getSource("composite:one", env).getProperties().get("foo").getValue())
7878
.isEqualTo("bar");
79+
assertThat(getSource("composite:two", env).getProperties().get("foo").getValue())
80+
.isEqualTo("spam");
7981
}
8082

8183
@Test

spring-boot/src/main/java/org/springframework/boot/context/properties/bind/PropertySourcesPlaceholdersResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public Object resolvePlaceholders(Object value) {
6363
return value;
6464
}
6565

66-
private String resolvePlaceholder(String placeholder) {
66+
protected String resolvePlaceholder(String placeholder) {
6767
if (this.sources != null) {
6868
for (PropertySource<?> source : this.sources) {
6969
Object value = source.getProperty(placeholder);

0 commit comments

Comments
 (0)