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