Only use GraalIssue5720PathResourceFactory when truly needed
Previously, we were always enabling this resource factory for GraalVM native-image environments. We now check if that's actually necessary. We fall back to MountedPathResourceFactory or PathResourceFactory, depending on whether the URL contains "!/" or not.
This commit is contained in:
parent
30ffbcb7e4
commit
cdea111d3f
|
@ -13,9 +13,19 @@
|
|||
|
||||
package org.eclipse.jetty.util.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileSystemAlreadyExistsException;
|
||||
import java.nio.file.FileSystemNotFoundException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* GraalVM Native-Image {@link Path} Resource.
|
||||
|
@ -24,6 +34,7 @@ import java.nio.file.Path;
|
|||
*/
|
||||
final class GraalIssue5720PathResource extends PathResource
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(GraalIssue5720PathResource.class);
|
||||
private static final String URI_BAD_RESOURCE_PREFIX = "file:///resources!";
|
||||
|
||||
GraalIssue5720PathResource(Path path, URI uri, boolean bypassAllowedSchemeCheck)
|
||||
|
@ -36,6 +47,57 @@ final class GraalIssue5720PathResource extends PathResource
|
|||
return "resource".equals(uri.getScheme());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given resource URL is affected by Graal issue 5720.
|
||||
*
|
||||
* @param url
|
||||
* The URL to check.
|
||||
* @return {@code true} if affected.
|
||||
*/
|
||||
static boolean isAffectedURL(URL url)
|
||||
{
|
||||
if (url == null || !"resource".equals(url.getProtocol()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
URI uri;
|
||||
try
|
||||
{
|
||||
uri = url.toURI();
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
uri = Path.of(uri).toUri();
|
||||
}
|
||||
catch (FileSystemNotFoundException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileSystems.newFileSystem(uri, Collections.emptyMap());
|
||||
}
|
||||
catch (FileSystemAlreadyExistsException e2)
|
||||
{
|
||||
LOG.debug("Race condition upon calling FileSystems.newFileSystem for: {}", uri, e);
|
||||
}
|
||||
uri = Path.of(uri).toUri();
|
||||
}
|
||||
}
|
||||
catch (IOException | RuntimeException e)
|
||||
{
|
||||
LOG.warn("Could not check URL: {}", url, e);
|
||||
}
|
||||
|
||||
return uri.getSchemeSpecificPart().startsWith(URI_BAD_RESOURCE_PREFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Corrects any bad {@code resource} based URIs, such as those starting with {@code resource:file:///resources!}.
|
||||
*
|
||||
|
|
|
@ -13,59 +13,18 @@
|
|||
|
||||
package org.eclipse.jetty.util.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileSystemNotFoundException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* GraalVM Native-Image {@link PathResourceFactory}.
|
||||
*
|
||||
* @see <a href="https://github.com/oracle/graal/issues/5720">Graal issue 5720</a>
|
||||
* @see GraalIssue5720PathResource
|
||||
*/
|
||||
final class GraalIssue5720PathResourceFactory extends PathResourceFactory
|
||||
{
|
||||
static final boolean ENABLE_NATIVE_IMAGE_RESOURCE_SCHEME;
|
||||
|
||||
static
|
||||
{
|
||||
URL url = GraalIssue5720PathResourceFactory.class.getResource("/org/eclipse/jetty/version/build.properties");
|
||||
ENABLE_NATIVE_IMAGE_RESOURCE_SCHEME = (url != null && "resource".equals(url.getProtocol()));
|
||||
}
|
||||
|
||||
public GraalIssue5720PathResourceFactory()
|
||||
{
|
||||
if (ENABLE_NATIVE_IMAGE_RESOURCE_SCHEME)
|
||||
{
|
||||
initNativeImageResourceFileSystem();
|
||||
}
|
||||
}
|
||||
|
||||
private void initNativeImageResourceFileSystem()
|
||||
{
|
||||
try
|
||||
{
|
||||
URI uri = new URI("resource:/");
|
||||
try
|
||||
{
|
||||
Path.of(uri);
|
||||
}
|
||||
catch (FileSystemNotFoundException e)
|
||||
{
|
||||
FileSystems.newFileSystem(uri, Collections.emptyMap());
|
||||
}
|
||||
}
|
||||
catch (IOException | URISyntaxException | RuntimeException ignore)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource newResource(URI uri)
|
||||
{
|
||||
|
|
|
@ -55,19 +55,27 @@ class ResourceFactoryInternals
|
|||
RESOURCE_FACTORIES.put("file", pathResourceFactory);
|
||||
RESOURCE_FACTORIES.put("jrt", pathResourceFactory);
|
||||
|
||||
if (GraalIssue5720PathResourceFactory.ENABLE_NATIVE_IMAGE_RESOURCE_SCHEME)
|
||||
RESOURCE_FACTORIES.put("resource", new GraalIssue5720PathResourceFactory());
|
||||
|
||||
/* Best effort attempt to detect that an alternate FileSystem type that is in use.
|
||||
* We don't attempt to look up a Class, as not all runtimes and environments have the classes anymore
|
||||
* (e.g., they were compiled into native code)
|
||||
* The build.properties is present in the jetty-util jar, so it's reasonably safe to look for that
|
||||
* as a resource
|
||||
/* Best-effort attempt to support an alternate FileSystem type that is in use for classpath
|
||||
* resources.
|
||||
*
|
||||
* The build.properties is present in the jetty-util jar, and explicitly included for reflection
|
||||
* with native-image (unlike classes, which are not accessible by default), so we use that
|
||||
* resource as a reference.
|
||||
*/
|
||||
URL url = ResourceFactoryInternals.class.getResource("/org/eclipse/jetty/version/build.properties");
|
||||
if ((url != null) && !RESOURCE_FACTORIES.contains(url.getProtocol()))
|
||||
{
|
||||
RESOURCE_FACTORIES.put(url.getProtocol(), mountedPathResourceFactory);
|
||||
ResourceFactory resourceFactory;
|
||||
if (GraalIssue5720PathResource.isAffectedURL(url))
|
||||
{
|
||||
resourceFactory = new GraalIssue5720PathResourceFactory();
|
||||
}
|
||||
else
|
||||
{
|
||||
resourceFactory = url.toString().contains("!/") ? mountedPathResourceFactory : pathResourceFactory;
|
||||
}
|
||||
|
||||
RESOURCE_FACTORIES.put(url.getProtocol(), resourceFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue