001 package org.openstreetmap.gui.jmapviewer; 002 003 //License: GPL. Copyright 2008 by Jan Peter Stotz 004 005 import java.io.IOException; 006 import java.io.InputStream; 007 import java.net.HttpURLConnection; 008 import java.net.URL; 009 import java.net.URLConnection; 010 import java.util.Map; 011 import java.util.Map.Entry; 012 import java.util.HashMap; 013 014 import org.openstreetmap.gui.jmapviewer.interfaces.TileJob; 015 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader; 016 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener; 017 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource; 018 019 /** 020 * A {@link TileLoader} implementation that loads tiles from OSM. 021 * 022 * @author Jan Peter Stotz 023 */ 024 public class OsmTileLoader implements TileLoader { 025 026 /** 027 * Holds the HTTP headers. Insert e.g. User-Agent here when default should not be used. 028 */ 029 public Map<String, String> headers = new HashMap<String, String>(); 030 031 public int timeoutConnect = 0; 032 public int timeoutRead = 0; 033 034 protected TileLoaderListener listener; 035 036 public OsmTileLoader(TileLoaderListener listener) { 037 headers.put("Accept", "text/html, image/png, image/jpeg, image/gif, */*"); 038 this.listener = listener; 039 } 040 041 public TileJob createTileLoaderJob(final Tile tile) { 042 return new TileJob() { 043 044 InputStream input = null; 045 046 public void run() { 047 synchronized (tile) { 048 if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading()) 049 return; 050 tile.loaded = false; 051 tile.error = false; 052 tile.loading = true; 053 } 054 try { 055 URLConnection conn = loadTileFromOsm(tile); 056 loadTileMetadata(tile, conn); 057 if ("no-tile".equals(tile.getValue("tile-info"))) { 058 tile.setError("No tile at this zoom level"); 059 } else { 060 input = conn.getInputStream(); 061 tile.loadImage(input); 062 input.close(); 063 input = null; 064 } 065 tile.setLoaded(true); 066 listener.tileLoadingFinished(tile, true); 067 } catch (Exception e) { 068 tile.setError(e.getMessage()); 069 listener.tileLoadingFinished(tile, false); 070 if (input == null) { 071 try { 072 System.err.println("Failed loading " + tile.getUrl() +": " + e.getMessage()); 073 } catch(IOException i) { 074 } 075 } 076 } finally { 077 tile.loading = false; 078 tile.setLoaded(true); 079 } 080 } 081 082 public Tile getTile() { 083 return tile; 084 } 085 }; 086 } 087 088 protected URLConnection loadTileFromOsm(Tile tile) throws IOException { 089 URL url; 090 url = new URL(tile.getUrl()); 091 URLConnection urlConn = url.openConnection(); 092 if (urlConn instanceof HttpURLConnection) { 093 prepareHttpUrlConnection((HttpURLConnection)urlConn); 094 } 095 urlConn.setReadTimeout(30000); // 30 seconds read timeout 096 return urlConn; 097 } 098 099 protected void loadTileMetadata(Tile tile, URLConnection urlConn) { 100 String str = urlConn.getHeaderField("X-VE-TILEMETA-CaptureDatesRange"); 101 if (str != null) { 102 tile.putValue("capture-date", str); 103 } 104 str = urlConn.getHeaderField("X-VE-Tile-Info"); 105 if (str != null) { 106 tile.putValue("tile-info", str); 107 } 108 } 109 110 protected void prepareHttpUrlConnection(HttpURLConnection urlConn) { 111 for(Entry<String, String> e : headers.entrySet()) { 112 urlConn.setRequestProperty(e.getKey(), e.getValue()); 113 } 114 if(timeoutConnect != 0) 115 urlConn.setConnectTimeout(timeoutConnect); 116 if(timeoutRead != 0) 117 urlConn.setReadTimeout(timeoutRead); 118 } 119 120 @Override 121 public String toString() { 122 return getClass().getSimpleName(); 123 } 124 125 }