Discussion:
[3/5] mina-sshd git commit: Fixed a few Checkstyle issues
l***@apache.org
2018-11-07 18:01:06 UTC
Permalink
Fixed a few Checkstyle issues


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/99dd4aae
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/99dd4aae
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/99dd4aae

Branch: refs/heads/master
Commit: 99dd4aae6e7ee37fed459d23734a4efba8da3e57
Parents: 5f4d0f8
Author: Lyor Goldstein <***@apache.org>
Authored: Wed Nov 7 07:25:19 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Wed Nov 7 20:06:39 2018 +0200

----------------------------------------------------------------------
.../apache/sshd/common/util/SelectorUtils.java | 47 ++++++++++----------
.../pubkey/CachingPublicKeyAuthenticator.java | 1 -
.../apache/sshd/common/AttributeStoreTest.java | 1 -
3 files changed, 24 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99dd4aae/sshd-common/src/main/java/org/apache/sshd/common/util/SelectorUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/SelectorUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/SelectorUtils.java
index 95975c2..1557c55 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/SelectorUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/SelectorUtils.java
@@ -26,15 +26,15 @@ import java.util.Objects;
import java.util.StringTokenizer;

/**
- * <p>This is a utility class used by selectors and DirectoryScanner. The
+ * <p>
+ * This is a utility class used by selectors and DirectoryScanner. The
* functionality more properly belongs just to selectors, but unfortunately
* DirectoryScanner exposed these as protected methods. Thus we have to
* support any subclasses of DirectoryScanner that may access these methods.
* </p>
* <p>This is a Singleton.</p>
*
- * @author Arnout J. Kuiper
- * <a href="mailto:***@wxs.nl">***@wxs.nl</a>
+ * @author Arnout J. Kuiper <a href="mailto:***@wxs.nl">***@wxs.nl</a>
* @author Magesh Umasankar
* @author <a href="mailto:***@callenish.com">Bruce Atherton</a>
* @version $Id$
@@ -91,18 +91,19 @@ public final class SelectorUtils {
* @param isCaseSensitive Whether or not matching should be performed
* case sensitively.
* @return whether or not a given path matches the start of a given
- * pattern up to the first "**".
+ * pattern up to the first &quot;**&quot;.
*/
- public static boolean matchPatternStart(String pattern, String str,
- boolean isCaseSensitive) {
- if (pattern.length() > (REGEX_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1)
- && pattern.startsWith(REGEX_HANDLER_PREFIX) && pattern.endsWith(PATTERN_HANDLER_SUFFIX)) {
+ public static boolean matchPatternStart(String pattern, String str, boolean isCaseSensitive) {
+ if ((pattern.length() > (REGEX_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1))
+ && pattern.startsWith(REGEX_HANDLER_PREFIX)
+ && pattern.endsWith(PATTERN_HANDLER_SUFFIX)) {
// FIXME: ICK! But we can't do partial matches for regex, so we have to reserve judgement until we have
// a file to deal with, or we can definitely say this is an exclusion...
return true;
} else {
- if (pattern.length() > (ANT_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1)
- && pattern.startsWith(ANT_HANDLER_PREFIX) && pattern.endsWith(PATTERN_HANDLER_SUFFIX)) {
+ if ((pattern.length() > (ANT_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1))
+ && pattern.startsWith(ANT_HANDLER_PREFIX)
+ && pattern.endsWith(PATTERN_HANDLER_SUFFIX)) {
pattern =
pattern.substring(ANT_HANDLER_PREFIX.length(), pattern.length() - PATTERN_HANDLER_SUFFIX.length());
}
@@ -114,7 +115,8 @@ public final class SelectorUtils {
}
}

- private static boolean matchAntPathPatternStart(String pattern, String str, String separator, boolean isCaseSensitive) {
+ private static boolean matchAntPathPatternStart(
+ String pattern, String str, String separator, boolean isCaseSensitive) {
// When str starts with a File.separator, pattern has to start with a
// File.separator.
// When pattern starts with a File.separator, str has to start with a
@@ -182,17 +184,16 @@ public final class SelectorUtils {
* or <code>false</code> otherwise.
*/
public static boolean matchPath(String pattern, String str, boolean isCaseSensitive) {
- if (pattern.length() > (REGEX_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1)
- && pattern.startsWith(REGEX_HANDLER_PREFIX) && pattern.endsWith(PATTERN_HANDLER_SUFFIX)) {
- pattern = pattern.substring(REGEX_HANDLER_PREFIX.length(), pattern.length()
- - PATTERN_HANDLER_SUFFIX.length());
-
+ if ((pattern.length() > (REGEX_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1))
+ && pattern.startsWith(REGEX_HANDLER_PREFIX)
+ && pattern.endsWith(PATTERN_HANDLER_SUFFIX)) {
+ pattern = pattern.substring(REGEX_HANDLER_PREFIX.length(), pattern.length() - PATTERN_HANDLER_SUFFIX.length());
return str.matches(pattern);
} else {
- if (pattern.length() > (ANT_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1)
- && pattern.startsWith(ANT_HANDLER_PREFIX) && pattern.endsWith(PATTERN_HANDLER_SUFFIX)) {
- pattern =
- pattern.substring(ANT_HANDLER_PREFIX.length(), pattern.length() - PATTERN_HANDLER_SUFFIX.length());
+ if ((pattern.length() > (ANT_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1))
+ && pattern.startsWith(ANT_HANDLER_PREFIX)
+ && pattern.endsWith(PATTERN_HANDLER_SUFFIX)) {
+ pattern = pattern.substring(ANT_HANDLER_PREFIX.length(), pattern.length() - PATTERN_HANDLER_SUFFIX.length());
}

return matchAntPathPattern(pattern, str, isCaseSensitive);
@@ -461,8 +462,7 @@ public final class SelectorUtils {
int patLength = patIdxTmp - patIdxStart - 1;
int strLength = strIdxEnd - strIdxStart + 1;
int foundIdx = -1;
- strLoop:
- for (int i = 0; i <= strLength - patLength; i++) {
+ strLoop: for (int i = 0; i <= strLength - patLength; i++) {
for (int j = 0; j < patLength; j++) {
ch = patArr[patIdxStart + j + 1];
if (ch != '?' && !equals(ch, strArr[strIdxStart + i + j], isCaseSensitive)) {
@@ -545,7 +545,8 @@ public final class SelectorUtils {
* @see #translateToLocalFileSystemPath(String, char, String)
*/
public static String translateToLocalFileSystemPath(String path, char pathSeparator, FileSystem fs) {
- return translateToLocalFileSystemPath(path, pathSeparator, Objects.requireNonNull(fs, "No target file system").getSeparator());
+ return translateToLocalFileSystemPath(path, pathSeparator,
+ Objects.requireNonNull(fs, "No target file system").getSeparator());
}

/**

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99dd4aae/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/CachingPublicKeyAuthenticator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/CachingPublicKeyAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/CachingPublicKeyAuthenticator.java
index 79cac90..a1c2169 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/CachingPublicKeyAuthenticator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/CachingPublicKeyAuthenticator.java
@@ -24,7 +24,6 @@ import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.sshd.common.AttributeRepository;
-import org.apache.sshd.common.AttributeRepository.AttributeKey;
import org.apache.sshd.common.RuntimeSshException;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.util.logging.AbstractLoggingBean;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99dd4aae/sshd-core/src/test/java/org/apache/sshd/common/AttributeStoreTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/common/AttributeStoreTest.java b/sshd-core/src/test/java/org/apache/sshd/common/AttributeStoreTest.java
index 741045e..f30ba0b 100644
--- a/sshd-core/src/test/java/org/apache/sshd/common/AttributeStoreTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/common/AttributeStoreTest.java
@@ -21,7 +21,6 @@ package org.apache.sshd.common;

import java.util.concurrent.atomic.AtomicInteger;

-import org.apache.sshd.common.AttributeRepository.AttributeKey;
import org.apache.sshd.common.channel.Channel;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.util.test.BaseTestSupport;
l***@apache.org
2018-11-07 18:01:05 UTC
Permalink
[SSHD-860] Define SshAgent#getIdentities as returning an Iterable rather than a List


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/c507cb00
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/c507cb00
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/c507cb00

Branch: refs/heads/master
Commit: c507cb00983c01fe207e4165f0d751bb3957730e
Parents: 044a1ca
Author: Lyor Goldstein <***@apache.org>
Authored: Wed Nov 7 08:05:42 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Wed Nov 7 20:06:39 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 4 +++-
.../main/java/org/apache/sshd/agent/SshAgent.java | 3 +--
.../sshd/agent/common/AbstractAgentClient.java | 16 ++++++++++++++--
.../sshd/agent/common/AbstractAgentProxy.java | 2 +-
.../org/apache/sshd/agent/common/AgentDelegate.java | 3 +--
.../java/org/apache/sshd/agent/local/AgentImpl.java | 5 +++--
.../auth/pubkey/UserAuthPublicKeyIterator.java | 13 ++++++++++---
.../test/java/org/apache/sshd/agent/AgentTest.java | 13 ++++++++-----
8 files changed, 41 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c507cb00/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index f518b79..0f44a1b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -23,4 +23,6 @@ accept also an `AttributeRepository` connection context argument (propagated fro
`ClientSessionCreator#connect` invocation).

* `FilePasswordProvider` has an extra method (`handleDecodeAttemptResult`) that enables
-user to try and repeat an encrypted private key decoding using a different password.
\ No newline at end of file
+user to try and repeat an encrypted private key decoding using a different password.
+
+* `SshAgent#getIdentities` returns an `Iterable` rather than a `List`

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c507cb00/sshd-core/src/main/java/org/apache/sshd/agent/SshAgent.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/SshAgent.java b/sshd-core/src/main/java/org/apache/sshd/agent/SshAgent.java
index dc5b832..c9ce8e7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/SshAgent.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/SshAgent.java
@@ -21,7 +21,6 @@ package org.apache.sshd.agent;
import java.io.IOException;
import java.security.KeyPair;
import java.security.PublicKey;
-import java.util.List;
import java.util.Map;

/**
@@ -31,7 +30,7 @@ public interface SshAgent extends java.nio.channels.Channel {

String SSH_AUTHSOCKET_ENV_NAME = "SSH_AUTH_SOCK";

- List<? extends Map.Entry<PublicKey, String>> getIdentities() throws IOException;
+ Iterable<? extends Map.Entry<PublicKey, String>> getIdentities() throws IOException;

byte[] sign(PublicKey key, byte[] data) throws IOException;


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c507cb00/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java b/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java
index 99aa472..07d04ce 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentClient.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.Collection;
+import java.util.LinkedList;
import java.util.Map;

import org.apache.sshd.agent.SshAgent;
@@ -97,7 +98,18 @@ public abstract class AbstractAgentClient extends AbstractLoggingBean {
}
switch (cmd) {
case SshAgentConstants.SSH2_AGENTC_REQUEST_IDENTITIES: {
- Collection<? extends Map.Entry<PublicKey, String>> keys = agent.getIdentities();
+ Iterable<? extends Map.Entry<PublicKey, String>> ids = agent.getIdentities();
+ Collection<? extends Map.Entry<PublicKey, String>> keys;
+ if (ids instanceof Collection<?>) {
+ keys = (Collection<? extends Map.Entry<PublicKey, String>>) ids;
+ } else {
+ Collection<Map.Entry<PublicKey, String>> c = new LinkedList<>();
+ for (Map.Entry<PublicKey, String> i : ids) {
+ c.add(i);
+ }
+ keys = c;
+ }
+
rep.putByte(SshAgentConstants.SSH2_AGENT_IDENTITIES_ANSWER);
rep.putInt(keys.size());
for (Map.Entry<PublicKey, String> key : keys) {
@@ -112,7 +124,7 @@ public abstract class AbstractAgentClient extends AbstractLoggingBean {
int flags = req.getInt();
if (debugEnabled) {
log.debug("SSH2_AGENTC_SIGN_REQUEST key={}, flags=0x{}, data={}",
- signingKey.getAlgorithm(), Integer.toHexString(flags), BufferUtils.toHex(':', data));
+ signingKey.getAlgorithm(), Integer.toHexString(flags), BufferUtils.toHex(':', data));
}
String keyType = ValidateUtils.checkNotNullAndNotEmpty(
KeyUtils.getKeyType(signingKey),

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c507cb00/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java b/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java
index 97a858a..717569d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/common/AbstractAgentProxy.java
@@ -67,7 +67,7 @@ public abstract class AbstractAgentProxy extends AbstractLoggingBean implements
}

@Override
- public List<? extends Map.Entry<PublicKey, String>> getIdentities() throws IOException {
+ public Iterable<? extends Map.Entry<PublicKey, String>> getIdentities() throws IOException {
int cmd = SshAgentConstants.SSH2_AGENTC_REQUEST_IDENTITIES;
int okcmd = SshAgentConstants.SSH2_AGENT_IDENTITIES_ANSWER;
if (FactoryManager.AGENT_FORWARDING_TYPE_IETF.equals(channelType)) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c507cb00/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentDelegate.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentDelegate.java b/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentDelegate.java
index 1bd9704..8d1c488 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentDelegate.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentDelegate.java
@@ -21,7 +21,6 @@ package org.apache.sshd.agent.common;
import java.io.IOException;
import java.security.KeyPair;
import java.security.PublicKey;
-import java.util.List;
import java.util.Map;

import org.apache.sshd.agent.SshAgent;
@@ -45,7 +44,7 @@ public class AgentDelegate implements SshAgent {
}

@Override
- public List<? extends Map.Entry<PublicKey, String>> getIdentities() throws IOException {
+ public Iterable<? extends Map.Entry<PublicKey, String>> getIdentities() throws IOException {
return agent.getIdentities();
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c507cb00/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
index eeffb98..e230be6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentImpl.java
@@ -60,7 +60,7 @@ public class AgentImpl implements SshAgent {
}

@Override
- public List<? extends Map.Entry<PublicKey, String>> getIdentities() throws IOException {
+ public Iterable<? extends Map.Entry<PublicKey, String>> getIdentities() throws IOException {
if (!isOpen()) {
throw new SshException("Agent closed");
}
@@ -138,7 +138,8 @@ public class AgentImpl implements SshAgent {
}
}

- protected static Map.Entry<KeyPair, String> getKeyPair(Collection<? extends Map.Entry<KeyPair, String>> keys, PublicKey key) {
+ protected static Map.Entry<KeyPair, String> getKeyPair(
+ Collection<? extends Map.Entry<KeyPair, String>> keys, PublicKey key) {
if (GenericUtils.isEmpty(keys) || (key == null)) {
return null;
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c507cb00/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
index 02ce1dc..84414a0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
@@ -21,9 +21,11 @@ package org.apache.sshd.client.auth.pubkey;

import java.io.IOException;
import java.nio.channels.Channel;
+import java.security.PublicKey;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -56,9 +58,14 @@ public class UserAuthPublicKeyIterator extends AbstractKeyPairIterator<PublicKey
if (factory != null) {
try {
agent = Objects.requireNonNull(factory.createClient(manager), "No agent created");
- identities.add(agent.getIdentities()
- .stream()
- .map(kp -> new KeyAgentIdentity(agent, kp.getKey(), kp.getValue())));
+ Iterable<? extends Map.Entry<PublicKey, String>> agentIds = agent.getIdentities();
+ Collection<KeyAgentIdentity> ids = new LinkedList<>();
+ for (Map.Entry<PublicKey, String> kp : agentIds) {
+ ids.add(new KeyAgentIdentity(agent, kp.getKey(), kp.getValue()));
+ }
+ if (!ids.isEmpty()) {
+ identities.add(ids.stream());
+ }
} catch (Exception e) {
try {
closeAgent();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c507cb00/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
index dffb00b..8f3e4eb 100644
--- a/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/agent/AgentTest.java
@@ -24,7 +24,7 @@ import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.PublicKey;
-import java.util.List;
+import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@@ -82,20 +82,23 @@ public class AgentTest extends BaseTestSupport {
String authSocket = agent.start();

try (SshAgent client = new AgentClient(authSocket)) {
- List<? extends Map.Entry<PublicKey, String>> keys = client.getIdentities();
+ Iterable<? extends Map.Entry<PublicKey, String>> keys = client.getIdentities();
assertNotNull("No initial identities", keys);
- assertEquals("Unexpected initial identities size", 0, keys.size());
+ assertObjectInstanceOf("Non collection initial identities", Collection.class, keys);
+ assertEquals("Unexpected initial identities size", 0, ((Collection<?>) keys).size());

KeyPair k = createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
client.addIdentity(k, "");
keys = client.getIdentities();
assertNotNull("No registered identities after add", keys);
- assertEquals("Mismatched registered keys size", 1, keys.size());
+ assertObjectInstanceOf("Non collection registered identities", Collection.class, keys);
+ assertEquals("Mismatched registered keys size", 1, ((Collection<?>) keys).size());

client.removeIdentity(k.getPublic());
keys = client.getIdentities();
assertNotNull("No registered identities after remove", keys);
- assertEquals("Registered keys size not empty", 0, keys.size());
+ assertObjectInstanceOf("Non collection removed identities", Collection.class, keys);
+ assertEquals("Registered keys size not empty", 0, ((Collection<?>) keys).size());

client.removeAllIdentities();
}
l***@apache.org
2018-11-07 18:01:08 UTC
Permalink
[SSHD-860] Using lazy iterator in AuthenticationIdentitiesProvider#wrap


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/044a1ca8
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/044a1ca8
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/044a1ca8

Branch: refs/heads/master
Commit: 044a1ca8dbdbfdd386108a571d5c130b53e4432b
Parents: 99dd4aa
Author: Lyor Goldstein <***@apache.org>
Authored: Wed Nov 7 07:50:11 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Wed Nov 7 20:06:39 2018 +0200

----------------------------------------------------------------------
.../auth/AuthenticationIdentitiesProvider.java | 31 +----
.../apache/sshd/common/util/GenericUtils.java | 116 ++++++++++++++++++-
.../sshd/common/util/GenericUtilsTest.java | 57 +++++++++
3 files changed, 175 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/044a1ca8/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java b/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
index cfd1f85..3fa61ba 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
@@ -20,11 +20,7 @@
package org.apache.sshd.client.auth;

import java.security.KeyPair;
-import java.util.Collection;
-import java.util.Collections;
import java.util.Comparator;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;

import org.apache.sshd.client.auth.password.PasswordIdentityProvider;
@@ -87,38 +83,17 @@ public interface AuthenticationIdentitiesProvider extends KeyIdentityProvider, P
return new AuthenticationIdentitiesProvider() {
@Override
public Iterable<KeyPair> loadKeys() {
- return selectIdentities(KeyPair.class);
+ return GenericUtils.lazySelectMatchingTypes(identities, KeyPair.class);
}

@Override
public Iterable<String> loadPasswords() {
- return selectIdentities(String.class);
+ return GenericUtils.lazySelectMatchingTypes(identities, String.class);
}

@Override
public Iterable<?> loadIdentities() {
- return selectIdentities(Object.class);
- }
-
- // NOTE: returns a NEW Collection on every call so that the original
- // identities remain unchanged
- private <T> Collection<T> selectIdentities(Class<T> type) {
- Collection<T> matches = null;
- for (Iterator<?> iter = GenericUtils.iteratorOf(identities); iter.hasNext();) {
- Object o = iter.next();
- Class<?> t = o.getClass();
- if (!type.isAssignableFrom(t)) {
- continue;
- }
-
- if (matches == null) {
- matches = new LinkedList<>();
- }
-
- matches.add(type.cast(o));
- }
-
- return (matches == null) ? Collections.<T>emptyList() : matches;
+ return GenericUtils.lazySelectMatchingTypes(identities, Object.class);
}
};
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/044a1ca8/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java
index c924d1e..52cf171 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -36,6 +36,7 @@ import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
+import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
@@ -867,6 +868,118 @@ public final class GenericUtils {
}

/**
+ * @param <T> Generic selected identities type
+ * @param The source values - ignored if {@code null}
+ * @param type The (never @code null) type of values to select - any value
+ * whose type is assignable to this type will be selected by the iterator.
+ * @return {@link Iterable} whose {@link Iterator} selects only values
+ * matching the specific type. <b>Note:</b> the matching values are not
+ * pre-calculated (hence the &quot;lazy&quot; denomination) - i.e.,
+ * the match is performed only when {@link Iterator#hasNext()} is called.
+ */
+ public static <T> Iterable<T> lazySelectMatchingTypes(Iterable<?> values, Class<T> type) {
+ Objects.requireNonNull(type, "No type selector specified");
+ if (values == null) {
+ return Collections.emptyList();
+ }
+
+ return new Iterable<T>() {
+ @Override
+ public Iterator<T> iterator() {
+ return lazySelectMatchingTypes(values.iterator(), type);
+ }
+
+ @Override
+ public String toString() {
+ return Iterable.class.getSimpleName() + "[lazy-select](" + type.getSimpleName() + ")";
+ }
+ };
+ }
+
+ /**
+ * @param <T> Generic selected identities type
+ * @param The source values - ignored if {@code null}
+ * @param type The (never @code null) type of values to select - any value
+ * whose type is assignable to this type will be selected by the iterator.
+ * @return An {@link Iterator} whose {@code next()} call selects only values
+ * matching the specific type. <b>Note:</b> the matching values are not
+ * pre-calculated (hence the &quot;lazy&quot; denomination) - i.e.,
+ * the match is performed only when {@link Iterator#hasNext()} is called.
+ */
+ public static <T> Iterator<T> lazySelectMatchingTypes(Iterator<?> values, Class<T> type) {
+ Objects.requireNonNull(type, "No type selector specified");
+ if (values == null) {
+ return Collections.emptyIterator();
+ }
+
+ return new Iterator<T>() {
+ private boolean finished;
+ private T nextValue;
+
+ @Override
+ public boolean hasNext() {
+ if (finished) {
+ return false;
+ }
+
+ nextValue = selectNextMatchingValue(values, type);
+ if (nextValue == null) {
+ finished = true;
+ }
+
+ return !finished;
+ }
+
+ @Override
+ public T next() {
+ if (finished) {
+ throw new NoSuchElementException("All values have been exhausted");
+ }
+ if (nextValue == null) {
+ throw new IllegalStateException("'next()' called without asking 'hasNext()'");
+ }
+
+ T v = nextValue;
+ nextValue = null; // so it will be re-fetched when 'hasNext' is called
+ return v;
+ }
+
+ @Override
+ public String toString() {
+ return Iterator.class.getSimpleName() + "[lazy-select](" + type.getSimpleName() + ")";
+ }
+ };
+ }
+
+ /**
+ * @param <T> Generic return type
+ * @param The source values - ignored if {@code null}
+ * @param type The (never @code null) type of values to select - any value
+ * whose type is assignable to this type will be selected by the iterator.
+ * @return The first value that matches the specified type - {@code null} if none found
+ */
+ public static <T> T selectNextMatchingValue(Iterator<?> values, Class<T> type) {
+ Objects.requireNonNull(type, "No type selector specified");
+ if (values == null) {
+ return null;
+ }
+
+ while (values.hasNext()) {
+ Object o = values.next();
+ if (o == null) {
+ continue;
+ }
+
+ Class<?> t = o.getClass();
+ if (type.isAssignableFrom(t)) {
+ return type.cast(o);
+ }
+ }
+
+ return null;
+ }
+
+ /**
* Wraps a group of {@link Supplier}s of {@link Iterable} instances into a &quot;unified&quot;
* {@link Iterable} of their values, in the same order as the suppliers - i.e., once the values
* from a specific supplier are exhausted, the next one is consulted, and so on, until all
@@ -876,7 +989,8 @@ public final class GenericUtils {
* @param providers The providers - ignored if {@code null} (i.e., return an empty iterable instance)
* @return The wrapping instance
*/
- public static <T> Iterable<T> multiIterableSuppliers(Iterable<? extends Supplier<? extends Iterable<? extends T>>> providers) {
+ public static <T> Iterable<T> multiIterableSuppliers(
+ Iterable<? extends Supplier<? extends Iterable<? extends T>>> providers) {
return () -> stream(providers).<T>flatMap(s -> stream(s.get())).map(Function.identity()).iterator();
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/044a1ca8/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
index 2b25f4a..8470385 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
@@ -19,10 +19,21 @@

package org.apache.sshd.common.util;

+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.temporal.Temporal;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;

import org.apache.sshd.util.test.JUnitTestSupport;
import org.apache.sshd.util.test.NoIoTestCase;
@@ -173,4 +184,50 @@ public class GenericUtilsTest extends JUnitTestSupport {
assertEquals("s1 vs. s2", Integer.signum(s1.compareTo(s2)), Integer.signum(GenericUtils.compare(c1, c2)));
assertEquals("s2 vs. s1", Integer.signum(s2.compareTo(s1)), Integer.signum(GenericUtils.compare(c2, c1)));
}
+
+ @Test
+ public void testLazySelectMatchingTypes() {
+ Collection<String> strings = Arrays.asList(
+ getCurrentTestName(),
+ getClass().getSimpleName(),
+ getClass().getPackage().getName());
+ Collection<Temporal> times = Arrays.asList(
+ LocalDateTime.now(),
+ LocalTime.now(),
+ LocalDate.now());
+ List<Object> values = Stream.concat(strings.stream(), times.stream()).collect(Collectors.toList());
+ AtomicInteger matchCount = new AtomicInteger(0);
+ for (int index = 1, count = values.size(); index <= count; index++) {
+ Collections.shuffle(values);
+ Class<?> type = ((index & 0x01) == 0) ? String.class : Temporal.class;
+ Iterator<?> lazy = GenericUtils.lazySelectMatchingTypes(
+ new Iterator<Object>() {
+ private final Iterator<?> iter = values.iterator();
+
+ {
+ matchCount.set(0);
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ @Override
+ public Object next() {
+ Object v = iter.next();
+ if (type.isInstance(v)) {
+ matchCount.incrementAndGet();
+ }
+ return v;
+ }
+ }, type);
+ Set<?> expected = (type == String.class) ? new HashSet<>(strings) : new HashSet<>(times);
+ for (int c = 1; lazy.hasNext(); c++) {
+ Object o = lazy.next();
+ assertEquals("Mismatched match count for " + o, c, matchCount.get());
+ assertTrue("Unexpected value: " + o, expected.remove(o));
+ }
+ }
+ }
}
l***@apache.org
2018-11-07 18:01:07 UTC
Permalink
[SSHD-860] UserAuthPublicKeyIterator uses lazy loading of public key identities both from agent and client session


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/2c2982d6
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/2c2982d6
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/2c2982d6

Branch: refs/heads/master
Commit: 2c2982d67f39eeafa938ba510f2bc4f126e3b72c
Parents: c507cb0
Author: Lyor Goldstein <***@apache.org>
Authored: Wed Nov 7 12:16:37 2018 +0200
Committer: Lyor Goldstein <***@apache.org>
Committed: Wed Nov 7 20:06:39 2018 +0200

----------------------------------------------------------------------
CHANGES.md | 6 +
.../auth/AuthenticationIdentitiesProvider.java | 8 +-
.../apache/sshd/common/util/GenericUtils.java | 85 -----------
.../util/helper/LazyIterablesConcatenator.java | 114 ++++++++++++++
.../util/helper/LazyMatchingTypeIterable.java | 82 ++++++++++
.../util/helper/LazyMatchingTypeIterator.java | 105 +++++++++++++
.../sshd/common/util/GenericUtilsTest.java | 57 -------
.../helper/LazyIterablesConcatenatorTest.java | 71 +++++++++
.../helper/LazyMatchingTypeIteratorTest.java | 98 ++++++++++++
.../client/auth/pubkey/KeyPairIdentity.java | 4 +-
.../auth/pubkey/UserAuthPublicKeyIterator.java | 152 +++++++++++++++----
11 files changed, 606 insertions(+), 176 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/CHANGES.md
----------------------------------------------------------------------
diff --git a/CHANGES.md b/CHANGES.md
index 0f44a1b..c43339c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -26,3 +26,9 @@ accept also an `AttributeRepository` connection context argument (propagated fro
user to try and repeat an encrypted private key decoding using a different password.

* `SshAgent#getIdentities` returns an `Iterable` rather than a `List`
+
+
+## Behavioral changes
+
+* [SSHD-860](https://issues.apache.org/jira/browse/SSHD-860) `UserAuthPublicKeyIterator` uses lazy loading
+of public key identities both from agent and client session

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java b/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
index 3fa61ba..ee7c856 100644
--- a/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
+++ b/sshd-common/src/main/java/org/apache/sshd/client/auth/AuthenticationIdentitiesProvider.java
@@ -26,7 +26,7 @@ import java.util.List;
import org.apache.sshd.client.auth.password.PasswordIdentityProvider;
import org.apache.sshd.common.config.keys.KeyUtils;
import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
-import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.helper.LazyMatchingTypeIterable;

/**
* @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
@@ -83,17 +83,17 @@ public interface AuthenticationIdentitiesProvider extends KeyIdentityProvider, P
return new AuthenticationIdentitiesProvider() {
@Override
public Iterable<KeyPair> loadKeys() {
- return GenericUtils.lazySelectMatchingTypes(identities, KeyPair.class);
+ return LazyMatchingTypeIterable.lazySelectMatchingTypes(identities, KeyPair.class);
}

@Override
public Iterable<String> loadPasswords() {
- return GenericUtils.lazySelectMatchingTypes(identities, String.class);
+ return LazyMatchingTypeIterable.lazySelectMatchingTypes(identities, String.class);
}

@Override
public Iterable<?> loadIdentities() {
- return GenericUtils.lazySelectMatchingTypes(identities, Object.class);
+ return LazyMatchingTypeIterable.lazySelectMatchingTypes(identities, Object.class);
}
};
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java
index 52cf171..b84dbd4 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -36,7 +36,6 @@ import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
-import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
@@ -868,90 +867,6 @@ public final class GenericUtils {
}

/**
- * @param <T> Generic selected identities type
- * @param The source values - ignored if {@code null}
- * @param type The (never @code null) type of values to select - any value
- * whose type is assignable to this type will be selected by the iterator.
- * @return {@link Iterable} whose {@link Iterator} selects only values
- * matching the specific type. <b>Note:</b> the matching values are not
- * pre-calculated (hence the &quot;lazy&quot; denomination) - i.e.,
- * the match is performed only when {@link Iterator#hasNext()} is called.
- */
- public static <T> Iterable<T> lazySelectMatchingTypes(Iterable<?> values, Class<T> type) {
- Objects.requireNonNull(type, "No type selector specified");
- if (values == null) {
- return Collections.emptyList();
- }
-
- return new Iterable<T>() {
- @Override
- public Iterator<T> iterator() {
- return lazySelectMatchingTypes(values.iterator(), type);
- }
-
- @Override
- public String toString() {
- return Iterable.class.getSimpleName() + "[lazy-select](" + type.getSimpleName() + ")";
- }
- };
- }
-
- /**
- * @param <T> Generic selected identities type
- * @param The source values - ignored if {@code null}
- * @param type The (never @code null) type of values to select - any value
- * whose type is assignable to this type will be selected by the iterator.
- * @return An {@link Iterator} whose {@code next()} call selects only values
- * matching the specific type. <b>Note:</b> the matching values are not
- * pre-calculated (hence the &quot;lazy&quot; denomination) - i.e.,
- * the match is performed only when {@link Iterator#hasNext()} is called.
- */
- public static <T> Iterator<T> lazySelectMatchingTypes(Iterator<?> values, Class<T> type) {
- Objects.requireNonNull(type, "No type selector specified");
- if (values == null) {
- return Collections.emptyIterator();
- }
-
- return new Iterator<T>() {
- private boolean finished;
- private T nextValue;
-
- @Override
- public boolean hasNext() {
- if (finished) {
- return false;
- }
-
- nextValue = selectNextMatchingValue(values, type);
- if (nextValue == null) {
- finished = true;
- }
-
- return !finished;
- }
-
- @Override
- public T next() {
- if (finished) {
- throw new NoSuchElementException("All values have been exhausted");
- }
- if (nextValue == null) {
- throw new IllegalStateException("'next()' called without asking 'hasNext()'");
- }
-
- T v = nextValue;
- nextValue = null; // so it will be re-fetched when 'hasNext' is called
- return v;
- }
-
- @Override
- public String toString() {
- return Iterator.class.getSimpleName() + "[lazy-select](" + type.getSimpleName() + ")";
- }
- };
- }
-
- /**
* @param <T> Generic return type
* @param The source values - ignored if {@code null}
* @param type The (never @code null) type of values to select - any value

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyIterablesConcatenator.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyIterablesConcatenator.java b/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyIterablesConcatenator.java
new file mode 100644
index 0000000..2e1b042
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyIterablesConcatenator.java
@@ -0,0 +1,114 @@
+/*
+ * 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.sshd.common.util.helper;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Creates a &quot;smooth&quot; wrapping {@link Iterable} using several
+ * underlying ones to provide the values. The &quot;lazy&quot; denomination
+ * is due to the fact that no iterable is consulted until the one(s) before
+ * it have been fully exhausted.
+ *
+ * @param <T> Type of element being iterared
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class LazyIterablesConcatenator<T> implements Iterable<T> {
+ private final Iterable<? extends Iterable<? extends T>> iterables;
+
+ public LazyIterablesConcatenator(Iterable<? extends Iterable<? extends T>> iterables) {
+ this.iterables = iterables;
+ }
+
+ public Iterable<? extends Iterable<? extends T>> getIterables() {
+ return iterables;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return new Iterator<T>() {
+ @SuppressWarnings("synthetic-access")
+ private final Iterator<? extends Iterable<? extends T>> itit =
+ (iterables == null) ? Collections.emptyIterator() : iterables.iterator();
+ private Iterator<? extends T> currentIterator;
+ private boolean finished;
+
+ @Override
+ public boolean hasNext() {
+ if (finished) {
+ return false;
+ }
+
+ // Do we have a current iterator, and if so does it still have values in it
+ if ((currentIterator != null) && currentIterator.hasNext()) {
+ return true;
+ }
+
+ while (itit.hasNext()) {
+ Iterable<? extends T> currentIterable = itit.next();
+ currentIterator = currentIterable.iterator();
+ if (currentIterator.hasNext()) {
+ return true;
+ }
+ }
+
+ // exhausted all
+ finished = true;
+ return false;
+ }
+
+ @Override
+ public T next() {
+ if (finished) {
+ throw new NoSuchElementException("All elements have been exhausted");
+ }
+
+ if (currentIterator == null) {
+ throw new IllegalStateException("'next()' called without a preceding 'hasNext()' query");
+ }
+
+ return currentIterator.next();
+ }
+
+ @Override
+ public String toString() {
+ return Iterator.class.getSimpleName() + "[lazy-concat]";
+ }
+ };
+ }
+
+ @Override
+ public String toString() {
+ return Iterable.class.getSimpleName() + "[lazy-concat]";
+ }
+
+ /**
+ * @param <T> Type if iterated element
+ * @param iterables The iterables to concatenate - ignored if {@code null}
+ * @return An {@link Iterable} that goes over all the elements in the wrapped
+ * iterables one after the other. The denomination &quot;lazy&quot; indicates
+ * that no iterable is consulted until the previous one has been fully exhausted.
+ */
+ public static <T> Iterable<T> lazyConcatenateIterables(Iterable<? extends Iterable<? extends T>> iterables) {
+ return (iterables == null) ? Collections.emptyList() : new LazyIterablesConcatenator<>(iterables);
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIterable.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIterable.java b/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIterable.java
new file mode 100644
index 0000000..267c661
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIterable.java
@@ -0,0 +1,82 @@
+/*
+ * 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.sshd.common.util.helper;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Objects;
+
+/**
+ * Provides a selective {@link Iterable} over values that match a
+ * specific type out of all available. The &quot;lazy&quot; denomination
+ * is due to the fact that the next matching value is calculated on-the-fly
+ * every time {@link Iterator#hasNext()} is called
+ *
+ * @param <T> Type of element being selected
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class LazyMatchingTypeIterable<T> implements Iterable<T> {
+ private final Iterable<?> values;
+ private final Class<T> type;
+
+ public LazyMatchingTypeIterable(Iterable<?> values, Class<T> type) {
+ this.values = values;
+ this.type = Objects.requireNonNull(type, "No type selector specified");
+ }
+
+ public Iterable<?> getValues() {
+ return values;
+ }
+
+ public Class<T> getType() {
+ return type;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ Iterable<?> vals = getValues();
+ if (vals == null) {
+ return Collections.emptyIterator();
+ }
+
+ return LazyMatchingTypeIterator.lazySelectMatchingTypes(vals.iterator(), getType());
+ }
+
+ @Override
+ public String toString() {
+ Class<?> t = getType();
+ return Iterable.class.getSimpleName() + "[lazy-select](" + t.getSimpleName() + ")";
+ }
+
+ /**
+ * @param <T> Type if iterated element
+ * @param The source values - ignored if {@code null}
+ * @param type The (never @code null) type of values to select - any value
+ * whose type is assignable to this type will be selected by the iterator.
+ * @return {@link Iterable} whose {@link Iterator} selects only values
+ * matching the specific type. <b>Note:</b> the matching values are not
+ * pre-calculated (hence the &quot;lazy&quot; denomination) - i.e.,
+ * the match is performed only when {@link Iterator#hasNext()} is called.
+ */
+ public static <T> Iterable<T> lazySelectMatchingTypes(Iterable<?> values, Class<T> type) {
+ Objects.requireNonNull(type, "No type selector specified");
+ return (values == null) ? Collections.emptyList() : new LazyMatchingTypeIterable<>(values, type);
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIterator.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIterator.java b/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIterator.java
new file mode 100644
index 0000000..d0fd18c
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIterator.java
@@ -0,0 +1,105 @@
+/*
+ * 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.sshd.common.util.helper;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * An {@link Iterator} that selects only objects of a certain type from
+ * the underlying available ones. The &quot;lazy&quot; denomination is due
+ * to the fact that selection occurs only when {@link #hasNext()} is called
+ *
+ * @param <T> Type of iterated element
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class LazyMatchingTypeIterator<T> implements Iterator<T> {
+ protected boolean finished;
+ protected T nextValue;
+
+ private final Iterator<?> values;
+ private final Class<T> type;
+
+ public LazyMatchingTypeIterator(Iterator<?> values, Class<T> type) {
+ this.values = values;
+ this.type = Objects.requireNonNull(type, "No type selector specified");
+ }
+
+ public Iterator<?> getValues() {
+ return values;
+ }
+
+ public Class<T> getType() {
+ return type;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (finished) {
+ return false;
+ }
+
+ nextValue = GenericUtils.selectNextMatchingValue(getValues(), getType());
+ if (nextValue == null) {
+ finished = true;
+ }
+
+ return !finished;
+ }
+
+ @Override
+ public T next() {
+ if (finished) {
+ throw new NoSuchElementException("All values have been exhausted");
+ }
+ if (nextValue == null) {
+ throw new IllegalStateException("'next()' called without asking 'hasNext()'");
+ }
+
+ T v = nextValue;
+ nextValue = null; // so it will be re-fetched when 'hasNext' is called
+ return v;
+ }
+
+ @Override
+ public String toString() {
+ Class<?> t = getType();
+ return Iterator.class.getSimpleName() + "[lazy-select](" + t.getSimpleName() + ")";
+ }
+
+ /**
+ * @param <T> Type if iterated element
+ * @param The source values - ignored if {@code null}
+ * @param type The (never @code null) type of values to select - any value
+ * whose type is assignable to this type will be selected by the iterator.
+ * @return An {@link Iterator} whose {@code next()} call selects only values
+ * matching the specific type. <b>Note:</b> the matching values are not
+ * pre-calculated (hence the &quot;lazy&quot; denomination) - i.e.,
+ * the match is performed only when {@link Iterator#hasNext()} is called.
+ */
+ public static <T> Iterator<T> lazySelectMatchingTypes(Iterator<?> values, Class<T> type) {
+ Objects.requireNonNull(type, "No type selector specified");
+ return (values == null) ? Collections.emptyIterator() : new LazyMatchingTypeIterator<>(values, type);
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
index 8470385..2b25f4a 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
@@ -19,21 +19,10 @@

package org.apache.sshd.common.util;

-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.temporal.Temporal;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;

import org.apache.sshd.util.test.JUnitTestSupport;
import org.apache.sshd.util.test.NoIoTestCase;
@@ -184,50 +173,4 @@ public class GenericUtilsTest extends JUnitTestSupport {
assertEquals("s1 vs. s2", Integer.signum(s1.compareTo(s2)), Integer.signum(GenericUtils.compare(c1, c2)));
assertEquals("s2 vs. s1", Integer.signum(s2.compareTo(s1)), Integer.signum(GenericUtils.compare(c2, c1)));
}
-
- @Test
- public void testLazySelectMatchingTypes() {
- Collection<String> strings = Arrays.asList(
- getCurrentTestName(),
- getClass().getSimpleName(),
- getClass().getPackage().getName());
- Collection<Temporal> times = Arrays.asList(
- LocalDateTime.now(),
- LocalTime.now(),
- LocalDate.now());
- List<Object> values = Stream.concat(strings.stream(), times.stream()).collect(Collectors.toList());
- AtomicInteger matchCount = new AtomicInteger(0);
- for (int index = 1, count = values.size(); index <= count; index++) {
- Collections.shuffle(values);
- Class<?> type = ((index & 0x01) == 0) ? String.class : Temporal.class;
- Iterator<?> lazy = GenericUtils.lazySelectMatchingTypes(
- new Iterator<Object>() {
- private final Iterator<?> iter = values.iterator();
-
- {
- matchCount.set(0);
- }
-
- @Override
- public boolean hasNext() {
- return iter.hasNext();
- }
-
- @Override
- public Object next() {
- Object v = iter.next();
- if (type.isInstance(v)) {
- matchCount.incrementAndGet();
- }
- return v;
- }
- }, type);
- Set<?> expected = (type == String.class) ? new HashSet<>(strings) : new HashSet<>(times);
- for (int c = 1; lazy.hasNext(); c++) {
- Object o = lazy.next();
- assertEquals("Mismatched match count for " + o, c, matchCount.get());
- assertTrue("Unexpected value: " + o, expected.remove(o));
- }
- }
- }
}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-common/src/test/java/org/apache/sshd/common/util/helper/LazyIterablesConcatenatorTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/helper/LazyIterablesConcatenatorTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/helper/LazyIterablesConcatenatorTest.java
new file mode 100644
index 0000000..06d2e7d
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/helper/LazyIterablesConcatenatorTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.sshd.common.util.helper;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class LazyIterablesConcatenatorTest extends JUnitTestSupport {
+ public LazyIterablesConcatenatorTest() {
+ super();
+ }
+
+ @Test
+ public void testLazyConcatenateIterables() {
+ Collection<String> l1 = Arrays.asList(
+ getCurrentTestName(),
+ getClass().getSimpleName(),
+ getClass().getPackage().getName());
+ Collection<String> l2 = Arrays.asList(
+ LocalDateTime.now().toString(),
+ LocalTime.now().toString(),
+ LocalDate.now().toString());
+ List<String> expected = Stream.concat(l1.stream(), l2.stream()).collect(Collectors.toList());
+ Iterable<String> iter = LazyIterablesConcatenator.lazyConcatenateIterables(Arrays.asList(l1, l2));
+ List<String> actual = new ArrayList<>(expected.size());
+ for (int index = 1, count = expected.size(); index <= count; index++) {
+ actual.clear();
+
+ for (String s : iter) {
+ actual.add(s);
+ }
+
+ assertListEquals("Attempt #" + index, expected, actual);
+ }
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-common/src/test/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIteratorTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIteratorTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIteratorTest.java
new file mode 100644
index 0000000..43a0d70
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/helper/LazyMatchingTypeIteratorTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.sshd.common.util.helper;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.temporal.Temporal;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class LazyMatchingTypeIteratorTest extends JUnitTestSupport {
+ public LazyMatchingTypeIteratorTest() {
+ super();
+ }
+
+ @Test
+ public void testLazySelectMatchingTypes() {
+ Collection<String> strings = Arrays.asList(
+ getCurrentTestName(),
+ getClass().getSimpleName(),
+ getClass().getPackage().getName());
+ Collection<Temporal> times = Arrays.asList(
+ LocalDateTime.now(),
+ LocalTime.now(),
+ LocalDate.now());
+ List<Object> values = Stream.concat(strings.stream(), times.stream()).collect(Collectors.toList());
+ AtomicInteger matchCount = new AtomicInteger(0);
+ for (int index = 1, count = values.size(); index <= count; index++) {
+ Collections.shuffle(values);
+ Class<?> type = ((index & 0x01) == 0) ? String.class : Temporal.class;
+ Iterator<?> lazy = LazyMatchingTypeIterator.lazySelectMatchingTypes(
+ new Iterator<Object>() {
+ private final Iterator<?> iter = values.iterator();
+
+ {
+ matchCount.set(0);
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ @Override
+ public Object next() {
+ Object v = iter.next();
+ if (type.isInstance(v)) {
+ matchCount.incrementAndGet();
+ }
+ return v;
+ }
+ }, type);
+ Set<?> expected = (type == String.class) ? new HashSet<>(strings) : new HashSet<>(times);
+ for (int c = 1; lazy.hasNext(); c++) {
+ Object o = lazy.next();
+ assertEquals("Mismatched match count for " + o, c, matchCount.get());
+ assertTrue("Unexpected value: " + o, expected.remove(o));
+ }
+ }
+ }
+}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
index b53c111..deb158c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/KeyPairIdentity.java
@@ -41,8 +41,8 @@ public class KeyPairIdentity implements PublicKeyIdentity {

public KeyPairIdentity(SignatureFactoriesManager primary, SignatureFactoriesManager secondary, KeyPair pair) {
this.signatureFactories = ValidateUtils.checkNotNullAndNotEmpty(
- SignatureFactoriesManager.resolveSignatureFactories(primary, secondary),
- "No available signature factories");
+ SignatureFactoriesManager.resolveSignatureFactories(primary, secondary),
+ "No available signature factories");
this.pair = Objects.requireNonNull(pair, "No key pair");
}


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/2c2982d6/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
index 84414a0..73e34ee 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKeyIterator.java
@@ -21,15 +21,17 @@ package org.apache.sshd.client.auth.pubkey;

import java.io.IOException;
import java.nio.channels.Channel;
+import java.security.KeyPair;
import java.security.PublicKey;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Stream;
+import java.util.concurrent.atomic.AtomicReference;

import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentFactory;
@@ -37,13 +39,13 @@ import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
import org.apache.sshd.common.signature.SignatureFactoriesManager;
-import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.helper.LazyIterablesConcatenator;
+import org.apache.sshd.common.util.helper.LazyMatchingTypeIterator;

/**
* @author <a href="mailto:***@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class UserAuthPublicKeyIterator extends AbstractKeyPairIterator<PublicKeyIdentity> implements Channel {
-
private final AtomicBoolean open = new AtomicBoolean(true);
private Iterator<? extends PublicKeyIdentity> current;
private SshAgent agent;
@@ -51,38 +53,132 @@ public class UserAuthPublicKeyIterator extends AbstractKeyPairIterator<PublicKey
public UserAuthPublicKeyIterator(ClientSession session, SignatureFactoriesManager signatureFactories) throws Exception {
super(session);

- Collection<Stream<? extends PublicKeyIdentity>> identities = new LinkedList<>();
+ try {
+ Collection<Iterable<? extends PublicKeyIdentity>> identities = new ArrayList<>(2);
+ Iterable<? extends PublicKeyIdentity> agentIds = initializeAgentIdentities(session);
+ if (agentIds != null) {
+ identities.add(agentIds);
+ }

- FactoryManager manager = Objects.requireNonNull(session.getFactoryManager(), "No session factory manager");
- SshAgentFactory factory = manager.getAgentFactory();
- if (factory != null) {
+ Iterable<? extends PublicKeyIdentity> sessionIds =
+ initializeSessionIdentities(session, signatureFactories);
+ if (sessionIds != null) {
+ identities.add(sessionIds);
+ }
+
+ if (identities.isEmpty()) {
+ current = Collections.emptyIterator();
+ } else {
+ Iterable<? extends PublicKeyIdentity> keys =
+ LazyIterablesConcatenator.lazyConcatenateIterables(identities);
+ current = LazyMatchingTypeIterator.lazySelectMatchingTypes(keys.iterator(), PublicKeyIdentity.class);
+ }
+ } catch (Exception e) {
try {
- agent = Objects.requireNonNull(factory.createClient(manager), "No agent created");
- Iterable<? extends Map.Entry<PublicKey, String>> agentIds = agent.getIdentities();
- Collection<KeyAgentIdentity> ids = new LinkedList<>();
- for (Map.Entry<PublicKey, String> kp : agentIds) {
- ids.add(new KeyAgentIdentity(agent, kp.getKey(), kp.getValue()));
- }
- if (!ids.isEmpty()) {
- identities.add(ids.stream());
- }
- } catch (Exception e) {
- try {
- closeAgent();
- } catch (Exception err) {
- e.addSuppressed(err);
+ closeAgent();
+ } catch (Exception err) {
+ e.addSuppressed(err);
+ }
+
+ throw e;
+ }
+ }
+
+ protected Iterable<KeyPairIdentity> initializeSessionIdentities(
+ ClientSession session, SignatureFactoriesManager signatureFactories) {
+ return new Iterable<KeyPairIdentity>() {
+ private final String sessionId = session.toString();
+ private final AtomicReference<Iterable<KeyPair>> keysHolder = new AtomicReference<>();
+
+ @Override
+ public Iterator<KeyPairIdentity> iterator() {
+ // Lazy load the keys the 1st time the iterator is called
+ if (keysHolder.get() == null) {
+ KeyIdentityProvider sessionKeysProvider = ClientSession.providerOf(session);
+ keysHolder.set(sessionKeysProvider.loadKeys());
}

- throw e;
+ return new Iterator<KeyPairIdentity>() {
+ private final Iterator<KeyPair> keys;
+
+ {
+ @SuppressWarnings("synthetic-access")
+ Iterable<KeyPair> sessionKeys =
+ Objects.requireNonNull(keysHolder.get(), "No session keys available");
+ keys = sessionKeys.iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return keys.hasNext();
+ }
+
+ @Override
+ public KeyPairIdentity next() {
+ KeyPair kp = keys.next();
+ return new KeyPairIdentity(signatureFactories, session, kp);
+ }
+
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public String toString() {
+ return KeyPairIdentity.class.getSimpleName() + "[iterator][" + sessionId + "]";
+ }
+ };
}
+
+ @Override
+ public String toString() {
+ return KeyPairIdentity.class.getSimpleName() + "[iterable][" + sessionId + "]";
+ }
+ };
+ }
+
+ protected Iterable<KeyAgentIdentity> initializeAgentIdentities(ClientSession session) throws IOException {
+ FactoryManager manager = Objects.requireNonNull(session.getFactoryManager(), "No session factory manager");
+ SshAgentFactory factory = manager.getAgentFactory();
+ if (factory == null) {
+ return null;
}

- identities.add(Stream.of(ClientSession.providerOf(session))
- .map(KeyIdentityProvider::loadKeys)
- .flatMap(GenericUtils::stream)
- .map(kp -> new KeyPairIdentity(signatureFactories, session, kp)));
+ agent = Objects.requireNonNull(factory.createClient(manager), "No agent created");
+ return new Iterable<KeyAgentIdentity>() {
+ @SuppressWarnings("synthetic-access")
+ private final Iterable<? extends Map.Entry<PublicKey, String>> agentIds = agent.getIdentities();
+ @SuppressWarnings("synthetic-access")
+ private final String agentId = agent.toString();
+
+ @Override
+ public Iterator<KeyAgentIdentity> iterator() {
+ return new Iterator<KeyAgentIdentity>() {
+ @SuppressWarnings("synthetic-access")
+ private final Iterator<? extends Map.Entry<PublicKey, String>> iter = agentIds.iterator();
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public KeyAgentIdentity next() {
+ Map.Entry<PublicKey, String> kp = iter.next();
+ return new KeyAgentIdentity(agent, kp.getKey(), kp.getValue());
+ }
+
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public String toString() {
+ return KeyAgentIdentity.class.getSimpleName() + "[iterator][" + agentId + "]";
+ }
+ };
+ }

- current = identities.stream().flatMap(r -> r).iterator();
+ @Override
+ public String toString() {
+ return KeyAgentIdentity.class.getSimpleName() + "[iterable][" + agentId + "]";
+ }
+ };
}

@Override

Loading...