diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java index 2e8972db685..c08d51c6aea 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java @@ -18,6 +18,8 @@ package org.springframework.boot.context.config; import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -108,6 +110,7 @@ import org.springframework.util.StringUtils; * @author Andy Wilkinson * @author Eddú Meléndez * @author Madhura Bhave + * @author Scott Frederick * @since 1.0.0 */ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered { @@ -519,6 +522,14 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, } continue; } + if (resource.isFile() && hasHiddenPathElement(resource)) { + if (this.logger.isTraceEnabled()) { + StringBuilder description = getDescription("Skipped location with hidden path element ", + location, resource, profile); + this.logger.trace(description); + } + continue; + } String name = "applicationConfig: [" + getLocationName(location, resource) + "]"; List documents = loadDocuments(loader, name, resource); if (CollectionUtils.isEmpty(documents)) { @@ -555,6 +566,16 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, } } + private boolean hasHiddenPathElement(Resource resource) throws IOException { + String cleanPath = StringUtils.cleanPath(resource.getFile().getAbsolutePath()); + for (Path value : Paths.get(cleanPath)) { + if (value.toString().startsWith(".")) { + return true; + } + } + return false; + } + private String getLocationName(String location, Resource resource) { if (!location.contains("*")) { return location; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java index a9884fdca93..295242de5d7 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java @@ -75,6 +75,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; * @author Dave Syer * @author Eddú Meléndez * @author Madhura Bhave + * @author Scott Frederick */ @ExtendWith(OutputCaptureExtension.class) class ConfigFileApplicationListenerTests { @@ -1080,6 +1081,16 @@ class ConfigFileApplicationListenerTests { assertThat(this.environment.getProperty("third.property")).isNull(); } + @Test + void locationsWithWildcardDirectoriesShouldIgnoreHiddenDirectories() { + String location = "file:src/test/resources/config/*/"; + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, + "spring.config.location=" + location); + this.initializer.setSearchNames("testproperties"); + this.initializer.postProcessEnvironment(this.environment, this.application); + assertThat(this.environment.getProperty("fourth.property")).isNull(); + } + @Test void locationsWithWildcardDirectoriesShouldLoadAllFilesThatMatch() { String location = "file:src/test/resources/config/*/"; @@ -1124,6 +1135,16 @@ class ConfigFileApplicationListenerTests { assertThat(second).isEqualTo("ball"); } + @Test + void locationsWithWildcardFilesShouldIgnoreHiddenDirectories() { + String location = "file:src/test/resources/config/*/testproperties.properties"; + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, + "spring.config.location=" + location); + this.initializer.setSearchNames("testproperties"); + this.initializer.postProcessEnvironment(this.environment, this.application); + assertThat(this.environment.getProperty("fourth.property")).isNull(); + } + private Condition matchingPropertySource(final String sourceName) { return new Condition("environment containing property source " + sourceName) { diff --git a/spring-boot-project/spring-boot/src/test/resources/config/.hidden/testproperties.properties b/spring-boot-project/spring-boot/src/test/resources/config/.hidden/testproperties.properties new file mode 100644 index 00000000000..1537a17cf26 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/config/.hidden/testproperties.properties @@ -0,0 +1 @@ +fourth.property=shouldbehidden \ No newline at end of file