Merge branch '2.4.x' into 2.5.x

Closes gh-27346
pull/27366/head
Andy Wilkinson 3 years ago
commit d4159130a5

@ -313,7 +313,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
private Map<String, Object> getInput(String property, ConfigurationProperty candidate) { private Map<String, Object> getInput(String property, ConfigurationProperty candidate) {
Map<String, Object> input = new LinkedHashMap<>(); Map<String, Object> input = new LinkedHashMap<>();
Object value = candidate.getValue(); Object value = stringifyIfNecessary(candidate.getValue());
Origin origin = Origin.from(candidate); Origin origin = Origin.from(candidate);
List<Origin> originParents = Origin.parentsFrom(candidate); List<Origin> originParents = Origin.parentsFrom(candidate);
input.put("value", this.sanitizer.sanitize(property, value)); input.put("value", this.sanitizer.sanitize(property, value));
@ -324,6 +324,16 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
return input; return input;
} }
private Object stringifyIfNecessary(Object value) {
if (value == null || value.getClass().isPrimitive()) {
return value;
}
if (CharSequence.class.isAssignableFrom(value.getClass())) {
return value.toString();
}
return "Complex property value " + value.getClass().getName();
}
private String getQualifiedKey(String prefix, String key) { private String getQualifiedKey(String prefix, String key) {
return (prefix.isEmpty() ? prefix : prefix + ".") + key; return (prefix.isEmpty() ? prefix : prefix + ".") + key;
} }

@ -16,8 +16,12 @@
package org.springframework.boot.actuate.context.properties; package org.springframework.boot.actuate.context.properties;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -28,11 +32,16 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties; import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ApplicationConfigurationProperties;
import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesBeanDescriptor; import org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesBeanDescriptor;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.io.InputStreamSource;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.entry;
@ -238,6 +247,43 @@ class ConfigurationPropertiesReportEndpointSerializationTests {
}); });
} }
@Test
@SuppressWarnings("unchecked")
void endpointResponseUsesToStringOfCharSequenceAsPropertyValue() throws IOException {
ApplicationContextRunner contextRunner = new ApplicationContextRunner().withInitializer((context) -> {
ConfigurableEnvironment environment = context.getEnvironment();
environment.getPropertySources().addFirst(new MapPropertySource("test",
Collections.singletonMap("foo.name", new CharSequenceProperty("Spring Boot"))));
}).withUserConfiguration(FooConfig.class);
contextRunner.run((context) -> {
ConfigurationPropertiesReportEndpoint endpoint = context
.getBean(ConfigurationPropertiesReportEndpoint.class);
ApplicationConfigurationProperties applicationProperties = endpoint.configurationProperties();
ConfigurationPropertiesBeanDescriptor descriptor = applicationProperties.getContexts().get(context.getId())
.getBeans().get("foo");
assertThat((Map<String, Object>) descriptor.getInputs().get("name")).containsEntry("value", "Spring Boot");
});
}
@Test
@SuppressWarnings("unchecked")
void endpointResponseUsesPlaceholderForComplexValueAsPropertyValue() throws IOException {
ApplicationContextRunner contextRunner = new ApplicationContextRunner().withInitializer((context) -> {
ConfigurableEnvironment environment = context.getEnvironment();
environment.getPropertySources().addFirst(new MapPropertySource("test",
Collections.singletonMap("foo.name", new ComplexProperty("Spring Boot"))));
}).withUserConfiguration(ComplexPropertyToStringConverter.class, FooConfig.class);
contextRunner.run((context) -> {
ConfigurationPropertiesReportEndpoint endpoint = context
.getBean(ConfigurationPropertiesReportEndpoint.class);
ApplicationConfigurationProperties applicationProperties = endpoint.configurationProperties();
ConfigurationPropertiesBeanDescriptor descriptor = applicationProperties.getContexts().get(context.getId())
.getBeans().get("foo");
assertThat((Map<String, Object>) descriptor.getInputs().get("name")).containsEntry("value",
"Complex property value " + ComplexProperty.class.getName());
});
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties @EnableConfigurationProperties
static class Base { static class Base {
@ -518,4 +564,59 @@ class ConfigurationPropertiesReportEndpointSerializationTests {
} }
static class CharSequenceProperty implements CharSequence, InputStreamSource {
private final String value;
CharSequenceProperty(String value) {
this.value = value;
}
@Override
public int length() {
return this.value.length();
}
@Override
public char charAt(int index) {
return this.value.charAt(index);
}
@Override
public CharSequence subSequence(int start, int end) {
return this.value.subSequence(start, end);
}
@Override
public String toString() {
return this.value;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(this.value.getBytes());
}
}
static class ComplexProperty {
private final String value;
ComplexProperty(String value) {
this.value = value;
}
}
@ConfigurationPropertiesBinding
static class ComplexPropertyToStringConverter implements Converter<ComplexProperty, String> {
@Override
public String convert(ComplexProperty source) {
return source.value;
}
}
} }

Loading…
Cancel
Save