mirror of
https://github.com/cryptomator/cryptomator.git
synced 2024-11-27 05:50:26 +00:00
refactoring
This commit is contained in:
parent
6a704ca0ad
commit
98590ecec5
@ -1,6 +0,0 @@
|
||||
package org.cryptomator.common.mount;
|
||||
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
|
||||
public record ActualMountService(MountService service, boolean isDesired) {
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package org.cryptomator.common.mount;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.integrations.mount.Mount;
|
||||
import org.cryptomator.integrations.mount.MountBuilder;
|
||||
@ -8,11 +9,13 @@ import org.cryptomator.integrations.mount.MountFailedException;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
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 static org.cryptomator.integrations.mount.MountCapability.MOUNT_AS_DRIVE_LETTER;
|
||||
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_EXISTING_DIR;
|
||||
@ -23,13 +26,24 @@ import static org.cryptomator.integrations.mount.MountCapability.UNMOUNT_FORCED;
|
||||
@Singleton
|
||||
public class Mounter {
|
||||
|
||||
private static final List<String> problematicFuseMountServices = List.of("org.cryptomator.frontend.fuse.mount.MacFuseMountProvider", "org.cryptomator.frontend.fuse.mount.FuseTMountProvider");
|
||||
|
||||
private final Environment env;
|
||||
private final WindowsDriveLetters driveLetters;
|
||||
private final Settings settings;
|
||||
private final List<MountService> mountProviders;
|
||||
private final AtomicReference<MountService> firstUsedProblematicFuseMountService;
|
||||
|
||||
@Inject
|
||||
public Mounter(Environment env, WindowsDriveLetters driveLetters) {
|
||||
public Mounter(Environment env, //
|
||||
WindowsDriveLetters driveLetters, //
|
||||
Settings settings, List<MountService> mountProviders, //
|
||||
@Named("FUPFMS") AtomicReference<MountService> firstUsedProblematicFuseMountService) {
|
||||
this.env = env;
|
||||
this.driveLetters = driveLetters;
|
||||
this.settings = settings;
|
||||
this.mountProviders = mountProviders;
|
||||
this.firstUsedProblematicFuseMountService = firstUsedProblematicFuseMountService;
|
||||
}
|
||||
|
||||
private class SettledMounter {
|
||||
@ -124,12 +138,32 @@ public class Mounter {
|
||||
|
||||
}
|
||||
|
||||
public MountHandle mount(VaultSettings vaultSettings, Path cryptoFsRoot, ObservableValue<ActualMountService> actualMountService) throws IOException, MountFailedException {
|
||||
var mountService = actualMountService.getValue().service();
|
||||
var builder = mountService.forFileSystem(cryptoFsRoot);
|
||||
var internal = new SettledMounter(mountService, builder, vaultSettings);
|
||||
public MountHandle mount(VaultSettings vaultSettings, Path cryptoFsRoot) throws IOException, MountFailedException {
|
||||
var fallbackProvider = mountProviders.stream().findFirst().orElse(null);
|
||||
var defMntServ = mountProviders.stream().filter(s -> s.getClass().getName().equals(settings.mountService.getValue())).findFirst().orElse(fallbackProvider);
|
||||
var selMntServ = mountProviders.stream().filter(s -> s.getClass().getName().equals(vaultSettings.mountService.getValue())).findFirst().orElse(defMntServ);
|
||||
|
||||
var targetIsProblematicFuse = isProblematicFuseService(selMntServ);
|
||||
if (targetIsProblematicFuse && firstUsedProblematicFuseMountService.get() == null) {
|
||||
firstUsedProblematicFuseMountService.set(selMntServ);
|
||||
}
|
||||
|
||||
var fuseRestartRequired = firstUsedProblematicFuseMountService.get() != null //
|
||||
&& isProblematicFuseService(selMntServ) //
|
||||
&& !firstUsedProblematicFuseMountService.get().equals(selMntServ);
|
||||
|
||||
if (fuseRestartRequired) {
|
||||
throw new FuseRestartRequiredException("fuseRestartRequired");
|
||||
}
|
||||
|
||||
var builder = selMntServ.forFileSystem(cryptoFsRoot);
|
||||
var internal = new SettledMounter(selMntServ, builder, vaultSettings);
|
||||
var cleanup = internal.prepare();
|
||||
return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), cleanup);
|
||||
return new MountHandle(builder.mount(), selMntServ.hasCapability(UNMOUNT_FORCED), cleanup);
|
||||
}
|
||||
|
||||
public static boolean isProblematicFuseService(MountService service) {
|
||||
return problematicFuseMountServices.contains(service.getClass().getName());
|
||||
}
|
||||
|
||||
public record MountHandle(Mount mountObj, boolean supportsUnmountForced, Runnable specialCleanup) {
|
||||
|
@ -10,10 +10,7 @@ package org.cryptomator.common.vaults;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Constants;
|
||||
import org.cryptomator.common.mount.ActualMountService;
|
||||
import org.cryptomator.common.mount.FuseRestartRequiredException;
|
||||
import org.cryptomator.common.mount.Mounter;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystem;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
|
||||
@ -24,7 +21,6 @@ import org.cryptomator.cryptolib.api.CryptoException;
|
||||
import org.cryptomator.cryptolib.api.MasterkeyLoader;
|
||||
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
|
||||
import org.cryptomator.integrations.mount.MountFailedException;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
import org.cryptomator.integrations.mount.Mountpoint;
|
||||
import org.cryptomator.integrations.mount.UnmountFailedException;
|
||||
import org.slf4j.Logger;
|
||||
@ -41,12 +37,10 @@ import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@ -58,9 +52,7 @@ public class Vault {
|
||||
private static final Path HOME_DIR = Paths.get(SystemUtils.USER_HOME);
|
||||
private static final int UNLIMITED_FILENAME_LENGTH = Integer.MAX_VALUE;
|
||||
|
||||
private final Settings settings;
|
||||
private final VaultSettings vaultSettings;
|
||||
private final List<MountService> mountProviders;
|
||||
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
|
||||
private final VaultState state;
|
||||
private final ObjectProperty<Exception> lastKnownException;
|
||||
@ -76,28 +68,20 @@ public class Vault {
|
||||
private final ObjectBinding<Mountpoint> mountPoint;
|
||||
private final Mounter mounter;
|
||||
private final BooleanProperty showingStats;
|
||||
private final ObservableValue<ActualMountService> actualMountService;
|
||||
private final AtomicReference<MountService> firstUsedProblematicFuseMountService;
|
||||
|
||||
private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
|
||||
|
||||
@Inject
|
||||
Vault(Settings settings, //
|
||||
VaultSettings vaultSettings, //
|
||||
Vault(VaultSettings vaultSettings, //
|
||||
VaultConfigCache configCache, //
|
||||
AtomicReference<CryptoFileSystem> cryptoFileSystem, //
|
||||
List<MountService> mountProviders, //
|
||||
VaultState state, //
|
||||
@Named("lastKnownException") ObjectProperty<Exception> lastKnownException, //
|
||||
VaultStats stats, //
|
||||
Mounter mounter, //
|
||||
@Named("vaultMountService") ObservableValue<ActualMountService> actualMountService, //
|
||||
@Named("FUPFMS") AtomicReference<MountService> firstUsedProblematicFuseMountService) {
|
||||
this.settings = settings;
|
||||
Mounter mounter) {
|
||||
this.vaultSettings = vaultSettings;
|
||||
this.configCache = configCache;
|
||||
this.cryptoFileSystem = cryptoFileSystem;
|
||||
this.mountProviders = mountProviders;
|
||||
this.state = state;
|
||||
this.lastKnownException = lastKnownException;
|
||||
this.stats = stats;
|
||||
@ -111,8 +95,6 @@ public class Vault {
|
||||
this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
|
||||
this.mounter = mounter;
|
||||
this.showingStats = new SimpleBooleanProperty(false);
|
||||
this.actualMountService = actualMountService;
|
||||
this.firstUsedProblematicFuseMountService = firstUsedProblematicFuseMountService;
|
||||
}
|
||||
|
||||
// ******************************************************************************
|
||||
@ -165,22 +147,13 @@ public class Vault {
|
||||
if (cryptoFileSystem.get() != null) {
|
||||
throw new IllegalStateException("Already unlocked.");
|
||||
}
|
||||
var fallbackProvider = mountProviders.stream().findFirst().orElse(null);
|
||||
var defMntServ = mountProviders.stream().filter(s -> s.getClass().getName().equals(settings.mountService.getValue())).findFirst().orElse(fallbackProvider);
|
||||
var selMntServ = mountProviders.stream().filter(s -> s.getClass().getName().equals(vaultSettings.mountService.getValue())).findFirst().orElse(defMntServ);
|
||||
var fuseRestartRequired = firstUsedProblematicFuseMountService.get() != null //
|
||||
&& VaultModule.isProblematicFuseService(selMntServ) //
|
||||
&& !firstUsedProblematicFuseMountService.get().equals(selMntServ);
|
||||
if (fuseRestartRequired) {
|
||||
throw new FuseRestartRequiredException("fuseRestartRequired");
|
||||
}
|
||||
|
||||
CryptoFileSystem fs = createCryptoFileSystem(keyLoader);
|
||||
boolean success = false;
|
||||
try {
|
||||
cryptoFileSystem.set(fs);
|
||||
var rootPath = fs.getRootDirectories().iterator().next();
|
||||
var mountHandle = mounter.mount(vaultSettings, rootPath, actualMountService);
|
||||
var mountHandle = mounter.mount(vaultSettings, rootPath);
|
||||
success = this.mountHandle.compareAndSet(null, mountHandle);
|
||||
} finally {
|
||||
if (!success) {
|
||||
|
@ -37,19 +37,19 @@ public class VaultListManager {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class);
|
||||
|
||||
private final AutoLocker autoLocker;
|
||||
private final VaultComponent.Factory vaultComponentFactory;
|
||||
private final ObservableList<Vault> vaultList;
|
||||
private final String defaultVaultName;
|
||||
private final Settings settings;
|
||||
|
||||
|
||||
@Inject
|
||||
public VaultListManager(ObservableList<Vault> vaultList, AutoLocker autoLocker, VaultComponent.Factory vaultComponentFactory, ResourceBundle resourceBundle, Settings settings) {
|
||||
public VaultListManager(ObservableList<Vault> vaultList, //
|
||||
AutoLocker autoLocker, //
|
||||
VaultComponent.Factory vaultComponentFactory, //
|
||||
ResourceBundle resourceBundle, Settings settings) {
|
||||
this.vaultList = vaultList;
|
||||
this.autoLocker = autoLocker;
|
||||
this.vaultComponentFactory = vaultComponentFactory;
|
||||
this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName");
|
||||
this.settings = settings;
|
||||
|
||||
addAll(settings.directories);
|
||||
vaultList.addListener(new VaultListChangeListener(settings.directories));
|
||||
|
@ -8,72 +8,22 @@ package org.cryptomator.common.vaults;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.cryptomator.common.Nullable;
|
||||
import org.cryptomator.common.ObservableUtil;
|
||||
import org.cryptomator.common.mount.ActualMountService;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.cryptofs.CryptoFileSystem;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@Module
|
||||
public class VaultModule {
|
||||
|
||||
private static final AtomicReference<MountService> formerSelectedMountService = new AtomicReference<>(null);
|
||||
private static final List<String> problematicFuseMountServices = List.of("org.cryptomator.frontend.fuse.mount.MacFuseMountProvider", "org.cryptomator.frontend.fuse.mount.FuseTMountProvider");
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VaultModule.class);
|
||||
|
||||
@Provides
|
||||
@PerVault
|
||||
public AtomicReference<CryptoFileSystem> provideCryptoFileSystemReference() {
|
||||
return new AtomicReference<>();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("vaultMountService")
|
||||
@PerVault
|
||||
static ObservableValue<ActualMountService> provideMountService(Settings settings, VaultSettings vaultSettings, List<MountService> serviceImpls, @Named("FUPFMS") AtomicReference<MountService> fupfms) {
|
||||
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
|
||||
var defaultMountService = ObservableUtil.mapWithDefault(settings.mountService, serviceName -> serviceImpls.stream().filter(s -> s.getClass().getName().equals(serviceName)).findFirst().orElse(fallbackProvider), fallbackProvider);
|
||||
return ObservableUtil.mapWithDefault(vaultSettings.mountService, //
|
||||
desiredServiceImpl -> { //
|
||||
var serviceFromSettings = serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(desiredServiceImpl)).findAny(); //
|
||||
var targetedService = serviceFromSettings.orElse(defaultMountService.getValue());
|
||||
return applyWorkaroundForProblematicFuse(targetedService, serviceFromSettings.isPresent(), fupfms);
|
||||
}, //
|
||||
() -> applyWorkaroundForProblematicFuse(defaultMountService.getValue(), true, fupfms)
|
||||
);
|
||||
}
|
||||
|
||||
//see https://github.com/cryptomator/cryptomator/issues/2786
|
||||
private synchronized static ActualMountService applyWorkaroundForProblematicFuse(MountService targetedService, boolean isDesired, AtomicReference<MountService> firstUsedProblematicFuseMountService) {
|
||||
//set the first used problematic fuse service if applicable
|
||||
var targetIsProblematicFuse = isProblematicFuseService(targetedService);
|
||||
if (targetIsProblematicFuse && firstUsedProblematicFuseMountService.get() == null) {
|
||||
firstUsedProblematicFuseMountService.set(targetedService);
|
||||
}
|
||||
|
||||
//do not use the targeted mount service and fallback to former one, if the service is problematic _and_ not the first problematic one used.
|
||||
if (targetIsProblematicFuse && !firstUsedProblematicFuseMountService.get().equals(targetedService)) {
|
||||
return new ActualMountService(formerSelectedMountService.get(), false);
|
||||
} else {
|
||||
formerSelectedMountService.set(targetedService);
|
||||
return new ActualMountService(targetedService, isDesired);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isProblematicFuseService(MountService service) {
|
||||
return problematicFuseMountServices.contains(service.getClass().getName());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("lastKnownException")
|
||||
@PerVault
|
||||
|
@ -3,11 +3,11 @@ package org.cryptomator.ui.vaultoptions;
|
||||
import com.google.common.base.Strings;
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.ObservableUtil;
|
||||
import org.cryptomator.common.mount.Mounter;
|
||||
import org.cryptomator.common.mount.WindowsDriveLetters;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultModule;
|
||||
import org.cryptomator.integrations.mount.MountCapability;
|
||||
import org.cryptomator.integrations.mount.MountService;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
@ -102,11 +102,10 @@ public class MountOptionsController implements FxController {
|
||||
fallbackProvider);
|
||||
this.selectedMountService = Bindings.createObjectBinding(this::reselectMountService, defaultMountService, vaultSettings.mountService);
|
||||
this.fuseRestartRequired = selectedMountService.map(s -> {
|
||||
return firstUsedProblematicFuseMountService.get() != null //
|
||||
&& VaultModule.isProblematicFuseService(s) //
|
||||
&& !firstUsedProblematicFuseMountService.get().equals(s);
|
||||
}
|
||||
);
|
||||
return firstUsedProblematicFuseMountService.get() != null //
|
||||
&& Mounter.isProblematicFuseService(s) //
|
||||
&& !firstUsedProblematicFuseMountService.get().equals(s);
|
||||
});
|
||||
this.loopbackPortSupported = BooleanExpression.booleanExpression(selectedMountService.map(s -> s.hasCapability(MountCapability.LOOPBACK_PORT)));
|
||||
|
||||
this.defaultMountFlags = selectedMountService.map(s -> {
|
||||
@ -130,7 +129,7 @@ public class MountOptionsController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
defaultMountService.addListener((_,_,_) -> vaultVolumeTypeChoiceBox.setConverter(new MountServiceConverter()));
|
||||
defaultMountService.addListener((_, _, _) -> vaultVolumeTypeChoiceBox.setConverter(new MountServiceConverter()));
|
||||
|
||||
// readonly:
|
||||
readOnlyCheckbox.selectedProperty().bindBidirectional(vaultSettings.usesReadOnlyMode);
|
||||
|
Loading…
Reference in New Issue
Block a user