Use first available mount provider if none is selected or selected is not present

This commit is contained in:
Armin Schrenk 2023-01-11 15:20:05 +01:00
parent 24d472ed8b
commit d07b1b96dd
No known key found for this signature in database
GPG Key ID: 8F2992163CBBA7FC
6 changed files with 56 additions and 24 deletions

View File

@ -0,0 +1,18 @@
package org.cryptomator.common;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import java.util.function.Function;
public class ObservableUtil {
public static <T, U> ObservableValue<U> mapWithDefault(ObservableValue<T> observable, Function<? super T, ? extends U> mapper, U defaultValue) {
return Bindings.createObjectBinding(() -> {
if (observable.getValue() == null) {
return defaultValue;
} else {
return mapper.apply(observable.getValue());
}
}, observable);
}
}

View File

@ -0,0 +1,6 @@
package org.cryptomator.common.mount;
import org.cryptomator.integrations.mount.MountService;
public record ActualMountService(MountService service, boolean isDesired) {
}

View File

@ -2,6 +2,7 @@ package org.cryptomator.common.mount;
import dagger.Module;
import dagger.Provides;
import org.cryptomator.common.ObservableUtil;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.integrations.mount.MountService;
@ -20,11 +21,14 @@ public class MountModule {
@Provides
@Singleton
static ObservableValue<MountService> provideMountService(Settings settings, List<MountService> serviceImpls) {
return settings.mountService().map(desiredServiceImpl -> {
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
return serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(desiredServiceImpl)).findAny().orElse(fallbackProvider);
});
static ObservableValue<ActualMountService> provideMountService(Settings settings, List<MountService> serviceImpls) {
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
return ObservableUtil.mapWithDefault(settings.mountService(), //
desiredServiceImpl -> { //
var desiredService = serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(desiredServiceImpl)).findAny(); //
return new ActualMountService(desiredService.orElse(fallbackProvider), desiredService.isPresent()); //
}, //
new ActualMountService(fallbackProvider, true));
}
}

View File

@ -12,6 +12,8 @@ import com.google.common.base.Strings;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants;
import org.cryptomator.common.Environment;
import org.cryptomator.common.mount.ActualMountService;
import org.cryptomator.common.mount.MountModule;
import org.cryptomator.common.mount.WindowsDriveLetters;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
@ -72,7 +74,7 @@ public class Vault {
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
private final VaultState state;
private final ObjectProperty<Exception> lastKnownException;
private final ObservableValue<MountService> mountService;
private final ObservableValue<ActualMountService> mountService;
private final ObservableValue<String> defaultMountFlags;
private final VaultConfigCache configCache;
private final VaultStats stats;
@ -90,7 +92,7 @@ public class Vault {
private AtomicReference<MountHandle> mountHandle = new AtomicReference<>(null);
@Inject
Vault(Environment env, Settings settings, VaultSettings vaultSettings, VaultConfigCache configCache, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, ObservableValue<MountService> mountService, VaultStats stats, WindowsDriveLetters windowsDriveLetters) {
Vault(Environment env, Settings settings, VaultSettings vaultSettings, VaultConfigCache configCache, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, ObservableValue<ActualMountService> mountService, VaultStats stats, WindowsDriveLetters windowsDriveLetters) {
this.env = env;
this.settings = settings;
this.vaultSettings = vaultSettings;
@ -99,7 +101,7 @@ public class Vault {
this.state = state;
this.lastKnownException = lastKnownException;
this.mountService = mountService;
this.defaultMountFlags = mountService.map(MountService::getDefaultMountFlags);
this.defaultMountFlags = mountService.map(s -> s.service().getDefaultMountFlags());
this.stats = stats;
this.displayablePath = Bindings.createStringBinding(this::getDisplayablePath, vaultSettings.path());
this.locked = Bindings.createBooleanBinding(this::isLocked, state);
@ -159,8 +161,8 @@ public class Vault {
}
}
private MountBuilder prepareMount(Path cryptoRoot) throws IOException {
var mountProvider = mountService.getValue();
private MountBuilder prepareMount(MountService actualMountService, Path cryptoRoot) throws IOException {
var mountProvider = mountService.getValue().service();
var builder = mountProvider.forFileSystem(cryptoRoot);
for (var capability : mountProvider.capabilities()) {
@ -207,8 +209,9 @@ public class Vault {
try {
cryptoFileSystem.set(fs);
var rootPath = fs.getRootDirectories().iterator().next();
var supportsForcedUnmount = mountService.getValue().hasCapability(MountCapability.UNMOUNT_FORCED);
var mountHandle = new MountHandle(prepareMount(rootPath).mount(), supportsForcedUnmount);
var actualMountService = mountService.getValue().service();
var supportsForcedUnmount = actualMountService.hasCapability(MountCapability.UNMOUNT_FORCED);
var mountHandle = new MountHandle(prepareMount(actualMountService, rootPath).mount(), supportsForcedUnmount);
success = this.mountHandle.compareAndSet(null, mountHandle);
} finally {
if (!success) {

View File

@ -1,5 +1,6 @@
package org.cryptomator.ui.preferences;
import org.cryptomator.common.mount.ActualMountService;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.integrations.mount.MountCapability;
import org.cryptomator.integrations.mount.MountService;
@ -22,7 +23,7 @@ import java.util.List;
public class VolumePreferencesController implements FxController {
private final Settings settings;
private final ObservableValue<MountService> selectedMountService;
private final ObservableValue<ActualMountService> selectedMountService;
private final BooleanExpression loopbackPortSupported;
private final List<MountService> mountProviders;
public ChoiceBox<MountService> volumeTypeChoiceBox;
@ -30,17 +31,17 @@ public class VolumePreferencesController implements FxController {
public Button loopbackPortApplyButton;
@Inject
VolumePreferencesController(Settings settings, List<MountService> mountProviders, ObservableValue<MountService> selectedMountService) {
VolumePreferencesController(Settings settings, List<MountService> mountProviders, ObservableValue<ActualMountService> actualMountService) {
this.settings = settings;
this.mountProviders = mountProviders;
this.selectedMountService = selectedMountService;
this.loopbackPortSupported = BooleanExpression.booleanExpression(selectedMountService.map(s -> s.hasCapability(MountCapability.LOOPBACK_PORT)));
this.selectedMountService = actualMountService;
this.loopbackPortSupported = BooleanExpression.booleanExpression(selectedMountService.map(as -> as.service().hasCapability(MountCapability.LOOPBACK_PORT)));
}
public void initialize() {
volumeTypeChoiceBox.getItems().addAll(mountProviders);
volumeTypeChoiceBox.setConverter(new MountServiceConverter());
volumeTypeChoiceBox.getSelectionModel().select(selectedMountService.getValue());
volumeTypeChoiceBox.getSelectionModel().select(selectedMountService.getValue().service());
volumeTypeChoiceBox.valueProperty().addListener((observableValue, oldProvide, newProvider) -> settings.mountService().set(newProvider.getClass().getName()));
loopbackPortField.setText(String.valueOf(settings.port().get()));
@ -81,7 +82,7 @@ public class VolumePreferencesController implements FxController {
@Override
public String toString(MountService provider) {
return provider== null? "None" : provider.displayName(); //TODO: adjust message
return provider== null? "Automatic" : provider.displayName(); //TODO: adjust message
}
@Override

View File

@ -1,10 +1,10 @@
package org.cryptomator.ui.vaultoptions;
import org.cryptomator.common.Environment;
import org.cryptomator.common.mount.ActualMountService;
import org.cryptomator.common.mount.WindowsDriveLetters;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.integrations.mount.MountCapability;
import org.cryptomator.integrations.mount.MountService;
import org.cryptomator.ui.common.FxController;
import javax.inject.Inject;
@ -54,15 +54,15 @@ public class MountOptionsController implements FxController {
public ChoiceBox<Path> driveLetterSelection;
@Inject
MountOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ObservableValue<MountService> mountService, WindowsDriveLetters windowsDriveLetters, ResourceBundle resourceBundle, Environment environment) {
MountOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ObservableValue<ActualMountService> mountService, WindowsDriveLetters windowsDriveLetters, ResourceBundle resourceBundle, Environment environment) {
this.window = window;
this.vault = vault;
this.windowsDriveLetters = windowsDriveLetters;
this.resourceBundle = resourceBundle;
this.mountpointDirSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_TO_EXISTING_DIR) || s.hasCapability(MountCapability.MOUNT_WITHIN_EXISTING_PARENT));
this.mountpointDriveLetterSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_AS_DRIVE_LETTER));
this.mountFlagsSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_FLAGS));
this.readOnlySupported = mountService.map(s -> s.hasCapability(MountCapability.READ_ONLY));
this.mountpointDirSupported = mountService.map(as -> as.service().hasCapability(MountCapability.MOUNT_TO_EXISTING_DIR) || as.service().hasCapability(MountCapability.MOUNT_WITHIN_EXISTING_PARENT));
this.mountpointDriveLetterSupported = mountService.map(as -> as.service().hasCapability(MountCapability.MOUNT_AS_DRIVE_LETTER));
this.mountFlagsSupported = mountService.map(as -> as.service().hasCapability(MountCapability.MOUNT_FLAGS));
this.readOnlySupported = mountService.map(as -> as.service().hasCapability(MountCapability.READ_ONLY));
this.driveLetter = vault.getVaultSettings().mountPoint().map(p -> isDriveLetter(p) ? p : null);
this.directoryPath = vault.getVaultSettings().mountPoint().map(p -> isDriveLetter(p) ? null : p.toString());
}