diff --git a/org.graalvm.python.embedding/src/main/java/org/graalvm/python/embedding/VirtualFileSystem.java b/org.graalvm.python.embedding/src/main/java/org/graalvm/python/embedding/VirtualFileSystem.java
index f74ab3f..b5c4392 100644
--- a/org.graalvm.python.embedding/src/main/java/org/graalvm/python/embedding/VirtualFileSystem.java
+++ b/org.graalvm.python.embedding/src/main/java/org/graalvm/python/embedding/VirtualFileSystem.java
@@ -107,7 +107,8 @@ public static final class Builder {
private HostIO allowHostIO = HostIO.READ_WRITE;
private boolean caseInsensitive = VirtualFileSystemImpl.isWindows();
- private Class> resourceLoadingClass;
+ private ClassLoader resourceClassLoader;
+
private String resourceDirectory;
private Builder() {
@@ -238,7 +239,7 @@ public Builder unixMountPoint(String unixMountPoint) {
/**
* By default, virtual filesystem resources are loaded by delegating to
- * VirtualFileSystem.class.getResource(name). Use
+ * VirtualFileSystem.class.getClassLoader().getResource(name). Use
* resourceLoadingClass to determine where to locate resources in
* cases when for example VirtualFileSystem is on module path and
* the jar containing the resources is on class path.
@@ -249,7 +250,24 @@ public Builder unixMountPoint(String unixMountPoint) {
* @since 24.2.0
*/
public Builder resourceLoadingClass(Class> c) {
- resourceLoadingClass = c;
+ resourceClassLoader = c.getClassLoader();
+ return this;
+ }
+
+ /**
+ * By default, virtual filesystem resources are loaded by delegating to
+ * VirtualFileSystem.class.getClassLoader().getResource(name). Use
+ * resourceClassLoader to determine where to locate resources in
+ * cases when for example VirtualFileSystem is on module path and
+ * the jar containing the resources is on class path.
+ *
+ * @param cl
+ * the classloader used to load resources
+ * @return this builder
+ * @since 26.0.0
+ */
+ public Builder resourceClassLoader(ClassLoader cl) {
+ resourceClassLoader = cl;
return this;
}
@@ -292,8 +310,8 @@ public VirtualFileSystem build() {
? Path.of(DEFAULT_WINDOWS_MOUNT_POINT)
: Path.of(DEFAULT_UNIX_MOUNT_POINT);
}
- return new VirtualFileSystem(extractFilter, mountPoint, allowHostIO, resourceLoadingClass,
- resourceDirectory, caseInsensitive);
+ return new VirtualFileSystem(extractFilter, mountPoint, allowHostIO, resourceClassLoader, resourceDirectory,
+ caseInsensitive);
}
}
@@ -308,10 +326,10 @@ private static Path getMountPointAsPath(String mp) {
}
private VirtualFileSystem(Predicate extractFilter, Path mountPoint, HostIO allowHostIO,
- Class> resourceLoadingClass, String resourceDirectory, boolean caseInsensitive) {
+ ClassLoader resourceClassLoader, String resourceDirectory, boolean caseInsensitive) {
this.impl = new VirtualFileSystemImpl(extractFilter, mountPoint, resourceDirectory, allowHostIO,
- resourceLoadingClass, caseInsensitive);
+ resourceClassLoader, caseInsensitive);
this.delegatingFileSystem = VirtualFileSystemImpl.createDelegatingFileSystem(impl);
}
diff --git a/org.graalvm.python.embedding/src/main/java/org/graalvm/python/embedding/VirtualFileSystemImpl.java b/org.graalvm.python.embedding/src/main/java/org/graalvm/python/embedding/VirtualFileSystemImpl.java
index 1bfa25c..8f5a8f6 100644
--- a/org.graalvm.python.embedding/src/main/java/org/graalvm/python/embedding/VirtualFileSystemImpl.java
+++ b/org.graalvm.python.embedding/src/main/java/org/graalvm/python/embedding/VirtualFileSystemImpl.java
@@ -171,10 +171,10 @@ private static String absoluteResourcePath(String... components) {
private final Map vfsEntries = new HashMap<>();
/**
- * Class used to read resources with getResource(name). By default
+ * Classloader used to read resources. By defaut, the classloader of
* VirtualFileSystem.class.
*/
- private Class> resourceLoadingClass;
+ private final ClassLoader resourceClassLoader;
static final String PLATFORM_SEPARATOR = Paths.get("").getFileSystem().getSeparator();
private static final char RESOURCE_SEPARATOR_CHAR = '/';
@@ -310,11 +310,11 @@ private void removeExtractDir() {
* argument may be {@code null} causing that no extraction will happen.
*/
VirtualFileSystemImpl(Predicate extractFilter, Path mountPoint, String resourceDirectory, HostIO allowHostIO,
- Class> resourceLoadingClass, boolean caseInsensitive) {
- if (resourceLoadingClass != null) {
- this.resourceLoadingClass = resourceLoadingClass;
+ ClassLoader resourceClassLoader, boolean caseInsensitive) {
+ if (resourceClassLoader != null) {
+ this.resourceClassLoader = resourceClassLoader;
} else {
- this.resourceLoadingClass = VirtualFileSystem.class;
+ this.resourceClassLoader = VirtualFileSystem.class.getClassLoader();
}
this.caseInsensitive = caseInsensitive;
this.mountPoint = mountPoint;
@@ -323,10 +323,14 @@ private void removeExtractDir() {
this.platformVenvPath = resourcePathToPlatformPath(absoluteResourcePath(vfsRoot, VFS_VENV));
this.platformSrcPath = resourcePathToPlatformPath(absoluteResourcePath(vfsRoot, VFS_SRC));
- fine("VirtualFilesystem %s, allowHostIO: %s, resourceLoadingClass: %s, caseInsensitive: %s, extractOnStartup: %s%s",
- mountPoint, allowHostIO.toString(), this.resourceLoadingClass.getName(), caseInsensitive,
- extractOnStartup, extractFilter != null ? "" : ", extractFilter: null");
-
+ if (LOGGER.isLoggable(Level.FINE)) {
+ var classLoaderLabel = this.resourceClassLoader == VirtualFileSystem.class.getClassLoader()
+ ? "VirtualFileSystem"
+ : "custom";
+ fine("VirtualFilesystem %s, allowHostIO: %s, resourceClassLoader: %s, caseInsensitive: %s, extractOnStartup: %s%s",
+ mountPoint, allowHostIO.toString(), classLoaderLabel, caseInsensitive, extractOnStartup,
+ extractFilter != null ? "" : ", extractFilter: null");
+ }
this.extractFilter = extractFilter;
if (extractFilter != null) {
try {
@@ -670,7 +674,7 @@ public boolean equals(Object obj) {
private List getFilelistURLs(String filelistPath) {
List filelistUrls;
try {
- filelistUrls = Collections.list(this.resourceLoadingClass.getClassLoader().getResources(filelistPath));
+ filelistUrls = Collections.list(resourceClassLoader.getResources(filelistPath));
} catch (IOException e) {
throw new IllegalStateException("IO error during reading the VirtualFileSystem metadata", e);
}
@@ -745,8 +749,7 @@ private void validateMultipleVFSLocations(List filelistUrls) {
// by the Maven/Gradle plugin and should contain "pip freeze" of the venv
ArrayList installedUrls;
try {
- installedUrls = Collections.list(
- this.resourceLoadingClass.getClassLoader().getResources(resourcePath(vfsRoot, INSTALLED_FILE)));
+ installedUrls = Collections.list(resourceClassLoader.getResources(resourcePath(vfsRoot, INSTALLED_FILE)));
} catch (IOException e) {
warn("Cannot check compatibility of the merged virtual environments. Cannot read list of packages installed in the virtual environments. IOException: "
+ e.getMessage());
@@ -790,8 +793,7 @@ private void validateMultipleVFSLocations(List filelistUrls) {
// Check compatibility of GraalPy versions that were used to create the VFSs
ArrayList contentsUrls;
try {
- contentsUrls = Collections.list(
- this.resourceLoadingClass.getClassLoader().getResources(resourcePath(vfsRoot, CONTENTS_FILE)));
+ contentsUrls = Collections.list(resourceClassLoader.getResources(resourcePath(vfsRoot, CONTENTS_FILE)));
} catch (IOException e) {
warn("Cannot check compatibility of the merged virtual environments. Cannot read GraalPy version of the virtual environments. IOException: "
+ e.getMessage());
@@ -831,7 +833,7 @@ private void validateMultipleVFSLocations(List filelistUrls) {
}
private URL getResourceUrl(String path) throws IOException {
- List urls = Collections.list(this.resourceLoadingClass.getClassLoader().getResources(path.substring(1)));
+ List urls = Collections.list(resourceClassLoader.getResources(path.substring(1)));
if (vfsRootURL != null) {
urls = getURLInRoot(urls);
}