001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.imagery; 003 004import java.io.File; 005import java.lang.reflect.Constructor; 006import java.util.Map; 007import java.util.concurrent.ConcurrentHashMap; 008 009import org.apache.commons.jcs.access.behavior.ICacheAccess; 010import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader; 011import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener; 012import org.openstreetmap.josm.Main; 013import org.openstreetmap.josm.data.Version; 014import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; 015import org.openstreetmap.josm.data.preferences.StringProperty; 016import org.openstreetmap.josm.tools.CheckParameterUtil; 017 018/** 019 * TileLoaderFactory creating JCS cached TileLoaders 020 * 021 * @author Wiktor Niesiobędzki 022 * @since 8526 023 */ 024public class CachedTileLoaderFactory implements TileLoaderFactory { 025 /** 026 * Keeps the cache directory where 027 */ 028 public static final StringProperty PROP_TILECACHE_DIR = getTileCacheDir(); 029 private final ICacheAccess<String, BufferedImageCacheEntry> cache; 030 private Constructor<? extends TileLoader> tileLoaderConstructor; 031 032 /** 033 * @param cache cache instance which will be used by tile loaders created by this tile loader 034 * @param tileLoaderClass tile loader class that will be created 035 * @throws IllegalArgumentException if a suitable constructor cannot be found for {@code tileLoaderClass} 036 */ 037 public CachedTileLoaderFactory(ICacheAccess<String, BufferedImageCacheEntry> cache, Class<? extends TileLoader> tileLoaderClass) { 038 CheckParameterUtil.ensureParameterNotNull(cache, "cache"); 039 this.cache = cache; 040 try { 041 tileLoaderConstructor = tileLoaderClass.getConstructor( 042 TileLoaderListener.class, 043 ICacheAccess.class, 044 int.class, 045 int.class, 046 Map.class); 047 } catch (NoSuchMethodException | SecurityException e) { 048 Main.warn(e); 049 throw new IllegalArgumentException(e); 050 } 051 } 052 053 private static StringProperty getTileCacheDir() { 054 String defPath = null; 055 try { 056 defPath = new File(Main.pref.getCacheDirectory(), "tiles").getAbsolutePath(); 057 } catch (SecurityException e) { 058 Main.warn(e); 059 } 060 return new StringProperty("imagery.generic.loader.cachedir", defPath); 061 } 062 063 @Override 064 public TileLoader makeTileLoader(TileLoaderListener listener, Map<String, String> inputHeaders) { 065 Map<String, String> headers = new ConcurrentHashMap<>(); 066 headers.put("User-Agent", Version.getInstance().getFullAgentString()); 067 headers.put("Accept", "text/html, image/png, image/jpeg, image/gif, */*"); 068 if (inputHeaders != null) 069 headers.putAll(inputHeaders); 070 071 return getLoader(listener, cache, 072 Main.pref.getInteger("socket.timeout.connect", 15) * 1000, 073 Main.pref.getInteger("socket.timeout.read", 30) * 1000, 074 headers); 075 } 076 077 protected TileLoader getLoader(TileLoaderListener listener, ICacheAccess<String, BufferedImageCacheEntry> cache, 078 int connectTimeout, int readTimeout, Map<String, String> headers) { 079 try { 080 return tileLoaderConstructor.newInstance( 081 listener, 082 cache, 083 connectTimeout, 084 readTimeout, 085 headers); 086 } catch (IllegalArgumentException e) { 087 Main.warn(e); 088 throw e; 089 } catch (ReflectiveOperationException e) { 090 Main.warn(e); 091 throw new IllegalArgumentException(e); 092 } 093 } 094}