You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by im...@apache.org on 2005/11/02 20:45:16 UTC

svn commit: r330327 - in /jakarta/commons/proper/vfs/trunk: RELEASE_NOTES.txt build.xml project.xml src/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java xdocs/download.xml

Author: imario
Date: Wed Nov  2 11:45:06 2005
New Revision: 330327

URL: http://svn.apache.org/viewcvs?rev=330327&view=rev
Log:
sftp: upgrade to jsch-0.1.23

Modified:
    jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt
    jakarta/commons/proper/vfs/trunk/build.xml
    jakarta/commons/proper/vfs/trunk/project.xml
    jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java
    jakarta/commons/proper/vfs/trunk/xdocs/download.xml

Modified: jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt?rev=330327&r1=330326&r2=330327&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt (original)
+++ jakarta/commons/proper/vfs/trunk/RELEASE_NOTES.txt Wed Nov  2 11:45:06 2005
@@ -2,6 +2,7 @@
 
 sftp:
 new configuration parameter SftpFileSystemConfigBuilder.timeout
+upgrade to jsch-0.1.23
 
 ftp:
 better error message if it isnt possible to aquire a input or output stream

Modified: jakarta/commons/proper/vfs/trunk/build.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/build.xml?rev=330327&r1=330326&r2=330327&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/build.xml (original)
+++ jakarta/commons/proper/vfs/trunk/build.xml Wed Nov  2 11:45:06 2005
@@ -194,8 +194,8 @@
         <get dest="${libdir}/commons-httpclient-2.0.2.jar" usetimestamp="true" ignoreerrors="true"
              src="http://www.ibiblio.org/maven/commons-httpclient/jars/commons-httpclient-2.0.2.jar">
         </get>
-        <get dest="${libdir}/jsch-0.1.17.jar" usetimestamp="true" ignoreerrors="true"
-             src="http://www.ibiblio.org/maven/jsch/jars/jsch-0.1.17.jar">
+        <get dest="${libdir}/jsch-0.1.23.jar" usetimestamp="true" ignoreerrors="true"
+             src="http://www.ibiblio.org/maven/jsch/jars/jsch-0.1.23.jar">
         </get>
         <get dest="${libdir}/xml-apis-1.0.b2.jar" usetimestamp="true" ignoreerrors="true"
              src="http://www.ibiblio.org/maven/xml-apis/jars/xml-apis-1.0.b2.jar">

Modified: jakarta/commons/proper/vfs/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/project.xml?rev=330327&r1=330326&r2=330327&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/project.xml (original)
+++ jakarta/commons/proper/vfs/trunk/project.xml Wed Nov  2 11:45:06 2005
@@ -148,7 +148,7 @@
         <dependency>
             <groupId>jsch</groupId>
             <artifactId>jsch</artifactId>
-            <version>0.1.17</version>
+            <version>0.1.23</version>
         </dependency>
 
         <dependency>

Modified: jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java?rev=330327&r1=330326&r2=330327&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java (original)
+++ jakarta/commons/proper/vfs/trunk/src/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java Wed Nov  2 11:45:06 2005
@@ -18,14 +18,18 @@
 import com.jcraft.jsch.ChannelSftp;
 import com.jcraft.jsch.SftpATTRS;
 import com.jcraft.jsch.SftpException;
+import com.jcraft.jsch.ChannelSftp.LsEntry;
+
 import org.apache.commons.vfs.FileName;
 import org.apache.commons.vfs.FileObject;
 import org.apache.commons.vfs.FileSystemException;
 import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
 import org.apache.commons.vfs.RandomAccessContent;
 import org.apache.commons.vfs.VFS;
 import org.apache.commons.vfs.provider.AbstractFileObject;
 import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.provider.webdav.WebdavFileObject;
 import org.apache.commons.vfs.util.MonitorOutputStream;
 import org.apache.commons.vfs.util.RandomAccessMode;
 
@@ -36,388 +40,375 @@
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Vector;
 
 /**
  * An SFTP file.
- *
+ * 
  * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
- * @version $Revision$ $Date$
+ * @version $Revision$ $Date: 2005-10-14 19:59:47 +0200 (Fr, 14 Okt
+ *          2005) $
  */
-public class SftpFileObject
-    extends AbstractFileObject
-    implements FileObject
+public class SftpFileObject extends AbstractFileObject implements FileObject
 {
-    private final SftpFileSystem fileSystem;
-    private SftpATTRS attrs;
-    private final String relPath;
-
-    protected SftpFileObject(final FileName name,
-                             final SftpFileSystem fileSystem) throws FileSystemException
-    {
-        super(name, fileSystem);
-        this.fileSystem = fileSystem;
-        relPath = UriParser.decode(fileSystem.getRootName().getRelativeName(name));
-    }
-
-    /**
-     * Determines the type of this file, returns null if the file does not
-     * exist.
-     */
-    protected FileType doGetType()
-        throws Exception
-    {
-        statSelf();
-
-        if (attrs == null)
-        {
-            return FileType.IMAGINARY;
-        }
-
-        if ((attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS) == 0)
-        {
-            throw new FileSystemException("vfs.provider.sftp/unknown-permissions.error");
-        }
-        if (attrs.isDir())
-        {
-            return FileType.FOLDER;
-        }
-        else
-        {
-            return FileType.FILE;
-        }
-    }
-
-    /**
-     * Called when the type or content of this file changes.
-     */
-    protected void onChange()
-        throws Exception
-    {
-        statSelf();
-    }
-
-    /**
-     * Fetches file attrs from server.
-     */
-    private void statSelf()
-        throws Exception
-    {
-        final ChannelSftp channel = fileSystem.getChannel();
-        try
-        {
-            attrs = channel.stat(relPath);
-        }
-        catch (final SftpException e)
-        {
-            // TODO - not strictly true, but jsch 0.1.2 does not give us
-            // enough info in the exception.  Should be using:
-            // if ( e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE )
-            // However, sometimes the exception has the correct id, and sometimes
-            // it does not.  Need to look into why.
-
-            // Does not exist
-            attrs = null;
-        }
-        finally
-        {
-            fileSystem.putChannel(channel);
-        }
-    }
-
-    /**
-     * Creates this file as a folder.
-     */
-    protected void doCreateFolder()
-        throws Exception
-    {
-        final ChannelSftp channel = fileSystem.getChannel();
-        try
-        {
-            channel.mkdir(relPath);
-        }
-        finally
-        {
-            fileSystem.putChannel(channel);
-        }
-    }
-
-    protected long doGetLastModifiedTime() throws Exception
-    {
-        if (attrs == null || (attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_ACMODTIME) == 0)
-        {
-            throw new FileSystemException("vfs.provider.sftp/unknown-modtime.error");
-        }
-        return attrs.getMTime() * 1000L;
-    }
-
-    /**
-     * Sets the last modified time of this file.  Is only called if
-     * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
-     * <p/>
-     *
-     * @param modtime is modification time in milliseconds. SFTP protocol can
-     *                send times with nanosecond precision but at the moment jsch send them
-     *                with second precision.
-     */
-    protected void doSetLastModifiedTime(final long modtime)
-        throws Exception
-    {
-        final ChannelSftp channel = fileSystem.getChannel();
-        try
-        {
-            int newMTime = (int) (modtime / 1000L);
-
-            attrs.setACMODTIME(attrs.getATime(), newMTime);
-            channel.setStat(relPath, attrs);
-        }
-        finally
-        {
-            fileSystem.putChannel(channel);
-        }
-    }
-
-    /**
-     * Deletes the file.
-     */
-    protected void doDelete()
-        throws Exception
-    {
-        final ChannelSftp channel = fileSystem.getChannel();
-        try
-        {
-            if (getType() == FileType.FILE)
-            {
-                channel.rm(relPath);
-            }
-            else
-            {
-                channel.rmdir(relPath);
-            }
-        }
-        finally
-        {
-            fileSystem.putChannel(channel);
-        }
-    }
-
-    /**
-     * Rename the file.
-     */
-    protected void doRename(FileObject newfile) throws Exception
-    {
-        final ChannelSftp channel = fileSystem.getChannel();
-        try
-        {
-            channel.rename(relPath, ((SftpFileObject) newfile).relPath);
-        }
-        finally
-        {
-            fileSystem.putChannel(channel);
-        }
-    }
-
-    /**
-     * Lists the children of this file.
-     */
-    protected String[] doListChildren()
-        throws Exception
-    {
-        // List the contents of the folder
-        final Vector vector;
-        final ChannelSftp channel = fileSystem.getChannel();
-        try
-        {
-            vector = channel.ls(relPath);
-        }
-        finally
-        {
-            fileSystem.putChannel(channel);
-        }
-        if (vector == null)
-        {
-            throw new FileSystemException("vfs.provider.sftp/list-children.error");
-        }
-
-        // Extract the child names
-        final ArrayList children = new ArrayList();
-        for (Iterator iterator = vector.iterator(); iterator.hasNext();)
-        {
-            // Each entry is in unix ls format <perms> <?> <user> <group> <size> <date> <name>
-            final String stat = (String) iterator.next();
-
-            // parse entry ==> 2005-06-19 imario@apache.org
-            // we can get rid of it as soon as jsch releases the next version
-            // which allows access to the raw stat object.
-            boolean trigger = true;
-            int state = 0;
-            StringBuffer nameBuf = new StringBuffer(stat.length());
-            for (int i = 0; i < stat.length(); i++)
-            {
-                char c = stat.charAt(i);
-                if (state == 16)
-                {
-                    nameBuf.append(c);
-                    continue;
-                }
-                if ((c != ' ' && trigger) || (c == ' ' && !trigger))
-                {
-                    state++;
-                    trigger = !trigger;
-                }
-            }
-            if (VFS.isUriStyle())
-            {
-                if (stat.charAt(0) == 'd' && nameBuf.charAt(nameBuf.length() - 1) != '/')
-                {
-                    nameBuf.append("/");
-                }
-            }
-            // <==
-
-            String name = nameBuf.toString();
-            int linkPos = name.indexOf(" -> ");
-            if (linkPos > -1)
-            {
-                // link = name.substring(linkPos + 4);
-                name = name.substring(0, linkPos);
-            }
-
-            if (name.equals(".") || name.equals("..") || name.equals("./") || name.equals("../"))
-            {
-                continue;
-            }
-            children.add(name);
-        }
-        return UriParser.encode((String[]) children.toArray(new String[children.size()]));
-    }
-
-    /**
-     * Returns the size of the file content (in bytes).
-     */
-    protected long doGetContentSize()
-        throws Exception
-    {
-        if (attrs == null || (attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_SIZE) == 0)
-        {
-            throw new FileSystemException("vfs.provider.sftp/unknown-size.error");
-        }
-        return attrs.getSize();
-    }
-
-    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception
-    {
-        return new SftpRandomAccessContent(this, mode);
-    }
-
-    /**
-     * Creates an input stream to read the file content from.
-     */
-    InputStream getInputStream(long filePointer) throws IOException
-    {
-        throw new UnsupportedOperationException("Implemented. Yes. But have to wait for jsch release :-)");
-        /*
-        final ChannelSftp channel = fileSystem.getChannel();
-        try
-        {
-            // return channel.get(getName().getPath());
-            // hmmm - using the in memory method is soooo much faster ...
-
-            // TODO - Don't read the entire file into memory.  Use the
-            // stream-based methods on ChannelSftp once they work properly
-            final ByteArrayOutputStream outstr = new ByteArrayOutputStream();
-            try
-            {
-                channel.get(getName().getPathDecoded(), outstr, null, ChannelSftp.RESUME, filePointer);
-            }
-            catch (SftpException e)
-            {
-                throw new FileSystemException(e);
-            }
-            outstr.close();
-            return new ByteArrayInputStream(outstr.toByteArray());
-
-        }
-        finally
-        {
-            fileSystem.putChannel(channel);
-        }
-        */
-    }
-
-    /**
-     * Creates an input stream to read the file content from.
-     */
-    protected InputStream doGetInputStream()
-        throws Exception
-    {
-        final ChannelSftp channel = fileSystem.getChannel();
-        try
-        {
-            // return channel.get(getName().getPath());
-            // hmmm - using the in memory method is soooo much faster ...
-
-            // TODO - Don't read the entire file into memory.  Use the
-            // stream-based methods on ChannelSftp once they work properly
-            final ByteArrayOutputStream outstr = new ByteArrayOutputStream();
-            channel.get(relPath, outstr);
-            outstr.close();
-            return new ByteArrayInputStream(outstr.toByteArray());
-
-        }
-        finally
-        {
-            fileSystem.putChannel(channel);
-        }
-    }
-
-    /**
-     * Creates an output stream to write the file content to.
-     */
-    protected OutputStream doGetOutputStream(boolean bAppend)
-        throws Exception
-    {
-        // TODO - Don't write the entire file into memory.  Use the stream-based
-        // methods on ChannelSftp once the work properly
-        final ChannelSftp channel = fileSystem.getChannel();
-        return new SftpOutputStream(channel);
-    }
-
-    /**
-     * An OutputStream that wraps an sftp OutputStream, and closes the channel
-     * when the stream is closed.
-     */
-    private class SftpOutputStream
-        extends MonitorOutputStream
-    {
-        private final ChannelSftp channel;
-
-        public SftpOutputStream(final ChannelSftp channel)
-        {
-            super(new ByteArrayOutputStream());
-            this.channel = channel;
-        }
-
-        /**
-         * Called after this stream is closed.
-         */
-        protected void onClose()
-            throws IOException
-        {
-            try
-            {
-                final ByteArrayOutputStream outstr = (ByteArrayOutputStream) out;
-                channel.put(new ByteArrayInputStream(outstr.toByteArray()),
-                    relPath);
-            }
-            catch (final SftpException e)
-            {
-                throw new FileSystemException(e);
-            }
-            finally
-            {
-                fileSystem.putChannel(channel);
-            }
-        }
-    }
+	private final SftpFileSystem fileSystem;
+	private SftpATTRS attrs;
+	private final String relPath;
+
+	protected SftpFileObject(final FileName name,
+			final SftpFileSystem fileSystem) throws FileSystemException
+	{
+		super(name, fileSystem);
+		this.fileSystem = fileSystem;
+		relPath = UriParser.decode(fileSystem.getRootName().getRelativeName(
+				name));
+	}
+
+	/**
+	 * Determines the type of this file, returns null if the file does not
+	 * exist.
+	 */
+	protected FileType doGetType() throws Exception
+	{
+		if (attrs == null)
+		{
+			statSelf();
+		}
+
+		if (attrs == null)
+		{
+			return FileType.IMAGINARY;
+		}
+
+		if ((attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS) == 0)
+		{
+			throw new FileSystemException(
+					"vfs.provider.sftp/unknown-permissions.error");
+		}
+		if (attrs.isDir())
+		{
+			return FileType.FOLDER;
+		}
+		else
+		{
+			return FileType.FILE;
+		}
+	}
+
+	/**
+	 * Called when the type or content of this file changes.
+	 */
+	protected void onChange() throws Exception
+	{
+		statSelf();
+	}
+
+	/**
+	 * Fetches file attrs from server.
+	 */
+	private void statSelf() throws Exception
+	{
+		final ChannelSftp channel = fileSystem.getChannel();
+		try
+		{
+			setStat(channel.stat(relPath));
+		}
+		catch (final SftpException e)
+		{
+			// TODO - not strictly true, but jsch 0.1.2 does not give us
+			// enough info in the exception. Should be using:
+			// if ( e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE )
+			// However, sometimes the exception has the correct id, and
+			// sometimes
+			// it does not. Need to look into why.
+
+			// Does not exist
+			attrs = null;
+		}
+		finally
+		{
+			fileSystem.putChannel(channel);
+		}
+	}
+
+	/**
+	 * Set attrs from listChildrenResolved
+	 */
+	private void setStat(SftpATTRS attrs)
+	{
+		this.attrs = attrs;
+	}
+
+	/**
+	 * Creates this file as a folder.
+	 */
+	protected void doCreateFolder() throws Exception
+	{
+		final ChannelSftp channel = fileSystem.getChannel();
+		try
+		{
+			channel.mkdir(relPath);
+		}
+		finally
+		{
+			fileSystem.putChannel(channel);
+		}
+	}
+
+	protected long doGetLastModifiedTime() throws Exception
+	{
+		if (attrs == null
+				|| (attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_ACMODTIME) == 0)
+		{
+			throw new FileSystemException(
+					"vfs.provider.sftp/unknown-modtime.error");
+		}
+		return attrs.getMTime() * 1000L;
+	}
+
+	/**
+	 * Sets the last modified time of this file. Is only called if
+	 * {@link #doGetType} does not return {@link FileType#IMAGINARY}. <p/>
+	 * 
+	 * @param modtime
+	 *            is modification time in milliseconds. SFTP protocol can send
+	 *            times with nanosecond precision but at the moment jsch send
+	 *            them with second precision.
+	 */
+	protected void doSetLastModifiedTime(final long modtime) throws Exception
+	{
+		final ChannelSftp channel = fileSystem.getChannel();
+		try
+		{
+			int newMTime = (int) (modtime / 1000L);
+
+			attrs.setACMODTIME(attrs.getATime(), newMTime);
+			channel.setStat(relPath, attrs);
+		}
+		finally
+		{
+			fileSystem.putChannel(channel);
+		}
+	}
+
+	/**
+	 * Deletes the file.
+	 */
+	protected void doDelete() throws Exception
+	{
+		final ChannelSftp channel = fileSystem.getChannel();
+		try
+		{
+			if (getType() == FileType.FILE)
+			{
+				channel.rm(relPath);
+			}
+			else
+			{
+				channel.rmdir(relPath);
+			}
+		}
+		finally
+		{
+			fileSystem.putChannel(channel);
+		}
+	}
+
+	/**
+	 * Rename the file.
+	 */
+	protected void doRename(FileObject newfile) throws Exception
+	{
+		final ChannelSftp channel = fileSystem.getChannel();
+		try
+		{
+			channel.rename(relPath, ((SftpFileObject) newfile).relPath);
+		}
+		finally
+		{
+			fileSystem.putChannel(channel);
+		}
+	}
+
+	/**
+	 * Lists the children of this file.
+	 */
+	protected FileObject[] doListChildrenResolved() throws Exception
+	{
+		// List the contents of the folder
+		final Vector vector;
+		final ChannelSftp channel = fileSystem.getChannel();
+		try
+		{
+			vector = channel.ls(relPath);
+		}
+		finally
+		{
+			fileSystem.putChannel(channel);
+		}
+		if (vector == null)
+		{
+			throw new FileSystemException(
+					"vfs.provider.sftp/list-children.error");
+		}
+
+		// Extract the child names
+		final ArrayList children = new ArrayList();
+		for (Iterator iterator = vector.iterator(); iterator.hasNext();)
+		{
+			final LsEntry stat = (LsEntry) iterator.next();
+
+			String name = stat.getFilename();
+			if (VFS.isUriStyle())
+			{
+				if (stat.getAttrs().isDir()
+						&& name.charAt(name.length() - 1) != '/')
+				{
+					name = name + "/";
+				}
+			}
+
+			if (name.equals(".") || name.equals("..") || name.equals("./")
+					|| name.equals("../"))
+			{
+				continue;
+			}
+
+			SftpFileObject fo = (SftpFileObject) getFileSystem().resolveFile(
+					getFileSystem().getFileSystemManager().resolveName(
+							getName(),
+							UriParser.encode(name),
+							NameScope.CHILD));
+			fo.setStat(stat.getAttrs());
+
+			children.add(fo);
+		}
+
+		return (SftpFileObject[]) children.toArray(new SftpFileObject[children
+				.size()]);
+	}
+
+	/**
+	 * Lists the children of this file.
+	 */
+	protected String[] doListChildren() throws Exception
+	{
+		// use doListChildrenResolved for performance
+		return null;
+	}
+
+	/**
+	 * Returns the size of the file content (in bytes).
+	 */
+	protected long doGetContentSize() throws Exception
+	{
+		if (attrs == null
+				|| (attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_SIZE) == 0)
+		{
+			throw new FileSystemException(
+					"vfs.provider.sftp/unknown-size.error");
+		}
+		return attrs.getSize();
+	}
+
+	protected RandomAccessContent doGetRandomAccessContent(
+			final RandomAccessMode mode) throws Exception
+	{
+		return new SftpRandomAccessContent(this, mode);
+	}
+
+	/**
+	 * Creates an input stream to read the file content from.
+	 */
+	InputStream getInputStream(long filePointer) throws IOException
+	{
+		throw new UnsupportedOperationException(
+				"Implemented. Yes. But have to wait for jsch release :-)");
+		/*
+		 * final ChannelSftp channel = fileSystem.getChannel(); try { // return
+		 * channel.get(getName().getPath()); // hmmm - using the in memory
+		 * method is soooo much faster ...
+		 *  // TODO - Don't read the entire file into memory. Use the //
+		 * stream-based methods on ChannelSftp once they work properly final
+		 * ByteArrayOutputStream outstr = new ByteArrayOutputStream(); try {
+		 * channel.get(getName().getPathDecoded(), outstr, null,
+		 * ChannelSftp.RESUME, filePointer); } catch (SftpException e) { throw
+		 * new FileSystemException(e); } outstr.close(); return new
+		 * ByteArrayInputStream(outstr.toByteArray());
+		 *  } finally { fileSystem.putChannel(channel); }
+		 */
+	}
+
+	/**
+	 * Creates an input stream to read the file content from.
+	 */
+	protected InputStream doGetInputStream() throws Exception
+	{
+		final ChannelSftp channel = fileSystem.getChannel();
+		try
+		{
+			// return channel.get(getName().getPath());
+			// hmmm - using the in memory method is soooo much faster ...
+
+			// TODO - Don't read the entire file into memory. Use the
+			// stream-based methods on ChannelSftp once they work properly
+			final ByteArrayOutputStream outstr = new ByteArrayOutputStream();
+			channel.get(relPath, outstr);
+			outstr.close();
+			return new ByteArrayInputStream(outstr.toByteArray());
+
+		}
+		finally
+		{
+			fileSystem.putChannel(channel);
+		}
+	}
+
+	/**
+	 * Creates an output stream to write the file content to.
+	 */
+	protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+	{
+		// TODO - Don't write the entire file into memory. Use the stream-based
+		// methods on ChannelSftp once the work properly
+		final ChannelSftp channel = fileSystem.getChannel();
+		return new SftpOutputStream(channel);
+	}
+
+	/**
+	 * An OutputStream that wraps an sftp OutputStream, and closes the channel
+	 * when the stream is closed.
+	 */
+	private class SftpOutputStream extends MonitorOutputStream
+	{
+		private final ChannelSftp channel;
+
+		public SftpOutputStream(final ChannelSftp channel)
+		{
+			super(new ByteArrayOutputStream());
+			this.channel = channel;
+		}
+
+		/**
+		 * Called after this stream is closed.
+		 */
+		protected void onClose() throws IOException
+		{
+			try
+			{
+				final ByteArrayOutputStream outstr = (ByteArrayOutputStream) out;
+				channel.put(new ByteArrayInputStream(outstr.toByteArray()),
+						relPath);
+			}
+			catch (final SftpException e)
+			{
+				throw new FileSystemException(e);
+			}
+			finally
+			{
+				fileSystem.putChannel(channel);
+			}
+		}
+	}
 }

Modified: jakarta/commons/proper/vfs/trunk/xdocs/download.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/vfs/trunk/xdocs/download.xml?rev=330327&r1=330326&r2=330327&view=diff
==============================================================================
--- jakarta/commons/proper/vfs/trunk/xdocs/download.xml (original)
+++ jakarta/commons/proper/vfs/trunk/xdocs/download.xml Wed Nov  2 11:45:06 2005
@@ -99,7 +99,7 @@
                 <tr>
                     <td>
                         <a href="http://www.jcraft.com/jsch/">JSch</a>
-                        Version 0.1.17 or later.
+                        Version 0.1.23 or later.
                     </td>
                     <td>SFTP</td>
                 </tr>



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