From 43e5e83d9c8a690737b3f9e88282322cdf627f8c Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 29 Jan 2018 09:59:38 +0100 Subject: [PATCH] Transparently handle migration from number to java.util.Duration See gh-11794 --- .../migrator/PropertiesMigrationReporter.java | 38 ++++++++++++++---- .../PropertiesMigrationReporterTests.java | 26 ++++++++++++ .../metadata/type-conversion-metadata.json | 40 +++++++++++++++++++ 3 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 spring-boot-project/spring-boot-properties-migrator/src/test/resources/metadata/type-conversion-metadata.json diff --git a/spring-boot-project/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporter.java b/spring-boot-project/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporter.java index 8fc28340ec4..aee490daf64 100644 --- a/spring-boot-project/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporter.java +++ b/spring-boot-project/spring-boot-properties-migrator/src/main/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporter.java @@ -16,6 +16,7 @@ package org.springframework.boot.context.properties.migrator; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -108,21 +109,42 @@ class PropertiesMigrationReporter { ConfigurationMetadataProperty replacement = this.allProperties .get(replacementId); if (replacement != null) { - return replacement.getType().equals(metadata.getType()); - } - replacement = getMapProperty(replacementId); - if (replacement != null) { - return replacement.getType().startsWith("java.util.Map") - && replacement.getType().endsWith(metadata.getType() + ">"); + return isCompatibleType(metadata.getType(), replacement.getType()); } + return isCompatibleType(metadata.getType(), + detectMapValueReplacementType(replacementId)); + } + return false; + } + + private boolean isCompatibleType(String currentType, String replacementType) { + if (replacementType == null || currentType == null) { + return false; + } + if (replacementType.equals(currentType)) { + return true; + } + if (replacementType.equals(Duration.class.getName()) + && (currentType.equals(Long.class.getName()) + || currentType.equals(Integer.class.getName()))) { + return true; } return false; } - private ConfigurationMetadataProperty getMapProperty(String fullId) { + private String detectMapValueReplacementType(String fullId) { int i = fullId.lastIndexOf('.'); if (i != -1) { - return this.allProperties.get(fullId.substring(0, i)); + ConfigurationMetadataProperty property = this.allProperties.get( + fullId.substring(0, i)); + String type = property.getType(); + if (type != null + && type.startsWith(Map.class.getName())) { + int lastComma = type.lastIndexOf(','); + if (lastComma != -1) { + return type.substring(lastComma + 1, type.length() - 1).trim(); + } + } } return null; } diff --git a/spring-boot-project/spring-boot-properties-migrator/src/test/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporterTests.java b/spring-boot-project/spring-boot-properties-migrator/src/test/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporterTests.java index 0367de21b3c..7e03fef0a20 100644 --- a/spring-boot-project/spring-boot-properties-migrator/src/test/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporterTests.java +++ b/spring-boot-project/spring-boot-properties-migrator/src/test/java/org/springframework/boot/context/properties/migrator/PropertiesMigrationReporterTests.java @@ -18,7 +18,9 @@ package org.springframework.boot.context.properties.migrator; import java.io.IOException; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import org.junit.Test; @@ -29,6 +31,7 @@ import org.springframework.boot.env.PropertiesPropertySourceLoader; import org.springframework.boot.origin.Origin; import org.springframework.boot.origin.OriginLookup; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySources; @@ -115,6 +118,29 @@ public class PropertiesMigrationReporterTests { .doesNotContain("debug"); } + @Test + public void durationTypeIsHandledTransparently() { + MutablePropertySources propertySources = this.environment.getPropertySources(); + Map content = new LinkedHashMap<>(); + content.put("test.cache-seconds", 50); + content.put("test.time-to-live-ms", 1234L); + content.put("test.ttl", 5678L); + propertySources.addFirst( + new MapPropertySource("test", content)); + assertThat(propertySources).hasSize(2); + String report = createWarningReport( + loadRepository("metadata/type-conversion-metadata.json")); + assertThat(report).contains("Property source 'test'", "test.cache-seconds", + "test.cache", "test.time-to-live-ms", "test.time-to-live", "test.ttl", + "test.mapped.ttl"); + assertThat(mapToNames(propertySources)).containsExactly("migrate-test", "test", + "mockProperties"); + PropertySource propertySource = propertySources.get("migrate-test"); + assertMappedProperty(propertySource, "test.cache", 50, null); + assertMappedProperty(propertySource, "test.time-to-live", 1234L, null); + assertMappedProperty(propertySource, "test.mapped.ttl", 5678L, null); + } + private List mapToNames(PropertySources sources) { List names = new ArrayList<>(); for (PropertySource source : sources) { diff --git a/spring-boot-project/spring-boot-properties-migrator/src/test/resources/metadata/type-conversion-metadata.json b/spring-boot-project/spring-boot-properties-migrator/src/test/resources/metadata/type-conversion-metadata.json new file mode 100644 index 00000000000..d58e2f60241 --- /dev/null +++ b/spring-boot-project/spring-boot-properties-migrator/src/test/resources/metadata/type-conversion-metadata.json @@ -0,0 +1,40 @@ +{ + "properties": [ + { + "name": "test.cache", + "type": "java.time.Duration" + }, + { + "name": "test.time-to-live", + "type": "java.time.Duration" + }, + { + "name": "test.mapped", + "type": "java.util.Map" + }, + { + "name": "test.cache-seconds", + "type": "java.lang.Integer", + "deprecation": { + "replacement": "test.cache", + "level": "error" + } + }, + { + "name": "test.time-to-live-ms", + "type": "java.lang.Long", + "deprecation": { + "replacement": "test.time-to-live", + "level": "error" + } + }, + { + "name": "test.ttl", + "type": "java.lang.Long", + "deprecation": { + "replacement": "test.mapped.ttl", + "level": "error" + } + } + ] +} \ No newline at end of file