Make SystemEnvironmentPropertySource origin aware
Closes gh-9252
This commit is contained in:
parent
d745b69630
commit
6f022565a5
63
spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedSystemPropertySource.java
vendored
Normal file
63
spring-boot/src/main/java/org/springframework/boot/env/OriginTrackedSystemPropertySource.java
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.env;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.OriginLookup;
|
||||
import org.springframework.boot.origin.OriginTrackedValue;
|
||||
import org.springframework.core.env.SystemEnvironmentPropertySource;
|
||||
|
||||
/**
|
||||
* {@link SystemEnvironmentPropertySource} and {@link OriginLookup} backed by a map
|
||||
* containing {@link OriginTrackedValue OriginTrackedValues}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class OriginTrackedSystemPropertySource extends SystemEnvironmentPropertySource implements OriginLookup<String> {
|
||||
|
||||
/**
|
||||
* Create a new {@code OriginTrackedSystemPropertySource} with the given name and
|
||||
* delegating to the given {@code MapPropertySource}.
|
||||
* @param name the property name
|
||||
* @param source the underlying map
|
||||
*/
|
||||
public OriginTrackedSystemPropertySource(String name, Map<String, Object> source) {
|
||||
super(name, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
Object value = super.getProperty(name);
|
||||
if (value instanceof OriginTrackedValue) {
|
||||
return ((OriginTrackedValue) value).getValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Origin getOrigin(String key) {
|
||||
Object value = super.getProperty(key);
|
||||
if (value instanceof OriginTrackedValue) {
|
||||
return ((OriginTrackedValue) value).getOrigin();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.env;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.origin.OriginTrackedValue;
|
||||
import org.springframework.boot.origin.SystemEnvironmentOrigin;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.env.SystemEnvironmentPropertySource;
|
||||
|
||||
/**
|
||||
* An {@link EnvironmentPostProcessor} that replaces the systemEnvironment {@link SystemEnvironmentPropertySource}
|
||||
* with an {@link OriginTrackedSystemPropertySource} that can track the {@link SystemEnvironmentOrigin} for
|
||||
* every system environment property.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class SystemEnvironmentPropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
||||
|
||||
/**
|
||||
* The default order for the processor.
|
||||
*/
|
||||
public static final int DEFAULT_ORDER = SpringApplicationJsonEnvironmentPostProcessor.DEFAULT_ORDER - 1;
|
||||
|
||||
private int order = DEFAULT_ORDER;
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
String sourceName = StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME;
|
||||
PropertySource<?> propertySource = environment.getPropertySources().get(sourceName);
|
||||
if (propertySource != null) {
|
||||
replacePropertySource(environment, sourceName, propertySource);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void replacePropertySource(ConfigurableEnvironment environment, String sourceName, PropertySource<?> propertySource) {
|
||||
if (propertySource.getSource() instanceof Map) {
|
||||
Map<String, Object> originalSource = (Map<String, Object>) propertySource.getSource();
|
||||
Map<String, Object> originTrackedSource = new LinkedHashMap<>(originalSource);
|
||||
originTrackedSource.entrySet().forEach(e -> e.setValue(OriginTrackedValue.of(e.getValue(),
|
||||
new SystemEnvironmentOrigin(e.getKey()))));
|
||||
OriginTrackedSystemPropertySource source = new OriginTrackedSystemPropertySource(sourceName,
|
||||
Collections.unmodifiableMap(originTrackedSource));
|
||||
environment.getPropertySources().replace(sourceName, source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.origin;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link Origin} for an item loaded from the system environment. Provides access to the
|
||||
* original property name.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class SystemEnvironmentOrigin implements Origin {
|
||||
|
||||
private final String property;
|
||||
|
||||
public SystemEnvironmentOrigin(String property) {
|
||||
Assert.notNull(property, "Property name must not be null");
|
||||
Assert.hasText(property, "Property name must not be empty");
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public String getProperty() {
|
||||
return this.property;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "System Environment Property \"" + this.property + "\"";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = ObjectUtils.nullSafeHashCode(this.property);
|
||||
result = 31 * result + ObjectUtils.nullSafeHashCode(this.property);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
SystemEnvironmentOrigin other = (SystemEnvironmentOrigin) obj;
|
||||
return ObjectUtils.nullSafeEquals(this.property, other.property);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +33,8 @@ org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
|
|||
# Environment Post Processors
|
||||
org.springframework.boot.env.EnvironmentPostProcessor=\
|
||||
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
|
||||
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor
|
||||
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
|
||||
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor
|
||||
|
||||
# Failure Analyzers
|
||||
org.springframework.boot.diagnostics.FailureAnalyzer=\
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.env;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.OriginTrackedValue;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link OriginTrackedSystemPropertySource}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class OriginTrackedSystemPropertySourceTests {
|
||||
|
||||
private Map<String, Object> map = new LinkedHashMap<>();
|
||||
|
||||
private OriginTrackedSystemPropertySource source = new OriginTrackedSystemPropertySource(
|
||||
"test", this.map);
|
||||
|
||||
private Origin origin = mock(Origin.class);
|
||||
|
||||
@Test
|
||||
public void getPropertyWhenMissingShouldReturnNull() throws Exception {
|
||||
assertThat(this.source.getProperty("test")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyWhenNonTrackedShouldReturnValue() throws Exception {
|
||||
this.map.put("test", "foo");
|
||||
assertThat(this.source.getProperty("test")).isEqualTo("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyWhenTrackedShouldReturnValue() throws Exception {
|
||||
this.map.put("test", OriginTrackedValue.of("foo", this.origin));
|
||||
assertThat(this.source.getProperty("test")).isEqualTo("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyOriginWhenMissingShouldReturnNull() throws Exception {
|
||||
assertThat(this.source.getOrigin("test")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyOriginWhenNonTrackedShouldReturnNull() throws Exception {
|
||||
this.map.put("test", "foo");
|
||||
assertThat(this.source.getOrigin("test")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyOriginWhenTrackedShouldReturnOrigin() throws Exception {
|
||||
this.map.put("test", OriginTrackedValue.of("foo", this.origin));
|
||||
assertThat(this.source.getOrigin("test")).isEqualTo(this.origin);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.env;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.origin.OriginTrackedValue;
|
||||
import org.springframework.boot.origin.SystemEnvironmentOrigin;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SystemEnvironmentPropertySourceEnvironmentPostProcessor}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class SystemEnvironmentPropertySourceEnvironmentPostProcessorTests {
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.environment = new StandardEnvironment();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postProcessShouldReplaceSystemEnviromentPropertySource() throws Exception {
|
||||
SystemEnvironmentPropertySourceEnvironmentPostProcessor postProcessor = new SystemEnvironmentPropertySourceEnvironmentPostProcessor();
|
||||
postProcessor.postProcessEnvironment(this.environment, null);
|
||||
PropertySource<?> replaced = this.environment.getPropertySources().get("systemEnvironment");
|
||||
assertThat(replaced).isInstanceOf(OriginTrackedSystemPropertySource.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void replacedPropertySourceShouldHaveOriginTrackedValues() throws Exception {
|
||||
SystemEnvironmentPropertySourceEnvironmentPostProcessor postProcessor = new SystemEnvironmentPropertySourceEnvironmentPostProcessor();
|
||||
PropertySource<?> original = this.environment.getPropertySources().get("systemEnvironment");
|
||||
postProcessor.postProcessEnvironment(this.environment, null);
|
||||
PropertySource<?> replaced = this.environment.getPropertySources().get("systemEnvironment");
|
||||
Map<String, Object> originalMap = (Map<String, Object>) original.getSource();
|
||||
Map<String, OriginTrackedValue> replacedMap = (Map<String, OriginTrackedValue>) replaced.getSource();
|
||||
for (Map.Entry<String, Object> entry : originalMap.entrySet()) {
|
||||
OriginTrackedValue actual = replacedMap.get(entry.getKey());
|
||||
assertThat(actual.getValue()).isEqualTo(entry.getValue());
|
||||
assertThat(actual.getOrigin()).isEqualTo(new SystemEnvironmentOrigin(entry.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2012-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.origin;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SystemEnvironmentOrigin}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class SystemEnvironmentOriginTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void createWhenPropertyIsNullShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
new SystemEnvironmentOrigin(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWhenPropertyNameIsEmptyShouldThrowException() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
new SystemEnvironmentOrigin("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPropertyShouldReturnProperty() throws Exception {
|
||||
SystemEnvironmentOrigin origin = new SystemEnvironmentOrigin("FOO_BAR");
|
||||
assertThat(origin.getProperty()).isEqualTo("FOO_BAR");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringShouldReturnStringWithDetails() throws Exception {
|
||||
SystemEnvironmentOrigin origin = new SystemEnvironmentOrigin("FOO_BAR");
|
||||
assertThat(origin.toString()).isEqualTo("System Environment Property \"FOO_BAR\"");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue