001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.io.imagery; 003 004import org.openstreetmap.josm.Main; 005import org.openstreetmap.josm.data.ProjectionBounds; 006import org.openstreetmap.josm.data.imagery.GeorefImage.State; 007import org.openstreetmap.josm.gui.MapView; 008import org.openstreetmap.josm.gui.layer.WMSLayer; 009 010public abstract class Grabber implements Runnable { 011 protected final MapView mv; 012 protected final WMSLayer layer; 013 private final boolean localOnly; 014 015 protected ProjectionBounds b; 016 protected volatile boolean canceled; 017 018 Grabber(MapView mv, WMSLayer layer, boolean localOnly) { 019 this.mv = mv; 020 this.layer = layer; 021 this.localOnly = localOnly; 022 } 023 024 abstract void fetch(WMSRequest request, int attempt) throws Exception; // the image fetch code 025 026 int width(){ 027 return layer.getBaseImageWidth(); 028 } 029 030 int height(){ 031 return layer.getBaseImageHeight(); 032 } 033 034 @Override 035 public void run() { 036 while (true) { 037 if (canceled) 038 return; 039 WMSRequest request = layer.getRequest(localOnly); 040 if (request == null) 041 return; 042 this.b = layer.getBounds(request); 043 if (request.isPrecacheOnly()) { 044 if (!layer.cache.hasExactMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth)) { 045 attempt(request); 046 } else if (Main.isDebugEnabled()) { 047 Main.debug("Ignoring "+request+" (precache only + exact match)"); 048 } 049 } else if (!loadFromCache(request)){ 050 attempt(request); 051 } else if (Main.isDebugEnabled()) { 052 Main.debug("Ignoring "+request+" (loaded from cache)"); 053 } 054 layer.finishRequest(request); 055 } 056 } 057 058 protected void attempt(WMSRequest request){ // try to fetch the image 059 int maxTries = 5; // n tries for every image 060 for (int i = 1; i <= maxTries; i++) { 061 if (canceled) 062 return; 063 try { 064 if (!request.isPrecacheOnly() && !layer.requestIsVisible(request)) 065 return; 066 fetch(request, i); 067 break; // break out of the retry loop 068 } catch (Exception e) { 069 try { // sleep some time and then ask the server again 070 Thread.sleep(random(1000, 2000)); 071 } catch (InterruptedException e1) { 072 Main.debug("InterruptedException in "+getClass().getSimpleName()+" during WMS request"); 073 } 074 if (i == maxTries) { 075 Main.error(e); 076 request.finish(State.FAILED, null); 077 } 078 } 079 } 080 } 081 082 public static int random(int min, int max) { 083 return (int)(Math.random() * ((max+1)-min) ) + min; 084 } 085 086 public abstract boolean loadFromCache(WMSRequest request); 087 088 public void cancel() { 089 canceled = true; 090 } 091}