From a9ffdca6f234042e301e40c3feff1ecaa4c0b7bd Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Mon, 14 Nov 2016 13:33:52 -0800 Subject: [PATCH 1/2] Validate excluded autoconfiguration classes Closes gh-7407 See gh-6865 --- ...EnableAutoConfigurationImportSelector.java | 18 +++++++ ...eAutoConfigurationImportSelectorTests.java | 52 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java index df815ef486..af199cc05f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java @@ -85,6 +85,7 @@ public class EnableAutoConfigurationImportSelector attributes); configurations = removeDuplicates(configurations); Set exclusions = getExclusions(metadata, attributes); + checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = sort(configurations); recordWithConditionEvaluationReport(configurations, exclusions); @@ -157,6 +158,23 @@ public class EnableAutoConfigurationImportSelector return EnableAutoConfiguration.class; } + private void checkExcludedClasses(List configurations, + Set exclusions) { + StringBuilder message = new StringBuilder(); + for (String exclusion : exclusions) { + if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) + && !configurations.contains(exclusion)) { + message.append("\t- ").append(exclusion).append("\n"); + } + } + if (!message.toString().isEmpty()) { + throw new IllegalStateException( + "The following classes could not be excluded because they are not auto-configuration classes:\n" + + message.toString()); + } + + } + /** * Return any exclusions that limit the candidate configurations. * @param metadata the source metadata diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java index 306b132ac9..91154a68ba 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java @@ -19,7 +19,9 @@ package org.springframework.boot.autoconfigure; import java.util.List; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -29,6 +31,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionEvaluationRepor import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration; import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration; import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; +import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.support.SpringFactoriesLoader; @@ -60,6 +63,9 @@ public class EnableAutoConfigurationImportSelectorTests { @Mock private AnnotationAttributes annotationAttributes; + @Rule + public ExpectedException expected = ExpectedException.none(); + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -166,6 +172,47 @@ public class EnableAutoConfigurationImportSelectorTests { assertThat(imports).isEmpty(); } + @Test + public void nonAutoConfigurationClassExclusionsShouldThrowException() throws Exception { + this.expected.expect(IllegalStateException.class); + configureExclusions(new String[] { TestConfiguration.class.getName() }, + new String[0], new String[0]); + this.importSelector.selectImports(this.annotationMetadata); + } + + @Test + public void nonAutoConfigurationClassNameExclusionsWhenPresentOnClassPathShouldThrowException() + throws Exception { + this.expected.expect(IllegalStateException.class); + configureExclusions(new String[0], + new String[] { "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration" }, + new String[0]); + this.importSelector.selectImports(this.annotationMetadata); + } + + @Test + public void nonAutoConfigurationPropertyExclusionsWhenPresentOnClassPathShouldThrowException() + throws Exception { + this.expected.expect(IllegalStateException.class); + configureExclusions(new String[0], + new String[0], + new String[] { "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration" }); + this.importSelector.selectImports(this.annotationMetadata); + } + + @Test + public void nameAndPropertyExclusionsWhenNotPresentOnClasspathShouldNotThrowException() + throws Exception { + configureExclusions(new String[0], + new String[] { "org.springframework.boot.autoconfigure.DoesNotExist1" }, + new String[] { "org.springframework.boot.autoconfigure.DoesNotExist2" }); + this.importSelector.selectImports(this.annotationMetadata); + assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) + .contains("org.springframework.boot.autoconfigure.DoesNotExist1"); + assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) + .contains("org.springframework.boot.autoconfigure.DoesNotExist2"); + } + private void configureExclusions(String[] classExclusion, String[] nameExclusion, String[] propertyExclusion) { String annotationName = EnableAutoConfiguration.class.getName(); @@ -187,4 +234,9 @@ public class EnableAutoConfigurationImportSelectorTests { getClass().getClassLoader()); } + @Configuration + private class TestConfiguration { + + } + } From 65d0c07fd63390e2dcd60d3df3da09c14d29dd76 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 22 Nov 2016 14:03:41 +0000 Subject: [PATCH 2/2] Polish "Validate excluded autoconfiguration classes" - Apply code formatting - Move configuration of excepted exception to immediately before line that will throw the exception - Use String.format with %n to produce platform-specific new lines See gh-7407 --- ...EnableAutoConfigurationImportSelector.java | 10 ++++++---- ...eAutoConfigurationImportSelectorTests.java | 19 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java index af199cc05f..b8dab15000 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java @@ -57,6 +57,7 @@ import org.springframework.util.ClassUtils; * @author Phillip Webb * @author Andy Wilkinson * @author Stephane Nicoll + * @author Madhura Bhave * @since 1.3.0 * @see EnableAutoConfiguration */ @@ -164,13 +165,14 @@ public class EnableAutoConfigurationImportSelector for (String exclusion : exclusions) { if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) && !configurations.contains(exclusion)) { - message.append("\t- ").append(exclusion).append("\n"); + message.append("\t- ").append(exclusion).append(String.format("%n")); } } if (!message.toString().isEmpty()) { - throw new IllegalStateException( - "The following classes could not be excluded because they are not auto-configuration classes:\n" - + message.toString()); + throw new IllegalStateException(String.format( + "The following classes could not be excluded because they are" + + " not auto-configuration classes:%n%s", + message.toString())); } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java index 91154a68ba..c4b09057ff 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java @@ -47,7 +47,7 @@ import static org.mockito.BDDMockito.given; * * @author Andy Wilkinson * @author Stephane Nicoll - * + * @author Madhura Bhave */ public class EnableAutoConfigurationImportSelectorTests { @@ -173,30 +173,31 @@ public class EnableAutoConfigurationImportSelectorTests { } @Test - public void nonAutoConfigurationClassExclusionsShouldThrowException() throws Exception { - this.expected.expect(IllegalStateException.class); + public void nonAutoConfigurationClassExclusionsShouldThrowException() + throws Exception { configureExclusions(new String[] { TestConfiguration.class.getName() }, new String[0], new String[0]); + this.expected.expect(IllegalStateException.class); this.importSelector.selectImports(this.annotationMetadata); } @Test public void nonAutoConfigurationClassNameExclusionsWhenPresentOnClassPathShouldThrowException() throws Exception { - this.expected.expect(IllegalStateException.class); configureExclusions(new String[0], - new String[] { "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration" }, + new String[] { + "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration" }, new String[0]); + this.expected.expect(IllegalStateException.class); this.importSelector.selectImports(this.annotationMetadata); } @Test - public void nonAutoConfigurationPropertyExclusionsWhenPresentOnClassPathShouldThrowException() + public void nonAutoConfigurationPropertyExclusionsWhenPresentOnClassPathShouldThrowException() throws Exception { + configureExclusions(new String[0], new String[0], new String[] { + "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration" }); this.expected.expect(IllegalStateException.class); - configureExclusions(new String[0], - new String[0], - new String[] { "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration" }); this.importSelector.selectImports(this.annotationMetadata); }