Add prefix support for property source
We configure the `SystemEnvironmentPropertySource` as a `Prefixed` property source. When adapting this to a `ConfigurationPropertySource, a `PrefixedConfigurationPropertySource` will be created for it. A `PrefixedConfigurationPropertySource` will resolve property such as `foo.bar` to `my.foo.bar` for a prefix of `my`. Closes gh-3450pull/25445/head
parent
888ca442fa
commit
a8592f36d4
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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.context.properties.source;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link ConfigurationPropertySource} supporting a prefix.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
class PrefixedConfigurationPropertySource implements ConfigurationPropertySource {
|
||||
|
||||
private final ConfigurationPropertySource source;
|
||||
|
||||
private final String prefix;
|
||||
|
||||
PrefixedConfigurationPropertySource(ConfigurationPropertySource source, String prefix) {
|
||||
Assert.notNull(source, "Source must not be null");
|
||||
Assert.notNull(prefix, "Prefix must not be null");
|
||||
this.source = source;
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
|
||||
ConfigurationProperty configurationProperty = this.source.getConfigurationProperty(getPrefixedName(name));
|
||||
if (configurationProperty == null) {
|
||||
return null;
|
||||
}
|
||||
return ConfigurationProperty.of(name, configurationProperty.getValue(), configurationProperty.getOrigin());
|
||||
}
|
||||
|
||||
private ConfigurationPropertyName getPrefixedName(ConfigurationPropertyName name) {
|
||||
String prefix = (StringUtils.hasText(this.prefix)) ? this.prefix + "." : "";
|
||||
return ConfigurationPropertyName.of(prefix + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name) {
|
||||
return this.source.containsDescendantOf(getPrefixedName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getUnderlyingSource() {
|
||||
return this.source.getUnderlyingSource();
|
||||
}
|
||||
|
||||
protected ConfigurationPropertySource getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
protected String getPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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.context.properties.source;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* An iterable {@link PrefixedConfigurationPropertySource}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
class PrefixedIterableConfigurationPropertySource extends PrefixedConfigurationPropertySource
|
||||
implements IterableConfigurationPropertySource {
|
||||
|
||||
PrefixedIterableConfigurationPropertySource(IterableConfigurationPropertySource source, String prefix) {
|
||||
super(source, prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ConfigurationPropertyName> stream() {
|
||||
ConfigurationPropertyName prefix = ConfigurationPropertyName.of(getPrefix());
|
||||
return getSource().stream().map((propertyName) -> {
|
||||
if (prefix.isAncestorOf(propertyName)) {
|
||||
String name = propertyName.toString();
|
||||
return ConfigurationPropertyName.of(name.substring(getPrefix().length() + 1));
|
||||
}
|
||||
return propertyName;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IterableConfigurationPropertySource getSource() {
|
||||
return (IterableConfigurationPropertySource) super.getSource();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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;
|
||||
|
||||
/**
|
||||
* Interface that can be implemented by a
|
||||
* {@link org.springframework.core.env.PropertySource} that can be used with a prefix.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.5.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Prefixed {
|
||||
|
||||
String getPrefix();
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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.context.properties.source;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Answers;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link PrefixedConfigurationPropertySource}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
class PrefixedConfigurationPropertySourceTests {
|
||||
|
||||
@Test
|
||||
void getConfigurationPropertyShouldConsiderPrefix() {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("my.foo.bar", "bing");
|
||||
source.put("my.foo.baz", "biff");
|
||||
ConfigurationPropertySource prefixed = source.nonIterable().withPrefix("my");
|
||||
assertThat(getName(prefixed, "foo.bar").toString()).isEqualTo("foo.bar");
|
||||
assertThat(getValue(prefixed, "foo.bar")).isEqualTo("bing");
|
||||
assertThat(getName(prefixed, "foo.baz").toString()).isEqualTo("foo.baz");
|
||||
assertThat(getValue(prefixed, "foo.baz")).isEqualTo("biff");
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsDescendantOfWhenSourceReturnsUnknownShouldReturnUnknown() {
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.foo");
|
||||
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
|
||||
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.UNKNOWN);
|
||||
ConfigurationPropertySource prefixed = source.withPrefix("my");
|
||||
assertThat(prefixed.containsDescendantOf(ConfigurationPropertyName.of("foo")))
|
||||
.isEqualTo(ConfigurationPropertyState.UNKNOWN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsDescendantOfWhenSourceReturnsPresentShouldReturnPresent() {
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.foo");
|
||||
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
|
||||
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.PRESENT);
|
||||
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
|
||||
.willReturn(ConfigurationPropertyState.UNKNOWN);
|
||||
ConfigurationPropertySource prefixed = source.withPrefix("my");
|
||||
assertThat(prefixed.containsDescendantOf(ConfigurationPropertyName.of("foo")))
|
||||
.isEqualTo(ConfigurationPropertyState.PRESENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsDescendantOfWhenSourceReturnsAbsentShouldReturnAbsent() {
|
||||
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.foo");
|
||||
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
|
||||
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.ABSENT);
|
||||
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
|
||||
.willReturn(ConfigurationPropertyState.ABSENT);
|
||||
ConfigurationPropertySource prefixed = source.withPrefix("my");
|
||||
assertThat(prefixed.containsDescendantOf(ConfigurationPropertyName.of("foo")))
|
||||
.isEqualTo(ConfigurationPropertyState.ABSENT);
|
||||
}
|
||||
|
||||
private ConfigurationPropertyName getName(ConfigurationPropertySource source, String name) {
|
||||
ConfigurationProperty property = source.getConfigurationProperty(ConfigurationPropertyName.of(name));
|
||||
return (property != null) ? property.getName() : null;
|
||||
}
|
||||
|
||||
private Object getValue(ConfigurationPropertySource source, String name) {
|
||||
ConfigurationProperty property = source.getConfigurationProperty(ConfigurationPropertyName.of(name));
|
||||
return (property != null) ? property.getValue() : null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2012-2021 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
|
||||
*
|
||||
* https://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.context.properties.source;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link PrefixedIterableConfigurationPropertySource}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
class PrefixedIterableConfigurationPropertySourceTests {
|
||||
|
||||
@Test
|
||||
void streamShouldConsiderPrefix() {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("my.foo.bar", "bing");
|
||||
source.put("my.foo.baz", "biff");
|
||||
source.put("hello.bing", "blah");
|
||||
IterableConfigurationPropertySource prefixed = source.withPrefix("my");
|
||||
assertThat(prefixed.stream()).containsExactly(ConfigurationPropertyName.of("foo.bar"),
|
||||
ConfigurationPropertyName.of("foo.baz"), ConfigurationPropertyName.of("hello.bing"));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue