1 package tim.prune.gui.map;
4 import java.awt.Toolkit;
5 import java.io.IOException;
6 import java.io.InputStream;
8 import java.net.URLConnection;
9 import java.util.HashSet;
11 import tim.prune.GpsPrune;
14 * Class to asynchronously download a tile from a url
15 * and populate an Image object with the contents
17 public class TileDownloader implements Runnable
19 private MapTileManager _manager = null;
20 private URL _url = null;
21 private int _layer = 0;
22 private int _x = 0, _y = 0;
23 private int _zoom = 0;
25 /** Hashset of all blocked / 404 tiles to avoid requesting them again */
26 private static final HashSet<String> BLOCKED_URLS = new HashSet<String>();
27 /** Hashset of all currently loading tiles to avoid requesting them again */
28 private static final HashSet<String> LOADING_URLS = new HashSet<String>();
29 /** Flag to maintain whether connection is active or not */
30 private static boolean CONNECTION_ACTIVE = true;
34 * Constructor (private)
35 * @param inManager parent manager for callback
36 * @param inUrl URL to load
37 * @param inLayer layer index from 0
38 * @param inX x coordinate of tile
39 * @param inY y coordinate of tile
40 * @param inZoom zoom level
42 private TileDownloader(MapTileManager inManager, URL inUrl, int inLayer, int inX, int inY, int inZoom)
52 * Trigger a download in a new thread
53 * @param inManager manager to callback when image is loaded
54 * @param inUrl URL to load
55 * @param inLayer layer index from 0
56 * @param inX x coordinate of tile
57 * @param inY y coordinate of tile
58 * @param inZoom current zoom level
60 public static synchronized void triggerLoad(MapTileManager inManager, URL inUrl, int inLayer,
61 int inX, int inY, int inZoom)
63 if (inManager != null && inUrl != null)
65 String url = inUrl.toString();
66 // System.out.println("Trigger load: " + url);
67 if (!BLOCKED_URLS.contains(url) && !LOADING_URLS.contains(url))
69 // System.out.println("Not blocked: " + url);
70 LOADING_URLS.add(url);
71 new Thread(new TileDownloader(inManager, inUrl, inLayer, inX, inY, inZoom)).start();
74 System.out.println("Already blocked: " + url);
80 * Run method, called in separate thread
84 InputStream in = null;
87 // System.out.println("TD Running thread to get: " + _url.toString());
88 // Set http user agent on connection
89 URLConnection conn = _url.openConnection();
90 conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
91 in = conn.getInputStream();
92 int len = conn.getContentLength();
95 byte[] data = new byte[len];
97 while (totalRead < len)
99 int numRead = in.read(data, totalRead, len-totalRead);
100 totalRead += numRead;
102 Image tile = Toolkit.getDefaultToolkit().createImage(data);
105 // Pass back to manager so it can be stored in its memory cache
106 _manager.notifyImageLoaded(tile, _layer, _x, _y, _zoom);
108 if (!CONNECTION_ACTIVE)
110 // We've just come back online, so forget which tiles gave 404 before
111 System.out.println("Deleting blocked urls, currently holds " + BLOCKED_URLS.size());
112 synchronized(this.getClass())
114 BLOCKED_URLS.clear();
116 CONNECTION_ACTIVE = true;
120 catch (IOException e)
122 System.err.println("IOE: " + e.getClass().getName() + " - " + e.getMessage());
123 synchronized(this.getClass())
125 BLOCKED_URLS.add(_url.toString());
127 try {in.close();} catch (Exception e2) {}
128 CONNECTION_ACTIVE = false; // lost connection?
130 LOADING_URLS.remove(_url.toString());