adammurdoch 2002/10/24 20:59:10 Modified: vfs/src/java/org/apache/commons/vfs FileObject.java FileSystem.java Resources.properties vfs/src/java/org/apache/commons/vfs/provider AbstractFileObject.java AbstractFileSystem.java vfs/src/java/org/apache/commons/vfs/provider/ftp FtpFileObject.java vfs/src/java/org/apache/commons/vfs/tasks AbstractSyncTask.java MkdirTask.java vfs/src/test/org/apache/commons/vfs/test AbstractWritableFileSystemTestCase.java Added: vfs/src/java/org/apache/commons/vfs FileChangeEvent.java FileListener.java Log: - Added initial support for file listeners: - Added FileSystem.addListener() and removeListener(). - FileObject: - Added delete() convenience method. - Split create( type ) into createFolder() and createFile(). - AbstractFileObject: - Added detach(), which allows a subclass to force cached state to be invalidated. - No longer detaches when the file is created, deleted, or the content changes. It is now the subclass' responsibility to explicitly detach if it needs to. Revision Changes Path 1.9 +31 -11 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/FileObject.java Index: FileObject.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/FileObject.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- FileObject.java 23 Oct 2002 13:09:45 -0000 1.8 +++ FileObject.java 25 Oct 2002 03:59:09 -0000 1.9 @@ -84,11 +84,11 @@ * * <h4>Creating and Deleting a File</h4> * - * <p>A file is created using either {@link #create}, or by writing to the - * file using one of the {@link FileContent} methods. + * <p>A file is created using either {@link #createFolder}, {@link #create}, + * or by writing to the file using one of the {@link FileContent} methods. * - * <p>A file is deleted using {@link #delete}. Deletion is recursive, so - * that when a folder is deleted, so are all its child files. + * <p>A file is deleted using {@link #delete}. Recursive deletion can be + * done using {@link #delete(FileSelector)}. * * <h4>Finding Files</h4> * @@ -261,8 +261,19 @@ List findFiles( FileSelector selector ) throws FileSystemException; /** - * Deletes this file, and all descendents. Does nothing if the file - * does not exist. + * Deletes this file. Does nothing if this file does not exist. Does + * not delete any descendents of this file, use {@link #delete(FileSelector)} + * for that. + * + * @throws FileSystemException + * If this file is a non-empty folder, or if this file is read-only, + * or on error deleteing this file. + */ + void delete() throws FileSystemException; + + /** + * Deletes all descendents of this file that match a selector. Does + * nothing if this file does not exist. * * <p>This method is not transactional. If it fails and throws an * exception, this file will potentially only be partially deleted. @@ -276,19 +287,28 @@ void delete( FileSelector selector ) throws FileSystemException; /** + * Creates this folder, if it does not exist. Also creates any ancestor + * folders which do not exist. This method does nothing if the folder + * already exists. + * + * @throws FileSystemException + * If the folder already exists with the wrong type, or the parent + * folder is read-only, or on error creating this folder or one of + * its ancestors. + */ + void createFolder() throws FileSystemException; + + /** * Creates this file, if it does not exist. Also creates any ancestor * folders which do not exist. This method does nothing if the file - * already exists with the requested type. - * - * @param type - * The type of file to create. + * already exists and is a file. * * @throws FileSystemException * If the file already exists with the wrong type, or the parent * folder is read-only, or on error creating this file or one of * its ancestors. */ - void create( FileType type ) throws FileSystemException; + void createFile() throws FileSystemException; /** * Copies another file, and all its descendents, to this file. 1.5 +17 -1 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/FileSystem.java Index: FileSystem.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/FileSystem.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- FileSystem.java 23 Oct 2002 11:59:39 -0000 1.4 +++ FileSystem.java 25 Oct 2002 03:59:09 -0000 1.5 @@ -136,4 +136,20 @@ * @return The file. Never returns null. */ FileObject resolveFile( String name ) throws FileSystemException; + + /** + * Adds a listener on a file in this file system. + * + * @param file The file to attach the listener to. + * @param listener The listener to add. + */ + void addListener( FileObject file, FileListener listener ); + + /** + * Removes a listener from a file in this file system. + * + * @param file The file to remove the listener from. + * @param listener The listener to remove. + */ + void removeListener( FileObject file, FileListener listener ); } 1.7 +7 -5 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/Resources.properties Index: Resources.properties =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/Resources.properties,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- Resources.properties 24 Oct 2002 02:11:03 -0000 1.6 +++ Resources.properties 25 Oct 2002 03:59:09 -0000 1.7 @@ -3,10 +3,10 @@ # AbstractFileObject vfs.provider/delete-not-supported.error=This file type does not support delete. -vfs.provider/create-folder-not-supported.error=this file type does not support folder creation. -vfs.provider/get-last-modified-not-supported.error=this file type does not support retriving last modified time. -vfs.provider/set-last-modified-not-supported.error=this file type does not support setting last modified time. -vfs.provider/set-attribute-not-supported.error=this file type does not support setting attributes. +vfs.provider/create-folder-not-supported.error=This file type does not support folder creation. +vfs.provider/get-last-modified-not-supported.error=This file type does not support retriving last modified time. +vfs.provider/set-last-modified-not-supported.error=This file type does not support setting last modified time. +vfs.provider/set-attribute-not-supported.error=This file type does not support setting attributes. vfs.provider/write-not-supported.error=This file type cannot be written to. vfs.provider/get-type-no-exist.error=Could not determine the type of file "{0}" because it does not exist. vfs.provider/get-type.error=Could not determine the type of file "{0}". @@ -17,7 +17,8 @@ vfs.provider/delete.error=Could not delete "{0}". vfs.provider/create-mismatched-type.error=Could not create {0} "{1}" because it already exists and is a {2}. vfs.provider/create-read-only.error=Could not create {0} "{1}" because the file system is read-only. -vfs.provider/create.error=Could not create {0} "{1}". +vfs.provider/create-folder.error=Could not create folder "{1}". +vfs.provider/create-file.error=Could not create file "{1}". vfs.provider/write-read-only.error=Could not write to "{0}" because it is read-only. vfs.provider/write-folder.error=Could not write to "{0}" because it is a folder. vfs.provider/write-in-use.error=Could not write to "{0}" because it is already in use. @@ -117,3 +118,4 @@ vfs.tasks/sync.src-file-no-exist.warn=Source file "{0}" does not exist. vfs.tasks/sync.duplicate-source-files.warn=Multiple source files for destination file "{0}". vfs.tasks/delete.no-source-files.error=No files to delete specified. +vfs.tasks/mkdir.create-folder.info=Creating directory "{0}". \ No newline at end of file 1.1 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/FileChangeEvent.java Index: FileChangeEvent.java =================================================================== /* ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.vfs; /** * An event fired when a file is changed. * * @author <a href="mailto:adammurdoch@;apache.org">Adam Murdoch</a> * @version $Revision: 1.1 $ $Date: 2002/10/25 03:59:09 $ */ public class FileChangeEvent { private final FileObject file; public FileChangeEvent( final FileObject file ) { this.file = file; } /** * Returns the file that changed. */ public FileObject getFile() { return file; } } 1.1 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/FileListener.java Index: FileListener.java =================================================================== /* ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.vfs; /** * Listens for changes to a file. * * @author <a href="mailto:adammurdoch@;apache.org">Adam Murdoch</a> * @version $Revision: 1.1 $ $Date: 2002/10/25 03:59:09 $ */ public interface FileListener { /** * Called when a file is created. */ void fileCreated( FileChangeEvent event ); /** * Called when a file is deleted. */ void fileDeleted( FileChangeEvent event ); } 1.14 +122 -86 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/AbstractFileObject.java Index: AbstractFileObject.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/AbstractFileObject.java,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- AbstractFileObject.java 23 Oct 2002 11:59:40 -0000 1.13 +++ AbstractFileObject.java 25 Oct 2002 03:59:09 -0000 1.14 @@ -66,7 +66,6 @@ import java.security.cert.Certificate; import java.util.ArrayList; import java.util.List; -import org.apache.commons.vfs.Selectors; import org.apache.commons.vfs.FileContent; import org.apache.commons.vfs.FileName; import org.apache.commons.vfs.FileObject; @@ -75,6 +74,7 @@ import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.FileType; import org.apache.commons.vfs.NameScope; +import org.apache.commons.vfs.Selectors; /** * A partial file object implementation. @@ -433,6 +433,7 @@ { if ( fs.getParentLayer() != null ) { + // Return the parent of the parent layer return fs.getParentLayer().getParent(); } else @@ -554,7 +555,7 @@ */ private void deleteSelf() throws FileSystemException { - if ( exists() && !isWriteable() ) + if ( !isWriteable() ) { throw new FileSystemException( "vfs.provider/delete-read-only.error", name ); } @@ -574,7 +575,17 @@ } // Update cached info - updateType(); + handleDelete(); + } + + /** + * Deletes this file. + * + * @todo This will not fail if this is a non-empty folder. + */ + public void delete() throws FileSystemException + { + delete( Selectors.SELECT_SELF ); } /** @@ -603,6 +614,7 @@ // If the file is a folder, make sure all its children have been deleted if ( file.type == FileType.FOLDER && file.getChildren().length != 0 ) { + // TODO - fail?? // Skip continue; } @@ -613,13 +625,33 @@ } /** - * Creates this file, if it does not exist. Also creates any ancestor + * Creates this file, if it does not exist. + */ + public void createFile() throws FileSystemException + { + try + { + getOutputStream().close(); + endOutput(); + } + catch ( final RuntimeException re ) + { + throw re; + } + catch ( final Exception e ) + { + throw new FileSystemException( "vfs.provider/create-file.error", name, e ); + } + } + + /** + * Creates this folder, if it does not exist. Also creates any ancestor * files which do not exist. */ - public void create( FileType type ) throws FileSystemException + public void createFolder() throws FileSystemException { attach(); - if ( this.type == type ) + if ( this.type == FileType.FOLDER ) { // Already exists as correct type return; @@ -637,35 +669,25 @@ FileObject parent = getParent(); if ( parent != null ) { - parent.create( FileType.FOLDER ); + parent.createFolder(); } // Create the folder try { - if ( type == FileType.FOLDER ) - { - doCreateFolder(); - children = EMPTY_FILE_ARRAY; - } - else if ( type == FileType.FILE ) - { - OutputStream outStr = doGetOutputStream(); - outStr.close(); - endOutput(); - } + doCreateFolder(); } - catch ( RuntimeException re ) + catch ( final RuntimeException re ) { throw re; } - catch ( Exception exc ) + catch ( final Exception exc ) { - throw new FileSystemException( "vfs.provider/create.error", new Object[]{type, name}, exc ); + throw new FileSystemException( "vfs.provider/create-folder.error", name, exc ); } // Update cached info - updateType(); + handleCreate( FileType.FOLDER ); } /** @@ -713,7 +735,7 @@ } else { - destFile.create( FileType.FOLDER ); + destFile.createFolder(); } } } @@ -750,19 +772,31 @@ final FileObject destFile ) throws FileSystemException { - InputStream instr = null; - OutputStream outstr = null; try { - instr = srcFile.getContent().getInputStream(); - // Create the output stream via getContent(), to pick up the - // validation it does - outstr = destFile.getContent().getOutputStream(); - final byte[] buffer = new byte[ 1024 * 4 ]; - int n = 0; - while ( -1 != ( n = instr.read( buffer ) ) ) + final InputStream instr = srcFile.getContent().getInputStream(); + try + { + // Create the output stream via getContent(), to pick up the + // validation it does + final OutputStream outstr = destFile.getContent().getOutputStream(); + try + { + final byte[] buffer = new byte[ 1024 * 4 ]; + int n = 0; + while ( -1 != ( n = instr.read( buffer ) ) ) + { + outstr.write( buffer, 0, n ); + } + } + finally + { + outstr.close(); + } + } + finally { - outstr.write( buffer, 0, n ); + instr.close(); } } catch ( RuntimeException re ) @@ -773,31 +807,6 @@ { throw new FileSystemException( "vfs.provider/copy-file.error", new Object[]{srcFile, destFile}, exc ); } - finally - { - if ( instr != null ) - { - try - { - instr.close(); - } - catch ( final Exception exc ) - { - //ignore - } - } - if ( outstr != null ) - { - try - { - outstr.close(); - } - catch ( final Exception exc ) - { - //ignore - } - } - } } /** @@ -842,13 +851,7 @@ } // Detach from the file - if ( attached ) - { - doDetach(); - attached = false; - type = null; - children = null; - } + detach(); if ( exc != null ) { @@ -879,7 +882,7 @@ FileObject parent = getParent(); if ( parent != null ) { - parent.create( FileType.FOLDER ); + parent.createFolder(); } } @@ -888,10 +891,6 @@ { return doGetOutputStream(); } - catch ( FileSystemException exc ) - { - throw exc; - } catch ( RuntimeException re ) { throw re; @@ -903,6 +902,21 @@ } /** + * Detaches this file, invaliating all cached info. This will force + * a call to {@link #doAttach} next time this file is used. + */ + protected void detach() + { + if ( attached ) + { + doDetach(); + attached = false; + type = null; + children = null; + } + } + + /** * Attaches to the file. */ private void attach() throws FileSystemException @@ -919,10 +933,6 @@ attached = true; type = doGetType(); } - catch ( FileSystemException exc ) - { - throw exc; - } catch ( RuntimeException re ) { throw re; @@ -931,31 +941,56 @@ { throw new FileSystemException( "vfs.provider/get-type.error", new Object[]{name}, exc ); } - } /** * Called when the ouput stream for this file is closed. */ - public void endOutput() throws Exception + protected void endOutput() throws Exception { - updateType(); + boolean newFile = ( type == null ); + doEndOutput(); + + if ( newFile ) + { + // File was created + handleCreate( FileType.FILE ); + } } /** - * Update cached info when this file's type changes. + * Called when this file is created. Updates cached info and notifies + * the parent and file system. */ - private void updateType() + private void handleCreate( final FileType newType ) { + // Fix up state + type = newType; + children = EMPTY_FILE_ARRAY; + // Notify parent that its child list may no longer be valid notifyParent(); - // Detach - doDetach(); - attached = false; + // Notify the file system + fs.fireFileCreated( this ); + } + + /** + * Called when this file is deleted. Updates cached info and notifies + * subclasses, parent and file system. + */ + private void handleDelete() + { + // Fix up state type = null; children = null; + + // Notify parent that its child list may no longer be valid + notifyParent(); + + // Notify the file system + fs.fireFileDeleted( this ); } /** @@ -978,6 +1013,7 @@ /** * Notifies a file that children have been created or deleted. + * @todo Indicate whether the child was added or removed, and which child. */ private void invalidateChildren() { @@ -1014,10 +1050,10 @@ /** * Traverses a file. */ - private void traverse( final DefaultFileSelectorInfo fileInfo, - final FileSelector selector, - final boolean depthwise, - final List selected ) + private static void traverse( final DefaultFileSelectorInfo fileInfo, + final FileSelector selector, + final boolean depthwise, + final List selected ) throws Exception { // Check the file itself 1.11 +72 -2 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/AbstractFileSystem.java Index: AbstractFileSystem.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/AbstractFileSystem.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- AbstractFileSystem.java 23 Oct 2002 11:59:40 -0000 1.10 +++ AbstractFileSystem.java 25 Oct 2002 03:59:09 -0000 1.11 @@ -57,10 +57,13 @@ import java.util.HashMap; import java.util.Map; +import java.util.ArrayList; import org.apache.commons.vfs.FileName; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.FileSystem; +import org.apache.commons.vfs.FileListener; +import org.apache.commons.vfs.FileChangeEvent; /** * A partial {@link org.apache.commons.vfs.FileSystem} implementation. @@ -79,6 +82,9 @@ /** Map from FileName to FileObject. */ private final Map files = new HashMap(); + /** Map from FileName to an ArrayList of listeners for that file. */ + private final Map listenerMap = new HashMap(); + protected AbstractFileSystem( final FileName rootName, final FileObject parentLayer ) { @@ -119,7 +125,7 @@ * Retrieves the attribute with the specified name. The default * implementation simply throws an exception. */ - public Object getAttribute( String attrName ) throws FileSystemException + public Object getAttribute( final String attrName ) throws FileSystemException { throw new FileSystemException( "vfs.provider/get-attribute-not-supported.error" ); } @@ -128,7 +134,7 @@ * Sets the attribute with the specified name. The default * implementation simply throws an exception. */ - public void setAttribute( String attrName, Object value ) + public void setAttribute( final String attrName, final Object value ) throws FileSystemException { throw new FileSystemException( "vfs.provider/set-attribute-not-supported.error" ); @@ -177,5 +183,69 @@ files.put( name, file ); } return file; + } + + /** + * Adds a listener on a file in this file system. + */ + public void addListener( final FileObject file, + final FileListener listener ) + { + ArrayList listeners = (ArrayList)listenerMap.get( file.getName() ); + if ( listeners == null ) + { + listeners = new ArrayList(); + listenerMap.put( file.getName(), listeners ); + } + listeners.add( listener ); + } + + /** + * Removes a listener from a file in this file system. + */ + public void removeListener( final FileObject file, + final FileListener listener ) + { + final ArrayList listeners = (ArrayList)listenerMap.get( file.getName() ); + if ( listeners != null ) + { + listeners.remove( listener ); + } + } + + /** + * Fires a file create event. + */ + protected void fireFileCreated( final FileObject file ) + { + final FileChangeEvent event = new FileChangeEvent( file ); + final ArrayList listeners = (ArrayList)listenerMap.get( file.getName() ); + if ( listeners != null ) + { + final int count = listeners.size(); + for ( int i = 0; i < count; i++ ) + { + final FileListener listener = (FileListener)listeners.get( i ); + listener.fileCreated( event ); + } + } + } + + /** + * Fires a file delete event. + */ + protected void fireFileDeleted( final FileObject file ) + { + final FileChangeEvent event = new FileChangeEvent( file ); + final ArrayList listeners = (ArrayList)listenerMap.get( file.getName() ); + if ( listeners != null ) + { + final int count = listeners.size(); + for ( int i = 0; i < count; i++ ) + { + final FileListener listener = (FileListener)listeners.get( i ); + listener.fileDeleted( event ); + } + } } } 1.8 +4 -0 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java Index: FtpFileObject.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- FtpFileObject.java 23 Oct 2002 11:59:41 -0000 1.7 +++ FtpFileObject.java 25 Oct 2002 03:59:09 -0000 1.8 @@ -218,6 +218,8 @@ { throw new FileSystemException( "vfs.provider.ftp/delete-file.error", getName() ); } + fileInfo = null; + children = EMPTY_FTP_FILE_ARRAY; } /** @@ -230,6 +232,7 @@ { throw new FileSystemException( "vfs.provider.ftp/create-folder.error", getName() ); } + detach(); } /** @@ -279,5 +282,6 @@ { throw new FileSystemException( "vfs.provider.ftp/finish-put.error", getName() ); } + detach(); } } 1.4 +2 -2 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/tasks/AbstractSyncTask.java Index: AbstractSyncTask.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/tasks/AbstractSyncTask.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- AbstractSyncTask.java 24 Oct 2002 02:11:03 -0000 1.3 +++ AbstractSyncTask.java 25 Oct 2002 03:59:10 -0000 1.4 @@ -191,7 +191,7 @@ { // Locate the destination folder, and make sure it exists final FileObject destFolder = resolveFile( destDirUrl ); - destFolder.create( FileType.FOLDER ); + destFolder.createFolder(); // Locate the source files, and make sure they exist final ArrayList srcs = new ArrayList(); 1.2 +4 -2 jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/tasks/MkdirTask.java Index: MkdirTask.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/tasks/MkdirTask.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- MkdirTask.java 24 Oct 2002 02:11:03 -0000 1.1 +++ MkdirTask.java 25 Oct 2002 03:59:10 -0000 1.2 @@ -95,7 +95,9 @@ try { final FileObject dir = resolveFile( dirName ); - dir.create( FileType.FOLDER ); + final String message = Messages.getString( "vfs.tasks/mkdir.create-folder.info", dir ); + log( message ); + dir.createFolder(); } catch ( final FileSystemException e ) { 1.4 +150 -20 jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/test/AbstractWritableFileSystemTestCase.java Index: AbstractWritableFileSystemTestCase.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/test/AbstractWritableFileSystemTestCase.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- AbstractWritableFileSystemTestCase.java 23 Oct 2002 11:59:39 -0000 1.3 +++ AbstractWritableFileSystemTestCase.java 25 Oct 2002 03:59:10 -0000 1.4 @@ -58,10 +58,14 @@ import java.io.OutputStream; import java.util.HashSet; import java.util.Set; +import java.util.ArrayList; import org.apache.commons.vfs.Selectors; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.FileType; +import org.apache.commons.vfs.FileSystem; +import org.apache.commons.vfs.FileListener; +import org.apache.commons.vfs.FileChangeEvent; /** * File system test that check that a file system can be modified. @@ -90,7 +94,7 @@ // Make sure the test folder is empty scratchFolder.delete( Selectors.EXCLUDE_SELF ); - scratchFolder.create( FileType.FOLDER ); + scratchFolder.createFolder(); return scratchFolder; } @@ -105,7 +109,7 @@ // Create direct child of the test folder FileObject folder = scratchFolder.resolveFile( "dir1" ); assertTrue( !folder.exists() ); - folder.create( FileType.FOLDER ); + folder.createFolder(); assertTrue( folder.exists() ); assertSame( FileType.FOLDER, folder.getType() ); assertEquals( 0, folder.getChildren().length ); @@ -115,7 +119,7 @@ assertTrue( !folder.exists() ); assertTrue( !folder.getParent().exists() ); assertTrue( !folder.getParent().getParent().exists() ); - folder.create( FileType.FOLDER ); + folder.createFolder(); assertTrue( folder.exists() ); assertSame( FileType.FOLDER, folder.getType() ); assertEquals( 0, folder.getChildren().length ); @@ -124,7 +128,7 @@ // Test creating a folder that already exists assertTrue( folder.exists() ); - folder.create( FileType.FOLDER ); + folder.createFolder(); } /** @@ -137,7 +141,7 @@ // Create direct child of the test folder FileObject file = scratchFolder.resolveFile( "file1.txt" ); assertTrue( !file.exists() ); - file.create( FileType.FILE ); + file.createFile(); assertTrue( file.exists() ); assertSame( FileType.FILE, file.getType() ); assertEquals( 0, file.getContent().getSize() ); @@ -147,7 +151,7 @@ assertTrue( !file.exists() ); assertTrue( !file.getParent().exists() ); assertTrue( !file.getParent().getParent().exists() ); - file.create( FileType.FILE ); + file.createFile(); assertTrue( file.exists() ); assertSame( FileType.FILE, file.getType() ); assertEquals( 0, file.getContent().getSize() ); @@ -156,7 +160,7 @@ // Test creating a file that already exists assertTrue( file.exists() ); - file.create( FileType.FILE ); + file.createFile(); } /** @@ -168,17 +172,17 @@ // Create a test file and folder FileObject file = scratchFolder.resolveFile( "dir1/file1.txt" ); - file.create( FileType.FILE ); + file.createFile(); assertEquals( FileType.FILE, file.getType() ); FileObject folder = scratchFolder.resolveFile( "dir1/dir2" ); - folder.create( FileType.FOLDER ); + folder.createFolder(); assertEquals( FileType.FOLDER, folder.getType() ); // Attempt to create a file that already exists as a folder try { - folder.create( FileType.FILE ); + folder.createFile(); fail(); } catch( FileSystemException exc ) @@ -188,7 +192,7 @@ // Attempt to create a folder that already exists as a file try { - file.create( FileType.FOLDER ); + file.createFolder(); fail(); } catch( FileSystemException exc ) @@ -199,7 +203,7 @@ FileObject folder2 = file.resolveFile( "some-child" ); try { - folder2.create( FileType.FOLDER ); + folder2.createFolder(); fail(); } catch( FileSystemException exc ) @@ -214,10 +218,10 @@ { // Set-up the test structure FileObject folder = createScratchFolder(); - folder.resolveFile( "file1.txt" ).create( FileType.FILE ); - folder.resolveFile( "emptydir" ).create( FileType.FOLDER ); - folder.resolveFile( "dir1/file1.txt" ).create( FileType.FILE ); - folder.resolveFile( "dir1/dir2/file2.txt" ).create( FileType.FILE ); + folder.resolveFile( "file1.txt" ).createFile(); + folder.resolveFile( "emptydir" ).createFolder(); + folder.resolveFile( "dir1/file1.txt" ).createFile(); + folder.resolveFile( "dir1/dir2/file2.txt" ).createFile(); // Delete a file FileObject file = folder.resolveFile( "file1.txt" ); @@ -259,17 +263,17 @@ assertEquals( 0, folder.getChildren().length ); // Create a child folder - folder.resolveFile( "dir1" ).create( FileType.FOLDER ); + folder.resolveFile( "dir1" ).createFolder(); names.add( "dir1" ); assertSameFileSet( names, folder.getChildren() ); // Create a child file - folder.resolveFile( "file1.html" ).create( FileType.FILE ); + folder.resolveFile( "file1.html" ).createFile(); names.add( "file1.html" ); assertSameFileSet( names, folder.getChildren() ); // Create a descendent - folder.resolveFile( "dir2/file1.txt" ).create( FileType.FILE ); + folder.resolveFile( "dir2/file1.txt" ).createFile(); names.add( "dir2" ); assertSameFileSet( names, folder.getChildren() ); @@ -291,11 +295,71 @@ // Recreate the folder folder.delete( Selectors.SELECT_ALL ); - folder.create( FileType.FOLDER ); + folder.createFolder(); assertEquals( 0, folder.getChildren().length ); } /** + * Check listeners are notified of changes. + */ + public void testListener() throws Exception + { + final FileObject baseFile = createScratchFolder(); + + FileObject child = baseFile.resolveFile( "newfile.txt" ); + assertTrue( !child.exists() ); + + FileSystem fs = baseFile.getFileSystem(); + TestListener listener = new TestListener( child ); + fs.addListener( child, listener ); + + // Create as a folder + listener.addCreateEvent(); + child.createFolder(); + listener.assertFinished(); + + // Create the folder again. Should not get an event. + child.createFolder(); + + // Delete + listener.addDeleteEvent(); + child.delete(); + listener.assertFinished(); + + // Delete again. Should not get an event + child.delete(); + + // Create as a file + listener.addCreateEvent(); + child.createFile(); + listener.assertFinished(); + + // Create the file again. Should not get an event + child.createFile(); + + listener.addDeleteEvent(); + child.delete(); + + // Create as a file, by writing to it. + listener.addCreateEvent(); + child.getContent().getOutputStream().close(); + listener.assertFinished(); + + // Recreate the file by writing to it + child.getContent().getOutputStream().close(); + + // Copy another file over the top + final FileObject otherChild = baseFile.resolveFile( "folder1" ); + otherChild.createFolder(); + listener.addDeleteEvent(); + listener.addCreateEvent(); + child.copyFrom( otherChild, Selectors.SELECT_SELF ); + listener.assertFinished(); + + fs.removeListener( child, listener ); + } + + /** * Ensures the names of a set of files match an expected set. */ private void assertSameFileSet( Set names, FileObject[] files ) @@ -308,6 +372,72 @@ { FileObject file = files[ i ]; assertTrue( names.contains( file.getName().getBaseName() ) ); + } + } + + /** + * A test listener. + */ + private static class TestListener + implements FileListener + { + private final FileObject file; + private final ArrayList events = new ArrayList(); + private static final Object CREATE = "create"; + private static final Object DELETE = "delete"; + + public TestListener( final FileObject file ) + { + this.file = file; + } + + /** + * Called when a file is created. + */ + public void fileCreated( final FileChangeEvent event ) + { + assertTrue( events.size() > 0 && events.remove( 0 ) == CREATE ); + assertSame( file, event.getFile() ); + try + { + assertTrue( file.exists() ); + } + catch ( FileSystemException e ) + { + fail(); + } + } + + /** + * Called when a file is deleted. + */ + public void fileDeleted( final FileChangeEvent event ) + { + assertTrue( events.size() > 0 && events.remove( 0 ) == DELETE ); + assertSame( file, event.getFile() ); + try + { + assertTrue( !file.exists() ); + } + catch ( FileSystemException e ) + { + fail(); + } + } + + public void addCreateEvent() + { + events.add( CREATE ); + } + + public void addDeleteEvent() + { + events.add( DELETE ); + } + + public void assertFinished() + { + assertEquals( "Missing event", 0, events.size() ); } } }
-- To unsubscribe, e-mail: <mailto:commons-dev-unsubscribe@;jakarta.apache.org> For additional commands, e-mail: <mailto:commons-dev-help@;jakarta.apache.org>