1 // ========================================================================
2 // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3 // ------------------------------------------------------------------------
4 // All rights reserved. This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v1.0
6 // and Apache License v2.0 which accompanies this distribution.
7 // The Eclipse Public License is available at
8 // http://www.eclipse.org/legal/epl-v10.html
9 // The Apache License v2.0 is available at
10 // http://www.opensource.org/licenses/apache2.0.php
11 // You may elect to redistribute this code under either of these licenses.
12 // ========================================================================
13
14 package org.eclipse.jetty.util;
15 import java.io.ByteArrayOutputStream;
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.io.OutputStream;
23 import java.io.PrintWriter;
24 import java.io.Reader;
25 import java.io.StringWriter;
26 import java.io.Writer;
27
28 import org.eclipse.jetty.util.log.Log;
29 import org.eclipse.jetty.util.log.Logger;
30 import org.eclipse.jetty.util.thread.QueuedThreadPool;
31
32 /* ======================================================================== */
33 /** IO Utilities.
34 * Provides stream handling utilities in
35 * singleton Threadpool implementation accessed by static members.
36 */
37 public class IO
38 {
39 private static final Logger LOG = Log.getLogger(IO.class);
40
41 /* ------------------------------------------------------------------- */
42 public final static String
43 CRLF = "\015\012";
44
45 /* ------------------------------------------------------------------- */
46 public final static byte[]
47 CRLF_BYTES = {(byte)'\015',(byte)'\012'};
48
49 /* ------------------------------------------------------------------- */
50 public static int bufferSize = 64*1024;
51
52 /* ------------------------------------------------------------------- */
53 // TODO get rid of this singleton!
54 private static class Singleton {
55 static final QueuedThreadPool __pool=new QueuedThreadPool();
56 static
57 {
58 try{__pool.start();}
59 catch(Exception e){LOG.warn(e); System.exit(1);}
60 }
61 }
62
63 /* ------------------------------------------------------------------- */
64 static class Job implements Runnable
65 {
66 InputStream in;
67 OutputStream out;
68 Reader read;
69 Writer write;
70
71 Job(InputStream in,OutputStream out)
72 {
73 this.in=in;
74 this.out=out;
75 this.read=null;
76 this.write=null;
77 }
78 Job(Reader read,Writer write)
79 {
80 this.in=null;
81 this.out=null;
82 this.read=read;
83 this.write=write;
84 }
85
86 /* ------------------------------------------------------------ */
87 /*
88 * @see java.lang.Runnable#run()
89 */
90 public void run()
91 {
92 try {
93 if (in!=null)
94 copy(in,out,-1);
95 else
96 copy(read,write,-1);
97 }
98 catch(IOException e)
99 {
100 LOG.ignore(e);
101 try{
102 if (out!=null)
103 out.close();
104 if (write!=null)
105 write.close();
106 }
107 catch(IOException e2)
108 {
109 LOG.ignore(e2);
110 }
111 }
112 }
113 }
114
115 /* ------------------------------------------------------------------- */
116 /** Copy Stream in to Stream out until EOF or exception.
117 * in own thread
118 */
119 public static void copyThread(InputStream in, OutputStream out)
120 {
121 try{
122 Job job=new Job(in,out);
123 if (!Singleton.__pool.dispatch(job))
124 job.run();
125 }
126 catch(Exception e)
127 {
128 LOG.warn(e);
129 }
130 }
131
132 /* ------------------------------------------------------------------- */
133 /** Copy Stream in to Stream out until EOF or exception.
134 */
135 public static void copy(InputStream in, OutputStream out)
136 throws IOException
137 {
138 copy(in,out,-1);
139 }
140
141 /* ------------------------------------------------------------------- */
142 /** Copy Stream in to Stream out until EOF or exception
143 * in own thread
144 */
145 public static void copyThread(Reader in, Writer out)
146 {
147 try
148 {
149 Job job=new Job(in,out);
150 if (!Singleton.__pool.dispatch(job))
151 job.run();
152 }
153 catch(Exception e)
154 {
155 LOG.warn(e);
156 }
157 }
158
159 /* ------------------------------------------------------------------- */
160 /** Copy Reader to Writer out until EOF or exception.
161 */
162 public static void copy(Reader in, Writer out)
163 throws IOException
164 {
165 copy(in,out,-1);
166 }
167
168 /* ------------------------------------------------------------------- */
169 /** Copy Stream in to Stream for byteCount bytes or until EOF or exception.
170 */
171 public static void copy(InputStream in,
172 OutputStream out,
173 long byteCount)
174 throws IOException
175 {
176 byte buffer[] = new byte[bufferSize];
177 int len=bufferSize;
178
179 if (byteCount>=0)
180 {
181 while (byteCount>0)
182 {
183 int max = byteCount<bufferSize?(int)byteCount:bufferSize;
184 len=in.read(buffer,0,max);
185
186 if (len==-1)
187 break;
188
189 byteCount -= len;
190 out.write(buffer,0,len);
191 }
192 }
193 else
194 {
195 while (true)
196 {
197 len=in.read(buffer,0,bufferSize);
198 if (len<0 )
199 break;
200 out.write(buffer,0,len);
201 }
202 }
203 }
204
205 /* ------------------------------------------------------------------- */
206 /** Copy Reader to Writer for byteCount bytes or until EOF or exception.
207 */
208 public static void copy(Reader in,
209 Writer out,
210 long byteCount)
211 throws IOException
212 {
213 char buffer[] = new char[bufferSize];
214 int len=bufferSize;
215
216 if (byteCount>=0)
217 {
218 while (byteCount>0)
219 {
220 if (byteCount<bufferSize)
221 len=in.read(buffer,0,(int)byteCount);
222 else
223 len=in.read(buffer,0,bufferSize);
224
225 if (len==-1)
226 break;
227
228 byteCount -= len;
229 out.write(buffer,0,len);
230 }
231 }
232 else if (out instanceof PrintWriter)
233 {
234 PrintWriter pout=(PrintWriter)out;
235 while (!pout.checkError())
236 {
237 len=in.read(buffer,0,bufferSize);
238 if (len==-1)
239 break;
240 out.write(buffer,0,len);
241 }
242 }
243 else
244 {
245 while (true)
246 {
247 len=in.read(buffer,0,bufferSize);
248 if (len==-1)
249 break;
250 out.write(buffer,0,len);
251 }
252 }
253 }
254
255 /* ------------------------------------------------------------ */
256 /** Copy files or directories
257 * @param from
258 * @param to
259 * @throws IOException
260 */
261 public static void copy(File from,File to) throws IOException
262 {
263 if (from.isDirectory())
264 copyDir(from,to);
265 else
266 copyFile(from,to);
267 }
268
269 /* ------------------------------------------------------------ */
270 public static void copyDir(File from,File to) throws IOException
271 {
272 if (to.exists())
273 {
274 if (!to.isDirectory())
275 throw new IllegalArgumentException(to.toString());
276 }
277 else
278 to.mkdirs();
279
280 File[] files = from.listFiles();
281 if (files!=null)
282 {
283 for (int i=0;i<files.length;i++)
284 {
285 String name = files[i].getName();
286 if (".".equals(name) || "..".equals(name))
287 continue;
288 copy(files[i],new File(to,name));
289 }
290 }
291 }
292
293 /* ------------------------------------------------------------ */
294 public static void copyFile(File from,File to) throws IOException
295 {
296 FileInputStream in=new FileInputStream(from);
297 FileOutputStream out=new FileOutputStream(to);
298 copy(in,out);
299 in.close();
300 out.close();
301 }
302
303 /* ------------------------------------------------------------ */
304 /** Read input stream to string.
305 */
306 public static String toString(InputStream in)
307 throws IOException
308 {
309 return toString(in,null);
310 }
311
312 /* ------------------------------------------------------------ */
313 /** Read input stream to string.
314 */
315 public static String toString(InputStream in,String encoding)
316 throws IOException
317 {
318 StringWriter writer=new StringWriter();
319 InputStreamReader reader = encoding==null?new InputStreamReader(in):new InputStreamReader(in,encoding);
320
321 copy(reader,writer);
322 return writer.toString();
323 }
324
325 /* ------------------------------------------------------------ */
326 /** Read input stream to string.
327 */
328 public static String toString(Reader in)
329 throws IOException
330 {
331 StringWriter writer=new StringWriter();
332 copy(in,writer);
333 return writer.toString();
334 }
335
336
337 /* ------------------------------------------------------------ */
338 /** Delete File.
339 * This delete will recursively delete directories - BE CAREFULL
340 * @param file The file to be deleted.
341 */
342 public static boolean delete(File file)
343 {
344 if (!file.exists())
345 return false;
346 if (file.isDirectory())
347 {
348 File[] files = file.listFiles();
349 for (int i=0;files!=null && i<files.length;i++)
350 delete(files[i]);
351 }
352 return file.delete();
353 }
354
355 /* ------------------------------------------------------------ */
356 /**
357 * closes an input stream, and logs exceptions
358 *
359 * @param is the input stream to close
360 */
361 public static void close(InputStream is)
362 {
363 try
364 {
365 if (is != null)
366 is.close();
367 }
368 catch (IOException e)
369 {
370 LOG.ignore(e);
371 }
372 }
373
374 /**
375 * closes a reader, and logs exceptions
376 *
377 * @param reader the reader to close
378 */
379 public static void close(Reader reader)
380 {
381 try
382 {
383 if (reader != null)
384 reader.close();
385 } catch (IOException e)
386 {
387 LOG.ignore(e);
388 }
389 }
390
391 /**
392 * closes a writer, and logs exceptions
393 *
394 * @param writer the writer to close
395 */
396 public static void close(Writer writer)
397 {
398 try
399 {
400 if (writer != null)
401 writer.close();
402 } catch (IOException e)
403 {
404 LOG.ignore(e);
405 }
406 }
407
408 /* ------------------------------------------------------------ */
409 public static byte[] readBytes(InputStream in)
410 throws IOException
411 {
412 ByteArrayOutputStream bout = new ByteArrayOutputStream();
413 copy(in,bout);
414 return bout.toByteArray();
415 }
416
417 /* ------------------------------------------------------------ */
418 /**
419 * closes an output stream, and logs exceptions
420 *
421 * @param os the output stream to close
422 */
423 public static void close(OutputStream os)
424 {
425 try
426 {
427 if (os != null)
428 os.close();
429 }
430 catch (IOException e)
431 {
432 LOG.ignore(e);
433 }
434 }
435
436 /* ------------------------------------------------------------ */
437 /**
438 * @return An outputstream to nowhere
439 */
440 public static OutputStream getNullStream()
441 {
442 return __nullStream;
443 }
444
445 /* ------------------------------------------------------------ */
446 /**
447 * @return An outputstream to nowhere
448 */
449 public static InputStream getClosedStream()
450 {
451 return __closedStream;
452 }
453
454 /* ------------------------------------------------------------ */
455 /* ------------------------------------------------------------ */
456 private static class NullOS extends OutputStream
457 {
458 @Override
459 public void close(){}
460 @Override
461 public void flush(){}
462 @Override
463 public void write(byte[]b){}
464 @Override
465 public void write(byte[]b,int i,int l){}
466 @Override
467 public void write(int b){}
468 }
469 private static NullOS __nullStream = new NullOS();
470
471
472 /* ------------------------------------------------------------ */
473 /* ------------------------------------------------------------ */
474 private static class ClosedIS extends InputStream
475 {
476 @Override
477 public int read() throws IOException
478 {
479 return -1;
480 }
481 }
482 private static ClosedIS __closedStream = new ClosedIS();
483
484 /* ------------------------------------------------------------ */
485 /**
486 * @return An writer to nowhere
487 */
488 public static Writer getNullWriter()
489 {
490 return __nullWriter;
491 }
492
493 /* ------------------------------------------------------------ */
494 /**
495 * @return An writer to nowhere
496 */
497 public static PrintWriter getNullPrintWriter()
498 {
499 return __nullPrintWriter;
500 }
501
502 /* ------------------------------------------------------------ */
503 /* ------------------------------------------------------------ */
504 private static class NullWrite extends Writer
505 {
506 @Override
507 public void close(){}
508 @Override
509 public void flush(){}
510 @Override
511 public void write(char[]b){}
512 @Override
513 public void write(char[]b,int o,int l){}
514 @Override
515 public void write(int b){}
516 @Override
517 public void write(String s){}
518 @Override
519 public void write(String s,int o,int l){}
520 }
521 private static NullWrite __nullWriter = new NullWrite();
522 private static PrintWriter __nullPrintWriter = new PrintWriter(__nullWriter);
523 }
524
525
526
527
528
529
530
531
532