Introduce getAbsolutePath() in ClassPathResource
Since getPath() returns a relative path if the resource was created using the ClassPathResource(String,Class) constructor, there was previously no way to consistently obtain the absolute path to the resource within the class path. This commit addresses this shortcoming by introducing a new getAbsolutePath() for consistently obtaining the absolute path to the resource within the class path. See gh-29083 Closes gh-29094
This commit is contained in:
parent
1052f48eb6
commit
d57e061d3f
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <em>relative path</em> supplied to the constructor.
|
||||
* <p>If you need the <em>absolute path</em>, use {@link #getAbsolutePath()}
|
||||
* instead.
|
||||
* @see #getAbsolutePath()
|
||||
*/
|
||||
public final String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the <em>absolute path</em> 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 + ']';
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue