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}