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 4bdf8a89c04..82be1949420 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 @@ -121,7 +121,7 @@ public class ResourceHints { */ public void registerResourceIfNecessary(Resource resource) { if (resource instanceof ClassPathResource classPathResource && classPathResource.exists()) { - registerPattern(classPathResource.getPath()); + registerPattern(classPathResource.getAbsolutePath()); } } diff --git a/spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java b/spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java index 93b5a503756..79d6fea794a 100644 --- a/spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java @@ -47,6 +47,8 @@ public class ClassPathResource extends AbstractFileResolvingResource { private final String path; + private final String absolutePath; + @Nullable private final ClassLoader classLoader; @@ -83,6 +85,7 @@ public class ClassPathResource extends AbstractFileResolvingResource { pathToUse = pathToUse.substring(1); } this.path = pathToUse; + this.absolutePath = pathToUse; this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); this.clazz = null; } @@ -100,6 +103,16 @@ public class ClassPathResource extends AbstractFileResolvingResource { public ClassPathResource(String path, @Nullable Class clazz) { Assert.notNull(path, "Path must not be null"); this.path = StringUtils.cleanPath(path); + + String absolutePath = this.path; + if (clazz != null && !absolutePath.startsWith("/")) { + absolutePath = ClassUtils.classPackageAsResourcePath(clazz) + "/" + absolutePath; + } + else if (absolutePath.startsWith("/")) { + absolutePath = absolutePath.substring(1); + } + this.absolutePath = absolutePath; + this.classLoader = null; this.clazz = clazz; } @@ -117,11 +130,24 @@ public class ClassPathResource extends AbstractFileResolvingResource { * {@link ClassPathResource#ClassPathResource(String, Class)}, the * returned path is a {@linkplain StringUtils#cleanPath(String) cleaned} * version of the relative path supplied to the constructor. + *

If you need the absolute path, use {@link #getAbsolutePath()} + * instead. + * @see #getAbsolutePath() */ public final String getPath() { return this.path; } + /** + * Return the absolute path for this resource, as a resource path + * within the class path. + * @since 6.0 + * @see #getPath() + */ + public final String getAbsolutePath() { + return this.absolutePath; + } + /** * Return the {@link ClassLoader} that this resource will be obtained from. */ @@ -245,18 +271,7 @@ public class ClassPathResource extends AbstractFileResolvingResource { */ @Override public String getDescription() { - StringBuilder builder = new StringBuilder("class path resource ["); - String pathToUse = this.path; - if (this.clazz != null && !pathToUse.startsWith("/")) { - builder.append(ClassUtils.classPackageAsResourcePath(this.clazz)); - builder.append('/'); - } - if (pathToUse.startsWith("/")) { - pathToUse = pathToUse.substring(1); - } - builder.append(pathToUse); - builder.append(']'); - return builder.toString(); + return "class path resource [" + this.absolutePath + ']'; } 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 3b00278fe47..690c8f6d575 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,7 +21,6 @@ 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; @@ -136,14 +135,11 @@ class ResourceHintsTests { 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)); }