IJPL-175521 Eel FS: MultiRoutingFileSystemProvider.newFileSystem throws UnsupportedOperationException

There are backends for opening archives as NIO filesystems. `java.nio.file.FileSystems.newFileSystem` iterates over backends and returns the filesystem from the first backend that doesn't throw an `UnsupportedOperationException`.

`FileSystems.newFileSystem` always tries the default file system provider the first. Before this commit, `FileSystems.newFileSystem` returned an instance of `MultiRoutingFileSystem` for ZIP files, while it was supposed to return `jdk.nio.zipfs.ZipFileSystem`.

Now `MultiRoutingFileSystemProvider.newFileSystem` throws UOE, just like `WindowsFileSystemProvider` and `UnixFileSystemProvider`.

GitOrigin-RevId: cb18db3d5d02060fc550a1b509b215b181ec6efc
This commit is contained in:
Vladimir Lagunov
2025-02-11 23:07:06 +00:00
committed by intellij-monorepo-bot
parent 1da8b5b197
commit f0a7a18efb
2 changed files with 49 additions and 44 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.core.nio.fs;
import org.jetbrains.annotations.Contract;
@@ -14,6 +14,7 @@ import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.spi.FileSystemProvider;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.BiFunction;
/**
@@ -77,6 +78,7 @@ public final class MultiRoutingFileSystemProvider
) {
if (provider.getClass().getName().equals(MultiRoutingFileSystemProvider.class.getName())) {
Map<String, Object> arguments = new HashMap<>();
arguments.put(KEY_MRFS, Void.TYPE);
arguments.put(KEY_ROOT, root);
arguments.put(KEY_PREFIX, isPrefix);
arguments.put(KEY_CASE_SENSITIVE, caseSensitive);
@@ -106,14 +108,18 @@ public final class MultiRoutingFileSystemProvider
}
@Override
public @NotNull MultiRoutingFileSystem newFileSystem(Path path, Map<String, ?> env) {
return getFileSystem(path.toUri());
public @Nullable MultiRoutingFileSystem newFileSystem(Path path, @Nullable Map<String, ?> env) {
throw new UnsupportedOperationException(MultiRoutingFileSystemProvider.class.getName() + " doesn't open other files as filesystems");
}
@Override
public @Nullable MultiRoutingFileSystem newFileSystem(URI uri, @Nullable Map<String, ?> env) {
if (env == null) {
return getFileSystem(uri);
if (env == null || !env.containsKey(KEY_MRFS)) {
throw new UnsupportedOperationException(
MultiRoutingFileSystem.class.getName() + " can be created only with `" +
MultiRoutingFileSystemProvider.class.getName() + ".computeBackend()`." +
" Otherwise, this file system provider behaves as a default file system provider and throws an error."
);
}
String root = Objects.requireNonNull((String)env.get(KEY_ROOT));
@@ -128,6 +134,7 @@ public final class MultiRoutingFileSystemProvider
return null;
}
private static final String KEY_MRFS = "MRFS." + ThreadLocalRandom.current().nextInt(0, Integer.MAX_VALUE);
private static final String KEY_ROOT = "KEY_ROOT";
private static final String KEY_PREFIX = "KEY_PREFIX";
private static final String KEY_CASE_SENSITIVE = "KEY_CASE_SENSITIVE";
@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.ijent.community.impl.nio
import com.intellij.openapi.diagnostic.thisLogger
@@ -73,7 +73,13 @@ class IjentNioFileSystemProvider : FileSystemProvider() {
override fun newFileSystem(uri: URI, env: MutableMap<String, *>): IjentNioFileSystem {
@Suppress("NAME_SHADOWING") val uri = uri.normalize()
typicalUriChecks(uri)
if (uri.authority.isNullOrEmpty()
|| uri.scheme != this.scheme
|| !uri.query.isNullOrEmpty()
|| !uri.fragment.isNullOrEmpty()) {
throw UnsupportedOperationException(uri.toString() + " doesn't look like a proper URL for " + IjentNioFileSystemProvider::class.simpleName)
}
val ijentFs =
try {
env[KEY_IJENT_FS] as IjentFileSystemApi
@@ -496,35 +502,35 @@ class IjentNioFileSystemProvider : FileSystemProvider() {
val oldPermissions =
(readAttributes(path, PosixFileAttributes::class.java, *options) as IjentNioPosixFileAttributes).fileInfo.permissions
builder.permissions(when (requestedAttributes.singleOrNull()) {
"permissions" -> {
value as Set<*> // ClassCastException is expected
@Suppress("UNCHECKED_CAST") val mask = PosixFilePermissionsUtil.toUnixMode(value as Set<PosixFilePermission>)
EelPosixFileInfoImpl.Permissions(oldPermissions.owner, oldPermissions.group, mask)
}
"owner" -> {
if (value is EelPosixUserPrincipal) {
if (value.uid != oldPermissions.owner) {
TODO("Changing uid is not supported yet")
}
oldPermissions
}
else {
throw UnsupportedOperationException("Unsupported owner principal: $value")
}
}
"group" -> {
if (value is EelPosixGroupPrincipal) {
if (value.gid != oldPermissions.group) {
TODO("Changing gid is not supported yet")
}
oldPermissions
}
else {
throw java.lang.UnsupportedOperationException("Unsupported group principal: $value")
}
}
else -> throw IllegalArgumentException("Unrecognized attribute: $attribute")
})
"permissions" -> {
value as Set<*> // ClassCastException is expected
@Suppress("UNCHECKED_CAST") val mask = PosixFilePermissionsUtil.toUnixMode(value as Set<PosixFilePermission>)
EelPosixFileInfoImpl.Permissions(oldPermissions.owner, oldPermissions.group, mask)
}
"owner" -> {
if (value is EelPosixUserPrincipal) {
if (value.uid != oldPermissions.owner) {
TODO("Changing uid is not supported yet")
}
oldPermissions
}
else {
throw UnsupportedOperationException("Unsupported owner principal: $value")
}
}
"group" -> {
if (value is EelPosixGroupPrincipal) {
if (value.gid != oldPermissions.group) {
TODO("Changing gid is not supported yet")
}
oldPermissions
}
else {
throw java.lang.UnsupportedOperationException("Unsupported group principal: $value")
}
}
else -> throw IllegalArgumentException("Unrecognized attribute: $attribute")
})
}
else -> throw java.lang.IllegalArgumentException("Unrecognized attribute: $attribute")
}
@@ -625,14 +631,6 @@ class IjentNioFileSystemProvider : FileSystemProvider() {
return path
}
private fun typicalUriChecks(uri: URI) {
require(uri.authority.isNotEmpty())
require(uri.scheme == scheme) { "${uri.scheme} != $scheme" }
require(uri.query.isNullOrEmpty()) { uri.query }
require(uri.fragment.isNullOrEmpty()) { uri.fragment }
}
}