You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2005/02/20 19:13:55 UTC
svn commit: r154553 - in jakarta/commons/proper/io/trunk: project.xml
src/java/org/apache/commons/io/FileUtils.java
src/test/org/apache/commons/io/FileUtilsTestCase.java
Author: scolebourne
Date: Sun Feb 20 10:13:54 2005
New Revision: 154553
URL: http://svn.apache.org/viewcvs?view=rev&rev=154553
Log:
Add copyDirectory, and refactor copyFile
bug 32944, from Ian Springer
Modified:
jakarta/commons/proper/io/trunk/project.xml
jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/FileUtils.java
jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/FileUtilsTestCase.java
Modified: jakarta/commons/proper/io/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/io/trunk/project.xml?view=diff&r1=154552&r2=154553
==============================================================================
--- jakarta/commons/proper/io/trunk/project.xml (original)
+++ jakarta/commons/proper/io/trunk/project.xml Sun Feb 20 10:13:54 2005
@@ -166,6 +166,9 @@
<email>alban.peignier at free.fr</email>
</contributor>
<contributor>
+ <name>Ian Springer</name>
+ </contributor>
+ <contributor>
<name>Masato Tezuka</name>
</contributor>
</contributors>
Modified: jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/FileUtils.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/FileUtils.java?view=diff&r1=154552&r2=154553
==============================================================================
--- jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/FileUtils.java (original)
+++ jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/FileUtils.java Sun Feb 20 10:13:54 2005
@@ -65,6 +65,7 @@
* @author Matthew Hawthorne
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
* @author Stephen Colebourne
+ * @author Ian Springer
* @version $Id$
*/
public class FileUtils {
@@ -391,111 +392,113 @@
//-----------------------------------------------------------------------
/**
- * Copy file from source to destination. If
- * <code>destinationDirectory</code> does not exist, it (and any parent
- * directories) will be created. If a file <code>source</code> in
- * <code>destinationDirectory</code> exists, it will be overwritten.
- * The copy will have the same file date as the original.
- *
- * @param source An existing <code>File</code> to copy.
- * @param destinationDirectory A directory to copy <code>source</code> into.
- *
- * @throws FileNotFoundException if <code>source</code> isn't a normal file.
- * @throws IllegalArgumentException if <code>destinationDirectory</code>
- * isn't a directory.
- * @throws IOException if <code>source</code> does not exist, the file in
- * <code>destinationDirectory</code> cannot be written to, or an IO error
- * occurs during copying.
- */
- public static void copyFileToDirectory(
- File source,
- File destinationDirectory)
- throws IOException {
- if (destinationDirectory.exists()
- && !destinationDirectory.isDirectory()) {
- throw new IllegalArgumentException(
- "Destination is not a directory");
- }
-
- copyFile(source,
- new File(destinationDirectory, source.getName()), true);
- }
-
- /**
- * Copy file from source to destination. The directories up to
- * <code>destination</code> will be created if they don't already exist.
- * <code>destination</code> will be overwritten if it already exists.
- * The copy will have the same file date as the original.
- *
- * @param source An existing non-directory <code>File</code> to copy
- * bytes from.
- * @param destination A non-directory <code>File</code> to write bytes to
- * (possibly overwriting).
+ * Copies a file to a directory preserving the file date.
+ * <p>
+ * This method copies the contents of the specified source file
+ * to a file of the same name in the specified destination directory.
+ * The destination directory is created if it does not exist.
+ * If the destination file exists, then this method will overwrite it.
*
- * @throws IOException if <code>source</code> does not exist,
- * <code>destination</code> cannot be written to, or an IO error occurs
- * during copying.
+ * @param srcFile an existing file to copy, must not be null
+ * @param destDir the directory to place the copy in, must not be null
*
- * @throws FileNotFoundException if <code>destination</code> is a directory
- * (use {@link #copyFileToDirectory}).
+ * @throws NullPointerException if source or destination is null
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ * @see #copyFile
*/
- public static void copyFile(File source, File destination)
- throws IOException {
- copyFile(source, destination, true);
+ public static void copyFileToDirectory(File srcFile, File destDir) throws IOException {
+ if (destDir == null) {
+ throw new NullPointerException("Destination must not be null");
+ }
+ if (destDir.exists() && destDir.isDirectory() == false) {
+ throw new IllegalArgumentException("Destination '" + destDir + "' is not a directory");
+ }
+ copyFile(srcFile, new File(destDir, srcFile.getName()), true);
}
-
/**
- * Copy file from source to destination. The directories up to
- * <code>destination</code> will be created if they don't already exist.
- * <code>destination</code> will be overwritten if it already exists.
- *
- * @param source An existing non-directory <code>File</code> to copy
- * bytes from.
- * @param destination A non-directory <code>File</code> to write bytes to
- * (possibly overwriting).
- * @param preserveFileDate True if the file date of the copy should be the
- * same as the original.
- *
- * @throws IOException if <code>source</code> does not exist,
- * <code>destination</code> cannot be written to, or an IO error occurs
- * during copying.
- *
- * @throws FileNotFoundException if <code>destination</code> is a directory
- * (use {@link #copyFileToDirectory}).
+ * Copies a file to a new location preserving the file date.
+ * <p>
+ * This method copies the contents of the specified source file to the
+ * specified destination file. The directory holding the destination file is
+ * created if it does not exist. If the destination file exists, then this
+ * method will overwrite it.
+ *
+ * @param srcFile an existing file to copy, must not be null
+ * @param destFile the new file, must not be null
+ *
+ * @throws NullPointerException if source or destination is null
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ * @see #copyFileToDirectory
*/
- public static void copyFile(File source, File destination,
- boolean preserveFileDate)
- throws IOException {
- //check source exists
- if (!source.exists()) {
- String message = "File " + source + " does not exist";
- throw new FileNotFoundException(message);
- }
+ public static void copyFile(File srcFile, File destFile) throws IOException {
+ copyFile(srcFile, destFile, true);
+ }
- //does destinations directory exist ?
- if (destination.getParentFile() != null
- && !destination.getParentFile().exists()) {
- destination.getParentFile().mkdirs();
+ /**
+ * Copies a file to a new location.
+ * <p>
+ * This method copies the contents of the specified source file
+ * to the specified destination file.
+ * The directory holding the destination file is created if it does not exist.
+ * If the destination file exists, then this method will overwrite it.
+ *
+ * @param srcFile an existing file to copy, must not be null
+ * @param destFile the new file, must not be null
+ * @param preserveFileDate true if the file date of the copy
+ * should be the same as the original
+ *
+ * @throws NullPointerException if source or destination is null
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ * @see #copyFileToDirectory
+ */
+ public static void copyFile(File srcFile, File destFile,
+ boolean preserveFileDate) throws IOException {
+ if (srcFile == null) {
+ throw new NullPointerException("Source must not be null");
+ }
+ if (destFile == null) {
+ throw new NullPointerException("Destination must not be null");
+ }
+ if (srcFile.exists() == false) {
+ throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
+ }
+ if (srcFile.isDirectory()) {
+ throw new IOException("Source '" + srcFile + "' exists but is a directory");
+ }
+ if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) {
+ throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same");
+ }
+ if (destFile.getParentFile() != null && destFile.getParentFile().exists() == false) {
+ if (destFile.getParentFile().mkdirs() == false) {
+ throw new IOException("Destination '" + destFile + "' directory cannot be created");
+ }
}
-
- //make sure we can write to destination
- if (destination.exists() && !destination.canWrite()) {
- String message =
- "Unable to open file " + destination + " for writing.";
- throw new IOException(message);
+ if (destFile.exists() && destFile.canWrite() == false) {
+ throw new IOException("Destination '" + destFile + "' exists but is read-only");
}
+ doCopyFile(srcFile, destFile, preserveFileDate);
+ }
- //makes sure it is not the same file
- if (source.getCanonicalPath().equals(destination.getCanonicalPath())) {
- String message =
- "Unable to write file " + source + " on itself.";
- throw new IOException(message);
+ /**
+ * Internal copy file method.
+ *
+ * @param srcFile the validated source file, not null
+ * @param destFile the validated destination file, not null
+ * @param preserveFileDate whether to preserve the file date
+ * @throws IOException if an error occurs
+ */
+ private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
+ if (destFile.exists() && destFile.isDirectory()) {
+ throw new IOException("Destination '" + destFile + "' exists but is a directory");
}
- FileInputStream input = new FileInputStream(source);
+ FileInputStream input = new FileInputStream(srcFile);
try {
- FileOutputStream output = new FileOutputStream(destination);
+ FileOutputStream output = new FileOutputStream(destFile);
try {
IOUtils.copy(input, output);
} finally {
@@ -505,21 +508,110 @@
IOUtils.closeQuietly(input);
}
- if (source.length() != destination.length()) {
- String message =
- "Failed to copy full contents from "
- + source
- + " to "
- + destination;
- throw new IOException(message);
+ if (srcFile.length() != destFile.length()) {
+ throw new IOException("Failed to copy full contents from '" +
+ srcFile + "' to '" + destFile + "'");
}
-
if (preserveFileDate) {
- //file copy should preserve file date
- destination.setLastModified(source.lastModified());
+ destFile.setLastModified(srcFile.lastModified());
}
}
+ //-----------------------------------------------------------------------
+ /**
+ * Copies a whole directory to a new location preserving the file dates.
+ * <p>
+ * This method copies the specified directory and all its child
+ * directories and files to the specified destination.
+ * The destination is the new location and name of the directory.
+ * If it already exists, the contents will be overwritten.
+ *
+ * @param srcDir an existing directory to copy, must not be null
+ * @param destDir the new directory, must not be null
+ *
+ * @throws NullPointerException if source or destination is null
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ */
+ public static void copyDirectory(File srcDir, File destDir) throws IOException {
+ copyDirectory(srcDir, destDir, true);
+ }
+
+ /**
+ * Copies a whole directory to a new location.
+ * <p>
+ * This method copies the contents of the specified source directory
+ * to within the specified destination directory.
+ * The destination directory is created if it does not exist.
+ * If the destination directory did exist, then this method merges
+ * the source with the destination, with the source taking precedence.
+ *
+ * @param srcDir an existing directory to copy, must not be null
+ * @param destDir the new directory, must not be null
+ * @param preserveFileDate true if the file date of the copy
+ * should be the same as the original
+ *
+ * @throws NullPointerException if source or destination is null
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ */
+ public static void copyDirectory(File srcDir, File destDir,
+ boolean preserveFileDate) throws IOException {
+ if (srcDir == null) {
+ throw new NullPointerException("Source must not be null");
+ }
+ if (destDir == null) {
+ throw new NullPointerException("Destination must not be null");
+ }
+ if (srcDir.exists() == false) {
+ throw new FileNotFoundException("Source '" + srcDir + "' does not exist");
+ }
+ if (srcDir.isDirectory() == false) {
+ throw new IOException("Source '" + srcDir + "' exists but is not a directory");
+ }
+ if (srcDir.getCanonicalPath().equals(destDir.getCanonicalPath())) {
+ throw new IOException("Source '" + srcDir + "' and destination '" + destDir + "' are the same");
+ }
+ doCopyDirectory(srcDir, destDir, preserveFileDate);
+ }
+
+ /**
+ * Internal copy directory method.
+ *
+ * @param srcDir the validated source directory, not null
+ * @param destDir the validated destination directory, not null
+ * @param preserveFileDate whether to preserve the file date
+ * @throws IOException if an error occurs
+ */
+ private static void doCopyDirectory(File srcDir, File destDir, boolean preserveFileDate) throws IOException {
+ if (destDir.exists()) {
+ if (destDir.isDirectory() == false) {
+ throw new IOException("Destination '" + destDir + "' exists but is not a directory");
+ }
+ } else {
+ if (destDir.mkdirs() == false) {
+ throw new IOException("Destination '" + destDir + "' directory cannot be created");
+ }
+ if (preserveFileDate) {
+ destDir.setLastModified(srcDir.lastModified());
+ }
+ }
+ if (destDir.canWrite() == false) {
+ throw new IOException("Destination '" + destDir + "' cannot be written to");
+ }
+ // recurse
+ File[] files = srcDir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ File copiedFile = new File(destDir, files[i].getName());
+ if (files[i].isDirectory()) {
+ doCopyDirectory(files[i], copiedFile, preserveFileDate);
+ } else {
+ doCopyFile(files[i], copiedFile, preserveFileDate);
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
/**
* Copies bytes from the URL <code>source</code> to a file
* <code>destination</code>. The directories up to <code>destination</code>
@@ -565,7 +657,7 @@
}
}
-
+ //-----------------------------------------------------------------------
/**
* Recursively delete a directory.
* @param directory directory to delete
Modified: jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/FileUtilsTestCase.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/FileUtilsTestCase.java?view=diff&r1=154552&r2=154553
==============================================================================
--- jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/FileUtilsTestCase.java (original)
+++ jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/FileUtilsTestCase.java Sun Feb 20 10:13:54 2005
@@ -405,6 +405,74 @@
testFile1.lastModified() != destination.lastModified());*/
}
+ public void testCopyDirectoryToNonExistingDest() throws Exception {
+ createFile(testFile1, 1234);
+ createFile(testFile2, 4321);
+ File srcDir = getTestDirectory();
+ File subDir = new File(srcDir, "sub");
+ subDir.mkdir();
+ File subFile = new File(subDir, "A.txt");
+ FileUtils.writeStringToFile(subFile, "HELLO WORLD", "UTF8");
+ File destDir = new File(System.getProperty("java.io.tmpdir"), "tmp-FileUtilsTestCase");
+ FileUtils.deleteDirectory(destDir);
+
+ FileUtils.copyDirectory(srcDir, destDir);
+
+ assertTrue("Check exists", destDir.exists());
+ assertEquals("Check size", FileUtils.sizeOfDirectory(srcDir), FileUtils.sizeOfDirectory(destDir));
+ assertEquals(true, new File(destDir, "sub/A.txt").exists());
+ FileUtils.deleteDirectory(destDir);
+ }
+
+ public void testCopyDirectoryToExistingDest() throws Exception {
+ createFile(testFile1, 1234);
+ createFile(testFile2, 4321);
+ File srcDir = getTestDirectory();
+ File subDir = new File(srcDir, "sub");
+ subDir.mkdir();
+ File subFile = new File(subDir, "A.txt");
+ FileUtils.writeStringToFile(subFile, "HELLO WORLD", "UTF8");
+ File destDir = new File(System.getProperty("java.io.tmpdir"), "tmp-FileUtilsTestCase");
+ FileUtils.deleteDirectory(destDir);
+ destDir.mkdirs();
+
+ FileUtils.copyDirectory(srcDir, destDir);
+
+ assertEquals(FileUtils.sizeOfDirectory(srcDir), FileUtils.sizeOfDirectory(destDir));
+ assertEquals(true, new File(destDir, "sub/A.txt").exists());
+ }
+
+ public void testCopyDirectoryErrors() throws Exception {
+ try {
+ FileUtils.copyDirectory(null, null);
+ fail();
+ } catch (NullPointerException ex) {}
+ try {
+ FileUtils.copyDirectory(new File("a"), null);
+ fail();
+ } catch (NullPointerException ex) {}
+ try {
+ FileUtils.copyDirectory(null, new File("a"));
+ fail();
+ } catch (NullPointerException ex) {}
+ try {
+ FileUtils.copyDirectory(new File("doesnt-exist"), new File("a"));
+ fail();
+ } catch (IOException ex) {}
+ try {
+ FileUtils.copyDirectory(testFile1, new File("a"));
+ fail();
+ } catch (IOException ex) {}
+ try {
+ FileUtils.copyDirectory(getTestDirectory(), testFile1);
+ fail();
+ } catch (IOException ex) {}
+ try {
+ FileUtils.copyDirectory(getTestDirectory(), getTestDirectory());
+ fail();
+ } catch (IOException ex) {}
+ }
+
// forceDelete
public void testForceDeleteAFile1() throws Exception {
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org