001 /*
002 * Copyright 2004 Stephen J. McConnell.
003 * Copyright 2004 Niclas Hedhman
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
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.util;
020
021 import java.io.BufferedInputStream;
022 import java.io.BufferedOutputStream;
023 import java.io.InputStream;
024 import java.io.IOException;
025 import java.io.OutputStream;
026
027 import java.net.URL;
028
029 import net.dpml.transit.NullArgumentException;
030
031 import net.dpml.transit.monitor.NetworkMonitor;
032
033 /**
034 * Utility class that provides support for stream copy operations.
035 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
036 * @version 1.0.3
037 */
038 public final class StreamUtils
039 {
040 /**
041 * Disabled constructor.
042 */
043 private StreamUtils()
044 {
045 // utility class
046 }
047
048 /**
049 * Buffer size.
050 */
051 private static final int BUFFER_SIZE = 102400;
052
053 /**
054 * Copy a stream.
055 * @param src the source input stream
056 * @param dest the destination output stream
057 * @param closeStreams TRUE if the streams should be closed on completion
058 * @exception IOException if an IO error occurs
059 * @exception NullArgumentException if src or destination are null
060 */
061 public static void copyStream( InputStream src, OutputStream dest, boolean closeStreams )
062 throws IOException, NullArgumentException
063 {
064 copyStream( null, null, 0, src, dest, closeStreams );
065 }
066
067 /**
068 * Copy a stream.
069 * @param monitor optional network monitor to log updates
070 * @param source the source url
071 * @param expected the expected size in bytes
072 * @param src the source input stream
073 * @param dest the destination output stream
074 * @param closeStreams TRUE if the streams should be closed on completion
075 * @exception IOException if an IO error occurs
076 * @exception NullArgumentException if src or destination are null
077 */
078 public static void copyStream( NetworkMonitor monitor, URL source, int expected,
079 InputStream src, OutputStream dest, boolean closeStreams )
080 throws IOException, NullArgumentException
081 {
082 if( src == null )
083 {
084 throw new NullArgumentException( "src" );
085 }
086
087 if( dest == null )
088 {
089 throw new NullArgumentException( "dest" );
090 }
091
092 int length;
093 int count = 0; // cumulative total read
094 byte[] buffer = new byte[BUFFER_SIZE];
095 if( !( dest instanceof BufferedOutputStream ) )
096 {
097 dest = new BufferedOutputStream( dest );
098 }
099 if( !( src instanceof BufferedInputStream ) )
100 {
101 src = new BufferedInputStream( src );
102 }
103
104 try
105 {
106 if( null != monitor )
107 {
108 monitor.notifyUpdate( source, expected, 0 );
109 }
110 while( ( length = src.read( buffer ) ) >= 0 )
111 {
112 count = count + length;
113 dest.write( buffer, 0, length );
114 if( null != monitor )
115 {
116 monitor.notifyUpdate( source, expected, count );
117 }
118 }
119 }
120 finally
121 {
122 if( closeStreams )
123 {
124 try
125 {
126 src.close();
127 }
128 catch( Throwable e )
129 {
130 e.printStackTrace();
131 }
132
133 try
134 {
135 dest.close();
136 }
137 catch( Throwable e )
138 {
139 e.printStackTrace();
140 }
141 }
142 if( null != monitor )
143 {
144 monitor.notifyCompletion( source );
145 }
146 }
147 }
148
149 /**
150 * Compare two streams.
151 * @param in1 the first input stream
152 * @param in2 the second input stream
153 * @return the equality status
154 * @exception IOException if an IO error occurs
155 */
156 public static boolean compareStreams( InputStream in1, InputStream in2 )
157 throws IOException
158 {
159 boolean result = true;
160 do
161 {
162 int v1 = in1.read();
163 int v2 = in2.read();
164 if( v1 != v2 )
165 {
166 return false;
167 }
168 if( v1 == -1 )
169 {
170 break;
171 }
172 } while( true );
173 return result;
174 }
175 }