mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-19 03:01:27 +00:00
Refactor mounter class
This commit is contained in:
@@ -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<ActualMountService> mountService;
|
||||
private final ObservableValue<ActualMountService> mountServiceObservable;
|
||||
|
||||
@Inject
|
||||
public Mounter(Settings settings, Environment env, WindowsDriveLetters driveLetters, ObservableValue<ActualMountService> mountService) {
|
||||
public Mounter(Settings settings, Environment env, WindowsDriveLetters driveLetters, ObservableValue<ActualMountService> 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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user