I found a bug in the VFS code for copying a file when the source and dest files are
accessed through the same FTP session. This creates a race condition between reading
the source file and writing to the dest file (I think).
Anyway, you can check out the code comments enclosed. I also added a unit test. Let
me know if it seems to make sense.
Index: vfs/src/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java
===================================================================
RCS file:
/home/cvspublic/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java,v
retrieving revision 1.9
diff -u -r1.9 FtpFileObject.java
--- vfs/src/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java 20 Nov 2002
23:55:36 -0000 1.9
+++ vfs/src/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java 20 Jan 2003
+21:16:34 -0000
@@ -60,6 +60,8 @@
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.provider.AbstractFileObject;
@@ -75,7 +77,7 @@
{
private static final FTPFile[] EMPTY_FTP_FILE_ARRAY = {};
- private final FtpFileSystem ftpFs;
+ private FtpFileSystem ftpFs;
private final String relPath;
// Cached info
@@ -91,6 +93,60 @@
ftpFs = fileSystem;
relPath = rootName.getRelativeName( name );
}
+
+ /**
+ * Copies another file, and all its descendents, to this file.
+ *
+ * If this file does not exist, it is created. Its parent folder is also
+ * created, if necessary. If this file does exist, it is deleted first.
+ *
+ * <p>This method is not transactional. If it fails and throws an
+ * exception, this file will potentially only be partially copied.
+ *
+ * @param file The source file to copy.
+ * @param selector The selector to use to select which files to copy.
+ *
+ * @throws FileSystemException
+ * If this file is read-only, or if the source file does not exist,
+ * or on error copying the file.
+ */
+ public void copyFrom( final FileObject file, final FileSelector selector )
+ throws FileSystemException {
+
+ // We override copyFrom here for the specific case where the source
+ // and destination files in the copy are from the same FTPFileSystem.
+
+ // The problem is this can't be done through one FTP session
+ // concurrently( I think it creates a race condition) So we
+ // temporarily create a new one just for use during this copy
+ // and then return everything to the way it was afterward.
+
+ // if we're copying to and from the same FileSystem
+ if ( file.getFileSystem().equals( this.getFileSystem() ) ) {
+
+ FtpFileNameParser parser = new FtpFileNameParser();
+
+ // save the old file system for later
+ FtpFileSystem oldFs = this.ftpFs;
+
+ // create a new file system for use temporarily
+ FtpUri uri = parser.parseFtpUri( this.getURL().toString() );
+ this.ftpFs = new FtpFileSystem( oldFs.getRoot().getName(),
+
+ uri.getHostName(),
+
+ uri.getUserName(),
+
+ uri.getPassword() );
+
+ // use our parent's copy functionality
+ super.copyFrom( file, selector );
+
+ // return the filesystem to the way it was
+ this.ftpFs.close();
+ this.ftpFs = oldFs;
+ }
+ // otherwise proceed normally
+ else {
+ super.copyFrom( file, selector );
+ }
+ }
/**
* Called by child file objects, to locate their ftp file info.
Index: vfs/src/test/org/apache/commons/vfs/test/ProviderWriteTests.java
===================================================================
RCS file:
/home/cvspublic/jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/test/ProviderWriteTests.java,v
retrieving revision 1.4
diff -u -r1.4 ProviderWriteTests.java
--- vfs/src/test/org/apache/commons/vfs/test/ProviderWriteTests.java 23 Nov 2002
00:41:10 -0000 1.4
+++ vfs/src/test/org/apache/commons/vfs/test/ProviderWriteTests.java 20 Jan 2003
+21:16:34 -0000
@@ -55,6 +55,7 @@
*/
package org.apache.commons.vfs.test;
+import java.io.DataOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
@@ -446,4 +447,42 @@
assertEquals( "Missing event", 0, events.size() );
}
}
+
+ /**
+ * Tests file copy to and from the same filesystem type. This was a problem
+ * w/ FTP.
+ *
+ * @see org.apache.commons.vfs.provider.ftp.FtpFileObject#copyFrom
+ * (FileObject, FileSelector)
+ */
+ public void testFileCopySameFileSystem() throws Exception
+ {
+ FileObject scratchFolder = createScratchFolder();
+
+ // Create direct child of the test folder
+ FileObject file = scratchFolder.resolveFile( "file1.txt" );
+ assertTrue( !file.exists() );
+ file.createFile();
+ assertTrue( file.exists() );
+ assertSame( FileType.FILE, file.getType() );
+ assertEquals( 0, file.getContent().getSize() );
+
+ // add content to the file
+ DataOutputStream os = null;
+ try {
+ os = new DataOutputStream( file.getContent().getOutputStream()
+);
+ os.writeChars( "Here is some sample content for the file.
+Blah Blah Blah." );
+ }
+ finally {
+ os.close();
+ }
+
+ // make sure we can copy the new file to another file on the same
+filesystem
+ FileObject fileCopy = scratchFolder.resolveFile( "file1copy.txt" );
+ assertTrue( !fileCopy.exists() );
+ fileCopy.copyFrom( file, Selectors.SELECT_SELF );
+ assertTrue( fileCopy.exists() );
+
+ }
+
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>