From dcbf0096d849938bb4258994c2715b532fd390d8 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 22 Oct 2024 19:22:33 -0700 Subject: [PATCH] Use context class loader when watching SSL resource Update `BundleContentProperty` to use a provided resource loader when watching files. Fixes gh-42468 --- .../ssl/BundleContentProperty.java | 12 ++++------ .../ssl/SslPropertiesBundleRegistrar.java | 2 +- .../ssl/BundleContentPropertyTests.java | 23 ++++++++++++++++--- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/BundleContentProperty.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/BundleContentProperty.java index 1a15a67ad3fc..fdb251c4576f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/BundleContentProperty.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/BundleContentProperty.java @@ -18,9 +18,9 @@ import java.nio.file.Path; -import org.springframework.boot.io.ApplicationResourceLoader; import org.springframework.boot.ssl.pem.PemContent; import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -51,9 +51,10 @@ boolean hasValue() { return StringUtils.hasText(this.value); } - Path toWatchPath() { + Path toWatchPath(ResourceLoader resourceLoader) { try { - Resource resource = getResource(); + Assert.state(!isPemContent(), "Value contains PEM content"); + Resource resource = resourceLoader.getResource(this.value); if (!resource.isFile()) { throw new BundleContentNotWatchableException(this); } @@ -68,9 +69,4 @@ Path toWatchPath() { } } - private Resource getResource() { - Assert.state(!isPemContent(), "Value contains PEM content"); - return new ApplicationResourceLoader().getResource(this.value); - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/SslPropertiesBundleRegistrar.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/SslPropertiesBundleRegistrar.java index 6687e81a6635..e1cbe6fbc4d6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/SslPropertiesBundleRegistrar.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/SslPropertiesBundleRegistrar.java @@ -111,7 +111,7 @@ private Set watchedPaths(String bundleName, List pr try { return properties.stream() .filter(BundleContentProperty::hasValue) - .map(BundleContentProperty::toWatchPath) + .map((content) -> content.toWatchPath(this.resourceLoader)) .collect(Collectors.toSet()); } catch (BundleContentNotWatchableException ex) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/BundleContentPropertyTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/BundleContentPropertyTests.java index caf822da60e4..b4e6477f002c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/BundleContentPropertyTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/BundleContentPropertyTests.java @@ -22,9 +22,15 @@ import org.junit.jupiter.api.Test; +import org.springframework.boot.io.ApplicationResourceLoader; +import org.springframework.core.io.ResourceLoader; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.spy; /** * Tests for {@link BundleContentProperty}. @@ -72,7 +78,7 @@ void hasValueWhenHasEmptyValueReturnsFalse() { @Test void toWatchPathWhenNotPathThrowsException() { BundleContentProperty property = new BundleContentProperty("name", PEM_TEXT); - assertThatIllegalStateException().isThrownBy(property::toWatchPath) + assertThatIllegalStateException().isThrownBy(() -> property.toWatchPath(new ApplicationResourceLoader())) .withMessage("Unable to convert value of property 'name' to a path"); } @@ -81,13 +87,24 @@ void toWatchPathWhenPathReturnsPath() throws URISyntaxException { URL resource = getClass().getResource("keystore.jks"); Path file = Path.of(resource.toURI()).toAbsolutePath(); BundleContentProperty property = new BundleContentProperty("name", file.toString()); - assertThat(property.toWatchPath()).isEqualTo(file); + assertThat(property.toWatchPath(new ApplicationResourceLoader())).isEqualTo(file); + } + + @Test + void toWatchPathUsesResourceLoader() throws URISyntaxException { + URL resource = getClass().getResource("keystore.jks"); + Path file = Path.of(resource.toURI()).toAbsolutePath(); + BundleContentProperty property = new BundleContentProperty("name", file.toString()); + ResourceLoader resourceLoader = spy(new ApplicationResourceLoader()); + assertThat(property.toWatchPath(resourceLoader)).isEqualTo(file); + then(resourceLoader).should(atLeastOnce()).getResource(file.toString()); } @Test void shouldThrowBundleContentNotWatchableExceptionIfContentIsNotWatchable() { BundleContentProperty property = new BundleContentProperty("name", "https://example.com/"); - assertThatExceptionOfType(BundleContentNotWatchableException.class).isThrownBy(property::toWatchPath) + assertThatExceptionOfType(BundleContentNotWatchableException.class) + .isThrownBy(() -> property.toWatchPath(new ApplicationResourceLoader())) .withMessageContaining("Only 'file:' resources are watchable"); }