View Javadoc

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