package org.csstudio.sds.ui.thumbnail; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import net.sf.ehcache.Status; import net.sf.ehcache.config.CacheConfiguration; import net.sf.ehcache.config.Configuration; import net.sf.ehcache.config.DiskStoreConfiguration; import org.csstudio.sds.ui.SdsUiPlugin; import org.eclipse.core.resources.ResourcesPlugin; public class SdsDisplayValueCache { private static final String CACHE_FOLDER_NAME = "libraryCache"; private final static Cache cache; private final static CacheManager cacheManager; static { File cacheDirectory = getImageCacheDirectory(); Configuration configuration = new Configuration(); configuration.addDiskStore(new DiskStoreConfiguration() .path(cacheDirectory.getAbsolutePath())); cacheManager = CacheManager.create(configuration); CacheConfiguration config = new CacheConfiguration( "DisplayThumbnailCache", 1000); config.overflowToOffHeap(false); config.overflowToDisk(true); config.setDiskPersistent(true); config.setTimeToIdleSeconds(60 * 60 * 24 * 7); config.setTimeToLiveSeconds(60 * 60 * 24 * 30); config.setMaxEntriesLocalHeap(100); config.setMaxBytesLocalDisk("25M"); config.setMaxEntriesLocalDisk(10000); cache = new Cache(config); cacheManager.addCache(cache); } public DisplayCacheValue getCacheValue(File file) { DisplayCacheValue result = null; ClassLoader prevContextClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); Element element = cache.get(file); if(element != null) { DisplayCacheValue value = (DisplayCacheValue) element.getValue(); // Check if cached values are valid if(Arrays.equals(value.getHash(),hashFile(file))) { result = value; } } } finally { Thread.currentThread().setContextClassLoader(prevContextClassLoader); } return result; } public void cacheValueForFile(File file, DisplayCacheValue value) { ClassLoader prevContextClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); cache.put(new Element(file, value)); } finally { Thread.currentThread().setContextClassLoader(prevContextClassLoader); } } public void flush() { cache.flush(); } public void shutdown() { if(cache.getStatus() == Status.STATUS_ALIVE) { cache.flush(); } cacheManager.shutdown(); } private static File getImageCacheDirectory() { File workspaceFile = ResourcesPlugin.getWorkspace().getRoot() .getLocation().toFile(); File result = new File(workspaceFile, ".metadata/.plugins/" + SdsUiPlugin.PLUGIN_ID + "/" + CACHE_FOLDER_NAME); if (!result.exists()) { result.mkdirs(); } return result; } private static byte[] hashFile(File file) { assert file != null : "Precondition failed: file != null"; assert file.exists() : "Precondition failed: file.exists()"; FileInputStream fis = null; try { MessageDigest messageDigest = MessageDigest.getInstance("SHA1"); fis = new FileInputStream(file); byte[] dataBytes = new byte[1024]; int nread = 0; while ((nread = fis.read(dataBytes)) != -1) { messageDigest.update(dataBytes, 0, nread); } return messageDigest.digest(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return null; } }