net.wirelabs.jmaps.map.cache.DirectoryBasedCache Maven / Gradle / Ivy
The newest version!
package net.wirelabs.jmaps.map.cache;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.wirelabs.jmaps.map.Defaults;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
/**
* Created 1/2/23 by Michał Szwaczko ([email protected])
*/
@Slf4j
@Getter
public class DirectoryBasedCache implements Cache {
private final Path baseDir;
@Setter private Duration cacheTimeout;
public DirectoryBasedCache() {
this(Defaults.DEFAULT_TILECACHE_DIR, Defaults.DEFAULT_CACHE_TIMEOUT);
}
public DirectoryBasedCache(String cacheDir, Duration cacheTimeout) {
this.baseDir = Paths.get(cacheDir);
this.cacheTimeout = cacheTimeout;
if (cacheTimeout.isZero()) {
log.info("Directory based cache expiration checking disabled!");
} else {
log.info("Directory based cache expiration timeout set to {}", cacheTimeout);
}
}
@Override
public BufferedImage get(String key) {
try {
File f = getLocalFile(key);
if (validityTimeGreaterThanZero() && (keyExpired(key))) {
return null;
}
return ImageIO.read(Files.newInputStream(f.toPath()));
} catch (IOException e) {
return null;
}
}
private boolean validityTimeGreaterThanZero() {
return getCacheTimeout().toMillis() > Duration.ZERO.toMillis();
}
@Override
public void put(String key, BufferedImage b) {
try {
File file = getLocalFile(key);
if (!file.exists()) {
Files.createDirectories(file.toPath());
}
writeImageToFile(b,file);
} catch (IOException ex) {
log.error("File cache put failed for {}", key, ex);
}
}
void writeImageToFile(BufferedImage image, File file) throws IOException {
ImageIO.write(image, "png", file);
}
public boolean keyExpired(String key) {
File file = getLocalFile(key);
long expirationTime = System.currentTimeMillis() - getCacheTimeout().toMillis();
long lastWrittenOn;
try {
lastWrittenOn = Files.getLastModifiedTime(file.toPath()).toMillis();
} catch (IOException e) {
return false;
}
return (lastWrittenOn < expirationTime);
}
private File getLocalFile(String remoteUri) {
URI uri = URI.create(remoteUri);
StringBuilder sb = new StringBuilder();
String host = uri.getHost();
String query = uri.getQuery();
String path = uri.getPath();
if (host != null) {
sb.append(host);
}
if (path != null) {
sb.append(path);
}
if (query != null) {
sb.append('?');
sb.append(query);
}
String name;
final int maxLen = 250;
if (sb.length() < maxLen) {
name = sb.toString();
} else {
name = sb.substring(0, maxLen);
}
name = normalizeUrl(name);
return new File(baseDir.toFile(), name);
}
private String normalizeUrl(String name) {
char replacementChar = '$';
char[] charsNormalized = new char[]{'&', '?', '*', ':', '<', '>', '"'};
for (char nchar : charsNormalized) {
name = name.replace(nchar, replacementChar);
}
return name;
}
}