Rename configuration-analyzer
Rename `spring-boot-configuration-analyzer` to `spring-boot-deprecated-properties-support`. Also renamed classes to match and polished some of the code. See gh-11301
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
<module>spring-boot-actuator</module>
|
<module>spring-boot-actuator</module>
|
||||||
<module>spring-boot-actuator-autoconfigure</module>
|
<module>spring-boot-actuator-autoconfigure</module>
|
||||||
<module>spring-boot-autoconfigure</module>
|
<module>spring-boot-autoconfigure</module>
|
||||||
<module>spring-boot-configuration-analyzer</module>
|
<module>spring-boot-deprecated-properties-support</module>
|
||||||
<module>spring-boot-devtools</module>
|
<module>spring-boot-devtools</module>
|
||||||
<module>spring-boot-test</module>
|
<module>spring-boot-test</module>
|
||||||
<module>spring-boot-test-autoconfigure</module>
|
<module>spring-boot-test-autoconfigure</module>
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
org.springframework.context.ApplicationListener=\
|
|
||||||
org.springframework.boot.configurationalayzer.LegacyPropertiesAnalyzerListener
|
|
||||||
@@ -8,9 +8,9 @@
|
|||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
<relativePath>../spring-boot-parent</relativePath>
|
<relativePath>../spring-boot-parent</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-boot-configuration-analyzer</artifactId>
|
<artifactId>spring-boot-deprecated-properties-support</artifactId>
|
||||||
<name>Spring Boot Configuration Analyzer</name>
|
<name>Spring Boot Deprecated Properties Support</name>
|
||||||
<description>Spring Boot Configuration Analyzer</description>
|
<description>Spring Boot Deprecated Properties Support</description>
|
||||||
<properties>
|
<properties>
|
||||||
<main.basedir>${basedir}/../..</main.basedir>
|
<main.basedir>${basedir}/../..</main.basedir>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -14,12 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.configurationalayzer;
|
package org.springframework.boot.deprecatedproperties;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@@ -37,20 +35,21 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link ApplicationListener} that inspects the {@link ConfigurableEnvironment
|
* An {@link ApplicationListener} that inspects the {@link ConfigurableEnvironment
|
||||||
* environment} for legacy configuration keys. Automatically renames the keys that
|
* environment} for deprecated configuration keys. Automatically renames the keys that
|
||||||
* have a matching replacement and log a report of what was discovered.
|
* have a matching replacement and log a report of what was discovered.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public class LegacyPropertiesAnalyzerListener
|
public class DeprecatedPropertiesListener
|
||||||
implements ApplicationListener<SpringApplicationEvent> {
|
implements ApplicationListener<SpringApplicationEvent> {
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(LegacyPropertiesAnalyzerListener.class);
|
private static final Log logger = LogFactory
|
||||||
|
.getLog(DeprecatedPropertiesListener.class);
|
||||||
|
|
||||||
private LegacyPropertiesAnalysis analysis;
|
private DeprecatedPropertiesReport report;
|
||||||
|
|
||||||
private boolean analysisLogged;
|
private boolean reported;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(SpringApplicationEvent event) {
|
public void onApplicationEvent(SpringApplicationEvent event) {
|
||||||
@@ -65,49 +64,45 @@ public class LegacyPropertiesAnalyzerListener
|
|||||||
|
|
||||||
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
|
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
|
||||||
ConfigurationMetadataRepository repository = loadRepository();
|
ConfigurationMetadataRepository repository = loadRepository();
|
||||||
ConfigurableEnvironment environment =
|
DeprecatedPropertiesReporter reporter = new DeprecatedPropertiesReporter(repository,
|
||||||
event.getApplicationContext().getEnvironment();
|
event.getApplicationContext().getEnvironment());
|
||||||
LegacyPropertiesAnalyzer validator = new LegacyPropertiesAnalyzer(
|
this.report = reporter.getReport();
|
||||||
repository, environment);
|
|
||||||
this.analysis = validator.analyseLegacyProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logLegacyPropertiesAnalysis() {
|
|
||||||
if (this.analysis == null || this.analysisLogged) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String warningReport = this.analysis.createWarningReport();
|
|
||||||
String errorReport = this.analysis.createErrorReport();
|
|
||||||
if (warningReport != null) {
|
|
||||||
logger.warn(warningReport);
|
|
||||||
}
|
|
||||||
if (errorReport != null) {
|
|
||||||
logger.error(errorReport);
|
|
||||||
}
|
|
||||||
this.analysisLogged = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigurationMetadataRepository loadRepository() {
|
private ConfigurationMetadataRepository loadRepository() {
|
||||||
try {
|
try {
|
||||||
ConfigurationMetadataRepositoryJsonBuilder builder = ConfigurationMetadataRepositoryJsonBuilder.create();
|
return loadRepository(ConfigurationMetadataRepositoryJsonBuilder.create());
|
||||||
for (InputStream inputStream : getResources()) {
|
|
||||||
builder.withJsonResource(inputStream);
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
throw new IllegalStateException("Failed to load metadata", ex);
|
throw new IllegalStateException("Failed to load metadata", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<InputStream> getResources() throws IOException {
|
private ConfigurationMetadataRepository loadRepository(
|
||||||
|
ConfigurationMetadataRepositoryJsonBuilder builder) throws IOException {
|
||||||
Resource[] resources = new PathMatchingResourcePatternResolver()
|
Resource[] resources = new PathMatchingResourcePatternResolver()
|
||||||
.getResources("classpath*:/META-INF/spring-configuration-metadata.json");
|
.getResources("classpath*:/META-INF/spring-configuration-metadata.json");
|
||||||
List<InputStream> result = new ArrayList<>();
|
|
||||||
for (Resource resource : resources) {
|
for (Resource resource : resources) {
|
||||||
result.add(resource.getInputStream());
|
try (InputStream inputStream = resource.getInputStream()) {
|
||||||
|
builder.withJsonResource(inputStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logLegacyPropertiesAnalysis() {
|
||||||
|
if (this.report == null || this.reported) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String warningReport = this.report.getWarningReport();
|
||||||
|
if (warningReport != null) {
|
||||||
|
logger.warn(warningReport);
|
||||||
|
}
|
||||||
|
String errorReport = this.report.getErrorReport();
|
||||||
|
if (errorReport != null) {
|
||||||
|
logger.error(errorReport);
|
||||||
|
}
|
||||||
|
this.reported = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.configurationalayzer;
|
package org.springframework.boot.deprecatedproperties;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -28,32 +28,30 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataPrope
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the outcome of the environment analysis.
|
* Provides a deprecated properties report.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
class LegacyPropertiesAnalysis {
|
class DeprecatedPropertiesReport {
|
||||||
|
|
||||||
private final Map<String, PropertySourceAnalysis> content = new LinkedHashMap<>();
|
private final Map<String, DeprecatedProperties> content = new LinkedHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a report for all the legacy properties that were automatically renamed. If
|
* Return a report for all the legacy properties that were automatically renamed. If
|
||||||
* no such legacy properties were found, return {@code null}.
|
* no such legacy properties were found, return {@code null}.
|
||||||
* @return a report with the configurations keys that should be renamed
|
* @return a report with the configurations keys that should be renamed
|
||||||
*/
|
*/
|
||||||
public String createWarningReport() {
|
public String getWarningReport() {
|
||||||
Map<String, List<LegacyProperty>> content = this.content.entrySet().stream()
|
Map<String, List<DeprecatedProperty>> content = getContent(
|
||||||
.filter(e -> !e.getValue().handledProperties.isEmpty())
|
DeprecatedProperties::getRenamed);
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey,
|
|
||||||
e -> new ArrayList<>(e.getValue().handledProperties)));
|
|
||||||
if (content.isEmpty()) {
|
if (content.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
StringBuilder report = new StringBuilder();
|
StringBuilder report = new StringBuilder();
|
||||||
report.append(String.format("%nThe use of configuration keys that have been "
|
report.append(String.format("%nThe use of configuration keys that have been "
|
||||||
+ "renamed was found in the environment:%n%n"));
|
+ "renamed was found in the environment:%n%n"));
|
||||||
appendProperties(report, content, metadata ->
|
append(report, content, (metadata) -> "Replacement: "
|
||||||
"Replacement: " + metadata.getDeprecation().getReplacement());
|
+ metadata.getDeprecation().getReplacement());
|
||||||
report.append(String.format("%n"));
|
report.append(String.format("%n"));
|
||||||
report.append("Each configuration key has been temporarily mapped to its "
|
report.append("Each configuration key has been temporarily mapped to its "
|
||||||
+ "replacement for your convenience. To silence this warning, please "
|
+ "replacement for your convenience. To silence this warning, please "
|
||||||
@@ -63,24 +61,23 @@ class LegacyPropertiesAnalysis {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a report for all the legacy properties that are no longer supported. If
|
* Return a report for all the legacy properties that are no longer supported. If no
|
||||||
* no such legacy properties were found, return {@code null}.
|
* such legacy properties were found, return {@code null}.
|
||||||
* @return a report with the configurations keys that are no longer supported
|
* @return a report with the configurations keys that are no longer supported
|
||||||
*/
|
*/
|
||||||
public String createErrorReport() {
|
public String getErrorReport() {
|
||||||
Map<String, List<LegacyProperty>> content = this.content.entrySet().stream()
|
Map<String, List<DeprecatedProperty>> content = getContent(
|
||||||
.filter(e -> !e.getValue().notHandledProperties.isEmpty())
|
DeprecatedProperties::getUnsupported);
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey,
|
|
||||||
e -> new ArrayList<>(e.getValue().notHandledProperties)));
|
|
||||||
if (content.isEmpty()) {
|
if (content.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
StringBuilder report = new StringBuilder();
|
StringBuilder report = new StringBuilder();
|
||||||
report.append(String.format("%nThe use of configuration keys that are no longer "
|
report.append(String.format("%nThe use of configuration keys that are no longer "
|
||||||
+ "supported was found in the environment:%n%n"));
|
+ "supported was found in the environment:%n%n"));
|
||||||
appendProperties(report, content, metadata ->
|
append(report, content,
|
||||||
"Reason: " + (StringUtils.hasText(metadata.getDeprecation().getReason())
|
metadata -> "Reason: "
|
||||||
? metadata.getDeprecation().getReason() : "none"));
|
+ (StringUtils.hasText(metadata.getDeprecation().getReason())
|
||||||
|
? metadata.getDeprecation().getReason() : "none"));
|
||||||
report.append(String.format("%n"));
|
report.append(String.format("%n"));
|
||||||
report.append("Please refer to the migration guide or reference guide for "
|
report.append("Please refer to the migration guide or reference guide for "
|
||||||
+ "potential alternatives.");
|
+ "potential alternatives.");
|
||||||
@@ -88,21 +85,29 @@ class LegacyPropertiesAnalysis {
|
|||||||
return report.toString();
|
return report.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendProperties(StringBuilder report,
|
private Map<String, List<DeprecatedProperty>> getContent(
|
||||||
Map<String, List<LegacyProperty>> content,
|
Function<DeprecatedProperties, List<DeprecatedProperty>> extractor) {
|
||||||
|
return this.content.entrySet().stream()
|
||||||
|
.filter((entry) -> !extractor.apply(entry.getValue()).isEmpty())
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey,
|
||||||
|
(entry) -> new ArrayList<>(extractor.apply(entry.getValue()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void append(StringBuilder report,
|
||||||
|
Map<String, List<DeprecatedProperty>> content,
|
||||||
Function<ConfigurationMetadataProperty, String> deprecationMessage) {
|
Function<ConfigurationMetadataProperty, String> deprecationMessage) {
|
||||||
content.forEach((name, properties) -> {
|
content.forEach((name, properties) -> {
|
||||||
report.append(String.format("Property source '%s':%n", name));
|
report.append(String.format("Property source '%s':%n", name));
|
||||||
properties.sort(LegacyProperty.COMPARATOR);
|
properties.sort(DeprecatedProperty.COMPARATOR);
|
||||||
properties.forEach((property) -> {
|
properties.forEach((property) -> {
|
||||||
ConfigurationMetadataProperty metadata = property.getMetadata();
|
ConfigurationMetadataProperty metadata = property.getMetadata();
|
||||||
report.append(String.format("\tKey: %s%n", metadata.getId()));
|
report.append(String.format("\tKey: %s%n", metadata.getId()));
|
||||||
if (property.getLineNumber() != null) {
|
if (property.getLineNumber() != null) {
|
||||||
report.append(String.format("\t\tLine: %d%n",
|
report.append(
|
||||||
property.getLineNumber()));
|
String.format("\t\tLine: %d%n", property.getLineNumber()));
|
||||||
}
|
}
|
||||||
report.append(String.format("\t\t%s%n",
|
report.append(
|
||||||
deprecationMessage.apply(metadata)));
|
String.format("\t\t%s%n", deprecationMessage.apply(metadata)));
|
||||||
});
|
});
|
||||||
report.append(String.format("%n"));
|
report.append(String.format("%n"));
|
||||||
});
|
});
|
||||||
@@ -111,29 +116,36 @@ class LegacyPropertiesAnalysis {
|
|||||||
/**
|
/**
|
||||||
* Register a new property source.
|
* Register a new property source.
|
||||||
* @param name the name of the property source
|
* @param name the name of the property source
|
||||||
* @param handledProperties the properties that were renamed
|
* @param renamed the properties that were renamed
|
||||||
* @param notHandledProperties the properties that are no longer supported
|
* @param unsupported the properties that are no longer supported
|
||||||
*/
|
*/
|
||||||
void register(String name, List<LegacyProperty> handledProperties,
|
void add(String name, List<DeprecatedProperty> renamed,
|
||||||
List<LegacyProperty> notHandledProperties) {
|
List<DeprecatedProperty> unsupported) {
|
||||||
List<LegacyProperty> handled = (handledProperties != null
|
this.content.put(name, new DeprecatedProperties(renamed, unsupported));
|
||||||
? new ArrayList<>(handledProperties) : Collections.emptyList());
|
|
||||||
List<LegacyProperty> notHandled = (notHandledProperties != null
|
|
||||||
? new ArrayList<>(notHandledProperties) : Collections.emptyList());
|
|
||||||
this.content.put(name, new PropertySourceAnalysis(handled, notHandled));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DeprecatedProperties {
|
||||||
|
|
||||||
private static class PropertySourceAnalysis {
|
private final List<DeprecatedProperty> renamed;
|
||||||
|
|
||||||
private final List<LegacyProperty> handledProperties;
|
private final List<DeprecatedProperty> unsupported;
|
||||||
|
|
||||||
private final List<LegacyProperty> notHandledProperties;
|
DeprecatedProperties(List<DeprecatedProperty> renamed,
|
||||||
|
List<DeprecatedProperty> unsupported) {
|
||||||
|
this.renamed = asNewList(renamed);
|
||||||
|
this.unsupported = asNewList(unsupported);
|
||||||
|
}
|
||||||
|
|
||||||
PropertySourceAnalysis(List<LegacyProperty> handledProperties,
|
private <T> List<T> asNewList(List<T> source) {
|
||||||
List<LegacyProperty> notHandledProperties) {
|
return (source == null ? Collections.emptyList() : new ArrayList<T>(source));
|
||||||
this.handledProperties = handledProperties;
|
}
|
||||||
this.notHandledProperties = notHandledProperties;
|
|
||||||
|
public List<DeprecatedProperty> getRenamed() {
|
||||||
|
return this.renamed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeprecatedProperty> getUnsupported() {
|
||||||
|
return this.unsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.configurationalayzer;
|
package org.springframework.boot.deprecatedproperties;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -40,19 +40,20 @@ import org.springframework.util.MultiValueMap;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyse {@link LegacyProperty legacy properties}.
|
* Report on {@link DeprecatedProperty deprecated properties}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
class LegacyPropertiesAnalyzer {
|
class DeprecatedPropertiesReporter {
|
||||||
|
|
||||||
private final Map<String, ConfigurationMetadataProperty> allProperties;
|
private final Map<String, ConfigurationMetadataProperty> allProperties;
|
||||||
|
|
||||||
private final ConfigurableEnvironment environment;
|
private final ConfigurableEnvironment environment;
|
||||||
|
|
||||||
LegacyPropertiesAnalyzer(ConfigurationMetadataRepository metadataRepository,
|
DeprecatedPropertiesReporter(ConfigurationMetadataRepository metadataRepository,
|
||||||
ConfigurableEnvironment environment) {
|
ConfigurableEnvironment environment) {
|
||||||
this.allProperties = Collections.unmodifiableMap(metadataRepository.getAllProperties());
|
this.allProperties = Collections
|
||||||
|
.unmodifiableMap(metadataRepository.getAllProperties());
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,60 +62,59 @@ class LegacyPropertiesAnalyzer {
|
|||||||
* legacy properties if a replacement exists.
|
* legacy properties if a replacement exists.
|
||||||
* @return the analysis
|
* @return the analysis
|
||||||
*/
|
*/
|
||||||
public LegacyPropertiesAnalysis analyseLegacyProperties() {
|
public DeprecatedPropertiesReport getReport() {
|
||||||
LegacyPropertiesAnalysis analysis = new LegacyPropertiesAnalysis();
|
DeprecatedPropertiesReport report = new DeprecatedPropertiesReport();
|
||||||
Map<String, List<LegacyProperty>> properties = getMatchingProperties(deprecatedFilter());
|
Map<String, List<DeprecatedProperty>> properties = getMatchingProperties(
|
||||||
|
deprecatedFilter());
|
||||||
if (properties.isEmpty()) {
|
if (properties.isEmpty()) {
|
||||||
return analysis;
|
return report;
|
||||||
}
|
}
|
||||||
properties.forEach((name, candidates) -> {
|
properties.forEach((name, candidates) -> {
|
||||||
PropertySource<?> propertySource = mapPropertiesWithReplacement(analysis,
|
PropertySource<?> propertySource = mapPropertiesWithReplacement(report,
|
||||||
name, candidates);
|
name, candidates);
|
||||||
if (propertySource != null) {
|
if (propertySource != null) {
|
||||||
this.environment.getPropertySources().addBefore(name, propertySource);
|
this.environment.getPropertySources().addBefore(name, propertySource);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return analysis;
|
return report;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PropertySource<?> mapPropertiesWithReplacement(
|
private PropertySource<?> mapPropertiesWithReplacement(
|
||||||
LegacyPropertiesAnalysis analysis, String name,
|
DeprecatedPropertiesReport report, String name,
|
||||||
List<LegacyProperty> properties) {
|
List<DeprecatedProperty> properties) {
|
||||||
List<LegacyProperty> matches = new ArrayList<>();
|
List<DeprecatedProperty> renamed = new ArrayList<>();
|
||||||
List<LegacyProperty> unhandled = new ArrayList<>();
|
List<DeprecatedProperty> unsupported = new ArrayList<>();
|
||||||
for (LegacyProperty property : properties) {
|
properties.forEach((property) -> {
|
||||||
if (hasValidReplacement(property)) {
|
(isRenamed(property) ? renamed : unsupported).add(property);
|
||||||
matches.add(property);
|
});
|
||||||
}
|
report.add(name, renamed, unsupported);
|
||||||
else {
|
if (renamed.isEmpty()) {
|
||||||
unhandled.add(property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
analysis.register(name, matches, unhandled);
|
|
||||||
if (matches.isEmpty()) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String target = "migrate-" + name;
|
String target = "migrate-" + name;
|
||||||
Map<String, OriginTrackedValue> content = new LinkedHashMap<>();
|
Map<String, OriginTrackedValue> content = new LinkedHashMap<>();
|
||||||
for (LegacyProperty candidate : matches) {
|
for (DeprecatedProperty candidate : renamed) {
|
||||||
OriginTrackedValue value = OriginTrackedValue.of(
|
OriginTrackedValue value = OriginTrackedValue.of(
|
||||||
candidate.getProperty().getValue(), candidate.getProperty().getOrigin());
|
candidate.getProperty().getValue(),
|
||||||
|
candidate.getProperty().getOrigin());
|
||||||
content.put(candidate.getMetadata().getDeprecation().getReplacement(), value);
|
content.put(candidate.getMetadata().getDeprecation().getReplacement(), value);
|
||||||
}
|
}
|
||||||
return new OriginTrackedMapPropertySource(target, content);
|
return new OriginTrackedMapPropertySource(target, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasValidReplacement(LegacyProperty property) {
|
private boolean isRenamed(DeprecatedProperty property) {
|
||||||
String replacementId = property.getMetadata().getDeprecation().getReplacement();
|
ConfigurationMetadataProperty metadata = property.getMetadata();
|
||||||
|
String replacementId = metadata.getDeprecation().getReplacement();
|
||||||
if (StringUtils.hasText(replacementId)) {
|
if (StringUtils.hasText(replacementId)) {
|
||||||
ConfigurationMetadataProperty replacement = this.allProperties.get(replacementId);
|
ConfigurationMetadataProperty replacement = this.allProperties
|
||||||
|
.get(replacementId);
|
||||||
if (replacement != null) {
|
if (replacement != null) {
|
||||||
return replacement.getType().equals(property.getMetadata().getType());
|
return replacement.getType().equals(metadata.getType());
|
||||||
}
|
}
|
||||||
replacement = getMapProperty(replacementId);
|
replacement = getMapProperty(replacementId);
|
||||||
if (replacement != null) {
|
if (replacement != null) {
|
||||||
return replacement.getType().startsWith("java.util.Map")
|
return replacement.getType().startsWith("java.util.Map")
|
||||||
&& replacement.getType().endsWith(property.getMetadata().getType() + ">");
|
&& replacement.getType().endsWith(metadata.getType() + ">");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -128,17 +128,19 @@ class LegacyPropertiesAnalyzer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, List<LegacyProperty>> getMatchingProperties(
|
private Map<String, List<DeprecatedProperty>> getMatchingProperties(
|
||||||
Predicate<ConfigurationMetadataProperty> filter) {
|
Predicate<ConfigurationMetadataProperty> filter) {
|
||||||
MultiValueMap<String, LegacyProperty> result = new LinkedMultiValueMap<>();
|
MultiValueMap<String, DeprecatedProperty> result = new LinkedMultiValueMap<>();
|
||||||
List<ConfigurationMetadataProperty> candidates = this.allProperties.values()
|
List<ConfigurationMetadataProperty> candidates = this.allProperties.values()
|
||||||
.stream().filter(filter).collect(Collectors.toList());
|
.stream().filter(filter).collect(Collectors.toList());
|
||||||
getPropertySourcesAsMap().forEach((name, source) -> {
|
getPropertySourcesAsMap().forEach((name, source) -> {
|
||||||
candidates.forEach(metadata -> {
|
candidates.forEach(metadata -> {
|
||||||
ConfigurationProperty configurationProperty = source.getConfigurationProperty(
|
ConfigurationProperty configurationProperty = source
|
||||||
ConfigurationPropertyName.of(metadata.getId()));
|
.getConfigurationProperty(
|
||||||
|
ConfigurationPropertyName.of(metadata.getId()));
|
||||||
if (configurationProperty != null) {
|
if (configurationProperty != null) {
|
||||||
result.add(name, new LegacyProperty(metadata, configurationProperty));
|
result.add(name,
|
||||||
|
new DeprecatedProperty(metadata, configurationProperty));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -146,14 +148,15 @@ class LegacyPropertiesAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Predicate<ConfigurationMetadataProperty> deprecatedFilter() {
|
private Predicate<ConfigurationMetadataProperty> deprecatedFilter() {
|
||||||
return p -> p.getDeprecation() != null
|
return (property) -> property.getDeprecation() != null
|
||||||
&& p.getDeprecation().getLevel() == Deprecation.Level.ERROR;
|
&& property.getDeprecation().getLevel() == Deprecation.Level.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, ConfigurationPropertySource> getPropertySourcesAsMap() {
|
private Map<String, ConfigurationPropertySource> getPropertySourcesAsMap() {
|
||||||
Map<String, ConfigurationPropertySource> map = new LinkedHashMap<>();
|
Map<String, ConfigurationPropertySource> map = new LinkedHashMap<>();
|
||||||
ConfigurationPropertySources.get(this.environment);
|
ConfigurationPropertySources.get(this.environment);
|
||||||
for (ConfigurationPropertySource source : ConfigurationPropertySources.get(this.environment)) {
|
for (ConfigurationPropertySource source : ConfigurationPropertySources
|
||||||
|
.get(this.environment)) {
|
||||||
map.put(determinePropertySourceName(source), source);
|
map.put(determinePropertySourceName(source), source);
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.configurationalayzer;
|
package org.springframework.boot.deprecatedproperties;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
@@ -28,9 +28,10 @@ import org.springframework.boot.origin.TextResourceOrigin;
|
|||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
class LegacyProperty {
|
class DeprecatedProperty {
|
||||||
|
|
||||||
static final LegacyPropertyComparator COMPARATOR = new LegacyPropertyComparator();
|
public static final Comparator<DeprecatedProperty> COMPARATOR = Comparator
|
||||||
|
.comparing((property) -> property.getMetadata().getId());
|
||||||
|
|
||||||
private final ConfigurationMetadataProperty metadata;
|
private final ConfigurationMetadataProperty metadata;
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ class LegacyProperty {
|
|||||||
|
|
||||||
private final Integer lineNumber;
|
private final Integer lineNumber;
|
||||||
|
|
||||||
LegacyProperty(ConfigurationMetadataProperty metadata,
|
DeprecatedProperty(ConfigurationMetadataProperty metadata,
|
||||||
ConfigurationProperty property) {
|
ConfigurationProperty property) {
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
this.property = property;
|
this.property = property;
|
||||||
@@ -68,13 +69,4 @@ class LegacyProperty {
|
|||||||
return this.lineNumber;
|
return this.lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class LegacyPropertyComparator implements Comparator<LegacyProperty> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(LegacyProperty p1, LegacyProperty p2) {
|
|
||||||
return p1.getMetadata().getId().compareTo(p2.getMetadata().getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for analyzing the environment.
|
* Support for migrating deprecated Spring Boot properties.
|
||||||
*/
|
*/
|
||||||
package org.springframework.boot.configurationalayzer;
|
package org.springframework.boot.deprecatedproperties;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
org.springframework.context.ApplicationListener=\
|
||||||
|
org.springframework.boot.deprecatedproperties.DeprecatedPropertiesListener
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.configurationalayzer;
|
package org.springframework.boot.deprecatedproperties;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@@ -28,11 +28,11 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link LegacyPropertiesAnalyzerListener}.
|
* Tests for {@link DeprecatedPropertiesListener}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
public class LegacyPropertiesAnalyzerListenerTests {
|
public class DeprecatedPropertiesListenerTests {
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public final OutputCapture output = new OutputCapture();
|
public final OutputCapture output = new OutputCapture();
|
||||||
@@ -48,8 +48,7 @@ public class LegacyPropertiesAnalyzerListenerTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sampleReport() {
|
public void sampleReport() {
|
||||||
this.context = createSampleApplication()
|
this.context = createSampleApplication().run("--banner.charset=UTF8");
|
||||||
.run("--banner.charset=UTF8");
|
|
||||||
assertThat(this.output.toString()).contains("commandLineArgs")
|
assertThat(this.output.toString()).contains("commandLineArgs")
|
||||||
.contains("spring.banner.charset")
|
.contains("spring.banner.charset")
|
||||||
.contains("Each configuration key has been temporarily mapped")
|
.contains("Each configuration key has been temporarily mapped")
|
||||||
@@ -60,7 +59,6 @@ public class LegacyPropertiesAnalyzerListenerTests {
|
|||||||
return new SpringApplication(TestApplication.class);
|
return new SpringApplication(TestApplication.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public static class TestApplication {
|
public static class TestApplication {
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.boot.configurationalayzer;
|
package org.springframework.boot.deprecatedproperties;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -38,13 +38,12 @@ import org.springframework.mock.env.MockEnvironment;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link LegacyPropertiesAnalyzer}.
|
* Tests for {@link DeprecatedPropertiesReporter}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
*/
|
*/
|
||||||
public class LegacyPropertiesAnalyzerTests {
|
public class DeprecatedPropertiesReporterTests {
|
||||||
|
|
||||||
private ConfigurableEnvironment environment = new MockEnvironment();
|
private ConfigurableEnvironment environment = new MockEnvironment();
|
||||||
|
|
||||||
@@ -64,56 +63,53 @@ public class LegacyPropertiesAnalyzerTests {
|
|||||||
propertySources.addFirst(one);
|
propertySources.addFirst(one);
|
||||||
propertySources.addAfter("one", two);
|
propertySources.addAfter("one", two);
|
||||||
assertThat(propertySources).hasSize(3);
|
assertThat(propertySources).hasSize(3);
|
||||||
createAnalyzer(loadRepository("metadata/sample-metadata.json"))
|
createAnalyzer(loadRepository("metadata/sample-metadata.json")).getReport();
|
||||||
.analyseLegacyProperties();
|
assertThat(mapToNames(propertySources)).containsExactly("one", "migrate-two",
|
||||||
assertThat(mapToNames(propertySources)).containsExactly("one",
|
"two", "mockProperties");
|
||||||
"migrate-two", "two", "mockProperties");
|
assertMappedProperty(propertySources.get("migrate-two"), "test.two", "another",
|
||||||
assertMappedProperty(propertySources.get("migrate-two"),
|
getOrigin(two, "wrong.two"));
|
||||||
"test.two", "another", getOrigin(two, "wrong.two"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void warningReport() throws IOException {
|
public void warningReport() throws IOException {
|
||||||
this.environment.getPropertySources().addFirst(loadPropertySource("test",
|
this.environment.getPropertySources().addFirst(
|
||||||
"config/config-warnings.properties"));
|
loadPropertySource("test", "config/config-warnings.properties"));
|
||||||
this.environment.getPropertySources().addFirst(loadPropertySource("ignore",
|
this.environment.getPropertySources()
|
||||||
"config/config-error.properties"));
|
.addFirst(loadPropertySource("ignore", "config/config-error.properties"));
|
||||||
String report = createWarningReport(loadRepository(
|
String report = createWarningReport(
|
||||||
"metadata/sample-metadata.json"));
|
loadRepository("metadata/sample-metadata.json"));
|
||||||
assertThat(report).isNotNull();
|
assertThat(report).isNotNull();
|
||||||
assertThat(report).containsSubsequence("Property source 'test'",
|
assertThat(report).containsSubsequence("Property source 'test'",
|
||||||
"wrong.four.test", "Line: 5", "test.four.test",
|
"wrong.four.test", "Line: 5", "test.four.test", "wrong.two", "Line: 2",
|
||||||
"wrong.two", "Line: 2", "test.two");
|
"test.two");
|
||||||
assertThat(report).doesNotContain("wrong.one");
|
assertThat(report).doesNotContain("wrong.one");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void errorReport() throws IOException {
|
public void errorReport() throws IOException {
|
||||||
this.environment.getPropertySources().addFirst(loadPropertySource("test1",
|
this.environment.getPropertySources().addFirst(
|
||||||
"config/config-warnings.properties"));
|
loadPropertySource("test1", "config/config-warnings.properties"));
|
||||||
this.environment.getPropertySources().addFirst(loadPropertySource("test2",
|
this.environment.getPropertySources()
|
||||||
"config/config-error.properties"));
|
.addFirst(loadPropertySource("test2", "config/config-error.properties"));
|
||||||
String report = createErrorReport(loadRepository(
|
String report = createErrorReport(
|
||||||
"metadata/sample-metadata.json"));
|
loadRepository("metadata/sample-metadata.json"));
|
||||||
assertThat(report).isNotNull();
|
assertThat(report).isNotNull();
|
||||||
assertThat(report).containsSubsequence("Property source 'test2'",
|
assertThat(report).containsSubsequence("Property source 'test2'", "wrong.one",
|
||||||
"wrong.one", "Line: 2", "This is no longer supported.");
|
"Line: 2", "This is no longer supported.");
|
||||||
assertThat(report).doesNotContain("wrong.four.test")
|
assertThat(report).doesNotContain("wrong.four.test").doesNotContain("wrong.two");
|
||||||
.doesNotContain("wrong.two");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void errorReportNoReplacement() throws IOException {
|
public void errorReportNoReplacement() throws IOException {
|
||||||
this.environment.getPropertySources().addFirst(loadPropertySource("first",
|
this.environment.getPropertySources().addFirst(loadPropertySource("first",
|
||||||
"config/config-error-no-replacement.properties"));
|
"config/config-error-no-replacement.properties"));
|
||||||
this.environment.getPropertySources().addFirst(loadPropertySource("second",
|
this.environment.getPropertySources()
|
||||||
"config/config-error.properties"));
|
.addFirst(loadPropertySource("second", "config/config-error.properties"));
|
||||||
String report = createErrorReport(loadRepository(
|
String report = createErrorReport(
|
||||||
"metadata/sample-metadata.json"));
|
loadRepository("metadata/sample-metadata.json"));
|
||||||
assertThat(report).isNotNull();
|
assertThat(report).isNotNull();
|
||||||
assertThat(report).containsSubsequence(
|
assertThat(report).containsSubsequence("Property source 'first'", "wrong.three",
|
||||||
"Property source 'first'", "wrong.three", "Line: 6", "none",
|
"Line: 6", "none", "Property source 'second'", "wrong.one", "Line: 2",
|
||||||
"Property source 'second'", "wrong.one", "Line: 2",
|
|
||||||
"This is no longer supported.");
|
"This is no longer supported.");
|
||||||
assertThat(report).doesNotContain("null").doesNotContain("server.port")
|
assertThat(report).doesNotContain("null").doesNotContain("server.port")
|
||||||
.doesNotContain("debug");
|
.doesNotContain("debug");
|
||||||
@@ -132,6 +128,7 @@ public class LegacyPropertiesAnalyzerTests {
|
|||||||
return ((OriginLookup<String>) propertySource).getOrigin(name);
|
return ((OriginLookup<String>) propertySource).getOrigin(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private void assertMappedProperty(PropertySource<?> propertySource, String name,
|
private void assertMappedProperty(PropertySource<?> propertySource, String name,
|
||||||
Object value, Origin origin) {
|
Object value, Origin origin) {
|
||||||
assertThat(propertySource.containsProperty(name)).isTrue();
|
assertThat(propertySource.containsProperty(name)).isTrue();
|
||||||
@@ -146,15 +143,16 @@ public class LegacyPropertiesAnalyzerTests {
|
|||||||
private PropertySource<?> loadPropertySource(String name, String path)
|
private PropertySource<?> loadPropertySource(String name, String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ClassPathResource resource = new ClassPathResource(path);
|
ClassPathResource resource = new ClassPathResource(path);
|
||||||
PropertySource<?> propertySource = new PropertiesPropertySourceLoader()
|
PropertySource<?> propertySource = new PropertiesPropertySourceLoader().load(name,
|
||||||
.load(name, resource, null);
|
resource, null);
|
||||||
assertThat(propertySource).isNotNull();
|
assertThat(propertySource).isNotNull();
|
||||||
return propertySource;
|
return propertySource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigurationMetadataRepository loadRepository(String... content) {
|
private ConfigurationMetadataRepository loadRepository(String... content) {
|
||||||
try {
|
try {
|
||||||
ConfigurationMetadataRepositoryJsonBuilder builder = ConfigurationMetadataRepositoryJsonBuilder.create();
|
ConfigurationMetadataRepositoryJsonBuilder builder = ConfigurationMetadataRepositoryJsonBuilder
|
||||||
|
.create();
|
||||||
for (String path : content) {
|
for (String path : content) {
|
||||||
Resource resource = new ClassPathResource(path);
|
Resource resource = new ClassPathResource(path);
|
||||||
builder.withJsonResource(resource.getInputStream());
|
builder.withJsonResource(resource.getInputStream());
|
||||||
@@ -167,18 +165,16 @@ public class LegacyPropertiesAnalyzerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String createWarningReport(ConfigurationMetadataRepository repository) {
|
private String createWarningReport(ConfigurationMetadataRepository repository) {
|
||||||
return createAnalyzer(repository).analyseLegacyProperties()
|
return createAnalyzer(repository).getReport().getWarningReport();
|
||||||
.createWarningReport();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createErrorReport(ConfigurationMetadataRepository repository) {
|
private String createErrorReport(ConfigurationMetadataRepository repository) {
|
||||||
return createAnalyzer(repository).analyseLegacyProperties()
|
return createAnalyzer(repository).getReport().getErrorReport();
|
||||||
.createErrorReport();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private LegacyPropertiesAnalyzer createAnalyzer(
|
private DeprecatedPropertiesReporter createAnalyzer(
|
||||||
ConfigurationMetadataRepository repository) {
|
ConfigurationMetadataRepository repository) {
|
||||||
return new LegacyPropertiesAnalyzer(repository, this.environment);
|
return new DeprecatedPropertiesReporter(repository, this.environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user