KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > io > FileUtil


1 /*
2
3  ============================================================================
4                    The Apache Software License, Version 1.1
5  ============================================================================
6  
7  Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  
9  Redistribution and use in source and binary forms, with or without modifica-
10  tion, are permitted provided that the following conditions are met:
11  
12  1. Redistributions of source code must retain the above copyright notice,
13     this list of conditions and the following disclaimer.
14  
15  2. Redistributions in binary form must reproduce the above copyright notice,
16     this list of conditions and the following disclaimer in the documentation
17     and/or other materials provided with the distribution.
18  
19  3. The end-user documentation included with the redistribution, if any, must
20     include the following acknowledgment: "This product includes software
21     developed by the Apache Software Foundation (http://www.apache.org/)."
22     Alternately, this acknowledgment may appear in the software itself, if
23     and wherever such third-party acknowledgments normally appear.
24  
25  4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
26     must not be used to endorse or promote products derived from this software
27     without prior written permission. For written permission, please contact
28     apache@apache.org.
29  
30  5. Products derived from this software may not be called "Apache", nor may
31     "Apache" appear in their name, without prior written permission of the
32     Apache Software Foundation.
33  
34  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45  This software consists of voluntary contributions made by many individuals
46  on behalf of the Apache Software Foundation. For more information on the
47  Apache Software Foundation, please see <http://www.apache.org/>.
48  
49 */

50 package org.apache.avalon.excalibur.io;
51
52 import java.io.File JavaDoc;
53 import java.io.FileInputStream JavaDoc;
54 import java.io.FileOutputStream JavaDoc;
55 import java.io.IOException JavaDoc;
56 import java.io.InputStream JavaDoc;
57 import java.net.URL JavaDoc;
58
59 /**
60  * This class provides basic facilities for manipulating files and file paths.
61  *
62  * <h3>Path-related methods</h3>
63  *
64  * <p>Methods exist to retrieve the components of a typical file path. For example
65  * <code>/www/hosted/mysite/index.html</code>, can be broken into:
66  * <ul>
67  * <li><code>/www/hosted/mysite/</code> -- retrievable through {@link #getPath}</li>
68  * <li><code>index.html</code> -- retrievable through {@link #removePath}</li>
69  * <li><code>/www/hosted/mysite/index</code> -- retrievable through {@link #removeExtension}</li>
70  * <li><code>html</code> -- retrievable through {@link #getExtension}</li>
71  * </ul>
72  * There are also methods to {@link #catPath concatenate two paths}, {@link #resolveFile resolve a
73  * path relative to a File} and {@link #normalize} a path.
74  * </p>
75  *
76  * <h3>File-related methods</h3>
77  * <p>
78  * There are methods to create a {@link #toFile File from a URL}, copy a
79  * {@link #copyFileToDirectory File to a directory},
80  * copy a {@link #copyFile File to another File},
81  * copy a {@link #copyURLToFile URL's contents to a File},
82  * as well as methods to {@link #deleteDirectory(File) delete} and {@link #cleanDirectory(File)
83  * clean} a directory.
84  * </p>
85  *
86  * @author <a HREF="mailto:peter at apache.org">Peter Donald</a>
87  * @author <a HREF="mailto:jefft@apache.org">Jeff Turner</a>
88  * @author <a HREF="mailto:nl@novadeck.com">Nicolas Leclerc</a>
89  * @version CVS $Revision: 1.5 $ $Date: 2003/03/29 18:53:24 $
90  * @since 4.0
91  */

92 public final class FileUtil
93 {
94     /**
95      * Private constructor to prevent instantiation.
96      *
97      */

98     private FileUtil()
99     {
100     }
101
102     /**
103      * Compare the contents of two files to determine if they are equal or not.
104      *
105      * @param file1 the first file
106      * @param file2 the second file
107      * @return true if the content of the files are equal or they both don't exist, false otherwise
108      */

109     public static boolean contentEquals( final File JavaDoc file1, final File JavaDoc file2 )
110         throws IOException JavaDoc
111     {
112         final boolean file1Exists = file1.exists();
113         if( file1Exists != file2.exists() )
114         {
115             return false;
116         }
117
118         if( !file1Exists )
119         {
120             // two not existing files are equal
121
return true;
122         }
123
124         if( file1.isDirectory() || file2.isDirectory() )
125         {
126             // don't want to compare directory contents
127
return false;
128         }
129
130         InputStream JavaDoc input1 = null;
131         InputStream JavaDoc input2 = null;
132         try
133         {
134             input1 = new FileInputStream JavaDoc( file1 );
135             input2 = new FileInputStream JavaDoc( file2 );
136             return IOUtil.contentEquals( input1, input2 );
137
138         }
139         finally
140         {
141             IOUtil.shutdownStream( input1 );
142             IOUtil.shutdownStream( input2 );
143         }
144     }
145
146     /**
147      * Convert from a <code>URL</code> to a <code>File</code>.
148      * @param url File URL.
149      * @return The equivalent <code>File</code> object, or <code>null</code> if the URL's protocol
150      * is not <code>file</code>
151      */

152     public static File JavaDoc toFile( final URL JavaDoc url )
153     {
154         if( url.getProtocol().equals( "file" ) == false )
155         {
156             return null;
157         }
158         else
159         {
160             final String JavaDoc filename = url.getFile().replace( '/', File.separatorChar );
161             return new File JavaDoc( filename );
162         }
163     }
164
165     /**
166      * Convert the array of Files into a list of URLs.
167      *
168      * @param files the array of files
169      * @return the array of URLs
170      * @throws IOException if an error occurs
171      */

172     public static URL JavaDoc[] toURLs( final File JavaDoc[] files )
173         throws IOException JavaDoc
174     {
175         final URL JavaDoc[] urls = new URL JavaDoc[ files.length ];
176
177         for( int i = 0; i < urls.length; i++ )
178         {
179             urls[ i ] = files[ i ].toURL();
180         }
181
182         return urls;
183     }
184
185     /**
186      * Remove extension from filename.
187      * ie
188      * <pre>
189      * foo.txt --> foo
190      * a\b\c.jpg --> a\b\c
191      * a\b\c --> a\b\c
192      * </pre>
193      *
194      * @param filename the filename
195      * @return the filename minus extension
196      * @deprecated Use removeExtension as removeExtention is mispelled
197      */

198     public static String JavaDoc removeExtention( final String JavaDoc filename )
199     {
200         return removeExtension( filename );
201     }
202
203     /**
204      * Remove extension from filename.
205      * ie
206      * <pre>
207      * foo.txt --> foo
208      * a\b\c.jpg --> a\b\c
209      * a\b\c --> a\b\c
210      * </pre>
211      *
212      * @param filename the filename
213      * @return the filename minus extension
214      */

215     public static String JavaDoc removeExtension( final String JavaDoc filename )
216     {
217         final int index = filename.lastIndexOf( '.' );
218
219         if( -1 == index )
220         {
221             return filename;
222         }
223         else
224         {
225             return filename.substring( 0, index );
226         }
227     }
228
229     /**
230      * Get extension from filename.
231      * ie
232      * <pre>
233      * foo.txt --> "txt"
234      * a\b\c.jpg --> "jpg"
235      * a\b\c --> ""
236      * </pre>
237      *
238      * @param filename the filename
239      * @return the extension of filename or "" if none
240      */

241     public static String JavaDoc getExtension( final String JavaDoc filename )
242     {
243         final int index = filename.lastIndexOf( '.' );
244
245         if( -1 == index )
246         {
247             return "";
248         }
249         else
250         {
251             return filename.substring( index + 1 );
252         }
253     }
254
255     /**
256      * Remove path from filename. Equivalent to the unix command <code>basename</code>
257      * ie.
258      * <pre>
259      * a/b/c.txt --> c.txt
260      * a.txt --> a.txt
261      * </pre>
262      *
263      * @param filepath the filepath
264      * @return the filename minus path
265      */

266     public static String JavaDoc removePath( final String JavaDoc filepath )
267     {
268         return removePath( filepath, File.separatorChar );
269     }
270
271     /**
272      * Remove path from filename.
273      * ie.
274      * <pre>
275      * a/b/c.txt --> c.txt
276      * a.txt --> a.txt
277      * </pre>
278      *
279      * @param filepath the filepath
280      * @return the filename minus path
281      */

282     public static String JavaDoc removePath( final String JavaDoc filepath, final char fileSeparatorChar )
283     {
284         final int index = filepath.lastIndexOf( fileSeparatorChar );
285
286         if( -1 == index )
287         {
288             return filepath;
289         }
290         else
291         {
292             return filepath.substring( index + 1 );
293         }
294     }
295
296     /**
297      * Get path from filename. Roughly equivalent to the unix command <code>dirname</code>.
298      * ie.
299      * <pre>
300      * a/b/c.txt --> a/b
301      * a.txt --> ""
302      * </pre>
303      *
304      * @param filepath the filepath
305      * @return the filename minus path
306      */

307     public static String JavaDoc getPath( final String JavaDoc filepath )
308     {
309         return getPath( filepath, File.separatorChar );
310     }
311
312     /**
313      * Get path from filename.
314      * ie.
315      * <pre>
316      * a/b/c.txt --> a/b
317      * a.txt --> ""
318      * </pre>
319      *
320      * @param filepath the filepath
321      * @return the filename minus path
322      */

323     public static String JavaDoc getPath( final String JavaDoc filepath, final char fileSeparatorChar )
324     {
325         final int index = filepath.lastIndexOf( fileSeparatorChar );
326         if( -1 == index )
327         {
328             return "";
329         }
330         else
331         {
332             return filepath.substring( 0, index );
333         }
334     }
335
336     /**
337      * Copy file from source to destination. If <code>destinationDirectory</code> does not exist, it
338      * (and any parent directories) will be created. If a file <code>source</code> in
339      * <code>destinationDirectory</code> exists, it will be overwritten.
340      *
341      * @param source An existing <code>File</code> to copy.
342      * @param destinationDirectory A directory to copy <code>source</code> into.
343      *
344      * @throws FileNotFoundException if <code>source</code> isn't a normal file.
345      * @throws IllegalArgumentException if <code>destinationDirectory</code> isn't a directory.
346      * @throws IOException if <code>source</code> does not exist, the file in
347      * <code>destinationDirectory</code> cannot be written to, or an IO error occurs during copying.
348      */

349     public static void copyFileToDirectory( final String JavaDoc source,
350                                             final String JavaDoc destinationDirectory )
351         throws IOException JavaDoc
352     {
353         copyFileToDirectory( new File JavaDoc( source ),
354                              new File JavaDoc( destinationDirectory ) );
355     }
356
357     /**
358      * Copy file from source to destination. If <code>destinationDirectory</code> does not exist, it
359      * (and any parent directories) will be created. If a file <code>source</code> in
360      * <code>destinationDirectory</code> exists, it will be overwritten.
361      *
362      * @param source An existing <code>File</code> to copy.
363      * @param destinationDirectory A directory to copy <code>source</code> into.
364      *
365      * @throws FileNotFoundException if <code>source</code> isn't a normal file.
366      * @throws IllegalArgumentException if <code>destinationDirectory</code> isn't a directory.
367      * @throws IOException if <code>source</code> does not exist, the file in
368      * <code>destinationDirectory</code> cannot be written to, or an IO error occurs during copying.
369      */

370     public static void copyFileToDirectory( final File JavaDoc source,
371                                             final File JavaDoc destinationDirectory )
372         throws IOException JavaDoc
373     {
374         if( destinationDirectory.exists() && !destinationDirectory.isDirectory() )
375         {
376             throw new IllegalArgumentException JavaDoc( "Destination is not a directory" );
377         }
378
379         copyFile( source, new File JavaDoc( destinationDirectory, source.getName() ) );
380     }
381
382     /**
383      * Copy file from source to destination. The directories up to <code>destination</code> will be
384      * created if they don't already exist. <code>destination</code> will be overwritten if it
385      * already exists.
386      *
387      * @param source An existing non-directory <code>File</code> to copy bytes from.
388      * @param destination A non-directory <code>File</code> to write bytes to (possibly
389      * overwriting).
390      *
391      * @throws IOException if <code>source</code> does not exist, <code>destination</code> cannot be
392      * written to, or an IO error occurs during copying.
393      *
394      * @throws FileNotFoundException if <code>destination</code> is a directory
395      * (use {@link #copyFileToDirectory}).
396      */

397     public static void copyFile( final File JavaDoc source, final File JavaDoc destination )
398         throws IOException JavaDoc
399     {
400         //check source exists
401
if( !source.exists() )
402         {
403             final String JavaDoc message = "File " + source + " does not exist";
404             throw new IOException JavaDoc( message );
405         }
406
407         //does destinations directory exist ?
408
if( destination.getParentFile() != null &&
409             !destination.getParentFile().exists() )
410         {
411             destination.getParentFile().mkdirs();
412         }
413
414         //make sure we can write to destination
415
if( destination.exists() && !destination.canWrite() )
416         {
417             final String JavaDoc message = "Unable to open file " +
418                 destination + " for writing.";
419             throw new IOException JavaDoc( message );
420         }
421
422         final FileInputStream JavaDoc input = new FileInputStream JavaDoc( source );
423         final FileOutputStream JavaDoc output = new FileOutputStream JavaDoc( destination );
424         IOUtil.copy( input, output );
425         IOUtil.shutdownStream( input );
426         IOUtil.shutdownStream( output );
427
428         if( source.length() != destination.length() )
429         {
430             final String JavaDoc message = "Failed to copy full contents from " + source +
431                 " to " + destination;
432             throw new IOException JavaDoc( message );
433         }
434     }
435
436     /**
437      * Copies bytes from the URL <code>source</code> to a file <code>destination</code>.
438      * The directories up to <code>destination</code> will be created if they don't already exist.
439      * <code>destination</code> will be overwritten if it already exists.
440      *
441      * @param source A <code>URL</code> to copy bytes from.
442      * @param destination A non-directory <code>File</code> to write bytes to (possibly
443      * overwriting).
444      *
445      * @throws IOException if
446      * <ul>
447      * <li><code>source</code> URL cannot be opened</li>
448      * <li><code>destination</code> cannot be written to</li>
449      * <li>an IO error occurs during copying</li>
450      * </ul>
451      */

452     public static void copyURLToFile( final URL JavaDoc source, final File JavaDoc destination )
453         throws IOException JavaDoc
454     {
455         //does destination directory exist ?
456
if( destination.getParentFile() != null &&
457             !destination.getParentFile().exists() )
458         {
459             destination.getParentFile().mkdirs();
460         }
461
462         //make sure we can write to destination
463
if( destination.exists() && !destination.canWrite() )
464         {
465             final String JavaDoc message = "Unable to open file " +
466                 destination + " for writing.";
467             throw new IOException JavaDoc( message );
468         }
469
470         final InputStream JavaDoc input = source.openStream();
471         final FileOutputStream JavaDoc output = new FileOutputStream JavaDoc( destination );
472         IOUtil.copy( input, output );
473         IOUtil.shutdownStream( input );
474         IOUtil.shutdownStream( output );
475     }
476
477     /**
478      * Normalize a path. That means:
479      * <ul>
480      * <li>changes to unix style if under windows</li>
481      * <li>eliminates "/../" and "/./"</li>
482      * <li>if path is absolute (starts with '/') and there are
483      * too many occurences of "../" (would then have some kind
484      * of 'negative' path) returns null.</li>
485      * <li>If path is relative, the exceeding ../ are kept at
486      * the begining of the path.</li>
487      * </ul>
488      * <br><br>
489      *
490      * <b>Note:</b> note that this method has been tested with unix and windows only.
491      *
492      * <p>Eg:</p>
493      * <pre>
494      * /foo// --> /foo/
495      * /foo/./ --> /foo/
496      * /foo/../bar --> /bar
497      * /foo/../bar/ --> /bar/
498      * /foo/../bar/../baz --> /baz
499      * //foo//./bar --> /foo/bar
500      * /../ --> null
501      * </pre>
502      *
503      * @param path the path to be normalized.
504      * @return the normalized path or null.
505      * @throws NullPointerException if path is null.
506      */

507     public static final String JavaDoc normalize( String JavaDoc path )
508     {
509         if( path.length() < 2 )
510         {
511             return path;
512         }
513
514         StringBuffer JavaDoc buff = new StringBuffer JavaDoc( path );
515
516         int length = path.length();
517
518         // this whole prefix thing is for windows compatibility only.
519
String JavaDoc prefix = null;
520
521         if( length > 2 && buff.charAt( 1 ) == ':' )
522         {
523             prefix = path.substring( 0, 2 );
524             buff.delete( 0, 2 );
525             path = path.substring( 2 );
526             length -= 2;
527         }
528
529         boolean startsWithSlash = length > 0 && ( buff.charAt( 0 ) == '/' || buff.charAt( 0 ) == '\\' );
530
531         boolean expStart = true;
532         int ptCount = 0;
533         int lastSlash = length + 1;
534         int upLevel = 0;
535
536         for( int i = length - 1; i >= 0; i-- )
537             switch( path.charAt( i ) )
538             {
539                 case '\\':
540                     buff.setCharAt( i, '/' );
541                 case '/':
542                     if( lastSlash == i + 1 )
543                     {
544                         buff.deleteCharAt( i );
545                     }
546
547                     switch( ptCount )
548                     {
549                         case 1:
550                             buff.delete( i, lastSlash );
551                             break;
552
553                         case 2:
554                             upLevel++;
555                             break;
556
557                         default:
558                             if( upLevel > 0 && lastSlash != i + 1 )
559                             {
560                                 buff.delete( i, lastSlash + 3 );
561                                 upLevel--;
562                             }
563                             break;
564                     }
565
566                     ptCount = 0;
567                     expStart = true;
568                     lastSlash = i;
569                     break;
570
571                 case '.':
572                     if( expStart )
573                     {
574                         ptCount++;
575                     }
576                     break;
577
578                 default:
579                     ptCount = 0;
580                     expStart = false;
581                     break;
582             }
583
584         switch( ptCount )
585         {
586             case 1:
587                 buff.delete( 0, lastSlash );
588                 break;
589
590             case 2:
591                 break;
592
593             default:
594                 if( upLevel > 0 )
595                 {
596                     if( startsWithSlash )
597                     {
598                         return null;
599                     }
600                     else
601                     {
602                         upLevel = 1;
603                     }
604                 }
605
606                 while( upLevel > 0 )
607                 {
608                     buff.delete( 0, lastSlash + 3 );
609                     upLevel--;
610                 }
611                 break;
612         }
613
614         length = buff.length();
615         boolean isLengthNull = length == 0;
616         char firstChar = isLengthNull?(char)0:buff.charAt( 0 );
617
618         if( !startsWithSlash && !isLengthNull && firstChar == '/' )
619         {
620             buff.deleteCharAt( 0 );
621         }
622         else if( startsWithSlash &&
623             ( isLengthNull || ( !isLengthNull && firstChar != '/' ) ) )
624         {
625             buff.insert( 0, '/' );
626         }
627
628         if( prefix != null )
629         {
630             buff.insert( 0, prefix );
631         }
632
633         return buff.toString();
634     }
635
636     /**
637      * Will concatenate 2 paths. Paths with <code>..</code> will be
638      * properly handled.
639      * <p>Eg.,<br />
640      * <code>/a/b/c</code> + <code>d</code> = <code>/a/b/d</code><br />
641      * <code>/a/b/c</code> + <code>../d</code> = <code>/a/d</code><br />
642      * </p>
643      *
644      * <p>Note: this method handles java/unix style path only (separator is '/').
645      * <ul>
646      * <li>it handles absolute and relative path.</li>
647      * <li>returned path is normalized (as with method <code>normalize<code>).</li>
648      * </ul>
649      *
650      * @return The concatenated paths, or null if error occurs
651      *
652      * @see #normalize
653      * @throws NullPointerException if any parameter is null.
654      */

655     public static String JavaDoc catPath( String JavaDoc lookupPath,
656                                   final String JavaDoc path )
657     {
658         if( path == null )
659         {
660             throw new NullPointerException JavaDoc( "path" );
661         }
662
663         if( !lookupPath.endsWith( "/" ) )
664         {
665             final int index = lookupPath.lastIndexOf( "/" );
666             if( index < 0 )
667             {
668                 lookupPath = "";
669             }
670             else
671             {
672                 lookupPath = lookupPath.substring( 0, index + 1 );
673             }
674         }
675
676         return normalize( lookupPath + path );
677     }
678
679     /**
680      * Resolve a file <code>filename</code> to it's canonical form. If <code>filename</code> is
681      * relative (doesn't start with <code>/</code>), it will be resolved relative to
682      * <code>baseFile</code>, otherwise it is treated as a normal root-relative path.
683      *
684      * @param baseFile Where to resolve <code>filename</code> from, if <code>filename</code> is
685      * relative.
686      * @param filename Absolute or relative file path to resolve.
687      * @return The canonical <code>File</code> of <code>filename</code>.
688      */

689     public static File JavaDoc resolveFile( final File JavaDoc baseFile, String JavaDoc filename )
690     {
691         String JavaDoc filenm = filename;
692         if( '/' != File.separatorChar )
693         {
694             filenm = filename.replace( '/', File.separatorChar );
695         }
696
697         if( '\\' != File.separatorChar )
698         {
699             filenm = filename.replace( '\\', File.separatorChar );
700         }
701
702         // deal with absolute files
703
if( filenm.startsWith( File.separator ) )
704         {
705             File JavaDoc file = new File JavaDoc( filenm );
706
707             try
708             {
709                 file = file.getCanonicalFile();
710             }
711             catch( final IOException JavaDoc ioe )
712             {
713             }
714
715             return file;
716         }
717
718         final char[] chars = filename.toCharArray();
719         final StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
720
721         //remove duplicate file separators in succession - except
722
//on win32 at start of filename as UNC filenames can
723
//be \\AComputer\AShare\myfile.txt
724
int start = 0;
725         if( '\\' == File.separatorChar )
726         {
727             sb.append( filenm.charAt( 0 ) );
728             start++;
729         }
730
731         for( int i = start; i < chars.length; i++ )
732         {
733             final boolean doubleSeparator =
734                 File.separatorChar == chars[ i ] && File.separatorChar == chars[ i - 1 ];
735
736             if( !doubleSeparator )
737             {
738                 sb.append( chars[ i ] );
739             }
740         }
741
742         filenm = sb.toString();
743
744         //must be relative
745
File JavaDoc file = ( new File JavaDoc( baseFile, filenm ) ).getAbsoluteFile();
746
747         try
748         {
749             file = file.getCanonicalFile();
750         }
751         catch( final IOException JavaDoc ioe )
752         {
753         }
754
755         return file;
756     }
757
758     /**
759      * Delete a file. If file is directory delete it and all sub-directories.
760      */

761     public static void forceDelete( final String JavaDoc file )
762         throws IOException JavaDoc
763     {
764         forceDelete( new File JavaDoc( file ) );
765     }
766
767     /**
768      * Delete a file. If file is directory delete it and all sub-directories.
769      */

770     public static void forceDelete( final File JavaDoc file )
771         throws IOException JavaDoc
772     {
773         if( file.isDirectory() )
774         {
775             deleteDirectory( file );
776         }
777         else
778         {
779             if( !file.delete() )
780             {
781                 final String JavaDoc message =
782                     "File " + file + " unable to be deleted.";
783                 throw new IOException JavaDoc( message );
784             }
785         }
786     }
787
788     /**
789      * Schedule a file to be deleted when JVM exits.
790      * If file is directory delete it and all sub-directories.
791      */

792     public static void forceDeleteOnExit( final File JavaDoc file )
793         throws IOException JavaDoc
794     {
795         if( file.isDirectory() )
796         {
797             deleteDirectoryOnExit( file );
798         }
799         else
800         {
801             file.deleteOnExit();
802         }
803     }
804
805     /**
806      * Recursively schedule directory for deletion on JVM exit.
807      */

808     private static void deleteDirectoryOnExit( final File JavaDoc directory )
809         throws IOException JavaDoc
810     {
811         if( !directory.exists() )
812         {
813             return;
814         }
815
816         cleanDirectoryOnExit( directory );
817         directory.deleteOnExit();
818     }
819
820     /**
821      * Clean a directory without deleting it.
822      */

823     private static void cleanDirectoryOnExit( final File JavaDoc directory )
824         throws IOException JavaDoc
825     {
826         if( !directory.exists() )
827         {
828             final String JavaDoc message = directory + " does not exist";
829             throw new IllegalArgumentException JavaDoc( message );
830         }
831
832         if( !directory.isDirectory() )
833         {
834             final String JavaDoc message = directory + " is not a directory";
835             throw new IllegalArgumentException JavaDoc( message );
836         }
837
838         IOException JavaDoc exception = null;
839
840         final File JavaDoc[] files = directory.listFiles();
841         for( int i = 0; i < files.length; i++ )
842         {
843             final File JavaDoc file = files[ i ];
844             try
845             {
846                 FileUtil.forceDeleteOnExit( file );
847             }
848             catch( final IOException JavaDoc ioe )
849             {
850                 exception = ioe;
851             }
852         }
853
854         if( null != exception )
855         {
856             throw exception;
857         }
858     }
859
860     /**
861      * Make a directory. If there already exists a file with specified name or
862      * the directory is unable to be created then an exception is thrown.
863      */

864     public static void forceMkdir( final File JavaDoc file )
865         throws IOException JavaDoc
866     {
867         if( file.exists() )
868         {
869             if( file.isFile() )
870             {
871                 final String JavaDoc message = "File " + file + " exists and is " +
872                     "not a directory. Unable to create directory.";
873                 throw new IOException JavaDoc( message );
874             }
875         }
876         else
877         {
878             if( false == file.mkdirs() )
879             {
880                 final String JavaDoc message = "Unable to create directory " + file;
881                 throw new IOException JavaDoc( message );
882             }
883         }
884     }
885
886     /**
887      * Recursively delete a directory.
888      */

889     public static void deleteDirectory( final String JavaDoc directory )
890         throws IOException JavaDoc
891     {
892         deleteDirectory( new File JavaDoc( directory ) );
893     }
894
895     /**
896      * Recursively delete a directory.
897      */

898     public static void deleteDirectory( final File JavaDoc directory )
899         throws IOException JavaDoc
900     {
901         if( !directory.exists() )
902         {
903             return;
904         }
905
906         cleanDirectory( directory );
907         if( !directory.delete() )
908         {
909             final String JavaDoc message =
910                 "Directory " + directory + " unable to be deleted.";
911             throw new IOException JavaDoc( message );
912         }
913     }
914
915     /**
916      * Clean a directory without deleting it.
917      */

918     public static void cleanDirectory( final String JavaDoc directory )
919         throws IOException JavaDoc
920     {
921         cleanDirectory( new File JavaDoc( directory ) );
922     }
923
924     /**
925      * Clean a directory without deleting it.
926      */

927     public static void cleanDirectory( final File JavaDoc directory )
928         throws IOException JavaDoc
929     {
930         if( !directory.exists() )
931         {
932             final String JavaDoc message = directory + " does not exist";
933             throw new IllegalArgumentException JavaDoc( message );
934         }
935
936         if( !directory.isDirectory() )
937         {
938             final String JavaDoc message = directory + " is not a directory";
939             throw new IllegalArgumentException JavaDoc( message );
940         }
941
942         IOException JavaDoc exception = null;
943
944         final File JavaDoc[] files = directory.listFiles();
945         for( int i = 0; i < files.length; i++ )
946         {
947             final File JavaDoc file = files[ i ];
948             try
949             {
950                 FileUtil.forceDelete( file );
951             }
952             catch( final IOException JavaDoc ioe )
953             {
954                 exception = ioe;
955             }
956         }
957
958         if( null != exception )
959         {
960             throw exception;
961         }
962     }
963
964     /**
965      * Recursively count size of a directory.
966      *
967      * @return size of directory in bytes.
968      */

969     public static long sizeOfDirectory( final String JavaDoc directory )
970     {
971         return sizeOfDirectory( new File JavaDoc( directory ) );
972     }
973
974     /**
975      * Recursively count size of a directory.
976      *
977      * @return size of directory in bytes.
978      */

979     public static long sizeOfDirectory( final File JavaDoc directory )
980     {
981         if( !directory.exists() )
982         {
983             final String JavaDoc message = directory + " does not exist";
984             throw new IllegalArgumentException JavaDoc( message );
985         }
986
987         if( !directory.isDirectory() )
988         {
989             final String JavaDoc message = directory + " is not a directory";
990             throw new IllegalArgumentException JavaDoc( message );
991         }
992
993         long size = 0;
994
995         final File JavaDoc[] files = directory.listFiles();
996         for( int i = 0; i < files.length; i++ )
997         {
998             final File JavaDoc file = files[ i ];
999
1000            if( file.isDirectory() )
1001            {
1002                size += sizeOfDirectory( file );
1003            }
1004            else
1005            {
1006                size += file.length();
1007            }
1008        }
1009
1010        return size;
1011    }
1012}
1013
Popular Tags