From 8ba89a3bf5fdfda04f69614917f371a4c8a719e8 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Fri, 20 Feb 2015 21:30:33 +0100 Subject: [PATCH] Injecting Cryptor using Guice --- main/crypto-api/pom.xml | 1 + main/pom.xml | 7 ++ main/ui/pom.xml | 18 +--- .../ui/{Main.java => Cryptomator.java} | 2 +- .../org/cryptomator/ui/MainApplication.java | 18 ++-- .../org/cryptomator/ui/MainController.java | 20 +++-- .../java/org/cryptomator/ui/MainModule.java | 21 +++-- .../java/org/cryptomator/ui/model/Vault.java | 12 +-- .../ui/model/VaultDeserializer.java | 27 ------ .../ui/model/VaultObjectMapperProvider.java | 70 ++++++++++++++++ .../cryptomator/ui/model/VaultSerializer.java | 20 ----- .../org/cryptomator/ui/settings/Settings.java | 64 +------------- .../ui/settings/SettingsProvider.java | 84 +++++++++++++++++++ .../ui/util/SingleInstanceManager.java | 12 +-- 14 files changed, 213 insertions(+), 163 deletions(-) rename main/ui/src/main/java/org/cryptomator/ui/{Main.java => Cryptomator.java} (99%) delete mode 100644 main/ui/src/main/java/org/cryptomator/ui/model/VaultDeserializer.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/model/VaultObjectMapperProvider.java delete mode 100644 main/ui/src/main/java/org/cryptomator/ui/model/VaultSerializer.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java diff --git a/main/crypto-api/pom.xml b/main/crypto-api/pom.xml index a903fed95..5e2ff08ad 100644 --- a/main/crypto-api/pom.xml +++ b/main/crypto-api/pom.xml @@ -18,6 +18,7 @@ Cryptomator cryptographic module API + commons-io commons-io diff --git a/main/pom.xml b/main/pom.xml index 5ce5d04e0..190d77ca2 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -103,6 +103,13 @@ commons-codec ${commons-codec.version} + + + + com.google.inject + guice + 3.0 + diff --git a/main/ui/pom.xml b/main/ui/pom.xml index fbcb9671b..033920f33 100644 --- a/main/ui/pom.xml +++ b/main/ui/pom.xml @@ -19,9 +19,8 @@ Cryptomator - org.cryptomator.ui.Main + org.cryptomator.ui.Cryptomator ${java.home}/../lib/ant-javafx.jar - 8.20.8 @@ -50,23 +49,10 @@ commons-lang3 - - + com.google.inject guice - 3.0 diff --git a/main/ui/src/main/java/org/cryptomator/ui/Main.java b/main/ui/src/main/java/org/cryptomator/ui/Cryptomator.java similarity index 99% rename from main/ui/src/main/java/org/cryptomator/ui/Main.java rename to main/ui/src/main/java/org/cryptomator/ui/Cryptomator.java index fca076b5a..27b3dbf68 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/Main.java +++ b/main/ui/src/main/java/org/cryptomator/ui/Cryptomator.java @@ -28,7 +28,7 @@ import org.eclipse.jetty.util.ConcurrentHashSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Main { +public class Cryptomator { public static final Logger LOG = LoggerFactory.getLogger(MainApplication.class); public static final CompletableFuture> OPEN_FILE_HANDLER = new CompletableFuture<>(); diff --git a/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java b/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java index b4d62bfa5..df204e2b6 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/MainApplication.java @@ -18,13 +18,14 @@ import java.util.concurrent.ExecutorService; import javafx.application.Application; import javafx.application.Platform; import javafx.fxml.FXMLLoader; +import javafx.fxml.JavaFXBuilderFactory; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.MainModule.ControllerFactory; +import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.util.ActiveWindowStyleSupport; import org.cryptomator.ui.util.DeferredCloser; import org.cryptomator.ui.util.SingleInstanceManager; @@ -32,6 +33,7 @@ import org.cryptomator.ui.util.SingleInstanceManager.LocalInstance; import org.cryptomator.ui.util.TrayIconUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import com.google.inject.Guice; import com.google.inject.Injector; @@ -42,11 +44,8 @@ public class MainApplication extends Application { private static final Logger LOG = LoggerFactory.getLogger(MainApplication.class); private final CleanShutdownPerformer cleanShutdownPerformer = new CleanShutdownPerformer(); - private final ExecutorService executorService; - private final ControllerFactory controllerFactory; - private final DeferredCloser closer; public MainApplication() { @@ -62,9 +61,7 @@ public class MainApplication extends Application { } public MainApplication(Injector injector) { - this(injector.getInstance(ExecutorService.class), - injector.getInstance(ControllerFactory.class), - injector.getInstance(DeferredCloser.class)); + this(injector.getInstance(ExecutorService.class), injector.getInstance(ControllerFactory.class), injector.getInstance(DeferredCloser.class)); } public MainApplication(ExecutorService executorService, ControllerFactory controllerFactory, DeferredCloser closer) { @@ -91,7 +88,7 @@ public class MainApplication extends Application { chooseNativeStylesheet(); final ResourceBundle rb = ResourceBundle.getBundle("localization"); - final FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/main.fxml"), rb); + final FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/main.fxml"), rb, new JavaFXBuilderFactory(MainApplication.class.getClassLoader())); loader.setControllerFactory(controllerFactory); final Parent root = loader.load(); final MainController ctrl = loader.getController(); @@ -112,11 +109,10 @@ public class MainApplication extends Application { } if (SystemUtils.IS_OS_MAC_OSX) { - Main.OPEN_FILE_HANDLER.complete(file -> handleCommandLineArg(ctrl, file.getAbsolutePath())); + Cryptomator.OPEN_FILE_HANDLER.complete(file -> handleCommandLineArg(ctrl, file.getAbsolutePath())); } - LocalInstance cryptomatorGuiInstance = closer.closeLater( - SingleInstanceManager.startLocalInstance(APPLICATION_KEY, executorService), LocalInstance::close).get().get(); + LocalInstance cryptomatorGuiInstance = closer.closeLater(SingleInstanceManager.startLocalInstance(APPLICATION_KEY, executorService), LocalInstance::close).get().get(); cryptomatorGuiInstance.registerListener(arg -> handleCommandLineArg(ctrl, arg)); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/MainController.java b/main/ui/src/main/java/org/cryptomator/ui/MainController.java index a1dd920e2..130a66be0 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/MainController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/MainController.java @@ -26,6 +26,7 @@ import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; +import javafx.fxml.JavaFXBuilderFactory; import javafx.geometry.Side; import javafx.scene.Parent; import javafx.scene.control.ContextMenu; @@ -37,7 +38,9 @@ import javafx.scene.layout.Pane; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.stage.WindowEvent; +import javafx.util.BuilderFactory; +import org.cryptomator.crypto.Cryptor; import org.cryptomator.ui.InitializeController.InitializationListener; import org.cryptomator.ui.MainModule.ControllerFactory; import org.cryptomator.ui.UnlockController.UnlockListener; @@ -49,6 +52,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; +import com.google.inject.Provider; public class MainController implements Initializable, InitializationListener, UnlockListener, LockListener { @@ -74,17 +78,19 @@ public class MainController implements Initializable, InitializationListener, Un @FXML private Pane contentPane; + private final ControllerFactory controllerFactory; + private final Settings settings; + private final Provider cryptorProvider; + private final BuilderFactory builderFactory = new JavaFXBuilderFactory(MainController.class.getClassLoader()); + private ResourceBundle rb; - private final ControllerFactory controllerFactory; - - private final Settings settings; - @Inject - public MainController(ControllerFactory controllerFactory, Settings settings) { + public MainController(ControllerFactory controllerFactory, Settings settings, Provider cryptorProvider) { super(); this.controllerFactory = controllerFactory; this.settings = settings; + this.cryptorProvider = cryptorProvider; } @Override @@ -164,7 +170,7 @@ public class MainController implements Initializable, InitializationListener, Un return; } - final Vault vault = new Vault(vaultPath); + final Vault vault = new Vault(vaultPath, cryptorProvider.get()); if (!directoryList.getItems().contains(vault)) { directoryList.getItems().add(vault); } @@ -222,7 +228,7 @@ public class MainController implements Initializable, InitializationListener, Un private T showView(String fxml) { try { - final FXMLLoader loader = new FXMLLoader(getClass().getResource(fxml), rb); + final FXMLLoader loader = new FXMLLoader(getClass().getResource(fxml), rb, builderFactory); loader.setControllerFactory(controllerFactory); final Parent root = loader.load(); contentPane.getChildren().clear(); diff --git a/main/ui/src/main/java/org/cryptomator/ui/MainModule.java b/main/ui/src/main/java/org/cryptomator/ui/MainModule.java index 06f294136..14520604d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/MainModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/MainModule.java @@ -11,21 +11,29 @@ package org.cryptomator.ui; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import javafx.util.Callback; + import javax.inject.Singleton; +import org.cryptomator.crypto.Cryptor; +import org.cryptomator.crypto.SamplingDecorator; +import org.cryptomator.crypto.aes256.Aes256Cryptor; +import org.cryptomator.ui.model.VaultObjectMapperProvider; import org.cryptomator.ui.settings.Settings; +import org.cryptomator.ui.settings.SettingsProvider; import org.cryptomator.ui.util.DeferredCloser; import org.cryptomator.ui.util.DeferredCloser.Closer; import org.cryptomator.webdav.WebDavServer; -import javafx.util.Callback; - +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.google.inject.Provides; +import com.google.inject.name.Names; public class MainModule extends AbstractModule { - DeferredCloser deferredCloser = new DeferredCloser(); + + private final DeferredCloser deferredCloser = new DeferredCloser(); public static interface ControllerFactory extends Callback, Object> { @@ -34,6 +42,8 @@ public class MainModule extends AbstractModule { @Override protected void configure() { bind(DeferredCloser.class).toInstance(deferredCloser); + bind(ObjectMapper.class).annotatedWith(Names.named("VaultJsonMapper")).toProvider(VaultObjectMapperProvider.class); + bind(Settings.class).toProvider(SettingsProvider.class); } @Provides @@ -49,9 +59,8 @@ public class MainModule extends AbstractModule { } @Provides - @Singleton - Settings getSettings() { - return closeLater(Settings.load(), Settings::save); + Cryptor getCryptor() { + return SamplingDecorator.decorate(new Aes256Cryptor()); } @Provides diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java index c688b6b0a..98867d0ee 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java @@ -13,8 +13,6 @@ import javafx.beans.property.SimpleObjectProperty; import org.apache.commons.lang3.StringUtils; import org.cryptomator.crypto.Cryptor; -import org.cryptomator.crypto.SamplingDecorator; -import org.cryptomator.crypto.aes256.Aes256Cryptor; import org.cryptomator.ui.util.DeferredClosable; import org.cryptomator.ui.util.DeferredCloser; import org.cryptomator.ui.util.MasterKeyFilter; @@ -26,11 +24,6 @@ import org.cryptomator.webdav.WebDavServer.ServletLifeCycleAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -@JsonSerialize(using = VaultSerializer.class) -@JsonDeserialize(using = VaultDeserializer.class) public class Vault implements Serializable { private static final long serialVersionUID = 3754487289683599469L; @@ -38,18 +31,19 @@ public class Vault implements Serializable { public static final String VAULT_FILE_EXTENSION = ".cryptomator"; - private final Cryptor cryptor = SamplingDecorator.decorate(new Aes256Cryptor()); + private final Cryptor cryptor; private final ObjectProperty unlocked = new SimpleObjectProperty(this, "unlocked", Boolean.FALSE); private final Path path; private String mountName; private DeferredClosable webDavServlet = DeferredClosable.empty(); private DeferredClosable webDavMount = DeferredClosable.empty(); - public Vault(final Path vaultDirectoryPath) { + public Vault(final Path vaultDirectoryPath, final Cryptor cryptor) { if (!Files.isDirectory(vaultDirectoryPath) || !vaultDirectoryPath.getFileName().toString().endsWith(VAULT_FILE_EXTENSION)) { throw new IllegalArgumentException("Not a valid vault directory: " + vaultDirectoryPath); } this.path = vaultDirectoryPath; + this.cryptor = cryptor; try { setMountName(getName()); diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/VaultDeserializer.java b/main/ui/src/main/java/org/cryptomator/ui/model/VaultDeserializer.java deleted file mode 100644 index 890a08310..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/model/VaultDeserializer.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.cryptomator.ui.model; - -import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Path; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -public class VaultDeserializer extends JsonDeserializer { - - @Override - public Vault deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { - final JsonNode node = jp.readValueAsTree(); - final String pathStr = node.get("path").asText(); - final Path path = FileSystems.getDefault().getPath(pathStr); - final Vault dir = new Vault(path); - if (node.has("mountName")) { - dir.setMountName(node.get("mountName").asText()); - } - return dir; - } - -} diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/VaultObjectMapperProvider.java b/main/ui/src/main/java/org/cryptomator/ui/model/VaultObjectMapperProvider.java new file mode 100644 index 000000000..7cac1a904 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/model/VaultObjectMapperProvider.java @@ -0,0 +1,70 @@ +package org.cryptomator.ui.model; + +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Path; + +import javax.inject.Inject; + +import org.cryptomator.crypto.Cryptor; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.google.inject.Provider; + +public class VaultObjectMapperProvider implements Provider { + + private final Provider cryptorProvider; + + @Inject + public VaultObjectMapperProvider(final Provider cryptorProvider) { + this.cryptorProvider = cryptorProvider; + } + + @Override + public ObjectMapper get() { + final ObjectMapper om = new ObjectMapper(); + final SimpleModule module = new SimpleModule("VaultJsonMapper"); + module.addSerializer(Vault.class, new VaultSerializer()); + module.addDeserializer(Vault.class, new VaultDeserializer()); + om.registerModule(module); + return om; + } + + private class VaultSerializer extends JsonSerializer { + + @Override + public void serialize(Vault value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeStringField("path", value.getPath().toString()); + jgen.writeStringField("mountName", value.getMountName().toString()); + jgen.writeEndObject(); + } + + } + + private class VaultDeserializer extends JsonDeserializer { + + @Override + public Vault deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + final JsonNode node = jp.readValueAsTree(); + final String pathStr = node.get("path").asText(); + final Path path = FileSystems.getDefault().getPath(pathStr); + final Vault dir = new Vault(path, cryptorProvider.get()); + if (node.has("mountName")) { + dir.setMountName(node.get("mountName").asText()); + } + return dir; + } + + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/VaultSerializer.java b/main/ui/src/main/java/org/cryptomator/ui/model/VaultSerializer.java deleted file mode 100644 index c77ceb367..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/model/VaultSerializer.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.cryptomator.ui.model; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class VaultSerializer extends JsonSerializer { - - @Override - public void serialize(Vault value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { - jgen.writeStartObject(); - jgen.writeStringField("path", value.getPath().toString()); - jgen.writeStringField("mountName", value.getMountName().toString()); - jgen.writeEndObject(); - } - -} diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java index 30365ec04..cb4445b3b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java +++ b/main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java @@ -8,82 +8,26 @@ ******************************************************************************/ package org.cryptomator.ui.settings; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.io.Serializable; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.List; -import org.apache.commons.lang3.SystemUtils; import org.cryptomator.ui.model.Vault; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import com.fasterxml.jackson.databind.ObjectMapper; @JsonPropertyOrder(value = {"directories"}) public class Settings implements Serializable { private static final long serialVersionUID = 7609959894417878744L; - private static final Logger LOG = LoggerFactory.getLogger(Settings.class); - private static final Path SETTINGS_DIR; - private static final String SETTINGS_FILE = "settings.json"; - private static final ObjectMapper JSON_OM = new ObjectMapper(); - - static { - final String appdata = System.getenv("APPDATA"); - final FileSystem fs = FileSystems.getDefault(); - - if (SystemUtils.IS_OS_WINDOWS && appdata != null) { - SETTINGS_DIR = fs.getPath(appdata, "Cryptomator"); - } else if (SystemUtils.IS_OS_WINDOWS && appdata == null) { - SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, ".Cryptomator"); - } else if (SystemUtils.IS_OS_MAC_OSX) { - SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, "Library/Application Support/Cryptomator"); - } else { - // (os.contains("solaris") || os.contains("sunos") || os.contains("linux") || os.contains("unix")) - SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, ".Cryptomator"); - } - } private List directories; - private Settings() { - // private constructor - } + /** + * Package-private constructor; use {@link SettingsProvider}. + */ + Settings() { - public static synchronized Settings load() { - try { - Files.createDirectories(SETTINGS_DIR); - final Path settingsFile = SETTINGS_DIR.resolve(SETTINGS_FILE); - final InputStream in = Files.newInputStream(settingsFile, StandardOpenOption.READ); - return JSON_OM.readValue(in, Settings.class); - } catch (IOException e) { - LOG.warn("Failed to load settings, creating new one."); - return Settings.defaultSettings(); - } - } - - public synchronized void save() { - try { - Files.createDirectories(SETTINGS_DIR); - final Path settingsFile = SETTINGS_DIR.resolve(SETTINGS_FILE); - final OutputStream out = Files.newOutputStream(settingsFile, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); - JSON_OM.writeValue(out, this); - } catch (IOException e) { - LOG.error("Failed to save settings.", e); - } - } - - private static Settings defaultSettings() { - return new Settings(); } /* Getter/Setter */ diff --git a/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java b/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java new file mode 100644 index 000000000..38988b13a --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/settings/SettingsProvider.java @@ -0,0 +1,84 @@ +package org.cryptomator.ui.settings; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.apache.commons.lang3.SystemUtils; +import org.cryptomator.ui.util.DeferredCloser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.inject.Provider; + +public class SettingsProvider implements Provider { + + private static final Logger LOG = LoggerFactory.getLogger(Settings.class); + private static final Path SETTINGS_DIR; + private static final String SETTINGS_FILE = "settings.json"; + + static { + final String appdata = System.getenv("APPDATA"); + final FileSystem fs = FileSystems.getDefault(); + + if (SystemUtils.IS_OS_WINDOWS && appdata != null) { + SETTINGS_DIR = fs.getPath(appdata, "Cryptomator"); + } else if (SystemUtils.IS_OS_WINDOWS && appdata == null) { + SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, ".Cryptomator"); + } else if (SystemUtils.IS_OS_MAC_OSX) { + SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, "Library/Application Support/Cryptomator"); + } else { + // (os.contains("solaris") || os.contains("sunos") || os.contains("linux") || os.contains("unix")) + SETTINGS_DIR = fs.getPath(SystemUtils.USER_HOME, ".Cryptomator"); + } + } + + private final DeferredCloser deferredCloser; + private final ObjectMapper objectMapper; + + @Inject + public SettingsProvider(DeferredCloser deferredCloser, @Named("VaultJsonMapper") ObjectMapper objectMapper) { + this.deferredCloser = deferredCloser; + this.objectMapper = objectMapper; + } + + @Override + public Settings get() { + Settings settings = null; + try { + Files.createDirectories(SETTINGS_DIR); + final Path settingsFile = SETTINGS_DIR.resolve(SETTINGS_FILE); + final InputStream in = Files.newInputStream(settingsFile, StandardOpenOption.READ); + settings = objectMapper.readValue(in, Settings.class); + } catch (IOException e) { + LOG.warn("Failed to load settings, creating new one."); + settings = new Settings(); + } + deferredCloser.closeLater(settings, this::save); + return settings; + } + + private void save(Settings settings) { + if (settings == null) { + return; + } + try { + Files.createDirectories(SETTINGS_DIR); + final Path settingsFile = SETTINGS_DIR.resolve(SETTINGS_FILE); + final OutputStream out = Files.newOutputStream(settingsFile, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); + objectMapper.writeValue(out, settings); + } catch (IOException e) { + LOG.error("Failed to save settings.", e); + } + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/SingleInstanceManager.java b/main/ui/src/main/java/org/cryptomator/ui/util/SingleInstanceManager.java index 4b687b7ce..a14b9f242 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/SingleInstanceManager.java +++ b/main/ui/src/main/java/org/cryptomator/ui/util/SingleInstanceManager.java @@ -30,7 +30,7 @@ import java.util.concurrent.ExecutorService; import java.util.prefs.Preferences; import org.apache.commons.io.IOUtils; -import org.cryptomator.ui.Main; +import org.cryptomator.ui.Cryptomator; import org.cryptomator.ui.util.ListenerRegistry.ListenerRegistration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -193,7 +193,7 @@ public class SingleInstanceManager { IOUtils.closeQuietly(selector); IOUtils.closeQuietly(channel); if (getSavedPort(applicationKey).orElse(-1).equals(port)) { - Preferences.userNodeForPackage(Main.class).remove(applicationKey); + Preferences.userNodeForPackage(Cryptomator.class).remove(applicationKey); } } @@ -226,7 +226,7 @@ public class SingleInstanceManager { /** * Checks if there is a valid port at - * {@link Preferences#userNodeForPackage(Class)} for {@link Main} under the + * {@link Preferences#userNodeForPackage(Class)} for {@link Cryptomator} under the * given applicationKey, tries to connect to the port at the loopback * address and checks if the port identifies with the applicationKey. * @@ -284,7 +284,7 @@ public class SingleInstanceManager { } static Optional getSavedPort(String applicationKey) { - int port = Preferences.userNodeForPackage(Main.class).getInt(applicationKey, -1); + int port = Preferences.userNodeForPackage(Cryptomator.class).getInt(applicationKey, -1); if (port == -1) { LOG.info("no running instance found"); @@ -296,7 +296,7 @@ public class SingleInstanceManager { /** * Creates a server socket on a free port and saves the port in - * {@link Preferences#userNodeForPackage(Class)} for {@link Main} under the + * {@link Preferences#userNodeForPackage(Class)} for {@link Cryptomator} under the * given applicationKey. * * @param applicationKey @@ -312,7 +312,7 @@ public class SingleInstanceManager { channel.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); final int port = ((InetSocketAddress) channel.getLocalAddress()).getPort(); - Preferences.userNodeForPackage(Main.class).putInt(applicationKey, port); + Preferences.userNodeForPackage(Cryptomator.class).putInt(applicationKey, port); LOG.info("InstanceManager bound to port {}", port); Selector selector = Selector.open();