Added implementations for MountPointChooser

Added AvailableDriveLetterChooser for automatic DriveLetter-choice
Added CustomDriveLetterChooser for a chosen DriveLetter
Added CustomMountPointChooser for a chosen directory
Added TemporaryMountPointChooser for automatic directory-choice
This commit is contained in:
JaniruTEC
2020-08-11 22:39:54 +02:00
parent b51a2602a9
commit d6bbc4383b
4 changed files with 202 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
package org.cryptomator.common.mountpoint;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.WindowsDriveLetters;
import java.nio.file.Path;
import java.util.Optional;
public class AvailableDriveLetterChooser implements MountPointChooser {
private final WindowsDriveLetters windowsDriveLetters;
public AvailableDriveLetterChooser(WindowsDriveLetters windowsDriveLetters) {
this.windowsDriveLetters = windowsDriveLetters;
}
@Override
public boolean isApplicable() {
return SystemUtils.IS_OS_WINDOWS;
}
@Override
public Optional<Path> chooseMountPoint() {
return this.windowsDriveLetters.getAvailableDriveLetterPath();
}
}

View File

@@ -0,0 +1,28 @@
package org.cryptomator.common.mountpoint;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.vaults.Vault;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
public class CustomDriveLetterChooser implements MountPointChooser {
private final VaultSettings vaultSettings;
public CustomDriveLetterChooser(Vault vault) {
this.vaultSettings = vault.getVaultSettings();
}
@Override
public boolean isApplicable() {
return SystemUtils.IS_OS_WINDOWS;
}
@Override
public Optional<Path> chooseMountPoint() {
return this.vaultSettings.getWinDriveLetter().map(letter -> letter.charAt(0) + ":\\").map(Paths::get);
}
}

View File

@@ -0,0 +1,69 @@
package org.cryptomator.common.mountpoint;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.vaults.Vault;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
public class CustomMountPointChooser implements MountPointChooser {
private static final Logger LOG = LoggerFactory.getLogger(CustomMountPointChooser.class);
private final VaultSettings vaultSettings;
public CustomMountPointChooser(Vault vault) {
this.vaultSettings = vault.getVaultSettings();
}
@Override
public Optional<Path> chooseMountPoint() {
//VaultSettings#getCustomMountPath already checks whether the saved custom mountpoint should be used
return this.vaultSettings.getCustomMountPath().map(Paths::get);
}
@Override
public boolean prepare(Path mountPoint) throws InvalidMountPointException {
//On Windows the target folder MUST NOT exist...
//https://github.com/billziss-gh/winfsp/issues/320
if (SystemUtils.IS_OS_WINDOWS) {
//We must use #notExists() here because notExists =/= !exists (see docs)
if (Files.notExists(mountPoint, LinkOption.NOFOLLOW_LINKS)) {
//File really doesn't exist
return false;
}
//File exists OR can't be determined
throw wrapAsIMPE(new FileAlreadyExistsException(mountPoint.toString()));
}
//... on Mac and Linux it's the opposite
if (!Files.isDirectory(mountPoint)) {
throw wrapAsIMPE(new NotDirectoryException(mountPoint.toString()));
}
try (DirectoryStream<Path> ds = Files.newDirectoryStream(mountPoint)) {
if (ds.iterator().hasNext()) {
throw wrapAsIMPE(new DirectoryNotEmptyException(mountPoint.toString()));
}
} catch (IOException exception) {
throw wrapAsIMPE(exception);
}
LOG.debug("Successfully checked custom mount point: {}", mountPoint);
return false;
}
private InvalidMountPointException wrapAsIMPE(Exception exception) {
return new InvalidMountPointException(exception);
}
}

View File

@@ -0,0 +1,79 @@
package org.cryptomator.common.mountpoint;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Environment;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.vaults.Vault;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
public class TemporaryMountPointChooser implements MountPointChooser {
private static final Logger LOG = LoggerFactory.getLogger(TemporaryMountPointChooser.class);
private static final int MAX_TMPMOUNTPOINT_CREATION_RETRIES = 10;
private final VaultSettings vaultSettings;
private final Environment environment;
public TemporaryMountPointChooser(Vault vault, Environment environment) {
this.vaultSettings = vault.getVaultSettings();
this.environment = environment;
}
@Override
public boolean isApplicable() {
if(this.environment.getMountPointsDir().isEmpty()) {
LOG.warn("\"cryptomator.mountPointsDir\" is not set to a valid path!");
return false;
}
return true;
}
@Override
public Optional<Path> chooseMountPoint() {
//Shouldn't throw, but let's keep #orElseThrow in case we made a mistake and the check in #isApplicable failed
Path parent = this.environment.getMountPointsDir().orElseThrow();
String basename = this.vaultSettings.getId();
for (int i = 0; i < MAX_TMPMOUNTPOINT_CREATION_RETRIES; i++) {
Path mountPoint = parent.resolve(basename + "_" + i);
if (Files.notExists(mountPoint)) {
return Optional.of(mountPoint);
}
}
return Optional.empty();
}
@Override
public boolean prepare(Path mountPoint) throws InvalidMountPointException {
// https://github.com/osxfuse/osxfuse/issues/306#issuecomment-245114592:
// In order to allow non-admin users to mount FUSE volumes in `/Volumes`,
// starting with version 3.5.0, FUSE will create non-existent mount points automatically.
if (SystemUtils.IS_OS_MAC && mountPoint.getParent().equals(Paths.get("/Volumes"))) {
return false;
}
try {
//WinFSP needs the parent, but the actual Mountpoint must not exist...
if (SystemUtils.IS_OS_WINDOWS) {
Files.createDirectories(mountPoint.getParent());
return false;
} else {
//For Linux and Mac the actual Mountpoint must exist
Files.createDirectories(mountPoint);
return true;
}
} catch (IOException exception) {
throw wrapAsIMPE(exception);
}
}
private InvalidMountPointException wrapAsIMPE(Exception exception) {
return new InvalidMountPointException(exception);
}
}