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