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