]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/gui/map/DiskTileCacher.java
Version 14, October 2012
[GpsPrune.git] / tim / prune / gui / map / DiskTileCacher.java
index dfc4f927aed2aee0baef04623c37831e824a5156..350b3b4b1cdb1f2bbc53ff9f98accadbb1d0bbe5 100644 (file)
@@ -8,6 +8,10 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashSet;
+
+import tim.prune.GpsPrune;
 
 /**
  * Class to control the reading and saving of map tiles
@@ -23,6 +27,8 @@ public class DiskTileCacher implements Runnable
        private ImageObserver _observer = null;
        /** Time limit to cache images for */
        private static final long CACHE_TIME_LIMIT = 20 * 24 * 60 * 60 * 1000; // 20 days in ms
+       /** Hashset of all blocked / 404 tiles to avoid requesting them again */
+       private static final HashSet<String> BLOCKED_URLS = new HashSet<String>();
 
        /**
         * Private constructor
@@ -49,7 +55,8 @@ public class DiskTileCacher implements Runnable
                if (inBasePath == null) {return null;}
                File tileFile = new File(inBasePath, inTilePath);
                Image image = null;
-               if (tileFile.exists() && tileFile.canRead() && tileFile.length() > 0) {
+               if (tileFile.exists() && tileFile.canRead() && tileFile.length() > 0)
+               {
                        long fileStamp = tileFile.lastModified();
                        if (!inCheckAge || ((System.currentTimeMillis()-fileStamp) < CACHE_TIME_LIMIT))
                        {
@@ -68,28 +75,31 @@ public class DiskTileCacher implements Runnable
         * @param inBasePath base path to disk cache
         * @param inTilePath relative path to this tile
         * @param inObserver observer to inform when load complete
+        * @return true if successful, false for failure
         */
-       public static void saveTile(URL inUrl, String inBasePath, String inTilePath, ImageObserver inObserver)
+       public static boolean saveTile(URL inUrl, String inBasePath, String inTilePath, ImageObserver inObserver)
        {
-               if (inBasePath == null || inTilePath == null) {return;}
+               if (inBasePath == null || inTilePath == null) {return false;}
                // save file if possible
                File basePath = new File(inBasePath);
                if (!basePath.exists() || !basePath.isDirectory() || !basePath.canWrite()) {
-                       //System.err.println("Can't write");
                        // Can't write to base path
-                       return;
+                       return false;
                }
                File tileFile = new File(basePath, inTilePath);
                // Check if this file is already being loaded
-               if (!isBeingLoaded(tileFile))
+               if (isBeingLoaded(tileFile)) {return true;}
+               // Check if it has already failed
+               if (BLOCKED_URLS.contains(inUrl.toString())) {return true;}
+
+               File dir = tileFile.getParentFile();
+               // Start a new thread to load the image if necessary
+               if ((dir.exists() || dir.mkdirs()) && dir.canWrite())
                {
-                       File dir = tileFile.getParentFile();
-                       // Start a new thread to load the image if necessary
-                       if (dir.exists() || dir.mkdirs())
-                       {
-                               new DiskTileCacher(inUrl, tileFile, inObserver);
-                       }
+                       new DiskTileCacher(inUrl, tileFile, inObserver);
+                       return true;
                }
+               return false; // couldn't write the file
        }
 
        /**
@@ -113,34 +123,44 @@ public class DiskTileCacher implements Runnable
                FileOutputStream out = null;
                File tempFile = new File(_file.getAbsolutePath() + ".temp");
                // Use a synchronized block across all threads to make sure this url is only fetched once
-               synchronized (DiskTileCacher.class) {
+               synchronized (DiskTileCacher.class)
+               {
                        if (tempFile.exists()) {return;}
                        try {
                                if (!tempFile.createNewFile()) {return;}
                        }
                        catch (Exception e) {return;}
                }
-               try {
+               try
+               {
                        // Open streams from URL and to file
                        out = new FileOutputStream(tempFile);
-                       in = _url.openStream();
+                       // Set http user agent on connection
+                       URLConnection conn = _url.openConnection();
+                       conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
+                       in = conn.getInputStream();
                        int d = 0;
                        // Loop over each byte in the stream (maybe buffering is more efficient?)
                        while ((d = in.read()) >= 0) {
                                out.write(d);
                        }
                        finished = true;
-               } catch (IOException e) {}
-               finally {
-                       try {
-                               in.close();
-                               out.close();
-                               if (!finished) {tempFile.delete();}
+               } catch (IOException e) {
+                       System.err.println("ioe: " + e.getClass().getName() + " - " + e.getMessage());
+                       BLOCKED_URLS.add(_url.toString());
+               }
+               finally
+               {
+                       // clean up files
+                       try {in.close();} catch (Exception e) {} // ignore
+                       try {out.close();} catch (Exception e) {} // ignore
+                       if (!finished) {
+                               tempFile.delete();
                        }
-                       catch (Exception e) {} // ignore
                }
                // Move temp file to desired file location
-               if (!tempFile.renameTo(_file)) {
+               if (!tempFile.renameTo(_file))
+               {
                        // File couldn't be moved - delete both to be sure
                        tempFile.delete();
                        _file.delete();