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 46a32071424..ff41ade15a5 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 * @deprecated since 2.4.0 in favor of {@link ConfigDataEnvironmentPostProcessor} */ @@ -504,6 +507,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)) { @@ -540,6 +551,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 locationReference, Resource resource) { if (!locationReference.contains("*")) { return locationReference; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataLocationResolver.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataLocationResolver.java index 3b0cbabc013..6cf710f42c5 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataLocationResolver.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/StandardConfigDataLocationResolver.java @@ -49,6 +49,7 @@ import org.springframework.util.StringUtils; * * @author Madhura Bhave * @author Phillip Webb + * @author Scott Frederick * @since 2.4.0 */ public class StandardConfigDataLocationResolver @@ -304,7 +305,7 @@ public class StandardConfigDataLocationResolver return new Resource[] { directoryResource }; } File directory = getDirectory(resourceLocationPattern, directoryResource); - File[] subDirectories = directory.listFiles(File::isDirectory); + File[] subDirectories = directory.listFiles(this::isVisibleDirectory); if (subDirectories == null) { return EMPTY_RESOURCES; } @@ -340,4 +341,8 @@ public class StandardConfigDataLocationResolver } } + private boolean isVisibleDirectory(File file) { + return file.isDirectory() && !file.getName().startsWith("."); + } + } 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 4ebd1333b4a..92971ad2f06 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 @@ -69,6 +69,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; * @author Dave Syer * @author Eddú Meléndez * @author Madhura Bhave + * @author Scott Frederick */ @Deprecated @ExtendWith({ OutputCaptureExtension.class, UseLegacyProcessing.class }) @@ -1075,6 +1076,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/*/"; @@ -1119,6 +1130,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