Merge branch '3.1.x'
This commit is contained in:
commit
8afbff3f28
|
@ -17,9 +17,11 @@
|
||||||
package org.springframework.boot.context.properties.migrator;
|
package org.springframework.boot.context.properties.migrator;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -86,15 +88,27 @@ class PropertiesMigrationReporter {
|
||||||
if (renamed.isEmpty()) {
|
if (renamed.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
NameTrackingPropertySource nameTrackingPropertySource = new NameTrackingPropertySource();
|
||||||
|
this.environment.getPropertySources().addFirst(nameTrackingPropertySource);
|
||||||
|
try {
|
||||||
String target = "migrate-" + name;
|
String target = "migrate-" + name;
|
||||||
Map<String, OriginTrackedValue> content = new LinkedHashMap<>();
|
Map<String, OriginTrackedValue> content = new LinkedHashMap<>();
|
||||||
for (PropertyMigration candidate : renamed) {
|
for (PropertyMigration candidate : renamed) {
|
||||||
OriginTrackedValue value = OriginTrackedValue.of(candidate.getProperty().getValue(),
|
String newPropertyName = candidate.getNewPropertyName();
|
||||||
|
Object value = candidate.getProperty().getValue();
|
||||||
|
if (nameTrackingPropertySource.isPlaceholderThatAccessesName(value, newPropertyName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
OriginTrackedValue originTrackedValue = OriginTrackedValue.of(value,
|
||||||
candidate.getProperty().getOrigin());
|
candidate.getProperty().getOrigin());
|
||||||
content.put(candidate.getNewPropertyName(), value);
|
content.put(newPropertyName, originTrackedValue);
|
||||||
}
|
}
|
||||||
return new OriginTrackedMapPropertySource(target, content);
|
return new OriginTrackedMapPropertySource(target, content);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
this.environment.getPropertySources().remove(nameTrackingPropertySource.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isMapType(ConfigurationMetadataProperty property) {
|
private boolean isMapType(ConfigurationMetadataProperty property) {
|
||||||
String type = property.getType();
|
String type = property.getType();
|
||||||
|
@ -172,4 +186,33 @@ class PropertiesMigrationReporter {
|
||||||
return source.getUnderlyingSource().toString();
|
return source.getUnderlyingSource().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link PropertySource} used to track accessed properties to protect against
|
||||||
|
* circular references.
|
||||||
|
*/
|
||||||
|
private class NameTrackingPropertySource extends PropertySource<Object> {
|
||||||
|
|
||||||
|
private final Set<String> accessedNames = new HashSet<>();
|
||||||
|
|
||||||
|
NameTrackingPropertySource() {
|
||||||
|
super(NameTrackingPropertySource.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isPlaceholderThatAccessesName(Object value, String name) {
|
||||||
|
if (value instanceof String) {
|
||||||
|
this.accessedNames.clear();
|
||||||
|
PropertiesMigrationReporter.this.environment.resolvePlaceholders((String) value);
|
||||||
|
return this.accessedNames.contains(name);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getProperty(String name) {
|
||||||
|
this.accessedNames.add(name);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@ class PropertiesMigrationReporterTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mapPropertiesDeprecatedNoReplacement() throws IOException {
|
void mapPropertiesDeprecatedNoReplacement() {
|
||||||
this.environment.getPropertySources()
|
this.environment.getPropertySources()
|
||||||
.addFirst(
|
.addFirst(
|
||||||
new MapPropertySource("first", Collections.singletonMap("custom.map-no-replacement.key", "value")));
|
new MapPropertySource("first", Collections.singletonMap("custom.map-no-replacement.key", "value")));
|
||||||
|
@ -173,7 +173,7 @@ class PropertiesMigrationReporterTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mapPropertiesDeprecatedWithReplacement() throws IOException {
|
void mapPropertiesDeprecatedWithReplacement() {
|
||||||
this.environment.getPropertySources()
|
this.environment.getPropertySources()
|
||||||
.addFirst(new MapPropertySource("first",
|
.addFirst(new MapPropertySource("first",
|
||||||
Collections.singletonMap("custom.map-with-replacement.key", "value")));
|
Collections.singletonMap("custom.map-with-replacement.key", "value")));
|
||||||
|
@ -205,6 +205,14 @@ class PropertiesMigrationReporterTests {
|
||||||
.contains("Replacement: custom.the-map-replacement.key");
|
.contains("Replacement: custom.the-map-replacement.key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // gh-35919
|
||||||
|
void directCircularReference() {
|
||||||
|
this.environment.getPropertySources()
|
||||||
|
.addFirst(new MapPropertySource("backcompat", Collections.singletonMap("wrong.two", "${test.two}")));
|
||||||
|
createAnalyzer(loadRepository("metadata/sample-metadata.json")).getReport();
|
||||||
|
assertThat(this.environment.getProperty("test.two")).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> mapToNames(PropertySources sources) {
|
private List<String> mapToNames(PropertySources sources) {
|
||||||
List<String> names = new ArrayList<>();
|
List<String> names = new ArrayList<>();
|
||||||
for (PropertySource<?> source : sources) {
|
for (PropertySource<?> source : sources) {
|
||||||
|
|
Loading…
Reference in New Issue