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.1.0 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 }