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/** 
033 * Provides a cache for storing multiple small files in memory. Can be used to e.g cache gzip compressed PDB files 
034 * for avoiding disk IO bottlenecks.
035 * Note this is just a wrapper for the singleton cache.
036 * 
037 * @author Andreas Prlic.
038 *
039 */
040public class FlatFileCache {
041
042        private final static Logger logger = LoggerFactory.getLogger(FlatFileCache.class);
043
044        /**
045         * The cache singleton.
046         */
047        private static SoftHashMap<String, byte[]> cache = new SoftHashMap<String, byte[]>(0);
048
049
050        // no public constructor;
051        private FlatFileCache(){
052
053        }
054
055
056        public  static void addToCache(String key, File fileToCache){
057                //logger.debug("storing " + key + " on file cache (cache size: " + cache.size() + ")");
058                try {
059                        InputStream is = new FileInputStream(fileToCache);
060                        // Get the size of the file
061                        long length = fileToCache.length();
062
063                        // You cannot create an array using a long type.
064                        // It needs to be an int type.
065                        // Before converting to an int type, check
066                        // to ensure that file is not larger than Integer.MAX_VALUE.
067                        if (length > Integer.MAX_VALUE) {
068                                // File is too large
069                        }
070
071                        // Create the byte array to hold the data
072                        byte[] bytes = new byte[(int)length];
073
074                        // Read in the bytes
075                        int offset = 0;
076                        int numRead = 0;
077                        while (offset < bytes.length
078                                        && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
079                                offset += numRead;
080                        }
081
082                        // Ensure all the bytes have been read in
083                        if (offset < bytes.length) {
084                                is.close();
085                                throw new IOException("Could not completely read file "+fileToCache.getName());
086                        }
087
088                        // Close the input stream and return bytes
089                        is.close();
090
091                        cache.put(key,bytes);
092
093                } catch (Exception e){
094                        logger.error("Error adding to cache! " + e.getMessage(), e);
095                }
096        }
097
098        public  static InputStream getInputStream(String key){
099                //logger.debug("returning " + key + " from file cache (cache size: " + cache.size() + ")");
100                byte[] bytes = cache.get(key);
101                if ( bytes == null)
102                        return null;
103
104                return new ByteArrayInputStream(bytes);
105
106        }
107
108        public static int size() {
109                if ( cache != null)
110                        return cache.size();
111                else
112                        return -1;
113        }
114
115        public static void clear(){
116           cache.clear();
117        }
118
119        
120
121}