Skip to content

Commit 090cf35

Browse files
committed
RunnerClassLoader - Return URL with an ending / if resource ending with /
While QuarkusClassLoader already has this behavior, RunnerClassLoader was forcibly removing the ending / even when the requested resource had one. This shouldn't be the case. Fixes #46563 Fixes #46998 (cherry picked from commit 3a8db48)
1 parent e7c787e commit 090cf35

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

independent-projects/bootstrap/runner/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@
6969
<type>pom</type>
7070
<scope>test</scope>
7171
</dependency>
72+
<dependency>
73+
<groupId>org.assertj</groupId>
74+
<artifactId>assertj-core</artifactId>
75+
<scope>test</scope>
76+
</dependency>
7277

7378
<dependency>
7479
<groupId>io.quarkus</groupId>

independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/JarResource.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,13 @@ private static class JarResourceURLProvider implements JarFileReference.JarFileC
9393
private static final JarResourceURLProvider INSTANCE = new JarResourceURLProvider();
9494

9595
@Override
96-
public URL apply(JarFile jarFile, Path path, String res) {
97-
JarEntry entry = jarFile.getJarEntry(res);
96+
public URL apply(JarFile jarFile, Path path, String resource) {
97+
JarEntry entry = jarFile.getJarEntry(resource);
9898
if (entry == null) {
9999
return null;
100100
}
101101
try {
102-
String realName = JarEntries.getRealName(entry);
103-
// Avoid ending the URL with / to avoid breaking compatibility
104-
if (realName.endsWith("/")) {
105-
realName = realName.substring(0, realName.length() - 1);
106-
}
107-
final URL resUrl = getUrl(path, realName);
102+
final URL resUrl = getUrl(path, getRealName(entry, resource));
108103
// wrap it up into a "jar" protocol URL
109104
//horrible hack to deal with '?' characters in the URL
110105
//seems to be the only way, the URI constructor just does not let you handle them in a sane way
@@ -124,6 +119,25 @@ public URL apply(JarFile jarFile, Path path, String res) {
124119
}
125120
}
126121

122+
private static String getRealName(JarEntry entry, String resource) {
123+
String realName = JarEntries.getRealName(entry);
124+
// Make sure directories are returned with a / when the resource was requested with a /
125+
if (resource.endsWith("/") && entry.isDirectory()) {
126+
if (realName.endsWith("/")) {
127+
return realName;
128+
} else {
129+
return realName + "/";
130+
}
131+
}
132+
133+
// this shouldn't be necessary but the previous implementation was doing it forcibly so keeping it for safety
134+
if (realName.endsWith("/")) {
135+
return realName.substring(0, realName.length() - 1);
136+
}
137+
138+
return realName;
139+
}
140+
127141
private static URL getUrl(Path jarPath, String realName) throws MalformedURLException, URISyntaxException {
128142
final URI jarUri = jarPath.toUri();
129143
// first create a URI which includes both the jar file path and the relative resource name

independent-projects/bootstrap/runner/src/test/java/io/quarkus/bootstrap/runner/RunnerClassLoaderTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.quarkus.bootstrap.runner;
22

3+
import static org.assertj.core.api.Assertions.assertThat;
34
import static org.junit.jupiter.api.Assertions.assertTrue;
45

56
import java.nio.file.Path;
@@ -98,6 +99,27 @@ public void testConcurrentJarCloseAndReload() throws Exception {
9899
assertTrue(exceptionsInThreads.isEmpty(), "Exceptions in threads: " + exceptionsInThreads);
99100
}
100101

102+
@Test
103+
public void testUrlWithTrailingSlash() {
104+
ClassLoadingResource[] classLoadingResources = new ClassLoadingResource[] {
105+
createProjectJarResource("simple-project-1.0.jar") };
106+
107+
Map<String, ClassLoadingResource[]> resourceDirectoryMap = Map.of(
108+
"org", classLoadingResources,
109+
"org/simple", classLoadingResources);
110+
111+
RunnerClassLoader runnerClassLoader = new RunnerClassLoader(ClassLoader.getSystemClassLoader(), resourceDirectoryMap,
112+
Collections.emptySet(), Collections.emptySet(),
113+
Collections.emptyList(), Collections.emptyMap());
114+
115+
assertThat(runnerClassLoader.findResource("org").toString()).endsWith("/org");
116+
assertThat(runnerClassLoader.findResource("org/").toString()).endsWith("/org/");
117+
assertThat(runnerClassLoader.findResource("org/simple").toString()).endsWith("/org/simple");
118+
assertThat(runnerClassLoader.findResource("org/simple/").toString()).endsWith("/org/simple/");
119+
assertThat(runnerClassLoader.findResource("org/simple/SimplePojo1.class").toString())
120+
.endsWith("/org/simple/SimplePojo1.class");
121+
}
122+
101123
private static JarResource createProjectJarResource(String jarName) {
102124
ManifestInfo manifestInfo = new ManifestInfo(jarName.substring(jarName.lastIndexOf('-')), "1.0", "Apache", null, null,
103125
null);

0 commit comments

Comments
 (0)