Changeset 9846 in osm for applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
- Timestamp:
- 2008-08-15T13:03:46+02:00 (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
r9780 r9846 13 13 import java.net.URL; 14 14 import java.net.URLConnection; 15 16 import org.openstreetmap.gui.jmapviewer.interfaces.Job; 15 import java.nio.charset.Charset; 16 17 17 import org.openstreetmap.gui.jmapviewer.interfaces.TileCache; 18 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader; 19 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener; 18 20 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource; 19 import org.openstreetmap.gui.jmapviewer.interfaces.Tile Loader;21 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource.TileUpdate; 20 22 21 23 /** … … 28 30 public class OsmFileCacheTileLoader extends OsmTileLoader { 29 31 30 private static final String FILE_EXT = ".png"; 32 private static final String TILE_FILE_EXT = ".png"; 33 private static final String ETAG_FILE_EXT = ".etag"; 34 35 private static final Charset ETAG_CHARSET = Charset.forName("UTF-8"); 31 36 32 37 public static final long FILE_AGE_ONE_DAY = 1000 * 60 * 60 * 24; … … 35 40 protected String cacheDirBase; 36 41 37 protected long maxFileAge = FILE_AGE_ONE_WEEK; 38 39 public OsmFileCacheTileLoader(JMapViewer map) { 42 protected long maxCacheFileAge = FILE_AGE_ONE_WEEK; 43 protected long recheckAfter = FILE_AGE_ONE_DAY; 44 45 public OsmFileCacheTileLoader(TileLoaderListener map) { 40 46 super(map); 41 47 String tempDir = System.getProperty("java.io.tmpdir"); … … 53 59 } 54 60 55 public JobcreateTileLoaderJob(final TileSource source, final int tilex, final int tiley,61 public Runnable createTileLoaderJob(final TileSource source, final int tilex, final int tiley, 56 62 final int zoom) { 57 63 return new FileLoadJob(source, tilex, tiley, zoom); 58 64 } 59 65 60 protected class FileLoadJob implements Job{66 protected class FileLoadJob implements Runnable { 61 67 InputStream input = null; 62 68 63 69 int tilex, tiley, zoom; 70 Tile tile; 64 71 TileSource source; 65 72 File tileCacheDir; 73 File tileFile = null; 74 long fileAge = 0; 75 boolean fileTilePainted = false; 66 76 67 77 public FileLoadJob(TileSource source, int tilex, int tiley, int zoom) { … … 74 84 75 85 public void run() { 76 TileCache cache = map.getTileCache(); 77 Tile tile; 86 TileCache cache = listener.getTileCache(); 78 87 synchronized (cache) { 79 88 tile = cache.getTile(source, tilex, tiley, zoom); … … 85 94 if (!tileCacheDir.exists()) 86 95 tileCacheDir.mkdirs(); 87 try { 88 long fileAge = 0; 89 FileInputStream fin = null; 90 File f = null; 91 try { 92 f = getTileFile(tile); 93 fin = new FileInputStream(f); 94 tile.loadImage(fin); 95 fin.close(); 96 fileAge = f.lastModified(); 97 boolean oldTile = System.currentTimeMillis() - fileAge > maxFileAge; 98 System.out.println("Loaded from file: " + tile); 99 if (!oldTile) { 100 tile.setLoaded(true); 101 map.repaint(); 102 return; 96 if (loadTileFromFile()) 97 return; 98 if (fileTilePainted) { 99 Runnable job = new Runnable() { 100 101 public void run() { 102 loadorUpdateTile(); 103 103 } 104 // System.out.println("Cache hit for " + tile + 105 // " but file age is high: " 106 // + new Date(fileAge)); 107 map.repaint(); 108 // if (!isOsmTileNewer(tile, fileAge)) { 109 // tile.setLoaded(true); 110 // return; 111 // } 112 } catch (Exception e) { 113 try { 114 if (fin != null) { 115 fin.close(); 116 f.delete(); 117 } 118 } catch (Exception e1) { 119 } 120 } 121 // Thread.sleep(500); 104 }; 105 JobDispatcher.getInstance().addJob(job); 106 } else { 107 loadorUpdateTile(); 108 } 109 } 110 111 protected void loadorUpdateTile() { 112 113 try { 122 114 // System.out.println("Loading tile from OSM: " + tile); 123 115 HttpURLConnection urlConn = loadTileFromOsm(tile); 124 // if (fileAge > 0) 125 // urlConn.setIfModifiedSince(fileAge); 126 // 127 // if (urlConn.getResponseCode() == 304) { 128 // System.out.println("Local version is up to date"); 129 // tile.setLoaded(true); 130 // return; 131 // } 116 if (tileFile != null) { 117 switch (source.getTileUpdate()) { 118 case IfModifiedSince: 119 urlConn.setIfModifiedSince(fileAge); 120 break; 121 case LastModified: 122 if (!isOsmTileNewer(fileAge)) { 123 System.out 124 .println("LastModified: Local version is up to date: " + tile); 125 tile.setLoaded(true); 126 tileFile.setLastModified(System.currentTimeMillis() - maxCacheFileAge 127 + recheckAfter); 128 return; 129 } 130 break; 131 } 132 } 133 if (source.getTileUpdate() == TileUpdate.ETag 134 || source.getTileUpdate() == TileUpdate.IfNoneMatch) { 135 if (tileFile != null) { 136 String fileETag = loadETagfromFile(); 137 if (fileETag != null) { 138 switch (source.getTileUpdate()) { 139 case IfNoneMatch: 140 urlConn.addRequestProperty("If-None-Match", fileETag); 141 break; 142 case ETag: 143 if (hasOsmTileETag(fileETag)) { 144 tile.setLoaded(true); 145 tileFile.setLastModified(System.currentTimeMillis() - maxCacheFileAge 146 + recheckAfter); 147 return; 148 } 149 } 150 } 151 } 152 153 String eTag = urlConn.getHeaderField("ETag"); 154 saveETagToFile(eTag); 155 } 156 if (urlConn.getResponseCode() == 304) { 157 // If we are isModifiedSince or If-None-Match has been set 158 // and the server answers with a HTTP 304 = "Not Modified" 159 System.out.println("Local version is up to date: " + tile); 160 tile.setLoaded(true); 161 tileFile.setLastModified(System.currentTimeMillis() - maxCacheFileAge 162 + recheckAfter); 163 return; 164 } 165 132 166 byte[] buffer = loadTileInBuffer(urlConn); 133 tile.loadImage(new ByteArrayInputStream(buffer)); 134 tile.setLoaded(true); 135 map.repaint(); 136 input = null; 137 saveTileToFile(tile, buffer); 167 if (buffer != null) { 168 tile.loadImage(new ByteArrayInputStream(buffer)); 169 tile.setLoaded(true); 170 listener.repaint(); 171 saveTileToFile(buffer); 172 } else { 173 tile.setLoaded(true); 174 } 138 175 } catch (Exception e) { 139 176 if (input == null /* || !input.isStopped() */) … … 143 180 tile.loading = false; 144 181 } 182 } 183 184 protected boolean loadTileFromFile() { 185 FileInputStream fin = null; 186 try { 187 tileFile = getTileFile(); 188 fin = new FileInputStream(tileFile); 189 if (fin.available() == 0) 190 throw new IOException("File empty"); 191 tile.loadImage(fin); 192 fin.close(); 193 fileAge = tileFile.lastModified(); 194 boolean oldTile = System.currentTimeMillis() - fileAge > maxCacheFileAge; 195 // System.out.println("Loaded from file: " + tile); 196 if (!oldTile) { 197 tile.setLoaded(true); 198 } 199 listener.repaint(); 200 fileTilePainted = true; 201 } catch (Exception e) { 202 try { 203 if (fin != null) { 204 fin.close(); 205 tileFile.delete(); 206 } 207 } catch (Exception e1) { 208 } 209 tileFile = null; 210 fileAge = 0; 211 } 212 return false; 145 213 } 146 214 … … 157 225 finished = true; 158 226 } while (!finished); 227 if (bout.size() == 0) 228 return null; 159 229 return bout.toByteArray(); 160 230 } … … 171 241 * </ul> 172 242 * 173 * @param tile174 243 * @param fileAge 175 244 * @return <code>true</code> if the tile on the server is newer than the … … 177 246 * @throws IOException 178 247 */ 179 protected boolean isOsmTileNewer( Tile tile,long fileAge) throws IOException {248 protected boolean isOsmTileNewer(long fileAge) throws IOException { 180 249 URL url; 181 250 url = new URL(tile.getUrl()); 182 251 HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); 183 252 urlConn.setRequestMethod("HEAD"); 184 urlConn.setReadTimeout(30000); // 30 seconds read 253 urlConn.setReadTimeout(30000); // 30 seconds read timeout 185 254 // System.out.println("Tile age: " + new 186 255 // Date(urlConn.getLastModified()) + " / " … … 188 257 long lastModified = urlConn.getLastModified(); 189 258 if (lastModified == 0) 259 return true; // no LastModified time returned 260 return (lastModified > fileAge); 261 } 262 263 protected boolean hasOsmTileETag(String eTag) throws IOException { 264 URL url; 265 url = new URL(tile.getUrl()); 266 HttpURLConnection urlConn = (HttpURLConnection) url.openConnection(); 267 urlConn.setRequestMethod("HEAD"); 268 urlConn.setReadTimeout(30000); // 30 seconds read timeout 269 // System.out.println("Tile age: " + new 270 // Date(urlConn.getLastModified()) + " / " 271 // + new Date(fileAge)); 272 String osmETag = urlConn.getHeaderField("ETag"); 273 if (osmETag == null) 190 274 return true; 191 return ( lastModified > fileAge);192 } 193 194 protected File getTileFile( Tile tile) throws IOException {275 return (osmETag.equals(eTag)); 276 } 277 278 protected File getTileFile() throws IOException { 195 279 return new File(tileCacheDir + "/" + tile.getZoom() + "_" + tile.getXtile() + "_" 196 + tile.getYtile() + FILE_EXT); 197 } 198 199 protected void saveTileToFile( Tile tile,byte[] rawData) {280 + tile.getYtile() + TILE_FILE_EXT); 281 } 282 283 protected void saveTileToFile(byte[] rawData) { 200 284 try { 201 285 FileOutputStream f = 202 286 new FileOutputStream(tileCacheDir + "/" + tile.getZoom() + "_" 203 + tile.getXtile() + "_" + tile.getYtile() + FILE_EXT); 287 + tile.getXtile() + "_" + tile.getYtile() + TILE_FILE_EXT); 204 288 f.write(rawData); 205 289 f.close(); … … 210 294 } 211 295 212 public void stop() { 213 } 296 protected void saveETagToFile(String eTag) { 297 try { 298 FileOutputStream f = 299 new FileOutputStream(tileCacheDir + "/" + tile.getZoom() + "_" 300 + tile.getXtile() + "_" + tile.getYtile() + ETAG_FILE_EXT); 301 f.write(eTag.getBytes(ETAG_CHARSET)); 302 f.close(); 303 } catch (Exception e) { 304 System.err.println("Failed to save ETag: " + e.getLocalizedMessage()); 305 } 306 } 307 308 protected String loadETagfromFile() { 309 try { 310 FileInputStream f = 311 new FileInputStream(tileCacheDir + "/" + tile.getZoom() + "_" 312 + tile.getXtile() + "_" + tile.getYtile() + ETAG_FILE_EXT); 313 byte[] buf = new byte[f.available()]; 314 f.read(buf); 315 f.close(); 316 return new String(buf, ETAG_CHARSET); 317 } catch (Exception e) { 318 return null; 319 } 320 } 321 214 322 } 215 323 216 324 public long getMaxFileAge() { 217 return maxFileAge; 325 return maxCacheFileAge; 218 326 } 219 327 220 328 /** 221 * Sets the maximum age of the local cached tile in the file system. 329 * Sets the maximum age of the local cached tile in the file system. If a 330 * local tile is older than the specified file age 331 * {@link OsmFileCacheTileLoader} will connect to the tile server and check 332 * if a newer tile is available using the mechanism specified for the 333 * selected tile source/server. 222 334 * 223 335 * @param maxFileAge … … 225 337 * @see #FILE_AGE_ONE_DAY 226 338 * @see #FILE_AGE_ONE_WEEK 339 * @see TileSource#getTileUpdate() 227 340 */ 228 public void setMaxFileAge(long maxFileAge) { 229 this.maxFileAge = maxFileAge; 341 public void setCacheMaxFileAge(long maxFileAge) { 342 this.maxCacheFileAge = maxFileAge; 230 343 } 231 344
Note:
See TracChangeset
for help on using the changeset viewer.
