diff --git a/main/commons/pom.xml b/main/commons/pom.xml index 5d7b53e9f..5603f36b5 100644 --- a/main/commons/pom.xml +++ b/main/commons/pom.xml @@ -17,11 +17,28 @@ Shared utilities + com.google.guava guava - + + org.apache.commons + commons-lang3 + + + + + com.google.dagger + dagger + + + com.google.dagger + dagger-compiler + provided + + + junit junit diff --git a/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java b/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java new file mode 100644 index 000000000..d56d22f80 --- /dev/null +++ b/main/commons/src/main/java/org/cryptomator/common/CommonsModule.java @@ -0,0 +1,21 @@ +package org.cryptomator.common; + +import java.util.Comparator; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class CommonsModule { + + @Provides + @Singleton + @Named("SemVer") + Comparator providesSemVerComparator() { + return new SemVerComparator(); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/SemVerComparator.java b/main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java similarity index 97% rename from main/ui/src/main/java/org/cryptomator/ui/util/SemVerComparator.java rename to main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java index b9031b471..930e2e93d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/SemVerComparator.java +++ b/main/commons/src/main/java/org/cryptomator/common/SemVerComparator.java @@ -6,7 +6,7 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.ui.util; +package org.cryptomator.common; import java.util.Comparator; diff --git a/main/ui/src/test/java/org/cryptomator/ui/util/SemVerComparatorTest.java b/main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java similarity index 95% rename from main/ui/src/test/java/org/cryptomator/ui/util/SemVerComparatorTest.java rename to main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java index a505d0af4..859eb9471 100644 --- a/main/ui/src/test/java/org/cryptomator/ui/util/SemVerComparatorTest.java +++ b/main/commons/src/test/java/org/cryptomator/common/SemVerComparatorTest.java @@ -6,10 +6,11 @@ * Contributors: * Sebastian Stenzel - initial API and implementation *******************************************************************************/ -package org.cryptomator.ui.util; +package org.cryptomator.common; import java.util.Comparator; +import org.cryptomator.common.SemVerComparator; import org.junit.Assert; import org.junit.Test; diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java index 9f6c5dbff..68f1a43e7 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java @@ -10,10 +10,12 @@ package org.cryptomator.frontend.webdav; import javax.inject.Singleton; +import org.cryptomator.common.CommonsModule; + import dagger.Component; @Singleton -@Component +@Component(modules = {CommonsModule.class}) public interface WebDavComponent { WebDavServer server(); diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXAppleScriptWebDavMounter.java similarity index 91% rename from main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java rename to main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXAppleScriptWebDavMounter.java index 0acf2ddee..f381e2e6f 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXAppleScriptWebDavMounter.java @@ -12,11 +12,13 @@ package org.cryptomator.frontend.webdav.mount; import java.io.IOException; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.util.Comparator; import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import org.apache.commons.io.IOUtils; @@ -26,15 +28,18 @@ import org.cryptomator.frontend.CommandFailedException; import org.cryptomator.frontend.Frontend.MountParam; @Singleton -final class MacOsXWebDavMounter implements WebDavMounterStrategy { +final class MacOsXAppleScriptWebDavMounter implements WebDavMounterStrategy { + + private final Comparator semVerComparator; @Inject - MacOsXWebDavMounter() { + MacOsXAppleScriptWebDavMounter(@Named("SemVer") Comparator semVerComparator) { + this.semVerComparator = semVerComparator; } @Override public boolean shouldWork() { - return SystemUtils.IS_OS_MAC_OSX; + return SystemUtils.IS_OS_MAC_OSX && semVerComparator.compare(SystemUtils.OS_VERSION, "10.10") >= 0; } @Override diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java new file mode 100644 index 000000000..89e8a86a2 --- /dev/null +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2014, 2016 Sebastian Stenzel, Markus Kreusch + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Sebastian Stenzel - initial API and implementation, strategy fine tuning + * Markus Kreusch - Refactored WebDavMounter to use strategy pattern + ******************************************************************************/ +package org.cryptomator.frontend.webdav.mount; + +import java.net.URI; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.util.Comparator; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.commons.lang3.SystemUtils; +import org.cryptomator.frontend.CommandFailedException; +import org.cryptomator.frontend.Frontend.MountParam; +import org.cryptomator.frontend.webdav.mount.command.Script; + +@Singleton +final class MacOsXShellScriptWebDavMounter implements WebDavMounterStrategy { + + private final Comparator semVerComparator; + + @Inject + MacOsXShellScriptWebDavMounter(@Named("SemVer") Comparator semVerComparator) { + this.semVerComparator = semVerComparator; + } + + @Override + public boolean shouldWork() { + return SystemUtils.IS_OS_MAC_OSX && semVerComparator.compare(SystemUtils.OS_VERSION, "10.10") < 0; + } + + @Override + public void warmUp(int serverPort) { + // no-op + } + + @Override + public WebDavMount mount(URI uri, Map> mountParams) throws CommandFailedException { + final String mountName = mountParams.getOrDefault(MountParam.MOUNT_NAME, Optional.empty()).orElseThrow(() -> { + return new IllegalArgumentException("Missing mount parameter MOUNT_NAME."); + }); + + // we don't use the uri to derive a path, as it *could* be longer than 255 chars. + final String path = "/Volumes/Cryptomator_" + UUID.randomUUID().toString(); + final Script mountScript = Script.fromLines("mkdir \"$MOUNT_PATH\"", "mount_webdav -S -v $MOUNT_NAME \"$DAV_AUTHORITY$DAV_PATH\" \"$MOUNT_PATH\"").addEnv("DAV_AUTHORITY", uri.getRawAuthority()) + .addEnv("DAV_PATH", uri.getRawPath()).addEnv("MOUNT_PATH", path).addEnv("MOUNT_NAME", mountName); + mountScript.execute(); + return new MacWebDavMount(path); + } + + private static class MacWebDavMount extends AbstractWebDavMount { + private final String mountPath; + private final Script revealScript; + private final Script unmountScript; + + private MacWebDavMount(String mountPath) { + this.mountPath = mountPath; + this.revealScript = Script.fromLines("open \"$MOUNT_PATH\"").addEnv("MOUNT_PATH", mountPath); + this.unmountScript = Script.fromLines("diskutil umount $MOUNT_PATH").addEnv("MOUNT_PATH", mountPath); + } + + @Override + public void unmount() throws CommandFailedException { + // only attempt unmount if user didn't unmount manually: + if (Files.exists(FileSystems.getDefault().getPath(mountPath))) { + unmountScript.execute(); + } + } + + @Override + public void reveal() throws CommandFailedException { + revealScript.execute(); + } + + } + +} diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java index edb5645fa..3cd1b2a08 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java @@ -19,74 +19,87 @@ import javax.inject.Singleton; @Singleton class MountStrategies implements Collection { - + private final Collection delegate; - + @Inject - MountStrategies(LinuxGvfsWebDavMounter linuxMounter, MacOsXWebDavMounter osxMounter, WindowsWebDavMounter winMounter) { - delegate = unmodifiableList(asList(linuxMounter, osxMounter, winMounter)); + MountStrategies(LinuxGvfsWebDavMounter linuxMounter, MacOsXAppleScriptWebDavMounter osxAppleScriptMounter, MacOsXShellScriptWebDavMounter osxShellScriptMounter, WindowsWebDavMounter winMounter) { + delegate = unmodifiableList(asList(linuxMounter, osxAppleScriptMounter, osxShellScriptMounter, winMounter)); } + @Override public int size() { return delegate.size(); } + @Override public boolean isEmpty() { return delegate.isEmpty(); } + @Override public boolean contains(Object o) { return delegate.contains(o); } + @Override public Iterator iterator() { return delegate.iterator(); } + @Override public Object[] toArray() { return delegate.toArray(); } + @Override public T[] toArray(T[] a) { return delegate.toArray(a); } + @Override public boolean add(WebDavMounterStrategy e) { return delegate.add(e); } + @Override public boolean remove(Object o) { return delegate.remove(o); } + @Override public boolean containsAll(Collection c) { return delegate.containsAll(c); } + @Override public boolean addAll(Collection c) { return delegate.addAll(c); } + @Override public boolean removeAll(Collection c) { return delegate.removeAll(c); } + @Override public boolean retainAll(Collection c) { return delegate.retainAll(c); } + @Override public void clear() { delegate.clear(); } + @Override public boolean equals(Object o) { return delegate.equals(o); } + @Override public int hashCode() { return delegate.hashCode(); } - - } diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java index a2a257a61..4136fd2bf 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java @@ -60,12 +60,12 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { @Override public WebDavMount mount(URI uri, Map> mountParams) throws CommandFailedException { - final String driveLetter = mountParams.getOrDefault(MountParam.WIN_DRIVE_LETTER, Optional.of(AUTO_ASSIGN_DRIVE_LETTER)).orElse(AUTO_ASSIGN_DRIVE_LETTER); + final String driveLetter = mountParams.getOrDefault(MountParam.WIN_DRIVE_LETTER, Optional.empty()).orElse(AUTO_ASSIGN_DRIVE_LETTER); if (driveLetters.getOccupiedDriveLetters().contains(CharUtils.toChar(driveLetter))) { throw new CommandFailedException("Drive letter occupied."); } - - final String hostname = mountParams.getOrDefault(MountParam.HOSTNAME, Optional.of(LOCALHOST)).orElse(LOCALHOST); + + final String hostname = mountParams.getOrDefault(MountParam.HOSTNAME, Optional.empty()).orElse(LOCALHOST); try { final URI adjustedUri = new URI(uri.getScheme(), uri.getUserInfo(), hostname, uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); CommandResult mountResult = mount(adjustedUri, driveLetter); @@ -74,14 +74,13 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy { throw new IllegalArgumentException("Invalid host: " + hostname); } } - + private CommandResult mount(URI uri, String driveLetter) throws CommandFailedException { - final Script proxyBypassScript = fromLines( - "reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v \"ProxyOverride\" /d \";%DAV_HOST%;%DAV_HOST%:%DAV_PORT%\" /f"); + final Script proxyBypassScript = fromLines("reg add \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\" /v \"ProxyOverride\" /d \";%DAV_HOST%;%DAV_HOST%:%DAV_PORT%\" /f"); proxyBypassScript.addEnv("DAV_HOST", uri.getHost()); proxyBypassScript.addEnv("DAV_PORT", String.valueOf(uri.getPort())); proxyBypassScript.execute(); - + final String driveLetterStr = AUTO_ASSIGN_DRIVE_LETTER.equals(driveLetter) ? AUTO_ASSIGN_DRIVE_LETTER : driveLetter + ":"; final Script mountScript = fromLines("net use %DRIVE_LETTER% \\\\%DAV_HOST%@%DAV_PORT%\\DavWWWRoot%DAV_UNC_PATH% /persistent:no"); mountScript.addEnv("DRIVE_LETTER", driveLetterStr); diff --git a/main/pom.xml b/main/pom.xml index 12de27cb6..1aac82079 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -35,12 +35,12 @@ 1.3 2.4 4.0 - 3.3.2 + 3.4 1.10 3.1 2.4.4 1.10.19 - 2.0.2 + 2.4 diff --git a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java index fa432cc9d..3740b566d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java @@ -8,13 +8,13 @@ *******************************************************************************/ package org.cryptomator.ui; -import java.util.Comparator; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.inject.Named; import javax.inject.Singleton; +import org.cryptomator.common.CommonsModule; import org.cryptomator.crypto.engine.impl.CryptoEngineModule; import org.cryptomator.frontend.FrontendFactory; import org.cryptomator.frontend.webdav.WebDavServer; @@ -24,7 +24,6 @@ import org.cryptomator.ui.model.VaultObjectMapperProvider; import org.cryptomator.ui.settings.Settings; import org.cryptomator.ui.settings.SettingsProvider; import org.cryptomator.ui.util.DeferredCloser; -import org.cryptomator.ui.util.SemVerComparator; import com.fasterxml.jackson.databind.ObjectMapper; @@ -33,7 +32,7 @@ import dagger.Provides; import javafx.application.Application; import javafx.stage.Stage; -@Module(includes = CryptoEngineModule.class) +@Module(includes = {CryptoEngineModule.class, CommonsModule.class}) class CryptomatorModule { private final Application application; @@ -65,13 +64,6 @@ class CryptomatorModule { return closer; } - @Provides - @Singleton - @Named("SemVer") - Comparator provideSemVerComparator() { - return new SemVerComparator(); - } - @Provides @Singleton @Named("VaultJsonMapper")