X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Fgui%2Fmap%2FTileDownloader.java;fp=src%2Ftim%2Fprune%2Fgui%2Fmap%2FTileDownloader.java;h=7c7540066c839d86105f71a0a95b3af1398d17de;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/gui/map/TileDownloader.java b/src/tim/prune/gui/map/TileDownloader.java new file mode 100644 index 0000000..7c75400 --- /dev/null +++ b/src/tim/prune/gui/map/TileDownloader.java @@ -0,0 +1,114 @@ +package tim.prune.gui.map; + +import java.awt.Image; +import java.awt.Toolkit; +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 asynchronously download a tile from a url + * and populate an Image object with the contents + */ +public class TileDownloader implements Runnable +{ + private MapTileManager _manager = null; + private URL _url = null; + private int _layer = 0; + private int _x = 0, _y = 0; + private int _zoom = 0; + /** Hashset of all blocked / 404 tiles to avoid requesting them again */ + private static final HashSet BLOCKED_URLS = new HashSet(); + /** Hashset of all currently loading tiles to avoid requesting them again */ + private static final HashSet LOADING_URLS = new HashSet(); + + + /** + * Constructor (private) + * @param inManager parent manager for callback + * @param inUrl URL to load + * @param inLayer layer index from 0 + * @param inX x coordinate of tile + * @param inY y coordinate of tile + * @param inZoom zoom level + */ + private TileDownloader(MapTileManager inManager, URL inUrl, int inLayer, int inX, int inY, int inZoom) + { + _manager = inManager; + _url = inUrl; + _layer = inLayer; + _x = inX; _y = inY; + _zoom = inZoom; + } + + /** + * Trigger a download in a new thread + * @param inManager manager to callback when image is loaded + * @param inUrl URL to load + * @param inLayer layer index from 0 + * @param inX x coordinate of tile + * @param inY y coordinate of tile + * @param inZoom current zoom level + */ + public static synchronized void triggerLoad(MapTileManager inManager, URL inUrl, int inLayer, + int inX, int inY, int inZoom) + { + if (inManager != null && inUrl != null) + { + String url = inUrl.toString(); + // System.out.println("Trigger load: " + url); + if (!BLOCKED_URLS.contains(url) && !LOADING_URLS.contains(url)) + { + // System.out.println("Not blocked: " + url); + LOADING_URLS.add(url); + new Thread(new TileDownloader(inManager, inUrl, inLayer, inX, inY, inZoom)).start(); + } + } + } + + /** + * Run method, called in separate thread + */ + public void run() + { + InputStream in = null; + try + { + // System.out.println("TD Running thread to get: " + _url.toString()); + // Set http user agent on connection + URLConnection conn = _url.openConnection(); + conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER); + in = conn.getInputStream(); + int len = conn.getContentLength(); + if (len > 0) + { + byte[] data = new byte[len]; + int totalRead = 0; + while (totalRead < len) + { + int numRead = in.read(data, totalRead, len-totalRead); + totalRead += numRead; + } + Image tile = Toolkit.getDefaultToolkit().createImage(data); + in.close(); + + // Pass back to manager so it can be stored in its memory cache + _manager.notifyImageLoaded(tile, _layer, _x, _y, _zoom); + } + } + catch (IOException e) + { + System.err.println("IOE: " + e.getClass().getName() + " - " + e.getMessage()); + synchronized(this.getClass()) + { + BLOCKED_URLS.add(_url.toString()); + } + try {in.close();} catch (Exception e2) {} + } + LOADING_URLS.remove(_url.toString()); + } +}