Index: src/org/openstreetmap/josm/io/CachedFile.java
===================================================================
--- src/org/openstreetmap/josm/io/CachedFile.java	(revision 16782)
+++ src/org/openstreetmap/josm/io/CachedFile.java	(working copy)
@@ -16,14 +16,18 @@
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
 import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 import java.util.zip.ZipEntry;
@@ -71,6 +75,23 @@
         IfModifiedSince
     }
 
+    /**
+     * Options that may be useful to more accurately control cached files.
+     *
+     * @author Taylor Smock
+     * @since xxx
+     */
+    public enum Options {
+        /**
+         * Fail quickly (~1 second)
+         */
+        FastFail,
+        /**
+         * Delete the files on graceful exit
+         */
+        DeleteOnExit,
+    }
+
     protected String name;
     protected long maxAge;
     protected String destDir;
@@ -77,12 +98,13 @@
     protected String httpAccept;
     protected CachingStrategy cachingStrategy;
 
-    private boolean fastFail;
     private HttpClient activeConnection;
     protected File cacheFile;
     protected boolean initialized;
     protected String parameter;
 
+    protected final Set<Options> options = EnumSet.noneOf(Options.class);
+
     public static final long DEFAULT_MAXTIME = -1L;
     public static final long DAYS = TimeUnit.DAYS.toSeconds(1); // factor to get caching time in days
 
@@ -177,7 +199,11 @@
      * @param fastFail whether opening HTTP connections should fail fast
      */
     public void setFastFail(boolean fastFail) {
-        this.fastFail = fastFail;
+        if (fastFail) {
+            options.add(Options.FastFail);
+        } else {
+            options.remove(Options.FastFail);
+        }
     }
 
     /**
@@ -189,6 +215,12 @@
         this.parameter = parameter;
     }
 
+    /**
+     * Get the name of the file. If a URL parameter is set,
+     * some characters will be deleted.
+     *
+     * @return The name of the file
+     */
     public String getName() {
         if (parameter != null)
             return name.replaceAll("%<(.*)>", "");
@@ -205,6 +237,11 @@
         return maxAge;
     }
 
+    /**
+     * The destination directory of the downloaded file
+     * @return The destination directory. If {@code null}, a default directory
+     * will be selected on download.
+     */
     public String getDestDir() {
         return destDir;
     }
@@ -425,7 +462,6 @@
     }
 
     private File checkLocal(URL url) throws IOException {
-        String prefKey = getPrefKey(url, destDir);
         String urlStr = url.toExternalForm();
         if (parameter != null)
             urlStr = urlStr.replaceAll("%<(.*)>", "");
@@ -432,30 +468,44 @@
         long age = 0L;
         long maxAgeMillis = TimeUnit.SECONDS.toMillis(maxAge);
         Long ifModifiedSince = null;
-        File localFile = null;
-        List<String> localPathEntry = new ArrayList<>(Config.getPref().getList(prefKey));
         boolean offline = NetworkManager.isOffline(urlStr);
-        if (localPathEntry.size() == 2) {
-            localFile = new File(localPathEntry.get(1));
-            if (!localFile.exists()) {
-                localFile = null;
-            } else {
-                if (maxAge == DEFAULT_MAXTIME
-                        || maxAge <= 0 // arbitrary value <= 0 is deprecated
-                ) {
-                    maxAgeMillis = TimeUnit.SECONDS.toMillis(Config.getPref().getLong("mirror.maxtime", TimeUnit.DAYS.toSeconds(7)));
-                }
-                age = System.currentTimeMillis() - Long.parseLong(localPathEntry.get(0));
-                if (offline || age < maxAgeMillis) {
-                    return localFile;
-                } else if (NetworkManager.isOffline(OnlineResource.CACHE_UPDATES)) {
-                    Logging.warn(OfflineAccessException.forResource(tr("Cache update for {0}", urlStr)).getMessage());
-                    return localFile;
-                }
-                if (cachingStrategy == CachingStrategy.IfModifiedSince) {
-                    ifModifiedSince = Long.valueOf(localPathEntry.get(0));
-                }
+
+        /** Start check for local file */
+        boolean nullDestDir = destDir == null;
+        if (nullDestDir) {
+            destDir = Config.getDirs().getCacheDirectory(true).getPath();
+        }
+        String localPath = getFilePath(urlStr, destDir);
+        File localFile = new File(destDir, localPath);
+        if (!localFile.exists()) {
+            localFile = null;
+        }
+        if (nullDestDir) {
+            destDir = null;
+        }
+        /** End check for local file */
+
+        if (localFile != null && !localFile.exists()) {
+            localFile = null;
+        } else if (localFile != null) {
+            if (maxAge == DEFAULT_MAXTIME
+                    || maxAge <= 0 // arbitrary value <= 0 is deprecated
+            ) {
+                maxAgeMillis = TimeUnit.SECONDS.toMillis(Config.getPref().getLong("mirror.maxtime", TimeUnit.DAYS.toSeconds(7)));
             }
+
+            BasicFileAttributes attributes = Files.readAttributes(localFile.toPath(), BasicFileAttributes.class);
+            Long fileAge = attributes.lastModifiedTime().toMillis();
+            age = System.currentTimeMillis() - fileAge;
+            if (offline || age < maxAgeMillis) {
+                return localFile;
+            } else if (NetworkManager.isOffline(OnlineResource.CACHE_UPDATES)) {
+                Logging.warn(OfflineAccessException.forResource(tr("Cache update for {0}", urlStr)).getMessage());
+                return localFile;
+            }
+            if (cachingStrategy == CachingStrategy.IfModifiedSince) {
+                ifModifiedSince = fileAge;
+            }
         }
         if (destDir == null) {
             destDir = Config.getDirs().getCacheDirectory(true).getPath();
@@ -483,9 +533,7 @@
                 url = new URL(uc);
         }
 
-        String a = urlStr.replaceAll("[^A-Za-z0-9_.-]", "_");
-        String localPath = "mirror_" + a;
-        localPath = truncatePath(destDir, localPath);
+        localPath = getFilePath(urlStr, destDir);
         destDirFile = new File(destDir, localPath + ".tmp");
         try {
             activeConnection = HttpClient.create(url)
@@ -492,14 +540,12 @@
                     .setAccept(httpAccept)
                     .setIfModifiedSince(ifModifiedSince == null ? 0L : ifModifiedSince)
                     .setHeaders(httpHeaders);
-            if (fastFail) {
+            if (options.contains(Options.FastFail)) {
                 activeConnection.setReadTimeout(1000);
             }
             final HttpClient.Response con = activeConnection.connect();
             if (ifModifiedSince != null && con.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
                 Logging.debug("304 Not Modified ({0})", urlStr);
-                Config.getPref().putList(prefKey,
-                        Arrays.asList(Long.toString(System.currentTimeMillis()), localPathEntry.get(1)));
                 return localFile;
             } else if (con.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
                 throw new IOException(tr("The requested URL {0} was not found", urlStr));
@@ -510,8 +556,9 @@
             activeConnection = null;
             localFile = new File(destDir, localPath);
             if (PlatformManager.getPlatform().rename(destDirFile, localFile)) {
-                Config.getPref().putList(prefKey,
-                        Arrays.asList(Long.toString(System.currentTimeMillis()), localFile.toString()));
+                if (options.contains(Options.DeleteOnExit)) {
+                    localFile.deleteOnExit();
+                }
             } else {
                 Logging.warn(tr("Failed to rename file {0} to {1}.",
                 destDirFile.getPath(), localFile.getPath()));
@@ -528,6 +575,12 @@
         return localFile;
     }
 
+    private static String getFilePath(String urlStr, String destDir) {
+        String a = urlStr.replaceAll("[^A-Za-z0-9_.-]", "_");
+        String localPath = "mirror_" + a;
+        return truncatePath(destDir, localPath);
+    }
+
     private static String truncatePath(String directory, String fileName) {
         if (directory.length() + fileName.length() > 255) {
             // Windows doesn't support paths longer than 260, leave 5 chars as safe buffer, 4 will be used by ".tmp"
@@ -586,4 +639,35 @@
             Utils.deleteFile(f);
         }
     }
+
+    /**
+     * Add an option to be used prior to getting the file
+     *
+     * @param option The option to add
+     * @since xxx
+     */
+    public void addOption(Options option) {
+        options.add(option);
+    }
+
+    /**
+     * Remove an option to be used prior to getting the file
+     *
+     * @param option The option to remove
+     * @since xxx
+     */
+    public void removeOption(Options option) {
+        options.remove(option);
+    }
+
+    /**
+     * CachedFile uses options when getting the actual file.
+     * These should generally be set prior to any action which may get a file.
+     *
+     * @return The options used by this CachedFile in an unmodifiable collection
+     * @since xxx
+     */
+    public Collection<Options> getOptions() {
+        return Collections.unmodifiableSet(options);
+    }
 }
