1
package tim.prune.gui.map;
4
import java.awt.Toolkit;
5
import java.awt.image.ImageObserver;
7
import java.io.FileOutputStream;
8
import java.io.IOException;
9
import java.io.InputStream;
13
* Class to control the reading and saving of map tiles
16
public class DiskTileCacher implements Runnable
18
/** URL to get image from */
19
private URL _url = null;
20
/** File to save image to */
21
private File _file = null;
22
/** Observer to be notified */
23
private ImageObserver _observer = null;
24
/** Time limit to cache images for */
25
private static final long CACHE_TIME_LIMIT = 20 * 24 * 60 * 60 * 1000; // 20 days in ms
29
* @param inUrl URL to get
30
* @param inFile file to save to
32
private DiskTileCacher(URL inUrl, File inFile, ImageObserver inObserver)
36
_observer = inObserver;
37
new Thread(this).start();
41
* Get the specified tile from the disk cache
42
* @param inBasePath base path to whole disk cache
43
* @param inTilePath relative path to requested tile
44
* @param inCheckAge true to check age of file, false to ignore
45
* @return tile image if available, or null if not there
47
public static Image getTile(String inBasePath, String inTilePath, boolean inCheckAge)
49
if (inBasePath == null) {return null;}
50
File tileFile = new File(inBasePath, inTilePath);
52
if (tileFile.exists() && tileFile.canRead() && tileFile.length() > 0) {
53
long fileStamp = tileFile.lastModified();
54
if (!inCheckAge || ((System.currentTimeMillis()-fileStamp) < CACHE_TIME_LIMIT))
57
image = Toolkit.getDefaultToolkit().createImage(tileFile.getAbsolutePath());
59
catch (Exception e) {}
66
* Save the specified image tile to disk
67
* @param inUrl url to get image from
68
* @param inBasePath base path to disk cache
69
* @param inTilePath relative path to this tile
70
* @param inObserver observer to inform when load complete
72
public static void saveTile(URL inUrl, String inBasePath, String inTilePath, ImageObserver inObserver)
74
if (inBasePath == null || inTilePath == null) {return;}
75
// save file if possible
76
File basePath = new File(inBasePath);
77
if (!basePath.exists() || !basePath.isDirectory() || !basePath.canWrite()) {
78
//System.err.println("Can't write");
79
// Can't write to base path
82
File tileFile = new File(basePath, inTilePath);
83
// Check if this file is already being loaded
84
if (!isBeingLoaded(tileFile))
86
File dir = tileFile.getParentFile();
87
// Start a new thread to load the image if necessary
88
if (dir.exists() || dir.mkdirs())
90
new DiskTileCacher(inUrl, tileFile, inObserver);
96
* Check whether the given tile is already being loaded
97
* @param inFile desired file
98
* @return true if temporary file with this name exists
100
private static boolean isBeingLoaded(File inFile)
102
File tempFile = new File(inFile.getAbsolutePath() + ".temp");
103
return tempFile.exists();
107
* Run method for loading URL asynchronously and saving to file
111
boolean finished = false;
112
InputStream in = null;
113
FileOutputStream out = null;
114
File tempFile = new File(_file.getAbsolutePath() + ".temp");
115
// Use a synchronized block across all threads to make sure this url is only fetched once
116
synchronized (DiskTileCacher.class) {
117
if (tempFile.exists()) {return;}
119
if (!tempFile.createNewFile()) {return;}
121
catch (Exception e) {return;}
124
// Open streams from URL and to file
125
out = new FileOutputStream(tempFile);
126
in = _url.openStream();
128
// Loop over each byte in the stream (maybe buffering is more efficient?)
129
while ((d = in.read()) >= 0) {
133
} catch (IOException e) {}
138
if (!finished) {tempFile.delete();}
140
catch (Exception e) {} // ignore
142
// Move temp file to desired file location
143
if (!tempFile.renameTo(_file)) {
144
// File couldn't be moved - delete both to be sure
148
// Tell parent that load is finished (parameters ignored)
149
_observer.imageUpdate(null, ImageObserver.ALLBITS, 0, 0, 0, 0);