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