1 // Copyright (C) 2000 Phil Dawes 2 // Copyright (C) 2000 - 2008 Philip Aston 3 // All rights reserved. 4 // 5 // This file is part of The Grinder software distribution. Refer to 6 // the file LICENSE which is part of The Grinder distribution for 7 // licensing details. The Grinder distribution is available on the 8 // Internet at http://grinder.sourceforge.net/ 9 // 10 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 11 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 12 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 14 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 15 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 16 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 18 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 19 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 20 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 21 // OF THE POSSIBILITY OF SUCH DAMAGE. 22 23 package net.grinder.util; 24 25 import java.io.InputStream; 26 import java.io.IOException; 27 import java.io.OutputStream; 28 29 import net.grinder.common.Closer; 30 import net.grinder.common.UncheckedInterruptedException; 31 import net.grinder.util.thread.InterruptibleRunnable; 32 import net.grinder.util.thread.InterruptibleRunnableAdapter; 33 34 35 /** 36 * Class that copies from <code>InputStream</code>s to 37 * <code>OutputStream</code>s. Can be used in conjunction with an 38 * active thread - see {@link #getInterruptibleRunnable}. 39 * 40 * @author Philip Aston 41 */ 42 public class StreamCopier { 43 44 private final byte[] m_buffer; 45 private final boolean m_closeStreams; 46 47 /** 48 * Constructor. 49 * 50 * @param bufferSize The buffer size. 51 * @param closeStreams <code>true</code> => ensure the streams are 52 * closed after copying. 53 */ 54 public StreamCopier(int bufferSize, boolean closeStreams) { 55 m_buffer = new byte[bufferSize]; 56 m_closeStreams = closeStreams; 57 } 58 59 /** 60 * Copies from the input stream to the output stream until the input 61 * stream is empty or one of the streams reports an error. 62 * 63 * <p>Not thread safe - use multiple <code>StreamCopier</code> 64 * instances instead. 65 * 66 * @param in Input stream. 67 * @param out Output stream. 68 * @throws IOException If an IO problem occurred during the copy. 69 */ 70 public void copy(InputStream in, OutputStream out) throws IOException { 71 72 try { 73 while (true) { 74 final int bytesRead = in.read(m_buffer, 0, m_buffer.length); 75 76 if (bytesRead == -1) { 77 break; 78 } 79 80 out.write(m_buffer, 0, bytesRead); 81 out.flush(); 82 } 83 } 84 finally { 85 if (m_closeStreams) { 86 Closer.close(out); 87 Closer.close(in); 88 } 89 } 90 } 91 92 /** 93 * Creates a <code>InterruptibleRunnable</code> that can be used to copy a 94 * stream with an active Thread. 95 * 96 * <p> 97 * Any exceptions that occur during processing are simply discarded. 98 * 99 * @param in 100 * Input stream. 101 * @param out 102 * Output stream. 103 * @return The <code>InterruptibleRunnable</code>. 104 */ 105 public InterruptibleRunnable getInterruptibleRunnable( 106 final InputStream in, 107 final OutputStream out) { 108 109 return new InterruptibleRunnable() { 110 public void interruptibleRun() { 111 try { 112 copy(in, out); 113 } 114 catch (IOException e) { 115 // Be silent about IOExceptions. 116 UncheckedInterruptedException.ioException(e); 117 } 118 } 119 }; 120 } 121 122 /** 123 * Convenience version of 124 * {@link #getInterruptibleRunnable(InputStream, OutputStream)} that returns a 125 * {@link Runnable}. 126 * 127 * @param in 128 * Input stream. 129 * @param out 130 * Output stream. 131 * @return The <code>InterruptibleRunnable</code>. 132 */ 133 public Runnable getRunnable(InputStream in, OutputStream out) { 134 return new InterruptibleRunnableAdapter(getInterruptibleRunnable(in, out)); 135 } 136 }