From b4963d2463188153a9dd2e34af6b48dc5b47be51 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 6 May 2020 11:35:39 -0700 Subject: [PATCH] Fix legacy environment names in isAncestorOf Fix the `SystemEnvironmentPropertyMapper.isAncestorOf` implementation to convert names based on their dashed form and to silently ignore any invalid results. Closes gh-14479 --- .../SystemEnvironmentPropertyMapper.java | 34 ++++++++++++++----- .../SystemEnvironmentPropertyMapperTests.java | 8 +++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapper.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapper.java index 58b63c3525..55504c9426 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapper.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapper.java @@ -39,7 +39,7 @@ final class SystemEnvironmentPropertyMapper implements PropertyMapper { @Override public PropertyMapping[] map(ConfigurationPropertyName configurationPropertyName) { String name = convertName(configurationPropertyName); - String legacyName = convertLegacyName(configurationPropertyName, '_', true); + String legacyName = convertLegacyName(configurationPropertyName); if (name.equals(legacyName)) { return new PropertyMapping[] { new PropertyMapping(name, configurationPropertyName) }; } @@ -62,7 +62,25 @@ final class SystemEnvironmentPropertyMapper implements PropertyMapper { } private boolean isLegacyAncestorOf(ConfigurationPropertyName name, ConfigurationPropertyName candidate) { - return ConfigurationPropertyName.of(convertLegacyName(name, '.', false)).isAncestorOf(candidate); + if (!hasDashedEntries(name)) { + return false; + } + StringBuilder legacyCompatibleName = new StringBuilder(); + for (int i = 0; i < name.getNumberOfElements(); i++) { + legacyCompatibleName.append((i != 0) ? "." : ""); + legacyCompatibleName.append(name.getElement(i, Form.DASHED).replace('-', '.')); + } + return ConfigurationPropertyName.isValid(legacyCompatibleName) + && ConfigurationPropertyName.of(legacyCompatibleName).isAncestorOf(candidate); + } + + boolean hasDashedEntries(ConfigurationPropertyName name) { + for (int i = 0; i < name.getNumberOfElements(); i++) { + if (name.getElement(i, Form.DASHED).indexOf('-') != -1) { + return true; + } + } + return false; } private ConfigurationPropertyName convertName(String propertySourceName) { @@ -89,21 +107,19 @@ final class SystemEnvironmentPropertyMapper implements PropertyMapper { return result.toString(); } - private String convertLegacyName(ConfigurationPropertyName name, char joinChar, boolean uppercase) { + private String convertLegacyName(ConfigurationPropertyName name) { StringBuilder result = new StringBuilder(); for (int i = 0; i < name.getNumberOfElements(); i++) { if (result.length() > 0) { - result.append(joinChar); + result.append("_"); } - String element = name.getElement(i, Form.ORIGINAL); - result.append(convertLegacyNameElement(element, joinChar, uppercase)); + result.append(convertLegacyNameElement(name.getElement(i, Form.ORIGINAL))); } return result.toString(); } - private Object convertLegacyNameElement(String element, char joinChar, boolean uppercase) { - String converted = element.replace('-', joinChar); - return !uppercase ? converted : converted.toUpperCase(Locale.ENGLISH); + private Object convertLegacyNameElement(String element) { + return element.replace('-', '_').toUpperCase(Locale.ENGLISH); } private CharSequence processElementValue(CharSequence value) { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapperTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapperTests.java index 95e3826ea8..01458c2d21 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapperTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapperTests.java @@ -83,4 +83,12 @@ class SystemEnvironmentPropertyMapperTests extends AbstractPropertyMapperTests { assertThat(getMapper().isAncestorOf(name, ConfigurationPropertyName.of("my.boot.property"))).isFalse(); } + @Test + void isAncestorOfWhenCamelCaseSourceConsidersLegacyNames() { + ConfigurationPropertyName name = ConfigurationPropertyName.adapt("my.springBoot", '.'); + assertThat(getMapper().isAncestorOf(name, ConfigurationPropertyName.of("my.spring-boot.property"))).isTrue(); + assertThat(getMapper().isAncestorOf(name, ConfigurationPropertyName.of("my.springboot.property"))).isTrue(); + assertThat(getMapper().isAncestorOf(name, ConfigurationPropertyName.of("my.boot.property"))).isFalse(); + } + }