001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.io.imagery;
003    
004    import org.openstreetmap.josm.Main;
005    import org.openstreetmap.josm.data.ProjectionBounds;
006    import org.openstreetmap.josm.data.imagery.GeorefImage.State;
007    import org.openstreetmap.josm.gui.MapView;
008    import org.openstreetmap.josm.gui.layer.WMSLayer;
009    
010    abstract public 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        int height(){
030            return layer.getBaseImageHeight();
031        }
032    
033        @Override
034        public void run() {
035            while (true) {
036                if (canceled)
037                    return;
038                WMSRequest request = layer.getRequest(localOnly);
039                if (request == null)
040                    return;
041                this.b = layer.getBounds(request);
042                if (request.isPrecacheOnly()) {
043                    if (!layer.cache.hasExactMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth)) {
044                        attempt(request);
045                    }
046                } else {
047                    if(!loadFromCache(request)){
048                        attempt(request);
049                    }
050                }
051                layer.finishRequest(request);
052            }
053        }
054    
055        protected void attempt(WMSRequest request){ // try to fetch the image
056            int maxTries = 5; // n tries for every image
057            for (int i = 1; i <= maxTries; i++) {
058                if (canceled)
059                    return;
060                try {
061                    if (!request.isPrecacheOnly() && !layer.requestIsVisible(request))
062                        return;
063                    fetch(request, i);
064                    break; // break out of the retry loop
065                } catch (Exception e) {
066                    try { // sleep some time and then ask the server again
067                        Thread.sleep(random(1000, 2000));
068                    } catch (InterruptedException e1) {}
069    
070                    if(i == maxTries) {
071                        e.printStackTrace();
072                        request.finish(State.FAILED, null);
073                    }
074                }
075            }
076        }
077    
078        public static int random(int min, int max) {
079            return (int)(Math.random() * ((max+1)-min) ) + min;
080        }
081    
082        abstract public boolean loadFromCache(WMSRequest request);
083    
084        public void cancel() {
085            canceled = true;
086        }
087    
088    }