001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.net.io;
019
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.io.OutputStream;
023 import java.io.Reader;
024 import java.io.Writer;
025
026 /***
027 * The Util class cannot be instantiated and stores short static convenience
028 * methods that are often quite useful.
029 * <p>
030 * <p>
031 * @see CopyStreamException
032 * @see CopyStreamListener
033 * @see CopyStreamAdapter
034 * @author Daniel F. Savarese
035 ***/
036
037 public final class Util
038 {
039 /***
040 * The default buffer size used by {@link #copyStream copyStream }
041 * and {@link #copyReader copyReader }. It's value is 1024.
042 ***/
043 public static final int DEFAULT_COPY_BUFFER_SIZE = 1024;
044
045 // Cannot be instantiated
046 private Util()
047 { }
048
049
050 /***
051 * Copies the contents of an InputStream to an OutputStream using a
052 * copy buffer of a given size and notifies the provided
053 * CopyStreamListener of the progress of the copy operation by calling
054 * its bytesTransferred(long, int) method after each write to the
055 * destination. If you wish to notify more than one listener you should
056 * use a CopyStreamAdapter as the listener and register the additional
057 * listeners with the CopyStreamAdapter.
058 * <p>
059 * The contents of the InputStream are
060 * read until the end of the stream is reached, but neither the
061 * source nor the destination are closed. You must do this yourself
062 * outside of the method call. The number of bytes read/written is
063 * returned.
064 * <p>
065 * @param source The source InputStream.
066 * @param dest The destination OutputStream.
067 * @param bufferSize The number of bytes to buffer during the copy.
068 * @param streamSize The number of bytes in the stream being copied.
069 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
070 * @param listener The CopyStreamListener to notify of progress. If
071 * this parameter is null, notification is not attempted.
072 * @param flush Whether to flush the output stream after every
073 * write. This is necessary for interactive sessions that rely on
074 * buffered streams. If you don't flush, the data will stay in
075 * the stream buffer.
076 * @exception CopyStreamException If an error occurs while reading from the
077 * source or writing to the destination. The CopyStreamException
078 * will contain the number of bytes confirmed to have been
079 * transferred before an
080 * IOException occurred, and it will also contain the IOException
081 * that caused the error. These values can be retrieved with
082 * the CopyStreamException getTotalBytesTransferred() and
083 * getIOException() methods.
084 ***/
085 public static final long copyStream(InputStream source, OutputStream dest,
086 int bufferSize, long streamSize,
087 CopyStreamListener listener,
088 boolean flush)
089 throws CopyStreamException
090 {
091 int bytes;
092 long total;
093 byte[] buffer;
094
095 buffer = new byte[bufferSize];
096 total = 0;
097
098 try
099 {
100 while ((bytes = source.read(buffer)) != -1)
101 {
102 // Technically, some read(byte[]) methods may return 0 and we cannot
103 // accept that as an indication of EOF.
104
105 if (bytes == 0)
106 {
107 bytes = source.read();
108 if (bytes < 0)
109 break;
110 dest.write(bytes);
111 if(flush)
112 dest.flush();
113 ++total;
114 if (listener != null)
115 listener.bytesTransferred(total, 1, streamSize);
116 continue;
117 }
118
119 dest.write(buffer, 0, bytes);
120 if(flush)
121 dest.flush();
122 total += bytes;
123 if (listener != null)
124 listener.bytesTransferred(total, bytes, streamSize);
125 }
126 }
127 catch (IOException e)
128 {
129 throw new CopyStreamException("IOException caught while copying.",
130 total, e);
131 }
132
133 return total;
134 }
135
136
137 /***
138 * Copies the contents of an InputStream to an OutputStream using a
139 * copy buffer of a given size and notifies the provided
140 * CopyStreamListener of the progress of the copy operation by calling
141 * its bytesTransferred(long, int) method after each write to the
142 * destination. If you wish to notify more than one listener you should
143 * use a CopyStreamAdapter as the listener and register the additional
144 * listeners with the CopyStreamAdapter.
145 * <p>
146 * The contents of the InputStream are
147 * read until the end of the stream is reached, but neither the
148 * source nor the destination are closed. You must do this yourself
149 * outside of the method call. The number of bytes read/written is
150 * returned.
151 * <p>
152 * @param source The source InputStream.
153 * @param dest The destination OutputStream.
154 * @param bufferSize The number of bytes to buffer during the copy.
155 * @param streamSize The number of bytes in the stream being copied.
156 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
157 * @param listener The CopyStreamListener to notify of progress. If
158 * this parameter is null, notification is not attempted.
159 * @exception CopyStreamException If an error occurs while reading from the
160 * source or writing to the destination. The CopyStreamException
161 * will contain the number of bytes confirmed to have been
162 * transferred before an
163 * IOException occurred, and it will also contain the IOException
164 * that caused the error. These values can be retrieved with
165 * the CopyStreamException getTotalBytesTransferred() and
166 * getIOException() methods.
167 ***/
168 public static final long copyStream(InputStream source, OutputStream dest,
169 int bufferSize, long streamSize,
170 CopyStreamListener listener)
171 throws CopyStreamException
172 {
173 return copyStream(source, dest, bufferSize, streamSize, listener,
174 true);
175 }
176
177
178 /***
179 * Copies the contents of an InputStream to an OutputStream using a
180 * copy buffer of a given size. The contents of the InputStream are
181 * read until the end of the stream is reached, but neither the
182 * source nor the destination are closed. You must do this yourself
183 * outside of the method call. The number of bytes read/written is
184 * returned.
185 * <p>
186 * @param source The source InputStream.
187 * @param dest The destination OutputStream.
188 * @return The number of bytes read/written in the copy operation.
189 * @exception CopyStreamException If an error occurs while reading from the
190 * source or writing to the destination. The CopyStreamException
191 * will contain the number of bytes confirmed to have been
192 * transferred before an
193 * IOException occurred, and it will also contain the IOException
194 * that caused the error. These values can be retrieved with
195 * the CopyStreamException getTotalBytesTransferred() and
196 * getIOException() methods.
197 ***/
198 public static final long copyStream(InputStream source, OutputStream dest,
199 int bufferSize)
200 throws CopyStreamException
201 {
202 return copyStream(source, dest, bufferSize,
203 CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
204 }
205
206
207 /***
208 * Same as <code> copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code>
209 ***/
210 public static final long copyStream(InputStream source, OutputStream dest)
211 throws CopyStreamException
212 {
213 return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
214 }
215
216
217 /***
218 * Copies the contents of a Reader to a Writer using a
219 * copy buffer of a given size and notifies the provided
220 * CopyStreamListener of the progress of the copy operation by calling
221 * its bytesTransferred(long, int) method after each write to the
222 * destination. If you wish to notify more than one listener you should
223 * use a CopyStreamAdapter as the listener and register the additional
224 * listeners with the CopyStreamAdapter.
225 * <p>
226 * The contents of the Reader are
227 * read until its end is reached, but neither the source nor the
228 * destination are closed. You must do this yourself outside of the
229 * method call. The number of characters read/written is returned.
230 * <p>
231 * @param source The source Reader.
232 * @param dest The destination writer.
233 * @param bufferSize The number of characters to buffer during the copy.
234 * @param streamSize The number of characters in the stream being copied.
235 * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
236 * @param listener The CopyStreamListener to notify of progress. If
237 * this parameter is null, notification is not attempted.
238 * @return The number of characters read/written in the copy operation.
239 * @exception CopyStreamException If an error occurs while reading from the
240 * source or writing to the destination. The CopyStreamException
241 * will contain the number of bytes confirmed to have been
242 * transferred before an
243 * IOException occurred, and it will also contain the IOException
244 * that caused the error. These values can be retrieved with
245 * the CopyStreamException getTotalBytesTransferred() and
246 * getIOException() methods.
247 ***/
248 public static final long copyReader(Reader source, Writer dest,
249 int bufferSize, long streamSize,
250 CopyStreamListener listener)
251 throws CopyStreamException
252 {
253 int chars;
254 long total;
255 char[] buffer;
256
257 buffer = new char[bufferSize];
258 total = 0;
259
260 try
261 {
262 while ((chars = source.read(buffer)) != -1)
263 {
264 // Technically, some read(char[]) methods may return 0 and we cannot
265 // accept that as an indication of EOF.
266 if (chars == 0)
267 {
268 chars = source.read();
269 if (chars < 0)
270 break;
271 dest.write(chars);
272 dest.flush();
273 ++total;
274 if (listener != null)
275 listener.bytesTransferred(total, chars, streamSize);
276 continue;
277 }
278
279 dest.write(buffer, 0, chars);
280 dest.flush();
281 total += chars;
282 if (listener != null)
283 listener.bytesTransferred(total, chars, streamSize);
284 }
285 }
286 catch (IOException e)
287 {
288 throw new CopyStreamException("IOException caught while copying.",
289 total, e);
290 }
291
292 return total;
293 }
294
295
296 /***
297 * Copies the contents of a Reader to a Writer using a
298 * copy buffer of a given size. The contents of the Reader are
299 * read until its end is reached, but neither the source nor the
300 * destination are closed. You must do this yourself outside of the
301 * method call. The number of characters read/written is returned.
302 * <p>
303 * @param source The source Reader.
304 * @param dest The destination writer.
305 * @param bufferSize The number of characters to buffer during the copy.
306 * @return The number of characters read/written in the copy operation.
307 * @exception CopyStreamException If an error occurs while reading from the
308 * source or writing to the destination. The CopyStreamException
309 * will contain the number of bytes confirmed to have been
310 * transferred before an
311 * IOException occurred, and it will also contain the IOException
312 * that caused the error. These values can be retrieved with
313 * the CopyStreamException getTotalBytesTransferred() and
314 * getIOException() methods.
315 ***/
316 public static final long copyReader(Reader source, Writer dest,
317 int bufferSize)
318 throws CopyStreamException
319 {
320 return copyReader(source, dest, bufferSize,
321 CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
322 }
323
324
325 /***
326 * Same as <code> copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code>
327 ***/
328 public static final long copyReader(Reader source, Writer dest)
329 throws CopyStreamException
330 {
331 return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
332 }
333
334 }