001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 * Created on Oct 1, 2009 021 * Author: Andreas Prlic 022 * 023 */ 024 025package org.biojava.nbio.core.util; 026 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030import java.io.*; 031 032/** Provides a cache for storing multiple small files in memory. Can be used to e.g cache gzip compressed PDB files for avoiding disk IO bottlenecks. 033 * 034 * @author Andreas Prlic. 035 * 036 */ 037public class FlatFileCache { 038 039 private final static Logger logger = LoggerFactory.getLogger(FlatFileCache.class); 040 041 private static FlatFileCache me ; 042 043 private static SoftHashMap<String, byte[]> cache = new SoftHashMap<String, byte[]>(0); 044 045 public static FlatFileCache getInstance() { 046 047 if ( me == null){ 048 me = new FlatFileCache(); 049 } 050 051 return me; 052 } 053 054 // no public constructor; 055 private FlatFileCache(){ 056 057 } 058 059 060 public static void addToCache(String key, File fileToCache){ 061 //logger.debug("storing " + key + " on file cache (cache size: " + cache.size() + ")"); 062 try { 063 InputStream is = new FileInputStream(fileToCache); 064 // Get the size of the file 065 long length = fileToCache.length(); 066 067 // You cannot create an array using a long type. 068 // It needs to be an int type. 069 // Before converting to an int type, check 070 // to ensure that file is not larger than Integer.MAX_VALUE. 071 if (length > Integer.MAX_VALUE) { 072 // File is too large 073 } 074 075 // Create the byte array to hold the data 076 byte[] bytes = new byte[(int)length]; 077 078 // Read in the bytes 079 int offset = 0; 080 int numRead = 0; 081 while (offset < bytes.length 082 && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { 083 offset += numRead; 084 } 085 086 // Ensure all the bytes have been read in 087 if (offset < bytes.length) { 088 is.close(); 089 throw new IOException("Could not completely read file "+fileToCache.getName()); 090 } 091 092 // Close the input stream and return bytes 093 is.close(); 094 095 cache.put(key,bytes); 096 097 } catch (Exception e){ 098 logger.error("Error adding to cache! " + e.getMessage(), e); 099 } 100 } 101 102 public static InputStream getInputStream(String key){ 103 //logger.debug("returning " + key + " from file cache (cache size: " + cache.size() + ")"); 104 byte[] bytes = cache.get(key); 105 if ( bytes == null) 106 return null; 107 108 return new ByteArrayInputStream(bytes); 109 110 } 111 112 public int size() { 113 if ( cache != null) 114 return cache.size(); 115 else 116 return -1; 117 } 118 119 public void clear(){ 120 cache.clear(); 121 } 122 123 public static void destroy(){ 124 me.clear(); 125 me = null; 126 } 127 128}