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