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]>