KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > io > FileUtils


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
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  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.io;
17
18 import java.io.File JavaDoc;
19 import java.io.FileInputStream JavaDoc;
20 import java.io.FileNotFoundException JavaDoc;
21 import java.io.FileOutputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.FileFilter JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.Date JavaDoc;
29
30 import org.apache.commons.io.filefilter.DirectoryFileFilter;
31 import org.apache.commons.io.filefilter.FalseFileFilter;
32 import org.apache.commons.io.filefilter.FileFilterUtils;
33 import org.apache.commons.io.filefilter.IOFileFilter;
34 import org.apache.commons.io.filefilter.SuffixFileFilter;
35 import org.apache.commons.io.filefilter.TrueFileFilter;
36
37 /**
38  * This class provides basic facilities for manipulating files and file paths.
39  *
40  * <h3>Path-related methods</h3>
41  *
42  * <p>Methods exist to retrieve the components of a typical file path. For example
43  * <code>/www/hosted/mysite/index.html</code>, can be broken into:
44  * <ul>
45  * <li><code>/www/hosted/mysite/</code> -- retrievable through {@link #getPath}</li>
46  * <li><code>index.html</code> -- retrievable through {@link #removePath}</li>
47  * <li><code>/www/hosted/mysite/index</code> -- retrievable through {@link #removeExtension}</li>
48  * <li><code>html</code> -- retrievable through {@link #getExtension}</li>
49  * </ul>
50  * There are also methods to {@link #catPath concatenate two paths}, {@link #resolveFile resolve a
51  * path relative to a File} and {@link #normalize} a path.
52  * </p>
53  *
54  * <h3>File-related methods</h3>
55  * <p>
56  * There are methods to create a {@link #toFile File from a URL}, copy a
57  * {@link #copyFileToDirectory File to a directory},
58  * copy a {@link #copyFile File to another File},
59  * copy a {@link #copyURLToFile URL's contents to a File},
60  * as well as methods to {@link #deleteDirectory(File) delete} and {@link #cleanDirectory(File)
61  * clean} a directory.
62  * </p>
63  *
64  * Common {@link java.io.File} manipulation routines.
65  *
66  * <h3>Origin of code</h3>
67  * <ul>
68  * <li>commons-utils repo</li>
69  * <li>Alexandria's FileUtils.</li>
70  * <li>Avalon Excalibur's IO.</li>
71  * </ul>
72  *
73  * @author <a HREF="mailto:burton@relativity.yi.org">Kevin A. Burton</A>
74  * @author <a HREF="mailto:sanders@apache.org">Scott Sanders</a>
75  * @author <a HREF="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
76  * @author <a HREF="mailto:Christoph.Reck@dlr.de">Christoph.Reck</a>
77  * @author <a HREF="mailto:peter@apache.org">Peter Donald</a>
78  * @author <a HREF="mailto:jefft@apache.org">Jeff Turner</a>
79  * @author Matthew Hawthorne
80  * @author <a HREF="mailto:jeremias@apache.org">Jeremias Maerki</a>
81  * @version $Id: FileUtils.java,v 1.31 2004/04/24 19:46:16 jeremias Exp $
82  */

83 public class FileUtils {
84
85     /**
86      * Instances should NOT be constructed in standard programming.
87      */

88     public FileUtils() { }
89
90     /**
91      * The number of bytes in a kilobyte.
92      */

93     public static final long ONE_KB = 1024;
94
95     /**
96      * The number of bytes in a megabyte.
97      */

98     public static final long ONE_MB = ONE_KB * ONE_KB;
99
100     /**
101      * The number of bytes in a gigabyte.
102      */

103     public static final long ONE_GB = ONE_KB * ONE_MB;
104
105     /**
106      * Returns a human-readable version of the file size (original is in
107      * bytes).
108      *
109      * @param size The number of bytes.
110      * @return A human-readable display value (includes units).
111      * @todo need for I18N?
112      */

113     public static String JavaDoc byteCountToDisplaySize(long size) {
114         String JavaDoc displaySize;
115
116         if (size / ONE_GB > 0) {
117             displaySize = String.valueOf(size / ONE_GB) + " GB";
118         } else if (size / ONE_MB > 0) {
119             displaySize = String.valueOf(size / ONE_MB) + " MB";
120         } else if (size / ONE_KB > 0) {
121             displaySize = String.valueOf(size / ONE_KB) + " KB";
122         } else {
123             displaySize = String.valueOf(size) + " bytes";
124         }
125
126         return displaySize;
127     }
128
129
130     /**
131      * Implements the same behaviour as the "touch" utility on Unix. It creates
132      * a new file with size 0 or, if the file exists already, it is opened and
133      * closed without modifying it, but updating the file date and time.
134      * @param file the File to touch
135      * @throws IOException If an I/O problem occurs
136      */

137     public static void touch(File JavaDoc file) throws IOException JavaDoc {
138         OutputStream JavaDoc out = new java.io.FileOutputStream JavaDoc(file);
139         IOUtils.closeQuietly(out);
140     }
141
142
143     private static void innerListFiles(Collection JavaDoc files, File JavaDoc directory, IOFileFilter filter) {
144         File JavaDoc[] found = directory.listFiles((FileFilter JavaDoc)filter);
145         for (int i = 0; i < found.length; i++) {
146             if (found[i].isDirectory()) {
147                 innerListFiles(files, found[i], filter);
148             } else {
149                 files.add(found[i]);
150             }
151         }
152     }
153
154
155     /**
156      * Converts a Collection containing java.io.File instanced into array
157      * representation. This is to account for the difference between
158      * File.listFiles() and FileUtils.listFiles().
159      * @param files a Collection containing java.io.File instances
160      * @return an array of java.io.File
161      */

162     public static File JavaDoc[] convertFileCollectionToFileArray(Collection JavaDoc files) {
163          return (File JavaDoc[])files.toArray(new File JavaDoc[files.size()]);
164     }
165
166
167     /**
168      * <p>Finds files within a given directory (and optionally its
169      * subdirectories). All files found are filtered by an IOFileFilter.
170      * </p>
171      * <p>If your search should recurse into subdirectories you can pass in
172      * an IOFileFilter for directories. You don't need to bind a
173      * DirectoryFileFilter (via logical AND) to this filter. This method does
174      * that for you.
175      * </p>
176      * <p>An example: If you want to search through all directories called
177      * "temp" you pass in <code>FileFilterUtils.NameFileFilter("temp")</code>
178      * </p>
179      * <p>Another common usage of this method is find files in a directory
180      * tree but ignoring the directories generated CVS. You can simply pass
181      * in <code>FileFilterUtils.makeCVSAware(null)</code>.
182      * </p>
183      * @param directory the directory to search in
184      * @param fileFilter filter to apply when finding files.
185      * @param dirFilter optional filter to apply when finding subdirectories.
186      * If this parameter is null, subdirectories will not be included in the
187      * search. Use TrueFileFilter.INSTANCE to match all directories.
188      * @return an collection of java.io.File with the matching files
189      * @see org.apache.commons.io.filefilter.FileFilterUtils
190      * @see org.apache.commons.io.filefilter.NameFileFilter
191      */

192     public static Collection JavaDoc listFiles(File JavaDoc directory, IOFileFilter fileFilter, IOFileFilter dirFilter) {
193         if (!directory.isDirectory()) {
194             throw new IllegalArgumentException JavaDoc("Parameter 'directory' is not a directory");
195         }
196         if (fileFilter == null) {
197             throw new NullPointerException JavaDoc("Parameter 'fileFilter' is null");
198         }
199         
200         //Setup effective file filter
201
IOFileFilter effFileFilter = FileFilterUtils.andFileFilter(fileFilter,
202             FileFilterUtils.notFileFilter(DirectoryFileFilter.INSTANCE));
203             
204         //Setup effective directory filter
205
IOFileFilter effDirFilter;
206         if (dirFilter == null) {
207             effDirFilter = FalseFileFilter.INSTANCE;
208         } else {
209             effDirFilter = FileFilterUtils.andFileFilter(dirFilter,
210                 DirectoryFileFilter.INSTANCE);
211         }
212         
213         //Find files
214
Collection JavaDoc files = new java.util.LinkedList JavaDoc();
215         innerListFiles(files, directory,
216             FileFilterUtils.orFileFilter(effFileFilter, effDirFilter));
217         return files;
218     }
219     
220
221     /**
222      * Converts an array of file extensions to suffixes for use
223      * with IOFileFilters.
224      * @param extensions an array of extensions. Format: {"java", "xml"}
225      * @return an array of suffixes. Format: {".java", ".xml"}
226      */

227     private static String JavaDoc[] toSuffixes(String JavaDoc[] extensions) {
228         String JavaDoc[] suffixes = new String JavaDoc[extensions.length];
229         for (int i = 0; i < extensions.length; i++) {
230             suffixes[i] = "." + extensions[i];
231         }
232         return suffixes;
233     }
234
235
236     /**
237      * Finds files within a given directory (and optionally its subdirectories)
238      * which match an array of extensions.
239      * @param directory the directory to search in
240      * @param extensions an array of extensions, ex. {"java","xml"}. If this
241      * parameter is null, all files are returned.
242      * @param recursive If true all subdirectories are searched, too.
243      * @return an collection of java.io.File with the matching files
244      */

245     public static Collection JavaDoc listFiles(File JavaDoc directory, String JavaDoc[] extensions, boolean recursive) {
246         IOFileFilter filter;
247         if (extensions == null) {
248             filter = TrueFileFilter.INSTANCE;
249         } else {
250             String JavaDoc[] suffixes = toSuffixes(extensions);
251             filter = new SuffixFileFilter(suffixes);
252         }
253         return listFiles(directory, filter,
254             (recursive ? TrueFileFilter.INSTANCE : FalseFileFilter.INSTANCE));
255     }
256
257
258     /**
259      * <p>Compare the contents of two files to determine if they are equal or not.</p>
260      * <p>Code origin: Avalon</p>
261      *
262      * @param file1 the first file
263      * @param file2 the second file
264      * @return true if the content of the files are equal or they both don't exist, false otherwise
265      * @throws IOException in case of an I/O error
266      */

267     public static boolean contentEquals(File JavaDoc file1, File JavaDoc file2)
268             throws IOException JavaDoc {
269         boolean file1Exists = file1.exists();
270         if (file1Exists != file2.exists()) {
271             return false;
272         }
273
274         if (!file1Exists) {
275             // two not existing files are equal
276
return true;
277         }
278
279         if (file1.isDirectory() || file2.isDirectory()) {
280             // don't want to compare directory contents
281
throw new IOException JavaDoc("Can't compare directories, only files");
282         }
283
284         InputStream JavaDoc input1 = null;
285         InputStream JavaDoc input2 = null;
286         try {
287             input1 = new java.io.FileInputStream JavaDoc(file1);
288             input2 = new java.io.FileInputStream JavaDoc(file2);
289             return IOUtils.contentEquals(input1, input2);
290
291         } finally {
292             IOUtils.closeQuietly(input1);
293             IOUtils.closeQuietly(input2);
294         }
295     }
296
297     /**
298      * Convert from a <code>URL</code> to a <code>File</code>.
299      * @param url File URL.
300      * @return The equivalent <code>File</code> object, or <code>null</code> if the URL's protocol
301      * is not <code>file</code>
302      */

303     public static File JavaDoc toFile(URL JavaDoc url) {
304         if (url.getProtocol().equals("file") == false) {
305             return null;
306         } else {
307             String JavaDoc filename =
308                 url.getFile().replace('/', File.separatorChar);
309             return new File JavaDoc(filename);
310         }
311     }
312
313     /**
314      * Convert the array of Files into a list of URLs.
315      *
316      * @param files the array of files
317      * @return the array of URLs
318      * @throws IOException if an error occurs
319      */

320     public static URL JavaDoc[] toURLs(File JavaDoc[] files) throws IOException JavaDoc {
321         URL JavaDoc[] urls = new URL JavaDoc[files.length];
322
323         for (int i = 0; i < urls.length; i++) {
324             urls[i] = files[i].toURL();
325         }
326
327         return urls;
328     }
329
330
331     /**
332      * Copy file from source to destination. If <code>destinationDirectory</code> does not exist, it
333      * (and any parent directories) will be created. If a file <code>source</code> in
334      * <code>destinationDirectory</code> exists, it will be overwritten.
335      * The copy will have the same file date as the original.
336      *
337      * @param source An existing <code>File</code> to copy.
338      * @param destinationDirectory A directory to copy <code>source</code> into.
339      *
340      * @throws FileNotFoundException if <code>source</code> isn't a normal file.
341      * @throws IllegalArgumentException if <code>destinationDirectory</code> isn't a directory.
342      * @throws IOException if <code>source</code> does not exist, the file in
343      * <code>destinationDirectory</code> cannot be written to, or an IO error occurs during copying.
344      */

345     public static void copyFileToDirectory(
346         File JavaDoc source,
347         File JavaDoc destinationDirectory)
348         throws IOException JavaDoc {
349         if (destinationDirectory.exists()
350             && !destinationDirectory.isDirectory()) {
351             throw new IllegalArgumentException JavaDoc("Destination is not a directory");
352         }
353
354         copyFile(source, new File JavaDoc(destinationDirectory, source.getName()), true);
355     }
356
357     /**
358      * Copy file from source to destination. The directories up to
359      * <code>destination</code> will be created if they don't already exist.
360      * <code>destination</code> will be overwritten if it already exists.
361      * The copy will have the same file date as the original.
362      *
363      * @param source An existing non-directory <code>File</code> to copy
364      * bytes from.
365      * @param destination A non-directory <code>File</code> to write bytes to
366      * (possibly overwriting).
367      *
368      * @throws IOException if <code>source</code> does not exist, <code>destination</code> cannot be
369      * written to, or an IO error occurs during copying.
370      *
371      * @throws FileNotFoundException if <code>destination</code> is a directory
372      * (use {@link #copyFileToDirectory}).
373      */

374     public static void copyFile(File JavaDoc source, File JavaDoc destination)
375                 throws IOException JavaDoc {
376         copyFile(source, destination, true);
377     }
378                 
379                 
380     /**
381      * Copy file from source to destination. The directories up to
382      * <code>destination</code> will be created if they don't already exist.
383      * <code>destination</code> will be overwritten if it already exists.
384      *
385      * @param source An existing non-directory <code>File</code> to copy
386      * bytes from.
387      * @param destination A non-directory <code>File</code> to write bytes to
388      * (possibly overwriting).
389      * @param preserveFileDate True if the file date of the copy should be the
390      * same as the original.
391      *
392      * @throws IOException if <code>source</code> does not exist, <code>destination</code> cannot be
393      * written to, or an IO error occurs during copying.
394      *
395      * @throws FileNotFoundException if <code>destination</code> is a directory
396      * (use {@link #copyFileToDirectory}).
397      */

398     public static void copyFile(File JavaDoc source, File JavaDoc destination, boolean preserveFileDate)
399                 throws IOException JavaDoc {
400         //check source exists
401
if (!source.exists()) {
402             String JavaDoc message = "File " + source + " does not exist";
403             throw new FileNotFoundException JavaDoc(message);
404         }
405
406         //does destinations directory exist ?
407
if (destination.getParentFile() != null
408             && !destination.getParentFile().exists()) {
409             destination.getParentFile().mkdirs();
410         }
411
412         //make sure we can write to destination
413
if (destination.exists() && !destination.canWrite()) {
414             String JavaDoc message =
415                 "Unable to open file " + destination + " for writing.";
416             throw new IOException JavaDoc(message);
417         }
418
419         //makes sure it is not the same file
420
if (source.getCanonicalPath().equals(destination.getCanonicalPath())) {
421             String JavaDoc message =
422                 "Unable to write file " + source + " on itself.";
423             throw new IOException JavaDoc(message);
424         }
425
426         FileInputStream JavaDoc input = new FileInputStream JavaDoc(source);
427         try {
428             FileOutputStream JavaDoc output = new FileOutputStream JavaDoc(destination);
429             try {
430                 CopyUtils.copy(input, output);
431             } finally {
432                 IOUtils.closeQuietly(output);
433             }
434         } finally {
435             IOUtils.closeQuietly(input);
436         }
437
438         if (source.length() != destination.length()) {
439             String JavaDoc message =
440                 "Failed to copy full contents from "
441                     + source
442                     + " to "
443                     + destination;
444             throw new IOException JavaDoc(message);
445         }
446         
447         if (preserveFileDate) {
448             //file copy should preserve file date
449
destination.setLastModified(source.lastModified());
450         }
451     }
452
453     /**
454      * Copies bytes from the URL <code>source</code> to a file <code>destination</code>.
455      * The directories up to <code>destination</code> will be created if they don't already exist.
456      * <code>destination</code> will be overwritten if it already exists.
457      *
458      * @param source A <code>URL</code> to copy bytes from.
459      * @param destination A non-directory <code>File</code> to write bytes to (possibly
460      * overwriting).
461      *
462      * @throws IOException if
463      * <ul>
464      * <li><code>source</code> URL cannot be opened</li>
465      * <li><code>destination</code> cannot be written to</li>
466      * <li>an IO error occurs during copying</li>
467      * </ul>
468      */

469     public static void copyURLToFile(URL JavaDoc source, File JavaDoc destination)
470                 throws IOException JavaDoc {
471         //does destination directory exist ?
472
if (destination.getParentFile() != null
473             && !destination.getParentFile().exists()) {
474             destination.getParentFile().mkdirs();
475         }
476
477         //make sure we can write to destination
478
if (destination.exists() && !destination.canWrite()) {
479             String JavaDoc message =
480                 "Unable to open file " + destination + " for writing.";
481             throw new IOException JavaDoc(message);
482         }
483
484         InputStream JavaDoc input = source.openStream();
485         try {
486             FileOutputStream JavaDoc output = new FileOutputStream JavaDoc(destination);
487             try {
488                 CopyUtils.copy(input, output);
489             } finally {
490                 IOUtils.closeQuietly(output);
491             }
492         } finally {
493             IOUtils.closeQuietly(input);
494         }
495     }
496
497
498     /**
499      * Recursively delete a directory.
500      * @param directory directory to delete
501      * @throws IOException in case deletion is unsuccessful
502      */

503     public static void deleteDirectory(File JavaDoc directory)
504         throws IOException JavaDoc {
505         if (!directory.exists()) {
506             return;
507         }
508
509         cleanDirectory(directory);
510         if (!directory.delete()) {
511             String JavaDoc message =
512                 "Unable to delete directory " + directory + ".";
513             throw new IOException JavaDoc(message);
514         }
515     }
516
517     /**
518      * Clean a directory without deleting it.
519      * @param directory directory to clean
520      * @throws IOException in case cleaning is unsuccessful
521      */

522     public static void cleanDirectory(File JavaDoc directory)
523         throws IOException JavaDoc {
524         if (!directory.exists()) {
525             String JavaDoc message = directory + " does not exist";
526             throw new IllegalArgumentException JavaDoc(message);
527         }
528
529         if (!directory.isDirectory()) {
530             String JavaDoc message = directory + " is not a directory";
531             throw new IllegalArgumentException JavaDoc(message);
532         }
533
534         IOException JavaDoc exception = null;
535
536         File JavaDoc[] files = directory.listFiles();
537         for (int i = 0; i < files.length; i++) {
538             File JavaDoc file = files[i];
539             try {
540                 forceDelete(file);
541             } catch (IOException JavaDoc ioe) {
542                 exception = ioe;
543             }
544         }
545
546         if (null != exception) {
547             throw exception;
548         }
549     }
550
551     /**
552      * Waits for NFS to propagate a file creation, imposing a timeout.
553      *
554      * @param file The file
555      * @param seconds The maximum time in seconds to wait.
556      * @return True if file exists.
557      * TODO Needs a clearer javadoc to see its real purpose for someone without
558      * NFS-knowledge.
559      */

560     public static boolean waitFor(File JavaDoc file, int seconds) {
561         int timeout = 0;
562         int tick = 0;
563         while (!file.exists()) {
564             if (tick++ >= 10) {
565                 tick = 0;
566                 if (timeout++ > seconds) {
567                     return false;
568                 }
569             }
570             try {
571                 Thread.sleep(100);
572             } catch (InterruptedException JavaDoc ignore) {} catch (Exception JavaDoc ex) {
573                 break;
574             }
575         }
576         return true;
577     }
578
579
580     /**
581      * <p>
582      * Reads the contents of a file into a String.
583      * </p>
584      * <p>
585      * There is no readFileToString method without encoding parameter because
586      * the default encoding can differ between platforms and therefore results
587      * in inconsistent results.
588      * </p>
589      *
590      * @param file the file to read.
591      * @param encoding the encoding to use
592      * @return The file contents or null if read failed.
593      * @throws IOException in case of an I/O error
594      * @throws UnsupportedEncodingException if the encoding is not supported
595      * by the VM
596      */

597     public static String JavaDoc readFileToString(
598             File JavaDoc file, String JavaDoc encoding) throws IOException JavaDoc {
599         InputStream JavaDoc in = new java.io.FileInputStream JavaDoc(file);
600         try {
601             return IOUtils.toString(in, encoding);
602         } finally {
603             IOUtils.closeQuietly(in);
604         }
605     }
606
607     /**
608      * <p>
609      * Writes data to a file. The file will be created if it does not exist.
610      * </p>
611      * <p>
612      * There is no readFileToString method without encoding parameter because
613      * the default encoding can differ between platforms and therefore results
614      * in inconsistent results.
615      * </p>
616      *
617      * @param file the file to write.
618      * @param data The content to write to the file.
619      * @param encoding encoding to use
620      * @throws IOException in case of an I/O error
621      * @throws UnsupportedEncodingException if the encoding is not supported
622      * by the VM
623      */

624     public static void writeStringToFile(File JavaDoc file,
625             String JavaDoc data, String JavaDoc encoding) throws IOException JavaDoc {
626         OutputStream JavaDoc out = new java.io.FileOutputStream JavaDoc(file);
627         try {
628             out.write(data.getBytes(encoding));
629         } finally {
630             IOUtils.closeQuietly(out);
631         }
632     }
633
634     /**
635      * <p>
636      * Delete a file. If file is a directory, delete it and all sub-directories.
637      * </p>
638      * <p>
639      * The difference between File.delete() and this method are:
640      * </p>
641      * <ul>
642      * <li>A directory to be deleted does not have to be empty.</li>
643      * <li>You get exceptions when a file or directory cannot be deleted.
644      * (java.io.File methods returns a boolean)</li>
645      * </ul>
646      * @param file file or directory to delete.
647      * @throws IOException in case deletion is unsuccessful
648      */

649     public static void forceDelete(File JavaDoc file) throws IOException JavaDoc {
650         if (file.isDirectory()) {
651             deleteDirectory(file);
652         } else {
653             if (!file.exists()) {
654                 throw new FileNotFoundException JavaDoc("File does not exist: " + file);
655             }
656             if (!file.delete()) {
657                 String JavaDoc message =
658                     "Unable to delete file: " + file;
659                 throw new IOException JavaDoc(message);
660             }
661         }
662     }
663
664     /**
665      * Schedule a file to be deleted when JVM exits.
666      * If file is directory delete it and all sub-directories.
667      * @param file file or directory to delete.
668      * @throws IOException in case deletion is unsuccessful
669      */

670     public static void forceDeleteOnExit(File JavaDoc file) throws IOException JavaDoc {
671         if (file.isDirectory()) {
672             deleteDirectoryOnExit(file);
673         } else {
674             file.deleteOnExit();
675         }
676     }
677
678     /**
679      * Recursively schedule directory for deletion on JVM exit.
680      * @param directory directory to delete.
681      * @throws IOException in case deletion is unsuccessful
682      */

683     private static void deleteDirectoryOnExit(File JavaDoc directory)
684             throws IOException JavaDoc {
685         if (!directory.exists()) {
686             return;
687         }
688
689         cleanDirectoryOnExit(directory);
690         directory.deleteOnExit();
691     }
692
693     /**
694      * Clean a directory without deleting it.
695      * @param directory directory to clean.
696      * @throws IOException in case cleaning is unsuccessful
697      */

698     private static void cleanDirectoryOnExit(File JavaDoc directory)
699             throws IOException JavaDoc {
700         if (!directory.exists()) {
701             String JavaDoc message = directory + " does not exist";
702             throw new IllegalArgumentException JavaDoc(message);
703         }
704
705         if (!directory.isDirectory()) {
706             String JavaDoc message = directory + " is not a directory";
707             throw new IllegalArgumentException JavaDoc(message);
708         }
709
710         IOException JavaDoc exception = null;
711
712         File JavaDoc[] files = directory.listFiles();
713         for (int i = 0; i < files.length; i++) {
714             File JavaDoc file = files[i];
715             try {
716                 forceDeleteOnExit(file);
717             } catch (IOException JavaDoc ioe) {
718                 exception = ioe;
719             }
720         }
721
722         if (null != exception) {
723             throw exception;
724         }
725     }
726
727
728     /**
729      * Make a directory. If there already exists a file with specified name or
730      * the directory cannot be created then an exception is thrown.
731      * @param directory directory to create
732      * @throws IOException if the directory cannot be created.
733      */

734     public static void forceMkdir(File JavaDoc directory) throws IOException JavaDoc {
735         if (directory.exists()) {
736             if (directory.isFile()) {
737                 String JavaDoc message =
738                     "File "
739                         + directory
740                         + " exists and is "
741                         + "not a directory. Unable to create directory.";
742                 throw new IOException JavaDoc(message);
743             }
744         } else {
745             if (false == directory.mkdirs()) {
746                 String JavaDoc message =
747                     "Unable to create directory " + directory;
748                 throw new IOException JavaDoc(message);
749             }
750         }
751     }
752
753     /**
754      * Recursively count size of a directory (sum of the length of all files).
755      *
756      * @param directory directory to inspect
757      * @return size of directory in bytes.
758      */

759     public static long sizeOfDirectory(File JavaDoc directory) {
760         if (!directory.exists()) {
761             String JavaDoc message = directory + " does not exist";
762             throw new IllegalArgumentException JavaDoc(message);
763         }
764
765         if (!directory.isDirectory()) {
766             String JavaDoc message = directory + " is not a directory";
767             throw new IllegalArgumentException JavaDoc(message);
768         }
769
770         long size = 0;
771
772         File JavaDoc[] files = directory.listFiles();
773         for (int i = 0; i < files.length; i++) {
774             File JavaDoc file = files[i];
775
776             if (file.isDirectory()) {
777                 size += sizeOfDirectory(file);
778             } else {
779                 size += file.length();
780             }
781         }
782
783         return size;
784     }
785    
786      /**
787       * Tests if the specified <code>File</code> is newer than the reference
788       * <code>File</code>.
789       *
790       * @param file the <code>File</code> of which the modification date must be compared
791       * @param reference the <code>File</code> of which the modification date is used
792       * like reference
793       * @return true if the <code>File</code> exists and has been modified more recently
794       * than the reference <code>File</code>.
795       */

796      public static boolean isFileNewer(File JavaDoc file, File JavaDoc reference) {
797          if (reference == null) {
798              throw new IllegalArgumentException JavaDoc("No specified reference file");
799          }
800          if (!reference.exists()) {
801              throw new IllegalArgumentException JavaDoc("The reference file '" + file + "' doesn't exist");
802          }
803  
804          return isFileNewer(file, reference.lastModified());
805      }
806  
807      /**
808       * Tests if the specified <code>File</code> is newer than the specified
809       * <code>Date</code>
810       *
811       * @param file the <code>File</code> of which the modification date must be compared
812       * @param date the date reference
813       * @return true if the <code>File</code> exists and has been modified after
814       * the given <code>Date</code>.
815       */

816      public static boolean isFileNewer(File JavaDoc file, Date JavaDoc date) {
817          if (date == null) {
818              throw new IllegalArgumentException JavaDoc("No specified date");
819          }
820          return isFileNewer(file, date.getTime());
821      }
822  
823      /**
824       * Tests if the specified <code>File</code> is newer than the specified
825       * time reference.
826       *
827       * @param file the <code>File</code> of which the modification date must be compared.
828       * @param timeMillis the time reference measured in milliseconds since the epoch
829       * (00:00:00 GMT, January 1, 1970)
830       * @return true if the <code>File</code> exists and has been modified after
831       * the given time reference.
832       */

833      public static boolean isFileNewer(File JavaDoc file, long timeMillis) {
834          if (file == null) {
835              throw new IllegalArgumentException JavaDoc("No specified file");
836          }
837          if (!file.exists()) {
838              return false;
839          }
840  
841          return file.lastModified() > timeMillis;
842     }
843
844 }
845
Popular Tags