From 47a32893f028fecb3ec016e64b6d8f46d1d1c0ab Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 13 Jan 2023 13:46:41 +0100 Subject: [PATCH] Refactor mounter class --- .../org/cryptomator/common/mount/Mounter.java | 147 +++++++++++------- .../org/cryptomator/common/vaults/Vault.java | 15 +- 2 files changed, 99 insertions(+), 63 deletions(-) diff --git a/src/main/java/org/cryptomator/common/mount/Mounter.java b/src/main/java/org/cryptomator/common/mount/Mounter.java index 968e889d7..bb6aace42 100644 --- a/src/main/java/org/cryptomator/common/mount/Mounter.java +++ b/src/main/java/org/cryptomator/common/mount/Mounter.java @@ -4,7 +4,9 @@ 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; import org.cryptomator.integrations.mount.MountFailedException; +import org.cryptomator.integrations.mount.MountService; import javax.inject.Inject; import javax.inject.Singleton; @@ -26,83 +28,118 @@ public class Mounter { private final Settings settings; private final Environment env; private final WindowsDriveLetters driveLetters; - private final ObservableValue mountService; + private final ObservableValue mountServiceObservable; @Inject - public Mounter(Settings settings, Environment env, WindowsDriveLetters driveLetters, ObservableValue mountService) { + public Mounter(Settings settings, Environment env, WindowsDriveLetters driveLetters, ObservableValue mountServiceObservable) { this.settings = settings; this.env = env; this.driveLetters = driveLetters; - this.mountService = mountService; + this.mountServiceObservable = mountServiceObservable; } - public MountHandle mountAndcreateHandle(VaultSettings vaultSettings, Path cryptoFsRoot) throws IOException, MountFailedException { - var mountService = this.mountService.getValue().service(); - var builder = mountService.forFileSystem(cryptoFsRoot); - boolean mountWithinParent = false; + private class SettledMounter { - for (var capability : mountService.capabilities()) { - switch (capability) { - case FILE_SYSTEM_NAME -> builder.setFileSystemName("crypto"); - case LOOPBACK_PORT -> builder.setLoopbackPort(settings.port().get()); //TODO: move port from settings to vaultsettings (see https://github.com/cryptomator/cryptomator/tree/feature/mount-setting-per-vault) - case LOOPBACK_HOST_NAME -> env.getLoopbackAlias().ifPresent(builder::setLoopbackHostName); - case READ_ONLY -> builder.setReadOnly(vaultSettings.usesReadOnlyMode().get()); - case MOUNT_FLAGS -> builder.setMountFlags(Objects.requireNonNullElse(vaultSettings.mountFlags().getValue(), mountService.getDefaultMountFlags())); - case VOLUME_ID -> builder.setVolumeId(vaultSettings.getId()); - case VOLUME_NAME -> builder.setVolumeName(vaultSettings.mountName().get()); - } + private MountService service; + private MountBuilder builder; + private VaultSettings vaultSettings; + + public SettledMounter(MountService service, MountBuilder builder, VaultSettings vaultSettings) { + this.service = service; + this.builder = builder; + this.vaultSettings = vaultSettings; } - //TODO: refactor logic to own method - var userChosenMountPoint = vaultSettings.getMountPoint(); - var defaultMountPointBase = env.getMountPointsDir().orElseThrow(); - var canMountToDriveLetter = mountService.hasCapability(MOUNT_AS_DRIVE_LETTER); - var canMountToParent = mountService.hasCapability(MOUNT_WITHIN_EXISTING_PARENT); - var canMountToDir = mountService.hasCapability(MOUNT_TO_EXISTING_DIR); - if (userChosenMountPoint == null) { - if (mountService.hasCapability(MOUNT_TO_SYSTEM_CHOSEN_PATH)) { - // no need to set a mount point - } else if (canMountToDriveLetter) { - builder.setMountpoint(driveLetters.getFirstDesiredAvailable().orElseThrow()); //TODO: catch exception - } else if (canMountToParent) { - Files.createDirectories(defaultMountPointBase); - builder.setMountpoint(defaultMountPointBase); - } else if (canMountToDir) { - var mountPoint = defaultMountPointBase.resolve(vaultSettings.mountName().get()); - Files.createDirectories(mountPoint); - builder.setMountpoint(mountPoint); - } - } else { - mountWithinParent = canMountToParent && !canMountToDir; - if(mountWithinParent) { - // TODO: move the mount point away in case of MOUNT_WITHIN_EXISTING_PARENT - } - try { - builder.setMountpoint(userChosenMountPoint); - } catch (IllegalArgumentException e) { - var mpIsDriveLetter = userChosenMountPoint.toString().matches("[A-Z]:\\\\"); - var configNotSupported = (!canMountToDriveLetter && mpIsDriveLetter) || (!canMountToDir && !mpIsDriveLetter) || (!canMountToParent && !mpIsDriveLetter); - if (configNotSupported) { - throw new MountPointNotSupportedException(e.getMessage()); - } else if (canMountToDir && !canMountToParent && !Files.exists(userChosenMountPoint)) { - //mountpoint must exist - throw new MountPointNotExistsException(e.getMessage()); - } else { - throw new IllegalMountPointException(e.getMessage()); + MadePreparations prepare() throws IOException { + for (var capability : service.capabilities()) { + switch (capability) { + case FILE_SYSTEM_NAME -> builder.setFileSystemName("cryptoFs"); + case LOOPBACK_PORT -> + builder.setLoopbackPort(settings.port().get()); //TODO: move port from settings to vaultsettings (see https://github.com/cryptomator/cryptomator/tree/feature/mount-setting-per-vault) + case LOOPBACK_HOST_NAME -> env.getLoopbackAlias().ifPresent(builder::setLoopbackHostName); + case READ_ONLY -> builder.setReadOnly(vaultSettings.usesReadOnlyMode().get()); + case MOUNT_FLAGS -> builder.setMountFlags(Objects.requireNonNullElse(vaultSettings.mountFlags().getValue(), service.getDefaultMountFlags())); + case VOLUME_ID -> builder.setVolumeId(vaultSettings.getId()); + case VOLUME_NAME -> builder.setVolumeName(vaultSettings.mountName().get()); } + } + + return prepareMountPoint(); + } + + private MadePreparations prepareMountPoint() throws IOException { + var userChosenMountPoint = vaultSettings.getMountPoint(); + var defaultMountPointBase = env.getMountPointsDir().orElseThrow(); + var canMountToDriveLetter = service.hasCapability(MOUNT_AS_DRIVE_LETTER); + var canMountToParent = service.hasCapability(MOUNT_WITHIN_EXISTING_PARENT); + var canMountToDir = service.hasCapability(MOUNT_TO_EXISTING_DIR); + boolean mountWithinCustomParent = false; + + if (userChosenMountPoint == null) { + if (service.hasCapability(MOUNT_TO_SYSTEM_CHOSEN_PATH)) { + // no need to set a mount point + } else if (canMountToDriveLetter) { + builder.setMountpoint(driveLetters.getFirstDesiredAvailable().orElseThrow()); //TODO: catch exception and translate + } else if (canMountToParent) { + Files.createDirectories(defaultMountPointBase); + builder.setMountpoint(defaultMountPointBase); + } else if (canMountToDir) { + var mountPoint = defaultMountPointBase.resolve(vaultSettings.mountName().get()); + Files.createDirectories(mountPoint); + builder.setMountpoint(mountPoint); + } + } else { + mountWithinCustomParent = canMountToParent && !canMountToDir; + if (mountWithinCustomParent) { + // TODO: move the mount point away in case of MOUNT_WITHIN_EXISTING_PARENT + } + try { + builder.setMountpoint(userChosenMountPoint); + } catch (IllegalArgumentException e) { + var mpIsDriveLetter = userChosenMountPoint.toString().matches("[A-Z]:\\\\"); + var configNotSupported = (!canMountToDriveLetter && mpIsDriveLetter) || (!canMountToDir && !mpIsDriveLetter) || (!canMountToParent && !mpIsDriveLetter); + if (configNotSupported) { + throw new MountPointNotSupportedException(e.getMessage()); + } else if (canMountToDir && !canMountToParent && !Files.exists(userChosenMountPoint)) { + //mountpoint must exist + throw new MountPointNotExistsException(e.getMessage()); + } else { + throw new IllegalMountPointException(e.getMessage()); + } /* //TODO: if (!canMountToDir && canMountToParent && !Files.notExists(userChosenMountPoint)) { //parent must exist, mountpoint must not exist } */ + } } + return new MadePreparations(mountWithinCustomParent); } - return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), mountWithinParent); } - public record MountHandle(Mount mount, boolean supportsUnmountForced, boolean mountWithinParent) { + public MountHandle mount(VaultSettings vaultSettings, Path cryptoFsRoot) throws IOException, MountFailedException { + var mountService = this.mountServiceObservable.getValue().service(); + var builder = mountService.forFileSystem(cryptoFsRoot); + var internal = new SettledMounter(mountService, builder, vaultSettings); + var preps = internal.prepare(); + return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), preps.mountWithinCustomParent); + } + + public void cleanup(MountHandle handle) { + if(handle.mountWithinCustomParent) { + //TODO + } + } + + + public record MountHandle(Mount mountObj, boolean supportsUnmountForced, boolean mountWithinCustomParent) { } + + private record MadePreparations(boolean mountWithinCustomParent) { + + } + } diff --git a/src/main/java/org/cryptomator/common/vaults/Vault.java b/src/main/java/org/cryptomator/common/vaults/Vault.java index 19e2efb68..b17372f16 100644 --- a/src/main/java/org/cryptomator/common/vaults/Vault.java +++ b/src/main/java/org/cryptomator/common/vaults/Vault.java @@ -8,7 +8,6 @@ *******************************************************************************/ package org.cryptomator.common.vaults; -import com.google.common.base.Strings; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.Constants; import org.cryptomator.common.mount.Mounter; @@ -150,7 +149,7 @@ public class Vault { try { cryptoFileSystem.set(fs); var rootPath = fs.getRootDirectories().iterator().next(); - var mountHandle = mounter.mountAndcreateHandle(vaultSettings, rootPath); + var mountHandle = mounter.mount(vaultSettings, rootPath); success = this.mountHandle.compareAndSet(null, mountHandle); } finally { if (!success) { @@ -167,15 +166,15 @@ public class Vault { } if (forced && mountHandle.supportsUnmountForced()) { - mountHandle.mount().unmountForced(); + mountHandle.mountObj().unmountForced(); } else { - mountHandle.mount().unmount(); + mountHandle.mountObj().unmount(); } try { - mountHandle.mount().close(); - if(mountHandle.mountWithinParent()) { - //TODO: cleanup + mountHandle.mountObj().close(); + if(mountHandle.mountWithinCustomParent()) { + mounter.cleanup(mountHandle); } } finally { destroyCryptoFileSystem(); @@ -271,7 +270,7 @@ public class Vault { public Mountpoint getMountPoint() { var handle = mountHandle.get(); - return handle == null ? null : handle.mount().getMountpoint(); + return handle == null ? null : handle.mountObj().getMountpoint(); } public StringBinding displayablePathProperty() {