]> gitweb.fperrin.net Git - GpsPrune.git/blob - src/tim/prune/gui/map/TileDownloader.java
Version 20.4, May 2021
[GpsPrune.git] / src / 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
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;
31
32
33         /**
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
41          */
42         private TileDownloader(MapTileManager inManager, URL inUrl, int inLayer, int inX, int inY, int inZoom)
43         {
44                 _manager = inManager;
45                 _url = inUrl;
46                 _layer = inLayer;
47                 _x = inX; _y = inY;
48                 _zoom = inZoom;
49         }
50
51         /**
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
59          */
60         public static synchronized void triggerLoad(MapTileManager inManager, URL inUrl, int inLayer,
61                 int inX, int inY, int inZoom)
62         {
63                 if (inManager != null && inUrl != null)
64                 {
65                         String url = inUrl.toString();
66                         // System.out.println("Trigger load: " + url);
67                         if (!BLOCKED_URLS.contains(url) && !LOADING_URLS.contains(url))
68                         {
69                                 // System.out.println("Not blocked: " + url);
70                                 LOADING_URLS.add(url);
71                                 new Thread(new TileDownloader(inManager, inUrl, inLayer, inX, inY, inZoom)).start();
72                         }
73                         else {
74                                 System.out.println("Already blocked: " + url);
75                         }
76                 }
77         }
78
79         /**
80          * Run method, called in separate thread
81          */
82         public void run()
83         {
84                 InputStream in = null;
85                 try
86                 {
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();
93                         if (len > 0)
94                         {
95                                 byte[] data = new byte[len];
96                                 int totalRead = 0;
97                                 while (totalRead < len)
98                                 {
99                                         int numRead = in.read(data, totalRead, len-totalRead);
100                                         totalRead += numRead;
101                                 }
102                                 Image tile = Toolkit.getDefaultToolkit().createImage(data);
103                                 in.close();
104
105                                 // Pass back to manager so it can be stored in its memory cache
106                                 _manager.notifyImageLoaded(tile, _layer, _x, _y, _zoom);
107
108                                 if (!CONNECTION_ACTIVE)
109                                 {
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())
113                                         {
114                                                 BLOCKED_URLS.clear();
115                                         }
116                                         CONNECTION_ACTIVE = true;
117                                 }
118                         }
119                 }
120                 catch (IOException e)
121                 {
122                         System.err.println("IOE: " + e.getClass().getName() + " - " + e.getMessage());
123                         synchronized(this.getClass())
124                         {
125                                 BLOCKED_URLS.add(_url.toString());
126                         }
127                         try {in.close();} catch (Exception e2) {}
128                         CONNECTION_ACTIVE = false;      // lost connection?
129                 }
130                 LOADING_URLS.remove(_url.toString());
131         }
132 }