From a0fcb63a1a05df7deb0e0932f0784d092cd18564 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 21 Dec 2023 09:40:43 +0100 Subject: [PATCH] replaced FUPFMS with more generic set of used mount services --- .../org/cryptomator/common/CommonsModule.java | 9 ----- .../cryptomator/common/mount/MountModule.java | 11 ++++++ .../org/cryptomator/common/mount/Mounter.java | 37 +++++++++++-------- .../vaultoptions/MountOptionsController.java | 9 +---- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/cryptomator/common/CommonsModule.java b/src/main/java/org/cryptomator/common/CommonsModule.java index 5ea69da6d..a1e3c0950 100644 --- a/src/main/java/org/cryptomator/common/CommonsModule.java +++ b/src/main/java/org/cryptomator/common/CommonsModule.java @@ -14,7 +14,6 @@ import org.cryptomator.common.settings.SettingsProvider; import org.cryptomator.common.vaults.VaultComponent; import org.cryptomator.common.vaults.VaultListModule; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; -import org.cryptomator.integrations.mount.MountService; import org.cryptomator.integrations.revealpath.RevealPathService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,7 +29,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; @Module(subcomponents = {VaultComponent.class}, includes = {VaultListModule.class, KeychainModule.class, MountModule.class}) public abstract class CommonsModule { @@ -134,11 +132,4 @@ public abstract class CommonsModule { LOG.error("Uncaught exception in " + thread.getName(), throwable); } - @Provides - @Singleton - @Named("FUPFMS") - static AtomicReference provideFirstUsedProblematicFuseMountService() { - return new AtomicReference<>(null); - } - } diff --git a/src/main/java/org/cryptomator/common/mount/MountModule.java b/src/main/java/org/cryptomator/common/mount/MountModule.java index 3b6fa63c7..9105ff332 100644 --- a/src/main/java/org/cryptomator/common/mount/MountModule.java +++ b/src/main/java/org/cryptomator/common/mount/MountModule.java @@ -6,9 +6,12 @@ import org.cryptomator.common.ObservableUtil; import org.cryptomator.common.settings.Settings; import org.cryptomator.integrations.mount.MountService; +import javax.inject.Named; import javax.inject.Singleton; import javafx.beans.value.ObservableValue; import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; @Module public class MountModule { @@ -28,4 +31,12 @@ public class MountModule { fallbackProvider); } + + @Provides + @Singleton + @Named("usedMountServices") + static Set provideSetOfUsedMountServices() { + return ConcurrentHashMap.newKeySet(); + } + } diff --git a/src/main/java/org/cryptomator/common/mount/Mounter.java b/src/main/java/org/cryptomator/common/mount/Mounter.java index bf9fb5b1f..56bc5622a 100644 --- a/src/main/java/org/cryptomator/common/mount/Mounter.java +++ b/src/main/java/org/cryptomator/common/mount/Mounter.java @@ -16,7 +16,8 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; +import java.util.Map; +import java.util.Set; import static org.cryptomator.integrations.mount.MountCapability.MOUNT_AS_DRIVE_LETTER; import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_EXISTING_DIR; @@ -27,12 +28,17 @@ import static org.cryptomator.integrations.mount.MountCapability.UNMOUNT_FORCED; @Singleton public class Mounter { - private static final List CONFLICTING_MOUNT_SERVICES = List.of("org.cryptomator.frontend.fuse.mount.MacFuseMountProvider", "org.cryptomator.frontend.fuse.mount.FuseTMountProvider"); + // mount providers (key) can not be used if any of the conflicting mount providers (values) are already in use + private static final Map> CONFLICTING_MOUNT_SERVICES = Map.of( + "org.cryptomator.frontend.fuse.mount.MacFuseMountProvider", Set.of("org.cryptomator.frontend.fuse.mount.FuseTMountProvider"), + "org.cryptomator.frontend.fuse.mount.FuseTMountProvider", Set.of("org.cryptomator.frontend.fuse.mount.MacFuseMountProvider") + ); + private final Environment env; private final Settings settings; private final WindowsDriveLetters driveLetters; private final List mountProviders; - private final AtomicReference firstUsedProblematicFuseMountService; + private final Set usedMountServices; private final ObservableValue defaultMountService; @Inject @@ -40,13 +46,13 @@ public class Mounter { Settings settings, // WindowsDriveLetters driveLetters, // List mountProviders, // - @Named("FUPFMS") AtomicReference firstUsedProblematicFuseMountService, // + @Named("usedMountServices") Set usedMountServices, // ObservableValue defaultMountService) { this.env = env; this.settings = settings; this.driveLetters = driveLetters; this.mountProviders = mountProviders; - this.firstUsedProblematicFuseMountService = firstUsedProblematicFuseMountService; + this.usedMountServices = usedMountServices; this.defaultMountService = defaultMountService; } @@ -149,23 +155,24 @@ public class Mounter { } public MountHandle mount(VaultSettings vaultSettings, Path cryptoFsRoot) throws IOException, MountFailedException { - var selMntServ = mountProviders.stream().filter(s -> s.getClass().getName().equals(vaultSettings.mountService.getValue())).findFirst().orElse(defaultMountService.getValue()); + var mountService = mountProviders.stream().filter(s -> s.getClass().getName().equals(vaultSettings.mountService.getValue())).findFirst().orElse(defaultMountService.getValue()); - var targetIsProblematicFuse = isProblematicFuseService(selMntServ); - if (targetIsProblematicFuse && firstUsedProblematicFuseMountService.get() == null) { - firstUsedProblematicFuseMountService.set(selMntServ); - } else if (targetIsProblematicFuse && !firstUsedProblematicFuseMountService.get().equals(selMntServ)) { + if (isConflictingMountService(mountService)) { + // TODO: neither message displayed in UI nor exception is specific to FUSE, so rename this class throw new FuseRestartRequiredException("Failed to mount the specified mount service."); } - var builder = selMntServ.forFileSystem(cryptoFsRoot); - var internal = new SettledMounter(selMntServ, builder, vaultSettings); + usedMountServices.add(mountService); + + var builder = mountService.forFileSystem(cryptoFsRoot); + var internal = new SettledMounter(mountService, builder, vaultSettings); // FIXME: no need for an inner class var cleanup = internal.prepare(); - return new MountHandle(builder.mount(), selMntServ.hasCapability(UNMOUNT_FORCED), cleanup); + return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), cleanup); } - public static boolean isProblematicFuseService(MountService service) { - return CONFLICTING_MOUNT_SERVICES.contains(service.getClass().getName()); + public boolean isConflictingMountService(MountService service) { + var conflictingServices = CONFLICTING_MOUNT_SERVICES.getOrDefault(service.getClass().getName(), Set.of()); + return usedMountServices.stream().map(MountService::getClass).map(Class::getName).anyMatch(conflictingServices::contains); } public record MountHandle(Mount mountObj, boolean supportsUnmountForced, Runnable specialCleanup) { diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java index 6340852f4..cc4a42f22 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java @@ -38,7 +38,6 @@ import java.util.List; import java.util.Optional; import java.util.ResourceBundle; import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; @VaultOptionsScoped public class MountOptionsController implements FxController { @@ -87,7 +86,7 @@ public class MountOptionsController implements FxController { FxApplicationWindows applicationWindows, // Lazy application, // List mountProviders, // - @Named("FUPFMS") AtomicReference firstUsedProblematicFuseMountService, // + Mounter mounter, // ObservableValue defaultMountService) { this.window = window; this.vaultSettings = vault.getVaultSettings(); @@ -99,11 +98,7 @@ public class MountOptionsController implements FxController { this.mountProviders = mountProviders; this.defaultMountService = defaultMountService; this.selectedMountService = Bindings.createObjectBinding(this::reselectMountService, defaultMountService, vaultSettings.mountService); - this.fuseRestartRequired = selectedMountService.map(s -> { - return firstUsedProblematicFuseMountService.get() != null // - && Mounter.isProblematicFuseService(s) // - && !firstUsedProblematicFuseMountService.get().equals(s); - }); + this.fuseRestartRequired = selectedMountService.map(mounter::isConflictingMountService); this.defaultMountFlags = selectedMountService.map(s -> { if (s.hasCapability(MountCapability.MOUNT_FLAGS)) {