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