diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportMessage.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportMessage.java index 7da1b0837d26..a4cc19855247 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportMessage.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/logging/ConditionEvaluationReportMessage.java @@ -18,17 +18,19 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import java.util.stream.Collectors; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcome; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcomes; import org.springframework.util.ClassUtils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; /** @@ -135,21 +137,28 @@ private void logUnconditionalClasses(ConditionEvaluationReport report, private Map orderByName( Map outcomes) { - List names = new ArrayList<>(); - Map classNames = new HashMap<>(); - for (String name : outcomes.keySet()) { - String shortName = ClassUtils.getShortName(name); - names.add(shortName); - classNames.put(shortName, name); - } - Collections.sort(names); + MultiValueMap map = mapShortNameToFullyQualifiedNames(outcomes.keySet()); + List shortNames = new ArrayList<>(map.keySet()); + Collections.sort(shortNames); Map result = new LinkedHashMap<>(); - for (String shortName : names) { - result.put(shortName, outcomes.get(classNames.get(shortName))); + for (String shortName : shortNames) { + List fullyQualifiedNames = map.get(shortName); + if (fullyQualifiedNames.size() > 1) { + fullyQualifiedNames.forEach(k -> result.put(k, outcomes.get(k))); + } + else { + result.put(shortName, outcomes.get(fullyQualifiedNames.get(0))); + } } return result; } + private MultiValueMap mapShortNameToFullyQualifiedNames(Set keySet) { + LinkedMultiValueMap map = new LinkedMultiValueMap<>(); + keySet.forEach(k -> map.add(ClassUtils.getShortName(k), k)); + return map; + } + private void addMatchLogMessage(StringBuilder message, String source, ConditionAndOutcomes matches) { message.append(String.format("%n %s matched:%n", source)); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportTests.java index 4515319d4456..a8352d88a1fc 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionEvaluationReportTests.java @@ -30,6 +30,7 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcome; import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcomes; +import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportMessage; import org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration; import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.test.util.TestPropertyValues; @@ -241,6 +242,37 @@ public void negativeOuterPositiveInnerBean() { assertThat(sourceOutcomes.get(positiveConfig).isFullMatch()).isFalse(); } + @Test + public void reportWhenSameShortNamePresentMoreThanOnceShouldUseFullyQualifiedName() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.register(WebMvcAutoConfiguration.class, + org.springframework.boot.autoconfigure.condition.config.first.SampleAutoConfiguration.class, + org.springframework.boot.autoconfigure.condition.config.second.SampleAutoConfiguration.class); + context.refresh(); + ConditionEvaluationReport report = ConditionEvaluationReport + .get(context.getBeanFactory()); + assertThat(report.getConditionAndOutcomesBySource()) + .containsKeys("org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration", + "org.springframework.boot.autoconfigure.condition.config.first.SampleAutoConfiguration", + "org.springframework.boot.autoconfigure.condition.config.second.SampleAutoConfiguration"); + } + + @Test + public void reportMessageWhenSameShortNamePresentMoreThanOnceShouldUseFullyQualifiedName() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.register(WebMvcAutoConfiguration.class, + org.springframework.boot.autoconfigure.condition.config.first.SampleAutoConfiguration.class, + org.springframework.boot.autoconfigure.condition.config.second.SampleAutoConfiguration.class); + context.refresh(); + ConditionEvaluationReport report = ConditionEvaluationReport + .get(context.getBeanFactory()); + String reportMessage = new ConditionEvaluationReportMessage(report).toString(); + assertThat(reportMessage) + .contains("WebMvcAutoConfiguration", "org.springframework.boot.autoconfigure.condition.config.first.SampleAutoConfiguration", + "org.springframework.boot.autoconfigure.condition.config.second.SampleAutoConfiguration"); + assertThat(reportMessage).doesNotContain("org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration"); + } + private int getNumberOfOutcomes(ConditionAndOutcomes outcomes) { Iterator iterator = outcomes.iterator(); int numberOfOutcomesAdded = 0; @@ -264,12 +296,12 @@ static class DuplicateConfig { } @Configuration - @Conditional({ ConditionEvaluationReportTests.MatchParseCondition.class, - ConditionEvaluationReportTests.NoMatchBeanCondition.class }) + @Conditional({ConditionEvaluationReportTests.MatchParseCondition.class, + ConditionEvaluationReportTests.NoMatchBeanCondition.class}) public static class NegativeOuterConfig { @Configuration - @Conditional({ ConditionEvaluationReportTests.MatchParseCondition.class }) + @Conditional({ConditionEvaluationReportTests.MatchParseCondition.class}) public static class PositiveInnerConfig { @Bean diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/config/first/SampleAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/config/first/SampleAutoConfiguration.java new file mode 100644 index 000000000000..778c2403ed2b --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/config/first/SampleAutoConfiguration.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.condition.config.first; + +import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Sample auto-configuration for {@link ConditionEvaluationReport} tests. + * + * @author Madhura Bhave + */ +@Configuration("autoConfigOne") +@ConditionalOnProperty("sample.first") +public class SampleAutoConfiguration { + + @Bean + public String one() { + return "one"; + } + +} + diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/config/second/SampleAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/config/second/SampleAutoConfiguration.java new file mode 100644 index 000000000000..8096c88122db --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/config/second/SampleAutoConfiguration.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.condition.config.second; + +import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Sample auto-configuration for {@link ConditionEvaluationReport} tests. + * + * @author Madhura Bhave + */ +@Configuration("autoConfigTwo") +@ConditionalOnProperty("sample.second") +public class SampleAutoConfiguration { + + @Bean + public String two() { + return "two"; + } + +} +