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

Code
Comments
Other
Rev Date Author Line
2689 02 Oct 06 nicklas 1 /**
2689 02 Oct 06 nicklas 2   $Id$
2689 02 Oct 06 nicklas 3
3675 16 Aug 07 jari 4   Copyright (C) 2006, 2007 Nicklas Nordborg
2689 02 Oct 06 nicklas 5
2689 02 Oct 06 nicklas 6   This file is part of BASE - BioArray Software Environment.
2689 02 Oct 06 nicklas 7   Available at http://base.thep.lu.se/
2689 02 Oct 06 nicklas 8
2689 02 Oct 06 nicklas 9   BASE is free software; you can redistribute it and/or
2689 02 Oct 06 nicklas 10   modify it under the terms of the GNU General Public License
4479 05 Sep 08 jari 11   as published by the Free Software Foundation; either version 3
2689 02 Oct 06 nicklas 12   of the License, or (at your option) any later version.
2689 02 Oct 06 nicklas 13
2689 02 Oct 06 nicklas 14   BASE is distributed in the hope that it will be useful,
2689 02 Oct 06 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
2689 02 Oct 06 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2689 02 Oct 06 nicklas 17   GNU General Public License for more details.
2689 02 Oct 06 nicklas 18
2689 02 Oct 06 nicklas 19   You should have received a copy of the GNU General Public License
4515 11 Sep 08 jari 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
2689 02 Oct 06 nicklas 21 */
2689 02 Oct 06 nicklas 22 package net.sf.basedb.util;
2689 02 Oct 06 nicklas 23
2689 02 Oct 06 nicklas 24 import java.io.IOException;
2689 02 Oct 06 nicklas 25 import java.io.InputStream;
2689 02 Oct 06 nicklas 26 import java.io.OutputStream;
2689 02 Oct 06 nicklas 27
2689 02 Oct 06 nicklas 28 /**
2689 02 Oct 06 nicklas 29   This class can be used to split an input stream into one or more 
2689 02 Oct 06 nicklas 30   additional output streams. When data is read from this input stream
2689 02 Oct 06 nicklas 31   the bytes are also written to the specified output streams with one of the
2689 02 Oct 06 nicklas 32   {@link java.io.OutputStream#write(int)} or 
2689 02 Oct 06 nicklas 33   {@link java.io.OutputStream#write(byte[], int, int)} methods.
2689 02 Oct 06 nicklas 34
2689 02 Oct 06 nicklas 35   @author nicklas
2689 02 Oct 06 nicklas 36   @version 2.0
2689 02 Oct 06 nicklas 37   @base.modified $Date$
2689 02 Oct 06 nicklas 38 */
2689 02 Oct 06 nicklas 39 public class InputStreamSplitter
2689 02 Oct 06 nicklas 40   extends InputStream
2689 02 Oct 06 nicklas 41 {
2689 02 Oct 06 nicklas 42
3606 27 Jul 07 nicklas 43   private int numRead;
3606 27 Jul 07 nicklas 44   
2689 02 Oct 06 nicklas 45   /**
2689 02 Oct 06 nicklas 46     The source input stream to read from.
2689 02 Oct 06 nicklas 47   */
2689 02 Oct 06 nicklas 48   private final InputStream in;
2689 02 Oct 06 nicklas 49   
2689 02 Oct 06 nicklas 50   /**
2689 02 Oct 06 nicklas 51     Streams to copy the data to.
2689 02 Oct 06 nicklas 52   */
2689 02 Oct 06 nicklas 53   private final OutputStream[] copyTo;
2689 02 Oct 06 nicklas 54   
2689 02 Oct 06 nicklas 55   /**
3606 27 Jul 07 nicklas 56     If the {@link #skip(long)} method should copy
3606 27 Jul 07 nicklas 57     to the output streams or no.
2689 02 Oct 06 nicklas 58   */
3606 27 Jul 07 nicklas 59   private final boolean copySkipped;
2689 02 Oct 06 nicklas 60   
2689 02 Oct 06 nicklas 61   /**
3606 27 Jul 07 nicklas 62     If the remainder of the input stream should be copied
3606 27 Jul 07 nicklas 63     if it is closed before the end.
3606 27 Jul 07 nicklas 64   */
3606 27 Jul 07 nicklas 65   private final boolean readToEnd;
3606 27 Jul 07 nicklas 66   
3606 27 Jul 07 nicklas 67   /**
3606 27 Jul 07 nicklas 68     Create a new input stream splitter. Skipped bytes are not copied
3606 27 Jul 07 nicklas 69     and the remainder of the stream is not copied if closed.
2689 02 Oct 06 nicklas 70     @param in The input stream to read from
2689 02 Oct 06 nicklas 71     @param copyTo The output streams to copy data to
2689 02 Oct 06 nicklas 72   */
2689 02 Oct 06 nicklas 73   public InputStreamSplitter(InputStream in, OutputStream... copyTo)
2689 02 Oct 06 nicklas 74   {
3606 27 Jul 07 nicklas 75     this(in, false, false, copyTo);
3606 27 Jul 07 nicklas 76   }
3606 27 Jul 07 nicklas 77
3606 27 Jul 07 nicklas 78   /**
3606 27 Jul 07 nicklas 79     Create a new input stream splitter. Skipped bytes are not copied
3606 27 Jul 07 nicklas 80     and the remainder of the stream is not copied if closed.
4034 05 Dec 07 martin 81     @param in The input stream to read from. Null is not allowed
4034 05 Dec 07 martin 82      @param copySkipped  TRUE if skipped bytes should be copied, FALSE otherwise
4034 05 Dec 07 martin 83      @param readToEnd If the remainder of the input stream should be copied
4034 05 Dec 07 martin 84       if it is closed before the end
4034 05 Dec 07 martin 85     @param copyTo The output streams to copy data to. Null is not allowed
3606 27 Jul 07 nicklas 86     @since 2.4
3606 27 Jul 07 nicklas 87   */
3606 27 Jul 07 nicklas 88   public InputStreamSplitter(InputStream in, boolean copySkipped, boolean readToEnd, OutputStream... copyTo)
3606 27 Jul 07 nicklas 89   {
2689 02 Oct 06 nicklas 90     if (in == null) throw new NullPointerException("in");
2689 02 Oct 06 nicklas 91     if (copyTo == null) throw new NullPointerException("copyTo");
2689 02 Oct 06 nicklas 92     this.in = in;
2689 02 Oct 06 nicklas 93     this.copyTo = copyTo;
3606 27 Jul 07 nicklas 94     this.copySkipped = copySkipped;
3606 27 Jul 07 nicklas 95     this.readToEnd = readToEnd;
2689 02 Oct 06 nicklas 96   }
3606 27 Jul 07 nicklas 97   
2689 02 Oct 06 nicklas 98   /*
2689 02 Oct 06 nicklas 99     From the InputStream class
2689 02 Oct 06 nicklas 100     -------------------------------------------
2689 02 Oct 06 nicklas 101   */
2689 02 Oct 06 nicklas 102   @Override
2689 02 Oct 06 nicklas 103   public int available() 
2689 02 Oct 06 nicklas 104     throws IOException
2689 02 Oct 06 nicklas 105   {
2689 02 Oct 06 nicklas 106     return in.available();
2689 02 Oct 06 nicklas 107   }
2689 02 Oct 06 nicklas 108   @Override
2689 02 Oct 06 nicklas 109   public void close() 
2689 02 Oct 06 nicklas 110     throws IOException
2689 02 Oct 06 nicklas 111   {
3606 27 Jul 07 nicklas 112     if (readToEnd)
3606 27 Jul 07 nicklas 113     {
3606 27 Jul 07 nicklas 114       FileUtil.read(this);
3606 27 Jul 07 nicklas 115     }
2689 02 Oct 06 nicklas 116     in.close();
3606 27 Jul 07 nicklas 117     for (OutputStream out : copyTo)
3606 27 Jul 07 nicklas 118     {
3606 27 Jul 07 nicklas 119       out.flush();
3606 27 Jul 07 nicklas 120     }
2689 02 Oct 06 nicklas 121   }
2689 02 Oct 06 nicklas 122   @Override
2689 02 Oct 06 nicklas 123   public synchronized void mark(int readlimit)
3606 27 Jul 07 nicklas 124   {}
2689 02 Oct 06 nicklas 125   @Override
2689 02 Oct 06 nicklas 126   public boolean markSupported()
2689 02 Oct 06 nicklas 127   {
3606 27 Jul 07 nicklas 128     return false;
2689 02 Oct 06 nicklas 129   }
3606 27 Jul 07 nicklas 130   @Override
2689 02 Oct 06 nicklas 131   public int read() 
2689 02 Oct 06 nicklas 132     throws IOException
2689 02 Oct 06 nicklas 133   {
2689 02 Oct 06 nicklas 134     int result = in.read();
3606 27 Jul 07 nicklas 135     if (result >= 0) 
3606 27 Jul 07 nicklas 136     {
3606 27 Jul 07 nicklas 137       ++numRead;
3606 27 Jul 07 nicklas 138       copy(result);
3606 27 Jul 07 nicklas 139     }
2689 02 Oct 06 nicklas 140     return result;
2689 02 Oct 06 nicklas 141   }
2689 02 Oct 06 nicklas 142   @Override
2689 02 Oct 06 nicklas 143   public int read(byte[] b, int off, int len) 
2689 02 Oct 06 nicklas 144     throws IOException
2689 02 Oct 06 nicklas 145   {
2689 02 Oct 06 nicklas 146     int result = in.read(b, off, len);
3606 27 Jul 07 nicklas 147     if (result > 0) 
3606 27 Jul 07 nicklas 148     {
3606 27 Jul 07 nicklas 149       numRead += result;
3606 27 Jul 07 nicklas 150       copy(b, off, result);
3606 27 Jul 07 nicklas 151     }
2689 02 Oct 06 nicklas 152     return result;
2689 02 Oct 06 nicklas 153   }
2689 02 Oct 06 nicklas 154   @Override
2689 02 Oct 06 nicklas 155   public int read(byte[] b) 
2689 02 Oct 06 nicklas 156     throws IOException
2689 02 Oct 06 nicklas 157   {
2689 02 Oct 06 nicklas 158     return read(b, 0, b.length);
2689 02 Oct 06 nicklas 159   }
2689 02 Oct 06 nicklas 160   @Override
2689 02 Oct 06 nicklas 161   public synchronized void reset() 
2689 02 Oct 06 nicklas 162     throws IOException
2689 02 Oct 06 nicklas 163   {
3606 27 Jul 07 nicklas 164     throw new IOException("reset/mark is not supported");
2689 02 Oct 06 nicklas 165   }
2689 02 Oct 06 nicklas 166   @Override
2689 02 Oct 06 nicklas 167   public long skip(long n)
2689 02 Oct 06 nicklas 168     throws IOException
2689 02 Oct 06 nicklas 169   {
3606 27 Jul 07 nicklas 170     long result = 0;
3606 27 Jul 07 nicklas 171     if (copySkipped)
3606 27 Jul 07 nicklas 172     {
3606 27 Jul 07 nicklas 173       // This will call the read(byte[], int, int) method
3606 27 Jul 07 nicklas 174       result = super.skip(n);
3606 27 Jul 07 nicklas 175     }
3606 27 Jul 07 nicklas 176     else
3606 27 Jul 07 nicklas 177     {
5384 13 Aug 10 nicklas 178       result = in.skip(n);
3606 27 Jul 07 nicklas 179     }
2689 02 Oct 06 nicklas 180     return result;
2689 02 Oct 06 nicklas 181   }
2689 02 Oct 06 nicklas 182   // -------------------------------------------
2689 02 Oct 06 nicklas 183
2689 02 Oct 06 nicklas 184   /**
3606 27 Jul 07 nicklas 185     Get the number of bytes that has been read or skipped 
3606 27 Jul 07 nicklas 186     from the input stream.
3606 27 Jul 07 nicklas 187     @since 2.4
3606 27 Jul 07 nicklas 188   */
3606 27 Jul 07 nicklas 189   public long getNumRead()
3606 27 Jul 07 nicklas 190   {
3606 27 Jul 07 nicklas 191     return numRead;
3606 27 Jul 07 nicklas 192   }
3606 27 Jul 07 nicklas 193   
3606 27 Jul 07 nicklas 194   /**
2689 02 Oct 06 nicklas 195     Write data to all output streams.
2689 02 Oct 06 nicklas 196   */
2689 02 Oct 06 nicklas 197   private void copy(int b)
2689 02 Oct 06 nicklas 198     throws IOException
2689 02 Oct 06 nicklas 199   {
2689 02 Oct 06 nicklas 200     for (OutputStream out : copyTo)
2689 02 Oct 06 nicklas 201     {
2689 02 Oct 06 nicklas 202       out.write(b);
2689 02 Oct 06 nicklas 203     }
2689 02 Oct 06 nicklas 204   }
2689 02 Oct 06 nicklas 205   
2689 02 Oct 06 nicklas 206   /**
2689 02 Oct 06 nicklas 207     Write data to all output streams.
2689 02 Oct 06 nicklas 208   */
2689 02 Oct 06 nicklas 209   private void copy(byte[] b, int off, int len)
2689 02 Oct 06 nicklas 210     throws IOException
2689 02 Oct 06 nicklas 211   {
2689 02 Oct 06 nicklas 212     for (OutputStream out : copyTo)
2689 02 Oct 06 nicklas 213     {
2689 02 Oct 06 nicklas 214       out.write(b, off, len);
2689 02 Oct 06 nicklas 215     }
2689 02 Oct 06 nicklas 216   }
2689 02 Oct 06 nicklas 217
2689 02 Oct 06 nicklas 218 }