Skip to content

Commit 138f9c6

Browse files
committed
Consistently return absolute path from ClassPathResource#getPath
Prior to this commit, the Javadoc for the getPath() method in ClassPathResource stated the following. > Return the path for this resource (as resource path within the class path). That implied the returned path was an "absolute path" within the class path; however, that was not always true. If the resource was created using ClassPathResource(String) or ClassPathResource(String, ClassLoader), the returned path was a cleaned version of the ABSOLUTE PATH supplied to the constructor, WITHOUT a leading slash. If the resource was created using ClassPathResource(String, Class) with an absolute path, the returned path was a cleaned version of the ABSOLUTE PATH supplied to the constructor, WITH a leading slash. If the resource was created using ClassPathResource(String, Class) with a relative path, the returned path was a cleaned version of the RELATIVE PATH supplied to the constructor. In addition, ClassPathResource does not provide public access the Class passed to the ClassPathResource(String, Class) constructor. Consequently, the path returned by getPath() could not be reliably used with ClassLoader.getResource(String) or with the recently introduced registerResource(Resource) method in ResourceHints. This commit addresses this issue by ensuring that getPath() consistently returns the absolute path within the class path without a leading slash. See spring-projectsgh-29083 Reverts spring-projectsgh-29094 Closes spring-projectsgh-29099
1 parent 0dba729 commit 138f9c6

File tree

3 files changed

+16
-41
lines changed

3 files changed

+16
-41
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ public ResourceHints registerPattern(String include) {
118118
* @throws IllegalArgumentException if the supplied resource is not a
119119
* {@link ClassPathResource} or does not {@linkplain Resource#exists() exist}
120120
* @see #registerPattern(String)
121-
* @see ClassPathResource#getAbsolutePath()
121+
* @see ClassPathResource#getPath()
122122
*/
123123
public void registerResource(Resource resource) {
124124
if (resource instanceof ClassPathResource classPathResource && classPathResource.exists()) {
125-
registerPattern(classPathResource.getAbsolutePath());
125+
registerPattern(classPathResource.getPath());
126126
}
127127
else {
128128
throw new IllegalArgumentException("Resource must be a ClassPathResource that exists: " + resource);

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

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
*/
4646
public class ClassPathResource extends AbstractFileResolvingResource {
4747

48+
/**
49+
* Internal representation of the original path supplied by the user,
50+
* used for creating relative paths and resolving URLs and InputStreams.
51+
*/
4852
private final String path;
4953

5054
private final String absolutePath;
@@ -119,44 +123,13 @@ else if (absolutePath.startsWith("/")) {
119123

120124

121125
/**
122-
* Return the path for this resource.
123-
* <p>If this resource was created using
124-
* {@link ClassPathResource#ClassPathResource(String) ClassPathResource(String)}
125-
* or {@link ClassPathResource#ClassPathResource(String, ClassLoader)
126-
* ClassPathResource(String, ClassLoader)}, the returned path is a
127-
* {@linkplain StringUtils#cleanPath(String) cleaned} version of the
128-
* <em>absolute path</em> supplied to the constructor, <strong>without</strong>
129-
* a leading slash.
130-
* <p>If this resource was created using
131-
* {@link ClassPathResource#ClassPathResource(String, Class)
132-
* ClassPathResource(String, Class)} with an absolute path, the returned path
133-
* is a {@linkplain StringUtils#cleanPath(String) cleaned} version of the
134-
* <em>absolute path</em> supplied to the constructor, <strong>with</strong>
135-
* a leading slash.
136-
* <p>If this resource was created using
137-
* {@link ClassPathResource#ClassPathResource(String, Class)
138-
* ClassPathResource(String, Class)} with a relative path, the returned path
139-
* is a {@linkplain StringUtils#cleanPath(String) cleaned} version of the
140-
* <em>relative path</em> supplied to the constructor.
141-
* <p>The path returned by this method cannot be reliably used with
142-
* {@link ClassLoader#getResource(String)}.
143-
* <p>If you consistently need the <em>absolute path</em>, use
144-
* {@link #getAbsolutePath()} instead.
145-
* @see #getAbsolutePath()
126+
* Return the <em>absolute path</em> for this resource, as a
127+
* {@linkplain StringUtils#cleanPath(String) cleaned} resource path within
128+
* the class path.
129+
* <p>The path returned by this method does not have a leading slash and is
130+
* suitable for use with {@link ClassLoader#getResource(String)}.
146131
*/
147132
public final String getPath() {
148-
return this.path;
149-
}
150-
151-
/**
152-
* Return the <em>absolute path</em> for this resource, as a resource path
153-
* within the class path without a leading slash.
154-
* <p>The path returned by this method is suitable for use with
155-
* {@link ClassLoader#getResource(String)}.
156-
* @since 6.0
157-
* @see #getPath()
158-
*/
159-
public final String getAbsolutePath() {
160133
return this.absolutePath;
161134
}
162135

spring-core/src/test/java/org/springframework/core/io/ClassPathResourceTests.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,11 @@ void dropLeadingSlashForClassLoaderAccess() {
103103
}
104104

105105
@Test
106-
void preserveLeadingSlashForClassRelativeAccess() {
107-
assertThat(new ClassPathResource("/test.html", getClass()).getPath()).isEqualTo("/test.html");
108-
assertThat(((ClassPathResource) new ClassPathResource("", getClass()).createRelative("/test.html")).getPath()).isEqualTo("/test.html");
106+
void convertToAbsolutePathForClassRelativeAccess() {
107+
assertThat(new ClassPathResource("/test.html", getClass()).getPath()).isEqualTo("test.html");
108+
assertThat(new ClassPathResource("", getClass()).getPath()).isEqualTo(PACKAGE_PATH + "/");
109+
assertThat(((ClassPathResource) new ClassPathResource("", getClass()).createRelative("/test.html")).getPath()).isEqualTo("test.html");
110+
assertThat(((ClassPathResource) new ClassPathResource("", getClass()).createRelative("test.html")).getPath()).isEqualTo(PACKAGE_PATH + "/test.html");
109111
}
110112

111113
@Test

0 commit comments

Comments
 (0)