Compare commits

..
38 Commits
Author SHA1 Message Date
Sebastian Stenzel ce17fff1ac Merge branch 'release/1.3.0-rc4' 2017-05-12 15:40:19 +02:00
Sebastian Stenzel 2d55da309b preparing 1.3.0-rc4 2017-05-12 15:32:54 +02:00
Sebastian Stenzel 761207155d updated dependency 2017-05-12 15:28:44 +02:00
Sebastian Stenzel 456a879181 removed unused badges [ci skip] 2017-05-12 15:02:57 +02:00
Sebastian Stenzel 2e02e70916 Removed codecov, reporting coverage to codacy 2017-05-12 14:48:15 +02:00
Sebastian Stenzel dbc803a0d9 Removed unused classes 2017-05-12 12:06:28 +02:00
Sebastian Stenzel fdccafaa68 cleanup 2017-05-12 12:03:28 +02:00
Sebastian Stenzel deebd82ecd updated javadoc [ci skip] 2017-05-11 17:16:36 +02:00
Sebastian Stenzel 0906abdea9 fixes #499 2017-05-11 17:14:23 +02:00
Sebastian Stenzel da94fe4f6f fixes #491 2017-05-11 10:13:41 +02:00
Sebastian Stenzel 79672a28ee UI improvements for unlock options (fixes #40) 2017-05-09 14:55:26 +02:00
Sebastian Stenzel e052a4b261 AutoUnlocker now workes sequentially and takes a small nap between unlocks. 2017-05-09 14:48:04 +02:00
Sebastian Stenzel 425d4e8fed code cleanup 2017-05-04 16:53:58 +02:00
Sebastian Stenzel d2a2e2304d Implemented #40, tested on macOS 2017-05-04 12:47:15 +02:00
Sebastian Stenzel e7157a64ed removed slack build notifications [ci skip] 2017-04-30 09:51:10 +02:00
Sebastian Stenzel 245a995203 Filtering key events using Guava 2017-04-30 01:00:39 +02:00
Sebastian Stenzel c29d7fb6a2 fixes unit test 2017-04-30 00:59:07 +02:00
Sebastian Stenzel 8cada6d0a2 Guava convenience functions instead of reinventing the wheel 2017-04-30 00:21:29 +02:00
Sebastian Stenzel d03446beef adjusted unit tests 2017-04-29 10:31:22 +02:00
Sebastian Stenzel f62c0b4ca8 Create non-existing parent directories of IPC port file. 2017-04-29 10:12:39 +02:00
Sebastian Stenzel c046056736 Updated JNI dependency [ci skip] 2017-04-29 00:09:15 +02:00
Sebastian Stenzel e63cbf94d0 Logging IOExceptions in main method. 2017-04-28 23:54:23 +02:00
Markus Kreusch d48247b7c6 #386: Allow forced locking after failed locking on Windows 2017-04-28 13:23:51 +02:00
Markus Kreusch 695dcd5de7 Using orange color from iOS for unlocked vault icons 2017-04-28 12:53:53 +02:00
Sebastian Stenzel 5e35985a3f Merge branch 'release/1.3.0-rc3' 2017-04-26 17:21:22 +02:00
Sebastian Stenzel d9325819fd Merge branch 'release/1.3.0-rc3' into develop 2017-04-26 17:20:26 +02:00
Sebastian Stenzel f960238b47 Preparing 1.3.0-rc3 2017-04-26 16:25:20 +02:00
Sebastian Stenzel d0aef5b683 Updated dependencies 2017-04-26 16:24:03 +02:00
Sebastian Stenzel c69fc95126 fixed test 2017-04-26 14:35:26 +02:00
Sebastian Stenzel 51cb41975b Updated dependencies (fixing broken directory listing). Loading correct default settings now 2017-04-26 14:30:49 +02:00
Sebastian Stenzel 0debbb83b1 Merge branch 'release/1.3.0-rc2' into develop 2017-04-25 15:39:01 +02:00
Sebastian Stenzel fbfe2b0a31 Merge branch 'release/1.3.0-rc2' 2017-04-25 15:37:37 +02:00
Sebastian Stenzel a719a83bce Merge branch 'develop' into release/1.3.0-rc2 2017-04-25 15:36:54 +02:00
Sebastian Stenzel d353a9cb9d added OS name + version to version checker user agent header [ci skip] 2017-04-25 15:36:24 +02:00
Sebastian Stenzel ee2e07a9a3 Updated dependencies and localization 2017-04-25 14:33:03 +02:00
Sebastian Stenzel f6689043c7 Preparing 1.3.0-rc2 2017-04-24 16:45:06 +02:00
Sebastian Stenzel 45531dc54a upgraded webdav-nio-adapter to 0.5.0 2017-04-24 15:46:57 +02:00
Sebastian Stenzel 0a26c192fe Merge branch 'release/1.3.0-rc1' into develop 2017-04-20 16:12:54 +02:00
112 changed files with 1069 additions and 4257 deletions
+5 -18
View File
@@ -8,8 +8,9 @@ cache:
- $HOME/.m2
env:
global:
- secure: "IfYURwZaDWuBDvyn47n0k1Zod/IQw1FF+CS5nnV08Q+NfC3vGGJMwV8m59XnbfwnWGxwvCaAbk4qP6s6+ijgZNKkvgfFMo3rfTok5zt43bIqgaFOANYV+OC/1c59gYD6ZUxhW5iNgMgU3qdsRtJuwSmfkVv/jKyLGfAbS4kN8BA=" #coverity
- secure: "lV9OwUbHMrMpLUH1CY+Z4puLDdFXytudyPlG1eGRsesdpuG6KM3uQVz6uAtf6lrU8DRbMM/T7ML+PmvQ4UoPPYLdLxESLLBat2qUPOIVBOhTSlCc7I0DmGy04CSvkeMy8dPaQC0ukgNiR7zwoNzfcpGRN/U9S8tziDruuHoZSrg=" #bintray
- secure: "IfYURwZaDWuBDvyn47n0k1Zod/IQw1FF+CS5nnV08Q+NfC3vGGJMwV8m59XnbfwnWGxwvCaAbk4qP6s6+ijgZNKkvgfFMo3rfTok5zt43bIqgaFOANYV+OC/1c59gYD6ZUxhW5iNgMgU3qdsRtJuwSmfkVv/jKyLGfAbS4kN8BA=" # COVERITY_SCAN_TOKEN
- secure: "lV9OwUbHMrMpLUH1CY+Z4puLDdFXytudyPlG1eGRsesdpuG6KM3uQVz6uAtf6lrU8DRbMM/T7ML+PmvQ4UoPPYLdLxESLLBat2qUPOIVBOhTSlCc7I0DmGy04CSvkeMy8dPaQC0ukgNiR7zwoNzfcpGRN/U9S8tziDruuHoZSrg=" # BINTRAY_API_KEY
- secure: "oWFgRTVP6lyTa7qVxlvkpm20MtVc3BtmsNXQJS6bfg2A0o/iCQMNx7OD59BaafCLGRKvCcJVESiC8FlSylVMS7CDSyYu0gg70NUiIuHp4NBM5inFWYCy/PdQsCTzr5uvNG+rMFQpMFRaCV0FrfM3tLondcVkhsHL68l93Xoexx4=" # CODACY_PROJECT_TOKEN
addons:
coverity_scan:
project:
@@ -19,24 +20,10 @@ addons:
branch_pattern: release.*
install:
# "clean" needed until https://bugs.openjdk.java.net/browse/JDK-8067747 is resolved.
- mvn -fmain/pom.xml clean package -DskipTests dependency:go-offline -Ptest-coverage
- mvn -fmain/pom.xml clean package -DskipTests dependency:go-offline -Pcoverage
- mvn -fmain/pom.xml clean package -DskipTests dependency:go-offline -Prelease
script:
- mvn --update-snapshots -fmain/pom.xml -Ptest-coverage clean test jacoco:report-aggregate
after_success:
- "bash <(curl -s https://codecov.io/bash)"
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/7d429ab35361726e26f2
on_success: change
on_failure: always
on_start: false
slack:
rooms:
secure: "lngJ/HEAFBbD5AdiO9avMqptKpZHdmEwOzS9FabZjkdFh7yAYueTk5RniPUvShjsKtThYm7cJ8AtDMDwc07NvPrzbMBRtUJGwuDT+7c7YFALGFJ1NYi+emkC9x1oafvmPgEYSE+tMKzNcwrHi3ytGgKdIotsKwaF35QNXYA9aMs="
on_success: change
on_failure: always
- mvn --update-snapshots -fmain/pom.xml clean test jacoco:report verify -Pcoverage
before_deploy:
- mvn -fmain/pom.xml -Prelease clean package -DskipTests
deploy:
-2
View File
@@ -3,8 +3,6 @@
[![Build Status](https://travis-ci.org/cryptomator/cryptomator.svg?branch=master)](https://travis-ci.org/cryptomator/cryptomator)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/cryptomator-cryptomator/badge.svg?flat=1)](https://scan.coverity.com/projects/cryptomator-cryptomator)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/2a0adf3cec6a4143b91035d3924178f1)](https://www.codacy.com/app/cryptomator/cryptomator?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cryptomator/cryptomator&amp;utm_campaign=Badge_Grade)
[![Coverage Status](https://coveralls.io/repos/github/cryptomator/cryptomator/badge.svg?branch=master)](https://coveralls.io/github/cryptomator/cryptomator?branch=master)
[![Join the chat at https://gitter.im/cryptomator/cryptomator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cryptomator/cryptomator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Twitter](https://img.shields.io/badge/twitter-@Cryptomator-blue.svg?style=flat)](http://twitter.com/Cryptomator)
[![POEditor](https://img.shields.io/badge/POEditor-Help%20Translate-blue.svg?style=flat)](https://poeditor.com/join/project/bHwbvJmx0E)
+1 -1
View File
@@ -8,7 +8,7 @@
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.3.0-rc1</version>
<version>1.3.0-rc4</version>
</parent>
<artifactId>ant-kit</artifactId>
<packaging>pom</packaging>
-43
View File
@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Markus Kreusch
This file is licensed under the terms of the MIT license.
See the LICENSE.txt file for more info.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>commons-test</artifactId>
<name>Cryptomator common test dependencies</name>
<description>Shared utilities for tests</description>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</dependency>
<dependency>
<groupId>de.bechte.junit</groupId>
<artifactId>junit-hierarchicalcontextrunner</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
</dependency>
</dependencies>
</project>
+1 -10
View File
@@ -10,7 +10,7 @@
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.3.0-rc1</version>
<version>1.3.0-rc4</version>
</parent>
<artifactId>commons</artifactId>
<name>Cryptomator Commons</name>
@@ -53,13 +53,4 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -1,26 +0,0 @@
package org.cryptomator.common;
import java.util.function.Supplier;
public class CachingSupplier<T> implements Supplier<T> {
public static <T> Supplier<T> from(Supplier<T> delegate) {
return new CachingSupplier<>(delegate);
}
private Supplier<T> delegate;
private CachingSupplier(Supplier<T> delegate) {
this.delegate = () -> {
T result = delegate.get();
CachingSupplier.this.delegate = () -> result;
return result;
};
}
@Override
public T get() {
return delegate.get();
}
}
@@ -1,34 +0,0 @@
package org.cryptomator.common;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class Holder<V> implements Supplier<V>, Consumer<V> {
private final V initial;
private V value;
public <W extends V> Holder(W initial) {
this.initial = initial;
reset();
}
public V get() {
return value;
}
public void set(V value) {
this.value = value;
}
public void reset() {
set(initial);
}
@Override
public void accept(V value) {
set(value);
}
}
@@ -4,6 +4,8 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import com.google.common.base.Throwables;
public final class LazyInitializer {
private LazyInitializer() {
@@ -41,11 +43,9 @@ public final class LazyInitializer {
try {
return reference.updateAndGet(invokeFactoryIfNull(factory));
} catch (InitializationException e) {
if (exceptionType.isInstance(e.getCause())) {
throw exceptionType.cast(e.getCause());
} else {
throw e;
}
Throwables.throwIfUnchecked(e);
Throwables.throwIfInstanceOf(e.getCause(), exceptionType);
throw e;
}
}
}
@@ -55,9 +55,8 @@ public final class LazyInitializer {
if (currentValue == null) {
try {
return factory.get();
} catch (RuntimeException e) {
throw e; // don't catch unchecked exceptions
} catch (Exception e) {
Throwables.throwIfUnchecked(e); // don't catch unchecked exceptions
throw new InitializationException(e);
}
} else {
@@ -1,17 +1,23 @@
package org.cryptomator.common;
import java.util.Optional;
import java.util.function.Function;
public final class Optionals {
private Optionals() {
}
public static <T, E extends Exception> void ifPresent(Optional<T> optional, ConsumerThrowingException<T, E> consumer) throws E {
final T t = optional.orElse(null);
if (t != null) {
consumer.accept(t);
}
/**
* Returns a function that is equivalent to the input function but immediately gets the value of the returned optional when invoked.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
* @param function An {@code Optional}-bearing input function {@code Function<Foo, Optional<Bar>>}
* @return A {@code Function<Foo, Bar>}, that may throw a NoSuchElementException, if the original function returns an empty optional.
*/
public static <T, R> Function<T, R> unwrap(Function<T, Optional<R>> function) {
return t -> function.apply(t).get();
}
}
@@ -1,56 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016 Markus Kreusch and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
* Contributors:
* Markus Kreusch - initial implementation
*******************************************************************************/
package org.cryptomator.common;
import java.util.stream.Stream;
/**
* Utility to print stack traces while analyzing issues.
*
* @author Markus Kreusch
*/
public class StackTrace {
public static void print(String message) {
Thread thread = Thread.currentThread();
System.err.println(stackTraceFor(message, thread));
}
private static String stackTraceFor(String message, Thread thread) {
StringBuilder result = new StringBuilder();
appendMessageAndThreadName(result, message, thread);
appendStackTrace(thread, result);
return result.toString();
}
private static void appendStackTrace(Thread thread, StringBuilder result) {
Stream.of(thread.getStackTrace()) //
.skip(4) //
.forEach(stackTraceElement -> append(stackTraceElement, result));
}
private static void appendMessageAndThreadName(StringBuilder result, String message, Thread thread) {
result //
.append('[') //
.append(thread.getName()) //
.append("] ") //
.append(message);
}
private static void append(StackTraceElement stackTraceElement, StringBuilder result) {
String className = stackTraceElement.getClassName();
String methodName = stackTraceElement.getMethodName();
String fileName = stackTraceElement.getFileName();
int lineNumber = stackTraceElement.getLineNumber();
result.append('\n') //
.append(className).append(':').append(methodName) //
.append(" (").append(fileName).append(':').append(lineNumber).append(')');
}
}
@@ -1,48 +0,0 @@
package org.cryptomator.common;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;
import java.util.function.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ExecutionError;
import com.google.common.util.concurrent.UncheckedExecutionException;
public class WeakValuedCache<Key, Value> {
private final LoadingCache<Key, Value> delegate;
private WeakValuedCache(Function<Key, Value> loader) {
delegate = CacheBuilder.newBuilder() //
.weakValues() //
.build(new CacheLoader<Key, Value>() {
@Override
public Value load(Key key) {
return loader.apply(key);
}
});
}
public static <Key, Value> WeakValuedCache<Key, Value> usingLoader(Function<Key, Value> loader) {
return new WeakValuedCache<>(loader);
}
public Value get(Key key) {
try {
return delegate.get(key);
} catch (ExecutionException e) {
throw new IllegalStateException("No checked exception can be thrown by loader", e);
} catch (UncheckedExecutionException e) {
throw (RuntimeException) e.getCause();
} catch (ExecutionError e) {
throw (Error) e.getCause();
}
}
public void forEach(BiConsumer<Key, Value> function) {
delegate.asMap().forEach(function);
}
}
@@ -10,6 +10,8 @@ package org.cryptomator.common.settings;
import java.util.function.Consumer;
import org.apache.commons.lang3.SystemUtils;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
@@ -27,25 +29,24 @@ public class Settings {
public static final int MAX_PORT = 65535;
public static final boolean DEFAULT_CHECK_FOR_UDPATES = true;
public static final int DEFAULT_PORT = 42427;
public static final boolean DEFAULT_USE_IPV6 = false;
public static final boolean DEFAULT_USE_IPV6 = SystemUtils.IS_OS_WINDOWS;
public static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
public static final String DEFAULT_GVFS_SCHEME = "dav";
public static final boolean DEFAULT_DEBUG_MODE = false;
private final Consumer<Settings> saveCmd;
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList();
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList(VaultSettings::observables);
private final BooleanProperty checkForUpdates = new SimpleBooleanProperty(DEFAULT_CHECK_FOR_UDPATES);
private final IntegerProperty port = new SimpleIntegerProperty(DEFAULT_PORT);
private final BooleanProperty useIpv6 = new SimpleBooleanProperty(DEFAULT_USE_IPV6);
private final IntegerProperty numTrayNotifications = new SimpleIntegerProperty(DEFAULT_NUM_TRAY_NOTIFICATIONS);
private final StringProperty preferredGvfsScheme = new SimpleStringProperty(DEFAULT_GVFS_SCHEME);
private final BooleanProperty debugMode = new SimpleBooleanProperty(DEFAULT_DEBUG_MODE);
private Consumer<Settings> saveCmd;
/**
* Package-private constructor; use {@link SettingsProvider}.
*/
Settings(Consumer<Settings> saveCmd) {
this.saveCmd = saveCmd;
Settings() {
directories.addListener((ListChangeListener.Change<? extends VaultSettings> change) -> this.save());
checkForUpdates.addListener(this::somethingChanged);
port.addListener(this::somethingChanged);
@@ -55,6 +56,10 @@ public class Settings {
debugMode.addListener(this::somethingChanged);
}
void setSaveCmd(Consumer<Settings> saveCmd) {
this.saveCmd = saveCmd;
}
private void somethingChanged(ObservableValue<?> observable, Object oldValue, Object newValue) {
this.save();
}
@@ -8,7 +8,6 @@ package org.cryptomator.common.settings;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,13 +21,8 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
private static final Logger LOG = LoggerFactory.getLogger(SettingsJsonAdapter.class);
private final Consumer<Settings> saveCmd;
private final VaultSettingsJsonAdapter vaultSettingsJsonAdapter = new VaultSettingsJsonAdapter();
public SettingsJsonAdapter(Consumer<Settings> saveCmd) {
this.saveCmd = saveCmd;
}
@Override
public void write(JsonWriter out, Settings value) throws IOException {
out.beginObject();
@@ -53,14 +47,14 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
@Override
public Settings read(JsonReader in) throws IOException {
Settings settings = new Settings(saveCmd);
Settings settings = new Settings();
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
switch (name) {
case "directories":
settings.getDirectories().addAll(readVaultSettingsArray(in, settings));
settings.getDirectories().addAll(readVaultSettingsArray(in));
break;
case "checkForUpdatesEnabled":
settings.checkForUpdates().set(in.nextBoolean());
@@ -69,7 +63,10 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
settings.port().set(in.nextInt());
break;
case "useIpv6":
settings.useIpv6().set(in.nextBoolean());
// Temporarily we will disable loading this setting, as we want the default value on each app start.
// This setting might be removed completely in the future
// settings.useIpv6().set(in.nextBoolean());
in.skipValue();
break;
case "numTrayNotifications":
settings.numTrayNotifications().set(in.nextInt());
@@ -90,11 +87,11 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
return settings;
}
private List<VaultSettings> readVaultSettingsArray(JsonReader in, Settings settings) throws IOException {
private List<VaultSettings> readVaultSettingsArray(JsonReader in) throws IOException {
List<VaultSettings> result = new ArrayList<>();
in.beginArray();
while (!JsonToken.END_ARRAY.equals(in.peek())) {
result.add(vaultSettingsJsonAdapter.read(in, settings));
result.add(vaultSettingsJsonAdapter.read(in));
}
in.endArray();
return result;
@@ -62,7 +62,7 @@ public class SettingsProvider implements Provider<Settings> {
private final ScheduledExecutorService saveScheduler = Executors.newSingleThreadScheduledExecutor();
private final AtomicReference<ScheduledFuture<?>> scheduledSaveCmd = new AtomicReference<>();
private final AtomicReference<Settings> settings = new AtomicReference<>();
private final SettingsJsonAdapter settingsJsonAdapter = new SettingsJsonAdapter(this::scheduleSave);
private final SettingsJsonAdapter settingsJsonAdapter = new SettingsJsonAdapter();
private final Gson gson;
@Inject
@@ -100,8 +100,9 @@ public class SettingsProvider implements Provider<Settings> {
LOG.info("Settings loaded from " + settingsPath);
} catch (IOException e) {
LOG.info("Failed to load settings, creating new one.");
settings = new Settings(this::scheduleSave);
settings = new Settings();
}
settings.setSaveCmd(this::scheduleSave);
return settings;
}
@@ -15,37 +15,36 @@ import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.fxmisc.easybind.EasyBind;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
public class VaultSettings {
private final Settings settings;
public static final boolean DEFAULT_UNLOCK_AFTER_STARTUP = false;
public static final boolean DEFAULT_MOUNT_AFTER_UNLOCK = true;
public static final boolean DEFAULT_REAVEAL_AFTER_MOUNT = true;
private final String id;
private final ObjectProperty<Path> path = new SimpleObjectProperty<>();
private final StringProperty mountName = new SimpleStringProperty();
private final StringProperty winDriveLetter = new SimpleStringProperty();
private final BooleanProperty mountAfterUnlock = new SimpleBooleanProperty();
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty();
private final BooleanProperty unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP);
private final BooleanProperty mountAfterUnlock = new SimpleBooleanProperty(DEFAULT_MOUNT_AFTER_UNLOCK);
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REAVEAL_AFTER_MOUNT);
public VaultSettings(Settings settings, String id) {
this.settings = settings;
public VaultSettings(String id) {
this.id = Objects.requireNonNull(id);
EasyBind.subscribe(path, this::deriveMountNameFromPath);
path.addListener(this::somethingChanged);
mountName.addListener(this::somethingChanged);
winDriveLetter.addListener(this::somethingChanged);
mountAfterUnlock.addListener(this::somethingChanged);
}
private void somethingChanged(ObservableValue<?> observable, Object oldValue, Object newValue) {
settings.save();
Observable[] observables() {
return new Observable[] {path, mountName, winDriveLetter, unlockAfterStartup, mountAfterUnlock, revealAfterMount};
}
private void deriveMountNameFromPath(Path path) {
@@ -54,8 +53,8 @@ public class VaultSettings {
}
}
public static VaultSettings withRandomId(Settings settings) {
return new VaultSettings(settings, generateId());
public static VaultSettings withRandomId() {
return new VaultSettings(generateId());
}
private static String generateId() {
@@ -112,6 +111,10 @@ public class VaultSettings {
return winDriveLetter;
}
public BooleanProperty unlockAfterStartup() {
return unlockAfterStartup;
}
public BooleanProperty mountAfterUnlock() {
return mountAfterUnlock;
}
@@ -24,18 +24,20 @@ class VaultSettingsJsonAdapter {
out.name("path").value(value.path().get().toString());
out.name("mountName").value(value.mountName().get());
out.name("winDriveLetter").value(value.winDriveLetter().get());
out.name("unlockAfterStartup").value(value.unlockAfterStartup().get());
out.name("mountAfterUnlock").value(value.mountAfterUnlock().get());
out.name("revealAfterMount").value(value.revealAfterMount().get());
out.endObject();
}
public VaultSettings read(JsonReader in, Settings settings) throws IOException {
public VaultSettings read(JsonReader in) throws IOException {
String id = null;
String path = null;
String mountName = null;
String winDriveLetter = null;
boolean mountAfterUnlock = true;
boolean revealAfterMount = true;
boolean unlockAfterStartup = VaultSettings.DEFAULT_UNLOCK_AFTER_STARTUP;
boolean mountAfterUnlock = VaultSettings.DEFAULT_MOUNT_AFTER_UNLOCK;
boolean revealAfterMount = VaultSettings.DEFAULT_REAVEAL_AFTER_MOUNT;
in.beginObject();
while (in.hasNext()) {
@@ -53,6 +55,9 @@ class VaultSettingsJsonAdapter {
case "winDriveLetter":
winDriveLetter = in.nextString();
break;
case "unlockAfterStartup":
unlockAfterStartup = in.nextBoolean();
break;
case "mountAfterUnlock":
mountAfterUnlock = in.nextBoolean();
break;
@@ -66,10 +71,11 @@ class VaultSettingsJsonAdapter {
}
in.endObject();
VaultSettings vaultSettings = (id == null) ? VaultSettings.withRandomId(settings) : new VaultSettings(settings, id);
VaultSettings vaultSettings = (id == null) ? VaultSettings.withRandomId() : new VaultSettings(id);
vaultSettings.mountName().set(mountName);
vaultSettings.path().set(Paths.get(path));
vaultSettings.winDriveLetter().set(winDriveLetter);
vaultSettings.unlockAfterStartup().set(unlockAfterStartup);
vaultSettings.mountAfterUnlock().set(mountAfterUnlock);
vaultSettings.revealAfterMount().set(revealAfterMount);
return vaultSettings;
@@ -1,178 +0,0 @@
package org.cryptomator.common.streams;
import static org.cryptomator.common.streams.AutoClosingStreamFactory.AUTO_CLOSING_STREAM_FACTORY;
import java.util.DoubleSummaryStatistics;
import java.util.OptionalDouble;
import java.util.function.BiConsumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoublePredicate;
import java.util.function.ObjDoubleConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
public class AutoClosingDoubleStream extends DelegatingDoubleStream {
public static DoubleStream from(DoubleStream delegate) {
return new AutoClosingDoubleStream(delegate);
}
public AutoClosingDoubleStream(DoubleStream delegate) {
super(delegate, AUTO_CLOSING_STREAM_FACTORY);
}
@Override
public void forEach(DoubleConsumer action) {
try {
super.forEach(action);
} finally {
close();
}
}
@Override
public void forEachOrdered(DoubleConsumer action) {
try {
super.forEachOrdered(action);
} finally {
close();
}
}
@Override
public double[] toArray() {
try {
return super.toArray();
} finally {
close();
}
}
@Override
public double reduce(double identity, DoubleBinaryOperator op) {
try {
return super.reduce(identity, op);
} finally {
close();
}
}
@Override
public OptionalDouble reduce(DoubleBinaryOperator op) {
try {
return super.reduce(op);
} finally {
close();
}
}
@Override
public <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R, R> combiner) {
try {
return super.collect(supplier, accumulator, combiner);
} finally {
close();
}
}
@Override
public double sum() {
try {
return super.sum();
} finally {
close();
}
}
@Override
public OptionalDouble min() {
try {
return super.min();
} finally {
close();
}
}
@Override
public OptionalDouble max() {
try {
return super.max();
} finally {
close();
}
}
@Override
public long count() {
try {
return super.count();
} finally {
close();
}
}
@Override
public OptionalDouble average() {
try {
return super.average();
} finally {
close();
}
}
@Override
public DoubleSummaryStatistics summaryStatistics() {
try {
return super.summaryStatistics();
} finally {
close();
}
}
@Override
public boolean anyMatch(DoublePredicate predicate) {
try {
return super.anyMatch(predicate);
} finally {
close();
}
}
@Override
public boolean allMatch(DoublePredicate predicate) {
try {
return super.allMatch(predicate);
} finally {
close();
}
}
@Override
public boolean noneMatch(DoublePredicate predicate) {
try {
return super.noneMatch(predicate);
} finally {
close();
}
}
@Override
public OptionalDouble findFirst() {
try {
return super.findFirst();
} finally {
close();
}
}
@Override
public OptionalDouble findAny() {
try {
return super.findAny();
} finally {
close();
}
}
}
@@ -1,179 +0,0 @@
package org.cryptomator.common.streams;
import static org.cryptomator.common.streams.AutoClosingStreamFactory.AUTO_CLOSING_STREAM_FACTORY;
import java.util.IntSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.function.BiConsumer;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntPredicate;
import java.util.function.ObjIntConsumer;
import java.util.function.Supplier;
import java.util.stream.IntStream;
public class AutoClosingIntStream extends DelegatingIntStream {
public static IntStream from(IntStream delegate) {
return new AutoClosingIntStream(delegate);
}
public AutoClosingIntStream(IntStream delegate) {
super(delegate, AUTO_CLOSING_STREAM_FACTORY);
}
@Override
public void forEach(IntConsumer action) {
try {
super.forEach(action);
} finally {
close();
}
}
@Override
public void forEachOrdered(IntConsumer action) {
try {
super.forEachOrdered(action);
} finally {
close();
}
}
@Override
public int[] toArray() {
try {
return super.toArray();
} finally {
close();
}
}
@Override
public int reduce(int identity, IntBinaryOperator op) {
try {
return super.reduce(identity, op);
} finally {
close();
}
}
@Override
public OptionalInt reduce(IntBinaryOperator op) {
try {
return super.reduce(op);
} finally {
close();
}
}
@Override
public <R> R collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R, R> combiner) {
try {
return super.collect(supplier, accumulator, combiner);
} finally {
close();
}
}
@Override
public int sum() {
try {
return super.sum();
} finally {
close();
}
}
@Override
public OptionalInt min() {
try {
return super.min();
} finally {
close();
}
}
@Override
public OptionalInt max() {
try {
return super.max();
} finally {
close();
}
}
@Override
public long count() {
try {
return super.count();
} finally {
close();
}
}
@Override
public OptionalDouble average() {
try {
return super.average();
} finally {
close();
}
}
@Override
public IntSummaryStatistics summaryStatistics() {
try {
return super.summaryStatistics();
} finally {
close();
}
}
@Override
public boolean anyMatch(IntPredicate predicate) {
try {
return super.anyMatch(predicate);
} finally {
close();
}
}
@Override
public boolean allMatch(IntPredicate predicate) {
try {
return super.allMatch(predicate);
} finally {
close();
}
}
@Override
public boolean noneMatch(IntPredicate predicate) {
try {
return super.noneMatch(predicate);
} finally {
close();
}
}
@Override
public OptionalInt findFirst() {
try {
return super.findFirst();
} finally {
close();
}
}
@Override
public OptionalInt findAny() {
try {
return super.findAny();
} finally {
close();
}
}
}
@@ -1,179 +0,0 @@
package org.cryptomator.common.streams;
import static org.cryptomator.common.streams.AutoClosingStreamFactory.AUTO_CLOSING_STREAM_FACTORY;
import java.util.LongSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalLong;
import java.util.function.BiConsumer;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongPredicate;
import java.util.function.ObjLongConsumer;
import java.util.function.Supplier;
import java.util.stream.LongStream;
public class AutoClosingLongStream extends DelegatingLongStream {
public static LongStream from(LongStream delegate) {
return new AutoClosingLongStream(delegate);
}
public AutoClosingLongStream(LongStream delegate) {
super(delegate, AUTO_CLOSING_STREAM_FACTORY);
}
@Override
public void forEach(LongConsumer action) {
try {
super.forEach(action);
} finally {
close();
}
}
@Override
public void forEachOrdered(LongConsumer action) {
try {
super.forEachOrdered(action);
} finally {
close();
}
}
@Override
public long[] toArray() {
try {
return super.toArray();
} finally {
close();
}
}
@Override
public long reduce(long identity, LongBinaryOperator op) {
try {
return super.reduce(identity, op);
} finally {
close();
}
}
@Override
public OptionalLong reduce(LongBinaryOperator op) {
try {
return super.reduce(op);
} finally {
close();
}
}
@Override
public <R> R collect(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner) {
try {
return super.collect(supplier, accumulator, combiner);
} finally {
close();
}
}
@Override
public long sum() {
try {
return super.sum();
} finally {
close();
}
}
@Override
public OptionalLong min() {
try {
return super.min();
} finally {
close();
}
}
@Override
public OptionalLong max() {
try {
return super.max();
} finally {
close();
}
}
@Override
public long count() {
try {
return super.count();
} finally {
close();
}
}
@Override
public OptionalDouble average() {
try {
return super.average();
} finally {
close();
}
}
@Override
public LongSummaryStatistics summaryStatistics() {
try {
return super.summaryStatistics();
} finally {
close();
}
}
@Override
public boolean anyMatch(LongPredicate predicate) {
try {
return super.anyMatch(predicate);
} finally {
close();
}
}
@Override
public boolean allMatch(LongPredicate predicate) {
try {
return super.allMatch(predicate);
} finally {
close();
}
}
@Override
public boolean noneMatch(LongPredicate predicate) {
try {
return super.noneMatch(predicate);
} finally {
close();
}
}
@Override
public OptionalLong findFirst() {
try {
return super.findFirst();
} finally {
close();
}
}
@Override
public OptionalLong findAny() {
try {
return super.findAny();
} finally {
close();
}
}
}
@@ -1,173 +0,0 @@
package org.cryptomator.common.streams;
import static org.cryptomator.common.streams.AutoClosingStreamFactory.AUTO_CLOSING_STREAM_FACTORY;
import java.util.Comparator;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Stream;
/**
* <p>
* A Stream which is automatically closed after execution of a terminal operation.
* <p>
* Streams returned by intermediate operations are also auto closing.
* <p>
* <b>Note:</b> When using {@link #iterator()} or {@link #spliterator()} auto closing does not occur.
*
* @author Markus Kreusch
*/
public class AutoClosingStream<T> extends DelegatingStream<T> {
public static <T> Stream<T> from(Stream<T> delegate) {
return new AutoClosingStream<>(delegate);
}
private AutoClosingStream(Stream<T> delegate) {
super(delegate, AUTO_CLOSING_STREAM_FACTORY);
}
public void forEach(Consumer<? super T> action) {
try {
super.forEach(action);
} finally {
close();
}
}
public void forEachOrdered(Consumer<? super T> action) {
try {
super.forEachOrdered(action);
} finally {
close();
}
}
public Object[] toArray() {
try {
return super.toArray();
} finally {
close();
}
}
public <A> A[] toArray(IntFunction<A[]> generator) {
try {
return super.toArray(generator);
} finally {
close();
}
}
public T reduce(T identity, BinaryOperator<T> accumulator) {
try {
return super.reduce(identity, accumulator);
} finally {
close();
}
}
public Optional<T> reduce(BinaryOperator<T> accumulator) {
try {
return super.reduce(accumulator);
} finally {
close();
}
}
public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
try {
return super.reduce(identity, accumulator, combiner);
} finally {
close();
}
}
public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
try {
return super.collect(supplier, accumulator, combiner);
} finally {
close();
}
}
public <R, A> R collect(Collector<? super T, A, R> collector) {
try {
return super.collect(collector);
} finally {
close();
}
}
public Optional<T> min(Comparator<? super T> comparator) {
try {
return super.min(comparator);
} finally {
close();
}
}
public Optional<T> max(Comparator<? super T> comparator) {
try {
return super.max(comparator);
} finally {
close();
}
}
public long count() {
try {
return super.count();
} finally {
close();
}
}
public boolean anyMatch(Predicate<? super T> predicate) {
try {
return super.anyMatch(predicate);
} finally {
close();
}
}
public boolean allMatch(Predicate<? super T> predicate) {
try {
return super.allMatch(predicate);
} finally {
close();
}
}
public boolean noneMatch(Predicate<? super T> predicate) {
try {
return super.noneMatch(predicate);
} finally {
close();
}
}
public Optional<T> findFirst() {
try {
return super.findFirst();
} finally {
close();
}
}
public Optional<T> findAny() {
try {
return super.findAny();
} finally {
close();
}
}
}
@@ -1,51 +0,0 @@
package org.cryptomator.common.streams;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
class AutoClosingStreamFactory implements DelegatingStreamFactory {
public static final DelegatingStreamFactory AUTO_CLOSING_STREAM_FACTORY = new AutoClosingStreamFactory();
private AutoClosingStreamFactory() {
}
@Override
public <S> Stream<S> from(Stream<S> other) {
if (AutoClosingStream.class.isInstance(other)) {
return other;
} else {
return AutoClosingStream.from(other);
}
}
@Override
public IntStream from(IntStream other) {
if (AutoClosingIntStream.class.isInstance(other)) {
return other;
} else {
return AutoClosingIntStream.from(other);
}
}
@Override
public LongStream from(LongStream other) {
if (AutoClosingLongStream.class.isInstance(other)) {
return other;
} else {
return AutoClosingLongStream.from(other);
}
}
@Override
public DoubleStream from(DoubleStream other) {
if (AutoClosingDoubleStream.class.isInstance(other)) {
return other;
} else {
return AutoClosingDoubleStream.from(other);
}
}
}
@@ -1,179 +0,0 @@
package org.cryptomator.common.streams;
import java.util.DoubleSummaryStatistics;
import java.util.OptionalDouble;
import java.util.PrimitiveIterator.OfDouble;
import java.util.function.BiConsumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.function.DoubleUnaryOperator;
import java.util.function.ObjDoubleConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
abstract class DelegatingDoubleStream implements DoubleStream {
private final DoubleStream delegate;
private final DelegatingStreamFactory wrapper;
public DelegatingDoubleStream(DoubleStream delegate, DelegatingStreamFactory wrapper) {
this.delegate = delegate;
this.wrapper = wrapper;
}
public DoubleStream filter(DoublePredicate predicate) {
return wrapper.from(delegate.filter(predicate));
}
public boolean isParallel() {
return delegate.isParallel();
}
public DoubleStream map(DoubleUnaryOperator mapper) {
return wrapper.from(delegate.map(mapper));
}
public <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
return wrapper.from(delegate.mapToObj(mapper));
}
public DoubleStream unordered() {
return wrapper.from(delegate.unordered());
}
public DoubleStream onClose(Runnable closeHandler) {
return wrapper.from(delegate.onClose(closeHandler));
}
public IntStream mapToInt(DoubleToIntFunction mapper) {
return wrapper.from(delegate.mapToInt(mapper));
}
public LongStream mapToLong(DoubleToLongFunction mapper) {
return wrapper.from(delegate.mapToLong(mapper));
}
public void close() {
delegate.close();
}
public DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
return wrapper.from(delegate.flatMap(mapper));
}
public DoubleStream distinct() {
return wrapper.from(delegate.distinct());
}
public DoubleStream sorted() {
return wrapper.from(delegate.sorted());
}
public DoubleStream peek(DoubleConsumer action) {
return wrapper.from(delegate.peek(action));
}
public DoubleStream limit(long maxSize) {
return wrapper.from(delegate.limit(maxSize));
}
public DoubleStream skip(long n) {
return wrapper.from(delegate.skip(n));
}
public void forEach(DoubleConsumer action) {
delegate.forEach(action);
}
public void forEachOrdered(DoubleConsumer action) {
delegate.forEachOrdered(action);
}
public double[] toArray() {
return delegate.toArray();
}
public double reduce(double identity, DoubleBinaryOperator op) {
return delegate.reduce(identity, op);
}
public OptionalDouble reduce(DoubleBinaryOperator op) {
return delegate.reduce(op);
}
public <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R, R> combiner) {
return delegate.collect(supplier, accumulator, combiner);
}
public double sum() {
return delegate.sum();
}
public OptionalDouble min() {
return delegate.min();
}
public OptionalDouble max() {
return delegate.max();
}
public long count() {
return delegate.count();
}
public OptionalDouble average() {
return delegate.average();
}
public DoubleSummaryStatistics summaryStatistics() {
return delegate.summaryStatistics();
}
public boolean anyMatch(DoublePredicate predicate) {
return delegate.anyMatch(predicate);
}
public boolean allMatch(DoublePredicate predicate) {
return delegate.allMatch(predicate);
}
public boolean noneMatch(DoublePredicate predicate) {
return delegate.noneMatch(predicate);
}
public OptionalDouble findFirst() {
return delegate.findFirst();
}
public OptionalDouble findAny() {
return delegate.findAny();
}
public Stream<Double> boxed() {
return wrapper.from(delegate.boxed());
}
public DoubleStream sequential() {
return wrapper.from(delegate.sequential());
}
public DoubleStream parallel() {
return wrapper.from(delegate.parallel());
}
public OfDouble iterator() {
return delegate.iterator();
}
public java.util.Spliterator.OfDouble spliterator() {
return delegate.spliterator();
}
}
@@ -1,188 +0,0 @@
package org.cryptomator.common.streams;
import java.util.IntSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.PrimitiveIterator.OfInt;
import java.util.function.BiConsumer;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.ObjIntConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
abstract class DelegatingIntStream implements IntStream {
private final IntStream delegate;
private final DelegatingStreamFactory wrapper;
public DelegatingIntStream(IntStream delegate, DelegatingStreamFactory wrapper) {
this.delegate = delegate;
this.wrapper = wrapper;
}
public IntStream filter(IntPredicate predicate) {
return wrapper.from(delegate.filter(predicate));
}
public boolean isParallel() {
return delegate.isParallel();
}
public IntStream map(IntUnaryOperator mapper) {
return wrapper.from(delegate.map(mapper));
}
public <U> Stream<U> mapToObj(IntFunction<? extends U> mapper) {
return wrapper.from(delegate.mapToObj(mapper));
}
public IntStream unordered() {
return wrapper.from(delegate.unordered());
}
public LongStream mapToLong(IntToLongFunction mapper) {
return wrapper.from(delegate.mapToLong(mapper));
}
public IntStream onClose(Runnable closeHandler) {
return wrapper.from(delegate.onClose(closeHandler));
}
public DoubleStream mapToDouble(IntToDoubleFunction mapper) {
return wrapper.from(delegate.mapToDouble(mapper));
}
public void close() {
delegate.close();
}
public IntStream flatMap(IntFunction<? extends IntStream> mapper) {
return wrapper.from(delegate.flatMap(mapper));
}
public IntStream distinct() {
return wrapper.from(delegate.distinct());
}
public IntStream sorted() {
return wrapper.from(delegate.sorted());
}
public IntStream peek(IntConsumer action) {
return wrapper.from(delegate.peek(action));
}
public IntStream limit(long maxSize) {
return wrapper.from(delegate.limit(maxSize));
}
public IntStream skip(long n) {
return wrapper.from(delegate.skip(n));
}
public void forEach(IntConsumer action) {
delegate.forEach(action);
}
public void forEachOrdered(IntConsumer action) {
delegate.forEachOrdered(action);
}
public int[] toArray() {
return delegate.toArray();
}
public int reduce(int identity, IntBinaryOperator op) {
return delegate.reduce(identity, op);
}
public OptionalInt reduce(IntBinaryOperator op) {
return delegate.reduce(op);
}
public <R> R collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R, R> combiner) {
return delegate.collect(supplier, accumulator, combiner);
}
public int sum() {
return delegate.sum();
}
public OptionalInt min() {
return delegate.min();
}
public OptionalInt max() {
return delegate.max();
}
public long count() {
return delegate.count();
}
public OptionalDouble average() {
return delegate.average();
}
public IntSummaryStatistics summaryStatistics() {
return delegate.summaryStatistics();
}
public boolean anyMatch(IntPredicate predicate) {
return delegate.anyMatch(predicate);
}
public boolean allMatch(IntPredicate predicate) {
return delegate.allMatch(predicate);
}
public boolean noneMatch(IntPredicate predicate) {
return delegate.noneMatch(predicate);
}
public OptionalInt findFirst() {
return delegate.findFirst();
}
public OptionalInt findAny() {
return delegate.findAny();
}
public LongStream asLongStream() {
return wrapper.from(delegate.asLongStream());
}
public DoubleStream asDoubleStream() {
return wrapper.from(delegate.asDoubleStream());
}
public Stream<Integer> boxed() {
return wrapper.from(delegate.boxed());
}
public IntStream sequential() {
return wrapper.from(delegate.sequential());
}
public IntStream parallel() {
return wrapper.from(delegate.parallel());
}
public OfInt iterator() {
return delegate.iterator();
}
public java.util.Spliterator.OfInt spliterator() {
return delegate.spliterator();
}
}
@@ -1,184 +0,0 @@
package org.cryptomator.common.streams;
import java.util.LongSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalLong;
import java.util.PrimitiveIterator.OfLong;
import java.util.function.BiConsumer;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongToIntFunction;
import java.util.function.LongUnaryOperator;
import java.util.function.ObjLongConsumer;
import java.util.function.Supplier;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
abstract class DelegatingLongStream implements LongStream {
private final LongStream delegate;
private final DelegatingStreamFactory wrapper;
public DelegatingLongStream(LongStream delegate, DelegatingStreamFactory wrapper) {
this.delegate = delegate;
this.wrapper = wrapper;
}
public LongStream filter(LongPredicate predicate) {
return wrapper.from(delegate.filter(predicate));
}
public boolean isParallel() {
return delegate.isParallel();
}
public LongStream map(LongUnaryOperator mapper) {
return wrapper.from(delegate.map(mapper));
}
public <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
return wrapper.from(delegate.mapToObj(mapper));
}
public LongStream unordered() {
return wrapper.from(delegate.unordered());
}
public LongStream onClose(Runnable closeHandler) {
return wrapper.from(delegate.onClose(closeHandler));
}
public IntStream mapToInt(LongToIntFunction mapper) {
return wrapper.from(delegate.mapToInt(mapper));
}
public DoubleStream mapToDouble(LongToDoubleFunction mapper) {
return wrapper.from(delegate.mapToDouble(mapper));
}
public void close() {
delegate.close();
}
public LongStream flatMap(LongFunction<? extends LongStream> mapper) {
return wrapper.from(delegate.flatMap(mapper));
}
public LongStream distinct() {
return wrapper.from(delegate.distinct());
}
public LongStream sorted() {
return wrapper.from(delegate.sorted());
}
public LongStream peek(LongConsumer action) {
return wrapper.from(delegate.peek(action));
}
public LongStream limit(long maxSize) {
return wrapper.from(delegate.limit(maxSize));
}
public LongStream skip(long n) {
return wrapper.from(delegate.skip(n));
}
public void forEach(LongConsumer action) {
delegate.forEach(action);
}
public void forEachOrdered(LongConsumer action) {
delegate.forEachOrdered(action);
}
public long[] toArray() {
return delegate.toArray();
}
public long reduce(long identity, LongBinaryOperator op) {
return delegate.reduce(identity, op);
}
public OptionalLong reduce(LongBinaryOperator op) {
return delegate.reduce(op);
}
public <R> R collect(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner) {
return delegate.collect(supplier, accumulator, combiner);
}
public long sum() {
return delegate.sum();
}
public OptionalLong min() {
return delegate.min();
}
public OptionalLong max() {
return delegate.max();
}
public long count() {
return delegate.count();
}
public OptionalDouble average() {
return delegate.average();
}
public LongSummaryStatistics summaryStatistics() {
return delegate.summaryStatistics();
}
public boolean anyMatch(LongPredicate predicate) {
return delegate.anyMatch(predicate);
}
public boolean allMatch(LongPredicate predicate) {
return delegate.allMatch(predicate);
}
public boolean noneMatch(LongPredicate predicate) {
return delegate.noneMatch(predicate);
}
public OptionalLong findFirst() {
return delegate.findFirst();
}
public OptionalLong findAny() {
return delegate.findAny();
}
public DoubleStream asDoubleStream() {
return wrapper.from(delegate.asDoubleStream());
}
public Stream<Long> boxed() {
return wrapper.from(delegate.boxed());
}
public LongStream sequential() {
return wrapper.from(delegate.sequential());
}
public LongStream parallel() {
return wrapper.from(delegate.parallel());
}
public OfLong iterator() {
return delegate.iterator();
}
public java.util.Spliterator.OfLong spliterator() {
return delegate.spliterator();
}
}
@@ -1,194 +0,0 @@
package org.cryptomator.common.streams;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Optional;
import java.util.Spliterator;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.Collector;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
abstract class DelegatingStream<T> implements Stream<T> {
private final Stream<T> delegate;
private final DelegatingStreamFactory wrapper;
protected DelegatingStream(Stream<T> delegate, DelegatingStreamFactory wrapper) {
this.delegate = delegate;
this.wrapper = wrapper;
}
public Iterator<T> iterator() {
return delegate.iterator();
}
public Spliterator<T> spliterator() {
return delegate.spliterator();
}
public boolean isParallel() {
return delegate.isParallel();
}
public Stream<T> sequential() {
return wrapper.from(delegate.sequential());
}
public Stream<T> parallel() {
return wrapper.from(delegate.parallel());
}
public Stream<T> unordered() {
return wrapper.from(delegate.unordered());
}
public Stream<T> onClose(Runnable closeHandler) {
return wrapper.from(delegate.onClose(closeHandler));
}
public void close() {
delegate.close();
}
public Stream<T> filter(Predicate<? super T> predicate) {
return wrapper.from(delegate.filter(predicate));
}
public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
return wrapper.from(delegate.map(mapper));
}
public IntStream mapToInt(ToIntFunction<? super T> mapper) {
return wrapper.from(delegate.mapToInt(mapper));
}
public LongStream mapToLong(ToLongFunction<? super T> mapper) {
return wrapper.from(delegate.mapToLong(mapper));
}
public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
return wrapper.from(delegate.mapToDouble(mapper));
}
public <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) {
return wrapper.from(delegate.flatMap(mapper));
}
public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
return wrapper.from(delegate.flatMapToInt(mapper));
}
public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
return wrapper.from(delegate.flatMapToLong(mapper));
}
public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
return wrapper.from(delegate.flatMapToDouble(mapper));
}
public Stream<T> distinct() {
return wrapper.from(delegate.distinct());
}
public Stream<T> sorted() {
return wrapper.from(delegate.sorted());
}
public Stream<T> sorted(Comparator<? super T> comparator) {
return wrapper.from(delegate.sorted(comparator));
}
public Stream<T> peek(Consumer<? super T> action) {
return wrapper.from(delegate.peek(action));
}
public Stream<T> limit(long maxSize) {
return wrapper.from(delegate.limit(maxSize));
}
public Stream<T> skip(long n) {
return wrapper.from(delegate.skip(n));
}
public void forEach(Consumer<? super T> action) {
delegate.forEach(action);
}
public void forEachOrdered(Consumer<? super T> action) {
delegate.forEachOrdered(action);
}
public Object[] toArray() {
return delegate.toArray();
}
public <A> A[] toArray(IntFunction<A[]> generator) {
return delegate.toArray(generator);
}
public T reduce(T identity, BinaryOperator<T> accumulator) {
return delegate.reduce(identity, accumulator);
}
public Optional<T> reduce(BinaryOperator<T> accumulator) {
return delegate.reduce(accumulator);
}
public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {
return delegate.reduce(identity, accumulator, combiner);
}
public <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) {
return delegate.collect(supplier, accumulator, combiner);
}
public <R, A> R collect(Collector<? super T, A, R> collector) {
return delegate.collect(collector);
}
public Optional<T> min(Comparator<? super T> comparator) {
return delegate.min(comparator);
}
public Optional<T> max(Comparator<? super T> comparator) {
return delegate.max(comparator);
}
public long count() {
return delegate.count();
}
public boolean anyMatch(Predicate<? super T> predicate) {
return delegate.anyMatch(predicate);
}
public boolean allMatch(Predicate<? super T> predicate) {
return delegate.allMatch(predicate);
}
public boolean noneMatch(Predicate<? super T> predicate) {
return delegate.noneMatch(predicate);
}
public Optional<T> findFirst() {
return delegate.findFirst();
}
public Optional<T> findAny() {
return delegate.findAny();
}
}
@@ -1,22 +0,0 @@
package org.cryptomator.common.streams;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
public interface DelegatingStreamFactory {
<S> Stream<S> from(Stream<S> other);
IntStream from(IntStream other);
LongStream from(LongStream other);
DoubleStream from(DoubleStream other);
public interface ObjectStreamWrapper {
<S> Stream<S> from(Stream<S> other);
}
}
@@ -1,43 +0,0 @@
package org.cryptomator.common;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.function.Supplier;
import org.junit.Test;
public class CachingSupplierTest {
@Test
public void testInvokingGetInvokesDelegate() {
@SuppressWarnings("unchecked")
Supplier<Object> delegate = mock(Supplier.class);
Object expectedResult = new Object();
when(delegate.get()).thenReturn(expectedResult);
Supplier<Object> inTest = CachingSupplier.from(delegate);
Object result = inTest.get();
assertThat(result, is(expectedResult));
}
@Test
public void testInvokingGetTwiceDoesNotInvokeDelegateTwice() {
@SuppressWarnings("unchecked")
Supplier<Object> delegate = mock(Supplier.class);
Object expectedResult = new Object();
when(delegate.get()).thenReturn(expectedResult);
Supplier<Object> inTest = CachingSupplier.from(delegate);
inTest.get();
Object result = inTest.get();
assertThat(result, is(expectedResult));
verify(delegate).get();
}
}
@@ -1,42 +0,0 @@
package org.cryptomator.common;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
public class HolderTest {
private static final Object INITIAL = new Object();
private static final Object VALUE = new Object();
private Holder<Object> inTest = new Holder<>(INITIAL);
@Test
public void testInitialValueIsInitial() {
assertThat(inTest.get(), is(INITIAL));
}
@Test
public void testSetChangesValue() {
inTest.set(VALUE);
assertThat(inTest.get(), is(VALUE));
}
@Test
public void testAcceptChangesValue() {
inTest.accept(VALUE);
assertThat(inTest.get(), is(VALUE));
}
@Test
public void testResetChangesValueToInitial() {
inTest.set(VALUE);
inTest.reset();
assertThat(inTest.get(), is(INITIAL));
}
}
@@ -1,156 +0,0 @@
package org.cryptomator.common;
import static java.lang.String.format;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.function.Function;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
public class WeakValuedCacheTest {
private final String A_KEY = "aKey";
private final String ANOTHER_KEY = "anotherKey";
private WeakValuedCache<String, Value> inTest;
private Function<String, Value> loader;
@SuppressWarnings("unchecked")
@Before
public void setup() {
loader = Mockito.mock(Function.class);
inTest = WeakValuedCache.usingLoader(loader);
}
@Test
public void testResultOfGetIsResultOfLoaderForTheSameKey() {
Value theValue = new Value();
Value theOtherValue = new Value();
when(loader.apply(A_KEY)).thenReturn(theValue);
when(loader.apply(ANOTHER_KEY)).thenReturn(theOtherValue);
Value result = inTest.get(A_KEY);
Value anotherResult = inTest.get(ANOTHER_KEY);
assertThat(result, is(sameInstance(theValue)));
assertThat(anotherResult, is(sameInstance(theOtherValue)));
}
@Test
public void testCachedResultIsResultOfLoaderForTheSameKey() {
Value theValue = new Value();
Value theOtherValue = new Value();
when(loader.apply(A_KEY)).thenReturn(theValue);
when(loader.apply(ANOTHER_KEY)).thenReturn(theOtherValue);
inTest.get(A_KEY);
inTest.get(ANOTHER_KEY);
Value result = inTest.get(A_KEY);
Value anotherResult = inTest.get(ANOTHER_KEY);
assertThat(result, is(sameInstance(theValue)));
assertThat(anotherResult, is(sameInstance(theOtherValue)));
}
@Test
public void testTwiceInvocationOfGetDoesNotInvokeLoaderTwice() {
Value theValue = new Value();
when(loader.apply(A_KEY)).thenReturn(theValue);
inTest.get(A_KEY);
inTest.get(A_KEY);
verify(loader).apply(A_KEY);
}
@Test
public void testSecondInvocationOfGetReturnsTheSameResult() {
Value theValue = new Value();
when(loader.apply(A_KEY)).thenReturn(theValue);
inTest.get(A_KEY);
Value result = inTest.get(A_KEY);
assertThat(result, is(sameInstance(theValue)));
}
@Ignore
@Test
public void testCacheDoesNotPreventGarbageCollectionOfValues() {
when(loader.apply(A_KEY)).thenAnswer(this::createValueUsingMoreThanHalfTheJvmMemory);
inTest.get(A_KEY);
// force garbage collection of previously created value by creating an
// object so large it can not coexist with the value
createObjectUsingMoreThanHalfTheJvmMemory();
}
@Test(expected = RuntimeExceptionThrownInLoader.class)
public void testCacheRethrowsRuntimeExceptionsFromLoader() {
when(loader.apply(A_KEY)).thenThrow(new RuntimeExceptionThrownInLoader());
inTest.get(A_KEY);
}
@Test(expected = ErrorThrownInLoader.class)
public void testCacheRethrowsErrorsFromLoader() {
when(loader.apply(A_KEY)).thenThrow(new ErrorThrownInLoader());
inTest.get(A_KEY);
}
private Value createValueUsingMoreThanHalfTheJvmMemory(InvocationOnMock invocation) {
Object data = createObjectUsingMoreThanHalfTheJvmMemory();
Value value = new Value();
value.setPayload(data);
return value;
}
private Object createObjectUsingMoreThanHalfTheJvmMemory() {
long maxMemory = Runtime.getRuntime().maxMemory();
long moreThanHalfTheJvmMemory = maxMemory / 2 + 1;
return createObjectUsingAtLeast(moreThanHalfTheJvmMemory);
}
private Object createObjectUsingAtLeast(long minMemory) {
if (minMemory <= Integer.MAX_VALUE) {
return new byte[(int) minMemory];
} else if ((minMemory / Integer.MAX_VALUE) <= Integer.MAX_VALUE) {
int numberOfArraysWithMaxIntSize = (int) (minMemory / Integer.MAX_VALUE);
int numberOfRemainingBytes = (int) (minMemory - Integer.MAX_VALUE * numberOfArraysWithMaxIntSize);
return new byte[][][] { //
new byte[numberOfArraysWithMaxIntSize][Integer.MAX_VALUE], //
new byte[1][numberOfRemainingBytes] //
};
} else {
throw new IllegalArgumentException(format("Can not create object with more than 3.999999996 Exabyte"));
}
}
private static class RuntimeExceptionThrownInLoader extends RuntimeException {
}
private static class ErrorThrownInLoader extends Error {
}
private static class Value {
@SuppressWarnings("unused")
private Object payload;
public void setPayload(Object payload) {
this.payload = payload;
}
}
}
@@ -12,10 +12,7 @@ import org.junit.Test;
public class SettingsJsonAdapterTest {
private final SettingsJsonAdapter adapter = new SettingsJsonAdapter(this::noop);
private void noop(Settings settings) {
}
private final SettingsJsonAdapter adapter = new SettingsJsonAdapter();
@Test
public void testDeserialize() throws IOException {
@@ -32,7 +29,7 @@ public class SettingsJsonAdapterTest {
Assert.assertTrue(settings.checkForUpdates().get());
Assert.assertEquals(2, settings.getDirectories().size());
Assert.assertEquals(8080, settings.port().get());
Assert.assertTrue(settings.useIpv6().get());
// Assert.assertTrue(settings.useIpv6().get()); temporarily ignored
Assert.assertEquals(42, settings.numTrayNotifications().get());
Assert.assertEquals("dav", settings.preferredGvfsScheme().get());
}
@@ -0,0 +1,33 @@
package org.cryptomator.common.settings;
import java.io.IOException;
import java.util.function.Consumer;
import org.junit.Test;
import org.mockito.Mockito;
public class SettingsTest {
@Test
public void testAutoSave() throws IOException {
@SuppressWarnings("unchecked")
Consumer<Settings> changeListener = Mockito.mock(Consumer.class);
Settings settings = new Settings();
settings.setSaveCmd(changeListener);
VaultSettings vaultSettings = VaultSettings.withRandomId();
Mockito.verify(changeListener, Mockito.times(0)).accept(settings);
// first change (to property):
settings.preferredGvfsScheme().set("asd");
Mockito.verify(changeListener, Mockito.times(1)).accept(settings);
// second change (to list):
settings.getDirectories().add(vaultSettings);
Mockito.verify(changeListener, Mockito.times(2)).accept(settings);
// third change (to property of list item):
vaultSettings.mountName().set("asd");
Mockito.verify(changeListener, Mockito.times(3)).accept(settings);
}
}
@@ -11,7 +11,6 @@ import java.nio.file.Paths;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import com.google.gson.stream.JsonReader;
@@ -23,9 +22,8 @@ public class VaultSettingsJsonAdapterTest {
public void testDeserialize() throws IOException {
String json = "{\"id\": \"foo\", \"path\": \"/foo/bar\", \"mountName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true}";
JsonReader jsonReader = new JsonReader(new StringReader(json));
Settings settings = Mockito.mock(Settings.class);
VaultSettings vaultSettings = adapter.read(jsonReader, settings);
VaultSettings vaultSettings = adapter.read(jsonReader);
Assert.assertEquals("foo", vaultSettings.getId());
Assert.assertEquals(Paths.get("/foo/bar"), vaultSettings.path().get());
Assert.assertEquals("test", vaultSettings.mountName().get());
@@ -1,227 +0,0 @@
package org.cryptomator.common.streams;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.OptionalDouble;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
import java.util.function.DoubleToIntFunction;
import java.util.function.DoubleToLongFunction;
import java.util.function.DoubleUnaryOperator;
import java.util.function.Function;
import java.util.function.ObjDoubleConsumer;
import java.util.function.Supplier;
import java.util.stream.BaseStream;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
@SuppressWarnings({"unchecked", "rawtypes"})
@RunWith(Theories.class)
public class AutoClosingDoubleStreamTest {
private static final DoublePredicate A_DOUBLE_PREDICATE = any -> true;
private static final DoubleFunction A_DOUBLE_FUNCTION = i -> null;
private static final BiConsumer A_BICONSUMER = (a, b) -> {
};
private static final Supplier A_SUPPLIER = () -> null;
@DataPoints("intermediateOperations")
public static final List<DoubleermediateOperation<?>> INTERMEDIATE_OPERATIONS = new ArrayList<>();
@DataPoints("terminalOperations")
public static final List<TerminalOperation<?>> TERMINAL_OPERATIONS = new ArrayList<>();
private static final DoubleUnaryOperator A_DOUBLE_UNARY_OPERATOR = i -> 3;
private static final DoubleToLongFunction A_DOUBLE_TO_LONG_FUNCTION = i -> 3L;
private static final DoubleToIntFunction A_DOUBLE_TO_INT_FUNCTION = i -> 5;
private static final DoubleConsumer A_DOUBLE_CONSUMER = i -> {
};
private static final ObjDoubleConsumer AN_OBJ_DOUBLE_CONSUMER = (a, b) -> {
};
private static final DoubleBinaryOperator A_DOUBLE_BINARY_OPERATOR = (a, b) -> a;
static {
// define intermediate operations
test(DoubleStream.class, DoubleStream::distinct);
test(DoubleStream.class, stream -> stream.filter(A_DOUBLE_PREDICATE));
test(DoubleStream.class, stream -> stream.flatMap(A_DOUBLE_FUNCTION));
test(DoubleStream.class, stream -> stream.limit(5));
test(DoubleStream.class, stream -> stream.map(A_DOUBLE_UNARY_OPERATOR));
test(LongStream.class, stream -> stream.mapToLong(A_DOUBLE_TO_LONG_FUNCTION));
test(Stream.class, stream -> stream.mapToObj(A_DOUBLE_FUNCTION));
test(IntStream.class, stream -> stream.mapToInt(A_DOUBLE_TO_INT_FUNCTION));
test(DoubleStream.class, DoubleStream::parallel);
test(DoubleStream.class, stream -> stream.peek(A_DOUBLE_CONSUMER));
test(DoubleStream.class, DoubleStream::sequential);
test(DoubleStream.class, stream -> stream.skip(5));
test(DoubleStream.class, DoubleStream::sorted);
test(DoubleStream.class, DoubleStream::unordered);
test(Stream.class, DoubleStream::boxed);
// define terminal operations
test(stream -> stream.allMatch(A_DOUBLE_PREDICATE), true);
test(stream -> stream.anyMatch(A_DOUBLE_PREDICATE), true);
test(stream -> stream.collect(A_SUPPLIER, AN_OBJ_DOUBLE_CONSUMER, A_BICONSUMER), 7d);
test(DoubleStream::count, 3L);
test(DoubleStream::findAny, OptionalDouble.of(3));
test(DoubleStream::findFirst, OptionalDouble.of(3));
test(stream -> stream.forEach(A_DOUBLE_CONSUMER));
test(stream -> stream.forEachOrdered(A_DOUBLE_CONSUMER));
test(stream -> stream.max(), OptionalDouble.of(3));
test(stream -> stream.min(), OptionalDouble.of(3));
test(stream -> stream.noneMatch(A_DOUBLE_PREDICATE), true);
test(stream -> stream.reduce(A_DOUBLE_BINARY_OPERATOR), OptionalDouble.of(3));
test(stream -> stream.reduce(1, A_DOUBLE_BINARY_OPERATOR), 3d);
test(DoubleStream::toArray, new double[1]);
test(DoubleStream::sum, 1d);
test(DoubleStream::average, OptionalDouble.of(3d));
test(DoubleStream::summaryStatistics, new DoubleSummaryStatistics());
}
private static <T> void test(Consumer<DoubleStream> consumer) {
TERMINAL_OPERATIONS.add(new TerminalOperation<T>() {
@Override
public T result() {
return null;
}
@Override
public T apply(DoubleStream stream) {
consumer.accept(stream);
return null;
}
});
}
private static <T> void test(Function<DoubleStream, T> function, T result) {
TERMINAL_OPERATIONS.add(new TerminalOperation<T>() {
@Override
public T result() {
return result;
}
@Override
public T apply(DoubleStream stream) {
return function.apply(stream);
}
});
}
private static <T extends BaseStream> void test(Class<? extends T> type, Function<DoubleStream, T> function) {
INTERMEDIATE_OPERATIONS.add(new DoubleermediateOperation<T>() {
@Override
public Class<? extends T> type() {
return type;
}
@Override
public T apply(DoubleStream stream) {
return function.apply(stream);
}
});
}
@Rule
public ExpectedException thrown = ExpectedException.none();
private DoubleStream delegate;
private DoubleStream inTest;
@Before
public void setUp() {
delegate = mock(DoubleStream.class);
inTest = AutoClosingDoubleStream.from(delegate);
}
@Theory
public void testIntermediateOperationReturnsNewAutoClosingStream(@FromDataPoints("intermediateOperations") DoubleermediateOperation intermediateOperation) {
BaseStream newDelegate = (BaseStream) mock(intermediateOperation.type());
when(intermediateOperation.apply(delegate)).thenReturn(newDelegate);
BaseStream result = intermediateOperation.apply(inTest);
assertThat(result, isAutoClosing());
verifyDelegate(result, newDelegate);
}
@Theory
public void testTerminalOperationDelegatesToAndClosesDelegate(@FromDataPoints("terminalOperations") TerminalOperation terminalOperation) {
Object expectedResult = terminalOperation.result();
if (expectedResult != null) {
when(terminalOperation.apply(delegate)).thenReturn(expectedResult);
}
Object result = terminalOperation.apply(inTest);
InOrder inOrder = inOrder(delegate);
assertThat(result, is(expectedResult));
inOrder.verify(delegate).close();
}
@Theory
public void testTerminalOperationClosesDelegateEvenOnException(@FromDataPoints("terminalOperations") TerminalOperation terminalOperation) {
RuntimeException exception = new RuntimeException();
terminalOperation.apply(doThrow(exception).when(delegate));
thrown.expect(is(exception));
try {
terminalOperation.apply(inTest);
} finally {
verify(delegate).close();
}
}
private Matcher<BaseStream> isAutoClosing() {
return is(anyOf(instanceOf(AutoClosingStream.class), instanceOf(AutoClosingDoubleStream.class), instanceOf(AutoClosingIntStream.class), instanceOf(AutoClosingLongStream.class)));
}
private void verifyDelegate(BaseStream result, BaseStream newDelegate) {
result.close();
verify(newDelegate).close();
}
private interface TerminalOperation<T> {
T result();
T apply(DoubleStream stream);
}
private interface DoubleermediateOperation<T extends BaseStream> {
Class<? extends T> type();
T apply(DoubleStream stream);
}
}
@@ -1,228 +0,0 @@
package org.cryptomator.common.streams;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.IntToDoubleFunction;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import java.util.function.ObjIntConsumer;
import java.util.function.Supplier;
import java.util.stream.BaseStream;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
@SuppressWarnings({"unchecked", "rawtypes"})
@RunWith(Theories.class)
public class AutoClosingIntStreamTest {
private static final IntPredicate AN_INT_PREDICATE = any -> true;
private static final IntFunction AN_INT_FUNCTION = i -> null;
private static final BiConsumer A_BICONSUMER = (a, b) -> {
};
private static final Supplier A_SUPPLIER = () -> null;
@DataPoints("intermediateOperations")
public static final List<IntermediateOperation<?>> INTERMEDIATE_OPERATIONS = new ArrayList<>();
@DataPoints("terminalOperations")
public static final List<TerminalOperation<?>> TERMINAL_OPERATIONS = new ArrayList<>();
private static final IntUnaryOperator AN_INT_UNARY_OPERATOR = i -> 3;
private static final IntToDoubleFunction AN_INT_TO_DOUBLE_FUNCTION = i -> 3d;
private static final IntToLongFunction AN_INT_TO_LONG_FUNCTION = i -> 5L;
private static final IntConsumer AN_INT_CONSUMER = i -> {
};
private static final ObjIntConsumer AN_OBJ_INT_CONSUMER = (a, b) -> {
};
private static final IntBinaryOperator AN_INT_BINARY_OPERATOR = (a, b) -> a;
static {
// define intermediate operations
test(IntStream.class, IntStream::distinct);
test(IntStream.class, stream -> stream.filter(AN_INT_PREDICATE));
test(IntStream.class, stream -> stream.flatMap(AN_INT_FUNCTION));
test(IntStream.class, stream -> stream.limit(5));
test(IntStream.class, stream -> stream.map(AN_INT_UNARY_OPERATOR));
test(DoubleStream.class, stream -> stream.mapToDouble(AN_INT_TO_DOUBLE_FUNCTION));
test(Stream.class, stream -> stream.mapToObj(AN_INT_FUNCTION));
test(LongStream.class, stream -> stream.mapToLong(AN_INT_TO_LONG_FUNCTION));
test(IntStream.class, IntStream::parallel);
test(IntStream.class, stream -> stream.peek(AN_INT_CONSUMER));
test(IntStream.class, IntStream::sequential);
test(IntStream.class, stream -> stream.skip(5));
test(IntStream.class, IntStream::sorted);
test(IntStream.class, IntStream::unordered);
test(Stream.class, IntStream::boxed);
// define terminal operations
test(stream -> stream.allMatch(AN_INT_PREDICATE), true);
test(stream -> stream.anyMatch(AN_INT_PREDICATE), true);
test(stream -> stream.collect(A_SUPPLIER, AN_OBJ_INT_CONSUMER, A_BICONSUMER), 7);
test(IntStream::count, 3L);
test(IntStream::findAny, OptionalInt.of(3));
test(IntStream::findFirst, OptionalInt.of(3));
test(stream -> stream.forEach(AN_INT_CONSUMER));
test(stream -> stream.forEachOrdered(AN_INT_CONSUMER));
test(stream -> stream.max(), OptionalInt.of(3));
test(stream -> stream.min(), OptionalInt.of(3));
test(stream -> stream.noneMatch(AN_INT_PREDICATE), true);
test(stream -> stream.reduce(AN_INT_BINARY_OPERATOR), OptionalInt.of(3));
test(stream -> stream.reduce(1, AN_INT_BINARY_OPERATOR), 3);
test(IntStream::toArray, new int[1]);
test(IntStream::sum, 1);
test(IntStream::average, OptionalDouble.of(3d));
test(IntStream::summaryStatistics, new IntSummaryStatistics());
}
private static <T> void test(Consumer<IntStream> consumer) {
TERMINAL_OPERATIONS.add(new TerminalOperation<T>() {
@Override
public T result() {
return null;
}
@Override
public T apply(IntStream stream) {
consumer.accept(stream);
return null;
}
});
}
private static <T> void test(Function<IntStream, T> function, T result) {
TERMINAL_OPERATIONS.add(new TerminalOperation<T>() {
@Override
public T result() {
return result;
}
@Override
public T apply(IntStream stream) {
return function.apply(stream);
}
});
}
private static <T extends BaseStream> void test(Class<? extends T> type, Function<IntStream, T> function) {
INTERMEDIATE_OPERATIONS.add(new IntermediateOperation<T>() {
@Override
public Class<? extends T> type() {
return type;
}
@Override
public T apply(IntStream stream) {
return function.apply(stream);
}
});
}
@Rule
public ExpectedException thrown = ExpectedException.none();
private IntStream delegate;
private IntStream inTest;
@Before
public void setUp() {
delegate = mock(IntStream.class);
inTest = AutoClosingIntStream.from(delegate);
}
@Theory
public void testIntermediateOperationReturnsNewAutoClosingStream(@FromDataPoints("intermediateOperations") IntermediateOperation intermediateOperation) {
BaseStream newDelegate = (BaseStream) mock(intermediateOperation.type());
when(intermediateOperation.apply(delegate)).thenReturn(newDelegate);
BaseStream result = intermediateOperation.apply(inTest);
assertThat(result, isAutoClosing());
verifyDelegate(result, newDelegate);
}
@Theory
public void testTerminalOperationDelegatesToAndClosesDelegate(@FromDataPoints("terminalOperations") TerminalOperation terminalOperation) {
Object expectedResult = terminalOperation.result();
if (expectedResult != null) {
when(terminalOperation.apply(delegate)).thenReturn(expectedResult);
}
Object result = terminalOperation.apply(inTest);
InOrder inOrder = inOrder(delegate);
assertThat(result, is(expectedResult));
inOrder.verify(delegate).close();
}
@Theory
public void testTerminalOperationClosesDelegateEvenOnException(@FromDataPoints("terminalOperations") TerminalOperation terminalOperation) {
RuntimeException exception = new RuntimeException();
terminalOperation.apply(doThrow(exception).when(delegate));
thrown.expect(is(exception));
try {
terminalOperation.apply(inTest);
} finally {
verify(delegate).close();
}
}
private Matcher<BaseStream> isAutoClosing() {
return is(anyOf(instanceOf(AutoClosingStream.class), instanceOf(AutoClosingDoubleStream.class), instanceOf(AutoClosingIntStream.class), instanceOf(AutoClosingLongStream.class)));
}
private void verifyDelegate(BaseStream result, BaseStream newDelegate) {
result.close();
verify(newDelegate).close();
}
private interface TerminalOperation<T> {
T result();
T apply(IntStream stream);
}
private interface IntermediateOperation<T extends BaseStream> {
Class<? extends T> type();
T apply(IntStream stream);
}
}
@@ -1,228 +0,0 @@
package org.cryptomator.common.streams;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.OptionalDouble;
import java.util.OptionalLong;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.LongBinaryOperator;
import java.util.function.LongConsumer;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
import java.util.function.LongToDoubleFunction;
import java.util.function.LongToIntFunction;
import java.util.function.LongUnaryOperator;
import java.util.function.ObjLongConsumer;
import java.util.function.Supplier;
import java.util.stream.BaseStream;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
@SuppressWarnings({"unchecked", "rawtypes"})
@RunWith(Theories.class)
public class AutoClosingLongStreamTest {
private static final LongPredicate AN_LONG_PREDICATE = any -> true;
private static final LongFunction AN_LONG_FUNCTION = i -> null;
private static final BiConsumer A_BICONSUMER = (a, b) -> {
};
private static final Supplier A_SUPPLIER = () -> null;
@DataPoints("intermediateOperations")
public static final List<LongermediateOperation<?>> INTERMEDIATE_OPERATIONS = new ArrayList<>();
@DataPoints("terminalOperations")
public static final List<TerminalOperation<?>> TERMINAL_OPERATIONS = new ArrayList<>();
private static final LongUnaryOperator AN_LONG_UNARY_OPERATOR = i -> 3;
private static final LongToDoubleFunction AN_LONG_TO_DOUBLE_FUNCTION = i -> 3d;
private static final LongToIntFunction AN_LONG_TO_INT_FUNCTION = i -> 5;
private static final LongConsumer AN_LONG_CONSUMER = i -> {
};
private static final ObjLongConsumer AN_OBJ_LONG_CONSUMER = (a, b) -> {
};
private static final LongBinaryOperator AN_LONG_BINARY_OPERATOR = (a, b) -> a;
static {
// define intermediate operations
test(LongStream.class, LongStream::distinct);
test(LongStream.class, stream -> stream.filter(AN_LONG_PREDICATE));
test(LongStream.class, stream -> stream.flatMap(AN_LONG_FUNCTION));
test(LongStream.class, stream -> stream.limit(5));
test(LongStream.class, stream -> stream.map(AN_LONG_UNARY_OPERATOR));
test(DoubleStream.class, stream -> stream.mapToDouble(AN_LONG_TO_DOUBLE_FUNCTION));
test(Stream.class, stream -> stream.mapToObj(AN_LONG_FUNCTION));
test(IntStream.class, stream -> stream.mapToInt(AN_LONG_TO_INT_FUNCTION));
test(LongStream.class, LongStream::parallel);
test(LongStream.class, stream -> stream.peek(AN_LONG_CONSUMER));
test(LongStream.class, LongStream::sequential);
test(LongStream.class, stream -> stream.skip(5));
test(LongStream.class, LongStream::sorted);
test(LongStream.class, LongStream::unordered);
test(Stream.class, LongStream::boxed);
// define terminal operations
test(stream -> stream.allMatch(AN_LONG_PREDICATE), true);
test(stream -> stream.anyMatch(AN_LONG_PREDICATE), true);
test(stream -> stream.collect(A_SUPPLIER, AN_OBJ_LONG_CONSUMER, A_BICONSUMER), 7L);
test(LongStream::count, 3L);
test(LongStream::findAny, OptionalLong.of(3));
test(LongStream::findFirst, OptionalLong.of(3));
test(stream -> stream.forEach(AN_LONG_CONSUMER));
test(stream -> stream.forEachOrdered(AN_LONG_CONSUMER));
test(stream -> stream.max(), OptionalLong.of(3));
test(stream -> stream.min(), OptionalLong.of(3));
test(stream -> stream.noneMatch(AN_LONG_PREDICATE), true);
test(stream -> stream.reduce(AN_LONG_BINARY_OPERATOR), OptionalLong.of(3));
test(stream -> stream.reduce(1, AN_LONG_BINARY_OPERATOR), 3L);
test(LongStream::toArray, new long[1]);
test(LongStream::sum, 1L);
test(LongStream::average, OptionalDouble.of(3d));
test(LongStream::summaryStatistics, new LongSummaryStatistics());
}
private static <T> void test(Consumer<LongStream> consumer) {
TERMINAL_OPERATIONS.add(new TerminalOperation<T>() {
@Override
public T result() {
return null;
}
@Override
public T apply(LongStream stream) {
consumer.accept(stream);
return null;
}
});
}
private static <T> void test(Function<LongStream, T> function, T result) {
TERMINAL_OPERATIONS.add(new TerminalOperation<T>() {
@Override
public T result() {
return result;
}
@Override
public T apply(LongStream stream) {
return function.apply(stream);
}
});
}
private static <T extends BaseStream> void test(Class<? extends T> type, Function<LongStream, T> function) {
INTERMEDIATE_OPERATIONS.add(new LongermediateOperation<T>() {
@Override
public Class<? extends T> type() {
return type;
}
@Override
public T apply(LongStream stream) {
return function.apply(stream);
}
});
}
@Rule
public ExpectedException thrown = ExpectedException.none();
private LongStream delegate;
private LongStream inTest;
@Before
public void setUp() {
delegate = mock(LongStream.class);
inTest = AutoClosingLongStream.from(delegate);
}
@Theory
public void testIntermediateOperationReturnsNewAutoClosingStream(@FromDataPoints("intermediateOperations") LongermediateOperation intermediateOperation) {
BaseStream newDelegate = (BaseStream) mock(intermediateOperation.type());
when(intermediateOperation.apply(delegate)).thenReturn(newDelegate);
BaseStream result = intermediateOperation.apply(inTest);
assertThat(result, isAutoClosing());
verifyDelegate(result, newDelegate);
}
@Theory
public void testTerminalOperationDelegatesToAndClosesDelegate(@FromDataPoints("terminalOperations") TerminalOperation terminalOperation) {
Object expectedResult = terminalOperation.result();
if (expectedResult != null) {
when(terminalOperation.apply(delegate)).thenReturn(expectedResult);
}
Object result = terminalOperation.apply(inTest);
InOrder inOrder = inOrder(delegate);
assertThat(result, is(expectedResult));
inOrder.verify(delegate).close();
}
@Theory
public void testTerminalOperationClosesDelegateEvenOnException(@FromDataPoints("terminalOperations") TerminalOperation terminalOperation) {
RuntimeException exception = new RuntimeException();
terminalOperation.apply(doThrow(exception).when(delegate));
thrown.expect(is(exception));
try {
terminalOperation.apply(inTest);
} finally {
verify(delegate).close();
}
}
private Matcher<BaseStream> isAutoClosing() {
return is(anyOf(instanceOf(AutoClosingStream.class), instanceOf(AutoClosingDoubleStream.class), instanceOf(AutoClosingIntStream.class), instanceOf(AutoClosingLongStream.class)));
}
private void verifyDelegate(BaseStream result, BaseStream newDelegate) {
result.close();
verify(newDelegate).close();
}
private interface TerminalOperation<T> {
T result();
T apply(LongStream stream);
}
private interface LongermediateOperation<T extends BaseStream> {
Class<? extends T> type();
T apply(LongStream stream);
}
}
@@ -1,231 +0,0 @@
package org.cryptomator.common.streams;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.BaseStream;
import java.util.stream.Collector;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
@SuppressWarnings({"unchecked", "rawtypes"})
@RunWith(Theories.class)
public class AutoClosingStreamTest {
private static final Predicate A_PREDICATE = any -> true;
private static final Function A_FUNCTION = any -> null;
private static final ToDoubleFunction A_TO_DOUBLE_FUNCTION = any -> 0d;
private static final ToIntFunction A_TO_INT_FUNCTION = any -> 1;
private static final ToLongFunction A_TO_LONG_FUNCTION = any -> 1L;
private static final Consumer A_CONSUMER = any -> {
};
private static final Comparator A_COMPARATOR = (left, right) -> 0;
private static final Collector A_COLLECTOR = mock(Collector.class);
private static final BinaryOperator A_BINARY_OPERATOR = (left, right) -> null;
private static final Object AN_OBJECT = new Object();
private static final IntFunction AN_INT_FUNCTION = i -> null;
private static final BiConsumer A_BICONSUMER = (a, b) -> {
};
private static final Supplier A_SUPPLIER = () -> null;
@DataPoints("intermediateOperations")
public static final List<IntermediateOperation<?>> INTERMEDIATE_OPERATIONS = new ArrayList<>();
@DataPoints("terminalOperations")
public static final List<TerminalOperation<?>> TERMINAL_OPERATIONS = new ArrayList<>();
static {
// define intermediate operations
test(Stream.class, Stream::distinct);
test(Stream.class, stream -> stream.filter(A_PREDICATE));
test(Stream.class, stream -> stream.flatMap(A_FUNCTION));
test(DoubleStream.class, stream -> stream.flatMapToDouble(A_FUNCTION));
test(IntStream.class, stream -> stream.flatMapToInt(A_FUNCTION));
test(LongStream.class, stream -> stream.flatMapToLong(A_FUNCTION));
test(Stream.class, stream -> stream.limit(5));
test(Stream.class, stream -> stream.map(A_FUNCTION));
test(DoubleStream.class, stream -> stream.mapToDouble(A_TO_DOUBLE_FUNCTION));
test(IntStream.class, stream -> stream.mapToInt(A_TO_INT_FUNCTION));
test(LongStream.class, stream -> stream.mapToLong(A_TO_LONG_FUNCTION));
test(Stream.class, Stream::parallel);
test(Stream.class, stream -> stream.peek(A_CONSUMER));
test(Stream.class, Stream::sequential);
test(Stream.class, stream -> stream.skip(5));
test(Stream.class, Stream::sorted);
test(Stream.class, stream -> stream.sorted(A_COMPARATOR));
test(Stream.class, Stream::unordered);
// define terminal operations
test(stream -> stream.allMatch(A_PREDICATE), true);
test(stream -> stream.anyMatch(A_PREDICATE), true);
test(stream -> stream.collect(A_COLLECTOR), new Object());
test(stream -> stream.collect(A_SUPPLIER, A_BICONSUMER, A_BICONSUMER), new Object());
test(Stream::count, 3L);
test(Stream::findAny, Optional.of(new Object()));
test(Stream::findFirst, Optional.of(new Object()));
test(stream -> stream.forEach(A_CONSUMER));
test(stream -> stream.forEachOrdered(A_CONSUMER));
test(stream -> stream.max(A_COMPARATOR), Optional.of(new Object()));
test(stream -> stream.min(A_COMPARATOR), Optional.of(new Object()));
test(stream -> stream.noneMatch(A_PREDICATE), true);
test(stream -> stream.reduce(A_BINARY_OPERATOR), Optional.of(new Object()));
test(stream -> stream.reduce(AN_OBJECT, A_BINARY_OPERATOR), Optional.of(new Object()));
test(stream -> stream.reduce(AN_OBJECT, A_BINARY_OPERATOR, A_BINARY_OPERATOR), Optional.of(new Object()));
test(Stream::toArray, new Object[1]);
test(stream -> stream.toArray(AN_INT_FUNCTION), new Object[1]);
}
private static <T> void test(Consumer<Stream> consumer) {
TERMINAL_OPERATIONS.add(new TerminalOperation<T>() {
@Override
public T result() {
return null;
}
@Override
public T apply(Stream stream) {
consumer.accept(stream);
return null;
}
});
}
private static <T> void test(Function<Stream, T> function, T result) {
TERMINAL_OPERATIONS.add(new TerminalOperation<T>() {
@Override
public T result() {
return result;
}
@Override
public T apply(Stream stream) {
return function.apply(stream);
}
});
}
private static <T extends BaseStream> void test(Class<? extends T> type, Function<Stream, T> function) {
INTERMEDIATE_OPERATIONS.add(new IntermediateOperation<T>() {
@Override
public Class<? extends T> type() {
return type;
}
@Override
public T apply(Stream stream) {
return function.apply(stream);
}
});
}
@Rule
public ExpectedException thrown = ExpectedException.none();
private Stream<Object> delegate;
private Stream<Object> inTest;
@Before
public void setUp() {
delegate = mock(Stream.class);
inTest = AutoClosingStream.from(delegate);
}
@Theory
public void testIntermediateOperationReturnsNewAutoClosingStream(@FromDataPoints("intermediateOperations") IntermediateOperation intermediateOperation) {
BaseStream newDelegate = (BaseStream) mock(intermediateOperation.type());
when(intermediateOperation.apply(delegate)).thenReturn(newDelegate);
BaseStream result = intermediateOperation.apply(inTest);
assertThat(result, isAutoClosing());
verifyDelegate(result, newDelegate);
}
@Theory
public void testTerminalOperationDelegatesToAndClosesDelegate(@FromDataPoints("terminalOperations") TerminalOperation terminalOperation) {
Object expectedResult = terminalOperation.result();
if (expectedResult != null) {
when(terminalOperation.apply(delegate)).thenReturn(expectedResult);
}
Object result = terminalOperation.apply(inTest);
InOrder inOrder = inOrder(delegate);
assertThat(result, is(expectedResult));
inOrder.verify(delegate).close();
}
@Theory
public void testTerminalOperationClosesDelegateEvenOnException(@FromDataPoints("terminalOperations") TerminalOperation terminalOperation) {
RuntimeException exception = new RuntimeException();
terminalOperation.apply(doThrow(exception).when(delegate));
thrown.expect(is(exception));
try {
terminalOperation.apply(inTest);
} finally {
verify(delegate).close();
}
}
private Matcher<BaseStream> isAutoClosing() {
return is(anyOf(instanceOf(AutoClosingStream.class), instanceOf(AutoClosingDoubleStream.class), instanceOf(AutoClosingIntStream.class), instanceOf(AutoClosingLongStream.class)));
}
private void verifyDelegate(BaseStream result, BaseStream newDelegate) {
result.close();
verify(newDelegate).close();
}
private interface TerminalOperation<T> {
T result();
T apply(Stream stream);
}
private interface IntermediateOperation<T extends BaseStream> {
Class<? extends T> type();
T apply(Stream stream);
}
}
-45
View File
@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Sebastian Stenzel
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>filesystem-charsets</artifactId>
<name>Cryptomator filesystem: Charset compatibility layer</name>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-inmemory</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2016 Sebastian Stenzel
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>filesystem-crypto-integration-tests</artifactId>
<name>Cryptomator filesystem: Encryption layer tests</name>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-crypto</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-nameshortening</artifactId>
</dependency>
<!-- DI -->
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<scope>provided</scope>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-inmemory</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-93
View File
@@ -1,93 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Sebastian Stenzel
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>filesystem-crypto</artifactId>
<name>Cryptomator filesystem: Encryption layer</name>
<properties>
<bouncycastle.version>1.51</bouncycastle.version>
<sivmode.version>1.2.0</sivmode.version>
</properties>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<!-- Crypto -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>siv-mode</artifactId>
<version>${sivmode.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<!-- Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<!-- JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- DI -->
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<scope>provided</scope>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-inmemory</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-41
View File
@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Sebastian Stenzel
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>filesystem-inmemory</artifactId>
<name>Cryptomator filesystem: In-memory mock</name>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-75
View File
@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Markus Kreusch
This file is licensed under the terms of the MIT license.
See the LICENSE.txt file for more info.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>filesystem-invariants-tests</artifactId>
<name>Cryptomator filesystem: Invariants tests</name>
<description>Test only project which checks invariants of FileSystem implementations</description>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-charsets</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-crypto</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-crypto-integration-tests</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-inmemory</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-nameshortening</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-nio</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-stats</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-76
View File
@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Sebastian Stenzel
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>filesystem-nameshortening</artifactId>
<name>Cryptomator filesystem: Name shortening layer</name>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<!-- Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<!-- JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- DI -->
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<scope>provided</scope>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-inmemory</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-64
View File
@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2015 Markus Kreusch This file is licensed under the terms
of the MIT license. See the LICENSE.txt file for more info. -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>filesystem-nio</artifactId>
<name>Cryptomator filesystem: NIO-based physical layer</name>
<description>FileSystem implementation to access the real file system of an operating system</description>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-45
View File
@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Sebastian Stenzel
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>filesystem-stats</artifactId>
<name>Cryptomator filesystem: Throughput statistics</name>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<!-- Tests -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-inmemory</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
-27
View File
@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2016 Sebastian Stenzel
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>frontend-api</artifactId>
<name>Cryptomator frontend: API</name>
<description>API for filesystem frontends</description>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
</dependencies>
</project>
-134
View File
@@ -1,134 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2015 Sebastian Stenzel
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.2.4</version>
</parent>
<artifactId>frontend-webdav</artifactId>
<name>Cryptomator frontend: WebDAV frontend</name>
<description>Provides access via WebDAV to filesystems</description>
<properties>
<jackrabbit.version>2.11.3</jackrabbit.version>
<jetty.version>9.3.3.v20150827</jetty.version>
</properties>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-api</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>frontend-api</artifactId>
</dependency>
<!-- Jackrabbit -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-webdav</artifactId>
<version>${jackrabbit.version}</version>
</dependency>
<!-- Jetty -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
</dependency>
<!-- Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!-- DI -->
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger</artifactId>
</dependency>
<dependency>
<groupId>com.google.dagger</groupId>
<artifactId>dagger-compiler</artifactId>
<scope>provided</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons-test</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-inmemory</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-crypto-integration-tests</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-nameshortening</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-crypto</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>filesystem-nio</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
+64 -1
View File
@@ -5,12 +5,53 @@
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.3.0-rc1</version>
<version>1.3.0-rc4</version>
</parent>
<artifactId>jacoco-report</artifactId>
<name>Cryptomator Code Coverage Report</name>
<packaging>pom</packaging>
<dependencies>
<!-- all modules containing unit tests: -->
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>commons</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>keychain</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>ui</artifactId>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>launcher</artifactId>
<exclusions>
<exclusion>
<!-- conflict with codacy-coverage-reporter -->
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- binary dependency used during build -->
<dependency>
<groupId>com.codacy</groupId>
<artifactId>codacy-coverage-reporter</artifactId>
<version>1.0.13</version>
<classifier>assembly</classifier>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
@@ -26,6 +67,28 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.codacy.CodacyCoverageReporter</mainClass>
<arguments>
<argument>-l</argument>
<argument>Java</argument>
<argument>-r</argument>
<argument>${project.build.directory}/site/jacoco-aggregate/jacoco.xml</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.3.0-rc1</version>
<version>1.3.0-rc4</version>
</parent>
<artifactId>keychain</artifactId>
<name>System Keychain Access</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.3.0-rc1</version>
<version>1.3.0-rc4</version>
</parent>
<artifactId>launcher</artifactId>
<name>Cryptomator Launcher</name>
@@ -17,7 +17,7 @@ public class Cryptomator {
private static final Logger LOG = LoggerFactory.getLogger(Cryptomator.class);
static final BlockingQueue<Path> FILE_OPEN_REQUESTS = new ArrayBlockingQueue<>(10);
public static void main(String[] args) throws IOException {
public static void main(String[] args) {
LOG.info("Starting Cryptomator {} on {} {} ({})", ApplicationVersion.orElse("SNAPSHOT"), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
FileOpenRequestHandler fileOpenRequestHandler = new FileOpenRequestHandler(FILE_OPEN_REQUESTS);
@@ -30,6 +30,8 @@ public class Cryptomator {
communicator.handleLaunchArgs(args);
LOG.info("Found running application instance. Shutting down.");
}
} catch (IOException e) {
LOG.error("Failed to initiate inter-process communication.", e);
}
System.exit(0); // end remaining non-daemon threads.
}
@@ -12,7 +12,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.rmi.ConnectException;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
@@ -27,6 +26,8 @@ import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.io.MoreFiles;
/**
* First running application on a machine opens a server socket. Further processes will connect as clients.
*/
@@ -113,7 +114,7 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt
}
@Override
public void close() throws IOException {
public void close() {
// no-op
}
@@ -150,14 +151,14 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt
}
@Override
public void close() throws IOException {
public void close() {
try {
registry.unbind(RMI_NAME);
UnicastRemoteObject.unexportObject(remote, true);
socket.close();
LOG.debug("Server shut down.");
} catch (NotBoundException | NoSuchObjectException e) {
// ignore
} catch (NotBoundException | IOException e) {
LOG.warn("Failed to close IPC Server.", e);
}
}
@@ -222,6 +223,7 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt
ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES);
buf.putInt(port);
buf.flip();
MoreFiles.createParentDirectories(path);
try (WritableByteChannel ch = Files.newByteChannel(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
if (ch.write(buf) != Integer.BYTES) {
throw new IOException("Did not write expected number of bytes.");
@@ -6,6 +6,7 @@ import java.nio.channels.SeekableByteChannel;
import java.nio.file.FileSystem;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.spi.FileSystemProvider;
import java.util.concurrent.atomic.AtomicInteger;
@@ -17,6 +18,8 @@ import org.mockito.Mockito;
public class InterProcessCommunicatorTest {
Path portFilePath = Mockito.mock(Path.class);
Path portFileParentPath = Mockito.mock(Path.class);
BasicFileAttributes portFileParentPathAttrs = Mockito.mock(BasicFileAttributes.class);
FileSystem fs = Mockito.mock(FileSystem.class);
FileSystemProvider provider = Mockito.mock(FileSystemProvider.class);
SeekableByteChannel portFileChannel = Mockito.mock(SeekableByteChannel.class);
@@ -25,7 +28,13 @@ public class InterProcessCommunicatorTest {
@Before
public void setup() throws IOException {
Mockito.when(portFilePath.getFileSystem()).thenReturn(fs);
Mockito.when(portFilePath.toAbsolutePath()).thenReturn(portFilePath);
Mockito.when(portFilePath.normalize()).thenReturn(portFilePath);
Mockito.when(portFilePath.getParent()).thenReturn(portFileParentPath);
Mockito.when(portFileParentPath.getFileSystem()).thenReturn(fs);
Mockito.when(fs.provider()).thenReturn(provider);
Mockito.when(provider.readAttributes(portFileParentPath, BasicFileAttributes.class)).thenReturn(portFileParentPathAttrs);
Mockito.when(portFileParentPathAttrs.isDirectory()).thenReturn(false, true); // Guava's MoreFiles will check if dir exists before attempting to create them.
Mockito.when(provider.newByteChannel(Mockito.eq(portFilePath), Mockito.any(), Mockito.any())).thenReturn(portFileChannel);
Mockito.when(portFileChannel.read(Mockito.any())).then(invocation -> {
ByteBuffer buf = invocation.getArgument(0);
@@ -45,6 +54,7 @@ public class InterProcessCommunicatorTest {
InterProcessCommunicationProtocol protocol = Mockito.mock(InterProcessCommunicationProtocol.class);
try (InterProcessCommunicator result = InterProcessCommunicator.start(portFilePath, protocol)) {
Assert.assertTrue(result.isServer());
Mockito.verify(provider).createDirectory(portFileParentPath);
Mockito.verifyZeroInteractions(protocol);
result.handleLaunchArgs(new String[] {"foo"});
}
@@ -57,6 +67,7 @@ public class InterProcessCommunicatorTest {
InterProcessCommunicationProtocol protocol = Mockito.mock(InterProcessCommunicationProtocol.class);
try (InterProcessCommunicator result = InterProcessCommunicator.start(portFilePath, protocol)) {
Assert.assertTrue(result.isServer());
Mockito.verify(provider).createDirectory(portFileParentPath);
Mockito.verifyZeroInteractions(protocol);
}
}
@@ -67,10 +78,12 @@ public class InterProcessCommunicatorTest {
InterProcessCommunicationProtocol protocol = Mockito.mock(InterProcessCommunicationProtocol.class);
try (InterProcessCommunicator result1 = InterProcessCommunicator.start(portFilePath, protocol)) {
Assert.assertTrue(result1.isServer());
Mockito.verify(provider, Mockito.times(1)).createDirectory(portFileParentPath);
Mockito.verifyZeroInteractions(protocol);
try (InterProcessCommunicator result2 = InterProcessCommunicator.start(portFilePath, null)) {
Assert.assertFalse(result2.isServer());
Mockito.verify(provider, Mockito.times(1)).createDirectory(portFileParentPath);
Assert.assertNotSame(result1, result2);
result2.handleLaunchArgs(new String[] {"foo"});
+14 -5
View File
@@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.3.0-rc1</version>
<version>1.3.0-rc4</version>
<packaging>pom</packaging>
<name>Cryptomator</name>
@@ -28,9 +28,9 @@
<!-- dependency versions -->
<cryptomator.cryptolib.version>1.1.1</cryptomator.cryptolib.version>
<cryptomator.cryptofs.version>1.2.0</cryptomator.cryptofs.version>
<cryptomator.webdav.version>0.4.0</cryptomator.webdav.version>
<cryptomator.jni.version>1.0.0</cryptomator.jni.version>
<cryptomator.cryptofs.version>1.2.2</cryptomator.cryptofs.version>
<cryptomator.webdav.version>0.6.0</cryptomator.webdav.version>
<cryptomator.jni.version>1.0.2</cryptomator.jni.version>
<log4j.version>2.8.1</log4j.version> <!-- keep in sync with https://github.com/edwgiz/maven-shaded-log4j-transformer (used in uber-jar), or wait for https://issues.apache.org/jira/browse/LOG4J2-954 fix -->
<slf4j.version>1.7.25</slf4j.version>
<junit.version>4.12</junit.version>
@@ -239,6 +239,7 @@
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
@@ -268,10 +269,18 @@
</modules>
</profile>
<profile>
<id>test-coverage</id>
<id>coverage</id>
<modules>
<module>jacoco-report</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
</profiles>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.3.0-rc1</version>
<version>1.3.0-rc4</version>
</parent>
<artifactId>uber-jar</artifactId>
<name>Single über jar with all dependencies</name>
+4 -11
View File
@@ -12,7 +12,7 @@
<parent>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.3.0-rc1</version>
<version>1.3.0-rc4</version>
</parent>
<artifactId>ui</artifactId>
<name>Cryptomator GUI</name>
@@ -99,16 +99,9 @@
<!-- Logging -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -37,7 +37,7 @@ import org.cryptomator.common.settings.Settings;
import org.cryptomator.jni.JniException;
import org.cryptomator.jni.MacApplicationUiState;
import org.cryptomator.jni.MacFunctions;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,15 +62,7 @@ public class ExitUtil {
this.macFunctions = macFunctions;
}
public void initExitHandler() {
initExitHandler(ExitUtil::platformExitOnMainThread);
}
private static void platformExitOnMainThread() {
Platform.runLater(Platform::exit);
}
private void initExitHandler(Runnable exitCommand) {
public void initExitHandler(Runnable exitCommand) {
if (SystemUtils.IS_OS_LINUX) {
initMinimizeExitHandler(exitCommand);
} else {
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -24,10 +24,7 @@ import org.cryptomator.jni.JniModule;
import org.cryptomator.keychain.KeychainModule;
import org.cryptomator.ui.controllers.ViewControllerModule;
import org.cryptomator.ui.model.VaultComponent;
import org.cryptomator.ui.util.DeferredCloser;
import org.fxmisc.easybind.EasyBind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dagger.Module;
import dagger.Provides;
@@ -36,22 +33,6 @@ import javafx.beans.binding.Binding;
@Module(includes = {ViewControllerModule.class, CommonsModule.class, KeychainModule.class, JniModule.class}, subcomponents = {VaultComponent.class})
public class UiModule {
private static final Logger LOG = LoggerFactory.getLogger(UiModule.class);
@Provides
@Singleton
DeferredCloser provideDeferredCloser(@Named("shutdownTaskScheduler") Consumer<Runnable> shutdownTaskScheduler) {
DeferredCloser closer = new DeferredCloser();
shutdownTaskScheduler.accept(() -> {
try {
closer.close();
} catch (Exception e) {
LOG.error("Error during shutdown.", e);
}
});
return closer;
}
@Provides
@Singleton
Settings provideSettings(SettingsProvider settingsProvider) {
@@ -60,8 +41,10 @@ public class UiModule {
@Provides
@Singleton
ExecutorService provideExecutorService(DeferredCloser closer) {
return closer.closeLater(Executors.newCachedThreadPool(), ExecutorService::shutdown).get().orElseThrow(IllegalStateException::new);
ExecutorService provideExecutorService(@Named("shutdownTaskScheduler") Consumer<Runnable> shutdownTaskScheduler) {
ExecutorService executorService = Executors.newCachedThreadPool();
shutdownTaskScheduler.accept(executorService::shutdown);
return executorService;
}
@Provides
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -20,8 +20,8 @@ import javax.inject.Singleton;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.cryptolib.api.UnsupportedVaultFormatException;
import org.cryptomator.ui.controls.SecPasswordField;
import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.model.Vault;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.util.PasswordStrengthUtil;
import org.fxmisc.easybind.EasyBind;
import org.slf4j.Logger;
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 Sebastian Stenzel
* Copyright (c) 2014, 2017 Sebastian Stenzel
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -19,8 +19,8 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.cryptomator.ui.controls.SecPasswordField;
import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.model.Vault;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.util.PasswordStrengthUtil;
import org.fxmisc.easybind.EasyBind;
import org.slf4j.Logger;
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 Sebastian Stenzel
* Copyright (c) 2014, 2017 Sebastian Stenzel
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -26,16 +26,16 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.ui.ExitUtil;
import org.cryptomator.ui.controls.DirectoryListCell;
import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.model.AutoUnlocker;
import org.cryptomator.ui.model.UpgradeStrategies;
import org.cryptomator.ui.model.UpgradeStrategy;
import org.cryptomator.ui.model.Vault;
import org.cryptomator.ui.model.VaultFactory;
import org.cryptomator.ui.model.VaultList;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.util.DialogBuilderUtil;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription;
@@ -51,6 +51,8 @@ import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.BooleanExpression;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.Side;
@@ -83,11 +85,11 @@ public class MainController implements ViewController {
private final Localization localization;
private final ExecutorService executorService;
private final BlockingQueue<Path> fileOpenRequests;
private final Settings settings;
private final VaultFactory vaultFactoy;
private final ViewControllerLoader viewControllerLoader;
private final ObjectProperty<ViewController> activeController = new SimpleObjectProperty<>();
private final VaultList vaults;
private final ObservableList<Vault> vaults;
private final BooleanBinding areAllVaultsLocked;
private final ObjectProperty<Vault> selectedVault = new SimpleObjectProperty<>();
private final BooleanExpression isSelectedVaultUnlocked = BooleanExpression.booleanExpression(EasyBind.select(selectedVault).selectObject(Vault::unlockedProperty).orElse(false));
private final BooleanExpression isSelectedVaultValid = BooleanExpression.booleanExpression(EasyBind.monadic(selectedVault).map(Vault::isValidVaultDirectory).orElse(false));
@@ -100,13 +102,12 @@ public class MainController implements ViewController {
@Inject
public MainController(@Named("mainWindow") Stage mainWindow, ExecutorService executorService, @Named("fileOpenRequests") BlockingQueue<Path> fileOpenRequests, ExitUtil exitUtil, Localization localization,
Settings settings, VaultFactory vaultFactoy, ViewControllerLoader viewControllerLoader, UpgradeStrategies upgradeStrategies, VaultList vaults) {
VaultFactory vaultFactoy, ViewControllerLoader viewControllerLoader, UpgradeStrategies upgradeStrategies, VaultList vaults, AutoUnlocker autoUnlocker) {
this.mainWindow = mainWindow;
this.executorService = executorService;
this.fileOpenRequests = fileOpenRequests;
this.exitUtil = exitUtil;
this.localization = localization;
this.settings = settings;
this.vaultFactoy = vaultFactoy;
this.viewControllerLoader = viewControllerLoader;
this.vaults = vaults;
@@ -114,6 +115,10 @@ public class MainController implements ViewController {
// derived bindings:
this.isShowingSettings = Bindings.equal(SettingsController.class, EasyBind.monadic(activeController).map(ViewController::getClass));
this.upgradeStrategyForSelectedVault = EasyBind.monadic(selectedVault).map(upgradeStrategies::getUpgradeStrategy);
this.areAllVaultsLocked = Bindings.isEmpty(FXCollections.observableList(vaults, Vault::observables).filtered(Vault::isUnlocked));
EasyBind.subscribe(areAllVaultsLocked, Platform::setImplicitExit);
autoUnlocker.unlockAllSilently();
}
@FXML
@@ -184,10 +189,15 @@ public class MainController implements ViewController {
stage.getIcons().add(new Image(getClass().getResourceAsStream("/window_icon.png")));
Application.setUserAgentStylesheet(getClass().getResource("/css/win_theme.css").toString());
}
exitUtil.initExitHandler();
exitUtil.initExitHandler(this::gracefulShutdown);
listenToFileOpenRequests(stage);
}
private void gracefulShutdown() {
vaults.filtered(Vault::isUnlocked).forEach(Vault::prepareForShutdown);
Platform.runLater(Platform::exit);
}
private void loadFont(String resourcePath) {
try (InputStream in = getClass().getResourceAsStream(resourcePath)) {
Font.loadFont(in, 12.0);
@@ -259,7 +269,7 @@ public class MainController implements ViewController {
final List<File> files = fileChooser.showOpenMultipleDialog(mainWindow);
if (files != null) {
for (final File file : files) {
addVault(file.toPath(), false);
addVault(file.toPath(), true);
}
}
}
@@ -281,7 +291,7 @@ public class MainController implements ViewController {
}
final Vault vault = vaults.stream().filter(v -> v.getPath().equals(vaultPath)).findAny().orElseGet(() -> {
VaultSettings vaultSettings = VaultSettings.withRandomId(settings);
VaultSettings vaultSettings = VaultSettings.withRandomId();
vaultSettings.path().set(vaultPath);
return vaultFactoy.get(vaultSettings);
});
@@ -399,7 +409,6 @@ public class MainController implements ViewController {
}
public void didUnlock(Vault vault) {
Platform.setImplicitExit(false);
if (vault.equals(selectedVault.getValue())) {
this.showUnlockedView(vault);
}
@@ -417,9 +426,6 @@ public class MainController implements ViewController {
public void didLock(UnlockedController ctrl) {
unlockedVaults.remove(ctrl.getVault());
showUnlockView();
if (!vaults.stream().anyMatch(Vault::isUnlocked)) {
Platform.setImplicitExit(true);
}
}
private void showChangePasswordView() {
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 Sebastian Stenzel
* Copyright (c) 2014, 2017 Sebastian Stenzel
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -14,10 +14,12 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import javafx.beans.binding.Bindings;
import javafx.event.ActionEvent;
@@ -34,6 +36,8 @@ import javafx.scene.layout.VBox;
@Singleton
public class SettingsController implements ViewController {
private static final CharMatcher DIGITS_MATCHER = CharMatcher.inRange('0', '9');
private final Localization localization;
private final Settings settings;
private final Optional<String> applicationVersion;
@@ -130,11 +134,7 @@ public class SettingsController implements ViewController {
}
private void filterNumericKeyEvents(KeyEvent t) {
if (t.getCharacter() == null || t.getCharacter().length() == 0) {
return;
}
char c = CharUtils.toChar(t.getCharacter());
if (!(CharUtils.isAsciiNumeric(c) || c == '_')) {
if (!Strings.isNullOrEmpty(t.getCharacter()) && !DIGITS_MATCHER.matchesAllOf(t.getCharacter())) {
t.consume();
}
}
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 Sebastian Stenzel
* Copyright (c) 2014, 2017 Sebastian Stenzel
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -17,20 +17,26 @@ import javax.inject.Inject;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.cryptolib.api.UnsupportedVaultFormatException;
import org.cryptomator.frontend.webdav.ServerLifecycleException;
import org.cryptomator.frontend.webdav.mount.Mounter.CommandFailedException;
import org.cryptomator.keychain.KeychainAccess;
import org.cryptomator.ui.controls.SecPasswordField;
import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.model.Vault;
import org.cryptomator.ui.model.WindowsDriveLetters;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.util.AsyncTaskService;
import org.cryptomator.ui.util.DialogBuilderUtil;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
@@ -55,6 +61,11 @@ import javafx.util.StringConverter;
public class UnlockController implements ViewController {
private static final Logger LOG = LoggerFactory.getLogger(UnlockController.class);
private static final CharMatcher ALPHA_NUMERIC_MATCHER = CharMatcher.inRange('a', 'z') //
.or(CharMatcher.inRange('A', 'Z')) //
.or(CharMatcher.inRange('0', '9')) //
.or(CharMatcher.is('_')) //
.precomputed();
private final Application app;
private final Localization localization;
@@ -64,6 +75,7 @@ public class UnlockController implements ViewController {
private final Optional<KeychainAccess> keychainAccess;
private Vault vault;
private Optional<UnlockListener> listener = Optional.empty();
private Subscription vaultSubs = Subscription.EMPTY;
@Inject
public UnlockController(Application app, Localization localization, AsyncTaskService asyncTaskService, WindowsDriveLetters driveLetters, Optional<KeychainAccess> keychainAccess) {
@@ -116,6 +128,9 @@ public class UnlockController implements ViewController {
@FXML
private GridPane root;
@FXML
private CheckBox unlockAfterStartup;
@Override
public void initialize() {
advancedOptions.managedProperty().bind(advancedOptions.visibleProperty());
@@ -125,6 +140,7 @@ public class UnlockController implements ViewController {
mountName.addEventFilter(KeyEvent.KEY_TYPED, this::filterAlphanumericKeyEvents);
mountName.textProperty().addListener(this::mountNameDidChange);
savePassword.setDisable(!keychainAccess.isPresent());
unlockAfterStartup.disableProperty().bind(savePassword.disabledProperty().or(savePassword.selectedProperty().not()));
if (SystemUtils.IS_OS_WINDOWS) {
winDriveLetter.setConverter(new WinDriveLetterLabelConverter());
} else {
@@ -141,18 +157,17 @@ public class UnlockController implements ViewController {
}
void setVault(Vault vault) {
// TODO overheadhunter refactor
if (this.vault != null) {
this.vault.getVaultSettings().mountAfterUnlock().unbind();
this.vault.getVaultSettings().revealAfterMount().unbind();
}
vaultSubs.unsubscribe();
vaultSubs = Subscription.EMPTY;
// trigger "default" change to refresh key bindings:
unlockButton.setDefaultButton(false);
unlockButton.setDefaultButton(true);
if (vault.equals(this.vault)) {
if (Objects.equals(this.vault, Objects.requireNonNull(vault))) {
return;
}
this.vault = Objects.requireNonNull(vault);
assert vault != null;
this.vault = vault;
passwordField.swipe();
advancedOptions.setVisible(false);
advancedOptionsButton.setText(localization.getString("unlock.button.advancedOptions.show"));
@@ -182,10 +197,14 @@ public class UnlockController implements ViewController {
Arrays.fill(storedPw, ' ');
}
}
mountAfterUnlock.setSelected(this.vault.getVaultSettings().mountAfterUnlock().get());
revealAfterMount.setSelected(this.vault.getVaultSettings().revealAfterMount().get());
this.vault.getVaultSettings().mountAfterUnlock().bind(mountAfterUnlock.selectedProperty());
this.vault.getVaultSettings().revealAfterMount().bind(revealAfterMount.selectedProperty());
VaultSettings settings = vault.getVaultSettings();
unlockAfterStartup.setSelected(savePassword.isSelected() && settings.unlockAfterStartup().get());
mountAfterUnlock.setSelected(settings.mountAfterUnlock().get());
revealAfterMount.setSelected(settings.revealAfterMount().get());
vaultSubs = vaultSubs.and(EasyBind.subscribe(unlockAfterStartup.selectedProperty(), settings.unlockAfterStartup()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(mountAfterUnlock.selectedProperty(), settings.mountAfterUnlock()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(revealAfterMount.selectedProperty(), settings.revealAfterMount()::set));
}
// ****************************************
@@ -212,11 +231,7 @@ public class UnlockController implements ViewController {
}
private void filterAlphanumericKeyEvents(KeyEvent t) {
if (t.getCharacter() == null || t.getCharacter().length() == 0) {
return;
}
char c = CharUtils.toChar(t.getCharacter());
if (!(CharUtils.isAsciiAlphanumeric(c) || c == '_')) {
if (!Strings.isNullOrEmpty(t.getCharacter()) && !ALPHA_NUMERIC_MATCHER.matchesAllOf(t.getCharacter())) {
t.consume();
}
}
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 Sebastian Stenzel
* Copyright (c) 2014, 2017 Sebastian Stenzel
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -8,14 +8,19 @@
******************************************************************************/
package org.cryptomator.ui.controllers;
import static java.lang.String.format;
import java.util.Optional;
import javax.inject.Inject;
import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.model.Vault;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.util.AsyncTaskService;
import org.cryptomator.ui.util.DialogBuilderUtil;
import org.fxmisc.easybind.EasyBind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
@@ -31,6 +36,8 @@ import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
@@ -43,6 +50,8 @@ import javafx.util.Duration;
public class UnlockedController implements ViewController {
private static final Logger LOG = LoggerFactory.getLogger(UnlockedController.class);
private static final int IO_SAMPLING_STEPS = 100;
private static final double IO_SAMPLING_INTERVAL = 0.25;
@@ -109,16 +118,63 @@ public class UnlockedController implements ViewController {
@FXML
private void didClickLockVault(ActionEvent event) {
regularLockVault();
}
private void regularLockVault() {
asyncTaskService.asyncTaskOf(() -> {
vault.get().unmount();
vault.get().lock();
}).onSuccess(() -> {
listener.ifPresent(listener -> listener.didLock(this));
}).onError(Exception.class, () -> {
messageLabel.setText(localization.getString("unlocked.label.unmountFailed"));
LOG.trace("Regular lock succeeded");
}).onError(Exception.class, e -> {
onRegularLockVaultFailed(e);
}).run();
}
private void forcedLockVault() {
asyncTaskService.asyncTaskOf(() -> {
vault.get().unmountForced();
vault.get().lock();
}).onSuccess(() -> {
listener.ifPresent(listener -> listener.didLock(this));
LOG.trace("Forced lock succeeded");
}).onError(Exception.class, e -> {
onForcedLockVaultFailed(e);
}).run();
}
private void onRegularLockVaultFailed(Exception e) {
if (vault.get().supportsForcedUnmount()) {
LOG.trace("Regular unmount failed", e);
Alert confirmDialog = DialogBuilderUtil.buildYesNoDialog( //
format(localization.getString("unlocked.lock.force.confirmation.title"), vault.get().name().getValue()), //
localization.getString("unlocked.lock.force.confirmation.header"), //
localization.getString("unlocked.lock.force.confirmation.content"), //
ButtonType.NO);
Optional<ButtonType> choice = confirmDialog.showAndWait();
if (ButtonType.YES.equals(choice.get())) {
forcedLockVault();
} else {
LOG.trace("Unmount cancelled", e);
}
} else {
LOG.error("Regular unmount failed", e);
showUnmountFailedMessage();
}
}
private void onForcedLockVaultFailed(Exception e) {
LOG.error("Forced unmount failed", e);
showUnmountFailedMessage();
}
private void showUnmountFailedMessage() {
messageLabel.setText(localization.getString("unlocked.label.unmountFailed"));
}
@FXML
private void didClickMoreOptions(ActionEvent event) {
if (moreOptionsMenu.isShowing()) {
@@ -11,11 +11,11 @@ import java.util.Optional;
import javax.inject.Inject;
import org.cryptomator.ui.controls.SecPasswordField;
import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.model.UpgradeStrategies;
import org.cryptomator.ui.model.UpgradeStrategy;
import org.cryptomator.ui.model.UpgradeStrategy.UpgradeFailedException;
import org.cryptomator.ui.model.Vault;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.util.AsyncTaskService;
import org.fxmisc.easybind.EasyBind;
@@ -1,3 +1,8 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.ui.controllers;
import java.net.URL;
@@ -1,3 +1,8 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.ui.controllers;
import static java.lang.annotation.ElementType.METHOD;
@@ -1,3 +1,8 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.ui.controllers;
import java.io.IOException;
@@ -9,7 +14,7 @@ import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import javafx.fxml.FXMLLoader;
@@ -1,3 +1,8 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.ui.controllers;
import dagger.Module;
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 Sebastian Stenzel
* Copyright (c) 2014, 2017 Sebastian Stenzel
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -30,7 +30,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.util.AsyncTaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -119,10 +119,11 @@ public class WelcomeController implements ViewController {
.setConnectionRequestTimeout(5000) //
.setSocketTimeout(5000) //
.build();
String userAgent = String.format("Cryptomator VersionChecker/%s %s %s (%s)", applicationVersion.orElse("SNAPSHOT"), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
HttpClientBuilder httpClientBuilder = HttpClients.custom() //
.disableCookieManagement() //
.setDefaultRequestConfig(requestConfig) //
.setUserAgent("Cryptomator VersionChecker/" + applicationVersion.orElse("SNAPSHOT"));
.setUserAgent(userAgent);
LOG.debug("Checking for updates...");
try (CloseableHttpClient client = httpClientBuilder.build()) {
HttpGet request = new HttpGet("https://api.cryptomator.org/updates/latestVersion.json");
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -20,9 +20,12 @@ import javafx.scene.control.OverrunStyle;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
public class DirectoryListCell extends DraggableListCell<Vault> {
private static final Color UNLOCKED_ICON_COLOR = new Color(0.901, 0.494, 0.133, 1.0);
private final Label statusText = new Label();
private final Label nameText = new Label();
private final Label pathText = new Label();
@@ -45,7 +48,7 @@ public class DirectoryListCell extends DraggableListCell<Vault> {
MonadicBinding<Boolean> optionalItemIsUnlocked = EasyBind.monadic(itemProperty()).flatMap(Vault::unlockedProperty);
statusText.textProperty().bind(optionalItemIsUnlocked.map(this::getStatusIconText));
statusText.textFillProperty().bind(this.textFillProperty());
statusText.textFillProperty().bind(EasyBind.combine(optionalItemIsUnlocked, textFillProperty(), this::getStatusIconColor));
statusText.setMinSize(16.0, 16.0);
statusText.setAlignment(Pos.CENTER);
statusText.getStyleClass().add("fontawesome");
@@ -67,6 +70,14 @@ public class DirectoryListCell extends DraggableListCell<Vault> {
}
}
private Paint getStatusIconColor(Boolean unlockedOrNull, Paint lockedValue) {
if (Boolean.TRUE.equals(unlockedOrNull)) {
return UNLOCKED_ICON_COLOR;
} else {
return lockedValue;
}
}
public void setVaultContextMenu(ContextMenu contextMenu) {
this.vaultContextMenu = contextMenu;
}
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 Sebastian Stenzel
* Copyright (c) 2014, 2017 Sebastian Stenzel
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -3,7 +3,7 @@
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.ui.settings;
package org.cryptomator.ui.l10n;
import java.io.IOException;
import java.io.InputStream;
@@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.ui.model;
import java.nio.CharBuffer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.frontend.webdav.mount.Mounter.CommandFailedException;
import org.cryptomator.keychain.KeychainAccess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class AutoUnlocker {
private static final Logger LOG = LoggerFactory.getLogger(AutoUnlocker.class);
private static final int NAP_TIME_MILLIS = 500;
private final Optional<KeychainAccess> keychainAccess;
private final VaultList vaults;
private final ExecutorService executor;
@Inject
public AutoUnlocker(Optional<KeychainAccess> keychainAccess, VaultList vaults, ExecutorService executor) {
this.keychainAccess = keychainAccess;
this.vaults = vaults;
this.executor = executor;
}
public void unlockAllSilently() {
Collection<Vault> vaultsToUnlock = vaults.stream().filter(this::shouldUnlockAfterStartup).collect(Collectors.toList());
if (keychainAccess.isPresent() && !vaultsToUnlock.isEmpty()) {
executor.submit(() -> unlockAll(vaultsToUnlock));
}
}
private boolean shouldUnlockAfterStartup(Vault vault) {
return vault.getVaultSettings().unlockAfterStartup().get();
}
private void unlockAll(Collection<Vault> vaults) {
try {
Iterator<Vault> iterator = vaults.iterator();
assert iterator.hasNext() : "vaults must not be empty";
unlockSilently(iterator.next());
while (iterator.hasNext()) {
Thread.sleep(NAP_TIME_MILLIS);
unlockSilently(iterator.next());
}
} catch (InterruptedException e) {
LOG.warn("Auto unlock thread interrupted.");
Thread.currentThread().interrupt();
}
}
private void unlockSilently(Vault vault) {
char[] storedPw = keychainAccess.get().loadPassphrase(vault.getId());
if (storedPw == null) {
LOG.warn("No passphrase stored in keychain for vault registered for auto unlocking: {}", vault.getPath());
}
try {
vault.unlock(CharBuffer.wrap(storedPw));
mountSilently(vault);
} catch (CryptoException e) {
LOG.error("Auto unlock failed.", e);
} finally {
Arrays.fill(storedPw, ' ');
}
}
private void mountSilently(Vault unlockedVault) {
if (!unlockedVault.getVaultSettings().mountAfterUnlock().get()) {
return;
}
try {
unlockedVault.mount();
revealSilently(unlockedVault);
} catch (CommandFailedException e) {
LOG.error("Auto unlock succeded, but mounting the drive failed.", e);
}
}
private void revealSilently(Vault mountedVault) {
if (!mountedVault.getVaultSettings().revealAfterMount().get()) {
return;
}
try {
mountedVault.reveal();
} catch (CommandFailedException e) {
LOG.error("Auto unlock succeded, but revealing the drive failed.", e);
}
}
}
@@ -18,7 +18,7 @@ import org.cryptomator.cryptolib.api.CryptorProvider;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.cryptolib.api.KeyFile;
import org.cryptomator.cryptolib.api.UnsupportedVaultFormatException;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -15,7 +15,7 @@ import javax.inject.Singleton;
import org.apache.commons.lang3.StringUtils;
import org.cryptomator.cryptolib.Cryptors;
import org.cryptomator.cryptolib.api.Cryptor;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,7 +28,7 @@ import org.apache.commons.lang3.StringUtils;
import org.cryptomator.cryptolib.Cryptors;
import org.cryptomator.cryptolib.api.Cryptor;
import org.cryptomator.cryptolib.common.MessageDigestSupplier;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -24,7 +24,7 @@ import javax.inject.Singleton;
import org.cryptomator.cryptolib.Cryptors;
import org.cryptomator.cryptolib.api.Cryptor;
import org.cryptomator.cryptolib.api.FileHeader;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -16,16 +16,16 @@ import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.LazyInitializer;
import org.cryptomator.common.Optionals;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystem;
@@ -34,17 +34,18 @@ import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.frontend.webdav.WebDavServer;
import org.cryptomator.frontend.webdav.mount.MountParams;
import org.cryptomator.frontend.webdav.mount.Mounter.CommandFailedException;
import org.cryptomator.frontend.webdav.mount.Mounter.Mount;
import org.cryptomator.frontend.webdav.mount.Mounter.MountParam;
import org.cryptomator.frontend.webdav.mount.Mounter.UnmountOperation;
import org.cryptomator.frontend.webdav.servlet.WebDavServletController;
import org.cryptomator.ui.model.VaultModule.PerVault;
import org.cryptomator.ui.util.DeferredCloser;
import org.fxmisc.easybind.EasyBind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.binding.Binding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
@@ -58,7 +59,6 @@ public class Vault {
private final Settings settings;
private final VaultSettings vaultSettings;
private final WebDavServer server;
private final DeferredCloser closer;
private final BooleanProperty unlocked = new SimpleBooleanProperty();
private final BooleanProperty mounted = new SimpleBooleanProperty();
private final AtomicReference<CryptoFileSystem> cryptoFileSystem = new AtomicReference<>();
@@ -67,18 +67,17 @@ public class Vault {
private Mount mount;
@Inject
Vault(Settings settings, VaultSettings vaultSettings, WebDavServer server, DeferredCloser closer) {
Vault(Settings settings, VaultSettings vaultSettings, WebDavServer server) {
this.settings = settings;
this.vaultSettings = vaultSettings;
this.server = server;
this.closer = closer;
}
// ******************************************************************************
// Commands
// ********************************************************************************/
private CryptoFileSystem getCryptoFileSystem(CharSequence passphrase) throws IOException {
private CryptoFileSystem getCryptoFileSystem(CharSequence passphrase) throws IOException, CryptoException {
return LazyInitializer.initializeLazily(cryptoFileSystem, () -> createCryptoFileSystem(passphrase), IOException.class);
}
@@ -87,9 +86,7 @@ public class Vault {
.withPassphrase(passphrase) //
.withMasterkeyFilename(MASTERKEY_FILENAME) //
.build();
CryptoFileSystem fs = CryptoFileSystemProvider.newFileSystem(getPath(), fsProps);
closer.closeLater(fs);
return fs;
return CryptoFileSystemProvider.newFileSystem(getPath(), fsProps);
}
public void create(CharSequence passphrase) throws IOException {
@@ -101,7 +98,7 @@ public class Vault {
}
}
if (!isValidVaultDirectory()) {
getCryptoFileSystem(passphrase); // implicitly creates a non-existing vault
createCryptoFileSystem(passphrase).close(); // implicitly creates a non-existing vault
} else {
throw new FileAlreadyExistsException(getPath().toString());
}
@@ -127,34 +124,43 @@ public class Vault {
}
}
public synchronized void mount() {
public synchronized void mount() throws CommandFailedException {
if (servlet == null) {
throw new IllegalStateException("Mounting requires unlocked WebDAV servlet.");
}
Map<MountParam, String> mountOptions = new HashMap<>();
mountOptions.put(MountParam.WIN_DRIVE_LETTER, vaultSettings.winDriveLetter().get());
mountOptions.put(MountParam.PREFERRED_GVFS_SCHEME, settings.preferredGvfsScheme().get());
MountParams mountParams = MountParams.create() //
.withWindowsDriveLetter(vaultSettings.winDriveLetter().get()) //
.withPreferredGvfsScheme(settings.preferredGvfsScheme().get()) //
.build();
try {
mount = servlet.mount(mountOptions);
Platform.runLater(() -> {
mounted.set(true);
});
} catch (CommandFailedException e) {
LOG.error("Unable to mount filesystem", e);
}
mount = servlet.mount(mountParams);
Platform.runLater(() -> {
mounted.set(true);
});
}
public synchronized void unmount() throws Exception {
public synchronized void unmount() throws CommandFailedException {
unmount(Function.identity());
}
public synchronized void unmountForced() throws CommandFailedException {
unmount(Optionals.unwrap(Mount::forced));
}
private synchronized void unmount(Function<Mount, ? extends UnmountOperation> unmountOperationChooser) throws CommandFailedException {
if (mount != null) {
mount.unmount();
unmountOperationChooser.apply(mount).unmount();
}
Platform.runLater(() -> {
mounted.set(false);
});
}
public boolean supportsForcedUnmount() {
return mount != null && mount.forced().isPresent();
}
public synchronized void lock() throws Exception {
if (servlet != null) {
servlet.stop();
@@ -168,6 +174,30 @@ public class Vault {
});
}
/**
* Ejects any mounted drives and locks this vault. no-op if this vault is currently locked.
*/
public void prepareForShutdown() {
try {
unmount();
} catch (CommandFailedException e) {
if (supportsForcedUnmount()) {
try {
unmountForced();
} catch (CommandFailedException e1) {
LOG.warn("Failed to force unmount vault.");
}
} else {
LOG.warn("Failed to gracefully unmount vault.");
}
}
try {
lock();
} catch (Exception e) {
LOG.warn("Failed to lock vault.");
}
}
public void reveal() throws CommandFailedException {
if (mount != null) {
mount.reveal();
@@ -178,6 +208,10 @@ public class Vault {
// Getter/Setter
// *******************************************************************************/
public Observable[] observables() {
return new Observable[] {unlocked, mounted};
}
public VaultSettings getVaultSettings() {
return vaultSettings;
}
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -15,12 +15,11 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.ui.model.VaultComponent.Builder;
@Singleton
public class VaultFactory {
private final Builder vaultComponentBuilder;
private final VaultComponent.Builder vaultComponentBuilder;
private final ConcurrentMap<VaultSettings, Vault> vaults = new ConcurrentHashMap<>();
@Inject
@@ -5,8 +5,8 @@
*******************************************************************************/
package org.cryptomator.ui.model;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -14,7 +14,9 @@ import javax.inject.Singleton;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import javafx.collections.ListChangeListener.Change;
import com.google.common.collect.Lists;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.TransformationList;
@@ -59,15 +61,15 @@ public class VaultList extends TransformationList<Vault, VaultSettings> {
}
@Override
protected void sourceChanged(Change<? extends VaultSettings> c) {
protected void sourceChanged(ListChangeListener.Change<? extends VaultSettings> c) {
this.fireChange(new VaultListChange(c));
}
private class VaultListChange extends Change<Vault> {
private class VaultListChange extends ListChangeListener.Change<Vault> {
private final Change<? extends VaultSettings> delegate;
private final ListChangeListener.Change<? extends VaultSettings> delegate;
public VaultListChange(Change<? extends VaultSettings> delegate) {
public VaultListChange(ListChangeListener.Change<? extends VaultSettings> delegate) {
super(VaultList.this);
this.delegate = delegate;
}
@@ -77,6 +79,11 @@ public class VaultList extends TransformationList<Vault, VaultSettings> {
return delegate.next();
}
@Override
public boolean wasUpdated() {
return delegate.wasUpdated();
}
@Override
public void reset() {
delegate.reset();
@@ -94,27 +101,28 @@ public class VaultList extends TransformationList<Vault, VaultSettings> {
@Override
public List<Vault> getRemoved() {
List<Vault> removed = new ArrayList<>();
for (VaultSettings s : delegate.getRemoved()) {
removed.add(vaultFactory.get(s));
}
return removed;
return Lists.transform(delegate.getRemoved(), vaultFactory::get);
}
@Override
public boolean wasPermutated() {
return delegate.wasPermutated();
}
@Override
protected int[] getPermutation() {
if (delegate.wasPermutated()) {
int len = getTo() - getFrom();
int[] permutations = new int[len];
for (int i = 0; i < len; i++) {
permutations[i] = getPermutation(i);
}
return permutations;
return IntStream.range(getFrom(), getTo()).map(delegate::getPermutation).toArray();
} else {
return new int[0];
}
}
@Override
public String toString() {
return delegate.toString();
}
}
}
@@ -49,7 +49,7 @@ public class AsyncTaskService {
private ConsumerThrowingException<ResultType, ?> successHandler = value -> {
};
private List<ErrorHandler<Throwable>> errorHandlers = new ArrayList<>();
private final List<ErrorHandler<Throwable>> errorHandlers = new ArrayList<>();
private RunnableThrowingException<?> finallyHandler = () -> {
};
@@ -1,37 +0,0 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 cryptomator.org
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
* Contributors:
* Tillmann Gaida - initial implementation
******************************************************************************/
package org.cryptomator.ui.util;
import java.util.Optional;
/**
* Wrapper around an object, which should be closed later - explicitly or by a
* {@link DeferredCloser}. The wrapped object can be accessed as long as the
* resource has not been closed.
*
* @author Tillmann Gaida
*
* @param <T>
* any type
*/
public interface DeferredClosable<T> extends AutoCloseable {
/**
* Returns the wrapped Object.
*
* @return empty if the object has been closed.
*/
public Optional<T> get();
/**
* @return an empty object.
*/
public static <T> DeferredClosable<T> empty() {
return DeferredCloser.empty();
}
}
@@ -1,136 +0,0 @@
/*******************************************************************************
* Copyright (c) 2014, 2016 cryptomator.org
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
* Contributors:
* Tillmann Gaida - initial implementation
******************************************************************************/
package org.cryptomator.ui.util;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicLong;
import org.cryptomator.common.ConsumerThrowingException;
import com.google.common.annotations.VisibleForTesting;
/**
* <p>
* Tries to bring open-close symmetry in contexts where the resource outlives
* the current scope by introducing a manager, which closes the resources if
* they haven't been closed before.
* </p>
*
* <p>
* If you have a {@link DeferredCloser} instance present, call
* {@link #closeLater(Object, ConsumerThrowingException)} immediately after you have opened the
* resource and return a resource handle. If {@link #close()} is called, the
* resource will be closed. Calling {@link DeferredClosable#close()} on the resource
* handle will also close the resource and prevent a second closing by
* {@link #close()}.
* </p>
*
* @author Tillmann Gaida
*/
public class DeferredCloser implements AutoCloseable {
@VisibleForTesting
final Map<Long, ManagedResource<?>> cleanups = new ConcurrentSkipListMap<>();
@VisibleForTesting
final AtomicLong counter = new AtomicLong();
private class ManagedResource<T> implements DeferredClosable<T> {
private final long number = counter.incrementAndGet();
private final T object;
private final ConsumerThrowingException<T, Exception> closer;
private boolean closed = false;
public ManagedResource(T object, ConsumerThrowingException<T, Exception> closer) {
super();
this.object = Objects.requireNonNull(object);
this.closer = Objects.requireNonNull(closer);
}
@Override
public synchronized void close() throws Exception {
closer.accept(object);
cleanups.remove(number);
closed = true;
}
@Override
public Optional<T> get() throws IllegalStateException {
if (closed) {
return Optional.empty();
} else {
return Optional.of(object);
}
}
}
/**
* Closes all added objects which have not been closed before and releases references.
*/
@Override
public void close() throws ExecutionException {
ExecutionException exception = null;
for (Iterator<ManagedResource<?>> iterator = cleanups.values().iterator(); iterator.hasNext();) {
final ManagedResource<?> closableProvider = iterator.next();
try {
closableProvider.close();
iterator.remove();
} catch (Exception e) {
if (exception == null) {
exception = new ExecutionException(e);
} else {
exception.addSuppressed(e);
}
}
}
if (exception != null) {
throw exception;
}
}
public <T> DeferredClosable<T> closeLater(T object, ConsumerThrowingException<T, Exception> closer) {
Objects.requireNonNull(object);
Objects.requireNonNull(closer);
final ManagedResource<T> resource = new ManagedResource<T>(object, closer);
cleanups.put(resource.number, resource);
return resource;
}
public <T extends AutoCloseable> DeferredClosable<T> closeLater(T object) {
Objects.requireNonNull(object);
final ManagedResource<T> resource = new ManagedResource<T>(object, AutoCloseable::close);
cleanups.put(resource.number, resource);
return resource;
}
private static final EmptyResource<?> EMPTY_RESOURCE = new EmptyResource<>();
@SuppressWarnings("unchecked")
public static <T> DeferredClosable<T> empty() {
return (DeferredClosable<T>) EMPTY_RESOURCE;
}
static class EmptyResource<T> implements DeferredClosable<T> {
@Override
public Optional<T> get() {
return Optional.empty();
}
@Override
public void close() {
}
}
}
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -34,11 +34,15 @@ public class DialogBuilderUtil {
return buildDialog(title, header, content, Alert.AlertType.CONFIRMATION, defaultButton);
}
private static Alert buildDialog(String title, String header, String content, Alert.AlertType type, ButtonType defaultButton) {
public static Alert buildYesNoDialog(String title, String header, String content, ButtonType defaultButton) {
return buildDialog(title, header, content, Alert.AlertType.CONFIRMATION, defaultButton, ButtonType.YES, ButtonType.NO);
}
private static Alert buildDialog(String title, String header, String content, Alert.AlertType type, ButtonType defaultButton, ButtonType... buttons) {
Text contentText = new Text(content);
contentText.setWrappingWidth(360.0);
Alert alert = new Alert(type);
Alert alert = new Alert(type, content, buttons);
alert.setTitle(title);
alert.setHeaderText(header);
alert.getDialogPane().setContent(contentText);
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* This file is licensed under the terms of the MIT license.
* See the LICENSE.txt file for more info.
*
@@ -15,7 +15,7 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.apache.commons.lang3.StringUtils;
import org.cryptomator.ui.settings.Localization;
import org.cryptomator.ui.l10n.Localization;
import com.nulabinc.zxcvbn.Zxcvbn;
@@ -53,7 +53,7 @@
<ChoiceBox GridPane.rowIndex="3" GridPane.columnIndex="1" fx:id="prefGvfsScheme" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<!-- Row 4 -->
<Label GridPane.rowIndex="4" GridPane.columnIndex="0" fx:id="debugModeLabel" text="%settings.debugMode.label" cacheShape="true" cache="true" />
<Label GridPane.rowIndex="4" GridPane.columnIndex="0" text="%settings.debugMode.label" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="4" GridPane.columnIndex="1" fx:id="debugModeCheckbox" cacheShape="true" cache="true" />
</children>
+10 -10
View File
@@ -68,24 +68,24 @@
</HBox>
<!-- Row 3.1 -->
<Label GridPane.rowIndex="1" GridPane.columnIndex="0" text="%unlock.label.savePassword" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="1" GridPane.columnIndex="1" fx:id="savePassword" onAction="#didClickSavePasswordCheckbox" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="1" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="savePassword" text="%unlock.label.savePassword" onAction="#didClickSavePasswordCheckbox" cacheShape="true" cache="true" />
<!-- Row 3.2 -->
<Label GridPane.rowIndex="2" GridPane.columnIndex="0" text="%unlock.label.mountAfterUnlock" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="2" GridPane.columnIndex="1" fx:id="mountAfterUnlock" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="2" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="unlockAfterStartup" text="%unlock.label.unlockAfterStartup" cacheShape="true" cache="true" />
<!-- Row 3.3 -->
<Label GridPane.rowIndex="3" GridPane.columnIndex="0" text="%unlock.label.mountName" cacheShape="true" cache="true" />
<TextField GridPane.rowIndex="3" GridPane.columnIndex="1" fx:id="mountName" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="3" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="mountAfterUnlock" text="%unlock.label.mountAfterUnlock" cacheShape="true" cache="true" />
<!-- Row 3.4 -->
<Label GridPane.rowIndex="4" GridPane.columnIndex="0" text="%unlock.label.revealAfterMount" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="4" GridPane.columnIndex="1" fx:id="revealAfterMount" cacheShape="true" cache="true" />
<Label GridPane.rowIndex="4" GridPane.columnIndex="0" text="%unlock.label.mountName" cacheShape="true" cache="true" />
<TextField GridPane.rowIndex="4" GridPane.columnIndex="1" fx:id="mountName" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<!-- Row 3.5 -->
<Label GridPane.rowIndex="5" GridPane.columnIndex="0" fx:id="winDriveLetterLabel" text="%unlock.label.winDriveLetter" cacheShape="true" cache="true" />
<ChoiceBox GridPane.rowIndex="5" GridPane.columnIndex="1" fx:id="winDriveLetter" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="5" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="revealAfterMount" text="%unlock.label.revealAfterMount" cacheShape="true" cache="true" />
<!-- Row 3.6 -->
<Label GridPane.rowIndex="6" GridPane.columnIndex="0" fx:id="winDriveLetterLabel" text="%unlock.label.winDriveLetter" cacheShape="true" cache="true" />
<ChoiceBox GridPane.rowIndex="6" GridPane.columnIndex="1" fx:id="winDriveLetter" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
</GridPane>
<!-- Row 4 -->
@@ -0,0 +1,97 @@
app.name = كريبتوماتور
# main.fxml
main.emptyListInstructions = اضغط هنا لاضافة محفظة
main.directoryList.contextMenu.remove = ازل من القائمة
main.directoryList.contextMenu.changePassword = تغيير كلمة المرور
main.addDirectory.contextMenu.new = انشاء محفظة جديدة
main.addDirectory.contextMenu.open = افتح محفظة موجوده
# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking = فحص التحديثات
welcome.newVersionMessage = يمكنك الان تحميل الاصدار رقم %1$s\nالاصدار الحالي %2$s
# initialize.fxml
initialize.label.password = كلمة المرور
initialize.label.retypePassword = اعد كتابة كلمة المرور
initialize.button.ok = انشاء محفظة
initialize.messageLabel.alreadyInitialized = لقد تم تهيئة المحفظة
initialize.messageLabel.initializationFailed = تعذر تهيئة المحفظة . يرجي مراجعة ملف التفاصيل ( log file )
# notfound.fxml
notfound.label = تعذر العثور علي المحفظه , هل قمت بنقلها ؟
# upgrade.fxml
upgrade.button = ترقية المحفظة
upgrade.version3dropBundleExtension.msg = This vault needs to be migrated to a newer format.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding.
upgrade.version3dropBundleExtension.err.alreadyExists = Automatic migration failed.\n"%s" already exists.
# unlock.fxml
unlock.label.password = كلمة المرور
unlock.label.mountName = Drive Name
unlock.label.winDriveLetter = Drive Letter
unlock.label.downloadsPageLink = جميع اصدارات كريبتوماتور
unlock.label.advancedHeading = خيارات اضافية
unlock.button.unlock = افتح المحفظة
unlock.button.advancedOptions.show = خيارات اكثر
unlock.button.advancedOptions.hide = خيارات اقل
unlock.choicebox.winDriveLetter.auto = دخول تلقائي
unlock.errorMessage.wrongPassword = كلمة مرور خاطئة
unlock.errorMessage.mountingFailed = فشل الدخول الي المحفظة . يرجي مراجعة ملف التفاصيل ( log file )
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = محفظة غير مدعومة . هذه المحفظة تم انشاؤها بواسطة اصدار اقدم من كريبتوماتور
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = محفظة غير مدعومة . هذه المحفظة تم انشاؤها بواسطة اصدار احدث من كريبتوماتور
unlock.messageLabel.startServerFailed = Starting WebDAV server failed.
# change_password.fxml
changePassword.label.oldPassword = كلمة المرور القديمة
changePassword.label.newPassword = كلمة المرور الجديدة
changePassword.label.retypePassword = اعد كتابة كلمة المرور
changePassword.label.downloadsPageLink = جميع اصدارات كريبتوماتور
changePassword.button.change = تغيير كلمة المرور
changePassword.errorMessage.wrongPassword = كلمة مرور خاطئة
changePassword.errorMessage.decryptionFailed = فشل فك التشفير
# unlocked.fxml
unlocked.button.lock = اغلاق المحفظة
unlocked.moreOptions.reveal = Reveal Drive
unlocked.moreOptions.copyUrl = نسخ رابط ويب داف ( WebDAV )
unlocked.label.revealFailed = Command failed
unlocked.label.unmountFailed = Ejecting drive failed
unlocked.label.statsEncrypted = مشفر
unlocked.label.statsDecrypted = غير مشفر
unlocked.ioGraph.yAxis.label = Throughput (MiB/s)
# settings.fxml
settings.version.label = الاصدار %s
settings.checkForUpdates.label = افحص التحديثات
settings.port.label = منفذ ويب داف ( WebDAV )
settings.port.prompt = 0 \= Choose automatically
settings.useipv6.label = Use IPv6 Literal
settings.requiresRestartLabel = * Cryptomator needs to restart
# tray icon
tray.menu.open = فتح
tray.menu.quit = اغلاق
tray.infoMsg.title = لا يزال مستخدم
tray.infoMsg.msg = Cryptomator is still alive. Quit it from the tray icon.
tray.infoMsg.msg.osx = Cryptomator is still alive. Quit it from the menu bar icon.
initialize.messageLabel.passwordStrength.0 = ضعيف جدا
initialize.messageLabel.passwordStrength.1 = ضعيف
initialize.messageLabel.passwordStrength.2 = عادي
initialize.messageLabel.passwordStrength.3 = قوي
initialize.messageLabel.passwordStrength.4 = قوي جدا
initialize.label.doNotForget = هام \: في حالة نسيانك لكلمة المرور , لا يوجد طريقة لاستعادتها مره اخري
main.directoryList.remove.confirmation.title = ازالة المحفظة
main.directoryList.remove.confirmation.header = هل تريد فعلا ازالة المحفظة ؟
main.directoryList.remove.confirmation.content = The vault will only be removed from the list. To permanently delete it, please delete the files from your filesystem.
upgrade.version3to4.msg = This vault needs to be migrated to a newer format.\nEncrypted folder names will be updated.\nPlease make sure synchronization has finished before proceeding.
upgrade.version3to4.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.prefGvfsScheme.label = WebDAV Scheme
# upgrade.fxml
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
initialize.messageLabel.notEmpty = المحفظة غير فارغة
unlock.label.savePassword = حفظ كلمة المرور
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed
unlock.savePassword.delete.confirmation.title = حذف كلمة المرور المحفوظة
unlock.savePassword.delete.confirmation.header = Do you really want to delete the saved password of this vault?
unlock.savePassword.delete.confirmation.content = The saved password of this vault will be immediately deleted from your system keychain. If you'd like to save your password again, you'd have to unlock your vault with the "Save password" option enabled.
settings.debugMode.label = Debug Mode *
upgrade.version3dropBundleExtension.title = Vault Version 3 Upgrade (Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 to 4 Upgrade
upgrade.version4to5.title = Vault Version 4 to 5 Upgrade
upgrade.version4to5.msg = This vault needs to be migrated to a newer format.\nEncrypted files will be updated.\nPlease make sure synchronization has finished before proceeding.\n\nNote\: Modification date of all files will be changed to the current date/time in the process.
upgrade.version4to5.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.port.apply = Apply
unlock.label.mountAfterUnlock = Mount Drive
unlock.label.revealAfterMount = Reveal Drive
@@ -0,0 +1,97 @@
app.name = Криптоматор
# main.fxml
main.emptyListInstructions = Натиснете тук за да добавите сейф
main.directoryList.contextMenu.remove = Премахнете от листа
main.directoryList.contextMenu.changePassword = Сменете парола
main.addDirectory.contextMenu.new = Създайте нов сейф
main.addDirectory.contextMenu.open = Отворете съществуващ сейф
# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking = Проверете за нови версии
welcome.newVersionMessage = Version %1$s can be downloaded.\nThis is %2$s.
# initialize.fxml
initialize.label.password = Парола
initialize.label.retypePassword = Повторете Паролата
initialize.button.ok = Създайте Сейф
initialize.messageLabel.alreadyInitialized = Сейфа е вече активен
initialize.messageLabel.initializationFailed = Неуспешно активиране на сейф. Проверете лог файловете за повече информация.
# notfound.fxml
notfound.label = Сейфа не може да бъде намерен. Може би е бил преместен?
# upgrade.fxml
upgrade.button = Обновете версията на Сейф
upgrade.version3dropBundleExtension.msg = This vault needs to be migrated to a newer format.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding.
upgrade.version3dropBundleExtension.err.alreadyExists = Автоматичната миграция е неуспешна. "%s" вече съществува.
# unlock.fxml
unlock.label.password = Парола
unlock.label.mountName = Име на диск
unlock.label.winDriveLetter = Инициали на диск
unlock.label.downloadsPageLink = Покажи всички версии на Криптоматор
unlock.label.advancedHeading = Опции за напреднали
unlock.button.unlock = Отключи Сейф
unlock.button.advancedOptions.show = Покажи повече опции
unlock.button.advancedOptions.hide = Покажи по-малко опции
unlock.choicebox.winDriveLetter.auto = Автоматично наименование на Диска
unlock.errorMessage.wrongPassword = Неправилна парола
unlock.errorMessage.mountingFailed = Неуспешно активиране на диска. За повече информация вижте лог файла.
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Неподържана версия. Този сейф е бил създаден със стара версия на Криптоматор.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Неподържана версия. Този сейф е бил създаден с по-нова версия на Криптоматор.
unlock.messageLabel.startServerFailed = Неуспешно стартиране на WebDAV сървъра.
# change_password.fxml
changePassword.label.oldPassword = Стара парола
changePassword.label.newPassword = Нова парола
changePassword.label.retypePassword = Повторете паролата
changePassword.label.downloadsPageLink = All Cryptomator versions
changePassword.button.change = Смени паролата
changePassword.errorMessage.wrongPassword = Неправилна парола
changePassword.errorMessage.decryptionFailed = Неуспешно декриптиране
# unlocked.fxml
unlocked.button.lock = Заключи Сейфа
unlocked.moreOptions.reveal = Покажи
unlocked.moreOptions.copyUrl = Copy WebDAV URL
unlocked.label.revealFailed = Командата е неуспешна
unlocked.label.unmountFailed = Ejecting drive failed
unlocked.label.statsEncrypted = encrypted
unlocked.label.statsDecrypted = decrypted
unlocked.ioGraph.yAxis.label = Throughput (MiB/s)
# settings.fxml
settings.version.label = Version %s
settings.checkForUpdates.label = Check for Updates
settings.port.label = WebDAV Port
settings.port.prompt = 0 \= Choose automatically
settings.useipv6.label = Use IPv6 Literal
settings.requiresRestartLabel = * Cryptomator needs to restart
# tray icon
tray.menu.open = Open
tray.menu.quit = Quit
tray.infoMsg.title = Still Running
tray.infoMsg.msg = Cryptomator is still alive. Quit it from the tray icon.
tray.infoMsg.msg.osx = Cryptomator is still alive. Quit it from the menu bar icon.
initialize.messageLabel.passwordStrength.0 = Very weak
initialize.messageLabel.passwordStrength.1 = Weak
initialize.messageLabel.passwordStrength.2 = Fair
initialize.messageLabel.passwordStrength.3 = Strong
initialize.messageLabel.passwordStrength.4 = Very strong
initialize.label.doNotForget = IMPORTANT\: If you forget your password, there is no way to recover your data.
main.directoryList.remove.confirmation.title = Remove Vault
main.directoryList.remove.confirmation.header = Do you really want to remove this vault?
main.directoryList.remove.confirmation.content = The vault will only be removed from the list. To permanently delete it, please delete the files from your filesystem.
upgrade.version3to4.msg = This vault needs to be migrated to a newer format.\nEncrypted folder names will be updated.\nPlease make sure synchronization has finished before proceeding.
upgrade.version3to4.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.prefGvfsScheme.label = WebDAV Scheme
# upgrade.fxml
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
initialize.messageLabel.notEmpty = Vault not empty
unlock.label.savePassword = Save Password
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed
unlock.savePassword.delete.confirmation.title = Delete Saved Password
unlock.savePassword.delete.confirmation.header = Do you really want to delete the saved password of this vault?
unlock.savePassword.delete.confirmation.content = The saved password of this vault will be immediately deleted from your system keychain. If you'd like to save your password again, you'd have to unlock your vault with the "Save password" option enabled.
settings.debugMode.label = Debug Mode *
upgrade.version3dropBundleExtension.title = Vault Version 3 Upgrade (Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 to 4 Upgrade
upgrade.version4to5.title = Vault Version 4 to 5 Upgrade
upgrade.version4to5.msg = This vault needs to be migrated to a newer format.\nEncrypted files will be updated.\nPlease make sure synchronization has finished before proceeding.\n\nNote\: Modification date of all files will be changed to the current date/time in the process.
upgrade.version4to5.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.port.apply = Apply
unlock.label.mountAfterUnlock = Mount Drive
unlock.label.revealAfterMount = Reveal Drive
@@ -0,0 +1,97 @@
app.name = Cryptomator
# main.fxml
main.emptyListInstructions = Tryk her for at tilføje en ny Vault
main.directoryList.contextMenu.remove = Fjern fra listen
main.directoryList.contextMenu.changePassword = Skift adgangskode
main.addDirectory.contextMenu.new = Opret ny Vault
main.addDirectory.contextMenu.open = Åben en eksisterende Vault
# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking = Tjek for opdateringer
welcome.newVersionMessage = Version %1$s kan nu hentes.\nDette er %2$s.
# initialize.fxml
initialize.label.password = Adgangskode
initialize.label.retypePassword = Gentag Adgangskode
initialize.button.ok = Opret Vault
initialize.messageLabel.alreadyInitialized = Vault er allerede initialiseret
initialize.messageLabel.initializationFailed = Kunne ikke initialisere Vault. Se logfilen for yderligere detaljer.
# notfound.fxml
notfound.label = Vault'en kunne ikke findes. Er den blevet flyttet?
# upgrade.fxml
upgrade.button = Opgradér Vault
upgrade.version3dropBundleExtension.msg = Denne Vault skal migreres til et nyere format.\n"%1$s" vil blive omdøbt til "%2$s".\nVent venligst til al synkronisering er gennemført, inden du fortsætter.
upgrade.version3dropBundleExtension.err.alreadyExists = Automatisk migrering fejlede.\n"%s" eksisterer allerede.
# unlock.fxml
unlock.label.password = Adgangskode
unlock.label.mountName = Drev navn
unlock.label.winDriveLetter = Drev bogstav
unlock.label.downloadsPageLink = Alle Cryptomator versioner
unlock.label.advancedHeading = Avancerede Indstillinger
unlock.button.unlock = Lås op for Vault
unlock.button.advancedOptions.show = Flere valgmuligheder
unlock.button.advancedOptions.hide = Færre valgmuligheder
unlock.choicebox.winDriveLetter.auto = Tildel automatisk
unlock.errorMessage.wrongPassword = Forkert adgangskode
unlock.errorMessage.mountingFailed = Montering fejlede. Se logfilen for yderligere detaljer.
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Ikke-understøttet Vault. Denne Vault er blevet oprettet med en ældre version af Cryptomator.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Ikke-understøttet Vault. Denne Vault er blevet oprettet med en nyere version af Cryptomator.
unlock.messageLabel.startServerFailed = Kunne ikke starte WebDAV server.
# change_password.fxml
changePassword.label.oldPassword = Gammel adgangskode
changePassword.label.newPassword = Ny adgangskode
changePassword.label.retypePassword = Gentag adgangskode
changePassword.label.downloadsPageLink = Alle Cryptomator versioner
changePassword.button.change = Skift adgangskode
changePassword.errorMessage.wrongPassword = Forkert adgangskode
changePassword.errorMessage.decryptionFailed = Dekryptering fejlede
# unlocked.fxml
unlocked.button.lock = Lås Vault
unlocked.moreOptions.reveal = Vis drev
unlocked.moreOptions.copyUrl = Kopier WebDAV URL
unlocked.label.revealFailed = Kommando fejlede
unlocked.label.unmountFailed = Afmontering af drev fejlede
unlocked.label.statsEncrypted = Krypteret
unlocked.label.statsDecrypted = Dekrypteret
unlocked.ioGraph.yAxis.label = Throughput (MiB/s)
# settings.fxml
settings.version.label = Version %s
settings.checkForUpdates.label = Tjek for opdateringer
settings.port.label = WebDAV Port
settings.port.prompt = 0 \= Vælg automatisk
settings.useipv6.label = Brug IPv6 adresse
settings.requiresRestartLabel = * Cryptomator skal genstartes
# tray icon
tray.menu.open = Åbn
tray.menu.quit = Afslut
tray.infoMsg.title = Kører Stadig
tray.infoMsg.msg = Cryptomator kører stadig. Afslut programmet fra tray-ikonet.
tray.infoMsg.msg.osx = Cryptomator kører stadig. Afslut programmet fra menu-baren.
initialize.messageLabel.passwordStrength.0 = Meget svag
initialize.messageLabel.passwordStrength.1 = Svag
initialize.messageLabel.passwordStrength.2 = Mellem
initialize.messageLabel.passwordStrength.3 = Stærk
initialize.messageLabel.passwordStrength.4 = Meget stærk
initialize.label.doNotForget = VIGTIGT\: Hvis du glemmer dit password, er der ingen måde hvorpå data kan genskabes.
main.directoryList.remove.confirmation.title = Slet Vault
main.directoryList.remove.confirmation.header = Er du sikker på at du vil slette denne Vault?
main.directoryList.remove.confirmation.content = Valgte Vault vil kun blive slettet fra listen. For at slette denne permanent, skal du slette filerne fra dit filsystem.
upgrade.version3to4.msg = Denne Vault skal migreres til et nyere format.\nDe krypterede foldernavne vil blive opdateret.\nVent venligst til al synkronisering er gennemført, inden du fortsætter.
upgrade.version3to4.err.io = Migrering fejlede pga. en I/O fejl. Se logfilen for yderligere detaljer.
settings.prefGvfsScheme.label = WebDAV Scheme
# upgrade.fxml
upgrade.confirmation.label = Ja, jeg har sikret mig at al synkronisering er gennemført.
initialize.messageLabel.notEmpty = Vault er ikke tom
unlock.label.savePassword = Gem adgangskode
unlock.errorMessage.unauthenticVersionMac = Kunne ikke autentificere versions-MAC
unlocked.label.mountFailed = Montering af drev fejlede
unlock.savePassword.delete.confirmation.title = Slet gemt adgangskode
unlock.savePassword.delete.confirmation.header = Er du sikker på at du vil slette den til Vault'en gemte adgangskode?
unlock.savePassword.delete.confirmation.content = Den til Vault'en gemte adgangskode vil blive slettet fra dit systems keychain med øjeblikkelig virkning. Hvis du vil gemme din adgangskode på ny, skal du låse din Vault op med indstillingen "Gem adgangskode" slået til.
settings.debugMode.label = Debug Tilstand *
upgrade.version3dropBundleExtension.title = Vault Version 3 Opgradering (Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 til 4 Opgradering
upgrade.version4to5.title = Vault Version 4 til 5 Opgradering
upgrade.version4to5.msg = Denne Vault skal migreres til et nyere format.\nDe krypterede filer vil blive opdateret.\nVent venligst til al synkronisering er gennemført, inden du fortsætter.\n\nNote\: Denne proces vil påvirke ændringsdato og -tidspunkt for samtlige filer.
upgrade.version4to5.err.io = Migrering fejlede pga. en I/O fejl. Se logfilen for yderligere detaljer.
settings.port.apply = Gem
unlock.label.mountAfterUnlock = Monter drev
unlock.label.revealAfterMount = Vis drev
@@ -52,12 +52,6 @@ unlocked.label.unmountFailed = Trennen des Laufwerks fehlgeschlagen
unlocked.label.statsEncrypted = verschlüsselt
unlocked.label.statsDecrypted = entschlüsselt
unlocked.ioGraph.yAxis.label = Durchsatz (MiB/s)
# mac_warnings.fxml
macWarnings.windowTitle = Achtung - Kompromittierte Datei in %s
# "potentially detected" or "potentially malicious"?
macWarnings.message = Cryptomator hat möglicherweise unerlaubte Veränderungen in den folgenden Dateien erkannt\:
macWarnings.moreInformationButton = Mehr erfahren
macWarnings.whitelistButton = Trotzdem entschlüsseln
# settings.fxml
settings.version.label = Version %s
settings.checkForUpdates.label = Auf Updates prüfen
@@ -97,4 +91,7 @@ upgrade.version3dropBundleExtension.title = Upgrade Tresor-Version 3 (Entfall de
upgrade.version3to4.title = Upgrade Tresor-Version 3 zu 4
upgrade.version4to5.title = Upgrade Tresor-Version 4 zu 5
upgrade.version4to5.msg = Dieser Tresor muss auf ein neueres Format aktualisiert werden.\nVerschlüsselte Dateien werden dabei aktualisiert.\nStellen Sie bitte sicher, dass derzeit keine Synchronisation stattfindet.\n\nHinweis\: Beim Upgrade wird das Änderungsdatum aller Dateien auf das aktuelle Datum geändert.
upgrade.version4to5.err.io = Migration aufgrund eines I/O-Fehlers fehlgeschlagen.\nWeitere Informationen in der Log-Datei.
upgrade.version4to5.err.io = Migration aufgrund eines I/O-Fehlers fehlgeschlagen.\nWeitere Informationen in der Log-Datei.
settings.port.apply = Anwenden
unlock.label.mountAfterUnlock = Laufwerk verbinden
unlock.label.revealAfterMount = Laufwerk anzeigen
@@ -59,6 +59,7 @@ unlock.label.password=Password
unlock.label.savePassword=Save Password
unlock.label.mountAfterUnlock=Mount Drive
unlock.label.mountName=Drive Name
unlock.label.unlockAfterStartup=Auto-Unlock on Start (Experimental)
unlock.label.revealAfterMount=Reveal Drive
unlock.label.winDriveLetter=Drive Letter
unlock.label.downloadsPageLink=All Cryptomator versions
@@ -96,6 +97,9 @@ unlocked.label.unmountFailed=Ejecting drive failed
unlocked.label.statsEncrypted=encrypted
unlocked.label.statsDecrypted=decrypted
unlocked.ioGraph.yAxis.label=Throughput (MiB/s)
unlocked.lock.force.confirmation.title=Locking of %1$s failed
unlocked.lock.force.confirmation.header=Do you want to force locking?
unlocked.lock.force.confirmation.content=This may be because other programs are still accessing files in the vault or because some other problem occurred.\n\nPrograms still accessing the files may not work correctly and data not already written by those programs may be lost.
# settings.fxml
settings.version.label=Version %s
+43 -45
View File
@@ -1,19 +1,19 @@
app.name = Cryptomator
# main.fxml
main.emptyListInstructions = Clic aquí para añadir una caja fuerte
main.emptyListInstructions = Haz clic aquí para añadir una caja fuerte
# should it be imperative?
main.directoryList.contextMenu.remove = Eliminar de la lista
main.directoryList.contextMenu.changePassword = Cambiar la contraseña
main.addDirectory.contextMenu.new = Crear una nueva caja fuerte
main.addDirectory.contextMenu.open = Abrir una caja fuerte existente
# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking = Chequando por actualizaciónes...
welcome.newVersionMessage = Se puede bajar version %1$s.\nEste es %2$s.
welcome.checkForUpdates.label.currentlyChecking = Comprobando actualizaciones...
welcome.newVersionMessage = La versión %1$s está disponible para descargar.\nLa versión actual es %2$s.
# initialize.fxml
initialize.label.password = Contraseña
initialize.label.retypePassword = Reintroduzca contraseña
initialize.label.retypePassword = Repetir contraseña
initialize.button.ok = Crear caja fuerte
initialize.messageLabel.alreadyInitialized = Caja fuerte ya está inicializado
initialize.messageLabel.alreadyInitialized = La caja fuerte ya está inicializada
initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles.
# notfound.fxml
notfound.label = No se pudo encontrar la caja fuerte. Se movió a otro lugar?
@@ -23,48 +23,43 @@ upgrade.version3dropBundleExtension.msg = Este caja fuerte se debe actualizar a
upgrade.version3dropBundleExtension.err.alreadyExists = Migración automática ha fallado.\n"%s" ya existe.
# unlock.fxml
unlock.label.password = Contraseña
unlock.label.mountName = Nombre del disco
unlock.label.winDriveLetter = Letra del disco
unlock.label.mountName = Nombre de la unidad
unlock.label.winDriveLetter = Letra de la unidad
unlock.label.downloadsPageLink = Todas las versiones de Cryptomator
unlock.label.advancedHeading = Opciones avanzadas
unlock.button.unlock = Abrir caja fuerte
unlock.button.unlock = Desbloquear caja fuerte
unlock.button.advancedOptions.show = Más opciones
unlock.button.advancedOptions.hide = Menos opciones
unlock.choicebox.winDriveLetter.auto = Asignar automáticamente
unlock.errorMessage.wrongPassword = Contraseña incorrecta
unlock.errorMessage.mountingFailed = Monteo ha fallado. Ver archivo del registro para detalles.
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versión pasada de Cryptomator.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versión nueva de Cryptomator.
unlock.errorMessage.mountingFailed = El montaje ha fallado. Ver archivo del registro para detalles.
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte no soportada. Ésta caja se ha creado con una versión anterior de Cryptomator.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte no soportada. Ésta caja se ha creado con una versión nueva de Cryptomator.
unlock.messageLabel.startServerFailed = Iniciación del servidor de WebDAV ha fallado.
# change_password.fxml
changePassword.label.oldPassword = Contraseña anterior
changePassword.label.oldPassword = Contraseña antigua
# Can also use "current password" = "contraseña actual"
changePassword.label.newPassword = Nueva contraseña
changePassword.label.retypePassword = Reintroduzca contraseña
changePassword.label.retypePassword = Repetir contraseña
changePassword.label.downloadsPageLink = Todas las versiones de Cryptomator
changePassword.button.change = Cambiar contraseña
changePassword.errorMessage.wrongPassword = Contraseña incorrecta
changePassword.errorMessage.decryptionFailed = Decifración ha fallado
# unlocked.fxml
unlocked.button.lock = Encerrar caja fuerte
unlocked.moreOptions.reveal = Mostrar disco
unlocked.moreOptions.reveal = Revelar unidad
unlocked.moreOptions.copyUrl = Copiar URL de WebDAV
unlocked.label.revealFailed = Comando ha fallado
unlocked.label.unmountFailed = Expulsar el disco ha fallado
unlocked.label.statsEncrypted = cifrado
unlocked.label.statsDecrypted = decifrado
unlocked.ioGraph.yAxis.label = Procesamiento (MiB/s)
# mac_warnings.fxml
macWarnings.windowTitle = Peligro - archivo corrupto en %s
macWarnings.message = Cryptomator ha detectado corrupciones malciosas en los seguientes archivos\:
macWarnings.moreInformationButton = Aprende más
macWarnings.whitelistButton = Decifrar selecionado de todos modos
# settings.fxml
settings.version.label = Version %s
settings.checkForUpdates.label = Chequear por actualizaciones
settings.port.label = Puerta de WebDAV *
settings.port.prompt = 0 \= Elige automáticamente
settings.useipv6.label = Usa literal de IPv6
settings.version.label = Versión %s
settings.checkForUpdates.label = Comprobar actualizaciones
settings.port.label = Puerto WebDAV
settings.port.prompt = 0 \= Elegir automáticamente
settings.useipv6.label = Usar IPv6 literal
settings.requiresRestartLabel = * Cryptomator se necesita reiniciar
# tray icon
tray.menu.open = Abrir
@@ -72,31 +67,34 @@ tray.menu.quit = Salir
tray.infoMsg.title = Todavía en ejecución
tray.infoMsg.msg = Cryptomator todavía esta en ejecución. Para salir usa el icono del tray.
tray.infoMsg.msg.osx = Cryptomator todavía esta en ejecución. Para salir usa el icono de la barra del menú.
initialize.messageLabel.passwordStrength.0 = muy débil
initialize.messageLabel.passwordStrength.1 = débil
initialize.messageLabel.passwordStrength.2 = suficiente
initialize.messageLabel.passwordStrength.3 = fuerte
initialize.messageLabel.passwordStrength.4 = muy fuerte
initialize.label.doNotForget = IMPORTANTE\: Si olivdes tú contraseña, no hay ninguna manera de recuperar tus datos.
initialize.messageLabel.passwordStrength.0 = Muy débil
initialize.messageLabel.passwordStrength.1 = Débil
initialize.messageLabel.passwordStrength.2 = Suficiente
initialize.messageLabel.passwordStrength.3 = Fuerte
initialize.messageLabel.passwordStrength.4 = Muy fuerte
initialize.label.doNotForget = IMPORTANTE\: Si olivdas tú contraseña, no hay ninguna manera de recuperar tus datos.
main.directoryList.remove.confirmation.title = Borrar caja fuerte
main.directoryList.remove.confirmation.header = ¿Quieres de verdad borrar este caja fuerte?
main.directoryList.remove.confirmation.header = ¿Quieres de verdad borrar esta caja fuerte?
main.directoryList.remove.confirmation.content = La caja fuerte solo se borra de la lista. Para eliminarla permanente por favor elimina los datos de tú sistema de archivos.
upgrade.version3to4.msg = Este caja fuerte se debe migrar a un formato más reciente.\nLos nombres de las carpetas cifradas se actualizan.\nPor favor asegurarse de que la sincronización ha terminado antes de seguir.
upgrade.version3to4.err.io = Migración ha fallado por causa de una excepción I/O. Para detalles revisa el archivo de registro.
# or esequema WEBDAV but I think sistema sounds better
settings.prefGvfsScheme.label = sistema WebDAV
settings.prefGvfsScheme.label = Esquema WebDAV
# upgrade.fxml
upgrade.confirmation.label = Sí, me he asegurado de que la sincronización ha terminado
initialize.messageLabel.notEmpty = Caja fuerte no está vacio
unlock.label.savePassword = Contraseña segura
unlock.errorMessage.unauthenticVersionMac = No se pudo autentificar la version de MAC.
unlocked.label.mountFailed = Connecting drive failed
unlock.savePassword.delete.confirmation.title = Delete Saved Password
unlock.savePassword.delete.confirmation.header = Do you really want to delete the saved password of this vault?
unlock.savePassword.delete.confirmation.content = The saved password of this vault will be immediately deleted from your system keychain. If you'd like to save your password again, you'd have to unlock your vault with the "Save password" option enabled.
settings.debugMode.label = Debug Mode *
upgrade.version3dropBundleExtension.title = Vault Version 3 Upgrade (Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 to 4 Upgrade
upgrade.version4to5.title = Vault Version 4 to 5 Upgrade
upgrade.version4to5.msg = This vault needs to be migrated to a newer format.\nEncrypted files will be updated.\nPlease make sure synchronization has finished before proceeding.\n\nNote\: Modification date of all files will be changed to the current date/time in the process.
upgrade.version4to5.err.io = Migration failed due to an I/O Exception. See log file for details.
initialize.messageLabel.notEmpty = Caja fuerte no está vacia
unlock.label.savePassword = Guardar contraseña
unlock.errorMessage.unauthenticVersionMac = No se pudo autentificar la versión de MAC.
unlocked.label.mountFailed = Error al montar la unidad
unlock.savePassword.delete.confirmation.title = Borrar contraseña guardada
unlock.savePassword.delete.confirmation.header = ¿Quieres borrar la contraseña guardada de esta unidad?
unlock.savePassword.delete.confirmation.content = La contraseña guardada de esta caja fuerte, será borrada inmediatamente del sistema de claves. Si quieres guardar tu contraseña de nuevo, tienes que volver a desbloquear la caja fuerte marcando la opción de "Guardar contraseña".
settings.debugMode.label = Modo depuración *
upgrade.version3dropBundleExtension.title = Actualizar caja fuerte a la versión 3 (Drop Bundle Extension)
upgrade.version3to4.title = Actualizar caja fuerte de versión 3 a 4
upgrade.version4to5.title = Actualizar caja fuerte de versión 3 a 4
upgrade.version4to5.msg = Esta caja fuerte tiene que ser migrada a un formato nuevo.\nLos archivos encriptados se actualizarán.\nPor favor, asegúrate de que la sincronización ha terminado antes de empezar con el proceso.\n\nNota\: Las fechas de modificación de todos los archivos, se cambiarán a la fecha actual.
upgrade.version4to5.err.io = La migración ha fallado por una excepción E/S. Consulta el log para ver más detalles.
settings.port.apply = Aplicar
unlock.label.mountAfterUnlock = Montar unidad
unlock.label.revealAfterMount = Revelar unidad
@@ -55,11 +55,6 @@ unlocked.label.statsEncrypted = chiffré
# Décryptage signifie récupérer les données en clair tout en ne connaissant pas la clé
unlocked.label.statsDecrypted = déchiffré
unlocked.ioGraph.yAxis.label = Débit (MiB/s)
# mac_warnings.fxml
macWarnings.windowTitle = Attention - Fichier corrompu dans %s
macWarnings.message = Cryptomator a détecté des corruptions de données dans les fichiers suivants \:
macWarnings.moreInformationButton = En savoir plus
macWarnings.whitelistButton = Déchiffrer tout de même
# settings.fxml
settings.version.label = Version %s
settings.checkForUpdates.label = Vérif. des mises à jour
@@ -99,4 +94,7 @@ upgrade.version3dropBundleExtension.title = mise à jour vers la version 3 du co
upgrade.version3to4.title = metre à jour le coffre de la version 3 à la version 4
upgrade.version4to5.title = metre à jour le coffre de la version 4 à la version 5
upgrade.version4to5.msg = ce coffre doit être mis à jour vers un format plus récent.\nles fichiés chiffrés seront mis à jour.\nVeuillez vérifier que la synchronisation est terminée avant de commencer.\n\nNote \: la date de modification des fichiers sera mise à jour avec la date courante.
upgrade.version4to5.err.io = Migration échouée due à une erreur de lecture. Lisez les logs pour plus de détails.
upgrade.version4to5.err.io = Migration échouée due à une erreur de lecture. Lisez les logs pour plus de détails.
settings.port.apply = Appliquer
unlock.label.mountAfterUnlock = Monter un lecteur
unlock.label.revealAfterMount = Voir le lecteur
@@ -52,11 +52,6 @@ unlocked.label.unmountFailed = Meghajtó leválasztása sikertelen
unlocked.label.statsEncrypted = titkosított
unlocked.label.statsDecrypted = titkosítás feloldva
unlocked.ioGraph.yAxis.label = Teljesítmény (MiB/s)
# mac_warnings.fxml
macWarnings.windowTitle = Veszély - Korrupt fájl a következőben\: %s
macWarnings.message = Cryptomator potenciálisan rosszindulatú hibákat fedezett fel a következő fájlokban\:
macWarnings.moreInformationButton = Tudj meg többet
macWarnings.whitelistButton = Kiválasztottak titkosításának feloldása mindenképp
# settings.fxml
settings.version.label = Verzió\: %s
settings.checkForUpdates.label = Frissítések keresése
@@ -96,4 +91,7 @@ upgrade.version3dropBundleExtension.title = Vault Version 3 Upgrade (Drop Bundle
upgrade.version3to4.title = Széf verziófrissítése 3-ról 4-re
upgrade.version4to5.title = Széf verziófrissítése 4-ről 5-re
upgrade.version4to5.msg = Ennek a széfnek egy újabb formátumra való migrációja szükséges. A titkosított könyvtárnevek frissítve lesznek. Kérlek, győződj meg a szinkronizáció befejeztéről mielőtt továbblépnél.\n\nMegjegyzés\: A összes fájl módosításának dátuma az aktuális időre fog módosulni
upgrade.version4to5.err.io = Migráció meghíusúlt egy I/O kivétel miatt. Kérlek nézd meg a naplófájlt a további részletekért.
upgrade.version4to5.err.io = Migráció meghíusúlt egy I/O kivétel miatt. Kérlek nézd meg a naplófájlt a további részletekért.
settings.port.apply = Apply
unlock.label.mountAfterUnlock = Mount Drive
unlock.label.revealAfterMount = Reveal Drive
+20 -22
View File
@@ -52,11 +52,6 @@ unlocked.label.unmountFailed = Espulsione disco fallita
unlocked.label.statsEncrypted = criptato
unlocked.label.statsDecrypted = decriptato
unlocked.ioGraph.yAxis.label = Volume dati (MiB/s)
# mac_warnings.fxml
macWarnings.windowTitle = Pericolo - File corroto in %s
macWarnings.message = Cryptomator ha individuato potenziali pericolose corruzioni nei seguenti file\:
macWarnings.moreInformationButton = Più informazioni
macWarnings.whitelistButton = Decripta i selezionati comunque
# settings.fxml
settings.version.label = Versione %s
settings.checkForUpdates.label = Verifica aggiornamenti
@@ -79,21 +74,24 @@ initialize.label.doNotForget = IMPORTANTE\: Se dimentichi la password, non c'è
main.directoryList.remove.confirmation.title = Rimuovi vault
main.directoryList.remove.confirmation.header = Vuoi davvero rimuovere questo vault?
main.directoryList.remove.confirmation.content = Il vault sarà rimosso solo dalla lista. Per eliminarlo definitivamente, elimina per favore i file dal tuo hard disk.
upgrade.version3to4.msg = This vault needs to be migrated to a newer format.\nEncrypted folder names will be updated.\nPlease make sure synchronization has finished before proceeding.
upgrade.version3to4.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.prefGvfsScheme.label = WebDAV Scheme
upgrade.version3to4.msg = Il vault deve ha bisogno di essere migrato in un nuovo formato. I nome delle cartelle criptate saranno aggiornati. Per favore assicurati che la sincronizzazione sia terminata prima di procedere.
upgrade.version3to4.err.io = Migrazione fallita a causa di una eccezione I/O. Verificare i file di log per i dettagli.
settings.prefGvfsScheme.label = Schema WebDAV
# upgrade.fxml
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
initialize.messageLabel.notEmpty = Vault not empty
unlock.label.savePassword = Save Password
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed
unlock.savePassword.delete.confirmation.title = Delete Saved Password
unlock.savePassword.delete.confirmation.header = Do you really want to delete the saved password of this vault?
unlock.savePassword.delete.confirmation.content = The saved password of this vault will be immediately deleted from your system keychain. If you'd like to save your password again, you'd have to unlock your vault with the "Save password" option enabled.
settings.debugMode.label = Debug Mode *
upgrade.version3dropBundleExtension.title = Vault Version 3 Upgrade (Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 to 4 Upgrade
upgrade.version4to5.title = Vault Version 4 to 5 Upgrade
upgrade.version4to5.msg = This vault needs to be migrated to a newer format.\nEncrypted files will be updated.\nPlease make sure synchronization has finished before proceeding.\n\nNote\: Modification date of all files will be changed to the current date/time in the process.
upgrade.version4to5.err.io = Migration failed due to an I/O Exception. See log file for details.
upgrade.confirmation.label = Si, sono sicuro che la sincronizzazione e' terminata
initialize.messageLabel.notEmpty = Vault non vuoto
unlock.label.savePassword = Salva Password
unlock.errorMessage.unauthenticVersionMac = Non riesco ad autenticare la versione MAC.
unlocked.label.mountFailed = Tentativo di connessione drive fallito
unlock.savePassword.delete.confirmation.title = Cancella la password salvata
unlock.savePassword.delete.confirmation.header = Vuoi veramente cancellare le password salvate in questo vault?
unlock.savePassword.delete.confirmation.content = Le password salvate in questo vault saranno immediatamente cancellate dal sistema di chiavi. Se vuoi salvare nuovamente la tua password, devi sbloccare il tuo vault con l'opzione "Salva password" abilitata.
settings.debugMode.label = Modalita' debug *
upgrade.version3dropBundleExtension.title = Aggiornamento Vault versione 3 ( Estensione Drop bundle )
upgrade.version3to4.title = Aggiornamento Vault da versione 3 a 4
upgrade.version4to5.title = Aggiornamento da versione 4 a 5
upgrade.version4to5.msg = Questo vault ha bisogno di essere migrato ad un formato piu' recente. Tutti i files criptati saranno aggiornati. Per favore assicurati che la sincronizzazione sia terminata prima di procedere.\n\nNota\: la data di modifica di tutti i files cambiera' alla data/ora attuale del processo.
upgrade.version4to5.err.io = Migrazione fallita a causa di una eccezione I/O. Verifica il file di log per i dettagli.
settings.port.apply = Apply
unlock.label.mountAfterUnlock = Mount Drive
unlock.label.revealAfterMount = Reveal Drive
+20 -22
View File
@@ -52,11 +52,6 @@ unlocked.label.unmountFailed = 外部出力の排出エラー
unlocked.label.statsEncrypted = 暗号化
unlocked.label.statsDecrypted = 解読
unlocked.ioGraph.yAxis.label = 情報処理量
# mac_warnings.fxml
macWarnings.windowTitle = 危険-有害でフォルダの%s
macWarnings.message = Cryptomatorは、以下のファイルで潜在的に悪意のある改悪されたものを見つけました
macWarnings.moreInformationButton = より習得する
macWarnings.whitelistButton = フォルダを選択、解読してください
# settings.fxml
settings.version.label = バージョンの%s
settings.checkForUpdates.label = 最新版のチェック
@@ -79,21 +74,24 @@ initialize.label.doNotForget = 重要:パスワードを忘れましたら、
main.directoryList.remove.confirmation.title = 金庫の削除
main.directoryList.remove.confirmation.header = 本当にこの金庫を取り除きたいですか?
main.directoryList.remove.confirmation.content = 金庫はリストのみで削除されます。永久に削除するなら、ファイルシステムからファイルを削除してください。
upgrade.version3to4.msg = This vault needs to be migrated to a newer format.\nEncrypted folder names will be updated.\nPlease make sure synchronization has finished before proceeding.
upgrade.version3to4.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.prefGvfsScheme.label = WebDAV Scheme
upgrade.version3to4.msg = この金庫は新しいフォーマットに移行する必要があります。暗号化されたフォルダの名前は更新されます。進行する前に同期が完了していることをご確認ください。
upgrade.version3to4.err.io = I/O例外のため移行が失敗しました。詳細はログをご確認ください。
settings.prefGvfsScheme.label = WebDAVスキーム
# upgrade.fxml
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
initialize.messageLabel.notEmpty = Vault not empty
unlock.label.savePassword = Save Password
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed
unlock.savePassword.delete.confirmation.title = Delete Saved Password
unlock.savePassword.delete.confirmation.header = Do you really want to delete the saved password of this vault?
unlock.savePassword.delete.confirmation.content = The saved password of this vault will be immediately deleted from your system keychain. If you'd like to save your password again, you'd have to unlock your vault with the "Save password" option enabled.
settings.debugMode.label = Debug Mode *
upgrade.version3dropBundleExtension.title = Vault Version 3 Upgrade (Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 to 4 Upgrade
upgrade.version4to5.title = Vault Version 4 to 5 Upgrade
upgrade.version4to5.msg = This vault needs to be migrated to a newer format.\nEncrypted files will be updated.\nPlease make sure synchronization has finished before proceeding.\n\nNote\: Modification date of all files will be changed to the current date/time in the process.
upgrade.version4to5.err.io = Migration failed due to an I/O Exception. See log file for details.
upgrade.confirmation.label = はい、同期が完了していることを確認しました。
initialize.messageLabel.notEmpty = 金庫が空いていません。
unlock.label.savePassword = パスワード保存
unlock.errorMessage.unauthenticVersionMac = バージョンMACを認証できません。
unlocked.label.mountFailed = ドライブの接続に失敗しました。
unlock.savePassword.delete.confirmation.title = 保存されたパスワードを削除
unlock.savePassword.delete.confirmation.header = あなたは本当にこの金庫の保存されたパスワードを削除しますか?
unlock.savePassword.delete.confirmation.content = この金庫の保存されたパスワードはあなたのシステムキーチェーンから直ちに削除されます。もしまたパスワードを保存したい際には、”パスワード保存”オプションを有効にした上に金庫を解除する必要があります。
settings.debugMode.label = デバッグモード
upgrade.version3dropBundleExtension.title = 金庫バージョン3アップグレード(Drop Bundle Extension)
upgrade.version3to4.title = 金庫バージョン3から4にアップグレード
upgrade.version4to5.title = 金庫バージョン4から5にアップグレード
upgrade.version4to5.msg = この金庫は新しいフォーマットに移行する必要があります。暗号化されたファイルは更新されます。進行する前に同期が完了していることをご確認ください。\n\n注意:すべてのファイルの変更日は、現在の日付・時刻に変わります。
upgrade.version4to5.err.io = I/O例外のため移行が失敗しました。詳細はログをご確認ください。
settings.port.apply = 適用
unlock.label.mountAfterUnlock = ドライブをマウント
unlock.label.revealAfterMount = ドライブを明らかにする
@@ -52,11 +52,6 @@ unlocked.label.unmountFailed = 드라이브 추출 실패
unlocked.label.statsEncrypted = 암호화
unlocked.label.statsDecrypted = 복호화
unlocked.ioGraph.yAxis.label = 처리량 (MiB/s)
# mac_warnings.fxml
macWarnings.windowTitle = 위험 - %s에 손상된 파일
macWarnings.message = Cryptomator가 다음 파일들에서 잠재적인 손상 위험을 감지했습니다.
macWarnings.moreInformationButton = 더 알아보기
macWarnings.whitelistButton = 선택 항목 강제로 암호 풀기
# settings.fxml
settings.version.label = 버전 %s
settings.checkForUpdates.label = 업데이트 확인
@@ -96,4 +91,7 @@ upgrade.version3dropBundleExtension.title = 버전 3 보관함 업그레이드 (
upgrade.version3to4.title = 보관함 버전 3에서 4로 업그레이드
upgrade.version4to5.title = 보관함 버전 4에서 5로 업그레이드
upgrade.version4to5.msg = 이 보관함은 새로운 포맷으로 이전되어야 합니다.\n암호화된 파일들은 업데이트 될 것입니다.\n진행하기 전에 동기화가 완료되었는지 확인해주세요.\n\n참고\: 모든 파일의 수정 날짜는 과정 진행 중에 현재 날짜/시간으로 바뀔 것입니다.
upgrade.version4to5.err.io = I/O 예외에 의해 마이그레이션 실패. 자세한 사항은 로그 파일을 참조하세요.
upgrade.version4to5.err.io = I/O 예외에 의해 마이그레이션 실패. 자세한 사항은 로그 파일을 참조하세요.
settings.port.apply = 적용
unlock.label.mountAfterUnlock = 드라이브 마운트
unlock.label.revealAfterMount = 드라이브 공개
+17 -19
View File
@@ -52,11 +52,6 @@ unlocked.label.unmountFailed = Diska izgrūšana neizdevās
unlocked.label.statsEncrypted = šifrēts
unlocked.label.statsDecrypted = atšifrēts
unlocked.ioGraph.yAxis.label = Caurlaidība (MiB/s)
# mac_warnings.fxml
macWarnings.windowTitle = Bīstami - %s satur bojātu datni
macWarnings.message = Cryptomator konstatēja potenciāli ļaunprātīgu bojājumu sekojošām datnēm\:
macWarnings.moreInformationButton = Skatīt vairāk
macWarnings.whitelistButton = Atšifrēt iezīmēto tāpat
# settings.fxml
settings.version.label = Versija %s
settings.checkForUpdates.label = Meklēt atjauninājumus
@@ -69,7 +64,7 @@ tray.menu.open = Atvērt
tray.menu.quit = Iziet
tray.infoMsg.title = Joprojām darbojās
# Fuzzy
tray.infoMsg.msg = Cryptomator joprojām darbojās. Iziet var no ikonas.
tray.infoMsg.msg = Cryptomator joprojām darbojās. Iziet var no statusa ikonas.
tray.infoMsg.msg.osx = Cryptomator is still alive. joprojām darbojās. Iziet var no izvēlnes ikonas.
initialize.messageLabel.passwordStrength.0 = Ļoti vāja
initialize.messageLabel.passwordStrength.1 = Vāja
@@ -85,16 +80,19 @@ upgrade.version3to4.err.io = Migrācija neizdevās dēļ I/O izņēmuma. Sīkāk
settings.prefGvfsScheme.label = WebDAV shēma
# upgrade.fxml
upgrade.confirmation.label = Jā, esmu pārliecinājies, ka sinhronizācija ir pabeigta.
initialize.messageLabel.notEmpty = Vault not empty
unlock.label.savePassword = Save Password
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed
unlock.savePassword.delete.confirmation.title = Delete Saved Password
unlock.savePassword.delete.confirmation.header = Do you really want to delete the saved password of this vault?
unlock.savePassword.delete.confirmation.content = The saved password of this vault will be immediately deleted from your system keychain. If you'd like to save your password again, you'd have to unlock your vault with the "Save password" option enabled.
settings.debugMode.label = Debug Mode *
upgrade.version3dropBundleExtension.title = Vault Version 3 Upgrade (Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 to 4 Upgrade
upgrade.version4to5.title = Vault Version 4 to 5 Upgrade
upgrade.version4to5.msg = This vault needs to be migrated to a newer format.\nEncrypted files will be updated.\nPlease make sure synchronization has finished before proceeding.\n\nNote\: Modification date of all files will be changed to the current date/time in the process.
upgrade.version4to5.err.io = Migration failed due to an I/O Exception. See log file for details.
initialize.messageLabel.notEmpty = Glabātuve nav tukša
unlock.label.savePassword = Saglabāt paroli
unlock.errorMessage.unauthenticVersionMac = Nevar autentificēt versijas MAC
unlocked.label.mountFailed = Diska pievienošana neizdevās
unlock.savePassword.delete.confirmation.title = Dzēst saglabāto paroli
unlock.savePassword.delete.confirmation.header = Vai tiešām vēlies dzēst saglabāto paroli šai glabātuvei?
unlock.savePassword.delete.confirmation.content = Saglabātā parole nekavējoties tiks izdzēsta. Ja vēlēsies paroli atkārtoti saglabāt, tev būs jāatslēdz glabātuve ar ieslēgtu opciju "Saglabāt paroli".
settings.debugMode.label = Atkļūdošanas režīms *
upgrade.version3dropBundleExtension.title = Glabātuves 3 versijas atjauninājums (atmet paplašinājumu)
upgrade.version3to4.title = Glabātuves versijas 3 uz 4 atjauninājums
upgrade.version4to5.title = Glabātuves versijas 4 uz 5 atjauninājums
upgrade.version4to5.msg = Šo glabātuvi nepieciešams migrēt uz jaunāku versiju.\nŠifrētās datnes tiks atjauninātas.\nPirms apstiprini, pārliecinies, ka ir beigusies sinhronizācija.\n\nPiezīme\: Visām datnēm modificēšanas datums tiks izmainīts uz šodienas datumu.
upgrade.version4to5.err.io = Migrācijas kļīda dēļ I/O izņēmuma. Sīkāku informāciju skaties žurnālā.
settings.port.apply = Apply
unlock.label.mountAfterUnlock = Mount Drive
unlock.label.revealAfterMount = Reveal Drive

Some files were not shown because too many files have changed in this diff Show More