diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/sbom/SbomEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/sbom/SbomEndpoint.java index 5708afba84a..503e667f72a 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/sbom/SbomEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/sbom/SbomEndpoint.java @@ -23,10 +23,14 @@ import java.util.List; import java.util.Map; import java.util.TreeSet; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.boot.actuate.endpoint.OperationResponseBody; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.boot.actuate.endpoint.annotation.Selector; +import org.springframework.boot.actuate.sbom.SbomEndpoint.SbomEndpointRuntimeHints; +import org.springframework.context.annotation.ImportRuntimeHints; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.util.StringUtils; @@ -38,6 +42,7 @@ import org.springframework.util.StringUtils; * @since 3.3.0 */ @Endpoint(id = "sbom") +@ImportRuntimeHints(SbomEndpointRuntimeHints.class) public class SbomEndpoint { private static final List DEFAULT_APPLICATION_SBOM_LOCATIONS = List.of("classpath:META-INF/sbom/bom.json", @@ -141,4 +146,19 @@ public class SbomEndpoint { } } + static class SbomEndpointRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + for (String defaultLocation : DEFAULT_APPLICATION_SBOM_LOCATIONS) { + hints.resources().registerPattern(stripClasspathPrefix(defaultLocation)); + } + } + + private String stripClasspathPrefix(String location) { + return location.substring("classpath:".length()); + } + + } + } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/sbom/SbomEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/sbom/SbomEndpointTests.java index 21db6474c2b..f4c724d6903 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/sbom/SbomEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/sbom/SbomEndpointTests.java @@ -22,6 +22,9 @@ import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.boot.actuate.sbom.SbomEndpoint.SbomEndpointRuntimeHints; import org.springframework.boot.actuate.sbom.SbomEndpoint.Sboms; import org.springframework.boot.actuate.sbom.SbomProperties.Sbom; import org.springframework.context.support.GenericApplicationContext; @@ -81,6 +84,14 @@ class SbomEndpointTests { assertThat(createEndpoint().sbom("application")).isNull(); } + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new SbomEndpointRuntimeHints().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.resource().forResource("META-INF/sbom/bom.json")).accepts(hints); + assertThat(RuntimeHintsPredicates.resource().forResource("META-INF/sbom/application.cdx.json")).accepts(hints); + } + private Sbom sbom(String location) { Sbom result = new Sbom(); result.setLocation(location);