1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
package tim.prune.gui.map.tile;
import tim.prune.gui.map.CacheFailure;
import tim.prune.gui.map.MapTile;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class DiskCache
{
private String _basePath = null;
/** Flag to remember whether we have already tried to create the base path */
private boolean _triedToCreateBasePath = false;
/** Time limit to cache images for */
private static final long CACHE_TIME_LIMIT = 20 * 24 * 60 * 60 * 1000; // 20 days in ms
/**
* @param inBasePath path to root of the tile cache
*/
public void setBasePath(String inBasePath) {
_basePath = inBasePath;
}
/**
* Get a tile from the disk cache
* @param inTileDef tile definition
* @return tile object if possible, otherwise null
*/
public MapTile getTile(TileDef inTileDef)
{
String tilePath = inTileDef.getFilePath();
if (_basePath == null || tilePath == null) {
return null;
}
// System.out.println("Disk Cache asked for tile: " + inTilePath);
File tileFile = new File(_basePath, tilePath);
if (tileFile.exists() && tileFile.canRead() && tileFile.length() > 0)
{
long fileStamp = tileFile.lastModified();
boolean isExpired = ((System.currentTimeMillis()-fileStamp) > CACHE_TIME_LIMIT);
// System.out.println("Disk Cache found tile: " + tilePath + (isExpired ? " (expired)" : ""));
try
{
Image image = Toolkit.getDefaultToolkit().createImage(tileFile.getAbsolutePath());
image.getWidth(null);
return new MapTile(image, isExpired);
}
catch (Exception e) {
System.err.println("error creating image: " + e.getClass().getName() + ": " + e.getMessage());
}
}
return null;
}
/**
* Save the bytes of a downloaded tile to disk
*/
public void saveTileBytes(TileBytes inBytes, TileDef inDefinition) throws CacheFailure
{
if (_basePath == null) {return;} // no cache specified
File tileFile = new File(_basePath, inDefinition.getFilePath());
if (directoryOk(tileFile))
{
try (FileOutputStream fos = new FileOutputStream(tileFile)) {
fos.write(inBytes.getData());
} catch (IOException ioe) {
System.out.println("Failed to write to: " + inDefinition.getFilePath());
ioe.printStackTrace();
throw new CacheFailure();
}
}
}
/**
* Check the cache directories exist, and create them if necessary
* @param tileFile file which we will want to write
* @return true if the specified file can be written
* @throws CacheFailure if creation not possible (eg read-only)
*/
private boolean directoryOk(File tileFile) throws CacheFailure
{
if (!checkBasePath()) {
throw new CacheFailure();
}
File dir = tileFile.getParentFile();
return ((dir.exists() || dir.mkdirs()) && dir.canWrite());
}
/**
* Save a sliced Image from a downloaded tile to disk
* @param inImage rendered image to be saved
* @param inDefinition tile definition which determines path
*/
public void saveTileImage(RenderedImage inImage, TileDef inDefinition) throws CacheFailure
{
if (_basePath == null) {return;} // no cache specified
if (!inDefinition._mapSource.getFileExtension(inDefinition._layerIdx).equals("png")) {
return; // can only write png tiles
}
File tileFile = new File(_basePath, inDefinition.getFilePath());
if (directoryOk(tileFile))
{
try {
if (!ImageIO.write(inImage, "png", tileFile))
{
System.err.println("Failed to write file: " + tileFile.getAbsolutePath());
throw new CacheFailure();
}
} catch (IOException e) {
e.printStackTrace();
throw new CacheFailure();
}
}
}
/**
* Check the given base path, and try (once) to create it if necessary
* @return true if base path can be written to
*/
private boolean checkBasePath()
{
File basePath = new File(_basePath);
if (!basePath.exists() && !_triedToCreateBasePath)
{
_triedToCreateBasePath = true;
System.out.println("Base path '" + basePath.getAbsolutePath() + "' does not exist, trying to create");
return basePath.mkdirs();
}
return basePath.exists() && basePath.isDirectory() && basePath.canWrite();
}
}
|