Jetty version(s)
12.1.9
Jetty Environment
HTTP version
Java version/vendor (use: java -version)
openjdk 25.0.3-ea
OS type/version
Ubuntu 26.04
Description
After the FileSystemPool deprecation in PR #14826, ResourceFactory.newClassLoaderResource(...) can return a multi-member CombinedResource whose members all point at the same jar entry. CombinedResource.gatherUniqueFlatResourceList no longer collapses them because PathResource.equals now returns false for what is effectively the same path but on different filesystems because of MountedPathResourceFactory.newFileSystem(...).
Affected code
- org.eclipse.jetty.util.resource.ResourceFactory#newClassLoaderResource(String, boolean)
- org.eclipse.jetty.util.resource.CombinedResource#gatherUniqueFlatResourceList(List)
How to reproduce?
Setup: any classpath where the same resource is visible through more than one classloader in newClassLoaderResource's search order (context CL, ResourceFactory.class CL, optionally system CL)
Easily reproduces with swagger-ui webjar.
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>12.1.9</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>5.32.5</version>
</dependency>
System.out.println("jetty-util " + ResourceFactory.class.getPackage().getImplementationVersion());
try (ResourceFactory.Closeable rf = ResourceFactory.closeable()) {
Resource r = rf.newClassLoaderResource("META-INF/resources/webjars/swagger-ui");
System.out.println("class: " + r.getClass().getSimpleName());
System.out.println("getURI(): " + r.getURI());
if (r instanceof CombinedResource combined && combined.getResources().size() >= 2) {
Resource a = combined.getResources().get(0);
Resource b = combined.getResources().get(1);
System.out.println("members: " + combined.getResources().size());
System.out.println("a.getURI().equals(b.getURI()) = " + a.getURI().equals(b.getURI()));
System.out.println("a.getPath().getFileSystem() == b.getPath().getFileSystem() = " + (a.getPath().getFileSystem() == b.getPath().getFileSystem()));
System.out.println("a.getPath().equals(b.getPath()) = " + a.getPath().equals(b.getPath()));
System.out.println("a.equals(b) = " + a.equals(b));
}
12.1.8 output
jetty-util 12.1.8
class: MountedPathResource
getURI(): jar:file:///home/aneta/.m2/repository/org/webjars/swagger-ui/5.32.5/swagger-ui-5.32.5.jar!/META-INF/resources/webjars/swagger-ui/
12.1.9 output
jetty-util 12.1.9
class: CombinedResource
getURI(): null
members: 2
a.getURI().equals(b.getURI()) = true
a.getPath().getFileSystem() == b.getPath().getFileSystem() = false
a.getPath().equals(b.getPath()) = false
a.equals(b) = false
Jetty version(s)
12.1.9
Jetty Environment
HTTP version
Java version/vendor
(use: java -version)openjdk 25.0.3-ea
OS type/version
Ubuntu 26.04
Description
After the FileSystemPool deprecation in PR #14826,
ResourceFactory.newClassLoaderResource(...)can return a multi-memberCombinedResourcewhose members all point at the same jar entry.CombinedResource.gatherUniqueFlatResourceListno longer collapses them becausePathResource.equalsnow returnsfalsefor what is effectively the same path but on different filesystems because ofMountedPathResourceFactory.newFileSystem(...).Affected code
How to reproduce?
Setup: any classpath where the same resource is visible through more than one classloader in newClassLoaderResource's search order (context CL, ResourceFactory.class CL, optionally system CL)
Easily reproduces with swagger-ui webjar.
12.1.8 output
12.1.9 output