001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.imagery; 003 004import java.io.IOException; 005import java.io.StringReader; 006import java.net.URL; 007import java.util.List; 008import java.util.concurrent.Callable; 009 010import org.openstreetmap.gui.jmapviewer.tilesources.BingAerialTileSource; 011import org.openstreetmap.gui.jmapviewer.tilesources.TileSourceInfo; 012import org.openstreetmap.josm.Main; 013import org.openstreetmap.josm.gui.util.GuiHelper; 014import org.openstreetmap.josm.io.CacheCustomContent; 015import org.openstreetmap.josm.tools.HttpClient; 016import org.xml.sax.InputSource; 017 018/** 019 * Bing TileSource with cached attribution 020 * 021 * @author Wiktor Niesiobędzki 022 * @since 8526 023 */ 024public class CachedAttributionBingAerialTileSource extends BingAerialTileSource { 025 private Runnable attributionDownloadedTask; 026 027 /** 028 * Creates tile source 029 * @param info ImageryInfo description of this tile source 030 */ 031 public CachedAttributionBingAerialTileSource(ImageryInfo info) { 032 super(info); 033 } 034 035 /** 036 * Creates tile source 037 * @param info ImageryInfo description of this tile source 038 * @param attributionDownloadedTask runnable to be executed once attribution is loaded 039 */ 040 041 public CachedAttributionBingAerialTileSource(TileSourceInfo info, Runnable attributionDownloadedTask) { 042 super(info); 043 this.attributionDownloadedTask = attributionDownloadedTask; 044 } 045 046 class BingAttributionData extends CacheCustomContent<IOException> { 047 048 BingAttributionData() { 049 super("bing.attribution.xml", CacheCustomContent.INTERVAL_HOURLY); 050 } 051 052 @Override 053 protected byte[] updateData() throws IOException { 054 URL u = getAttributionUrl(); 055 final String r = HttpClient.create(u).connect().fetchContent(); 056 Main.info("Successfully loaded Bing attribution data."); 057 return r.getBytes("UTF-8"); 058 } 059 } 060 061 @Override 062 protected Callable<List<Attribution>> getAttributionLoaderCallable() { 063 return new Callable<List<Attribution>>() { 064 065 @Override 066 public List<Attribution> call() throws Exception { 067 BingAttributionData attributionLoader = new BingAttributionData(); 068 int waitTimeSec = 1; 069 while (true) { 070 try { 071 String xml = attributionLoader.updateIfRequiredString(); 072 List<Attribution> ret = parseAttributionText(new InputSource(new StringReader((xml)))); 073 if (attributionDownloadedTask != null) { 074 GuiHelper.runInEDT(attributionDownloadedTask); 075 attributionDownloadedTask = null; 076 } 077 return ret; 078 } catch (IOException ex) { 079 Main.warn("Could not connect to Bing API. Will retry in " + waitTimeSec + " seconds."); 080 Thread.sleep(waitTimeSec * 1000L); 081 waitTimeSec *= 2; 082 } 083 } 084 } 085 }; 086 } 087}