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
This commit is contained in:
Stephane Nicoll 2017-09-26 18:16:45 +02:00
parent f52c081ec1
commit eb045f1da1
3 changed files with 27 additions and 27 deletions

View File

@ -31,19 +31,20 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor;
import org.springframework.boot.actuate.env.EnvironmentEndpoint.EnvironmentDescriptor.PropertySourceDescriptor.PropertyValueDescriptor;
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
import org.springframework.boot.origin.OriginLookup;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySources;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.http.HttpStatus;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.StringUtils;
import org.springframework.util.SystemPropertyUtils;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
@ -85,7 +86,7 @@ public class EnvironmentEndpoint {
private EnvironmentDescriptor getEnvironmentDescriptor(
Predicate<String> propertyNamePredicate) {
PropertyResolver resolver = getResolver();
PlaceholdersResolver resolver = getResolver();
List<PropertySourceDescriptor> propertySources = new ArrayList<>();
getPropertySourcesAsMap().forEach((sourceName, source) -> {
if (source instanceof EnumerablePropertySource) {
@ -99,7 +100,7 @@ public class EnvironmentEndpoint {
}
private PropertySourceDescriptor describeSource(String sourceName,
EnumerablePropertySource<?> source, PropertyResolver resolver,
EnumerablePropertySource<?> source, PlaceholdersResolver resolver,
Predicate<String> namePredicate) {
Map<String, PropertyValueDescriptor> properties = new LinkedHashMap<>();
Stream.of(source.getPropertyNames()).filter(namePredicate).forEach(
@ -108,19 +109,17 @@ public class EnvironmentEndpoint {
}
private PropertyValueDescriptor describeValueOf(String name,
EnumerablePropertySource<?> source, PropertyResolver resolver) {
Object resolved = resolver.getProperty(name, Object.class);
EnumerablePropertySource<?> source, PlaceholdersResolver resolver) {
Object resolved = resolver.resolvePlaceholders(source.getProperty(name));
@SuppressWarnings("unchecked")
String origin = (source instanceof OriginLookup)
? ((OriginLookup<Object>) source).getOrigin(name).toString() : null;
return new PropertyValueDescriptor(sanitize(name, resolved), origin);
}
private PropertyResolver getResolver() {
PlaceholderSanitizingPropertyResolver resolver = new PlaceholderSanitizingPropertyResolver(
private PlaceholdersResolver getResolver() {
return new PropertySourcesPlaceholdersSanitizingResolver(
getPropertySources(), this.sanitizer);
resolver.setIgnoreUnresolvableNestedPlaceholders(true);
return resolver;
}
private Map<String, PropertySource<?>> getPropertySourcesAsMap() {
@ -160,29 +159,28 @@ public class EnvironmentEndpoint {
}
/**
* {@link PropertySourcesPropertyResolver} that sanitizes sensitive placeholders if
* present.
* {@link PropertySourcesPlaceholdersResolver} that sanitizes sensitive placeholders
* if present.
*/
private class PlaceholderSanitizingPropertyResolver
extends PropertySourcesPropertyResolver {
private static class PropertySourcesPlaceholdersSanitizingResolver
extends PropertySourcesPlaceholdersResolver {
private final Sanitizer sanitizer;
/**
* Create a new resolver against the given property sources.
* @param propertySources the set of {@link PropertySource} objects to use
* @param sanitizer the sanitizer used to sanitize sensitive values
*/
PlaceholderSanitizingPropertyResolver(PropertySources propertySources,
Sanitizer sanitizer) {
super(propertySources);
public PropertySourcesPlaceholdersSanitizingResolver(
Iterable<PropertySource<?>> sources, Sanitizer sanitizer) {
super(sources, new PropertyPlaceholderHelper(
SystemPropertyUtils.PLACEHOLDER_PREFIX,
SystemPropertyUtils.PLACEHOLDER_SUFFIX,
SystemPropertyUtils.VALUE_SEPARATOR, true));
this.sanitizer = sanitizer;
}
@Override
protected String getPropertyAsRawString(String key) {
String value = super.getPropertyAsRawString(key);
return (String) this.sanitizer.sanitize(key, value);
protected String resolvePlaceholder(String placeholder) {
String value = super.resolvePlaceholder(placeholder);
return (value != null ?
(String) this.sanitizer.sanitize(placeholder, value) : null);
}
}

View File

@ -76,6 +76,8 @@ public class EnvironmentEndpointTests {
.environment(null);
assertThat(getSource("composite:one", env).getProperties().get("foo").getValue())
.isEqualTo("bar");
assertThat(getSource("composite:two", env).getProperties().get("foo").getValue())
.isEqualTo("spam");
}
@Test

View File

@ -63,7 +63,7 @@ public class PropertySourcesPlaceholdersResolver implements PlaceholdersResolver
return value;
}
private String resolvePlaceholder(String placeholder) {
protected String resolvePlaceholder(String placeholder) {
if (this.sources != null) {
for (PropertySource<?> source : this.sources) {
Object value = source.getProperty(placeholder);