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