src/core/net/sf/basedb/util/StreamCacher.java

Code
Comments
Other
Rev Date Author Line
5353 27 May 10 nicklas 1 /**
5353 27 May 10 nicklas 2   $Id$
5353 27 May 10 nicklas 3
5353 27 May 10 nicklas 4   Copyright (C) 2010 Nicklas Nordborg
5353 27 May 10 nicklas 5
5353 27 May 10 nicklas 6   This file is part of BASE - BioArray Software Environment.
5353 27 May 10 nicklas 7   Available at http://base.thep.lu.se/
5353 27 May 10 nicklas 8
5353 27 May 10 nicklas 9   BASE is free software; you can redistribute it and/or
5353 27 May 10 nicklas 10   modify it under the terms of the GNU General Public License
5353 27 May 10 nicklas 11   as published by the Free Software Foundation; either version 3
5353 27 May 10 nicklas 12   of the License, or (at your option) any later version.
5353 27 May 10 nicklas 13
5353 27 May 10 nicklas 14   BASE is distributed in the hope that it will be useful,
5353 27 May 10 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
5353 27 May 10 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5353 27 May 10 nicklas 17   GNU General Public License for more details.
5353 27 May 10 nicklas 18
5353 27 May 10 nicklas 19   You should have received a copy of the GNU General Public License
5353 27 May 10 nicklas 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
5353 27 May 10 nicklas 21 */
5353 27 May 10 nicklas 22 package net.sf.basedb.util;
5353 27 May 10 nicklas 23
5353 27 May 10 nicklas 24 import java.io.IOException;
5353 27 May 10 nicklas 25 import java.io.InputStream;
5353 27 May 10 nicklas 26 import java.io.OutputStream;
5353 27 May 10 nicklas 27
5353 27 May 10 nicklas 28 import net.sf.basedb.core.File;
5353 27 May 10 nicklas 29
5353 27 May 10 nicklas 30 /**
5353 27 May 10 nicklas 31   Caches the contents of a stream to a local temporary file. The 
5353 27 May 10 nicklas 32   {@link #getNewStream()} method will create a stream that appears
5353 27 May 10 nicklas 33   to be reading from the start of the master stream, except that
5353 27 May 10 nicklas 34   it will read cached data to begin with and continue with the master
5353 27 May 10 nicklas 35   stream only if needed. 
5353 27 May 10 nicklas 36   <p>
5353 27 May 10 nicklas 37   
5353 27 May 10 nicklas 38   This class is useful when you know (or suspect) that you need
5353 27 May 10 nicklas 39   to read the same stream multiple times, but the stream may be
5353 27 May 10 nicklas 40   "expensive" to retrieve, either in terms of network capacity or
5353 27 May 10 nicklas 41   cpu processing.
5353 27 May 10 nicklas 42
5353 27 May 10 nicklas 43   @author Nicklas
5353 27 May 10 nicklas 44   @since 2.16
5353 27 May 10 nicklas 45   @base.modified $Date$
5353 27 May 10 nicklas 46   @see File#getCachedDownloadStream()
5353 27 May 10 nicklas 47 */
5353 27 May 10 nicklas 48 public class StreamCacher
7551 12 Dec 18 nicklas 49   implements AutoCloseable
5353 27 May 10 nicklas 50 {
5353 27 May 10 nicklas 51
5353 27 May 10 nicklas 52   // The master stream we are reading from
5353 27 May 10 nicklas 53   private final InputStream master;
5353 27 May 10 nicklas 54   // The splitter stream which will write master-data to the temp-file 
5353 27 May 10 nicklas 55   private final InputStream splitter;
5353 27 May 10 nicklas 56   // The temporary file for storing master-data
5353 27 May 10 nicklas 57   private final java.io.File cacheFile;
5353 27 May 10 nicklas 58   // Stream for writing to the tmp-file
5353 27 May 10 nicklas 59   private final OutputStream cacheOut;
5353 27 May 10 nicklas 60   
5353 27 May 10 nicklas 61   /**
5353 27 May 10 nicklas 62     Create a new stream cacher for reading from the given master stream.
5353 27 May 10 nicklas 63     
5353 27 May 10 nicklas 64     @param master The master input stream
5353 27 May 10 nicklas 65   */
5353 27 May 10 nicklas 66   public StreamCacher(InputStream master)
5353 27 May 10 nicklas 67     throws IOException
5353 27 May 10 nicklas 68   {
5353 27 May 10 nicklas 69     this(master, null);
5353 27 May 10 nicklas 70   }
5353 27 May 10 nicklas 71   
5353 27 May 10 nicklas 72   /**
5353 27 May 10 nicklas 73     Create a new stream cacher for reading from the given master stream.
5353 27 May 10 nicklas 74     
5353 27 May 10 nicklas 75     @param master The master input stream
5353 27 May 10 nicklas 76     @param cacheFile Use this file for the cached data, if the file
5353 27 May 10 nicklas 77       already exist it will be overwritten, if this parameter is null
5353 27 May 10 nicklas 78       a random file will be created in the default temporary directory
5353 27 May 10 nicklas 79   */
5353 27 May 10 nicklas 80   public StreamCacher(InputStream master, java.io.File cacheFile)
5353 27 May 10 nicklas 81     throws IOException
5353 27 May 10 nicklas 82   {
5353 27 May 10 nicklas 83     if (master == null) throw new NullPointerException("master");
5353 27 May 10 nicklas 84     this.master = master;
5353 27 May 10 nicklas 85     if (cacheFile == null)
5353 27 May 10 nicklas 86     {
5353 27 May 10 nicklas 87       cacheFile = java.io.File.createTempFile("cache", ".tmp");
5353 27 May 10 nicklas 88       cacheFile.deleteOnExit();
5353 27 May 10 nicklas 89     }
5353 27 May 10 nicklas 90     this.cacheFile = cacheFile;
5353 27 May 10 nicklas 91     this.cacheOut = FileUtil.getOutputStream(cacheFile);
5353 27 May 10 nicklas 92     this.splitter = new InputStreamSplitter(master, true, false, cacheOut) 
5353 27 May 10 nicklas 93     {
5353 27 May 10 nicklas 94       // Ignore close since we want to keep the master stream open.
5353 27 May 10 nicklas 95       @Override
5353 27 May 10 nicklas 96       public void close()
5353 27 May 10 nicklas 97       {}
5353 27 May 10 nicklas 98     };
5353 27 May 10 nicklas 99   }
5353 27 May 10 nicklas 100
5353 27 May 10 nicklas 101   
5353 27 May 10 nicklas 102   /**
5353 27 May 10 nicklas 103     Close the master stream and remove the cached file data.
5353 27 May 10 nicklas 104   */
7551 12 Dec 18 nicklas 105   @Override
5353 27 May 10 nicklas 106   public void close()
5353 27 May 10 nicklas 107   {
5353 27 May 10 nicklas 108     FileUtil.close(master);
5353 27 May 10 nicklas 109     FileUtil.close(cacheOut);
5353 27 May 10 nicklas 110     cacheFile.delete();
5353 27 May 10 nicklas 111   }
5353 27 May 10 nicklas 112   
5353 27 May 10 nicklas 113   /**
5353 27 May 10 nicklas 114     Get a new stream that appears to be reading from the start of the
5353 27 May 10 nicklas 115     master stream. The new stream will read cached data (if any), and
5353 27 May 10 nicklas 116     only when the end of that data is reached it will start reading from
5353 27 May 10 nicklas 117     the master stream. The data from the master stream is automatically
5353 27 May 10 nicklas 118     copied to the cache.
5353 27 May 10 nicklas 119     
5353 27 May 10 nicklas 120     @return An Input stream
5353 27 May 10 nicklas 121   */
5353 27 May 10 nicklas 122   public InputStream getNewStream()
5353 27 May 10 nicklas 123     throws IOException
5353 27 May 10 nicklas 124   {
5353 27 May 10 nicklas 125     cacheOut.flush(); // Make sure anything from previous reads is flushed to the temp file
5353 27 May 10 nicklas 126     return new InputStreamCombiner(FileUtil.getInputStream(cacheFile), splitter);
5353 27 May 10 nicklas 127   }
5353 27 May 10 nicklas 128   
5353 27 May 10 nicklas 129   
5353 27 May 10 nicklas 130   
5353 27 May 10 nicklas 131   
5353 27 May 10 nicklas 132 }