You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2018/09/06 16:03:36 UTC

[26/51] [abbrv] mina-sshd git commit: [SSHD-842] Split common utilities code from sshd-core into sshd-common (new artifact)

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/KnownHostHashValue.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/KnownHostHashValue.java b/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/KnownHostHashValue.java
deleted file mode 100644
index 28a3d1f..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/hosts/KnownHostHashValue.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.client.config.hosts;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.Objects;
-
-import org.apache.sshd.common.Factory;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.RuntimeSshException;
-import org.apache.sshd.common.mac.Mac;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.NumberUtils;
-import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.buffer.BufferUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class KnownHostHashValue {
-    /**
-     * Character used to indicate a hashed host pattern
-     */
-    public static final char HASHED_HOST_DELIMITER = '|';
-
-    public static final NamedFactory<Mac> DEFAULT_DIGEST = KnownHostDigest.SHA1;
-
-    private NamedFactory<Mac> digester = DEFAULT_DIGEST;
-    private byte[] saltValue;
-    private byte[] digestValue;
-
-    public KnownHostHashValue() {
-        super();
-    }
-
-    public NamedFactory<Mac> getDigester() {
-        return digester;
-    }
-
-    public void setDigester(NamedFactory<Mac> digester) {
-        this.digester = digester;
-    }
-
-    public byte[] getSaltValue() {
-        return saltValue;
-    }
-
-    public void setSaltValue(byte[] saltValue) {
-        this.saltValue = saltValue;
-    }
-
-    public byte[] getDigestValue() {
-        return digestValue;
-    }
-
-    public void setDigestValue(byte[] digestValue) {
-        this.digestValue = digestValue;
-    }
-
-    /**
-     * Checks if the host matches the hash
-     *
-     * @param host The host name/address - ignored if {@code null}/empty
-     * @return {@code true} if host matches the hash
-     * @throws RuntimeException If entry not properly initialized
-     */
-    public boolean isHostMatch(String host) {
-        if (GenericUtils.isEmpty(host)) {
-            return false;
-        }
-
-        try {
-            byte[] expected = getDigestValue();
-            byte[] actual = calculateHashValue(host, getDigester(), getSaltValue());
-            return Arrays.equals(expected, actual);
-        } catch (Throwable t) {
-            if (t instanceof RuntimeException) {
-                throw (RuntimeException) t;
-            }
-            throw new RuntimeSshException("Failed (" + t.getClass().getSimpleName() + ")"
-                    + " to calculate hash value: " + t.getMessage(), t);
-        }
-    }
-
-    @Override
-    public String toString() {
-        if ((getDigester() == null) || NumberUtils.isEmpty(getSaltValue()) || NumberUtils.isEmpty(getDigestValue())) {
-            return Objects.toString(getDigester(), null)
-                 + "-" + BufferUtils.toHex(':', getSaltValue())
-                 + "-" + BufferUtils.toHex(':', getDigestValue());
-        }
-
-        try {
-            return append(new StringBuilder(Byte.MAX_VALUE), this).toString();
-        } catch (IOException | RuntimeException e) {    // unexpected
-            return e.getClass().getSimpleName() + ": " + e.getMessage();
-        }
-    }
-
-    // see http://nms.lcs.mit.edu/projects/ssh/README.hashed-hosts
-    public static byte[] calculateHashValue(String host, Factory<? extends Mac> factory, byte[] salt) throws Exception {
-        return calculateHashValue(host, factory.create(), salt);
-    }
-
-    public static byte[] calculateHashValue(String host, Mac mac, byte[] salt) throws Exception {
-        mac.init(salt);
-
-        byte[] hostBytes = host.getBytes(StandardCharsets.UTF_8);
-        mac.update(hostBytes);
-        return mac.doFinal();
-    }
-
-    public static <A extends Appendable> A append(A sb, KnownHostHashValue hashValue) throws IOException {
-        return (hashValue == null) ? sb : append(sb, hashValue.getDigester(), hashValue.getSaltValue(), hashValue.getDigestValue());
-    }
-
-    public static <A extends Appendable> A append(A sb, NamedResource factory, byte[] salt, byte[] digest) throws IOException {
-        Base64.Encoder encoder = Base64.getEncoder();
-        sb.append(HASHED_HOST_DELIMITER).append(factory.getName());
-        sb.append(HASHED_HOST_DELIMITER).append(encoder.encodeToString(salt));
-        sb.append(HASHED_HOST_DELIMITER).append(encoder.encodeToString(digest));
-        return sb;
-    }
-
-    public static KnownHostHashValue parse(String patternString) {
-        String pattern = GenericUtils.replaceWhitespaceAndTrim(patternString);
-        return parse(pattern, GenericUtils.isEmpty(pattern) ? null : new KnownHostHashValue());
-    }
-
-    public static <V extends KnownHostHashValue> V parse(String patternString, V value) {
-        String pattern = GenericUtils.replaceWhitespaceAndTrim(patternString);
-        if (GenericUtils.isEmpty(pattern)) {
-            return value;
-        }
-
-        String[] components = GenericUtils.split(pattern, HASHED_HOST_DELIMITER);
-        ValidateUtils.checkTrue(components.length == 4 /* 1st one is empty */, "Invalid hash pattern (insufficient data): %s", pattern);
-        ValidateUtils.checkTrue(GenericUtils.isEmpty(components[0]), "Invalid hash pattern (unexpected extra data): %s", pattern);
-
-        NamedFactory<Mac> factory =
-                ValidateUtils.checkNotNull(KnownHostDigest.fromName(components[1]),
-                        "Invalid hash pattern (unknown digest): %s", pattern);
-        Base64.Decoder decoder = Base64.getDecoder();
-        value.setDigester(factory);
-        value.setSaltValue(decoder.decode(components[2]));
-        value.setDigestValue(decoder.decode(components[3]));
-        return value;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
deleted file mode 100644
index ab9929b..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/BuiltinClientIdentitiesWatcher.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.client.config.keys;
-
-import java.nio.file.Path;
-import java.security.KeyPair;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.Supplier;
-
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.config.keys.BuiltinIdentities;
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.config.keys.KeyUtils;
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class BuiltinClientIdentitiesWatcher extends ClientIdentitiesWatcher {
-    private final boolean supportedOnly;
-
-    public BuiltinClientIdentitiesWatcher(Path keysFolder, boolean supportedOnly,
-            ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
-        this(keysFolder, NamedResource.getNameList(BuiltinIdentities.VALUES), supportedOnly, loader, provider, strict);
-    }
-
-    public BuiltinClientIdentitiesWatcher(Path keysFolder, Collection<String> ids, boolean supportedOnly,
-            ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
-        this(keysFolder, ids, supportedOnly,
-             GenericUtils.supplierOf(Objects.requireNonNull(loader, "No client identity loader")),
-             GenericUtils.supplierOf(Objects.requireNonNull(provider, "No password provider")),
-             strict);
-    }
-
-    public BuiltinClientIdentitiesWatcher(Path keysFolder, boolean supportedOnly,
-            Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
-        this(keysFolder, NamedResource.getNameList(BuiltinIdentities.VALUES), supportedOnly, loader, provider, strict);
-    }
-
-    public BuiltinClientIdentitiesWatcher(Path keysFolder, Collection<String> ids, boolean supportedOnly,
-            Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
-        super(getBuiltinIdentitiesPaths(keysFolder, ids), loader, provider, strict);
-        this.supportedOnly = supportedOnly;
-    }
-
-    public final boolean isSupportedOnly() {
-        return supportedOnly;
-    }
-
-    @Override
-    public Iterable<KeyPair> loadKeys() {
-        return isSupportedOnly() ? loadKeys(this::isSupported) : super.loadKeys();
-    }
-
-    private boolean isSupported(KeyPair kp) {
-        BuiltinIdentities id = BuiltinIdentities.fromKeyPair(kp);
-        if ((id != null) && id.isSupported()) {
-            return true;
-        }
-        if (log.isDebugEnabled()) {
-            log.debug("loadKeys - remove unsupported identity={}, key-type={}, key={}",
-                    id, KeyUtils.getKeyType(kp), KeyUtils.getFingerPrint(kp.getPublic()));
-        }
-        return false;
-    }
-
-    public static List<Path> getDefaultBuiltinIdentitiesPaths(Path keysFolder) {
-        return getBuiltinIdentitiesPaths(keysFolder, NamedResource.getNameList(BuiltinIdentities.VALUES));
-    }
-
-    public static List<Path> getBuiltinIdentitiesPaths(Path keysFolder, Collection<String> ids) {
-        Objects.requireNonNull(keysFolder, "No keys folder");
-        if (GenericUtils.isEmpty(ids)) {
-            return Collections.emptyList();
-        }
-
-        List<Path> paths = new ArrayList<>(ids.size());
-        for (String id : ids) {
-            String fileName = ClientIdentity.getIdentityFileName(id);
-            paths.add(keysFolder.resolve(fileName));
-        }
-
-        return paths;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
deleted file mode 100644
index 094766f..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentitiesWatcher.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.client.config.keys;
-
-import java.nio.file.Path;
-import java.security.KeyPair;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.stream.Stream;
-
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * Watches over a group of files that contains client identities
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ClientIdentitiesWatcher extends AbstractKeyPairProvider implements KeyPairProvider {
-    private final Collection<ClientIdentityProvider> providers;
-
-    public ClientIdentitiesWatcher(Collection<? extends Path> paths,
-            ClientIdentityLoader loader, FilePasswordProvider provider) {
-        this(paths, loader, provider, true);
-    }
-
-    public ClientIdentitiesWatcher(Collection<? extends Path> paths,
-            ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
-        this(paths,
-             GenericUtils.supplierOf(Objects.requireNonNull(loader, "No client identity loader")),
-             GenericUtils.supplierOf(Objects.requireNonNull(provider, "No password provider")),
-             strict);
-    }
-
-    public ClientIdentitiesWatcher(Collection<? extends Path> paths,
-            Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider) {
-        this(paths, loader, provider, true);
-    }
-
-    public ClientIdentitiesWatcher(Collection<? extends Path> paths,
-            Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
-        this(buildProviders(paths, loader, provider, strict));
-    }
-
-    public ClientIdentitiesWatcher(Collection<ClientIdentityProvider> providers) {
-        this.providers = providers;
-    }
-
-    @Override
-    public Iterable<KeyPair> loadKeys() {
-        return loadKeys(null);
-    }
-
-    protected Iterable<KeyPair> loadKeys(Predicate<? super KeyPair> filter) {
-        return () -> {
-            Stream<KeyPair> stream = safeMap(GenericUtils.stream(providers), this::doGetKeyPair);
-            if (filter != null) {
-                stream = stream.filter(filter);
-            }
-            return stream.iterator();
-        };
-    }
-
-    /**
-     * Performs a mapping operation on the stream, discarding any null values
-     * returned by the mapper.
-     *
-     * @param <U> Original type
-     * @param <V> Mapped type
-     * @param stream Original values stream
-     * @param mapper Mapper to target type
-     * @return Mapped stream
-     */
-    protected <U, V> Stream<V> safeMap(Stream<U> stream, Function<? super U, ? extends V> mapper) {
-        return stream.map(u -> Optional.ofNullable(mapper.apply(u)))
-                .filter(Optional::isPresent)
-                .map(Optional::get);
-    }
-
-    protected KeyPair doGetKeyPair(ClientIdentityProvider p) {
-        try {
-            KeyPair kp = p.getClientIdentity();
-            if (kp == null) {
-                if (log.isDebugEnabled()) {
-                    log.debug("loadKeys({}) no key loaded", p);
-                }
-            }
-            return kp;
-        } catch (Throwable e) {
-            log.warn("loadKeys({}) failed ({}) to load key: {}", p, e.getClass().getSimpleName(), e.getMessage());
-            if (log.isDebugEnabled()) {
-                log.debug("loadKeys(" + p + ") key load failure details", e);
-            }
-            return null;
-        }
-    }
-
-    public static List<ClientIdentityProvider> buildProviders(
-            Collection<? extends Path> paths, ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
-        return buildProviders(paths,
-                GenericUtils.supplierOf(Objects.requireNonNull(loader, "No client identity loader")),
-                GenericUtils.supplierOf(Objects.requireNonNull(provider, "No password provider")),
-                strict);
-    }
-
-    public static List<ClientIdentityProvider> buildProviders(
-            Collection<? extends Path> paths, Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
-        if (GenericUtils.isEmpty(paths)) {
-            return Collections.emptyList();
-        }
-
-        return GenericUtils.map(paths, p -> new ClientIdentityFileWatcher(p, loader, provider, strict));
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
deleted file mode 100644
index 9060fec..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentity.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * 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.client.config.keys;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.LinkOption;
-import java.nio.file.Path;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.function.Function;
-
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.config.keys.BuiltinIdentities;
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.config.keys.IdentityUtils;
-import org.apache.sshd.common.config.keys.KeyUtils;
-import org.apache.sshd.common.config.keys.PublicKeyEntry;
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.io.FileInfoExtractor;
-import org.apache.sshd.common.util.io.IoUtils;
-
-/**
- * Provides keys loading capability from the user's keys folder - e.g., {@code id_rsa}
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @see org.apache.sshd.common.util.security.SecurityUtils#getKeyPairResourceParser()
- */
-public final class ClientIdentity {
-
-    public static final String ID_FILE_PREFIX = "id_";
-
-    public static final String ID_FILE_SUFFIX = "";
-
-    public static final Function<String, String> ID_GENERATOR =
-            ClientIdentity::getIdentityFileName;
-
-    private ClientIdentity() {
-        throw new UnsupportedOperationException("No instance");
-    }
-
-    /**
-     * @param name The file name - ignored if {@code null}/empty
-     * @return The identity type - {@code null} if cannot determine it - e.g.,
-     * does not start with the {@link #ID_FILE_PREFIX}
-     */
-    public static String getIdentityType(String name) {
-        if (GenericUtils.isEmpty(name)
-                || (name.length() <= ID_FILE_PREFIX.length())
-                || (!name.startsWith(ID_FILE_PREFIX))) {
-            return null;
-        } else {
-            return name.substring(ID_FILE_PREFIX.length());
-        }
-    }
-
-    public static String getIdentityFileName(NamedResource r) {
-        return getIdentityFileName((r == null) ? null : r.getName());
-    }
-
-    /**
-     * @param type The identity type - e.g., {@code rsa} - ignored
-     *             if {@code null}/empty
-     * @return The matching file name for the identity - {@code null}
-     * if no name
-     * @see #ID_FILE_PREFIX
-     * @see #ID_FILE_SUFFIX
-     * @see IdentityUtils#getIdentityFileName(String, String, String)
-     */
-    public static String getIdentityFileName(String type) {
-        return IdentityUtils.getIdentityFileName(ID_FILE_PREFIX, type, ID_FILE_SUFFIX);
-    }
-
-    /**
-     * @param <C>           The generic client class
-     * @param client        The {@link SshClient} to updated
-     * @param strict        If {@code true} then files that do not have the required
-     *                      access rights are excluded from consideration
-     * @param supportedOnly If {@code true} then ignore identities that are not
-     *                      supported internally
-     * @param provider      A {@link FilePasswordProvider} - may be {@code null}
-     *                      if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
-     *                      to {@link FilePasswordProvider#getPassword(String)} is the path of the
-     *                      file whose key is to be loaded
-     * @param options       The {@link LinkOption}s to apply when checking
-     *                      for existence
-     * @return The updated <tt>client</tt> instance - provided a non-{@code null}
-     * {@link KeyPairProvider} was generated
-     * @throws IOException              If failed to access the file system
-     * @throws GeneralSecurityException If failed to load the keys
-     * @see #setKeyPairProvider(SshClient, Path, boolean, boolean, FilePasswordProvider, LinkOption...)
-     */
-    public static <C extends SshClient> C setKeyPairProvider(
-            C client, boolean strict, boolean supportedOnly, FilePasswordProvider provider, LinkOption... options)
-            throws IOException, GeneralSecurityException {
-        return setKeyPairProvider(client, PublicKeyEntry.getDefaultKeysFolderPath(), strict, supportedOnly, provider, options);
-    }
-
-    /**
-     * @param <C>           The generic client class
-     * @param client        The {@link SshClient} to updated
-     * @param dir           The folder to scan for the built-in identities
-     * @param strict        If {@code true} then files that do not have the required
-     *                      access rights are excluded from consideration
-     * @param supportedOnly If {@code true} then ignore identities that are not
-     *                      supported internally
-     * @param provider      A {@link FilePasswordProvider} - may be {@code null}
-     *                      if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
-     *                      to {@link FilePasswordProvider#getPassword(String)} is the path of the
-     *                      file whose key is to be loaded
-     * @param options       The {@link LinkOption}s to apply when checking
-     *                      for existence
-     * @return The updated <tt>client</tt> instance - provided a non-{@code null}
-     * {@link KeyPairProvider} was generated
-     * @throws IOException              If failed to access the file system
-     * @throws GeneralSecurityException If failed to load the keys
-     * @see #loadDefaultKeyPairProvider(Path, boolean, boolean, FilePasswordProvider, LinkOption...)
-     */
-    public static <C extends SshClient> C setKeyPairProvider(
-            C client, Path dir, boolean strict, boolean supportedOnly, FilePasswordProvider provider, LinkOption... options)
-            throws IOException, GeneralSecurityException {
-        KeyPairProvider kpp = loadDefaultKeyPairProvider(dir, strict, supportedOnly, provider, options);
-        if (kpp != null) {
-            client.setKeyPairProvider(kpp);
-        }
-
-        return client;
-    }
-
-    /**
-     * @param strict        If {@code true} then files that do not have the required
-     *                      access rights are excluded from consideration
-     * @param supportedOnly If {@code true} then ignore identities that are not
-     *                      supported internally
-     * @param provider      A {@link FilePasswordProvider} - may be {@code null}
-     *                      if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
-     *                      to {@link FilePasswordProvider#getPassword(String)} is the path of the
-     *                      file whose key is to be loaded
-     * @param options       The {@link LinkOption}s to apply when checking
-     *                      for existence
-     * @return A {@link KeyPair} for the identities - {@code null} if no identities
-     * available (e.g., after filtering unsupported ones or strict permissions)
-     * @throws IOException              If failed to access the file system
-     * @throws GeneralSecurityException If failed to load the keys
-     * @see PublicKeyEntry#getDefaultKeysFolderPath()
-     * @see #loadDefaultIdentities(Path, boolean, FilePasswordProvider, LinkOption...)
-     */
-    public static KeyPairProvider loadDefaultKeyPairProvider(
-            boolean strict, boolean supportedOnly, FilePasswordProvider provider, LinkOption... options)
-            throws IOException, GeneralSecurityException {
-        return loadDefaultKeyPairProvider(PublicKeyEntry.getDefaultKeysFolderPath(), strict, supportedOnly, provider, options);
-    }
-
-    /**
-     * @param dir           The folder to scan for the built-in identities
-     * @param strict        If {@code true} then files that do not have the required
-     *                      access rights are excluded from consideration
-     * @param supportedOnly If {@code true} then ignore identities that are not
-     *                      supported internally
-     * @param provider      A {@link FilePasswordProvider} - may be {@code null}
-     *                      if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
-     *                      to {@link FilePasswordProvider#getPassword(String)} is the path of the
-     *                      file whose key is to be loaded
-     * @param options       The {@link LinkOption}s to apply when checking
-     *                      for existence
-     * @return A {@link KeyPair} for the identities - {@code null} if no identities
-     * available (e.g., after filtering unsupported ones or strict permissions)
-     * @throws IOException              If failed to access the file system
-     * @throws GeneralSecurityException If failed to load the keys
-     * @see #loadDefaultIdentities(Path, boolean, FilePasswordProvider, LinkOption...)
-     * @see IdentityUtils#createKeyPairProvider(Map, boolean)
-     */
-    public static KeyPairProvider loadDefaultKeyPairProvider(
-            Path dir, boolean strict, boolean supportedOnly, FilePasswordProvider provider, LinkOption... options)
-            throws IOException, GeneralSecurityException {
-        Map<String, KeyPair> ids = loadDefaultIdentities(dir, strict, provider, options);
-        return IdentityUtils.createKeyPairProvider(ids, supportedOnly);
-    }
-
-    /**
-     * @param strict   If {@code true} then files that do not have the required
-     *                 access rights are excluded from consideration
-     * @param provider A {@link FilePasswordProvider} - may be {@code null}
-     *                 if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
-     *                 to {@link FilePasswordProvider#getPassword(String)} is the path of the
-     *                 file whose key is to be loaded
-     * @param options  The {@link LinkOption}s to apply when checking
-     *                 for existence
-     * @return A {@link Map} of the found files where key=identity type (case
-     * <U>insensitive</U>), value=the {@link KeyPair} of the identity
-     * @throws IOException              If failed to access the file system
-     * @throws GeneralSecurityException If failed to load the keys
-     * @see PublicKeyEntry#getDefaultKeysFolderPath()
-     * @see #loadDefaultIdentities(Path, boolean, FilePasswordProvider, LinkOption...)
-     */
-    public static Map<String, KeyPair> loadDefaultIdentities(boolean strict, FilePasswordProvider provider, LinkOption... options)
-            throws IOException, GeneralSecurityException {
-        return loadDefaultIdentities(PublicKeyEntry.getDefaultKeysFolderPath(), strict, provider, options);
-    }
-
-    /**
-     * @param dir      The folder to scan for the built-in identities
-     * @param strict   If {@code true} then files that do not have the required
-     *                 access rights are excluded from consideration
-     * @param provider A {@link FilePasswordProvider} - may be {@code null}
-     *                 if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
-     *                 to {@link FilePasswordProvider#getPassword(String)} is the path of the
-     *                 file whose key is to be loaded
-     * @param options  The {@link LinkOption}s to apply when checking
-     *                 for existence
-     * @return A {@link Map} of the found files where key=identity type (case
-     * <U>insensitive</U>), value=the {@link KeyPair} of the identity
-     * @throws IOException              If failed to access the file system
-     * @throws GeneralSecurityException If failed to load the keys
-     * @see #loadIdentities(Path, boolean, Collection, Function, FilePasswordProvider, LinkOption...)
-     * @see BuiltinIdentities
-     */
-    public static Map<String, KeyPair> loadDefaultIdentities(Path dir, boolean strict, FilePasswordProvider provider, LinkOption... options)
-            throws IOException, GeneralSecurityException {
-        return loadIdentities(dir, strict, BuiltinIdentities.NAMES, ID_GENERATOR, provider, options);
-    }
-
-    /**
-     * Scans a folder and loads all available identity files
-     *
-     * @param dir         The {@link Path} of the folder to scan - ignored if not exists
-     * @param strict      If {@code true} then files that do not have the required
-     *                    access rights are excluded from consideration
-     * @param types       The identity types - ignored if {@code null}/empty
-     * @param idGenerator A {@link Function} to derive the file name
-     *                    holding the specified type
-     * @param provider    A {@link FilePasswordProvider} - may be {@code null}
-     *                    if the loaded keys are <U>guaranteed</U> not to be encrypted. The argument
-     *                    to {@link FilePasswordProvider#getPassword(String)} is the path of the
-     *                    file whose key is to be loaded
-     * @param options     The {@link LinkOption}s to apply when checking
-     *                    for existence
-     * @return A {@link Map} of the found files where key=identity type (case
-     * <U>insensitive</U>), value=the {@link KeyPair} of the identity
-     * @throws IOException              If failed to access the file system
-     * @throws GeneralSecurityException If failed to load the keys
-     * @see #scanIdentitiesFolder(Path, boolean, Collection, Function, LinkOption...)
-     * @see IdentityUtils#loadIdentities(Map, FilePasswordProvider, java.nio.file.OpenOption...)
-     */
-    public static Map<String, KeyPair> loadIdentities(
-            Path dir, boolean strict, Collection<String> types, Function<String, String> idGenerator, FilePasswordProvider provider, LinkOption... options)
-            throws IOException, GeneralSecurityException {
-        Map<String, Path> paths = scanIdentitiesFolder(dir, strict, types, idGenerator, options);
-        return IdentityUtils.loadIdentities(paths, provider, IoUtils.EMPTY_OPEN_OPTIONS);
-    }
-
-    /**
-     * Scans a folder for possible identity files
-     *
-     * @param dir         The {@link Path} of the folder to scan - ignored if not exists
-     * @param strict      If {@code true} then files that do not have the required
-     *                    access rights are excluded from consideration
-     * @param types       The identity types - ignored if {@code null}/empty
-     * @param idGenerator A {@link Function} to derive the file name
-     *                    holding the specified type
-     * @param options     The {@link LinkOption}s to apply when checking
-     *                    for existence
-     * @return A {@link Map} of the found files where key=identity type (case
-     * <U>insensitive</U>), value=the {@link Path} of the file holding the key
-     * @throws IOException If failed to access the file system
-     * @see KeyUtils#validateStrictKeyFilePermissions(Path, LinkOption...)
-     */
-    public static Map<String, Path> scanIdentitiesFolder(
-            Path dir, boolean strict, Collection<String> types, Function<String, String> idGenerator, LinkOption... options)
-            throws IOException {
-        if (GenericUtils.isEmpty(types)) {
-            return Collections.emptyMap();
-        }
-
-        if (!Files.exists(dir, options)) {
-            return Collections.emptyMap();
-        }
-
-        ValidateUtils.checkTrue(FileInfoExtractor.ISDIR.infoOf(dir, options), "Not a directory: %s", dir);
-
-        Map<String, Path> paths = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        for (String t : types) {
-            String fileName = idGenerator.apply(t);
-            Path p = dir.resolve(fileName);
-            if (!Files.exists(p, options)) {
-                continue;
-            }
-
-            if (strict) {
-                if (KeyUtils.validateStrictKeyFilePermissions(p, options) != null) {
-                    continue;
-                }
-            }
-
-            Path prev = paths.put(t, p);
-            ValidateUtils.checkTrue(prev == null, "Multiple mappings for type=%s", t);
-        }
-
-        return paths;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
deleted file mode 100644
index a00cb24..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityFileWatcher.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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.client.config.keys;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Supplier;
-
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.config.keys.KeyUtils;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.common.util.io.ModifiableFileWatcher;
-
-/**
- * A {@link ClientIdentityProvider} that watches a given key file re-loading
- * its contents if it is ever modified, deleted or (re-)created
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class ClientIdentityFileWatcher extends ModifiableFileWatcher implements ClientIdentityProvider {
-    private final AtomicReference<KeyPair> identityHolder = new AtomicReference<>(null);
-    private final Supplier<ClientIdentityLoader> loaderHolder;
-    private final Supplier<FilePasswordProvider> providerHolder;
-    private final boolean strict;
-
-    public ClientIdentityFileWatcher(Path path, ClientIdentityLoader loader, FilePasswordProvider provider) {
-        this(path, loader, provider, true);
-    }
-
-    public ClientIdentityFileWatcher(Path path, ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
-        this(path,
-             GenericUtils.supplierOf(Objects.requireNonNull(loader, "No client identity loader")),
-             GenericUtils.supplierOf(Objects.requireNonNull(provider, "No password provider")),
-             strict);
-    }
-
-    public ClientIdentityFileWatcher(Path path, Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider) {
-        this(path, loader, provider, true);
-    }
-
-    public ClientIdentityFileWatcher(Path path, Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
-        super(path);
-        this.loaderHolder = Objects.requireNonNull(loader, "No client identity loader");
-        this.providerHolder = Objects.requireNonNull(provider, "No password provider");
-        this.strict = strict;
-    }
-
-    public final boolean isStrict() {
-        return strict;
-    }
-
-    public final ClientIdentityLoader getClientIdentityLoader() {
-        return loaderHolder.get();
-    }
-
-    public final FilePasswordProvider getFilePasswordProvider() {
-        return providerHolder.get();
-    }
-
-    @Override
-    public KeyPair getClientIdentity() throws IOException, GeneralSecurityException {
-        if (checkReloadRequired()) {
-            KeyPair kp = identityHolder.getAndSet(null);     // start fresh
-            Path path = getPath();
-
-            if (exists()) {
-                KeyPair id = reloadClientIdentity(path);
-                if (!KeyUtils.compareKeyPairs(kp, id)) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("getClientIdentity({}) identity {}", path, (kp == null) ? "loaded" : "re-loaded");
-                    }
-                }
-
-                updateReloadAttributes();
-                identityHolder.set(id);
-            }
-        }
-
-        return identityHolder.get();
-    }
-
-    protected KeyPair reloadClientIdentity(Path path) throws IOException, GeneralSecurityException {
-        if (isStrict()) {
-            Map.Entry<String, Object> violation = KeyUtils.validateStrictKeyFilePermissions(path, IoUtils.EMPTY_LINK_OPTIONS);
-            if (violation != null) {
-                if (log.isDebugEnabled()) {
-                    log.debug("reloadClientIdentity({}) ignore due to {}", path, violation.getKey());
-                }
-                return null;
-            }
-        }
-
-        String location = path.toString();
-        ClientIdentityLoader idLoader = Objects.requireNonNull(getClientIdentityLoader(), "No client identity loader");
-        if (idLoader.isValidLocation(location)) {
-            KeyPair kp = idLoader.loadClientIdentity(location, Objects.requireNonNull(getFilePasswordProvider(), "No file password provider"));
-            if (log.isTraceEnabled()) {
-                PublicKey key = (kp == null) ? null : kp.getPublic();
-                if (key != null) {
-                    log.trace("reloadClientIdentity({}) loaded {}-{}",
-                              location, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key));
-
-                } else {
-                    log.trace("reloadClientIdentity({}) no key loaded", location);
-                }
-            }
-
-            return kp;
-        }
-
-        if (log.isDebugEnabled()) {
-            log.debug("reloadClientIdentity({}) invalid location", location);
-        }
-
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
deleted file mode 100644
index 8b3a295..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityLoader.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.client.config.keys;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.util.ValidateUtils;
-import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.common.util.security.SecurityUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface ClientIdentityLoader {
-    /**
-     * <P>A default implementation that assumes a file location that <U>must</U> exist.</P>
-     *
-     * <P>
-     * <B>Note:</B> It calls {@link SecurityUtils#loadKeyPairIdentity(String, InputStream, FilePasswordProvider)}
-     * </P>
-     */
-    ClientIdentityLoader DEFAULT = new ClientIdentityLoader() {
-        @Override
-        public boolean isValidLocation(String location) throws IOException {
-            Path path = toPath(location);
-            return Files.exists(path, IoUtils.EMPTY_LINK_OPTIONS);
-        }
-
-        @Override
-        public KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException {
-            Path path = toPath(location);
-            try (InputStream inputStream = Files.newInputStream(path, IoUtils.EMPTY_OPEN_OPTIONS)) {
-                return SecurityUtils.loadKeyPairIdentity(path.toString(), inputStream, provider);
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "DEFAULT";
-        }
-
-        private Path toPath(String location) {
-            Path path = Paths.get(ValidateUtils.checkNotNullAndNotEmpty(location, "No location"));
-            path = path.toAbsolutePath();
-            path = path.normalize();
-            return path;
-        }
-    };
-
-    /**
-     * @param location The identity key-pair location - the actual meaning (file, URL, etc.)
-     * depends on the implementation.
-     * @return {@code true} if it represents a valid location - the actual meaning of
-     * the validity depends on the implementation
-     * @throws IOException If failed to validate the location
-     */
-    boolean isValidLocation(String location) throws IOException;
-
-    /**
-     * @param location The identity key-pair location - the actual meaning (file, URL, etc.)
-     * depends on the implementation.
-     * @param provider The {@link FilePasswordProvider} to consult if the location contains
-     * an encrypted identity
-     * @return The loaded {@link KeyPair} - {@code null} if location is empty
-     * and it is OK that it does not exist
-     * @throws IOException If failed to access / process the remote location
-     * @throws GeneralSecurityException If failed to convert the contents into
-     * a valid identity
-     */
-    KeyPair loadClientIdentity(String location, FilePasswordProvider provider) throws IOException, GeneralSecurityException;
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java
deleted file mode 100644
index bda4700..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/ClientIdentityProvider.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.client.config.keys;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface ClientIdentityProvider {
-    /**
-     * Provides a {@link KeyPair} representing the client identity
-     *
-     * @return The client identity - may be {@code null} if no currently
-     * available identity from this provider. <B>Note:</B> the provider
-     * may return a <U>different</U> value every time this method is called
-     * - e.g., if it is (re-)loading contents from a file.
-     * @throws IOException If failed to load the identity
-     * @throws GeneralSecurityException If failed to parse the identity
-     */
-    KeyPair getClientIdentity() throws IOException, GeneralSecurityException;
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java b/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java
deleted file mode 100644
index 3afa129..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/client/config/keys/DefaultClientIdentitiesWatcher.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.client.config.keys;
-
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.Supplier;
-
-import org.apache.sshd.common.config.keys.FilePasswordProvider;
-import org.apache.sshd.common.config.keys.PublicKeyEntry;
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class DefaultClientIdentitiesWatcher extends BuiltinClientIdentitiesWatcher {
-    public DefaultClientIdentitiesWatcher(ClientIdentityLoader loader, FilePasswordProvider provider) {
-        this(loader, provider, true);
-    }
-
-    public DefaultClientIdentitiesWatcher(ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
-        this(true, loader, provider, strict);
-    }
-
-    public DefaultClientIdentitiesWatcher(boolean supportedOnly, ClientIdentityLoader loader, FilePasswordProvider provider, boolean strict) {
-        this(supportedOnly,
-             GenericUtils.supplierOf(Objects.requireNonNull(loader, "No client identity loader")),
-             GenericUtils.supplierOf(Objects.requireNonNull(provider, "No password provider")),
-             strict);
-    }
-
-    public DefaultClientIdentitiesWatcher(Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider) {
-        this(loader, provider, true);
-    }
-
-    public DefaultClientIdentitiesWatcher(Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
-        this(true, loader, provider, strict);
-    }
-
-    public DefaultClientIdentitiesWatcher(boolean supportedOnly,
-            Supplier<ClientIdentityLoader> loader, Supplier<FilePasswordProvider> provider, boolean strict) {
-        super(PublicKeyEntry.getDefaultKeysFolderPath(), supportedOnly, loader, provider, strict);
-    }
-
-    public static List<Path> getDefaultBuiltinIdentitiesPaths() {
-        return getDefaultBuiltinIdentitiesPaths(PublicKeyEntry.getDefaultKeysFolderPath());
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java b/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java
index 7a5052d..c4cb849 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifier.java
@@ -46,7 +46,7 @@ import org.apache.sshd.client.session.ClientSession;
 import org.apache.sshd.common.Factory;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.config.SshConfigFileReader;
+import org.apache.sshd.common.config.ConfigFileReaderSupport;
 import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
 import org.apache.sshd.common.config.keys.KeyUtils;
 import org.apache.sshd.common.config.keys.PublicKeyEntry;
@@ -350,7 +350,7 @@ public class KnownHostsServerKeyVerifier
                         continue;
                     }
 
-                    int pos = line.indexOf(SshConfigFileReader.COMMENT_CHAR);
+                    int pos = line.indexOf(ConfigFileReaderSupport.COMMENT_CHAR);
                     if (pos == 0) {
                         lines.add(line);
                         continue;
@@ -703,7 +703,7 @@ public class KnownHostsServerKeyVerifier
                 KnownHostHashValue.append(sb, digester, salt, digestValue);
             } else {
                 int portValue = hostIdentity.getPort();
-                boolean nonDefaultPort = (portValue > 0) && (portValue != SshConfigFileReader.DEFAULT_PORT);
+                boolean nonDefaultPort = (portValue > 0) && (portValue != ConfigFileReaderSupport.DEFAULT_PORT);
                 if (nonDefaultPort) {
                     sb.append(HostPatternsHolder.NON_STANDARD_PORT_PATTERN_ENCLOSURE_START_DELIM);
                 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
index 1d68a20..31202bb 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSession.java
@@ -27,14 +27,17 @@ import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.rmi.RemoteException;
 import java.rmi.ServerException;
+import java.security.KeyPair;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
 import org.apache.sshd.client.ClientAuthenticationManager;
 import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.auth.password.PasswordIdentityProvider;
 import org.apache.sshd.client.channel.ChannelDirectTcpip;
 import org.apache.sshd.client.channel.ChannelExec;
 import org.apache.sshd.client.channel.ChannelShell;
@@ -46,6 +49,7 @@ import org.apache.sshd.client.session.forward.DynamicPortForwardingTracker;
 import org.apache.sshd.client.session.forward.ExplicitPortForwardingTracker;
 import org.apache.sshd.common.forward.PortForwardingManager;
 import org.apache.sshd.common.future.KeyExchangeFuture;
+import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
 import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.util.io.NoCloseOutputStream;
 import org.apache.sshd.common.util.io.NullOutputStream;
@@ -353,4 +357,54 @@ public interface ClientSession
      * @throws IOException if a key exchange is already running
      */
     KeyExchangeFuture switchToNoneCipher() throws IOException;
+
+    /**
+     * Creates a &quot;unified&quot; {@link KeyIdentityProvider} of key pairs out of the registered
+     * {@link KeyPair} identities and the extra available ones as a single iterator
+     * of key pairs
+     *
+     *
+     * @param session The {@link ClientSession} - ignored if {@code null} (i.e., empty
+     * iterator returned)
+     * @return The wrapping KeyIdentityProvider
+     * @see ClientSession#getRegisteredIdentities()
+     * @see ClientSession#getKeyPairProvider()
+     */
+    static KeyIdentityProvider providerOf(ClientSession session) {
+        return session == null
+            ? KeyIdentityProvider.EMPTY_KEYS_PROVIDER
+            : KeyIdentityProvider.resolveKeyIdentityProvider(
+                    session.getRegisteredIdentities(), session.getKeyPairProvider());
+    }
+
+    /**
+     * Creates a &quot;unified&quot; {@link Iterator} of key pairs out of the registered
+     * {@link KeyPair} identities and the extra available ones as a single iterator
+     * of key pairs
+     *
+     * @param session The {@link ClientSession} - ignored if {@code null} (i.e., empty
+     * iterator returned)
+     * @return The wrapping iterator
+     * @see ClientSession#getRegisteredIdentities()
+     * @see ClientSession#getKeyPairProvider()
+     */
+    static Iterator<KeyPair> keyPairIteratorOf(ClientSession session) {
+        return KeyIdentityProvider.iteratorOf(providerOf(session));
+    }
+
+    /**
+     * Creates a &quot;unified&quot; {@link Iterator} of passwords out of the registered
+     * passwords and the extra available ones as a single iterator of passwords
+     *
+     * @param session The {@link ClientSession} - ignored if {@code null} (i.e., empty
+     * iterator returned)
+     * @return The wrapping iterator
+     * @see ClientSession#getRegisteredIdentities()
+     * @see ClientSession#getPasswordIdentityProvider()
+     */
+    static Iterator<String> passwordIteratorOf(ClientSession session) {
+        return (session == null)
+            ? Collections.<String>emptyIterator()
+            : PasswordIdentityProvider.iteratorOf(session.getRegisteredIdentities(), session.getPasswordIdentityProvider());
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/client/simple/SimpleClientConfigurator.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/simple/SimpleClientConfigurator.java b/sshd-core/src/main/java/org/apache/sshd/client/simple/SimpleClientConfigurator.java
index 58913b4..31a994b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/simple/SimpleClientConfigurator.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/simple/SimpleClientConfigurator.java
@@ -19,7 +19,7 @@
 
 package org.apache.sshd.client.simple;
 
-import org.apache.sshd.common.config.SshConfigFileReader;
+import org.apache.sshd.common.config.ConfigFileReaderSupport;
 
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
@@ -35,7 +35,7 @@ public interface SimpleClientConfigurator {
      */
     long DEFAULT_AUTHENTICATION_TIMEOUT = Long.MAX_VALUE;   // virtually infinite
 
-    int DEFAULT_PORT = SshConfigFileReader.DEFAULT_PORT;
+    int DEFAULT_PORT = ConfigFileReaderSupport.DEFAULT_PORT;
 
     /**
      * @return Current connect timeout (msec.) - always positive

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java b/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java
deleted file mode 100644
index 2b58d94..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/AttributeStore.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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;
-
-import java.util.Objects;
-
-import org.apache.sshd.common.channel.Channel;
-import org.apache.sshd.common.session.Session;
-
-/**
- * Provides the capability to attach in-memory attributes to the entity
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface AttributeStore {
-    /**
-     * <P>
-     * Type safe key for storage of user attributes. Typically it is used as a static
-     * variable that is shared between the producer and the consumer. To further
-     * restrict access the setting or getting it from the store one can add static
-     * {@code get/set methods} e.g:
-     * </P>
-     *
-     * <pre>
-     * public static final AttributeKey&lt;MyValue&gt; MY_KEY = new AttributeKey&lt;MyValue&gt;();
-     *
-     * public static MyValue getMyValue(Session s) {
-     *   return s.getAttribute(MY_KEY);
-     * }
-     *
-     * public static void setMyValue(Session s, MyValue value) {
-     *   s.setAttribute(MY_KEY, value);
-     * }
-     * </pre>
-     *
-     * @param <T> type of value stored in the attribute.
-     * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
-     */
-    // CHECKSTYLE:OFF
-    class AttributeKey<T> {
-        public AttributeKey() {
-            super();
-        }
-    }
-    // CHECKSTYLE:ON
-
-    /**
-     * Returns the value of the user-defined attribute.
-     *
-     * @param <T> The generic attribute type
-     * @param key The key of the attribute; must not be {@code null}.
-     * @return {@code null} if there is no value associated with the specified key
-     */
-    <T> T getAttribute(AttributeKey<T> key);
-
-    /**
-     * Sets a user-defined attribute.
-     *
-     * @param <T>   The generic attribute type
-     * @param key   The key of the attribute; must not be {@code null}.
-     * @param value The value of the attribute; must not be {@code null}.
-     * @return The old value of the attribute; {@code null} if it is new.
-     */
-    <T> T setAttribute(AttributeKey<T> key, T value);
-
-    /**
-     * Removes the user-defined attribute
-     *
-     * @param <T> The generic attribute type
-     * @param key The key of the attribute; must not be {@code null}.
-     * @return The removed value; {@code null} if no previous value
-     */
-    <T> T removeAttribute(AttributeKey<T> key);
-
-    /**
-     * Attempts to resolve the associated value by going up the store's
-     * hierarchy (if any)
-     *
-     * @param <T> The generic attribute type
-     * @param key The key of the attribute; must not be {@code null}.
-     * @return {@code null} if there is no value associated with the specified key
-     */
-    <T> T resolveAttribute(AttributeKey<T> key);
-
-    /**
-     * @param <T> The generic attribute type
-     * @param manager The {@link FactoryManager} - ignored if {@code null}
-     * @param key The attribute key - never {@code null}
-     * @return Associated value - {@code null} if not found
-     */
-    static <T> T resolveAttribute(FactoryManager manager, AttributeKey<T> key) {
-        Objects.requireNonNull(key, "No key");
-        return (manager == null) ? null : manager.getAttribute(key);
-    }
-
-    /**
-     * Attempts to use the session's attribute, if not found then tries the factory manager
-     *
-     * @param <T> The generic attribute type
-     * @param session The {@link Session} - ignored if {@code null}
-     * @param key The attribute key - never {@code null}
-     * @return Associated value - {@code null} if not found
-     * @see Session#getFactoryManager()
-     * @see #resolveAttribute(FactoryManager, AttributeKey)
-     */
-    static <T> T resolveAttribute(Session session, AttributeKey<T> key) {
-        Objects.requireNonNull(key, "No key");
-        if (session == null) {
-            return null;
-        }
-
-        T value = session.getAttribute(key);
-        return (value != null) ? value : resolveAttribute(session.getFactoryManager(), key);
-    }
-
-    /**
-     * Attempts to use the channel attribute, if not found then tries the session
-     *
-     * @param <T> The generic attribute type
-     * @param channel The {@link Channel} - ignored if {@code null}
-     * @param key The attribute key - never {@code null}
-     * @return Associated value - {@code null} if not found
-     * @see Session#getFactoryManager()
-     * @see #resolveAttribute(Session, AttributeKey)
-     */
-    static <T> T resolveAttribute(Channel channel, AttributeKey<T> key) {
-        Objects.requireNonNull(key, "No key");
-        if (channel == null) {
-            return null;
-        }
-
-        T value = channel.getAttribute(key);
-        return (value != null) ? value : resolveAttribute(channel.getSession(), key);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/BuiltinFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/BuiltinFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/BuiltinFactory.java
deleted file mode 100644
index 33b53a9..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/BuiltinFactory.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * A named optional factory.
- *
- * @param <T> The create object instance type
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface BuiltinFactory<T> extends NamedFactory<T>, OptionalFeature {
-    static <T, E extends BuiltinFactory<T>> List<NamedFactory<T>> setUpFactories(
-            boolean ignoreUnsupported, Collection<? extends E> preferred) {
-        return GenericUtils.stream(preferred)
-                .filter(f -> ignoreUnsupported || f.isSupported())
-                .collect(Collectors.toList());
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java b/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java
deleted file mode 100644
index 6a6f622..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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;
-
-import java.io.IOException;
-import java.net.SocketTimeoutException;
-import java.nio.channels.Channel;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.sshd.common.future.CloseFuture;
-import org.apache.sshd.common.future.SshFutureListener;
-
-/**
- * A {@code Closeable} is a resource that can be closed.
- * The close method is invoked to release resources that the object is
- * holding. The user can pre-register listeners to be notified
- * when resource close is completed (successfully or otherwise)
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface Closeable extends Channel {
-
-    /**
-     * Timeout (milliseconds) for waiting on a {@link CloseFuture} to successfully
-     * complete its action.
-     * @see #DEFAULT_CLOSE_WAIT_TIMEOUT
-     */
-    String CLOSE_WAIT_TIMEOUT = "sshd-close-wait-time";
-
-    /**
-     * Default value for {@link #CLOSE_WAIT_TIMEOUT} if none specified
-     */
-    long DEFAULT_CLOSE_WAIT_TIMEOUT = TimeUnit.SECONDS.toMillis(15L);
-
-    /**
-     * Close this resource asynchronously and return a future.
-     * Resources support two closing modes: a graceful mode
-     * which will cleanly close the resource and an immediate mode
-     * which will close the resources abruptly.
-     *
-     * @param immediately <code>true</code> if the resource should be shut down abruptly,
-     *                    <code>false</code> for a graceful close
-     * @return a {@link CloseFuture} representing the close request
-     */
-    CloseFuture close(boolean immediately);
-
-    /**
-     * Pre-register a listener to be informed when resource is closed. If
-     * resource is already closed, the listener will be invoked immediately
-     * and not registered for future notification
-     *
-     * @param listener The notification {@link SshFutureListener} - never {@code null}
-     */
-    void addCloseFutureListener(SshFutureListener<CloseFuture> listener);
-
-    /**
-     * Remove a pre-registered close event listener
-     *
-     * @param listener The register {@link SshFutureListener} - never {@code null}.
-     * Ignored if not registered or resource already closed
-     */
-    void removeCloseFutureListener(SshFutureListener<CloseFuture> listener);
-
-    /**
-     * Returns <code>true</code> if this object has been closed.
-     *
-     * @return <code>true</code> if closing
-     */
-    boolean isClosed();
-
-    /**
-     * Returns <code>true</code> if the {@link #close(boolean)} method
-     * has been called. Note that this method will return <code>true</code>
-     * even if this {@link #isClosed()} returns <code>true</code>.
-     *
-     * @return <code>true</code> if closing
-     */
-    boolean isClosing();
-
-    @Override
-    default boolean isOpen() {
-        return !(isClosed() || isClosing());
-    }
-
-    @Override
-    default void close() throws IOException {
-        Closeable.close(this);
-    }
-
-    static long getMaxCloseWaitTime(PropertyResolver resolver) {
-        return (resolver == null) ? DEFAULT_CLOSE_WAIT_TIMEOUT
-                : resolver.getLongProperty(CLOSE_WAIT_TIMEOUT, DEFAULT_CLOSE_WAIT_TIMEOUT);
-    }
-
-    static void close(Closeable closeable) throws IOException {
-        if (closeable == null) {
-            return;
-        }
-
-        if ((!closeable.isClosed()) && (!closeable.isClosing())) {
-            CloseFuture future = closeable.close(true);
-            long maxWait = (closeable instanceof PropertyResolver)
-                    ? getMaxCloseWaitTime((PropertyResolver) closeable) : DEFAULT_CLOSE_WAIT_TIMEOUT;
-            boolean successful = future.await(maxWait);
-            if (!successful) {
-                throw new SocketTimeoutException("Failed to receive closure confirmation within " + maxWait + " millis");
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/Factory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Factory.java b/sshd-core/src/main/java/org/apache/sshd/common/Factory.java
deleted file mode 100644
index 93b351c..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/Factory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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;
-
-import java.util.function.Supplier;
-
-/**
- * Factory is a simple interface that is used to create other objects.
- *
- * @param <T> type of object this factory will create
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface Factory<T> extends Supplier<T> {
-
-    @Override
-    default T get() {
-        return create();
-    }
-
-    /**
-     * @return A new instance
-     */
-    T create();
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
index 31f0de6..22c7d49 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
@@ -19,6 +19,7 @@
 package org.apache.sshd.common;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
@@ -467,4 +468,19 @@ public interface FactoryManager
      */
     List<RequestHandler<ConnectionService>> getGlobalRequestHandlers();
 
+    @Override
+    default <T> T resolveAttribute(AttributeKey<T> key) {
+        return resolveAttribute(this, key);
+    }
+
+    /**
+     * @param <T> The generic attribute type
+     * @param manager The {@link FactoryManager} - ignored if {@code null}
+     * @param key The attribute key - never {@code null}
+     * @return Associated value - {@code null} if not found
+     */
+    static <T> T resolveAttribute(FactoryManager manager, AttributeKey<T> key) {
+        Objects.requireNonNull(key, "No key");
+        return (manager == null) ? null : manager.getAttribute(key);
+    }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
deleted file mode 100644
index 5386447..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/NamedFactory.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-/**
- * A named factory is a factory identified by a name.
- * Such names are used mainly in the algorithm negotiation at the beginning of the SSH connection.
- *
- * @param <T> The create object instance type
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface NamedFactory<T> extends Factory<T>, NamedResource {
-    /**
-     * Create an instance of the specified name by looking up the needed factory
-     * in the list.
-     *
-     * @param factories list of available factories
-     * @param name      the factory name to use
-     * @param <T>       type of object to create
-     * @return a newly created object or {@code null} if the factory is not in the list
-     */
-    static <T> T create(Collection<? extends NamedFactory<? extends T>> factories, String name) {
-        NamedFactory<? extends T> f = NamedResource.findByName(name, String.CASE_INSENSITIVE_ORDER, factories);
-        if (f != null) {
-            return f.create();
-        } else {
-            return null;
-        }
-    }
-
-    static <S extends OptionalFeature, T, E extends NamedFactory<T>> List<NamedFactory<T>> setUpTransformedFactories(
-            boolean ignoreUnsupported, Collection<? extends S> preferred, Function<? super S, ? extends E> xform) {
-        return preferred.stream()
-            .filter(f -> ignoreUnsupported || f.isSupported())
-            .map(xform)
-            .collect(Collectors.toList());
-    }
-
-    static <T, E extends NamedFactory<T> & OptionalFeature> List<NamedFactory<T>> setUpBuiltinFactories(
-            boolean ignoreUnsupported, Collection<? extends E> preferred) {
-        return preferred.stream()
-            .filter(f -> ignoreUnsupported || f.isSupported())
-            .collect(Collectors.toList());
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java b/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
deleted file mode 100644
index 813f53d..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/NamedResource.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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;
-
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.List;
-import java.util.function.Function;
-
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface NamedResource {
-
-    /**
-     * Returns the value of {@link #getName()} - or {@code null} if argument is {@code null}
-     */
-    Function<NamedResource, String> NAME_EXTRACTOR = input -> input == null ? null : input.getName();
-
-    /**
-     * Compares 2 {@link NamedResource}s according to their {@link #getName()}
-     * value case <U>insensitive</U>
-     */
-    Comparator<NamedResource> BY_NAME_COMPARATOR = Comparator.comparing(NAME_EXTRACTOR, String.CASE_INSENSITIVE_ORDER);
-
-    /**
-     * @return The resource name
-     */
-    String getName();
-
-    /**
-     * @param resources The named resources
-     * @return A {@link List} of all the factories names - in same order
-     * as they appear in the input collection
-     */
-    static List<String> getNameList(Collection<? extends NamedResource> resources) {
-        return GenericUtils.map(resources, NamedResource::getName);
-    }
-
-    /**
-     * @param resources list of available resources
-     * @return A comma separated list of factory names
-     */
-    static String getNames(Collection<? extends NamedResource> resources) {
-        Collection<String> nameList = getNameList(resources);
-        return GenericUtils.join(nameList, ',');
-    }
-
-    /**
-     * Remove the resource identified by the name from the list.
-     *
-     * @param <R>       The generic resource type
-     * @param name      Name of the resource - ignored if {@code null}/empty
-     * @param c         The {@link Comparator} to decide whether the {@link NamedResource#getName()}
-     *                  matches the <tt>name</tt> parameter
-     * @param resources The {@link NamedResource} to check - ignored if {@code null}/empty
-     * @return the removed resource from the list or {@code null} if not in the list
-     */
-    static <R extends NamedResource> R removeByName(String name, Comparator<? super String> c, Collection<? extends R> resources) {
-        R r = findByName(name, c, resources);
-        if (r != null) {
-            resources.remove(r);
-        }
-        return r;
-    }
-
-    /**
-     * @param <R>       The generic resource type
-     * @param name      Name of the resource - ignored if {@code null}/empty
-     * @param c         The {@link Comparator} to decide whether the {@link NamedResource#getName()}
-     *                  matches the <tt>name</tt> parameter
-     * @param resources The {@link NamedResource} to check - ignored if {@code null}/empty
-     * @return The <U>first</U> resource whose name matches the parameter (by invoking
-     * {@link Comparator#compare(Object, Object)} - {@code null} if no match found
-     */
-    static <R extends NamedResource> R findByName(String name, Comparator<? super String> c, Collection<? extends R> resources) {
-        return GenericUtils.isEmpty(name)
-            ? null
-            : GenericUtils.stream(resources)
-                .filter(r -> c.compare(name, r.getName()) == 0)
-                .findFirst()
-                .orElse(null);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/OptionalFeature.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/OptionalFeature.java b/sshd-core/src/main/java/org/apache/sshd/common/OptionalFeature.java
deleted file mode 100644
index 1afa864..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/OptionalFeature.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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;
-
-import java.util.Collection;
-
-import org.apache.sshd.common.util.GenericUtils;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface OptionalFeature {
-    OptionalFeature TRUE = new OptionalFeature() {
-        @Override
-        public boolean isSupported() {
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            return "TRUE";
-        }
-    };
-
-    OptionalFeature FALSE = new OptionalFeature() {
-        @Override
-        public boolean isSupported() {
-            return false;
-        }
-
-        @Override
-        public String toString() {
-            return "FALSE";
-        }
-    };
-
-    boolean isSupported();
-
-    static OptionalFeature of(boolean supported) {
-        return supported ? TRUE : FALSE;
-    }
-
-    static OptionalFeature all(Collection<? extends OptionalFeature> features) {
-        return () -> {
-            if (GenericUtils.isEmpty(features)) {
-                return false;
-            }
-
-            for (OptionalFeature f : features) {
-                if (!f.isSupported()) {
-                    return false;
-                }
-            }
-
-            return true;
-        };
-    }
-
-    static OptionalFeature any(Collection<? extends OptionalFeature> features) {
-        return () -> {
-            if (GenericUtils.isEmpty(features)) {
-                return false;
-            }
-
-            for (OptionalFeature f : features) {
-                if (f.isSupported()) {
-                    return true;
-                }
-            }
-
-            return false;
-        };
-    }
-}