Skip to content

Commit

Permalink
detect properties of Map type that are marked as deprecated
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominic Croce authored and Dominic Croce committed Nov 24, 2021
1 parent 490ec89 commit a6ef481
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@

import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepository;
import org.springframework.boot.configurationmetadata.Deprecation;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
Expand Down Expand Up @@ -105,10 +107,50 @@ private Map<String, List<PropertyMigration>> getMatchingProperties(
result.add(name,
new PropertyMigration(configurationProperty, metadata, determineReplacementMetadata(metadata)));
}
getMatchingPropertiesForMapEntries(name, source, metadata, result);
}));
return result;
}

private void getMatchingPropertiesForMapEntries(String name, ConfigurationPropertySource source, ConfigurationMetadataProperty metadata, MultiValueMap<String, PropertyMigration> result) {
if (source.getUnderlyingSource() instanceof MapPropertySource && name.equals(metadata.getName())) {
MapPropertySource mapSource = ((MapPropertySource) source.getUnderlyingSource());
for (String propertyName: mapSource.getPropertyNames()) {
ConfigurationProperty configurationProperty = source.getConfigurationProperty(ConfigurationPropertyName.of(propertyName));
if (configurationProperty != null) {
ConfigurationMetadataProperty entryMetadata = generateMetadataForMapEntry(propertyName, metadata);
result.add(name,
new PropertyMigration(configurationProperty, entryMetadata, determineReplacementMetadata(entryMetadata)));
}
}
}
}

private ConfigurationMetadataProperty generateMetadataForMapEntry(String propertyName, ConfigurationMetadataProperty mapMetadata) {
ConfigurationMetadataProperty newMetadata = new ConfigurationMetadataProperty();
newMetadata.setName(propertyName);
newMetadata.setId(propertyName);
String entryName = propertyName.substring(propertyName.lastIndexOf("."));
Deprecation oldDeprecation = mapMetadata.getDeprecation();
if (oldDeprecation != null) {
Deprecation deprecation = new Deprecation();
deprecation.setLevel(oldDeprecation.getLevel());
deprecation.setReason(oldDeprecation.getReason());
deprecation.setShortReason(oldDeprecation.getShortReason());
deprecation.setReplacement(oldDeprecation.getReplacement() + entryName);
newMetadata.setDeprecation(deprecation);
}

String type = mapMetadata.getType();
if (type.startsWith(Map.class.getName())) {
int lastComma = type.lastIndexOf(',');
if (lastComma != -1) {
newMetadata.setType(type.substring(lastComma + 1, type.length() - 1).trim());
}
}
return newMetadata;
}

private ConfigurationMetadataProperty determineReplacementMetadata(ConfigurationMetadataProperty metadata) {
String replacementId = metadata.getDeprecation().getReplacement();
if (StringUtils.hasText(replacementId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,30 @@ void invalidReplacementHandled() throws IOException {
assertThat(report).doesNotContain("null");
}

@Test
void detectDeprecatedPropertyInMap() {
MutablePropertySources propertySources = this.environment.getPropertySources();
Map<String, Object> content = new LinkedHashMap<>();
content.put("status.http-mapping.down", 500);
content.put("status.http-mapping.out-of-service", 503);
content.put("status.http-mapping.warning", 500);
propertySources.addFirst(new MapPropertySource("status.http-mapping", content));
assertThat(propertySources).hasSize(2);

String report = createWarningReport(loadRepository("metadata/map-deprecated-metadata.json"));
assertThat(report).isNotNull();
assertThat(report).contains("Property source 'status.http-mapping'", "Key: status.http-mapping.down",
"Replacement: endpoint.status.http-mapping.down", "Key: status.http-mapping.out-of-service",
"Replacement: endpoint.status.http-mapping.out-of-service", "Key: status.http-mapping.warning",
"Replacement: endpoint.status.http-mapping.warning");
assertThat(mapToNames(propertySources)).containsExactly("migrate-status.http-mapping", "status.http-mapping", "mockProperties");
PropertySource<?> propertySource = propertySources.get("migrate-status.http-mapping");
assertThat(propertySource).isNotNull();
assertMappedProperty(propertySource, "endpoint.status.http-mapping.down", 500, null);
assertMappedProperty(propertySource, "endpoint.status.http-mapping.out-of-service", 503, null);
assertMappedProperty(propertySource, "endpoint.status.http-mapping.warning", 500, null);
}

private List<String> mapToNames(PropertySources sources) {
List<String> names = new ArrayList<>();
for (PropertySource<?> source : sources) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"properties": [
{
"name": "status.http-mapping",
"type": "java.util.Map<java.lang.String,java.lang.Integer>",
"deprecated": true,
"deprecation": {
"replacement": "endpoint.status.http-mapping"
}
},
{
"name": "endpoint.status.http-mapping",
"type": "java.util.Map<java.lang.String,java.lang.Integer>",
"description": ""
}
]
}

0 comments on commit a6ef481

Please sign in to comment.