File: DiskCache.java

package info (click to toggle)
gpsprune 26.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,824 kB
  • sloc: java: 52,154; sh: 25; makefile: 21; python: 15
file content (136 lines) | stat: -rw-r--r-- 4,185 bytes parent folder | download | duplicates (5)
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();
	}
}