1 /*******************************************************************************
2 * Copyright (c) 2012 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.maps.eclipse;
14 import java.awt.Image;
15 import java.awt.geom.Rectangle2D;
16 import java.awt.image.BufferedImage;
17 import java.awt.image.RenderedImage;
19 import java.io.IOException;
21 import java.util.concurrent.ForkJoinPool;
23 import javax.imageio.ImageIO;
25 import org.eclipse.core.runtime.IPath;
26 import org.eclipse.core.runtime.Platform;
27 import org.osgi.framework.Bundle;
28 import org.simantics.maps.ProvisionException;
29 import org.simantics.maps.internal.ImageUtil;
30 import org.simantics.maps.tile.ITileProvider;
31 import org.simantics.maps.tile.TileKey;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * @author Tuukka Lehtonen
38 public class DiskCachingTileProvider implements ITileProvider {
40 private static final Logger LOGGER = LoggerFactory.getLogger(DiskCachingTileProvider.class);
42 private final String CACHED_IMAGE_FORMAT = "png";
44 ITileProvider provider;
50 public DiskCachingTileProvider(ITileProvider provider, Boolean supportAlpha) {
51 this.provider = provider;
52 this.supportAlpha = supportAlpha;
57 public URI getSource() {
58 return provider.getSource();
62 public Rectangle2D getExtent() {
63 return provider.getExtent();
66 private void initCache() {
67 Bundle b = Platform.getBundle("org.simantics.maps");
70 IPath statePath = Platform.getStateLocation(b);
71 URI source = provider.getSource();
72 IPath cache = statePath.append("cache").append(source.getScheme()).append(source.getHost());
74 // Create the cache directory if it doesn't exist.
75 File f = cache.toFile();
78 } else if (!f.isDirectory()) {
79 LOGGER.error("Tile cache directory " + f.toString() + " already exists as a file, cannot use it as a cache directory", new Exception());
83 this.cachePath = cache;
84 // System.out.println("MAP DATA CACHE: " + cachePath);
86 // Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(CACHED_IMAGE_FORMAT);
87 // writer = writers.next();
88 // Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(CACHED_IMAGE_FORMAT);
89 // reader = readers.next();
92 private IPath toTileCachePath(TileKey key) {
93 return cachePath.append(key.getLevel() + "." + key.getX() + "." + key.getY());
96 private Image lookupFromDisk(TileKey key) {
97 if (cachePath == null)
100 IPath cachePath = toTileCachePath(key).addFileExtension(CACHED_IMAGE_FORMAT);
101 File f = cachePath.toFile();
104 BufferedImage img = ImageIO.read(f);
106 //System.out.println("[" + provider + "] Disk cache hit: " + key);
107 //System.out.println("[" + provider + "] image: " + img);
108 // Need to make sure that the type of the loaded image is
109 // something that can be rendered in an accelerated fashion.
110 return ImageUtil.toScreenCompatibleImage(img);
112 } catch (IOException e) {
113 LOGGER.warn("Failed to load cached tile from {}", f.toString(), e);
116 // Data is most likely corrupted, just destroy it.
119 // System.out.println("Disk cache miss: " + key);
123 private void cacheToDisk(TileKey key, Image img) {
124 if (cachePath == null)
127 if (!(img instanceof RenderedImage))
130 IPath cachePath = toTileCachePath(key).addFileExtension(CACHED_IMAGE_FORMAT);
131 File f = cachePath.toFile();
133 if (ImageIO.write((RenderedImage) img, CACHED_IMAGE_FORMAT, f)) {
134 //System.out.println("[" + provider + "] Disk cache write: " + key);
136 } catch (IOException e) {
137 // Caching failed, be silent about it.
142 public Image get(TileKey key) throws ProvisionException {
143 Image img = lookupFromDisk(key);
145 img = provider.get(key);
146 final Image image = img;
147 if (cachePath != null) {
148 // Write image to disk in the background
149 ForkJoinPool.commonPool().submit(() -> cacheToDisk(key, image));
156 public String toString() {
157 return getClass().getSimpleName() + " [" + provider.toString() + "]";