diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/Tarpit.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/Tarpit.java index 011adddc6..14c528fef 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/Tarpit.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/Tarpit.java @@ -7,8 +7,10 @@ package org.cryptomator.frontend.webdav; import static java.lang.Math.max; import static java.lang.System.currentTimeMillis; +import static java.util.Collections.synchronizedSet; import java.io.Serializable; +import java.util.Collection; import java.util.HashSet; import java.util.Optional; import java.util.Set; @@ -27,18 +29,15 @@ class Tarpit implements Serializable { private static final Logger LOG = LoggerFactory.getLogger(Tarpit.class); private static final long DELAY_MS = 10000; - private final Set validFrontendIds = new HashSet<>(); + private final Set validFrontendIds = synchronizedSet(new HashSet<>()); @Inject - public Tarpit() { - } + public Tarpit() {} - public void register(FrontendId frontendId) { - validFrontendIds.add(frontendId); - } - - public void unregister(FrontendId frontendId) { - validFrontendIds.remove(frontendId); + public void setValidFrontendIds(Collection validFrontendIds) { + this.validFrontendIds.retainAll(validFrontendIds); + this.validFrontendIds.addAll(validFrontendIds); + validFrontendIds.forEach(System.out::println); } public void handle(HttpServletRequest req) { diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java index f80e5543b..0bfd9515d 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java @@ -24,15 +24,13 @@ class WebDavFrontend implements Frontend { private final WebDavMounterProvider webdavMounterProvider; private final ServletContextHandler handler; private final URI uri; - private final Runnable afterClose; private WebDavMount mount; - public WebDavFrontend(WebDavMounterProvider webdavMounterProvider, ServletContextHandler handler, URI uri, Runnable afterUnmount) throws FrontendCreationFailedException { + public WebDavFrontend(WebDavMounterProvider webdavMounterProvider, ServletContextHandler handler, URI uri) throws FrontendCreationFailedException { this.webdavMounterProvider = webdavMounterProvider; this.handler = handler; this.uri = uri; - this.afterClose = afterUnmount; try { handler.start(); } catch (Exception e) { @@ -42,12 +40,8 @@ class WebDavFrontend implements Frontend { @Override public void close() throws Exception { - try { - unmount(); - handler.stop(); - } finally { - afterClose.run(); - } + unmount(); + handler.stop(); } @Override diff --git a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServer.java b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServer.java index 0f18bbab5..cf40f1ce1 100644 --- a/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServer.java +++ b/main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServer.java @@ -12,6 +12,7 @@ import static java.lang.String.format; import java.net.URI; import java.net.URISyntaxException; +import java.util.Collection; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -117,9 +118,12 @@ public class WebDavServer implements FrontendFactory { throw new IllegalStateException(e); } final ServletContextHandler handler = addServlet(root, uri); - tarpit.register(id); LOG.info("Servlet available under " + uri); - return new WebDavFrontend(webdavMounterProvider, handler, uri, () -> tarpit.unregister(id)); + return new WebDavFrontend(webdavMounterProvider, handler, uri); + } + + public void setValidFrontendIds(Collection validFrontendIds) { + tarpit.setValidFrontendIds(validFrontendIds); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java index b62f631c4..f460dc133 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java @@ -8,6 +8,8 @@ *******************************************************************************/ package org.cryptomator.ui; +import static java.util.stream.Collectors.toList; + import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -17,9 +19,12 @@ import javax.inject.Singleton; import org.cryptomator.common.CommonsModule; import org.cryptomator.crypto.engine.impl.CryptoEngineModule; import org.cryptomator.frontend.FrontendFactory; +import org.cryptomator.frontend.FrontendId; import org.cryptomator.frontend.webdav.WebDavModule; import org.cryptomator.frontend.webdav.WebDavServer; +import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.model.VaultObjectMapperProvider; +import org.cryptomator.ui.model.Vaults; import org.cryptomator.ui.settings.Settings; import org.cryptomator.ui.settings.SettingsProvider; import org.cryptomator.ui.util.DeferredCloser; @@ -31,6 +36,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import dagger.Module; import dagger.Provides; import javafx.application.Application; +import javafx.beans.Observable; import javafx.stage.Stage; @Module(includes = {CryptoEngineModule.class, CommonsModule.class, WebDavModule.class}) @@ -93,10 +99,19 @@ class CryptomatorModule { @Provides @Singleton - FrontendFactory provideFrontendFactory(DeferredCloser closer, WebDavServer webDavServer, Settings settings) { + FrontendFactory provideFrontendFactory(DeferredCloser closer, WebDavServer webDavServer, Vaults vaults, Settings settings) { + vaults.addListener((Observable o) -> setValidFrontendIds(webDavServer, vaults)); + setValidFrontendIds(webDavServer, vaults); webDavServer.setPort(settings.getPort()); webDavServer.start(); return closer.closeLater(webDavServer, WebDavServer::stop).get().orElseThrow(IllegalStateException::new); } + private void setValidFrontendIds(WebDavServer webDavServer, Vaults vaults) { + webDavServer.setValidFrontendIds(vaults.stream() // + .map(Vault::getId) + .map(FrontendId::from) + .collect(toList())); + } + } diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java index c9dee3248..478c6be6b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java @@ -29,6 +29,7 @@ import org.cryptomator.ui.controls.DirectoryListCell; import org.cryptomator.ui.model.UpgradeStrategies; import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.model.VaultFactory; +import org.cryptomator.ui.model.Vaults; import org.cryptomator.ui.settings.Localization; import org.cryptomator.ui.settings.Settings; import org.cryptomator.ui.util.DialogBuilderUtil; @@ -44,9 +45,6 @@ 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.ListChangeListener.Change; -import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.geometry.Side; @@ -81,7 +79,7 @@ public class MainController extends LocalizedFXMLViewController { private final Lazy settingsController; private final Lazy upgradeStrategies; private final ObjectProperty activeController = new SimpleObjectProperty<>(); - private final ObservableList vaults; + private final Vaults vaults; private final ObjectProperty selectedVault = new SimpleObjectProperty<>(); private final BooleanExpression isSelectedVaultUnlocked = BooleanBinding.booleanExpression(EasyBind.select(selectedVault).selectObject(Vault::unlockedProperty).orElse(false)); private final BooleanExpression isSelectedVaultValid = BooleanBinding.booleanExpression(EasyBind.monadic(selectedVault).map(Vault::isValidVaultDirectory).orElse(false)); @@ -92,7 +90,8 @@ public class MainController extends LocalizedFXMLViewController { @Inject public MainController(@Named("mainWindow") Stage mainWindow, Localization localization, Settings settings, VaultFactory vaultFactoy, Lazy welcomeController, Lazy initializeController, Lazy notFoundController, Lazy upgradeController, Lazy unlockController, - Provider unlockedControllerProvider, Lazy changePasswordController, Lazy settingsController, Lazy upgradeStrategies) { + Provider unlockedControllerProvider, Lazy changePasswordController, Lazy settingsController, Lazy upgradeStrategies, + Vaults vaults) { super(localization); this.mainWindow = mainWindow; this.vaultFactoy = vaultFactoy; @@ -105,10 +104,7 @@ public class MainController extends LocalizedFXMLViewController { this.changePasswordController = changePasswordController; this.settingsController = settingsController; this.upgradeStrategies = upgradeStrategies; - this.vaults = FXCollections.observableList(settings.getDirectories()); - this.vaults.addListener((Change c) -> { - settings.save(); - }); + this.vaults = vaults; // derived bindings: this.isShowingSettings = activeController.isEqualTo(settingsController.get()); diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vaults.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vaults.java new file mode 100644 index 000000000..9ac94d66e --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vaults.java @@ -0,0 +1,177 @@ +package org.cryptomator.ui.model; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.cryptomator.ui.settings.Settings; + +import javafx.beans.InvalidationListener; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ListChangeListener.Change; +import javafx.collections.ObservableList; + +@Singleton +public class Vaults implements ObservableList { + + private final ObservableList delegate; + + @Inject + public Vaults(Settings settings) { + this.delegate = FXCollections.observableList(settings.getDirectories()); + addListener((Change change) -> settings.save()); + } + + public void addListener(ListChangeListener listener) { + delegate.addListener(listener); + } + + public void removeListener(ListChangeListener listener) { + delegate.removeListener(listener); + } + + public void addListener(InvalidationListener listener) { + delegate.addListener(listener); + } + + public boolean addAll(Vault... elements) { + return delegate.addAll(elements); + } + + public boolean setAll(Vault... elements) { + return delegate.setAll(elements); + } + + public boolean setAll(Collection col) { + return delegate.setAll(col); + } + + public boolean removeAll(Vault... elements) { + return delegate.removeAll(elements); + } + + public void removeListener(InvalidationListener listener) { + delegate.removeListener(listener); + } + + public boolean retainAll(Vault... elements) { + return delegate.retainAll(elements); + } + + public void remove(int from, int to) { + delegate.remove(from, to); + } + + public int size() { + return delegate.size(); + } + + public boolean isEmpty() { + return delegate.isEmpty(); + } + + public boolean contains(Object o) { + return delegate.contains(o); + } + + public Iterator iterator() { + return delegate.iterator(); + } + + public Object[] toArray() { + return delegate.toArray(); + } + + public T[] toArray(T[] a) { + return delegate.toArray(a); + } + + public boolean add(Vault e) { + return delegate.add(e); + } + + public boolean remove(Object o) { + return delegate.remove(o); + } + + public boolean containsAll(Collection c) { + return delegate.containsAll(c); + } + + public boolean addAll(Collection c) { + return delegate.addAll(c); + } + + public boolean addAll(int index, Collection c) { + return delegate.addAll(index, c); + } + + public boolean removeAll(Collection c) { + return delegate.removeAll(c); + } + + public boolean retainAll(Collection c) { + return delegate.retainAll(c); + } + + public void clear() { + delegate.clear(); + } + + public Vault get(int index) { + return delegate.get(index); + } + + public Vault set(int index, Vault element) { + return delegate.set(index, element); + } + + public void add(int index, Vault element) { + delegate.add(index, element); + } + + public Vault remove(int index) { + return delegate.remove(index); + } + + public int indexOf(Object o) { + return delegate.indexOf(o); + } + + public int lastIndexOf(Object o) { + return delegate.lastIndexOf(o); + } + + public ListIterator listIterator() { + return delegate.listIterator(); + } + + public ListIterator listIterator(int index) { + return delegate.listIterator(index); + } + + public List subList(int fromIndex, int toIndex) { + return delegate.subList(fromIndex, toIndex); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || getClass() != obj.getClass()) return false; + return internalEquals((Vaults)obj); + } + + private boolean internalEquals(Vaults other) { + return delegate.equals(other.delegate); + } + + public int hashCode() { + return delegate.hashCode(); + } + +}