This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git


The following commit(s) were added to refs/heads/master by this push:
     new 885ca9f  [VFS-609] SFTP provider doesn't support a private key as byte 
array #60.
885ca9f is described below

commit 885ca9fd1a6da890e9fd9b5d9b8884ae94cbb45d
Author: Gary Gregory <gardgreg...@gmail.com>
AuthorDate: Sat Apr 27 10:31:56 2019 -0400

    [VFS-609] SFTP provider doesn't support a private key as byte array #60.
---
 .../vfs2/provider/sftp/BytesIdentityInfo.java      |  79 +++++++++++++
 .../commons/vfs2/provider/sftp/IdentityInfo.java   |  40 ++++---
 .../vfs2/provider/sftp/IdentityProvider.java       |  32 +++++
 .../vfs2/provider/sftp/SftpClientFactory.java      |  18 ++-
 .../provider/sftp/SftpFileSystemConfigBuilder.java | 131 +++++++++++++--------
 .../provider/sftp/test/SftpProviderTestCase.java   |  35 ++++--
 src/changes/changes.xml                            |   3 +
 7 files changed, 254 insertions(+), 84 deletions(-)

diff --git 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/BytesIdentityInfo.java
 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/BytesIdentityInfo.java
new file mode 100644
index 0000000..aaa833f
--- /dev/null
+++ 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/BytesIdentityInfo.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.vfs2.provider.sftp;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+
+/**
+ * Structure for an identity based on byte arrays.
+ * 
+ * @since 2.4
+ */
+public class BytesIdentityInfo implements IdentityProvider {
+
+    private final byte[] passPhrase;
+
+    private final byte[] privateKey;
+
+    private final byte[] publicKey;
+
+    /**
+     * Constructs an identity info with private and passphrase for the private 
key.
+     *
+     * @param privateKey Private key bytes
+     * @param passPhrase The passphrase to decrypt the private key (can be 
{@code null} if no passphrase is used)
+     */
+    public BytesIdentityInfo(byte[] privateKey, byte[] passPhrase) {
+        super();
+        this.privateKey = privateKey;
+        this.publicKey = null;
+        this.passPhrase = passPhrase;
+    }
+
+    /**
+     * Constructs an identity info with private and public key and passphrase 
for the private key.
+     *
+     * @param privateKey Private key bytes
+     * @param publicKey  The public key part used for connections with 
exchange of certificates (can be {@code null})
+     * @param passPhrase The passphrase to decrypt the private key (can be 
{@code null} if no passphrase is used)
+     */
+    public BytesIdentityInfo(byte[] privateKey, byte[] publicKey, byte[] 
passPhrase) {
+        super();
+        this.privateKey = privateKey;
+        this.publicKey = publicKey;
+        this.passPhrase = passPhrase;
+    }
+
+    @Override
+    public void addIdentity(JSch jsch) throws JSchException {
+        jsch.addIdentity("PrivateKey", privateKey, publicKey, passPhrase);
+    }
+
+    public byte[] getPassPhrase() {
+        return passPhrase;
+    }
+
+    public byte[] getPrivateKeyBytes() {
+        return privateKey;
+    }
+
+    public byte[] getPublicKeyBytes() {
+        return publicKey;
+    }
+}
diff --git 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityInfo.java
 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityInfo.java
index e1f1ccf..7fb4331 100644
--- 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityInfo.java
+++ 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityInfo.java
@@ -18,15 +18,18 @@ package org.apache.commons.vfs2.provider.sftp;
 
 import java.io.File;
 
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+
 /**
- * Structure for an identity.
+ * Structure for an identity based on Files.
  *
  * @since 2.1
  */
-public class IdentityInfo {
+public class IdentityInfo implements IdentityProvider {
+    private final byte[] passPhrase;
     private final File privateKey;
     private final File publicKey;
-    private final byte[] passPhrase;
 
     /**
      * Constructs an identity info with private key.
@@ -61,7 +64,7 @@ public class IdentityInfo {
      * We use java.io.File because JSch cannot deal with VFS FileObjects.
      *
      * @param privateKey The file with the private key
-     * @param publicKey The public key part used for connections with exchange 
of certificates (can be {@code null})
+     * @param publicKey  The public key part used for connections with 
exchange of certificates (can be {@code null})
      * @param passPhrase The passphrase to decrypt the private key (can be 
{@code null} if no passphrase is used)
      * @since 2.1
      */
@@ -71,6 +74,25 @@ public class IdentityInfo {
         this.passPhrase = passPhrase;
     }
 
+    @Override
+    public void addIdentity(final JSch jsch) throws JSchException {
+        jsch.addIdentity(getAbsolutePath(privateKey), 
getAbsolutePath(publicKey), passPhrase);
+    }
+
+    private String getAbsolutePath(final File file) {
+        return file != null ? file.getAbsolutePath() : null;
+    }
+
+    /**
+     * Get the passphrase of the private key.
+     *
+     * @return the passphrase
+     * @since 2.1
+     */
+    public byte[] getPassPhrase() {
+        return passPhrase;
+    }
+
     /**
      * Get the file with the private key.
      *
@@ -90,14 +112,4 @@ public class IdentityInfo {
     public File getPublicKey() {
         return publicKey;
     }
-
-    /**
-     * Get the passphrase of the private key.
-     *
-     * @return the passphrase
-     * @since 2.1
-     */
-    public byte[] getPassPhrase() {
-        return passPhrase;
-    }
 }
diff --git 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityProvider.java
 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityProvider.java
new file mode 100644
index 0000000..a5690a2
--- /dev/null
+++ 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/IdentityProvider.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.vfs2.provider.sftp;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+
+/**
+ * Provides identity to a {@link JSch}.
+ * 
+ * @since 2.4
+ */
+public interface IdentityProvider {
+
+    void addIdentity(final JSch jsch) throws JSchException;
+
+}
diff --git 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java
 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java
index 6be9cc2..3a6ef19 100644
--- 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java
+++ 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpClientFactory.java
@@ -73,7 +73,7 @@ public final class SftpClientFactory {
         // new style - user passed
         final SftpFileSystemConfigBuilder builder = 
SftpFileSystemConfigBuilder.getInstance();
         final File knownHostsFile = builder.getKnownHosts(fileSystemOptions);
-        final IdentityInfo[] identities = 
builder.getIdentityInfo(fileSystemOptions);
+        final IdentityProvider[] identities = 
builder.getIdentityProvider(fileSystemOptions);
         final IdentityRepositoryFactory repositoryFactory = 
builder.getIdentityRepositoryFactory(fileSystemOptions);
         final ConfigRepository configRepository = 
builder.getConfigRepository(fileSystemOptions);
         final boolean loadOpenSSHConfig = 
builder.isLoadOpenSSHConfig(fileSystemOptions);
@@ -166,17 +166,17 @@ public final class SftpClientFactory {
         return session;
     }
 
-    private static void addIdentities(final JSch jsch, final File sshDir, 
final IdentityInfo[] identities)
+    private static void addIdentities(final JSch jsch, final File sshDir, 
final IdentityProvider[] identities)
             throws FileSystemException {
         if (identities != null) {
-            for (final IdentityInfo info : identities) {
-                addIndentity(jsch, info);
+            for (final IdentityProvider info : identities) {
+                addIdentity(jsch, info);
             }
         } else {
             // Load the private key (rsa-key only)
             final File privateKeyFile = new File(sshDir, "id_rsa");
             if (privateKeyFile.isFile() && privateKeyFile.canRead()) {
-                addIndentity(jsch, new IdentityInfo(privateKeyFile));
+                addIdentity(jsch, new IdentityInfo(privateKeyFile));
             }
         }
     }
@@ -195,13 +195,11 @@ public final class SftpClientFactory {
         }
     }
 
-    private static void addIndentity(final JSch jsch, final IdentityInfo info) 
throws FileSystemException {
+    private static void addIdentity(final JSch jsch, final IdentityProvider 
identity) throws FileSystemException {
         try {
-            final String privateKeyFile = info.getPrivateKey() != null ? 
info.getPrivateKey().getAbsolutePath() : null;
-            final String publicKeyFile = info.getPublicKey() != null ? 
info.getPublicKey().getAbsolutePath() : null;
-            jsch.addIdentity(privateKeyFile, publicKeyFile, 
info.getPassPhrase());
+            identity.addIdentity(jsch);
         } catch (final JSchException e) {
-            throw new 
FileSystemException("vfs.provider.sftp/load-private-key.error", info, e);
+            throw new 
FileSystemException("vfs.provider.sftp/load-private-key.error", identity, e);
         }
     }
 
diff --git 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.java
 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.java
index 93ba4fe..eeefb74 100644
--- 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.java
+++ 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/sftp/SftpFileSystemConfigBuilder.java
@@ -18,6 +18,8 @@ package org.apache.commons.vfs2.provider.sftp;
 
 import java.io.File;
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.commons.vfs2.FileSystem;
 import org.apache.commons.vfs2.FileSystemConfigBuilder;
@@ -105,13 +107,13 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     private static final String PROXY_OPTIONS = _PREFIX + ".PROXY_OPTIONS";
     private static final String PROXY_PASSWORD = _PREFIX + ".PROXY_PASSWORD";
     private static final String PROXY_PORT = _PREFIX + ".PROXY_PORT";
-    
+
     /** HTTP Proxy. */
     public static final ProxyType PROXY_HTTP = new ProxyType("http");
-    
+
     /** SOCKS Proxy. */
     public static final ProxyType PROXY_SOCKS5 = new ProxyType("socks");
-    
+
     /**
      * Connects to the SFTP server through a remote host reached by SSH.
      * <p>
@@ -202,14 +204,36 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     }
 
     /**
-     * Gets the identity info.
+     * Gets the identity infos.
      *
      * @param opts The FileSystem options.
-     * @return the array of identity info instances.
+     * @return the array of identity info.
      * @see #setIdentityInfo
      */
     public IdentityInfo[] getIdentityInfo(final FileSystemOptions opts) {
-        return (IdentityInfo[]) this.getParam(opts, IDENTITIES);
+        final IdentityProvider[] infos = getIdentityProvider(opts);
+        if (infos != null) {
+            final List<IdentityInfo> list = new ArrayList<>(infos.length);
+            for (IdentityProvider identityProvider : infos) {
+                if (identityProvider instanceof IdentityInfo) {
+                    list.add((IdentityInfo) identityProvider);
+                }
+            }
+            return list.toArray(new IdentityInfo[list.size()]);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the identity providers.
+     *
+     * @param opts The FileSystem options.
+     * @return the array of identity providers.
+     * @see #setIdentityProvider
+     * @since 2.4
+     */
+    public IdentityProvider[] getIdentityProvider(final FileSystemOptions 
opts) {
+        return (IdentityProvider[]) this.getParam(opts, IDENTITIES);
     }
 
     /**
@@ -233,9 +257,8 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     }
 
     /**
-     * Returns {@link Boolean#TRUE} if VFS should load the OpenSSH config. 
Defaults to
-     * <code>Boolean.FALSE</code> if the method {@link 
#setLoadOpenSSHConfig(FileSystemOptions, boolean)} has not been
-     * invoked.
+     * Returns {@link Boolean#TRUE} if VFS should load the OpenSSH config. 
Defaults to <code>Boolean.FALSE</code> if the
+     * method {@link #setLoadOpenSSHConfig(FileSystemOptions, boolean)} has 
not been invoked.
      *
      * @param opts The FileSystemOptions.
      * @return <code>Boolean.TRUE</code> if VFS should load the OpenSSH config.
@@ -369,12 +392,12 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     public String getStrictHostKeyChecking(final FileSystemOptions opts) {
         return this.getString(opts, STRICT_HOST_KEY_CHECKING, 
HOST_KEY_CHECK_NO);
     }
-    
+
     /**
-    * @param opts The FileSystem options.
-    * @return the option value for spesific key exchange algorithm
-    * @see #setKeyExchangeAlgorithm(FileSystemOptions, String)
-    **/
+     * @param opts The FileSystem options.
+     * @return the option value for spesific key exchange algorithm
+     * @see #setKeyExchangeAlgorithm(FileSystemOptions, String)
+     **/
     public String getKeyExchangeAlgorithm(final FileSystemOptions opts) {
         return this.getString(opts, KEY_EXCHANGE_ALGORITHM);
     }
@@ -419,7 +442,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
      * <p>
      * See the Jsch documentation (in particular the README file) for details.
      *
-     * @param opts The FileSystem options.
+     * @param opts        The FileSystem options.
      * @param compression The names of the compression algorithms, 
comma-separated.
      * @throws FileSystemException if an error occurs.
      */
@@ -430,7 +453,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the timeout value to create a Jsch connection.
      *
-     * @param opts The FileSystem options.
+     * @param opts    The FileSystem options.
      * @param timeout The connect timeout in milliseconds.
      * @since 2.3
      */
@@ -441,7 +464,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the file name encoding.
      *
-     * @param opts The FileSystem options.
+     * @param opts             The FileSystem options.
      * @param fileNameEncoding The name of the encoding to use for file names.
      */
     public void setFileNameEncoding(final FileSystemOptions opts, final String 
fileNameEncoding) {
@@ -453,16 +476,16 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
      * <p>
      * We use {@link java.io.File} because JSch cannot deal with VFS 
FileObjects.
      *
-     * @param opts The FileSystem options.
+     * @param opts          The FileSystem options.
      * @param identityFiles An array of identity Files.
      * @throws FileSystemException if an error occurs.
      * @deprecated As of 2.1 use {@link #setIdentityInfo(FileSystemOptions, 
IdentityInfo...)}
      */
     @Deprecated
     public void setIdentities(final FileSystemOptions opts, final File... 
identityFiles) throws FileSystemException {
-        IdentityInfo[] info = null;
+        IdentityProvider[] info = null;
         if (identityFiles != null) {
-            info = new IdentityInfo[identityFiles.length];
+            info = new IdentityProvider[identityFiles.length];
             for (int i = 0; i < identityFiles.length; i++) {
                 info[i] = new IdentityInfo(identityFiles[i]);
             }
@@ -473,22 +496,37 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the identity info (your private key files).
      *
-     * @param opts The FileSystem options.
+     * @param opts      The FileSystem options.
      * @param identites An array of identity info.
      * @throws FileSystemException if an error occurs.
      * @since 2.1
+     * @deprecated Use {@link 
#setIdentityProvider(FileSystemOptions,IdentityProvider...)}
      */
+    @Deprecated
     public void setIdentityInfo(final FileSystemOptions opts, final 
IdentityInfo... identites)
             throws FileSystemException {
         this.setParam(opts, IDENTITIES, identites);
     }
 
     /**
+     * Sets the identity info (your private key files).
+     *
+     * @param opts      The FileSystem options.
+     * @param identites An array of identity info.
+     * @throws FileSystemException if an error occurs.
+     * @since 2.4
+     */
+    public void setIdentityProvider(final FileSystemOptions opts, final 
IdentityProvider... identites)
+            throws FileSystemException {
+        this.setParam(opts, IDENTITIES, identites);
+    }
+
+    /**
      * Set the identity repository.
      * <p>
      * This is useful when you want to use e.g. an SSH agent as provided.
      *
-     * @param opts The FileSystem options.
+     * @param opts    The FileSystem options.
      * @param factory An identity repository.
      * @throws FileSystemException if an error occurs.
      * @see <a href="http://www.jcraft.com/jsch-agent-proxy/";>JSch agent 
proxy</a>
@@ -503,7 +541,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
      * <p>
      * This is useful when you want to use OpenSSHConfig.
      *
-     * @param opts The FileSystem options.
+     * @param opts             The FileSystem options.
      * @param configRepository An config repository.
      * @throws FileSystemException if an error occurs.
      * @see <a 
href="http://www.jcraft.com/jsch/examples/OpenSSHConfig.java.html";>OpenSSHConfig</a>
@@ -518,7 +556,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
      * <p>
      * We use {@link java.io.File} because JSch cannot deal with VFS 
FileObjects.
      *
-     * @param opts The FileSystem options.
+     * @param opts       The FileSystem options.
      * @param knownHosts The known hosts file.
      * @throws FileSystemException if an error occurs.
      */
@@ -529,7 +567,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Configures authentication order.
      *
-     * @param opts The FileSystem options.
+     * @param opts                     The FileSystem options.
      * @param preferredAuthentications The authentication order.
      * @since 2.0
      */
@@ -540,7 +578,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the proxy username to use for the SFTP connection.
      *
-     * @param opts The FileSystem options.
+     * @param opts         The FileSystem options.
      * @param proxyCommand the port
      * @see #getProxyOptions
      * @since 2.1
@@ -554,7 +592,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
      *
      * You MUST also set the proxy port to use the proxy.
      *
-     * @param opts The FileSystem options.
+     * @param opts      The FileSystem options.
      * @param proxyHost the host
      * @see #setProxyPort
      */
@@ -565,7 +603,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the proxy username to use for the SFTP connection.
      *
-     * @param opts The FileSystem options.
+     * @param opts         The FileSystem options.
      * @param proxyOptions the options
      * @see #getProxyOptions
      * @since 2.1
@@ -577,7 +615,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the proxy password to use for the SFTP connection.
      *
-     * @param opts The FileSystem options.
+     * @param opts          The FileSystem options.
      * @param proxyPassword the username used to connect to the proxy
      * @see #getProxyPassword
      * @since 2.1
@@ -591,7 +629,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
      * <p>
      * You MUST also set the proxy host to use the proxy.
      *
-     * @param opts The FileSystem options.
+     * @param opts      The FileSystem options.
      * @param proxyPort the port
      * @see #setProxyHost
      */
@@ -609,7 +647,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
      * <li>{@linkplain #PROXY_STREAM} connects through a remote host stream 
command</li>
      * </ul>
      *
-     * @param opts The FileSystem options.
+     * @param opts      The FileSystem options.
      * @param proxyType the type of the proxy to use.
      */
     public void setProxyType(final FileSystemOptions opts, final ProxyType 
proxyType) {
@@ -619,7 +657,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the proxy username to use for the SFTP connection.
      *
-     * @param opts The FileSystem options.
+     * @param opts      The FileSystem options.
      * @param proxyUser the username used to connect to the proxy
      * @see #getProxyUser
      * @since 2.1
@@ -631,7 +669,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the timeout value on Jsch session.
      *
-     * @param opts The FileSystem options.
+     * @param opts    The FileSystem options.
      * @param timeout The session timeout in milliseconds.
      * @since 2.3
      */
@@ -639,18 +677,17 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
         this.setParam(opts, SESSION_TIMEOUT_MILLIS, timeout);
     }
 
-    
     /**
-     ** Configure Key exchange algoritm explicitly
-     ** e.g 
diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
-      * @param opts The FileSystem options.
-      * @param keyExchangeAlgoritm The key exchange algoritm picked.
-    **/
-        public void setKeyExchangeAlgorithm(final FileSystemOptions opts, 
final String keyExchangeAlgoritm) {
-      setParam(opts, KEY_EXCHANGE_ALGORITHM, keyExchangeAlgoritm);
+     ** Configure Key exchange algoritm explicitly e.g
+     * 
diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
+     * 
+     * @param opts                The FileSystem options.
+     * @param keyExchangeAlgoritm The key exchange algoritm picked.
+     **/
+    public void setKeyExchangeAlgorithm(final FileSystemOptions opts, final 
String keyExchangeAlgoritm) {
+        setParam(opts, KEY_EXCHANGE_ALGORITHM, keyExchangeAlgoritm);
     }
-    
-    
+
     /**
      * Configures the host key checking to use.
      * <p>
@@ -660,7 +697,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
      * See the jsch documentation for details.
      * </p>
      *
-     * @param opts The FileSystem options.
+     * @param opts            The FileSystem options.
      * @param hostKeyChecking The host key checking to use.
      * @throws FileSystemException if an error occurs.
      */
@@ -677,7 +714,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the timeout value on Jsch session.
      *
-     * @param opts The FileSystem options.
+     * @param opts    The FileSystem options.
      * @param timeout The timeout in milliseconds.
      * @deprecated Use {@link #setSessionTimeoutMillis(FileSystemOptions, 
Integer)}
      */
@@ -689,7 +726,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the whether to use the user directory as root (do not change to 
file system root).
      *
-     * @param opts The FileSystem options.
+     * @param opts          The FileSystem options.
      * @param userDirIsRoot true if the user directory is the root directory.
      */
     public void setUserDirIsRoot(final FileSystemOptions opts, final boolean 
userDirIsRoot) {
@@ -709,7 +746,7 @@ public final class SftpFileSystemConfigBuilder extends 
FileSystemConfigBuilder {
     /**
      * Sets the whether to load OpenSSH config.
      *
-     * @param opts The FileSystem options.
+     * @param opts              The FileSystem options.
      * @param loadOpenSSHConfig true if the OpenSSH config should be loaded.
      */
     public void setLoadOpenSSHConfig(final FileSystemOptions opts, final 
boolean loadOpenSSHConfig) {
diff --git 
a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
 
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
index 69cf1d6..a44da9d 100644
--- 
a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
+++ 
b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/sftp/test/SftpProviderTestCase.java
@@ -32,10 +32,6 @@ import java.util.TreeMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import junit.extensions.TestSetup;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import org.apache.commons.AbstractVfsTestCase;
 import org.apache.commons.vfs2.FileObject;
 import org.apache.commons.vfs2.FileSystemManager;
@@ -80,6 +76,10 @@ import org.apache.sshd.server.sftp.SftpSubsystem;
 import com.jcraft.jsch.SftpATTRS;
 import com.jcraft.jsch.TestIdentityRepositoryFactory;
 
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
 /**
  * Tests cases for the SFTP provider.
  * <p>
@@ -87,6 +87,7 @@ import com.jcraft.jsch.TestIdentityRepositoryFactory;
  * </p>
  */
 public class SftpProviderTestCase extends AbstractProviderTestConfig {
+
     /**
      * The underlying filesystem
      */
@@ -378,12 +379,16 @@ public class SftpProviderTestCase extends 
AbstractProviderTestConfig {
 
             final URI parsedURI = new URI(uri);
             final String userInfo = parsedURI.getUserInfo();
-            final String[] userFields = userInfo.split(":", 2);
+            final String[] userFields = userInfo == null ? null : 
userInfo.split(":", 2);
 
             builder.setProxyType(fileSystemOptions, 
SftpFileSystemConfigBuilder.PROXY_STREAM);
-            builder.setProxyUser(fileSystemOptions, userFields[0]);
-            if (userFields.length > 1) {
-                builder.setProxyPassword(fileSystemOptions, userFields[1]);
+            if (userFields != null) {
+                if (userFields.length > 0) {
+                    builder.setProxyUser(fileSystemOptions, userFields[0]);
+                }
+                if (userFields.length > 1) {
+                    builder.setProxyPassword(fileSystemOptions, userFields[1]);
+                }
             }
             builder.setProxyHost(fileSystemOptions, parsedURI.getHost());
             builder.setProxyPort(fileSystemOptions, parsedURI.getPort());
@@ -392,7 +397,11 @@ public class SftpProviderTestCase extends 
AbstractProviderTestConfig {
             builder.setProxyPassword(fileSystemOptions, 
parsedURI.getAuthority());
 
             // Set up the new URI
-            uri = String.format("sftp://%s@localhost:%d";, userInfo, 
parsedURI.getPort());
+            if (userInfo == null) {
+                uri = String.format("sftp://localhost:%d";, 
parsedURI.getPort());
+            } else {
+                uri = String.format("sftp://%s@localhost:%d";, userInfo, 
parsedURI.getPort());
+            }
         }
 
         final FileObject fileObject = manager.resolveFile(uri, 
fileSystemOptions);
@@ -497,11 +506,11 @@ public class SftpProviderTestCase extends 
AbstractProviderTestConfig {
     /**
      * Creates a pipe thread that connects an input to an output
      *
-     * @param name The name of the thread (for debugging purposes)
-     * @param in The input stream
-     * @param out The output stream
+     * @param name     The name of the thread (for debugging purposes)
+     * @param in       The input stream
+     * @param out      The output stream
      * @param callback An object whose method {@linkplain 
ExitCallback#onExit(int)} will be called when the pipe is
-     *            broken. The integer argument is 0 if everything went well.
+     *                 broken. The integer argument is 0 if everything went 
well.
      */
     private static void connect(final String name, final InputStream in, final 
OutputStream out,
             final ExitCallback callback) {
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 709a09f..25fa371 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -86,6 +86,9 @@ The <action> type attribute can be add,update,fix,remove.
       <action issue="VFS-706" dev="ggregory" type="add" due-to="Boris Petrov">
         Add ability to specify buffer sizes #59.
       </action>
+      <action issue="VFS-609" dev="ggregory" type="add" due-to="stevezhuang, 
Rostislav, Gary Gregory">
+        SFTP provider doesn't support a private key as byte array #60.
+      </action>
     </release>
     <release version="2.3" date="2019-02-01" description="New features and bug 
fix release.">
       <action issue="VFS-645" dev="ggregory" type="fix">

Reply via email to