Make SpringApplicationJsonEnvironmentPostProcessor origin aware

Closes gh-8932
This commit is contained in:
Madhura Bhave
2017-05-10 12:33:12 -07:00
parent f4444a36b3
commit 226db4697f
2 changed files with 43 additions and 16 deletions

View File

@@ -19,6 +19,7 @@ package org.springframework.boot.env;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.StreamSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -26,15 +27,15 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.json.JsonParser;
import org.springframework.boot.json.JsonParserFactory;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.boot.origin.PropertySourceOrigin;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.StandardServletEnvironment;
/**
@@ -45,6 +46,7 @@ import org.springframework.web.context.support.StandardServletEnvironment;
*
* @author Dave Syer
* @author Phillip Webb
* @author Madhura Bhave
* @since 1.3.0
*/
public class SpringApplicationJsonEnvironmentPostProcessor
@@ -75,20 +77,30 @@ public class SpringApplicationJsonEnvironmentPostProcessor
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
String json = environment.resolvePlaceholders(
"${spring.application.json:${SPRING_APPLICATION_JSON:}}");
if (StringUtils.hasText(json)) {
processJson(environment, json);
MutablePropertySources propertySources = environment.getPropertySources();
PropertySource<?> source = StreamSupport.stream(propertySources.spliterator(), false)
.filter(s -> getProperty(s) != null)
.findFirst().orElse(null);
if (source != null) {
String json = (String) getProperty(source);
processJson(environment, json, source);
}
}
private void processJson(ConfigurableEnvironment environment, String json) {
private Object getProperty(PropertySource<?> source) {
if (source.containsProperty("spring.application.json")) {
return source.getProperty("spring.application.json");
}
return source.getProperty("SPRING_APPLICATION_JSON");
}
private void processJson(ConfigurableEnvironment environment, String json, PropertySource source) {
try {
JsonParser parser = JsonParserFactory.getJsonParser();
Map<String, Object> map = parser.parseMap(json);
if (!map.isEmpty()) {
addJsonPropertySource(environment,
new MapPropertySource("spring.application.json", flatten(map)));
new OriginTrackedMapPropertySource("spring.application.json", flatten(map, source)));
}
}
catch (Exception ex) {
@@ -99,36 +111,38 @@ public class SpringApplicationJsonEnvironmentPostProcessor
/**
* Flatten the map keys using period separator.
* @param map The map that should be flattened
* @param source The property source for spring.application.json or SPRING_APPLICATION_JSON
* @return the flattened map
*/
private Map<String, Object> flatten(Map<String, Object> map) {
private Map<String, Object> flatten(Map<String, Object> map, PropertySource source) {
Map<String, Object> result = new LinkedHashMap<>();
flatten(null, result, map);
flatten(null, result, map, source);
return result;
}
private void flatten(String prefix, Map<String, Object> result,
Map<String, Object> map) {
Map<String, Object> map, PropertySource source) {
prefix = (prefix == null ? "" : prefix + ".");
for (Map.Entry<String, Object> entry : map.entrySet()) {
extract(prefix + entry.getKey(), result, entry.getValue());
extract(prefix + entry.getKey(), result, entry.getValue(), source);
}
}
@SuppressWarnings("unchecked")
private void extract(String name, Map<String, Object> result, Object value) {
private void extract(String name, Map<String, Object> result, Object value, PropertySource source) {
if (value instanceof Map) {
flatten(name, result, (Map<String, Object>) value);
flatten(name, result, (Map<String, Object>) value, source);
}
else if (value instanceof Collection) {
int index = 0;
for (Object object : (Collection<Object>) value) {
extract(name + "[" + index + "]", result, object);
extract(name + "[" + index + "]", result, object, source);
index++;
}
}
else {
result.put(name, value);
OriginTrackedValue originTrackedValue = OriginTrackedValue.of(value, PropertySourceOrigin.get(source, name));
result.put(name, originTrackedValue);
}
}

View File

@@ -18,7 +18,9 @@ package org.springframework.boot.env;
import org.junit.Test;
import org.springframework.boot.origin.PropertySourceOrigin;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.test.context.support.TestPropertySourceUtils;
@@ -116,4 +118,15 @@ public class SpringApplicationJsonEnvironmentPostProcessorTests {
.isEqualTo("spam");
}
@Test
public void propertySourceShouldTrackOrigin() throws Exception {
assertThat(this.environment.resolvePlaceholders("${foo:}")).isEmpty();
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.application.json={\"foo\":\"bar\"}");
this.processor.postProcessEnvironment(this.environment, null);
PropertySource<?> propertySource = this.environment.getPropertySources().get("spring.application.json");
PropertySourceOrigin origin = (PropertySourceOrigin) PropertySourceOrigin.get(propertySource, "foo");
assertThat(origin.getPropertySource().getName()).isEqualTo("Inlined Test Properties");
assertThat(this.environment.resolvePlaceholders("${foo:}")).isEqualTo("bar");
}
}