diff --git a/spring-core/src/main/java/org/springframework/aot/hint/ResourceHints.java b/spring-core/src/main/java/org/springframework/aot/hint/ResourceHints.java index e806abcccd7..4bdf8a89c04 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/ResourceHints.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/ResourceHints.java @@ -24,12 +24,15 @@ import java.util.Set; import java.util.function.Consumer; import java.util.stream.Stream; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import org.springframework.lang.Nullable; /** * Gather the need for resources available at runtime. * * @author Stephane Nicoll + * @author Sam Brannen * @since 6.0 */ public class ResourceHints { @@ -75,7 +78,8 @@ public class ResourceHints { * @param resourceHint a builder to customize the resource pattern * @return {@code this}, to facilitate method chaining */ - public ResourceHints registerPatternIfPresent(@Nullable ClassLoader classLoader, String location, Consumer resourceHint) { + public ResourceHints registerPatternIfPresent(@Nullable ClassLoader classLoader, String location, + Consumer resourceHint) { ClassLoader classLoaderToUse = (classLoader != null) ? classLoader : getClass().getClassLoader(); if (classLoaderToUse.getResource(location) != null) { registerPattern(resourceHint); @@ -108,6 +112,19 @@ public class ResourceHints { return registerPattern(builder -> builder.includes(include)); } + /** + * Determine if the supplied resource is a {@link ClassPathResource} that + * {@linkplain Resource#exists() exists} and register the resource for run-time + * availability accordingly. + * @param resource the resource to register + * @see #registerPattern(String) + */ + public void registerResourceIfNecessary(Resource resource) { + if (resource instanceof ClassPathResource classPathResource && classPathResource.exists()) { + registerPattern(classPathResource.getPath()); + } + } + /** * Register that the bytecode of the type defined by the specified * {@link TypeReference} should be made available at runtime. diff --git a/spring-core/src/main/java/org/springframework/aot/hint/support/RuntimeHintsUtils.java b/spring-core/src/main/java/org/springframework/aot/hint/support/RuntimeHintsUtils.java index fa6cc03b91a..9668f1d891a 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/support/RuntimeHintsUtils.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/support/RuntimeHintsUtils.java @@ -19,14 +19,11 @@ package org.springframework.aot.hint.support; import java.util.function.Consumer; import org.springframework.aot.hint.MemberCategory; -import org.springframework.aot.hint.ResourceHints; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeHint; import org.springframework.aot.hint.TypeHint.Builder; import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.MergedAnnotation; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; /** * Utility methods for runtime hints support code. @@ -95,18 +92,4 @@ public abstract class RuntimeHintsUtils { } } - /** - * Determine if the supplied resource is a {@link ClassPathResource} that - * {@linkplain Resource#exists() exists} and register the resource for run-time - * availability accordingly. - * @param hints the {@link RuntimeHints} instance to use - * @param resource the resource to register - * @see ResourceHints#registerPattern(String) - */ - public static void registerResourceIfNecessary(RuntimeHints hints, Resource resource) { - if (resource instanceof ClassPathResource classPathResource && classPathResource.exists()) { - hints.resources().registerPattern(classPathResource.getPath()); - } - } - } diff --git a/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java index 209e72cecee..3b00278fe47 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java @@ -21,9 +21,12 @@ import java.util.Collections; import java.util.List; import java.util.function.Consumer; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.aot.hint.ResourceHintsTests.Nested.Inner; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.DescriptiveResource; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -33,6 +36,7 @@ import static org.mockito.Mockito.verifyNoInteractions; * Tests for {@link ResourceHints}. * * @author Stephane Nicoll + * @author Sam Brannen */ class ResourceHintsTests { @@ -110,6 +114,39 @@ class ResourceHintsTests { verifyNoInteractions(hintBuilder); } + @Test + void registerResourceIfNecessaryWithUnsupportedResourceType() { + DescriptiveResource resource = new DescriptiveResource("bogus"); + this.resourceHints.registerResourceIfNecessary(resource); + assertThat(this.resourceHints.resourcePatterns()).isEmpty(); + } + + @Test + void registerResourceIfNecessaryWithNonexistentClassPathResource() { + ClassPathResource resource = new ClassPathResource("bogus", getClass()); + this.resourceHints.registerResourceIfNecessary(resource); + assertThat(this.resourceHints.resourcePatterns()).isEmpty(); + } + + @Test + void registerResourceIfNecessaryWithExistingClassPathResource() { + String path = "org/springframework/aot/hint/support"; + ClassPathResource resource = new ClassPathResource(path); + this.resourceHints.registerResourceIfNecessary(resource); + assertThat(this.resourceHints.resourcePatterns()).singleElement().satisfies(patternOf(path)); + } + + @Disabled("Disabled since ClassPathResource.getPath() does not honor its contract for relative resources") + @Test + void registerResourceIfNecessaryWithExistingRelativeClassPathResource() { + String path = "org/springframework/aot/hint/support"; + ClassPathResource resource = new ClassPathResource("support", RuntimeHints.class); + this.resourceHints.registerResourceIfNecessary(resource); + // This unfortunately fails since ClassPathResource.getPath() returns + // "support" instead of "org/springframework/aot/hint/support". + assertThat(this.resourceHints.resourcePatterns()).singleElement().satisfies(patternOf(path)); + } + @Test void registerResourceBundle() { this.resourceHints.registerResourceBundle("com.example.message"); diff --git a/spring-core/src/test/java/org/springframework/aot/hint/support/RuntimeHintsUtilsTests.java b/spring-core/src/test/java/org/springframework/aot/hint/support/RuntimeHintsUtilsTests.java index 0b8b0248584..ca4f576e6ea 100644 --- a/spring-core/src/test/java/org/springframework/aot/hint/support/RuntimeHintsUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/aot/hint/support/RuntimeHintsUtilsTests.java @@ -20,7 +20,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.function.Consumer; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.aot.hint.JdkProxyHint; @@ -29,11 +28,8 @@ import org.springframework.aot.hint.TypeReference; import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.DescriptiveResource; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.resource; /** * Tests for {@link RuntimeHintsUtils}. @@ -45,39 +41,6 @@ class RuntimeHintsUtilsTests { private final RuntimeHints hints = new RuntimeHints(); - @Test - void registerResourceIfNecessaryWithUnsupportedResourceType() { - DescriptiveResource resource = new DescriptiveResource("bogus"); - RuntimeHintsUtils.registerResourceIfNecessary(this.hints, resource); - assertThat(this.hints.resources().resourcePatterns()).isEmpty(); - } - - @Test - void registerResourceIfNecessaryWithNonexistentClassPathResource() { - ClassPathResource resource = new ClassPathResource("bogus", getClass()); - RuntimeHintsUtils.registerResourceIfNecessary(this.hints, resource); - assertThat(this.hints.resources().resourcePatterns()).isEmpty(); - } - - @Test - void registerResourceIfNecessaryWithExistingClassPathResource() { - String path = "org/springframework/aot/hint/support"; - ClassPathResource resource = new ClassPathResource(path); - RuntimeHintsUtils.registerResourceIfNecessary(this.hints, resource); - assertThat(resource().forResource(path)).accepts(this.hints); - } - - @Disabled("Disabled since ClassPathResource.getPath() does not honor its contract for relative resources") - @Test - void registerResourceIfNecessaryWithExistingRelativeClassPathResource() { - String path = "org/springframework/aot/hint/support"; - ClassPathResource resource = new ClassPathResource("support", RuntimeHints.class); - RuntimeHintsUtils.registerResourceIfNecessary(this.hints, resource); - // This unfortunately fails since ClassPathResource.getPath() returns - // "support" instead of "org/springframework/aot/hint/support". - assertThat(resource().forResource(path)).accepts(this.hints); - } - @Test @SuppressWarnings("deprecation") void registerSynthesizedAnnotation() { diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/hint/StandardTestRuntimeHints.java b/spring-test/src/main/java/org/springframework/test/context/aot/hint/StandardTestRuntimeHints.java index 54dd5bd4af5..6642c5fda64 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/hint/StandardTestRuntimeHints.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/hint/StandardTestRuntimeHints.java @@ -20,7 +20,6 @@ import java.util.Arrays; import java.util.List; import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.support.RuntimeHintsUtils; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.test.context.ActiveProfiles; @@ -101,7 +100,7 @@ class StandardTestRuntimeHints implements TestRuntimeHintsRegistrar { Arrays.stream(paths) .filter(path -> path.startsWith(CLASSPATH_URL_PREFIX)) .map(resourceLoader::getResource) - .forEach(resource -> RuntimeHintsUtils.registerResourceIfNecessary(runtimeHints, resource)); + .forEach(runtimeHints.resources()::registerResourceIfNecessary); } private void registerClasspathResourceDirectoryStructure(String directory, RuntimeHints runtimeHints) { diff --git a/spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java index 581f9dd978a..77102118c56 100644 --- a/spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/jdbc/SqlScriptsTestExecutionListener.java @@ -28,7 +28,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.support.RuntimeHintsUtils; import org.springframework.context.ApplicationContext; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.io.ByteArrayResource; @@ -397,7 +396,7 @@ public class SqlScriptsTestExecutionListener extends AbstractTestExecutionListen Arrays.stream(paths) .filter(path -> path.startsWith(CLASSPATH_URL_PREFIX)) .map(resourceLoader::getResource) - .forEach(resource -> RuntimeHintsUtils.registerResourceIfNecessary(runtimeHints, resource)); + .forEach(runtimeHints.resources()::registerResourceIfNecessary); } }