From bed6732d354b09b25514e4b02c7fc3d99edb674b Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Fri, 11 Mar 2016 11:14:50 +0000 Subject: [PATCH] Unify application folder logic --- source/net/filebot/CacheManager.java | 19 +- source/net/filebot/HistorySpooler.java | 2 +- source/net/filebot/Main.java | 11 +- source/net/filebot/Settings.java | 172 ++++++++++-------- source/net/filebot/cli/GroovyPad.java | 3 +- .../net/filebot/format/MediaBindingBean.java | 5 +- .../filebot/format/SecureCompiledScript.java | 10 +- 7 files changed, 121 insertions(+), 101 deletions(-) diff --git a/source/net/filebot/CacheManager.java b/source/net/filebot/CacheManager.java index 962c826c..51f9318b 100644 --- a/source/net/filebot/CacheManager.java +++ b/source/net/filebot/CacheManager.java @@ -26,10 +26,12 @@ public class CacheManager { } private final net.sf.ehcache.CacheManager manager; + private final File diskStore; public CacheManager() { try { - this.manager = net.sf.ehcache.CacheManager.create(getConfiguration()); + this.diskStore = acquireDiskStore(); + this.manager = net.sf.ehcache.CacheManager.create(new Configuration().diskStore(new DiskStoreConfiguration().path(diskStore.getPath()))); } catch (IOException e) { throw new CacheException(e); } @@ -47,19 +49,13 @@ public class CacheManager { manager.removeAllCaches(); // clear all caches that have not been added yet - clearDiskStore(new File(manager.getConfiguration().getDiskStoreConfiguration().getPath())); + clearDiskStore(diskStore); } public synchronized void shutdown() { manager.shutdown(); } - private Configuration getConfiguration() throws IOException { - Configuration config = new Configuration(); - config.addDiskStore(getDiskStoreConfiguration()); - return config; - } - private void clearDiskStore(File cache) { getChildren(cache).stream().filter(f -> f.isFile() && !f.getName().startsWith(".")).forEach(f -> { if (!delete(f)) { @@ -68,9 +64,9 @@ public class CacheManager { }); } - private DiskStoreConfiguration getDiskStoreConfiguration() throws IOException { + private File acquireDiskStore() throws IOException { // prepare cache folder for this application instance - File cacheRoot = getApplicationCache().getCanonicalFile(); + File cacheRoot = ApplicationFolder.Cache.getCanonicalFile(); for (int i = 0; i < 10; i++) { File cache = new File(cacheRoot, Integer.toString(i)); @@ -116,7 +112,7 @@ public class CacheManager { Runtime.getRuntime().addShutdownHook(new ShutdownHook(this, channel, lock)); // cache for this application instance is successfully set up and locked - return new DiskStoreConfiguration().path(cache.getPath()); + return cache; } // try next lock file @@ -130,7 +126,6 @@ public class CacheManager { private static class ShutdownHook extends Thread { private final CacheManager manager; - private final FileChannel channel; private final FileLock lock; diff --git a/source/net/filebot/HistorySpooler.java b/source/net/filebot/HistorySpooler.java index a66b6750..5acc8c5e 100644 --- a/source/net/filebot/HistorySpooler.java +++ b/source/net/filebot/HistorySpooler.java @@ -39,7 +39,7 @@ public final class HistorySpooler { }); } - private File persistentHistoryFile = new File(getApplicationFolder(), "history.xml"); + private File persistentHistoryFile = ApplicationFolder.AppData.resolve("history.xml"); private int persistentHistoryTotalSize = -1; private boolean persistentHistoryEnabled = true; diff --git a/source/net/filebot/Main.java b/source/net/filebot/Main.java index 6968490f..68630575 100644 --- a/source/net/filebot/Main.java +++ b/source/net/filebot/Main.java @@ -43,6 +43,7 @@ import javax.swing.UIManager; import org.kohsuke.args4j.CmdLineException; import org.w3c.dom.Document; +import net.filebot.Settings.ApplicationFolder; import net.filebot.cli.ArgumentBean; import net.filebot.cli.ArgumentProcessor; import net.filebot.format.ExpressionFormat; @@ -85,7 +86,7 @@ public class Main { // clear preferences and cache if (args.clearCache()) { System.out.println("Clear cache and temporary files"); - for (File folder : getChildren(getApplicationFolder().getCanonicalFile(), FOLDERS)) { + for (File folder : getChildren(ApplicationFolder.AppData.getCanonicalFile(), FOLDERS)) { System.out.println("* Delete " + folder); delete(folder); } @@ -104,7 +105,7 @@ public class Main { initializeLogging(args); // make sure java.io.tmpdir exists - createFolders(getApplicationTempFolder()); + createFolders(ApplicationFolder.Temp.get()); // initialize this stuff before anything else CacheManager.getInstance(); @@ -410,7 +411,7 @@ public class Main { System.setProperty("sun.net.client.defaultReadTimeout", "60000"); System.setProperty("swing.crossplatformlaf", "javax.swing.plaf.nimbus.NimbusLookAndFeel"); - System.setProperty("grape.root", new File(getApplicationFolder(), "grape").getAbsolutePath()); + System.setProperty("grape.root", ApplicationFolder.AppData.resolve("grape").getAbsolutePath()); System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog"); System.setProperty("unixfs", Boolean.toString(args.unixfs)); @@ -424,7 +425,7 @@ public class Main { if (args.logFile != null) { File logFile = new File(args.logFile); if (!logFile.isAbsolute()) { - logFile = new File(new File(getApplicationFolder(), "logs"), logFile.getPath()).getAbsoluteFile(); // by default resolve relative paths against {applicationFolder}/logs/{logFile} + logFile = new File(ApplicationFolder.AppData.resolve("logs"), logFile.getPath()).getAbsoluteFile(); // by default resolve relative paths against {applicationFolder}/logs/{logFile} } if (!logFile.exists() && !logFile.getParentFile().mkdirs() && !logFile.createNewFile()) { throw new IOException("Failed to create log file: " + logFile); @@ -459,7 +460,7 @@ public class Main { // log errors to file try { - Handler error = createSimpleFileHandler(new File(getApplicationFolder(), "error.log"), Level.WARNING); + Handler error = createSimpleFileHandler(ApplicationFolder.AppData.resolve("error.log"), Level.WARNING); log.addHandler(error); debug.addHandler(error); } catch (Exception e) { diff --git a/source/net/filebot/Settings.java b/source/net/filebot/Settings.java index b8fcecbc..158fac98 100644 --- a/source/net/filebot/Settings.java +++ b/source/net/filebot/Settings.java @@ -135,58 +135,6 @@ public final class Settings { return Runtime.getRuntime().availableProcessors(); } - public static File getApplicationFolder() { - String applicationFolderPath = System.getProperty("application.dir"); - File applicationFolder = null; - - if (applicationFolderPath != null && !applicationFolderPath.isEmpty()) { - // use given path - applicationFolder = new File(applicationFolderPath); - } else { - // create folder in user home (can't use working directory for web start applications) - applicationFolder = new File(System.getProperty("user.home"), ".filebot"); - } - - // create folder if necessary - try { - createFolders(applicationFolder); - } catch (Exception e) { - throw new IllegalStateException("application.dir", e); - } - - return applicationFolder; - } - - public static File getApplicationCache() { - String cacheFolderPath = System.getProperty("application.cache"); - File cacheFolder = null; - - if (cacheFolderPath != null && !cacheFolderPath.isEmpty()) { - cacheFolder = new File(cacheFolderPath); - } else { - cacheFolder = new File(getApplicationFolder(), "cache"); - } - - return cacheFolder; - } - - public static File getApplicationTempFolder() { - return new File(System.getProperty("java.io.tmpdir")); - } - - public static File getRealUserHome() { - if (isMacSandbox()) { - // when running sandboxed applications user.home may point to the application-specific container - String username = System.getProperty("user.name"); - if (username != null && username.length() > 0) { - return new File("/Users", username); - } - } - - // default home - return new File(System.getProperty("user.home")); - } - public static String getAppStoreName() { if (isMacApp()) return "Mac App Store"; @@ -235,6 +183,104 @@ public final class Settings { return links; } + public static String getApplicationIdentifier() { + return String.format("%s %s (r%d)", getApplicationName(), getApplicationVersion(), getApplicationRevisionNumber()); + } + + public static String getJavaRuntimeIdentifier() { + return String.format("%s %s %s", System.getProperty("java.runtime.name"), System.getProperty("java.version"), GraphicsEnvironment.isHeadless() ? "(headless)" : "").trim(); + } + + private static String[] applicationArgumentArray; + + protected static void setApplicationArgumentArray(String[] args) { + applicationArgumentArray = args; + } + + public static ArgumentBean getApplicationArguments() { + try { + return ArgumentBean.parse(applicationArgumentArray); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + public static enum ApplicationFolder { + + AppData { + + @Override + public File get() { + String appdata = System.getProperty("application.dir"); + + if (appdata != null) { + // use given $APP_DATA folder + return new File(appdata); + } else { + // use $HOME/.filebot as application data folder + return new File(System.getProperty("user.home"), ".filebot"); + } + } + }, + + UserHome { + + @Override + public File get() { + // The user.home of sandboxed applications will point to the application-specific container + if (isMacSandbox()) { + return new File("/Users", System.getProperty("user.name", "anonymous")); + } + + // default user home + return new File(System.getProperty("user.home")); + } + + }, + + Temp { + + @Override + public File get() { + return new File(System.getProperty("java.io.tmpdir")); + } + }, + + Cache { + + @Override + public File get() { + String cache = System.getProperty("application.cache"); + if (cache != null) { + return new File(cache); + } + + // default to $APP_DATA/cache + return AppData.resolve("cache"); + } + }; + + public abstract File get(); + + public File resolve(String name) { + return new File(getCanonicalFile(), name); + } + + public File getCanonicalFile() { + File path = get(); + try { + if (!path.isDirectory()) { + createFolders(path); + } + return path.getCanonicalFile(); + } catch (Exception e) { + debug.log(Level.SEVERE, String.format("Failed to create application folder: %s => %s", this, path), e); + return path; + } + } + + } + public static Settings forPackage(Class type) { return new Settings(Preferences.userNodeForPackage(type)); } @@ -295,26 +341,4 @@ public final class Settings { } } - public static String getApplicationIdentifier() { - return String.format("%s %s (r%d)", getApplicationName(), getApplicationVersion(), getApplicationRevisionNumber()); - } - - public static String getJavaRuntimeIdentifier() { - return String.format("%s %s %s", System.getProperty("java.runtime.name"), System.getProperty("java.version"), GraphicsEnvironment.isHeadless() ? "(headless)" : "").trim(); - } - - private static String[] applicationArgumentArray; - - protected static void setApplicationArgumentArray(String[] args) { - applicationArgumentArray = args; - } - - public static ArgumentBean getApplicationArguments() { - try { - return ArgumentBean.parse(applicationArgumentArray); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - } diff --git a/source/net/filebot/cli/GroovyPad.java b/source/net/filebot/cli/GroovyPad.java index 67e36dd5..90324d78 100644 --- a/source/net/filebot/cli/GroovyPad.java +++ b/source/net/filebot/cli/GroovyPad.java @@ -33,6 +33,7 @@ import javax.swing.text.JTextComponent; import net.filebot.ResourceManager; import net.filebot.Settings; +import net.filebot.Settings.ApplicationFolder; import net.filebot.cli.ArgumentProcessor.DefaultScriptProvider; import net.filebot.util.TeePrintStream; @@ -142,7 +143,7 @@ public class GroovyPad extends JFrame { } protected FileLocation getFileLocation(String name) throws IOException { - File pad = new File(Settings.getApplicationFolder(), name); + File pad = ApplicationFolder.AppData.resolve(name); if (!pad.exists()) { // use this default value so people can easily submit bug reports with fn:sysinfo logs ScriptShellMethods.saveAs("runScript 'fn:sysinfo'", pad); diff --git a/source/net/filebot/format/MediaBindingBean.java b/source/net/filebot/format/MediaBindingBean.java index 9c4386d1..584693e7 100644 --- a/source/net/filebot/format/MediaBindingBean.java +++ b/source/net/filebot/format/MediaBindingBean.java @@ -42,6 +42,7 @@ import net.filebot.Language; import net.filebot.MediaTypes; import net.filebot.MetaAttributeView; import net.filebot.Settings; +import net.filebot.Settings.ApplicationFolder; import net.filebot.WebServices; import net.filebot.hash.HashType; import net.filebot.media.MetaAttributes; @@ -848,8 +849,8 @@ public class MediaBindingBean { } @Define("home") - public File getUserHome() throws IOException { - return Settings.getRealUserHome(); + public File getUserHome() { + return ApplicationFolder.UserHome.getCanonicalFile(); } @Define("now") diff --git a/source/net/filebot/format/SecureCompiledScript.java b/source/net/filebot/format/SecureCompiledScript.java index 581fd239..7d5ecdce 100644 --- a/source/net/filebot/format/SecureCompiledScript.java +++ b/source/net/filebot/format/SecureCompiledScript.java @@ -20,6 +20,7 @@ import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptException; +import net.filebot.Settings.ApplicationFolder; import net.filebot.util.ExceptionUtilities; public class SecureCompiledScript extends CompiledScript { @@ -46,12 +47,9 @@ public class SecureCompiledScript extends CompiledScript { permissions.add(new ReflectPermission("suppressAccessChecks")); permissions.add(new ReflectPermission("newProxyInPackage.*")); - // write permissions for temp and cache folders - try { - permissions.add(new FilePermission(new File(System.getProperty("java.io.tmpdir")).getAbsolutePath() + File.separator + "-", "write, delete")); - permissions.add(new FilePermission(new File(System.getProperty("ehcache.disk.store.dir")).getAbsolutePath() + File.separator + "-", "write, delete")); - } catch (Exception e) { - // ignore + // write permissions for cache and temp folders + for (ApplicationFolder it : ApplicationFolder.values()) { + permissions.add(new FilePermission(it.getCanonicalFile() + File.separator + "-", "read, write, delete")); } return permissions;