]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/gui/map/TileDownloader.java
Version 14, October 2012
[GpsPrune.git] / tim / prune / gui / map / TileDownloader.java
1 package tim.prune.gui.map;
2
3 import java.awt.Image;
4 import java.awt.Toolkit;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.net.URL;
8 import java.net.URLConnection;
9 import java.util.HashSet;
10
11 import tim.prune.GpsPrune;
12
13 /**
14  * Class to asynchronously download a tile from a url
15  * and populate an Image object with the contents
16  */
17 public class TileDownloader implements Runnable
18 {
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;
24         /** Hashset of all blocked / 404 tiles to avoid requesting them again */
25         private static final HashSet<String> BLOCKED_URLS = new HashSet<String>();
26         /** Hashset of all currently loading tiles to avoid requesting them again */
27         private static final HashSet<String> LOADING_URLS = new HashSet<String>();
28
29
30         /**
31          * Constructor (private)
32          * @param inManager parent manager for callback
33          * @param inUrl URL to load
34          * @param inLayer layer index from 0
35          * @param inX x coordinate of tile
36          * @param inY y coordinate of tile
37          * @param inZoom zoom level
38          */
39         private TileDownloader(MapTileManager inManager, URL inUrl, int inLayer, int inX, int inY, int inZoom)
40         {
41                 _manager = inManager;
42                 _url = inUrl;
43                 _layer = inLayer;
44                 _x = inX; _y = inY;
45                 _zoom = inZoom;
46         }
47
48         /**
49          * Trigger a download in a new thread
50          * @param inManager manager to callback when image is loaded
51          * @param inUrl URL to load
52          * @param inLayer layer index from 0
53          * @param inX x coordinate of tile
54          * @param inY y coordinate of tile
55          * @param inZoom current zoom level
56          */
57         public static synchronized void triggerLoad(MapTileManager inManager, URL inUrl, int inLayer,
58                 int inX, int inY, int inZoom)
59         {
60                 if (inManager != null && inUrl != null)
61                 {
62                         String url = inUrl.toString();
63                         if (!BLOCKED_URLS.contains(url) && !LOADING_URLS.contains(url))
64                         {
65                                 LOADING_URLS.add(url);
66                                 new Thread(new TileDownloader(inManager, inUrl, inLayer, inX, inY, inZoom)).start();
67                         }
68                 }
69         }
70
71         /**
72          * Run method, called in separate thread
73          */
74         public void run()
75         {
76                 InputStream in = null;
77                 try
78                 {
79                         // Set http user agent on connection
80                         URLConnection conn = _url.openConnection();
81                         conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
82                         in = conn.getInputStream();
83                         int len = conn.getContentLength();
84                         if (len > 0)
85                         {
86                                 byte[] data = new byte[len];
87                                 int totalRead = 0;
88                                 while (totalRead < len)
89                                 {
90                                         int numRead = in.read(data, totalRead, len-totalRead);
91                                         totalRead += numRead;
92                                 }
93                                 Image tile = Toolkit.getDefaultToolkit().createImage(data);
94                                 in.close();
95
96                                 // Pass back to manager so it can be stored in its memory cache
97                                 _manager.notifyImageLoaded(tile, _layer, _x, _y, _zoom);
98                         }
99                 }
100                 catch (IOException e)
101                 {
102                         System.err.println("IOE: " + e.getClass().getName() + " - " + e.getMessage());
103                         synchronized(this.getClass())
104                         {
105                                 BLOCKED_URLS.add(_url.toString());
106                         }
107                         try {in.close();} catch (Exception e2) {}
108                 }
109                 LOADING_URLS.remove(_url.toString());
110         }
111 }