From 6ab55d3f236c98b4381cc8b37057e684aa522e7f Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Sun, 09 Dec 2018 14:27:49 +0000
Subject: [PATCH] Caches...

---
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java         |   60 ++++---------------
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java      |    2 
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java         |    2 
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java |   76 +++++++++++++++++++++++++
 borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java |   16 ++++
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java           |   16 ++--
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java         |    2 
 7 files changed, 115 insertions(+), 59 deletions(-)

diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
index 569c11f..b31e7e0 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
@@ -1,7 +1,6 @@
 package de.micromata.borgbutler.cache;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
-import de.micromata.borgbutler.config.BorgRepoConfig;
 import de.micromata.borgbutler.config.Definitions;
 import de.micromata.borgbutler.json.JsonUtils;
 import lombok.Getter;
@@ -15,73 +14,40 @@
 
 import java.io.*;
 import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
 
-public abstract class AbstractCache<T> {
+public abstract class AbstractCache {
     private static Logger log = LoggerFactory.getLogger(AbstractCache.class);
     private static final String CACHE_FILE_PREFIX = "cache-";
     private static final String CACHE_FILE_EXTENSION = "json";
-    private static final String CACHE_FILE_ZIP_EXTENSION = ".zip";
+    private static final String CACHE_FILE_ZIP_EXTENSION = ".gz";
 
     /**
      * INITIAL - on startup (not yet read), DIRTY - modifications not written, SAVED - content written to file.
      */
-    private enum STATE {INITIAL, DIRTY, SAVED}
+    protected enum STATE {INITIAL, DIRTY, SAVED}
 
     @JsonIgnore
     protected File cacheFile;
     @JsonIgnore
     @Getter
-    private boolean zip;
+    private boolean compress;
+    @Getter
     @JsonIgnore
     private STATE state = STATE.INITIAL;
     @Getter
     private Date lastModified;
     @Getter
     private Date created;
-    @Getter
-    protected Map<String, T> elements = new HashMap<>();
-
-    public T get(BorgRepoConfig repoConfig, String identifier) {
-        if (identifier == null) {
-            return null;
-        }
-        if (this.state == STATE.INITIAL) {
-            read();
-        }
-        for (T element : elements.values()) {
-            if (matches(element, identifier)) {
-                return element;
-            }
-        }
-        return load(repoConfig, identifier);
-    }
-
-    protected abstract T load(BorgRepoConfig repoConfig, String identifier);
-
-    public abstract boolean matches(T element, String identifier);
-
-    public abstract String getIdentifier(T element);
-
-    public abstract void updateFrom(T dest, T source);
 
     /**
      * Removes all entries (doesn't effect the cache files!).
      */
     public void clear() {
-        elements.clear();
         state = STATE.DIRTY;
     }
 
-    public void upsert(BorgRepoConfig repoConfig, T element) {
-        T existingElement = get(repoConfig, getIdentifier(element));
-        if (existingElement == null) {
-            elements.put(getIdentifier(element), element);
-        } else {
-            updateFrom(existingElement, element);
-        }
-        state = STATE.DIRTY; // Needed to save cache to file.
+    protected void setDirty() {
+        state = STATE.DIRTY;
     }
 
     public void read() {
@@ -93,7 +59,7 @@
             }
             log.info("Parsing cache file '" + cacheFile.getAbsolutePath() + "'.");
             String json;
-            if (zip) {
+            if (compress) {
                 try (GzipCompressorInputStream in = new GzipCompressorInputStream(new FileInputStream(cacheFile))) {
                     StringWriter writer = new StringWriter();
                     IOUtils.copy(in, writer, Definitions.STD_CHARSET);
@@ -104,10 +70,10 @@
             }
             AbstractCache readCache = JsonUtils.fromJson(this.getClass(), json);
             if (readCache != null) {
-                this.elements = readCache.elements;
                 this.lastModified = readCache.lastModified;
                 this.created = readCache.created;
                 this.state = STATE.SAVED; // State of cache is updated from cache file.
+                update(readCache);
             } else {
                 log.error("Error while parsing cache: " + cacheFile.getAbsolutePath());
                 this.state = STATE.DIRTY; // Needed to save cache to file.
@@ -119,6 +85,8 @@
         }
     }
 
+    protected abstract void update(AbstractCache readCache);
+
     public void save() {
         if (this.state == STATE.SAVED || this.state == STATE.INITIAL) {
             log.info("Cache file is up to date (nothing to save): " + cacheFile);
@@ -132,7 +100,7 @@
         }
         String json = JsonUtils.toJson(this);
         try {
-            if (this.zip) {
+            if (this.compress) {
                 try (GzipCompressorOutputStream out = new GzipCompressorOutputStream(new FileOutputStream(cacheFile))) {
                     IOUtils.copy(new StringReader(json), out, Definitions.STD_CHARSET);
                 }
@@ -158,9 +126,9 @@
     }
 
     AbstractCache(File cacheDir, String cacheFilename, boolean zip) {
-        this.zip = zip;
+        this.compress = zip;
         String filename = CACHE_FILE_PREFIX + cacheFilename + "." + CACHE_FILE_EXTENSION;
-        if (this.zip)
+        if (this.compress)
             filename = filename + CACHE_FILE_EXTENSION;
         cacheFile = new File(cacheDir, CACHE_FILE_PREFIX + cacheFilename + "." + CACHE_FILE_EXTENSION);
         this.state = STATE.INITIAL;
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java
new file mode 100644
index 0000000..c7e5ad4
--- /dev/null
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java
@@ -0,0 +1,76 @@
+package de.micromata.borgbutler.cache;
+
+import de.micromata.borgbutler.config.BorgRepoConfig;
+import lombok.Getter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class AbstractElementsCache<T> extends AbstractCache {
+    private static Logger log = LoggerFactory.getLogger(AbstractElementsCache.class);
+
+    @Getter
+    protected Map<String, T> elements = new HashMap<>();
+
+    public T get(BorgRepoConfig repoConfig, String identifier) {
+        if (identifier == null) {
+            return null;
+        }
+        if (getState() == STATE.INITIAL) {
+            read();
+        }
+        for (T element : elements.values()) {
+            if (matches(element, identifier)) {
+                return element;
+            }
+        }
+        return load(repoConfig, identifier);
+    }
+
+    protected abstract T load(BorgRepoConfig repoConfig, String identifier);
+
+    public abstract boolean matches(T element, String identifier);
+
+    public abstract String getIdentifier(T element);
+
+    public abstract void updateFrom(T dest, T source);
+
+    /**
+     * Removes all entries (doesn't effect the cache files!).
+     */
+    public void clear() {
+        elements.clear();
+        super.clear();
+    }
+
+    public void upsert(BorgRepoConfig repoConfig, T element) {
+        T existingElement = get(repoConfig, getIdentifier(element));
+        if (existingElement == null) {
+            elements.put(getIdentifier(element), element);
+        } else {
+            updateFrom(existingElement, element);
+        }
+        setDirty();
+    }
+
+    protected void update(AbstractCache readCache) {
+        this.elements = ((AbstractElementsCache)readCache).elements;
+    }
+
+    /**
+     * Needed by jackson for deserialization.
+     */
+    AbstractElementsCache() {
+    }
+
+    AbstractElementsCache(File cacheDir, String cacheFilename) {
+        super(cacheDir, cacheFilename);
+    }
+
+    AbstractElementsCache(File cacheDir, String cacheFilename, boolean compress) {
+        super(cacheDir, cacheFilename, compress);
+    }
+}
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java
index c418939..3f31c3c 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveListCache.java
@@ -8,7 +8,7 @@
 
 import java.io.File;
 
-public class ArchiveListCache extends AbstractCache<ArchiveInfo> {
+public class ArchiveListCache extends AbstractElementsCache<ArchiveInfo> {
     private static Logger log = LoggerFactory.getLogger(ArchiveListCache.class);
     public static final String CACHE_ARCHIVE_LISTS_BASENAME = "archive-lists";
 
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
index f9e9789..1be4dca 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
@@ -1,6 +1,7 @@
 package de.micromata.borgbutler.cache;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
+import de.micromata.borgbutler.config.ConfigurationHandler;
 import lombok.Getter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -11,7 +12,7 @@
 
 public class ButlerCache {
     private static Logger log = LoggerFactory.getLogger(ButlerCache.class);
-    public static final String CACHE_DIR_NAME = ".borgbutler";
+    public static final String CACHE_DIR_NAME = "caches";
     private static ButlerCache instance = new ButlerCache();
 
     @Getter
@@ -19,7 +20,7 @@
     @Getter
     private RepoListCache repoListCache;
     private ArchiveListCache archiveListCache;
-    private List<AbstractCache> caches;
+    private List<AbstractElementsCache> caches;
 
     @JsonIgnore
     private File cacheDir;
@@ -29,13 +30,13 @@
     }
 
     public void read() {
-        for (AbstractCache cache : caches) {
+        for (AbstractElementsCache cache : caches) {
             cache.read();
         }
     }
 
     public void save() {
-        for (AbstractCache cache : caches) {
+        for (AbstractElementsCache cache : caches) {
             cache.save();
         }
     }
@@ -46,19 +47,18 @@
     public void removeAllCacheFiles() {
         File[] files = cacheDir.listFiles();
         for (File file : files) {
-            if (AbstractCache.isCacheFile(file)) {
+            if (AbstractElementsCache.isCacheFile(file)) {
                 log.info("Deleting cache file: " + file.getAbsolutePath());
                 file.delete();
             }
         }
-        for (AbstractCache cache : caches) {
+        for (AbstractElementsCache cache : caches) {
             cache.clear();
         }
     }
 
     private ButlerCache() {
-        String homeDir = System.getProperty("user.home");
-        cacheDir = new File(homeDir, CACHE_DIR_NAME);
+        cacheDir = new File(ConfigurationHandler.getInstance().getWorkingDir(), CACHE_DIR_NAME);
         if (!cacheDir.exists()) {
             log.info("Creating cache dir: " + cacheDir.getAbsolutePath());
             cacheDir.mkdir();
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java
index d6f360d..b71fb55 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoInfoCache.java
@@ -8,7 +8,7 @@
 
 import java.io.File;
 
-public class RepoInfoCache extends AbstractCache<RepoInfo> {
+public class RepoInfoCache extends AbstractElementsCache<RepoInfo> {
     private static Logger log = LoggerFactory.getLogger(RepoInfoCache.class);
     public static final String CACHE_REPOS_BASENAME = "repo-infos";
 
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java
index 6a3eea3..ef5773d 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/RepoListCache.java
@@ -8,7 +8,7 @@
 
 import java.io.File;
 
-public class RepoListCache extends AbstractCache<RepoList> {
+public class RepoListCache extends AbstractElementsCache<RepoList> {
     private static Logger log = LoggerFactory.getLogger(RepoListCache.class);
     public static final String CACHE_REPO_LISTS_BASENAME = "repo-lists";
 
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java
index 0575a77..e3bf842 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java
@@ -12,11 +12,13 @@
 public class ConfigurationHandler {
     private static Logger log = LoggerFactory.getLogger(ConfigurationHandler.class);
     private static ConfigurationHandler instance = new ConfigurationHandler();
+    private static final String APP_WORKING_DIR = ".borgbutler";
     private static final String CONFIG_FILENAME = ".borgbutler.json";
     private static final String CONFIG_BACKUP_FILENAME = ".borgbutler-bak.json";
     @Getter
     private File configFile;
     private File backupConfigFile;
+    private File workingDir;
     private Configuration configuration = new Configuration();
 
     public static ConfigurationHandler getInstance() {
@@ -53,8 +55,18 @@
         }
     }
 
+    public File getWorkingDir() {
+        if (!workingDir.exists()) {
+            log.info("Creating borg-butlers working directory: " + workingDir.getAbsolutePath());
+            workingDir.mkdirs();
+        }
+        return workingDir;
+    }
+
     private ConfigurationHandler() {
-        configFile = new File(System.getProperty("user.home"), CONFIG_FILENAME);
-        backupConfigFile = new File(System.getProperty("user.home"), CONFIG_BACKUP_FILENAME);
+        File userHome = new File(System.getProperty("user.home"));
+        configFile = new File(userHome, CONFIG_FILENAME);
+        backupConfigFile = new File(userHome, CONFIG_BACKUP_FILENAME);
+        workingDir = new File(userHome, APP_WORKING_DIR);
     }
 }

--
Gitblit v1.10.0