View Javadoc

1   /*
2    * Copyright 2001-2005 The Apache Software Foundation
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.net.io;
17  
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.io.OutputStream;
21  import java.io.Reader;
22  import java.io.Writer;
23  
24  /***
25   * The Util class cannot be instantiated and stores short static convenience
26   * methods that are often quite useful.
27   * <p>
28   * <p>
29   * @see CopyStreamException
30   * @see CopyStreamListener
31   * @see CopyStreamAdapter
32   * @author Daniel F. Savarese
33   ***/
34  
35  public final class Util
36  {
37      /***
38       * The default buffer size used by {@link #copyStream  copyStream }
39       * and {@link #copyReader  copyReader }. It's value is 1024.
40       ***/
41      public static final int DEFAULT_COPY_BUFFER_SIZE = 1024;
42  
43      // Cannot be instantiated
44      private Util()
45      { }
46  
47  
48      /***
49       * Copies the contents of an InputStream to an OutputStream using a
50       * copy buffer of a given size and notifies the provided
51       * CopyStreamListener of the progress of the copy operation by calling
52       * its bytesTransferred(long, int) method after each write to the
53       * destination.  If you wish to notify more than one listener you should
54       * use a CopyStreamAdapter as the listener and register the additional
55       * listeners with the CopyStreamAdapter.
56       * <p>
57       * The contents of the InputStream are
58       * read until the end of the stream is reached, but neither the
59       * source nor the destination are closed.  You must do this yourself
60       * outside of the method call.  The number of bytes read/written is
61       * returned.
62       * <p>
63       * @param source  The source InputStream.
64       * @param dest    The destination OutputStream.
65       * @param bufferSize  The number of bytes to buffer during the copy.
66       * @param streamSize  The number of bytes in the stream being copied.
67       *          Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
68       * @param listener  The CopyStreamListener to notify of progress.  If
69       *      this parameter is null, notification is not attempted.
70       * @param flush Whether to flush the output stream after every
71       *        write.  This is necessary for interactive sessions that rely on
72       *        buffered streams.  If you don't flush, the data will stay in
73       *        the stream buffer.
74       * @exception CopyStreamException  If an error occurs while reading from the
75       *            source or writing to the destination.  The CopyStreamException
76       *            will contain the number of bytes confirmed to have been
77       *            transferred before an
78       *            IOException occurred, and it will also contain the IOException
79       *            that caused the error.  These values can be retrieved with
80       *            the CopyStreamException getTotalBytesTransferred() and
81       *            getIOException() methods.
82       ***/
83      public static final long copyStream(InputStream source, OutputStream dest,
84                                          int bufferSize, long streamSize,
85                                          CopyStreamListener listener,
86                                          boolean flush)
87      throws CopyStreamException
88      {
89          int bytes;
90          long total;
91          byte[] buffer;
92  
93          buffer = new byte[bufferSize];
94          total = 0;
95  
96          try
97          {
98              while ((bytes = source.read(buffer)) != -1)
99              {
100                 // Technically, some read(byte[]) methods may return 0 and we cannot
101                 // accept that as an indication of EOF.
102 
103                 if (bytes == 0)
104                 {
105                     bytes = source.read();
106                     if (bytes < 0)
107                         break;
108                     dest.write(bytes);
109                     if(flush)
110                       dest.flush();
111                     ++total;
112                     if (listener != null)
113                         listener.bytesTransferred(total, 1, streamSize);
114                     continue;
115                 }
116 
117                 dest.write(buffer, 0, bytes);
118                 if(flush)
119                   dest.flush();
120                 total += bytes;
121                 if (listener != null)
122                     listener.bytesTransferred(total, bytes, streamSize);
123             }
124         }
125         catch (IOException e)
126         {
127             throw new CopyStreamException("IOException caught while copying.",
128                                           total, e);
129         }
130 
131         return total;
132     }
133 
134 
135     /***
136      * Copies the contents of an InputStream to an OutputStream using a
137      * copy buffer of a given size and notifies the provided
138      * CopyStreamListener of the progress of the copy operation by calling
139      * its bytesTransferred(long, int) method after each write to the
140      * destination.  If you wish to notify more than one listener you should
141      * use a CopyStreamAdapter as the listener and register the additional
142      * listeners with the CopyStreamAdapter.
143      * <p>
144      * The contents of the InputStream are
145      * read until the end of the stream is reached, but neither the
146      * source nor the destination are closed.  You must do this yourself
147      * outside of the method call.  The number of bytes read/written is
148      * returned.
149      * <p>
150      * @param source  The source InputStream.
151      * @param dest    The destination OutputStream.
152      * @param bufferSize  The number of bytes to buffer during the copy.
153      * @param streamSize  The number of bytes in the stream being copied.
154      *          Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
155      * @param listener  The CopyStreamListener to notify of progress.  If
156      *      this parameter is null, notification is not attempted.
157      * @exception CopyStreamException  If an error occurs while reading from the
158      *            source or writing to the destination.  The CopyStreamException
159      *            will contain the number of bytes confirmed to have been
160      *            transferred before an
161      *            IOException occurred, and it will also contain the IOException
162      *            that caused the error.  These values can be retrieved with
163      *            the CopyStreamException getTotalBytesTransferred() and
164      *            getIOException() methods.
165      ***/
166     public static final long copyStream(InputStream source, OutputStream dest,
167                                         int bufferSize, long streamSize,
168                                         CopyStreamListener listener)
169     throws CopyStreamException
170     {
171       return copyStream(source, dest, bufferSize, streamSize, listener,
172                         true);
173     }
174 
175 
176     /***
177      * Copies the contents of an InputStream to an OutputStream using a
178      * copy buffer of a given size.  The contents of the InputStream are
179      * read until the end of the stream is reached, but neither the
180      * source nor the destination are closed.  You must do this yourself
181      * outside of the method call.  The number of bytes read/written is
182      * returned.
183      * <p>
184      * @param source  The source InputStream.
185      * @param dest    The destination OutputStream.
186      * @return  The number of bytes read/written in the copy operation.
187      * @exception CopyStreamException  If an error occurs while reading from the
188      *            source or writing to the destination.  The CopyStreamException
189      *            will contain the number of bytes confirmed to have been
190      *            transferred before an
191      *            IOException occurred, and it will also contain the IOException
192      *            that caused the error.  These values can be retrieved with
193      *            the CopyStreamException getTotalBytesTransferred() and
194      *            getIOException() methods.
195      ***/
196     public static final long copyStream(InputStream source, OutputStream dest,
197                                         int bufferSize)
198     throws CopyStreamException
199     {
200         return copyStream(source, dest, bufferSize,
201                           CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
202     }
203 
204 
205     /***
206      * Same as <code> copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code>
207      ***/
208     public static final long copyStream(InputStream source, OutputStream dest)
209     throws CopyStreamException
210     {
211         return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
212     }
213 
214 
215     /***
216      * Copies the contents of a Reader to a Writer using a
217      * copy buffer of a given size and notifies the provided
218      * CopyStreamListener of the progress of the copy operation by calling
219      * its bytesTransferred(long, int) method after each write to the
220      * destination.  If you wish to notify more than one listener you should
221      * use a CopyStreamAdapter as the listener and register the additional
222      * listeners with the CopyStreamAdapter.
223      * <p>
224      * The contents of the Reader are
225      * read until its end is reached, but neither the source nor the
226      * destination are closed.  You must do this yourself outside of the
227      * method call.  The number of characters read/written is returned.
228      * <p>
229      * @param source  The source Reader.
230      * @param dest    The destination writer.
231      * @param bufferSize  The number of characters to buffer during the copy.
232      * @param streamSize  The number of characters in the stream being copied.
233      *          Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
234      * @param listener  The CopyStreamListener to notify of progress.  If
235      *      this parameter is null, notification is not attempted.
236      * @return  The number of characters read/written in the copy operation.
237      * @exception CopyStreamException  If an error occurs while reading from the
238      *            source or writing to the destination.  The CopyStreamException
239      *            will contain the number of bytes confirmed to have been
240      *            transferred before an
241      *            IOException occurred, and it will also contain the IOException
242      *            that caused the error.  These values can be retrieved with
243      *            the CopyStreamException getTotalBytesTransferred() and
244      *            getIOException() methods.
245      ***/
246     public static final long copyReader(Reader source, Writer dest,
247                                         int bufferSize, long streamSize,
248                                         CopyStreamListener listener)
249     throws CopyStreamException
250     {
251         int chars;
252         long total;
253         char[] buffer;
254 
255         buffer = new char[bufferSize];
256         total = 0;
257 
258         try
259         {
260             while ((chars = source.read(buffer)) != -1)
261             {
262                 // Technically, some read(char[]) methods may return 0 and we cannot
263                 // accept that as an indication of EOF.
264                 if (chars == 0)
265                 {
266                     chars = source.read();
267                     if (chars < 0)
268                         break;
269                     dest.write(chars);
270                     dest.flush();
271                     ++total;
272                     if (listener != null)
273                         listener.bytesTransferred(total, chars, streamSize);
274                     continue;
275                 }
276 
277                 dest.write(buffer, 0, chars);
278                 dest.flush();
279                 total += chars;
280                 if (listener != null)
281                     listener.bytesTransferred(total, chars, streamSize);
282             }
283         }
284         catch (IOException e)
285         {
286             throw new CopyStreamException("IOException caught while copying.",
287                                           total, e);
288         }
289 
290         return total;
291     }
292 
293 
294     /***
295      * Copies the contents of a Reader to a Writer using a
296      * copy buffer of a given size.  The contents of the Reader are
297      * read until its end is reached, but neither the source nor the
298      * destination are closed.  You must do this yourself outside of the
299      * method call.  The number of characters read/written is returned.
300      * <p>
301      * @param source  The source Reader.
302      * @param dest    The destination writer.
303      * @param bufferSize  The number of characters to buffer during the copy.
304      * @return  The number of characters read/written in the copy operation.
305      * @exception CopyStreamException  If an error occurs while reading from the
306      *            source or writing to the destination.  The CopyStreamException
307      *            will contain the number of bytes confirmed to have been
308      *            transferred before an
309      *            IOException occurred, and it will also contain the IOException
310      *            that caused the error.  These values can be retrieved with
311      *            the CopyStreamException getTotalBytesTransferred() and
312      *            getIOException() methods.
313      ***/
314     public static final long copyReader(Reader source, Writer dest,
315                                         int bufferSize)
316     throws CopyStreamException
317     {
318         return copyReader(source, dest, bufferSize,
319                           CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
320     }
321 
322 
323     /***
324      * Same as <code> copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code>
325      ***/
326     public static final long copyReader(Reader source, Writer dest)
327     throws CopyStreamException
328     {
329         return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
330     }
331 
332 }