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 2003/02/13 05:28:46 UTC

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

adammurdoch    2003/02/12 20:28:46

  Modified:    vfs/src/java/org/apache/commons/vfs FileContent.java
                        Resources.properties
               vfs/src/java/org/apache/commons/vfs/impl
                        VirtualFileSystem.java
               vfs/src/java/org/apache/commons/vfs/provider
                        AbstractFileObject.java DefaultFileContent.java
                        DelegateFileObject.java
               vfs/src/java/org/apache/commons/vfs/provider/ftp
                        FtpFileObject.java
               vfs/src/test/org/apache/commons/vfs/provider/test
                        JunctionTests.java
               vfs/src/test/org/apache/commons/vfs/test ContentTests.java
                        ProviderWriteTests.java
  Added:       vfs/src/java/org/apache/commons/vfs/util
                        MonitorInputStream.java MonitorOutputStream.java
  Log:
  - FileContent now allows multiple readers.
  - Tidied-up the interface between AbstractFileObject and its subclasses:
    - Added onChildrenChanged() and onChange() to deal with way-too-overloaded
      meaning of onDetach().
    - Replaced invalidateChildren() with childrenChanged().
    - All doBlah() methods now throw Exception, rather than a mix of exceptions.
    - Axed doInputEnd() and doOutputEnd().
  
  Revision  Changes    Path
  1.7       +8 -7      jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/FileContent.java
  
  Index: FileContent.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/FileContent.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- FileContent.java	12 Feb 2003 07:56:09 -0000	1.6
  +++ FileContent.java	13 Feb 2003 04:28:45 -0000	1.7
  @@ -62,15 +62,16 @@
   /**
    * Represents the data content of a file.
    *
  - * <p>To read from a file, use the {@link #getInputStream} method.
  + * <p>To read from a file, use the <code>InputStream</code> returned by
  + * {@link #getInputStream}.
    *
  - * <p>To write to a file, use the {@link #getOutputStream} method.  This
  - * method will create the file and the parent folder, if necessary.
  + * <p>To write to a file, use the <code>OutputStream</code> returned by
  + * {@link #getOutputStream} method.  This will create the file, and the parent
  + * folder, if necessary.
    *
  - * <p>To prevent concurrency problems, only a single <code>InputStream</code>,
  - * or <code>OutputStream</code> may be open at any time, for each file.
  - *
  - * <p>TODO - allow multiple input streams?
  + * <p>To prevent concurrency problems, a file may not have an OutputStream and
  + * an InputStream open at the same time.  A file may have multiple InputStreams
  + * open at the sametime.
    *
    * @see FileObject#getContent
    *
  
  
  
  1.15      +9 -3      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.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- Resources.properties	25 Nov 2002 05:30:59 -0000	1.14
  +++ Resources.properties	13 Feb 2003 04:28:45 -0000	1.15
  @@ -22,7 +22,6 @@
   vfs.provider/create-file.error=Could not create file "{0}".
   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.
   vfs.provider/write.error=Could not write to "{0}".
   vfs.provider/copy-file.error=Could not copy "{0}" to "{1}".
   vfs.provider/copy-read-only.error=Could not copy {0} "{1}" to "{2}" because the destination file is read-only.
  @@ -31,6 +30,7 @@
   vfs.provider/check-is-writeable.error=Could not determine if file "{0}" is writeable.
   vfs.provider/check-is-readable.error=Could not determine if file "{0}" is readable.
   vfs.provider/get-url.error=Could not create URL for "{0}".
  +vfs.provider/close.error=Could not close "{0}".
   
   # DefaultFileContent
   vfs.provider/get-size-folder.error=Could not determine the size of "{0}" because it is a folder.
  @@ -39,13 +39,15 @@
   vfs.provider/get-size.error=Could not determine the size of file "{0}".
   vfs.provider/read-folder.error=Could not read from "{0}" because it is a folder.
   vfs.provider/read-no-exist.error=Could not read file "{0}" because it does not exist.
  -vfs.provider/read-in-use.error=Could not read file "{0}" because it is already being used.
  +vfs.provider/read-in-use.error=Could not read file "{0}" because it is currently being written to.
   vfs.provider/read.error=Could not read file "{0}".
  +vfs.provider/write-in-use.error=Could not write to "{0}" because it is currently in use.
   vfs.provider/get-last-modified-no-exist.error=Could not determine the last modified timestamp of "{0}" because it does not exist.
   vfs.provider/get-last-modified.error=Could not determine the last modified timestamp of "{0}".
   vfs.provider/set-last-modified-no-exist.error=Could not set the last modified timestamp of "{0}" because it does not exist.
   vfs.provider/set-last-modified.error=Could not set the last modified timestamp of "{0}".
  -vfs.provider/get-certificates-no-exist.error=Could not retrive the certificates of "{0}" because it does not exist.
  +vfs.provider/get-certificates-no-exist.error=Could not retrieve the certificates of "{0}" because it does not exist.
  +vfs.provider/get-certificates.error=Could not retrieve the certificates of "{0}".
   vfs.provider/close-instr.error=Could not close the input stream for file "{0}".
   vfs.provider/close-outstr.error=Could not close the output stream for file "{0}".
   vfs.provider/get-attribute.error=Could not get attribute "{0}" of "{1}".
  @@ -89,6 +91,10 @@
   vfs.impl/pkg-sealing-unsealed=Trying to seal package "{0}" that exists as unsealed.
   vfs.impl/pkg-sealed-other-url=Package "{0}" exists and is sealed with other URL.
   
  +# VirtualFileSystem
  +vfs.impl/nested-junction.error=Attempting to create a nested junction at "{0}".  Nested junctions are not supported.
  +vfs.impl/create-junction.error=Could not create a junction at "{0}".
  +r
   # Local Provider
   vfs.provider.local/get-type.error=Could not determine the type of "{0}".
   vfs.provider.local/delete-file.error=Could not delete "{0}".
  
  
  
  1.6       +29 -22    jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/impl/VirtualFileSystem.java
  
  Index: VirtualFileSystem.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/impl/VirtualFileSystem.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- VirtualFileSystem.java	12 Feb 2003 07:56:10 -0000	1.5
  +++ VirtualFileSystem.java	13 Feb 2003 04:28:45 -0000	1.6
  @@ -142,33 +142,40 @@
           // Check for nested junction - these are not supported yet
           if ( getJunctionForFile( junctionName ) != null )
           {
  -            throw new FileSystemException( "impl/nested-junction.error", junctionName );
  +            throw new FileSystemException( "vfs.impl/nested-junction.error", junctionName );
           }
   
  -        // Add to junction table
  -        junctions.put( junctionName, targetFile );
  -
  -        // Create ancestors of junction point
  -        FileName childName = junctionName;
  -        boolean done = false;
  -        for ( FileName parentName = childName.getParent();
  -              !done && parentName != null;
  -              childName = parentName, parentName = parentName.getParent() )
  +        try
           {
  -            DelegateFileObject file = (DelegateFileObject)getFile( parentName );
  -            if ( file == null )
  -            {
  -                file = new DelegateFileObject( parentName, this, null );
  -                putFile( file );
  -            }
  -            else
  +            // Add to junction table
  +            junctions.put( junctionName, targetFile );
  +
  +            // Create ancestors of junction point
  +            FileName childName = junctionName;
  +            boolean done = false;
  +            for ( FileName parentName = childName.getParent();
  +                  !done && parentName != null;
  +                  childName = parentName, parentName = parentName.getParent() )
               {
  -                done = file.exists();
  +                DelegateFileObject file = (DelegateFileObject)getFile( parentName );
  +                if ( file == null )
  +                {
  +                    file = new DelegateFileObject( parentName, this, null );
  +                    putFile( file );
  +                }
  +                else
  +                {
  +                    done = file.exists();
  +                }
  +                file.attachChild( childName.getBaseName() );
               }
  -            file.attachChild( childName.getBaseName() );
  -        }
   
  -        // TODO - attach all cached children of the junction point to their real file
  +            // TODO - attach all cached children of the junction point to their real file
  +        }
  +        catch ( final Exception e )
  +        {
  +            throw new FileSystemException( "vfs.impl/create-junction.error", junctionName );
  +        }
       }
   
       /**
  
  
  
  1.24      +92 -63    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.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- AbstractFileObject.java	12 Feb 2003 07:56:12 -0000	1.23
  +++ AbstractFileObject.java	13 Feb 2003 04:28:45 -0000	1.24
  @@ -110,6 +110,8 @@
        * Attaches this file object to its file resource.  This method is called
        * before any of the doBlah() or onBlah() methods.  Sub-classes can use
        * this method to perform lazy initialisation.
  +     *
  +     * This implementation does nothing.
        */
       protected void doAttach() throws Exception
       {
  @@ -118,10 +120,12 @@
       /**
        * Detaches this file object from its file resource.
        *
  -     * <p>Called when this file is closed, or its type changes.  Note that
  -     * the file object may be reused later, so should be able to be reattached.
  +     * <p>Called when this file is closed.  Note that the file object may be
  +     * reused later, so should be able to be reattached.
  +     *
  +     * This implementation does nothing.
        */
  -    protected void doDetach() throws FileSystemException
  +    protected void doDetach() throws Exception
       {
       }
   
  @@ -134,7 +138,9 @@
   
       /**
        * Determines if this file can be read.  Is only called if {@link #doGetType}
  -     * does not return null. This implementation always returns true.
  +     * does not return null.
  +     *
  +     * This implementation always returns true.
        */
       protected boolean doIsReadable() throws Exception
       {
  @@ -143,8 +149,9 @@
   
       /**
        * Determines if this file can be written to.  Is only called if
  -     * {@link #doGetType} does not return null.  This implementation always
  -     * returns true.
  +     * {@link #doGetType} does not return null.
  +     *
  +     * This implementation always returns true.
        */
       protected boolean doIsWriteable() throws Exception
       {
  @@ -165,6 +172,8 @@
        * <li>{@link #doIsWriteable} returns true.
        * <li>This file has no children, if a folder.
        * </ul>
  +     *
  +     * This implementation throws an exception.
        */
       protected void doDelete() throws Exception
       {
  @@ -178,6 +187,8 @@
        * <li>The parent folder exists and is writeable, or this file is the
        *     root of the file system.
        * </ul>
  +     *
  +     * This implementation throws an exception.
        */
       protected void doCreateFolder() throws Exception
       {
  @@ -185,16 +196,29 @@
       }
   
       /**
  -     * Called when the children of this file change.
  +     * Called when the children of this file change.  Allows subclasses to
  +     * refresh any cached information about the children of this file.
  +     *
  +     * This implementation does nothing.
  +     */
  +    protected void onChildrenChanged() throws Exception
  +    {
  +    }
  +
  +    /**
  +     * Called when the type or content of this file changes.
  +     *
  +     * This implementation does nothing.
        */
  -    protected void onChildrenChanged()
  +    protected void onChange() throws Exception
       {
       }
   
       /**
        * Returns the last modified time of this file.  Is only called if
  -     * {@link #doGetType} does not return null. This implementation throws
  -     * an exception.
  +     * {@link #doGetType} does not return null.
  +     *
  +     * This implementation throws an exception.
        */
       protected long doGetLastModifiedTime() throws Exception
       {
  @@ -203,10 +227,11 @@
   
       /**
        * Sets the last modified time of this file.  Is only called if
  -     * {@link #doGetType} does not return null.  This implementation
  -     * throws an exception.
  +     * {@link #doGetType} does not return null.
  +     *
  +     * This implementation throws an exception.
        */
  -    protected void doSetLastModifiedTime( long modtime )
  +    protected void doSetLastModifiedTime( final long modtime )
           throws Exception
       {
           throw new FileSystemException( "vfs.provider/set-last-modified-not-supported.error" );
  @@ -214,7 +239,9 @@
   
       /**
        * Gets an attribute of this file.  Is only called if {@link #doGetType}
  -     * does not return null.  This implementation return null.
  +     * does not return null.
  +     *
  +     * This implementation always returns null.
        */
       protected Object doGetAttribute( final String attrName )
           throws Exception
  @@ -224,9 +251,11 @@
   
       /**
        * Sets an attribute of this file.  Is only called if {@link #doGetType}
  -     * does not return null.  This implementation throws an exception.
  +     * does not return null.
  +     *
  +     * This implementation throws an exception.
        */
  -    protected void doSetAttribute( String atttrName, Object value )
  +    protected void doSetAttribute( final String atttrName, final Object value )
           throws Exception
       {
           throw new FileSystemException( "vfs.provider/set-attribute-not-supported.error" );
  @@ -234,10 +263,11 @@
   
       /**
        * Returns the certificates used to sign this file.  Is only called if
  -     * {@link #doGetType} does not return null.  This implementation returns
  -     * null.
  +     * {@link #doGetType} does not return null.
  +     *
  +     * This implementation always returns null.
        */
  -    protected Certificate[] doGetCertificates() throws FileSystemException
  +    protected Certificate[] doGetCertificates() throws Exception
       {
           return null;
       }
  @@ -252,8 +282,8 @@
        * Creates an input stream to read the file content from.  Is only called
        * if {@link #doGetType} returns {@link FileType#FILE}.
        *
  -     * <p>There is guaranteed never to be more than one stream for this file
  -     * (input or output) open at any given time.
  +     * <p>It is guaranteed that there are no open output streams for this file
  +     * when this method is called.
        *
        * <p>The returned stream does not have to be buffered.
        */
  @@ -269,10 +299,12 @@
        * and is a folder.
        * </ul>
        *
  -     * <p>There is guaranteed never to be more than one stream for this file
  -     * (input or output) open at any given time.
  +     * <p>It is guaranteed that there are no open stream (input or output) for
  +     * this file when this method is called.
        *
        * <p>The returned stream does not have to be buffered.
  +     *
  +     * This implementation throws an exception.
        */
       protected OutputStream doGetOutputStream() throws Exception
       {
  @@ -280,22 +312,6 @@
       }
   
       /**
  -     * Notification of the output stream being closed.
  -     * TODO - get rid of this.
  -     */
  -    protected void doEndOutput() throws Exception
  -    {
  -    }
  -
  -    /**
  -     * Notification of the input stream being closed.
  -     * TODO - get rid of this.
  -     */
  -    protected void doEndInput() throws Exception
  -    {
  -    }
  -
  -    /**
        * Returns the URI of the file.
        */
       public String toString()
  @@ -552,22 +568,22 @@
               throw new FileSystemException( "vfs.provider/delete-read-only.error", name );
           }
   
  -        // Delete the file
           try
           {
  +            // Delete the file
               doDelete();
  +
  +            // Update cached info
  +            handleDelete();
           }
  -        catch ( RuntimeException re )
  +        catch ( final RuntimeException re )
           {
               throw re;
           }
  -        catch ( Exception exc )
  +        catch ( final Exception exc )
           {
               throw new FileSystemException( "vfs.provider/delete.error", new Object[]{name}, exc );
           }
  -
  -        // Update cached info
  -        handleDelete();
       }
   
       /**
  @@ -664,10 +680,13 @@
               parent.createFolder();
           }
   
  -        // Create the folder
           try
           {
  +            // Create the folder
               doCreateFolder();
  +
  +            // Update cached info
  +            handleCreate( FileType.FOLDER );
           }
           catch ( final RuntimeException re )
           {
  @@ -677,9 +696,6 @@
           {
               throw new FileSystemException( "vfs.provider/create-folder.error", name, exc );
           }
  -
  -        // Update cached info
  -        handleCreate( FileType.FOLDER );
       }
   
       /**
  @@ -829,7 +845,14 @@
           }
   
           // Detach from the file
  -        detach();
  +        try
  +        {
  +            detach();
  +        }
  +        catch ( final Exception e )
  +        {
  +            exc = new FileSystemException( "vfs.provider/close.error", name, e );
  +        }
   
           if ( exc != null )
           {
  @@ -883,7 +906,7 @@
        * Detaches this file, invaliating all cached info.  This will force
        * a call to {@link #doAttach} next time this file is used.
        */
  -    protected void detach() throws FileSystemException
  +    private void detach() throws Exception
       {
           if ( attached )
           {
  @@ -932,22 +955,23 @@
        */
       protected void endOutput() throws Exception
       {
  -        boolean newFile = ( type == null );
  -
  -        doEndOutput();
  -
  -        if ( newFile )
  +        if ( type == null )
           {
               // File was created
               handleCreate( FileType.FILE );
           }
  +        else
  +        {
  +            // File has changed
  +            onChange();
  +        }
       }
   
       /**
        * Called when this file is created.  Updates cached info and notifies
        * the parent and file system.
        */
  -    protected void handleCreate( final FileType newType )
  +    protected void handleCreate( final FileType newType ) throws Exception
       {
           // Fix up state
           type = newType;
  @@ -956,6 +980,9 @@
           // Notify parent that its child list may no longer be valid
           notifyParent();
   
  +        // Notify subclass
  +        onChange();
  +
           // Notify the file system
           fs.fireFileCreated( this );
       }
  @@ -964,7 +991,7 @@
        * Called when this file is deleted.  Updates cached info and notifies
        * subclasses, parent and file system.
        */
  -    protected void handleDelete()
  +    protected void handleDelete() throws Exception
       {
           // Fix up state
           type = null;
  @@ -973,6 +1000,9 @@
           // Notify parent that its child list may no longer be valid
           notifyParent();
   
  +        // Notify subclass
  +        onChange();
  +
           // Notify the file system
           fs.fireFileDeleted( this );
       }
  @@ -981,7 +1011,7 @@
        * Notify the parent of a change to its children, when a child is created
        * or deleted.
        */
  -    private void notifyParent()
  +    private void notifyParent() throws Exception
       {
           if ( parent == null )
           {
  @@ -991,15 +1021,15 @@
   
           if ( parent != null )
           {
  -            parent.invalidateChildren();
  +            parent.childrenChanged();
           }
       }
   
       /**
  -     * Notifies a file that children have been created or deleted.
  +     * Notifies the file that its children have changed.
        * @todo Indicate whether the child was added or removed, and which child.
        */
  -    private void invalidateChildren()
  +    protected void childrenChanged() throws Exception
       {
           children = null;
           onChildrenChanged();
  @@ -1078,5 +1108,4 @@
               }
           }
       }
  -
   }
  
  
  
  1.12      +55 -103   jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/DefaultFileContent.java
  
  Index: DefaultFileContent.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/DefaultFileContent.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- DefaultFileContent.java	12 Feb 2003 07:56:13 -0000	1.11
  +++ DefaultFileContent.java	13 Feb 2003 04:28:45 -0000	1.12
  @@ -55,15 +55,16 @@
    */
   package org.apache.commons.vfs.provider;
   
  -import java.io.BufferedInputStream;
  -import java.io.BufferedOutputStream;
   import java.io.IOException;
   import java.io.InputStream;
   import java.io.OutputStream;
   import java.security.cert.Certificate;
  +import java.util.ArrayList;
   import org.apache.commons.vfs.FileContent;
   import org.apache.commons.vfs.FileObject;
   import org.apache.commons.vfs.FileSystemException;
  +import org.apache.commons.vfs.util.MonitorInputStream;
  +import org.apache.commons.vfs.util.MonitorOutputStream;
   
   /**
    * The content of a file.
  @@ -80,7 +81,7 @@
   
       private final AbstractFileObject file;
       private int state = STATE_NONE;
  -    private FileContentInputStream instr;
  +    private final ArrayList instrs = new ArrayList();
       private FileContentOutputStream outstr;
   
       public DefaultFileContent( final AbstractFileObject file )
  @@ -89,7 +90,7 @@
       }
   
       /**
  -     * Returns the file which this is the content of.
  +     * Returns the file that this is the content of.
        */
       public FileObject getFile()
       {
  @@ -206,7 +207,15 @@
           {
               throw new FileSystemException( "vfs.provider/get-certificates-no-exist.error", file );
           }
  -        return file.doGetCertificates();
  +
  +        try
  +        {
  +            return file.doGetCertificates();
  +        }
  +        catch ( final Exception e )
  +        {
  +            throw new FileSystemException( "vfs.provider/get-certificates.error", file, e );
  +        }
       }
   
       /**
  @@ -222,26 +231,26 @@
           {
               throw new FileSystemException( "vfs.provider/read-no-exist.error", file );
           }
  -        if ( state != STATE_NONE )
  +        if ( state == STATE_WRITING )
           {
               throw new FileSystemException( "vfs.provider/read-in-use.error", file );
           }
   
           // Get the raw input stream
  -        InputStream instr;
  +        InputStream rawInstr;
           try
           {
  -            instr = file.doGetInputStream();
  +            rawInstr = file.doGetInputStream();
           }
  -        catch ( Exception exc )
  +        catch ( final Exception exc )
           {
               throw new FileSystemException( "vfs.provider/read.error", new Object[]{file}, exc );
           }
   
  -        // TODO - reuse
  -        this.instr = new FileContentInputStream( instr );
  +        final FileContentInputStream instr = new FileContentInputStream( rawInstr );
  +        this.instrs.add( instr );
           state = STATE_READING;
  -        return this.instr;
  +        return instr;
       }
   
       /**
  @@ -262,7 +271,6 @@
           OutputStream outstr = file.getOutputStream();
   
           // Create wrapper
  -        // TODO - reuse
           this.outstr = new FileContentOutputStream( outstr );
           state = STATE_WRITING;
           return this.outstr;
  @@ -277,8 +285,9 @@
           try
           {
               // Close the input stream
  -            if ( instr != null )
  +            while ( instrs.size() > 0 )
               {
  +                final FileContentInputStream instr = (FileContentInputStream)instrs.remove( 0 );
                   instr.close();
               }
   
  @@ -297,11 +306,13 @@
       /**
        * Handles the end of input stream.
        */
  -    private void endInput() throws Exception
  +    private void endInput( final FileContentInputStream instr )
       {
  -        instr = null;
  -        state = STATE_NONE;
  -        file.doEndInput();
  +        instrs.remove( instr );
  +        if ( instrs.size() == 0 )
  +        {
  +            state = STATE_NONE;
  +        }
       }
   
       /**
  @@ -318,95 +329,35 @@
        * An input stream for reading content.  Provides buffering, and
        * end-of-stream monitoring.
        */
  -    private final class FileContentInputStream extends BufferedInputStream
  +    private final class FileContentInputStream
  +        extends MonitorInputStream
       {
  -        private boolean finished;
  -
  -        FileContentInputStream( InputStream instr )
  +        FileContentInputStream( final InputStream instr )
           {
               super( instr );
           }
   
           /**
  -         * Reads a character.
  -         */
  -        public int read() throws IOException
  -        {
  -            if ( finished )
  -            {
  -                return -1;
  -            }
  -
  -            int ch = super.read();
  -            if ( ch != -1 )
  -            {
  -                return ch;
  -            }
  -
  -            // End-of-stream
  -            close();
  -            return -1;
  -        }
  -
  -        /**
  -         * Reads bytes from this input stream.error occurs.
  -         */
  -        public int read( byte[] buffer, int offset, int length )
  -            throws IOException
  -        {
  -            if ( finished )
  -            {
  -                return -1;
  -            }
  -
  -            int nread = super.read( buffer, offset, length );
  -            if ( nread != -1 )
  -            {
  -                return nread;
  -            }
  -
  -            // End-of-stream
  -            close();
  -            return -1;
  -        }
  -
  -        /**
            * Closes this input stream.
            */
           public void close() throws FileSystemException
           {
  -            if ( finished )
  -            {
  -                return;
  -            }
  -
  -            // Close the stream
  -            FileSystemException exc = null;
               try
               {
                   super.close();
               }
  -            catch ( IOException ioe )
  -            {
  -                exc = new FileSystemException( "vfs.provider/close-instr.error", file, ioe );
  -            }
  -
  -            // Notify the file object
  -            try
  -            {
  -                endInput();
  -            }
  -            catch ( final Exception e )
  +            catch ( final IOException e )
               {
  -                exc = new FileSystemException( "vfs.provider/close-instr.error", file, e );
  +                throw new FileSystemException( "vfs.provider/close-instr.error", file, e );
               }
  +        }
   
  -            finished = true;
  -
  -            if ( exc != null )
  -            {
  -                throw exc;
  -            }
  +        /**
  +         * Called after the stream has been closed.
  +         */
  +        protected void onClose() throws IOException
  +        {
  +            endInput( this );
           }
       }
   
  @@ -414,9 +365,9 @@
        * An output stream for writing content.
        */
       private final class FileContentOutputStream
  -        extends BufferedOutputStream
  +        extends MonitorOutputStream
       {
  -        FileContentOutputStream( OutputStream outstr )
  +        FileContentOutputStream( final OutputStream outstr )
           {
               super( outstr );
           }
  @@ -426,31 +377,32 @@
            */
           public void close() throws FileSystemException
           {
  -            FileSystemException exc = null;
  -
  -            // Close the output stream
               try
               {
                   super.close();
               }
  +            catch ( final FileSystemException e )
  +            {
  +                throw e;
  +            }
               catch ( final IOException e )
               {
  -                exc = new FileSystemException( "vfs.provider/close-outstr.error", file, e );
  +                throw new FileSystemException( "vfs.provider/close-outstr.error", file, e );
               }
  +        }
   
  -            // Notify of end of output
  +        /**
  +         * Called after this stream is closed.
  +         */
  +        protected void onClose() throws IOException
  +        {
               try
               {
                   endOutput();
               }
               catch ( final Exception e )
               {
  -                exc = new FileSystemException( "vfs.provider/close-outstr.error", file, e );
  -            }
  -
  -            if ( exc != null )
  -            {
  -                throw exc;
  +                throw new FileSystemException( "vfs.provider/close-outstr.error", file, e );
               }
           }
       }
  
  
  
  1.4       +8 -14     jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/DelegateFileObject.java
  
  Index: DelegateFileObject.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/provider/DelegateFileObject.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- DelegateFileObject.java	12 Feb 2003 07:56:13 -0000	1.3
  +++ DelegateFileObject.java	13 Feb 2003 04:28:45 -0000	1.4
  @@ -91,21 +91,15 @@
           this.file = file;
       }
   
  -    public void attachChild( final String baseName ) throws FileSystemException
  +    /** Adds a child to this file. */
  +    public void attachChild( final String baseName ) throws Exception
       {
           if ( children.add( baseName ) )
           {
  -            detach();
  +            childrenChanged();
           }
       }
   
  -    public void setFile( final FileObject file ) throws FileSystemException
  -    {
  -        this.file = file;
  -        children.clear();
  -        detach();
  -    }
  -
       /**
        * Attaches this file object to its file resource.
        */
  @@ -120,7 +114,7 @@
       /**
        * Detaches this file object from its file resource.
        */
  -    protected void doDetach() throws FileSystemException
  +    protected void doDetach() throws Exception
       {
           if ( file != null )
           {
  @@ -247,7 +241,7 @@
       /**
        * Called from {@link DefaultFileContent#getCertificates}.
        */
  -    protected Certificate[] doGetCertificates() throws FileSystemException
  +    protected Certificate[] doGetCertificates() throws Exception
       {
           return file.getContent().getCertificates();
       }
  @@ -288,7 +282,7 @@
       /**
        * Called when a file is created.
        */
  -    public void fileCreated( final FileChangeEvent event ) throws FileSystemException
  +    public void fileCreated( final FileChangeEvent event ) throws Exception
       {
           handleCreate( file.getType() );
       }
  @@ -296,7 +290,7 @@
       /**
        * Called when a file is deleted.
        */
  -    public void fileDeleted( final FileChangeEvent event )
  +    public void fileDeleted( final FileChangeEvent event ) throws Exception
       {
           handleDelete();
       }
  
  
  
  1.13      +89 -44    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.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- FtpFileObject.java	12 Feb 2003 07:56:15 -0000	1.12
  +++ FtpFileObject.java	13 Feb 2003 04:28:45 -0000	1.13
  @@ -64,6 +64,8 @@
   import org.apache.commons.vfs.FileSystemException;
   import org.apache.commons.vfs.FileType;
   import org.apache.commons.vfs.provider.AbstractFileObject;
  +import org.apache.commons.vfs.util.MonitorInputStream;
  +import org.apache.commons.vfs.util.MonitorOutputStream;
   
   /**
    * An FTP file.
  @@ -83,9 +85,6 @@
       private FTPFile fileInfo;
       private FTPFile[] children;
   
  -    // The client currently being used to read/write the content of this file
  -    private FTPClient client;
  -
       public FtpFileObject( final FileName name,
                             final FtpFileSystem fileSystem,
                             final FileName rootName )
  @@ -99,8 +98,14 @@
       /**
        * Called by child file objects, to locate their ftp file info.
        */
  -    private FTPFile getChildFile( final String name ) throws Exception
  +    private FTPFile getChildFile( final String name, final boolean flush )
  +        throws IOException
       {
  +        if ( flush )
  +        {
  +            children = null;
  +        }
  +
           // List the children of this file
           doGetChildren();
   
  @@ -148,13 +153,19 @@
        * Attaches this file object to its file resource.
        */
       protected void doAttach()
  -        throws Exception
  +        throws IOException
       {
           // Get the parent folder to find the info for this file
  +        getInfo( false );
  +    }
  +
  +    /** Fetches the info for this file. */
  +    private void getInfo( boolean flush ) throws IOException
  +    {
           final FtpFileObject parent = (FtpFileObject)getParent();
           if ( parent != null )
           {
  -            fileInfo = parent.getChildFile( getName().getBaseName() );
  +            fileInfo = parent.getChildFile( getName().getBaseName(), flush );
           }
           if ( fileInfo == null || !fileInfo.isDirectory() )
           {
  @@ -180,6 +191,15 @@
       }
   
       /**
  +     * Called when the type or content of this file changes.
  +     */
  +    protected void onChange() throws IOException
  +    {
  +        children = null;
  +        getInfo( true );
  +    }
  +
  +    /**
        * Determines the type of the file, returns null if the file does not
        * exist.
        */
  @@ -274,7 +294,6 @@
           {
               throw new FileSystemException( "vfs.provider.ftp/create-folder.error", getName() );
           }
  -        detach();
       }
   
       /**
  @@ -290,64 +309,90 @@
        */
       protected InputStream doGetInputStream() throws Exception
       {
  -        client = ftpFs.getClient();
  -        return client.retrieveFileStream( relPath );
  +        final FTPClient client = ftpFs.getClient();
  +        final InputStream instr = client.retrieveFileStream( relPath );
  +        return new FtpInputStream( client, instr );
       }
   
       /**
  -     * Notification of the input stream being closed.
  +     * Creates an output stream to write the file content to.
        */
  -    protected void doEndInput()
  +    protected OutputStream doGetOutputStream()
           throws Exception
       {
  -        final boolean ok;
  -        try
  -        {
  -            ok = client.completePendingCommand();
  -        }
  -        finally
  +        final FTPClient client = ftpFs.getClient();
  +        return new FtpOutputStream( client, client.storeFileStream( relPath ) );
  +    }
  +
  +    /**
  +     * An InputStream that monitors for end-of-file.
  +     */
  +    private class FtpInputStream
  +        extends MonitorInputStream
  +    {
  +        private final FTPClient client;
  +
  +        public FtpInputStream( final FTPClient client, final InputStream in )
           {
  -            ftpFs.putClient( client );
  -            client = null;
  +            super( in );
  +            this.client = client;
           }
   
  -        if ( !ok )
  +        /**
  +         * Called after the stream has been closed.
  +         */
  +        protected void onClose() throws IOException
           {
  -            throw new FileSystemException( "vfs.provider.ftp/finish-get.error", getName() );
  +            final boolean ok;
  +            try
  +            {
  +                ok = client.completePendingCommand();
  +            }
  +            finally
  +            {
  +                ftpFs.putClient( client );
  +            }
  +
  +            if ( !ok )
  +            {
  +                throw new FileSystemException( "vfs.provider.ftp/finish-get.error", getName() );
  +            }
           }
       }
   
       /**
  -     * Creates an output stream to write the file content to.
  +     * An OutputStream that monitors for end-of-file.
        */
  -    protected OutputStream doGetOutputStream()
  -        throws Exception
  +    private class FtpOutputStream
  +        extends MonitorOutputStream
       {
  -        client = ftpFs.getClient();
  -        return client.storeFileStream( relPath );
  -    }
  +        private final FTPClient client;
   
  -    /**
  -     * Notification of the output stream being closed.
  -     */
  -    protected void doEndOutput()
  -        throws Exception
  -    {
  -        final boolean ok;
  -        try
  -        {
  -            ok = client.completePendingCommand();
  -        }
  -        finally
  +        public FtpOutputStream( final FTPClient client, final OutputStream outstr )
           {
  -            ftpFs.putClient( client );
  -            client = null;
  +            super( outstr );
  +            this.client = client;
           }
   
  -        if ( !ok )
  +        /**
  +         * Called after this stream is closed.
  +         */
  +        protected void onClose() throws IOException
           {
  -            throw new FileSystemException( "vfs.provider.ftp/finish-put.error", getName() );
  +            final boolean ok;
  +            try
  +            {
  +                ok = client.completePendingCommand();
  +            }
  +            finally
  +            {
  +                ftpFs.putClient( client );
  +            }
  +
  +            if ( !ok )
  +            {
  +                throw new FileSystemException( "vfs.provider.ftp/finish-put.error", getName() );
  +            }
           }
  -        detach();
       }
   }
  
  
  
  1.1                  jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/util/MonitorInputStream.java
  
  Index: MonitorInputStream.java
  ===================================================================
  /* ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 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.util;
  
  import java.io.BufferedInputStream;
  import java.io.InputStream;
  import java.io.IOException;
  
  /**
   * An InputStream that provides buffering and end-of-stream monitoring.
   *
   * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
   * @version $Revision: 1.1 $ $Date: 2003/02/13 04:28:45 $
   */
  public class MonitorInputStream
      extends BufferedInputStream
  {
      private boolean finished;
  
      public MonitorInputStream( final InputStream in )
      {
          super( in );
      }
  
      /**
       * Reads a character.
       */
      public int read() throws IOException
      {
          if ( finished )
          {
              return -1;
          }
  
          final int ch = super.read();
          if ( ch != -1 )
          {
              return ch;
          }
  
          // End-of-stream
          close();
          return -1;
      }
  
      /**
       * Reads bytes from this input stream.error occurs.
       */
      public int read( final byte[] buffer, final int offset, final int length )
          throws IOException
      {
          if ( finished )
          {
              return -1;
          }
  
          final int nread = super.read( buffer, offset, length );
          if ( nread != -1 )
          {
              return nread;
          }
  
          // End-of-stream
          close();
          return -1;
      }
  
      /**
       * Closes this input stream and releases any system resources
       * associated with the stream.
       */
      public void close() throws IOException
      {
          if ( finished )
          {
              return;
          }
  
          // Close the stream
          IOException exc = null;
          try
          {
              super.close();
          }
          catch ( final IOException ioe )
          {
              exc = ioe;
          }
  
          // Notify that the stream has been closed
          try
          {
              onClose();
          }
          catch ( final IOException ioe )
          {
              exc = ioe;
          }
  
          finished = true;
          if ( exc != null )
          {
              throw exc;
          }
      }
  
      /**
       * Called after the stream has been closed.  This implementation does
       * nothing.
       */
      protected void onClose() throws IOException
      {
      }
  }
  
  
  
  1.1                  jakarta-commons-sandbox/vfs/src/java/org/apache/commons/vfs/util/MonitorOutputStream.java
  
  Index: MonitorOutputStream.java
  ===================================================================
  /* ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 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.util;
  
  import java.io.BufferedOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  
  /**
   * An OutputStream that provides buffering and end-of-stream monitoring.
   *
   * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
   * @version $Revision: 1.1 $ $Date: 2003/02/13 04:28:45 $
   */
  public class MonitorOutputStream
      extends BufferedOutputStream
  {
      private boolean finished;
  
      public MonitorOutputStream( final OutputStream out )
      {
          super( out );
      }
  
      /**
       * Closes this output stream.
       */
      public void close() throws IOException
      {
          if ( finished )
          {
              return;
          }
  
          // Close the output stream
          IOException exc = null;
          try
          {
              super.close();
          }
          catch ( final IOException ioe )
          {
              exc = ioe;
          }
  
          // Notify of end of output
          try
          {
              onClose();
          }
          catch ( final IOException ioe )
          {
              exc = ioe;
          }
  
          finished = true;
  
          if ( exc != null )
          {
              throw exc;
          }
      }
  
      /**
       * Called after this stream is closed.  This implementation does nothing.
       */
      protected void onClose() throws IOException
      {
      }
  }
  
  
  
  1.3       +3 -3      jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/provider/test/JunctionTests.java
  
  Index: JunctionTests.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/provider/test/JunctionTests.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- JunctionTests.java	12 Feb 2003 07:56:19 -0000	1.2
  +++ JunctionTests.java	13 Feb 2003 04:28:46 -0000	1.3
  @@ -94,7 +94,7 @@
           }
           catch ( final Exception e )
           {
  -            assertSameMessage( "impl/nested-junction.error", "vfs:/a/b", e );
  +            assertSameMessage( "vfs.impl/nested-junction.error", "vfs:/a/b", e );
           }
   
           // At same point
  @@ -105,7 +105,7 @@
           }
           catch ( final Exception e )
           {
  -            assertSameMessage( "impl/nested-junction.error", "vfs:/a", e );
  +            assertSameMessage( "vfs.impl/nested-junction.error", "vfs:/a", e );
           }
       }
   
  
  
  
  1.3       +32 -17    jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/test/ContentTests.java
  
  Index: ContentTests.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/test/ContentTests.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ContentTests.java	12 Feb 2003 07:56:19 -0000	1.2
  +++ ContentTests.java	13 Feb 2003 04:28:46 -0000	1.3
  @@ -55,14 +55,14 @@
    */
   package org.apache.commons.vfs.test;
   
  +import java.io.InputStream;
  +import java.util.Iterator;
  +import org.apache.commons.vfs.FileContent;
   import org.apache.commons.vfs.FileObject;
  -import org.apache.commons.vfs.NameScope;
  -import org.apache.commons.vfs.FileType;
  -import org.apache.commons.vfs.FileSystemException;
   import org.apache.commons.vfs.FileSystem;
  -import org.apache.commons.vfs.FileContent;
  -import java.util.Iterator;
  -import java.io.InputStream;
  +import org.apache.commons.vfs.FileSystemException;
  +import org.apache.commons.vfs.FileType;
  +import org.apache.commons.vfs.NameScope;
   
   /**
    * Test cases for reading file content.
  @@ -254,9 +254,7 @@
       }
   
       /**
  -     * Tests concurrent reads on a file fail.
  -     *
  -     * @todo Change model so that concurrent reads are allowed (maybe optional)
  +     * Tests concurrent reads on a file.
        */
       public void testConcurrentRead() throws Exception
       {
  @@ -268,12 +266,7 @@
           try
           {
               // Start reading again
  -            file.getContent().getInputStream();
  -            fail();
  -        }
  -        catch ( final Exception e )
  -        {
  -            assertSameMessage( "vfs.provider/read-in-use.error", file, e );
  +            file.getContent().getInputStream().close();
           }
           finally
           {
  @@ -326,5 +319,27 @@
           // Read the content again
           assertSameContent( FILE1_CONTENT, file );
       }
  -    
  +
  +    /**
  +     * Tests that input streams are cleaned up on file close.
  +     */
  +    public void testInstrCleanup() throws Exception
  +    {
  +        // Get the test file
  +        FileObject file = getReadFolder().resolveFile( "file1.txt" );
  +        assertEquals( FileType.FILE, file.getType() );
  +
  +        // Open some input streams
  +        final InputStream instr1 = file.getContent().getInputStream();
  +        assertTrue( instr1.read() == FILE1_CONTENT.charAt( 0 ) );
  +        final InputStream instr2 = file.getContent().getInputStream();
  +        assertTrue( instr2.read() == FILE1_CONTENT.charAt( 0 ) );
  +
  +        // Close the file
  +        file.close();
  +
  +        // Check
  +        assertTrue( instr1.read() == -1 );
  +        assertTrue( instr2.read() == -1 );
  +    }
   }
  
  
  
  1.9       +41 -3     jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/test/ProviderWriteTests.java
  
  Index: ProviderWriteTests.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/vfs/src/test/org/apache/commons/vfs/test/ProviderWriteTests.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- ProviderWriteTests.java	12 Feb 2003 07:56:19 -0000	1.8
  +++ ProviderWriteTests.java	13 Feb 2003 04:28:46 -0000	1.9
  @@ -288,7 +288,43 @@
               instr.close();
           }
       }
  -    
  +
  +    /**
  +     * Tests concurrent writes on the same file fails.
  +     */
  +    public void testConcurrentWrite() throws Exception
  +    {
  +        final FileObject scratchFolder = createScratchFolder();
  +
  +        final FileObject file = scratchFolder.resolveFile( "file1.txt" );
  +        file.createFile();
  +
  +        // Start writing to the file
  +        final OutputStream outstr = file.getContent().getOutputStream();
  +        final String testContent = "some content";
  +        try
  +        {
  +            // Write some content to the first stream
  +            outstr.write( testContent.getBytes() );
  +
  +            // Try to open another output stream
  +            file.getContent().getOutputStream();
  +            fail();
  +        }
  +        catch ( final FileSystemException e )
  +        {
  +            // Check error message
  +            assertSameMessage( "vfs.provider/write-in-use.error", file, e );
  +        }
  +        finally
  +        {
  +            outstr.close();
  +        }
  +
  +        // Make sure that the content written to the first stream is actually applied
  +        assertSameContent( testContent, file );
  +    }
  +
       /**
        * Tests file copy to and from the same filesystem type.  This was a problem
        * w/ FTP.
  @@ -468,7 +504,8 @@
            */
           public void fileCreated( final FileChangeEvent event )
           {
  -            assertTrue( events.size() > 0 && events.remove( 0 ) == CREATE );
  +            assertTrue( "Unexpected create event", events.size() > 0 );
  +            assertSame( "Expecting a create event",  CREATE, events.remove( 0 ) );
               assertSame( file, event.getFile() );
               try
               {
  @@ -485,7 +522,8 @@
            */
           public void fileDeleted( final FileChangeEvent event )
           {
  -            assertTrue( events.size() > 0 && events.remove( 0 ) == DELETE );
  +            assertTrue( "Unexpected delete event", events.size() > 0 );
  +            assertSame( "Expecting a delete event", DELETE, events.remove( 0 ) );
               assertSame( file, event.getFile() );
               try
               {
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org