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