View Javadoc

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 }