You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by ad...@apache.org on 2002/10/25 05:59:10 UTC

cvs commit: jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/test AbstractWritableFileSystemTestCase.java

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 apache@apache.org.
   *
   * 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 apache@apache.org.
   *
   * 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:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>