001 /*
002 * JBoss DNA (http://www.jboss.org/dna)
003 * See the COPYRIGHT.txt file distributed with this work for information
004 * regarding copyright ownership. Some portions may be licensed
005 * to Red Hat, Inc. under one or more contributor license agreements.
006 * See the AUTHORS.txt file in the distribution for a full listing of
007 * individual contributors.
008 *
009 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010 * is licensed to you under the terms of the GNU Lesser General Public License as
011 * published by the Free Software Foundation; either version 2.1 of
012 * the License, or (at your option) any later version.
013 *
014 * JBoss DNA is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017 * Lesser General Public License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this software; if not, write to the Free
021 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023 */
024 package org.jboss.dna.common.util;
025
026 import java.io.BufferedInputStream;
027 import java.io.ByteArrayOutputStream;
028 import java.io.File;
029 import java.io.FileInputStream;
030 import java.io.FileReader;
031 import java.io.IOException;
032 import java.io.InputStream;
033 import java.io.InputStreamReader;
034 import java.io.OutputStream;
035 import java.io.Reader;
036 import java.io.Writer;
037 import java.util.Arrays;
038
039 /**
040 * @author Randall Hauch
041 */
042 public class IoUtil {
043
044 /**
045 * Read and return the entire contents of the supplied {@link InputStream stream}. This method always closes the stream when
046 * finished reading.
047 *
048 * @param stream the stream to the contents; may be null
049 * @return the contents, or an empty byte array if the supplied reader is null
050 * @throws IOException if there is an error reading the content
051 */
052 public static byte[] readBytes( InputStream stream ) throws IOException {
053 if (stream == null) return new byte[] {};
054 byte[] buffer = new byte[1024];
055 ByteArrayOutputStream output = new ByteArrayOutputStream();
056 boolean error = false;
057 try {
058 int numRead = 0;
059 while ((numRead = stream.read(buffer)) > -1) {
060 output.write(buffer, 0, numRead);
061 }
062 } catch (IOException e) {
063 error = true; // this error should be thrown, even if there is an error closing stream
064 throw e;
065 } catch (RuntimeException e) {
066 error = true; // this error should be thrown, even if there is an error closing stream
067 throw e;
068 } finally {
069 try {
070 stream.close();
071 } catch (IOException e) {
072 if (!error) throw e;
073 }
074 }
075 output.flush();
076 return output.toByteArray();
077 }
078
079 /**
080 * Read and return the entire contents of the supplied {@link File file}.
081 *
082 * @param file the file containing the contents; may be null
083 * @return the contents, or an empty byte array if the supplied file is null
084 * @throws IOException if there is an error reading the content
085 */
086 public static byte[] readBytes( File file ) throws IOException {
087 if (file == null) return new byte[] {};
088 InputStream stream = new BufferedInputStream(new FileInputStream(file));
089 boolean error = false;
090 try {
091 return readBytes(stream);
092 } catch (IOException e) {
093 error = true; // this error should be thrown, even if there is an error closing stream
094 throw e;
095 } catch (RuntimeException e) {
096 error = true; // this error should be thrown, even if there is an error closing stream
097 throw e;
098 } finally {
099 try {
100 stream.close();
101 } catch (IOException e) {
102 if (!error) throw e;
103 }
104 }
105 }
106
107 /**
108 * Read and return the entire contents of the supplied {@link Reader}. This method always closes the reader when finished
109 * reading.
110 *
111 * @param reader the reader of the contents; may be null
112 * @return the contents, or an empty string if the supplied reader is null
113 * @throws IOException if there is an error reading the content
114 */
115 public static String read( Reader reader ) throws IOException {
116 if (reader == null) return "";
117 StringBuilder sb = new StringBuilder();
118 boolean error = false;
119 try {
120 int numRead = 0;
121 char[] buffer = new char[1024];
122 while ((numRead = reader.read(buffer)) > -1) {
123 sb.append(buffer, 0, numRead);
124 }
125 } catch (IOException e) {
126 error = true; // this error should be thrown, even if there is an error closing reader
127 throw e;
128 } catch (RuntimeException e) {
129 error = true; // this error should be thrown, even if there is an error closing reader
130 throw e;
131 } finally {
132 try {
133 reader.close();
134 } catch (IOException e) {
135 if (!error) throw e;
136 }
137 }
138 return sb.toString();
139 }
140
141 /**
142 * Read and return the entire contents of the supplied {@link InputStream}. This method always closes the stream when finished
143 * reading.
144 *
145 * @param stream the streamed contents; may be null
146 * @return the contents, or an empty string if the supplied stream is null
147 * @throws IOException if there is an error reading the content
148 */
149 public static String read( InputStream stream ) throws IOException {
150 return stream == null ? "" : read(new InputStreamReader(stream));
151 }
152
153 /**
154 * Read and return the entire contents of the supplied {@link File}.
155 *
156 * @param file the file containing the information to be read; may be null
157 * @return the contents, or an empty string if the supplied reader is null
158 * @throws IOException if there is an error reading the content
159 */
160 public static String read( File file ) throws IOException {
161 if (file == null) return "";
162 StringBuilder sb = new StringBuilder();
163 boolean error = false;
164 Reader reader = new FileReader(file);
165 try {
166 int numRead = 0;
167 char[] buffer = new char[1024];
168 while ((numRead = reader.read(buffer)) > -1) {
169 sb.append(buffer, 0, numRead);
170 }
171 } catch (IOException e) {
172 error = true; // this error should be thrown, even if there is an error closing reader
173 throw e;
174 } catch (RuntimeException e) {
175 error = true; // this error should be thrown, even if there is an error closing reader
176 throw e;
177 } finally {
178 try {
179 reader.close();
180 } catch (IOException e) {
181 if (!error) throw e;
182 }
183 }
184 return sb.toString();
185 }
186
187 /**
188 * Write the entire contents of the supplied string to the given stream. This method always flushes and closes the stream when
189 * finished.
190 *
191 * @param content the content to write to the stream; may be null
192 * @param stream the stream to which the content is to be written
193 * @throws IOException
194 * @throws IllegalArgumentException if the stream is null
195 */
196 public static void write( String content,
197 OutputStream stream ) throws IOException {
198 CheckArg.isNotNull(stream, "destination stream");
199 boolean error = false;
200 try {
201 if (content != null) {
202 byte[] bytes = content.getBytes();
203 stream.write(bytes, 0, bytes.length);
204 }
205 } catch (IOException e) {
206 error = true; // this error should be thrown, even if there is an error flushing/closing stream
207 throw e;
208 } catch (RuntimeException e) {
209 error = true; // this error should be thrown, even if there is an error flushing/closing stream
210 throw e;
211 } finally {
212 try {
213 stream.flush();
214 } catch (IOException e) {
215 if (!error) throw e;
216 } finally {
217 try {
218 stream.close();
219 } catch (IOException e) {
220 if (!error) throw e;
221 }
222 }
223 }
224 }
225
226 /**
227 * Write the entire contents of the supplied string to the given writer. This method always flushes and closes the writer when
228 * finished.
229 *
230 * @param content the content to write to the writer; may be null
231 * @param writer the writer to which the content is to be written
232 * @throws IOException
233 * @throws IllegalArgumentException if the writer is null
234 */
235 public static void write( String content,
236 Writer writer ) throws IOException {
237 CheckArg.isNotNull(writer, "destination writer");
238 boolean error = false;
239 try {
240 if (content != null) {
241 writer.write(content);
242 }
243 } catch (IOException e) {
244 error = true; // this error should be thrown, even if there is an error flushing/closing writer
245 throw e;
246 } catch (RuntimeException e) {
247 error = true; // this error should be thrown, even if there is an error flushing/closing writer
248 throw e;
249 } finally {
250 try {
251 writer.flush();
252 } catch (IOException e) {
253 if (!error) throw e;
254 } finally {
255 try {
256 writer.close();
257 } catch (IOException e) {
258 if (!error) throw e;
259 }
260 }
261 }
262 }
263
264 /**
265 * Write the entire contents of the supplied string to the given stream. This method always flushes and closes the stream when
266 * finished.
267 *
268 * @param input the content to write to the stream; may be null
269 * @param stream the stream to which the content is to be written
270 * @throws IOException
271 * @throws IllegalArgumentException if the stream is null
272 */
273 public static void write( InputStream input,
274 OutputStream stream ) throws IOException {
275 CheckArg.isNotNull(stream, "destination stream");
276 boolean error = false;
277 try {
278 if (input != null) {
279 byte[] buffer = new byte[1024];
280 try {
281 int numRead = 0;
282 while ((numRead = input.read(buffer)) > -1) {
283 stream.write(buffer, 0, numRead);
284 }
285 } finally {
286 input.close();
287 }
288 }
289 } catch (IOException e) {
290 error = true; // this error should be thrown, even if there is an error flushing/closing stream
291 throw e;
292 } catch (RuntimeException e) {
293 error = true; // this error should be thrown, even if there is an error flushing/closing stream
294 throw e;
295 } finally {
296 try {
297 stream.flush();
298 } catch (IOException e) {
299 if (!error) throw e;
300 } finally {
301 try {
302 stream.close();
303 } catch (IOException e) {
304 if (!error) throw e;
305 }
306 }
307 }
308 }
309
310 /**
311 * Write the entire contents of the supplied string to the given writer. This method always flushes and closes the writer when
312 * finished.
313 *
314 * @param input the content to write to the writer; may be null
315 * @param writer the writer to which the content is to be written
316 * @throws IOException
317 * @throws IllegalArgumentException if the writer is null
318 */
319 public static void write( Reader input,
320 Writer writer ) throws IOException {
321 CheckArg.isNotNull(writer, "destination writer");
322 boolean error = false;
323 try {
324 if (input != null) {
325 char[] buffer = new char[1024];
326 try {
327 int numRead = 0;
328 while ((numRead = input.read(buffer)) > -1) {
329 writer.write(buffer, 0, numRead);
330 }
331 } finally {
332 input.close();
333 }
334 }
335 } catch (IOException e) {
336 error = true; // this error should be thrown, even if there is an error flushing/closing writer
337 throw e;
338 } catch (RuntimeException e) {
339 error = true; // this error should be thrown, even if there is an error flushing/closing writer
340 throw e;
341 } finally {
342 try {
343 writer.flush();
344 } catch (IOException e) {
345 if (!error) throw e;
346 } finally {
347 try {
348 writer.close();
349 } catch (IOException e) {
350 if (!error) throw e;
351 }
352 }
353 }
354 }
355
356 /**
357 * Write the entire contents of the supplied string to the given stream. This method always flushes and closes the stream when
358 * finished.
359 *
360 * @param input1 the first stream
361 * @param input2 the second stream
362 * @return true if the streams contain the same content, or false otherwise
363 * @throws IOException
364 * @throws IllegalArgumentException if the stream is null
365 */
366 public static boolean isSame( InputStream input1,
367 InputStream input2 ) throws IOException {
368 CheckArg.isNotNull(input1, "input1");
369 CheckArg.isNotNull(input2, "input2");
370 boolean error = false;
371 try {
372 byte[] buffer1 = new byte[1024];
373 byte[] buffer2 = new byte[1024];
374 try {
375 int numRead1 = 0;
376 int numRead2 = 0;
377 while (true) {
378 numRead1 = input1.read(buffer1);
379 numRead2 = input2.read(buffer2);
380 if (numRead1 > -1) {
381 if (numRead2 != numRead1) return false;
382 // Otherwise same number of bytes read
383 if (!Arrays.equals(buffer1, buffer2)) return false;
384 // Otherwise same bytes read, so continue ...
385 } else {
386 // Nothing more in stream 1 ...
387 return numRead2 < 0;
388 }
389 }
390 } finally {
391 input1.close();
392 }
393 } catch (IOException e) {
394 error = true; // this error should be thrown, even if there is an error closing stream 2
395 throw e;
396 } catch (RuntimeException e) {
397 error = true; // this error should be thrown, even if there is an error closing stream 2
398 throw e;
399 } finally {
400 try {
401 input2.close();
402 } catch (IOException e) {
403 if (!error) throw e;
404 }
405 }
406 }
407
408 private IoUtil() {
409 // Prevent construction
410 }
411 }