/*
* Copyright 2013 Serdar.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.fub.mapviewer.ui.caches;
import de.fub.mapviewer.ui.MapViewerTileFactory;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.jdesktop.swingx.mapviewer.TileCache;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.RequestProcessor;
/**
*
* @author Serdar
*/
public class PersistenceCache extends TileCache {
private static final Logger LOG = Logger.getLogger(PersistenceCache.class.getName());
private final String TEMP_FOLDER = "java.io.tmpdir";
private final int WEEK_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000;
private final Map<URI, BufferedImage> TILES = Collections.synchronizedMap(new HashMap<URI, BufferedImage>());
private final String TILE_NAME = "tile.png";
private final MapViewerTileFactory TILEFACTORYINFO;
private final Dispatcher DISPATCHER = new Dispatcher();
private FileObject cacheFolder;
public PersistenceCache(MapViewerTileFactory tileFactory) {
assert tileFactory != null;
this.TILEFACTORYINFO = tileFactory;
}
@Override
public void needMoreMemory() {
TILES.clear();
}
@Override
public BufferedImage get(URI uri) throws IOException {
BufferedImage img = null;
if (TILES.containsKey(uri)) {
img = TILES.get(uri);
} else {
img = getCached(uri);
}
return img;
}
@Override
public void put(URI uri, byte[] bimg, BufferedImage img) {
TILES.put(uri, img);
BufferedImage cached = getCached(uri);
if (cached == null) {
DISPATCHER.persist(uri, img);
}
}
private BufferedImage getCached(URI uri) {
BufferedImage img = null;
FileObject cache = getCacheFolder();
if (cache != null && uri.getPath() != null) {
try {
String path = URLEncoder.encode(uri.getPath().replaceAll("/", "-"), "UTF-8");
FileObject fileObject = cache.getFileObject(path);
if (fileObject != null && fileObject.isFolder()) {
fileObject = fileObject.getFileObject(TILE_NAME);
if (fileObject != null) {
img = ImageIO.read(FileUtil.toFile(fileObject));
}
}
} catch (UnsupportedEncodingException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
} catch (IOException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
}
}
return img;
}
private FileObject getCacheFolder() {
synchronized (TILE_NAME) {
if (cacheFolder == null) {
final String TEMP_DIR = System.getProperty(TEMP_FOLDER);
if (TEMP_DIR != null) {
String normalizePath = FileUtil.normalizePath(TEMP_DIR);
if (normalizePath != null) {
FileObject fileObject = FileUtil.toFileObject(new File(normalizePath));
if (fileObject != null) {
cacheFolder = fileObject.getFileObject(TILEFACTORYINFO.getName());
if (cacheFolder == null) {
try {
cacheFolder = fileObject.createFolder(TILEFACTORYINFO.getName());
} catch (IOException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
}
}
}
}
}
}
}
return cacheFolder;
}
private class Dispatcher {
private final RequestProcessor REQUESTPROCESSOR = new RequestProcessor(Dispatcher.class.getName(), Runtime.getRuntime().availableProcessors() * 4);
private void persist(URI uri, BufferedImage img) {
REQUESTPROCESSOR.post(new TileJob(uri, img));
}
}
private class TileJob implements Runnable {
private final URI uri;
private final BufferedImage img;
private TileJob(URI uri, BufferedImage img) {
this.uri = uri;
this.img = img;
}
@Override
public void run() {
FileObject cache = getCacheFolder();
if (cache != null && uri.getPath() != null) {
try {
String path = URLEncoder.encode(uri.getPath().replaceAll("/", "-"), "UTF-8");
FileObject fileObject = cache.getFileObject(path);
if (fileObject == null) {
FileObject folder = cache.createFolder(path);
FileObject tile = folder.createData(TILE_NAME);
ImageIO.write(img, "png", FileUtil.toFile(tile));
} else {
if (fileObject.isFolder()) {
FileObject tile = fileObject.getFileObject(TILE_NAME);
if (tile == null) {
tile = fileObject.createData(TILE_NAME);
ImageIO.write(img, "png", FileUtil.toFile(tile));
} else {
long timeDiff = System.currentTimeMillis() - tile.lastModified().getTime();
if (timeDiff > WEEK_IN_MILLISECONDS) {
ImageIO.write(img, "png", FileUtil.toFile(tile));
}
}
}
}
} catch (UnsupportedEncodingException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
} catch (IOException ex) {
LOG.log(Level.SEVERE, ex.getMessage(), ex);
}
}
}
}
}