- Timestamp:
- 2015-05-28T22:00:41+02:00 (9 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/data
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java
r8425 r8433 85 85 public static ThreadFactory getNamedThreadFactory(final String name) { 86 86 return new ThreadFactory(){ 87 @Override 87 88 public Thread newThread(Runnable r) { 88 89 Thread t = Executors.defaultThreadFactory().newThread(r); … … 185 186 if (first || force) { 186 187 ensureCacheElement(); 187 if (!force && cacheElement != null && isCacheElementValid() && (isObjectLoadable())) {188 if (!force && cacheElement != null && isCacheElementValid() && isObjectLoadable()) { 188 189 // we got something in cache, and it's valid, so lets return it 189 190 log.log(Level.FINE, "JCS - Returning object from cache: {0}", getCacheKey()); … … 215 216 216 217 /** 218 * Simple implementation. All errors should be cached as empty. Though some JDK (JDK8 on Windows for example) 219 * doesn't return 4xx error codes, instead they do throw an FileNotFoundException or IOException 217 220 * 218 * @return cache object as empty, regardless of what remote resource has returned (ex. based on headers)219 */ 220 protected boolean cacheAsEmpty( Map<String, List<String>> headers, int statusCode, byte[] content) {221 return false;221 * @return true if we should put empty object into cache, regardless of what remote resource has returned 222 */ 223 protected boolean cacheAsEmpty() { 224 return attributes.getResponseCode() < 500; 222 225 } 223 226 … … 262 265 } 263 266 264 265 267 private void finishLoading(LoadResult result) { 266 268 Set<ICachedLoaderListener> listeners = null; … … 272 274 return; 273 275 } 274 try { 275 for (ICachedLoaderListener l: listeners) { 276 l.loadingFinished(cacheData, attributes, result); 277 } 278 } catch (Exception e) { 279 log.log(Level.WARNING, "JCS - Error while loading object from cache: {0}; {1}", new Object[]{e.getMessage(), getUrl()}); 280 Main.warn(e); 281 for (ICachedLoaderListener l: listeners) { 282 l.loadingFinished(cacheData, attributes, LoadResult.FAILURE); 283 } 284 285 } 286 276 for (ICachedLoaderListener l: listeners) { 277 l.loadingFinished(cacheData, attributes, result); 278 } 287 279 } 288 280 … … 362 354 byte[] raw = read(urlConn); 363 355 364 if (!cacheAsEmpty(urlConn.getHeaderFields(), urlConn.getResponseCode(), raw) && 365 raw != null && raw.length > 0) { 356 if (isResponseLoadable(urlConn.getHeaderFields(), urlConn.getResponseCode(), raw)) { 366 357 // we need to check cacheEmpty, so for cases, when data is returned, but we want to store 367 358 // as empty (eg. empty tile images) to save some space … … 371 362 new Object[] {getCacheKey(), raw.length, getUrl()}); 372 363 return true; 373 } else {364 } else if (cacheAsEmpty()) { 374 365 cacheData = createCacheEntry(new byte[]{}); 375 366 cache.put(getCacheKey(), cacheData, attributes); 376 367 log.log(Level.FINE, "JCS - Caching empty object {0}", getUrl()); 377 368 return true; 369 } else { 370 log.log(Level.FINE, "JCS - failure during load - reponse is not loadable nor cached as empty"); 371 return false; 378 372 } 379 373 } 380 374 } catch (FileNotFoundException e) { 381 375 log.log(Level.FINE, "JCS - Caching empty object as server returned 404 for: {0}", getUrl()); 382 cache.put(getCacheKey(), createCacheEntry(new byte[]{}), attributes); 383 return handleNotFound(); 376 attributes.setResponseCode(404); 377 boolean doCache = isResponseLoadable(null, 404, null) || cacheAsEmpty(); 378 if (doCache) { 379 cacheData = createCacheEntry(new byte[]{}); 380 cache.put(getCacheKey(), cacheData, attributes); 381 } 382 return doCache; 383 } catch (IOException e) { 384 log.log(Level.FINE, "JCS - IOExecption during communication with server for: {0}", getUrl()); 385 attributes.setResponseCode(499); // set dummy error code 386 boolean doCache = isResponseLoadable(null, 499, null) || cacheAsEmpty(); //generic 499 error code returned 387 if (doCache) { 388 cacheData = createCacheEntry(new byte[]{}); 389 cache.put(getCacheKey(), createCacheEntry(new byte[]{}), attributes); 390 } 391 return doCache; 384 392 } catch (Exception e) { 385 393 log.log(Level.WARNING, "JCS - Exception during download {0}", getUrl()); … … 392 400 393 401 /** 394 * @return if we should treat this object as properly loaded 395 */ 396 protected abstract boolean handleNotFound(); 402 * Check if the object is loadable. This means, if the data will be parsed, and if this response 403 * will finish as successful retrieve. 404 * 405 * This simple implementation doesn't load empty response, nor client (4xx) and server (5xx) errors 406 * 407 * @param headerFields headers sent by server 408 * @param responseCode http status code 409 * @param raw data read from server 410 * @return true if object should be cached and returned to listener 411 */ 412 protected boolean isResponseLoadable(Map<String, List<String>> headerFields, int responseCode, byte[] raw) { 413 if (raw == null || raw.length == 0 || responseCode >= 400) { 414 return false; 415 } 416 return true; 417 } 397 418 398 419 protected abstract V createCacheEntry(byte[] content); -
trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java
r8425 r8433 137 137 138 138 @Override 139 protected boolean cacheAsEmpty(Map<String, List<String>> headers, int statusCode, byte[] content) { 140 // cacheAsEmpty is called for every successful download, so we can put 141 // metadata handling here 139 protected boolean isResponseLoadable(Map<String, List<String>> headers, int statusCode, byte[] content) { 142 140 attributes.setMetadata(tile.getTileSource().getMetadata(headers)); 143 141 if (tile.getTileSource().isNoTileAtZoom(headers, statusCode, content)) { 144 142 attributes.setNoTileAtZoom(true); 145 return true; 146 } 147 return false; 143 return false; // do no try to load data from no-tile at zoom, cache empty object instead 144 } 145 return super.isResponseLoadable(headers, statusCode, content); 146 } 147 148 @Override 149 protected boolean cacheAsEmpty() { 150 return isNoTileAtZoom() || super.cacheAsEmpty(); 148 151 } 149 152 … … 171 174 listeners = inProgress.remove(getCacheKey()); 172 175 } 176 boolean status = result.equals(LoadResult.SUCCESS); 173 177 174 178 try { … … 194 198 if (!isNoTileAtZoom() && httpStatusCode >= 400) { 195 199 tile.setError(tr("HTTP error {0} when loading tiles", httpStatusCode)); 200 status = false; 196 201 } 197 202 break; … … 207 212 if (listeners != null) { // listeners might be null, if some other thread notified already about success 208 213 for(TileLoaderListener l: listeners) { 209 l.tileLoadingFinished(tile, result.equals(LoadResult.SUCCESS));214 l.tileLoadingFinished(tile, status); 210 215 } 211 216 } … … 259 264 } 260 265 261 @Override262 protected boolean handleNotFound() {263 if (tile.getSource().isNoTileAtZoom(null, 404, null)) {264 tile.setError("No tile at this zoom level");265 tile.putValue("tile-info", "no-tile");266 return true;267 }268 return false;269 }270 271 266 /** 272 267 * For TMS use BaseURL as settings discovery, so for different paths, we will have different settings (useful for developer servers)
Note:
See TracChangeset
for help on using the changeset viewer.