From 256ca681fd40b0935d3a1927fc08c60d64e4ecd7 Mon Sep 17 00:00:00 2001 From: chang-chao Date: Fri, 26 Oct 2018 00:40:08 +0900 Subject: [PATCH] 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 --- .../AliasedConfigurationPropertySource.java | 18 +++++++++---- .../ConfigurationPropertyNameAliases.java | 5 ++++ ...iasedConfigurationPropertySourceTests.java | 26 ++++++++++++++++++- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/AliasedConfigurationPropertySource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/AliasedConfigurationPropertySource.java index ea9496881b..6b2eefa708 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/AliasedConfigurationPropertySource.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/AliasedConfigurationPropertySource.java @@ -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 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; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyNameAliases.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyNameAliases.java index f668bae35f..36b33f74e4 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyNameAliases.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyNameAliases.java @@ -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 getAllNames() { + return this.aliases.keySet(); + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/AliasedConfigurationPropertySourceTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/AliasedConfigurationPropertySourceTests.java index ca9e4e34e5..fd1a7af93e 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/AliasedConfigurationPropertySourceTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/AliasedConfigurationPropertySourceTests.java @@ -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); }