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