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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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 "unified" {@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 "unified" {@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 "unified" {@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:[email protected]">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:[email protected]">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<MyValue> MY_KEY = new AttributeKey<MyValue>(); - * - * 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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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:[email protected]">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; - }; - } -}
