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