Consider aliases when checking descendants

Update `AliasedConfigurationPropertySource` to consider aliases in
`containsDescendantOf`.

Prior to this commit, given a source containing `example.name` with
a defined alias of `other.name -> example.name` calling
`containsDescendantOf("other")` would incorrectly return
`ConfigurationPropertyState.ABSENT`.

Closes gh-14967
pull/16246/head
chang-chao 6 years ago committed by Phillip Webb
parent 7bb6df4206
commit 256ca681fd

@ -16,6 +16,8 @@
package org.springframework.boot.context.properties.source;
import java.util.Set;
import org.springframework.util.Assert;
/**
@ -58,11 +60,17 @@ class AliasedConfigurationPropertySource implements ConfigurationPropertySource
if (result != ConfigurationPropertyState.ABSENT) {
return result;
}
for (ConfigurationPropertyName alias : getAliases().getAliases(name)) {
ConfigurationPropertyState aliasResult = this.source
.containsDescendantOf(alias);
if (aliasResult != ConfigurationPropertyState.ABSENT) {
return aliasResult;
Set<ConfigurationPropertyName> aliasNames = this.aliases.getAllNames();
for (ConfigurationPropertyName configurationPropertyName : aliasNames) {
boolean descendantPresentInAlias = this.aliases
.getAliases(configurationPropertyName).stream()
.filter(name::isAncestorOf).findFirst().isPresent();
if (descendantPresentInAlias) {
ConfigurationProperty configurationProperty = this.getSource()
.getConfigurationProperty(configurationPropertyName);
if (configurationProperty != null) {
return ConfigurationPropertyState.PRESENT;
}
}
}
return ConfigurationPropertyState.ABSENT;

@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
@ -74,4 +75,8 @@ public final class ConfigurationPropertyNameAliases {
.findFirst().orElse(null);
}
public Set<ConfigurationPropertyName> getAllNames() {
return this.aliases.keySet();
}
}

@ -19,6 +19,8 @@ package org.springframework.boot.context.properties.source;
import org.junit.Test;
import org.mockito.Answers;
import org.springframework.boot.origin.Origin;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
@ -105,8 +107,30 @@ public class AliasedConfigurationPropertySourceTests {
.willReturn(ConfigurationPropertyState.ABSENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(ConfigurationPropertyState.PRESENT);
ConfigurationPropertyName barBar = ConfigurationPropertyName.of("bar.bar");
given(source.getConfigurationProperty(barBar)).willReturn(
new ConfigurationProperty(barBar, "barBarValue", mock(Origin.class)));
ConfigurationPropertySource aliased = source
.withAliases(new ConfigurationPropertyNameAliases("foo", "bar"));
.withAliases(new ConfigurationPropertyNameAliases("bar.bar", "foo.foo"));
assertThat(aliased.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.PRESENT);
}
@Test
public void containsDescendantOfWhenPresentInAliasShouldReturnPresent() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("baz");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
given(source.containsDescendantOf(name))
.willReturn(ConfigurationPropertyState.ABSENT);
ConfigurationPropertyName barFoo = ConfigurationPropertyName.of("bar.foo");
given(source.getConfigurationProperty(barFoo)).willReturn(
new ConfigurationProperty(barFoo, "barFooValue", mock(Origin.class)));
ConfigurationPropertySource aliased = source
.withAliases(new ConfigurationPropertyNameAliases("bar.foo", "baz.foo"));
assertThat(aliased.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.PRESENT);
}

Loading…
Cancel
Save