Browse Source

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
pull/29130/head
Sam Brannen 4 years ago
parent
commit
d57e061d3f
  1. 2
      spring-core/src/main/java/org/springframework/aot/hint/ResourceHints.java
  2. 39
      spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java
  3. 4
      spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java

2
spring-core/src/main/java/org/springframework/aot/hint/ResourceHints.java

@ -121,7 +121,7 @@ public class ResourceHints { @@ -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());
}
}

39
spring-core/src/main/java/org/springframework/core/io/ClassPathResource.java

@ -47,6 +47,8 @@ public class ClassPathResource extends AbstractFileResolvingResource { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 + ']';
}

4
spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java

@ -21,7 +21,6 @@ import java.util.Collections; @@ -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 { @@ -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…
Cancel
Save