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 }