/* * Cuelib library for manipulating cue sheets. * Copyright (C) 2007-2008 Jan-Willem van den Broek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package jwbroek.io; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.logging.Level; import java.util.logging.Logger; import jwbroek.util.LogUtil; /** * Utility class for piping data from an InputStream to an OutputStream, or to nowhere. This class is particularly useful * for reading the output streams of a java.lang.Process, as such a Process may block if its output is not read. * @author jwbroek */ public class StreamPiper implements Runnable { /** * Stream to read input from. mus not be null. */ private InputStream from; /** * Stream to pipe input to. May be null, in which case all input is discarded. */ private OutputStream to; /** * Whether or not to close the output stream after all data has been piped. */ private boolean closeOutput; /** * The logger for this class. */ private final static Logger logger = Logger.getLogger(StreamPiper.class.getCanonicalName()); /** * Pipe all input from the InputStream to the OutputStream. The OutputStream is explicitly allowed to be null. * In such a case, all input will be discarded. In any case, the OutputStream will not be closed by StreamPiper, * but the InputStream will, once its end is reached. * @param from * @param to */ public StreamPiper(final InputStream from, final OutputStream to) { this(from, to, false); StreamPiper.logger.entering (StreamPiper.class.getCanonicalName(), "StreamPiper(InputStream,OutputStream)", new Object[] {from, to}); StreamPiper.logger.exiting(StreamPiper.class.getCanonicalName(), "StreamPiper(InputStream,OutputStream)"); } /** * Pipe all input from the InputStream to the OutputStream. The OutputStream is explicitly allowed to be null. * In such a case, all input will be discarded. In any case, the OutputStream will only be closed by StreamPiper if * this is requested, while the InputStream will always be, once its end is reached. * @param from * @param to * @param closeOutput */ public StreamPiper(final InputStream from, final OutputStream to, final boolean closeOutput) { StreamPiper.logger.entering ( StreamPiper.class.getCanonicalName() , "StreamPiper(InputStream,OutputStream,boolean)" , new Object [] {from, to, closeOutput} ); this.from = from; this.to = to; this.closeOutput = closeOutput; StreamPiper.logger.exiting(StreamPiper.class.getCanonicalName(), "StreamPiper(InputStream,OutputStream,boolean)"); } /** * Pipe the contents of the specified input stream to the specified file, or throw it away if the file is * null. * @param from The input to stream to file. * @param file The file to pipe input to, or null if the input should be thrown away. * @throws IOException */ public static void pipeStream(final InputStream from, final File file) throws IOException { StreamPiper.logger.entering (StreamPiper.class.getCanonicalName(), "pipeStream(InputStream,File)", new Object [] {from, file}); OutputStream out = null; if (file!=null) { out = new FileOutputStream(file); } new Thread(new StreamPiper(from, out, true)).start(); StreamPiper.logger.exiting(StreamPiper.class.getCanonicalName(), "pipeStream(InputStream,File)"); } /** * Perform the data piping. */ public void run() { StreamPiper.logger.entering(StreamPiper.class.getCanonicalName(), "run()"); try { int input = this.from.read(); while (input != -1) { if (this.to != null) { this.to.write(input); } input = this.from.read(); } } catch (IOException e) { // Nothing we can do. LogUtil.logStacktrace(StreamPiper.logger, Level.WARNING, e); } finally { try { this.from.close(); } catch (IOException e) { // Nothing we can do. LogUtil.logStacktrace(StreamPiper.logger, Level.WARNING, e); } if (this.closeOutput && this.to != null) { try { this.to.close(); } catch (IOException e) { // Nothing we can do. LogUtil.logStacktrace(StreamPiper.logger, Level.WARNING, e); } } } StreamPiper.logger.exiting(StreamPiper.class.getCanonicalName(), "run()"); } }