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 () -> { 064 BingAttributionData attributionLoader = new BingAttributionData(); 065 int waitTimeSec = 1; 066 while (true) { 067 try { 068 String xml = attributionLoader.updateIfRequiredString(); 069 List<Attribution> ret = parseAttributionText(new InputSource(new StringReader(xml))); 070 if (attributionDownloadedTask != null) { 071 GuiHelper.runInEDT(attributionDownloadedTask); 072 attributionDownloadedTask = null; 073 } 074 return ret; 075 } catch (IOException ex) { 076 Main.warn(ex, "Could not connect to Bing API. Will retry in " + waitTimeSec + " seconds."); 077 Thread.sleep(waitTimeSec * 1000L); 078 waitTimeSec *= 2; 079 } 080 } 081 }; 082 } 083}