Ticket #1906: Cache for WMS.patch

File Cache for WMS.patch, 7.4 KB (added by xeen, 17 years ago)

Simple Cache

  • src/wmsplugin/Cache.java

     
     1package wmsplugin;
     2
     3import java.awt.image.BufferedImage;
     4import java.io.File;
     5import java.io.FileFilter;
     6import java.util.Date;
     7import java.util.Iterator;
     8import java.util.Set;
     9import java.util.TreeMap;
     10import javax.imageio.*;
     11
     12import org.openstreetmap.josm.Main;
     13
     14
     15public class Cache {
     16    final File dir;
     17    // Last 5 days
     18    private final long expire = Main.pref.getInteger("wmsplugin.cache.expire", 1000*60*60*24*5);
     19    // 40 MBytes
     20    private final long maxsize = Main.pref.getInteger("wmsplugin.cache.size", 1000*1000*40);
     21    private boolean disabled = false;
     22    // If the cache is full, we don't want to delete just one file
     23    private final int cleanUpThreshold = 20;
     24   
     25    Cache() {
     26        this(Main.pref.getPreferencesDir() + "plugins/wmsplugin/cache");
     27    }
     28   
     29    Cache(String working_dir) {
     30        // Override default working directory
     31        this.dir = new File(working_dir);
     32        try {
     33            this.dir.mkdirs();
     34        } catch(Exception e) {
     35            // We probably won't be able to do anything anyway
     36            disabled = true;
     37        }
     38       
     39        if(expire <= 0 || maxsize <= 0)
     40            disabled = true;
     41    }
     42   
     43    public BufferedImage getImg(String ident) {
     44        if(disabled) return null;
     45        try {
     46            File img = getPath(ident);
     47            if(!img.exists()) {
     48                //System.out.println("Miss");
     49                return null;
     50            }   
     51            if(img.lastModified() < (new Date().getTime() - expire)) {
     52                img.delete();
     53                //System.out.println("Miss");
     54                return null;
     55            }
     56            //System.out.println("Hit");
     57            return ImageIO.read(img);
     58        } catch(Exception e) {
     59            System.out.println(e.getMessage());
     60        }
     61        //System.out.println("Miss");
     62        return null;
     63    }
     64   
     65    public void saveImg(String ident, BufferedImage image) {
     66        if(disabled) return;
     67        try {
     68            ImageIO.write(image, "png", getPath(ident));
     69        } catch(Exception e){
     70            System.out.println(e.getMessage());
     71        }
     72       
     73        // Clean up must be called manually
     74    }
     75   
     76    public BufferedImage saveImg(String ident, BufferedImage image, boolean passThrough) {
     77        saveImg(ident, image);
     78        return image;
     79    }
     80   
     81    public void cleanUp() {
     82        if(disabled) return;
     83       
     84        TreeMap modtime = new TreeMap<Long, File>();
     85        long time = new Date().getTime() - expire;
     86        long dirsize = 0;
     87       
     88        for(File f : getFiles()) {
     89            if(f.lastModified() < time)
     90                f.delete();
     91            else {
     92                dirsize += f.length();
     93                modtime.put(f.lastModified(), f);
     94            }
     95        }
     96       
     97        if(dirsize < maxsize) return;
     98       
     99        Set keySet = modtime.keySet();
     100        Iterator it = keySet.iterator();
     101        int i=0;
     102        while (it.hasNext()) {
     103            i++;
     104            ((File)modtime.get(it.next())).delete();
     105           
     106            // Delete a couple of files, then check again
     107            if(i % cleanUpThreshold == 0 && getDirSize() < maxsize)
     108                return;
     109        }
     110    }
     111   
     112    private long getDirSize() {
     113        long dirsize = 0;
     114       
     115        for(File f : getFiles())
     116            dirsize += f.length();
     117        return dirsize;
     118    }
     119   
     120    private File[] getFiles() {
     121        return dir.listFiles(
     122            new FileFilter() {
     123                public boolean accept(File file) {
     124                    return file.getName().endsWith(".png");
     125                }
     126            }
     127        );
     128    }
     129   
     130    private String clean(String ident) {       
     131        return ident.replaceAll("[^a-zA-Z0-9]", "");
     132    }
     133   
     134    private File getPath(String ident) {
     135        return new File(dir, clean(ident) + ".png");
     136    }
     137}
     138 No newline at end of file
  • src/wmsplugin/WMSGrabber.java

     
    2525
    2626public class WMSGrabber extends Grabber {
    2727    protected String baseURL;
     28    protected Cache cache = new wmsplugin.Cache();
    2829
    2930    WMSGrabber(String baseURL, Bounds b, Projection proj,
    3031            double pixelPerDegree, GeorefImage image, MapView mv, WMSLayer layer) {
     
    7576    }
    7677
    7778    protected BufferedImage grab(URL url) throws IOException {
     79        BufferedImage cached = cache.getImg(url.toString());
     80        if(cached != null) return cached;
     81   
    7882        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    7983
    8084        String contentType = conn.getHeaderField("Content-Type");
     
    8690        InputStream is = new ProgressInputStream(conn, null);
    8791        BufferedImage img = ImageIO.read(is);
    8892        is.close();
    89         return img;
     93       
     94        return cache.saveImg(url.toString(), img, true);
    9095    }
    9196
    9297    protected String readException(URLConnection conn) throws IOException {
  • src/wmsplugin/WMSLayer.java

     
    175175                    executor.submit(gr);
    176176            }
    177177        }
     178
     179        new wmsplugin.Cache().cleanUp();
    178180    }
    179181
    180182    @Override public void visitBoundingBox(BoundingXYVisitor v) {
  • src/wmsplugin/YAHOOGrabber.java

     
    2020
    2121public class YAHOOGrabber extends WMSGrabber{
    2222    protected String browserCmd;
     23    protected Cache cache = new wmsplugin.Cache();
    2324
    2425    YAHOOGrabber(String baseURL, Bounds b, Projection proj,
    2526            double pixelPerDegree, GeorefImage image, MapView mv, WMSLayer layer) {
     
    3031    }
    3132
    3233    protected BufferedImage grab(URL url) throws IOException {
    33         ArrayList<String> cmdParams = new ArrayList<String>();
    3434        String urlstring = url.toExternalForm();
    3535        // work around a problem in URL removing 2 slashes
    3636        if(!urlstring.startsWith("file:///"))
    3737            urlstring = urlstring.replaceFirst("file:", "file://");
     38           
     39        BufferedImage cached = cache.getImg(urlstring);
     40        if(cached != null) return cached;
     41       
     42        ArrayList<String> cmdParams = new ArrayList<String>();
    3843        StringTokenizer st = new StringTokenizer(MessageFormat.format(browserCmd, urlstring));
    3944        while( st.hasMoreTokens() )
    4045            cmdParams.add(st.nextToken());
     
    4954            throw new IOException( "Could not start browser. Please check that the executable path is correct.\n" + ioe.getMessage() );
    5055        }
    5156
    52         return ImageIO.read(browser.getInputStream());
     57        return cache.saveImg(urlstring, ImageIO.read(browser.getInputStream()), true);
    5358    }
    5459}