http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java deleted file mode 100644 index f469583..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java +++ /dev/null @@ -1,166 +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.digest; - -import java.util.Collections; -import java.util.EnumSet; -import java.util.Set; - -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.common.NamedResource; -import org.apache.sshd.common.util.GenericUtils; - -/** - * Provides easy access to the currently implemented digests - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public enum BuiltinDigests implements DigestFactory { - md5(Constants.MD5, "MD5", 16), - sha1(Constants.SHA1, "SHA-1", 20), - sha224(Constants.SHA224, "SHA-224", 28), - sha256(Constants.SHA256, "SHA-256", 32), - sha384(Constants.SHA384, "SHA-384", 48), - sha512(Constants.SHA512, "SHA-512", 64); - - public static final Set<BuiltinDigests> VALUES = - Collections.unmodifiableSet(EnumSet.allOf(BuiltinDigests.class)); - - private final String algorithm; - private final int blockSize; - private final String factoryName; - private final boolean supported; - - BuiltinDigests(String factoryName, String algorithm, int blockSize) { - this.factoryName = factoryName; - this.algorithm = algorithm; - this.blockSize = blockSize; - /* - * This can be done once since in order to change the support the JVM - * needs to be stopped, some unlimited-strength files need be installed - * and then the JVM re-started. Therefore, the answer is not going to - * change while the JVM is running - */ - this.supported = DigestUtils.checkSupported(algorithm); - } - - @Override - public final String getName() { - return factoryName; - } - - @Override - public final String getAlgorithm() { - return algorithm; - } - - @Override - public final int getBlockSize() { - return blockSize; - } - - @Override - public final String toString() { - return getName(); - } - - @Override - public final Digest create() { - return new BaseDigest(getAlgorithm(), getBlockSize()); - } - - @Override - public final boolean isSupported() { - return supported; - } - - /** - * @param s The {@link Enum}'s name - ignored if {@code null}/empty - * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose {@link Enum#name()} matches - * (case <U>insensitive</U>) the provided argument - {@code null} if no match - */ - public static BuiltinDigests fromString(String s) { - if (GenericUtils.isEmpty(s)) { - return null; - } - - for (BuiltinDigests c : VALUES) { - if (s.equalsIgnoreCase(c.name())) { - return c; - } - } - - return null; - } - - /** - * @param factory The {@link org.apache.sshd.common.NamedFactory} for the cipher - ignored if {@code null} - * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose factory name matches - * (case <U>insensitive</U>) the digest factory name - * @see #fromFactoryName(String) - */ - public static BuiltinDigests fromFactory(NamedFactory<? extends Digest> factory) { - if (factory == null) { - return null; - } else { - return fromFactoryName(factory.getName()); - } - } - - /** - * @param name The factory name - ignored if {@code null}/empty - * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose factory name matches - * (case <U>insensitive</U>) the provided name - {@code null} if no match - */ - public static BuiltinDigests fromFactoryName(String name) { - return NamedResource.findByName(name, String.CASE_INSENSITIVE_ORDER, VALUES); - } - - /** - * @param d The {@link Digest} instance - ignored if {@code null} - * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose algorithm matches - * (case <U>insensitive</U>) the digets's algorithm - {@code null} if no match - */ - public static BuiltinDigests fromDigest(Digest d) { - return fromAlgorithm((d == null) ? null : d.getAlgorithm()); - } - - /** - * @param algo The algorithm to find - ignored if {@code null}/empty - * @return The matching {@link org.apache.sshd.common.digest.BuiltinDigests} whose algorithm matches - * (case <U>insensitive</U>) the provided name - {@code null} if no match - */ - public static BuiltinDigests fromAlgorithm(String algo) { - return DigestUtils.findFactoryByAlgorithm(algo, String.CASE_INSENSITIVE_ORDER, VALUES); - } - - public static final class Constants { - public static final String MD5 = "md5"; - public static final String SHA1 = "sha1"; - public static final String SHA224 = "sha224"; - public static final String SHA256 = "sha256"; - public static final String SHA384 = "sha384"; - public static final String SHA512 = "sha512"; - - private Constants() { - throw new UnsupportedOperationException("No instance allowed"); - } - } -}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/digest/Digest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/Digest.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/Digest.java deleted file mode 100644 index 27204ff..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/digest/Digest.java +++ /dev/null @@ -1,36 +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.digest; - -/** - * Interface used to compute digests, based on algorithms such as MD5 or SHA1. - * The digest implementation are compared first by the algorithm name (case - * <U>insensitive</U> and second according to the block size - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface Digest extends DigestInformation, Comparable<Digest> { - void init() throws Exception; - - void update(byte[] data) throws Exception; - - void update(byte[] data, int start, int len) throws Exception; - - byte[] digest() throws Exception; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestFactory.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestFactory.java deleted file mode 100644 index f00e7ba..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestFactory.java +++ /dev/null @@ -1,32 +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.digest; - -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.common.OptionalFeature; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -// CHECKSTYLE:OFF -public interface DigestFactory extends DigestInformation, NamedFactory<Digest>, OptionalFeature { - // nothing extra -} -// CHECKSTYLE:ON http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestInformation.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestInformation.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestInformation.java deleted file mode 100644 index ba181dc..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestInformation.java +++ /dev/null @@ -1,36 +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.digest; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface DigestInformation { - /** - * @return The digest algorithm name - */ - String getAlgorithm(); - - /** - * @return The number of bytes in the digest's output - */ - int getBlockSize(); - -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestUtils.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestUtils.java deleted file mode 100644 index 30369ac..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/digest/DigestUtils.java +++ /dev/null @@ -1,228 +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.digest; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.util.Base64; -import java.util.Collection; -import java.util.Comparator; -import java.util.Objects; - -import org.apache.sshd.common.Factory; -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; -import org.apache.sshd.common.util.security.SecurityUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public final class DigestUtils { - private DigestUtils() { - throw new UnsupportedOperationException("No instance"); - } - - /** - * @param algorithm The digest algorithm - never {@code null}/empty - * @return {@code true} if this digest algorithm is supported - * @see SecurityUtils#getMessageDigest(String) - */ - public static boolean checkSupported(String algorithm) { - ValidateUtils.checkNotNullAndNotEmpty(algorithm, "No algorithm"); - try { - MessageDigest digest = SecurityUtils.getMessageDigest(algorithm); - return digest != null; // just in case - } catch (Exception e) { - return false; - } - } - - /** - * @param <D> The generic type of digest factory - * @param algo The required algorithm name - ignored if {@code null}/empty - * @param comp The {@link Comparator} to use to compare algorithm names - * @param digests The factories to check - ignored if {@code null}/empty - * @return The first {@link DigestFactory} whose algorithm matches the required one - * according to the comparator - {@code null} if no match found - */ - public static <D extends Digest> D findDigestByAlgorithm(String algo, Comparator<? super String> comp, Collection<? extends D> digests) { - if (GenericUtils.isEmpty(algo) || GenericUtils.isEmpty(digests)) { - return null; - } - - for (D d : digests) { - if (comp.compare(algo, d.getAlgorithm()) == 0) { - return d; - } - } - - return null; - } - - /** - * @param <F> The generic type of digest factory - * @param algo The required algorithm name - ignored if {@code null}/empty - * @param comp The {@link Comparator} to use to compare algorithm names - * @param factories The factories to check - ignored if {@code null}/empty - * @return The first {@link DigestFactory} whose algorithm matches the required one - * according to the comparator - {@code null} if no match found - */ - public static <F extends DigestFactory> F findFactoryByAlgorithm(String algo, Comparator<? super String> comp, Collection<? extends F> factories) { - if (GenericUtils.isEmpty(algo) || GenericUtils.isEmpty(factories)) { - return null; - } - - for (F f : factories) { - if (comp.compare(algo, f.getAlgorithm()) == 0) { - return f; - } - } - - return null; - } - - /** - * @param f The {@link Factory} to create the {@link Digest} to use - * @param s The {@link String} to digest - ignored if {@code null}/empty, - * otherwise its UTF-8 representation is used as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input - * @throws Exception If failed to calculate the digest - * @see #getFingerPrint(Digest, String, Charset) - */ - public static String getFingerPrint(Factory<? extends Digest> f, String s) throws Exception { - return getFingerPrint(f, s, StandardCharsets.UTF_8); - } - - /** - * @param f The {@link Factory} to create the {@link Digest} to use - * @param s The {@link String} to digest - ignored if {@code null}/empty - * @param charset The {@link Charset} to use in order to convert the - * string to its byte representation to use as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input - * @throws Exception If failed to calculate the digest - */ - public static String getFingerPrint(Factory<? extends Digest> f, String s, Charset charset) throws Exception { - return getFingerPrint(Objects.requireNonNull(f, "No factory").create(), s, charset); - } - - /** - * @param d The {@link Digest} to use - * @param s The {@link String} to digest - ignored if {@code null}/empty, - * otherwise its UTF-8 representation is used as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input - * @throws Exception If failed to calculate the digest - * @see #getFingerPrint(Digest, String, Charset) - */ - public static String getFingerPrint(Digest d, String s) throws Exception { - return getFingerPrint(d, s, StandardCharsets.UTF_8); - } - - /** - * @param d The {@link Digest} to use - * @param s The {@link String} to digest - ignored if {@code null}/empty - * @param charset The {@link Charset} to use in order to convert the - * string to its byte representation to use as input for the fingerprint - * @return The fingerprint - {@code null} if {@code null}/empty input - * @throws Exception If failed to calculate the digest - */ - public static String getFingerPrint(Digest d, String s, Charset charset) throws Exception { - if (GenericUtils.isEmpty(s)) { - return null; - } else { - return DigestUtils.getFingerPrint(d, s.getBytes(charset)); - } - } - - /** - * @param f The {@link Factory} to create the {@link Digest} to use - * @param buf The data buffer to be fingerprint-ed - * @return The fingerprint - {@code null} if empty data buffer - * @throws Exception If failed to calculate the fingerprint - * @see #getFingerPrint(Factory, byte[], int, int) - */ - public static String getFingerPrint(Factory<? extends Digest> f, byte... buf) throws Exception { - return getFingerPrint(f, buf, 0, NumberUtils.length(buf)); - } - - /** - * @param f The {@link Factory} to create the {@link Digest} to use - * @param buf The data buffer to be fingerprint-ed - * @param offset The offset of the data in the buffer - * @param len The length of data - ignored if non-positive - * @return The fingerprint - {@code null} if non-positive length - * @throws Exception If failed to calculate the fingerprint - */ - public static String getFingerPrint(Factory<? extends Digest> f, byte[] buf, int offset, int len) throws Exception { - return getFingerPrint(Objects.requireNonNull(f, "No factory").create(), buf, offset, len); - } - - /** - * @param d The {@link Digest} to use - * @param buf The data buffer to be fingerprint-ed - * @return The fingerprint - {@code null} if empty data buffer - * @throws Exception If failed to calculate the fingerprint - * @see #getFingerPrint(Digest, byte[], int, int) - */ - public static String getFingerPrint(Digest d, byte... buf) throws Exception { - return getFingerPrint(d, buf, 0, NumberUtils.length(buf)); - } - - /** - * @param d The {@link Digest} to use - * @param buf The data buffer to be fingerprint-ed - * @param offset The offset of the data in the buffer - * @param len The length of data - ignored if non-positive - * @return The fingerprint - {@code null} if non-positive length - * @throws Exception If failed to calculate the fingerprint - * @see #getRawFingerprint(Digest, byte[], int, int) - */ - public static String getFingerPrint(Digest d, byte[] buf, int offset, int len) throws Exception { - if (len <= 0) { - return null; - } - - byte[] data = getRawFingerprint(d, buf, offset, len); - String algo = d.getAlgorithm(); - if (BuiltinDigests.md5.getAlgorithm().equals(algo)) { - return algo + ":" + BufferUtils.toHex(':', data).toLowerCase(); - } - - Base64.Encoder encoder = Base64.getEncoder(); - return algo.replace("-", "").toUpperCase() + ":" + encoder.encodeToString(data).replaceAll("=", ""); - } - - public static byte[] getRawFingerprint(Digest d, byte... buf) throws Exception { - return getRawFingerprint(d, buf, 0, NumberUtils.length(buf)); - } - - public static byte[] getRawFingerprint(Digest d, byte[] buf, int offset, int len) throws Exception { - if (len <= 0) { - return null; - } - - Objects.requireNonNull(d, "No digest").init(); - d.update(buf, offset, len); - - return d.digest(); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/digest/package.html ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/package.html b/sshd-core/src/main/java/org/apache/sshd/common/digest/package.html deleted file mode 100644 index 65940e0..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/digest/package.html +++ /dev/null @@ -1,25 +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. ---> -<html> -<head> -</head> -<body> - -<a href="{@docRoot}/org/apache/sshd/common/digest/Digest.html"><code>Digest</code></a> implementations. - -</body> -</html> http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/AbstractSshFuture.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/AbstractSshFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/AbstractSshFuture.java deleted file mode 100644 index 1dca54c..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/AbstractSshFuture.java +++ /dev/null @@ -1,194 +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.future; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.io.StreamCorruptedException; -import java.util.function.Function; - -import org.apache.sshd.common.SshException; -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.logging.AbstractLoggingBean; - -/** - * @param <T> Type of future - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractSshFuture<T extends SshFuture> extends AbstractLoggingBean implements SshFuture<T> { - /** - * A default value to indicate the future has been canceled - */ - protected static final Object CANCELED = new Object(); - - protected final boolean debugEnabled; - protected final boolean traceEnabled; - private final Object id; - - /** - * @param id Some identifier useful as {@link #toString()} value - */ - protected AbstractSshFuture(Object id) { - this.id = id; - this.debugEnabled = log.isDebugEnabled(); - this.traceEnabled = log.isTraceEnabled(); - } - - @Override - public Object getId() { - return id; - } - - @Override - public boolean await(long timeoutMillis) throws IOException { - return await0(timeoutMillis, true) != null; - } - - @Override - public boolean awaitUninterruptibly(long timeoutMillis) { - try { - return await0(timeoutMillis, false) != null; - } catch (InterruptedIOException e) { - throw formatExceptionMessage(msg -> new InternalError(msg, e), - "Unexpected interrupted exception wile awaitUninterruptibly %d msec: %s", - timeoutMillis, e.getMessage()); - } - } - - /** - * <P>Waits (interruptible) for the specified timeout (msec.) and then checks - * the result:</P> - * <UL> - * <LI><P> - * If result is {@code null} then timeout is assumed to have expired - throw - * an appropriate {@link IOException} - * </P></LI> - * - * <LI><P> - * If the result is of the expected type, then cast and return it - * </P></LI> - * - * <LI><P> - * If the result is an {@link IOException} then re-throw it - * </P></LI> - * - * <LI><P> - * If the result is a {@link Throwable} then throw an {@link IOException} - * whose cause is the original exception - * </P></LI> - * - * <LI><P> - * Otherwise (should never happen), throw a {@link StreamCorruptedException} - * with the name of the result type - * </P></LI> - * </UL> - * - * @param <R> The generic result type - * @param expectedType The expected result type - * @param timeout The timeout (millis) to wait for a result - * @return The (never {@code null}) result - * @throws IOException If failed to retrieve the expected result on time - */ - protected <R> R verifyResult(Class<? extends R> expectedType, long timeout) throws IOException { - Object value = await0(timeout, true); - if (value == null) { - throw formatExceptionMessage(SshException::new, "Failed to get operation result within specified timeout: %s", timeout); - } - - Class<?> actualType = value.getClass(); - if (expectedType.isAssignableFrom(actualType)) { - return expectedType.cast(value); - } - - if (Throwable.class.isAssignableFrom(actualType)) { - Throwable t = GenericUtils.peelException((Throwable) value); - if (t != value) { - value = t; - actualType = value.getClass(); - } - - if (IOException.class.isAssignableFrom(actualType)) { - throw (IOException) value; - } - - Throwable cause = GenericUtils.resolveExceptionCause(t); - throw formatExceptionMessage(msg -> new SshException(msg, cause), "Failed (%s) to execute: %s", t.getClass().getSimpleName(), t.getMessage()); - } else { // what else can it be ???? - throw formatExceptionMessage(StreamCorruptedException::new, "Unknown result type: %s", actualType.getName()); - } - } - - /** - * Wait for the Future to be ready. If the requested delay is 0 or - * negative, this method returns immediately. - * - * @param timeoutMillis The delay we will wait for the Future to be ready - * @param interruptable Tells if the wait can be interrupted or not. - * If {@code true} and the thread is interrupted then an {@link InterruptedIOException} - * is thrown. - * @return The non-{@code null} result object if the Future is ready, - * {@code null} if the timeout expired and no result was received - * @throws InterruptedIOException If the thread has been interrupted when it's not allowed. - */ - protected abstract Object await0(long timeoutMillis, boolean interruptable) throws InterruptedIOException; - - @SuppressWarnings("unchecked") - protected SshFutureListener<T> asListener(Object o) { - return (SshFutureListener<T>) o; - } - - protected void notifyListener(SshFutureListener<T> l) { - try { - l.operationComplete(asT()); - } catch (Throwable t) { - log.warn("notifyListener({}) failed ({}) to invoke {}: {}", - this, t.getClass().getSimpleName(), l, t.getMessage()); - if (debugEnabled) { - log.debug("notifyListener(" + this + ")[" + l + "] invocation failure details", t); - } - } - } - - @SuppressWarnings("unchecked") - protected T asT() { - return (T) this; - } - - /** - * Generates an exception whose message is prefixed by the future simple class name + {@link #getId() identifier} - * as a hint to the context of the failure. - * - * @param <E> Type of {@link Throwable} being generated - * @param exceptionCreator The exception creator from the formatted message - * @param format The extra payload format as per {@link String#format(String, Object...)} - * @param args The formatting arguments - * @return The generated exception - */ - protected <E extends Throwable> E formatExceptionMessage(Function<? super String, ? extends E> exceptionCreator, String format, Object... args) { - String messagePayload = String.format(format, args); - String excMessage = getClass().getSimpleName() + "[" + getId() + "]: " + messagePayload; - return exceptionCreator.apply(excMessage); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[id=" + getId() + "]"; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/CloseFuture.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/CloseFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/CloseFuture.java deleted file mode 100644 index 808716d..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/CloseFuture.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.future; - -/** - * An {@link SshFuture} for asynchronous close requests. - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface CloseFuture extends SshFuture<CloseFuture> { - - /** - * @return <tt>true</tt> if the close request is finished and the target is closed. - */ - boolean isClosed(); - - /** - * Marks this future as closed and notifies all threads waiting for this - * future. This method is invoked by SSHD internally. Please do not call - * this method directly. - */ - void setClosed(); - -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultCloseFuture.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultCloseFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultCloseFuture.java deleted file mode 100644 index 4c34a06..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultCloseFuture.java +++ /dev/null @@ -1,52 +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.future; - -/** - * A default implementation of {@link CloseFuture}. - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class DefaultCloseFuture extends DefaultSshFuture<CloseFuture> implements CloseFuture { - - /** - * Create a new instance - * - * @param id Some identifier useful as {@link #toString()} value - * @param lock A synchronization object for locking access - if {@code null} - * then synchronization occurs on {@code this} instance - */ - public DefaultCloseFuture(Object id, Object lock) { - super(id, lock); - } - - @Override - public boolean isClosed() { - if (isDone()) { - return (Boolean) getValue(); - } else { - return false; - } - } - - @Override - public void setClosed() { - setValue(Boolean.TRUE); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java deleted file mode 100644 index cd475ff..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultSshFuture.java +++ /dev/null @@ -1,236 +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.future; - -import java.io.InterruptedIOException; -import java.lang.reflect.Array; -import java.util.Objects; - -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.ValidateUtils; - -/** - * A default implementation of {@link SshFuture}. - * - * @param <T> Type of future - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class DefaultSshFuture<T extends SshFuture> extends AbstractSshFuture<T> { - /** - * A lock used by the wait() method - */ - private final Object lock; - private Object listeners; - private Object result; - - /** - * Creates a new instance. - * - * @param id Some identifier useful as {@link #toString()} value - * @param lock A synchronization object for locking access - if {@code null} - * then synchronization occurs on {@code this} instance - */ - public DefaultSshFuture(Object id, Object lock) { - super(id); - - this.lock = (lock != null) ? lock : this; - } - - @Override - protected Object await0(long timeoutMillis, boolean interruptable) throws InterruptedIOException { - ValidateUtils.checkTrue(timeoutMillis >= 0L, "Negative timeout N/A: %d", timeoutMillis); - long startTime = System.currentTimeMillis(); - long curTime = startTime; - long endTime = ((Long.MAX_VALUE - timeoutMillis) < curTime) ? Long.MAX_VALUE : (curTime + timeoutMillis); - - synchronized (lock) { - if ((result != null) || (timeoutMillis <= 0)) { - return result; - } - - for (;;) { - try { - lock.wait(endTime - curTime); - } catch (InterruptedException e) { - if (interruptable) { - curTime = System.currentTimeMillis(); - throw formatExceptionMessage(msg -> { - InterruptedIOException exc = new InterruptedIOException(msg); - exc.initCause(e); - return exc; - }, "Interrupted after %d msec.", curTime - startTime); - } - } - - curTime = System.currentTimeMillis(); - if ((result != null) || (curTime >= endTime)) { - return result; - } - } - } - } - - @Override - public boolean isDone() { - synchronized (lock) { - return result != null; - } - } - - /** - * Sets the result of the asynchronous operation, and mark it as finished. - * - * @param newValue The operation result - */ - public void setValue(Object newValue) { - synchronized (lock) { - // Allow only once. - if (result != null) { - return; - } - - result = (newValue != null) ? newValue : GenericUtils.NULL; - lock.notifyAll(); - } - - notifyListeners(); - } - - public int getNumRegisteredListeners() { - synchronized (lock) { - if (listeners == null) { - return 0; - } else if (listeners instanceof SshFutureListener) { - return 1; - } else { - int l = Array.getLength(listeners); - int count = 0; - for (int i = 0; i < l; i++) { - if (Array.get(listeners, i) != null) { - count++; - } - } - return count; - } - } - } - - /** - * @return The result of the asynchronous operation - or {@code null} - * if none set. - */ - public Object getValue() { - synchronized (lock) { - return (result == GenericUtils.NULL) ? null : result; - } - } - - @Override - public T addListener(SshFutureListener<T> listener) { - Objects.requireNonNull(listener, "Missing listener argument"); - boolean notifyNow = false; - synchronized (lock) { - // if already have a result don't register the listener and invoke it directly - if (result != null) { - notifyNow = true; - } else if (listeners == null) { - listeners = listener; // 1st listener ? - } else if (listeners instanceof SshFutureListener) { - listeners = new Object[]{listeners, listener}; - } else { // increase array of registered listeners - Object[] ol = (Object[]) listeners; - int l = ol.length; - Object[] nl = new Object[l + 1]; - System.arraycopy(ol, 0, nl, 0, l); - nl[l] = listener; - listeners = nl; - } - } - - if (notifyNow) { - notifyListener(listener); - } - - return asT(); - } - - @Override - public T removeListener(SshFutureListener<T> listener) { - Objects.requireNonNull(listener, "No listener provided"); - - synchronized (lock) { - if (result != null) { - return asT(); // the train has already left the station... - } - - if (listeners == null) { - return asT(); // no registered instances anyway - } - - if (listeners == listener) { - listeners = null; // the one and only - } else if (!(listeners instanceof SshFutureListener)) { - int l = Array.getLength(listeners); - for (int i = 0; i < l; i++) { - if (Array.get(listeners, i) == listener) { - Array.set(listeners, i, null); - break; - } - } - } - } - - return asT(); - } - - protected void notifyListeners() { - /* - * There won't be any visibility problem or concurrent modification - * because result value is checked in both addListener and - * removeListener calls under lock. If the result is already set then - * both methods will not modify the internal listeners - */ - if (listeners != null) { - if (listeners instanceof SshFutureListener) { - notifyListener(asListener(listeners)); - } else { - int l = Array.getLength(listeners); - for (int i = 0; i < l; i++) { - SshFutureListener<T> listener = asListener(Array.get(listeners, i)); - if (listener != null) { - notifyListener(listener); - } - } - } - } - } - - public boolean isCanceled() { - return getValue() == CANCELED; - } - - public void cancel() { - setValue(CANCELED); - } - - @Override - public String toString() { - return super.toString() + "[value=" + result + "]"; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultVerifiableSshFuture.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultVerifiableSshFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultVerifiableSshFuture.java deleted file mode 100644 index 1b02fed..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/DefaultVerifiableSshFuture.java +++ /dev/null @@ -1,30 +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.future; - -/** - * @param <T> Type of future - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class DefaultVerifiableSshFuture<T extends SshFuture> extends DefaultSshFuture<T> implements VerifiableFuture<T> { - protected DefaultVerifiableSshFuture(Object id, Object lock) { - super(id, lock); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/SshFuture.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/SshFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/SshFuture.java deleted file mode 100644 index b0d8e3c..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/SshFuture.java +++ /dev/null @@ -1,48 +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.future; - -/** - * Represents the completion of an asynchronous SSH operation on a given object - * (it may be an SSH session or an SSH channel). - * Can be listened for completion using a {@link SshFutureListener}. - * - * @param <T> Type of future - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface SshFuture<T extends SshFuture> extends WaitableFuture { - /** - * Adds an event <tt>listener</tt> which is notified when - * this future is completed. If the listener is added - * after the completion, the listener is directly notified. - * - * @param listener The {@link SshFutureListener} instance to add - * @return The future instance - */ - T addListener(SshFutureListener<T> listener); - - /** - * Removes an existing event <tt>listener</tt> so it won't be notified when - * the future is completed. - * - * @param listener The {@link SshFutureListener} instance to remove - * @return The future instance - */ - T removeListener(SshFutureListener<T> listener); -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/SshFutureListener.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/SshFutureListener.java b/sshd-core/src/main/java/org/apache/sshd/common/future/SshFutureListener.java deleted file mode 100644 index a005c0f..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/SshFutureListener.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.common.future; - -import org.apache.sshd.common.util.SshdEventListener; - -/** - * Something interested in being notified when the completion - * of an asynchronous SSH operation : {@link SshFuture}. - * - * @param <T> type of future - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -@SuppressWarnings("rawtypes") -@FunctionalInterface -public interface SshFutureListener<T extends SshFuture> extends SshdEventListener { - - /** - * Invoked when the operation associated with the {@link SshFuture} - * has been completed even if you add the listener after the completion. - * - * @param future The source {@link SshFuture} which called this - * callback. - */ - void operationComplete(T future); -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/VerifiableFuture.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/VerifiableFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/VerifiableFuture.java deleted file mode 100644 index e318de7..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/VerifiableFuture.java +++ /dev/null @@ -1,68 +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.future; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -/** - * Represents an asynchronous operation whose successful result can be - * verified somehow. The contract guarantees that if the {@code verifyXXX} - * method returns without an exception then the operation was completed - * <U>successfully</U> - * - * @param <T> Type of verification result - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -@FunctionalInterface -public interface VerifiableFuture<T> { - /** - * Wait {@link Long#MAX_VALUE} msec. and verify that the operation was successful - * - * @return The (same) future instance - * @throws IOException If failed to verify successfully on time - * @see #verify(long) - */ - default T verify() throws IOException { - return verify(Long.MAX_VALUE); - } - - /** - * Wait and verify that the operation was successful - * - * @param timeout The number of time units to wait - * @param unit The wait {@link TimeUnit} - * @return The (same) future instance - * @throws IOException If failed to verify successfully on time - * @see #verify(long) - */ - default T verify(long timeout, TimeUnit unit) throws IOException { - return verify(unit.toMillis(timeout)); - } - - /** - * Wait and verify that the operation was successful - * - * @param timeoutMillis Wait timeout in milliseconds - * @return The (same) future instance - * @throws IOException If failed to verify successfully on time - */ - T verify(long timeoutMillis) throws IOException; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/future/WaitableFuture.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/future/WaitableFuture.java b/sshd-core/src/main/java/org/apache/sshd/common/future/WaitableFuture.java deleted file mode 100644 index aff4adc..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/future/WaitableFuture.java +++ /dev/null @@ -1,118 +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.future; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -/** - * Represents an asynchronous operation which one can wait for its completion. - * <B>Note:</B> the only thing guaranteed is that if {@code true} is returned - * from one of the {@code awaitXXX} methods then the operation has completed. - * However, the <B>caller</B> has to determine whether it was a successful or - * failed completion. - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public interface WaitableFuture { - /** - * @return Some identifier useful as {@link #toString()} value - */ - Object getId(); - - /** - * Wait {@link Long#MAX_VALUE} msec. for the asynchronous operation to complete. - * The attached listeners will be notified when the operation is - * completed. - * - * @return {@code true} if the operation is completed. - * @throws IOException if failed - specifically {@link java.io.InterruptedIOException} - * if waiting was interrupted - * @see #await(long) - */ - default boolean await() throws IOException { - return await(Long.MAX_VALUE); - } - - /** - * Wait for the asynchronous operation to complete with the specified timeout. - * - * @param timeout The number of time units to wait - * @param unit The {@link TimeUnit} for waiting - * @return {@code true} if the operation is completed. - * @throws IOException if failed - specifically {@link java.io.InterruptedIOException} - * if waiting was interrupted - * @see #await(long) - */ - default boolean await(long timeout, TimeUnit unit) throws IOException { - return await(unit.toMillis(timeout)); - } - - /** - * Wait for the asynchronous operation to complete with the specified timeout. - * - * @param timeoutMillis Wait time in milliseconds - * @return {@code true} if the operation is completed. - * @throws IOException if failed - specifically {@link java.io.InterruptedIOException} - * if waiting was interrupted - */ - boolean await(long timeoutMillis) throws IOException; - - /** - * Wait {@link Long#MAX_VALUE} msec. for the asynchronous operation to complete - * uninterruptibly. The attached listeners will be notified when the operation is - * completed. - * - * @return {@code true} if the operation is completed. - * @see #awaitUninterruptibly(long) - */ - default boolean awaitUninterruptibly() { - return awaitUninterruptibly(Long.MAX_VALUE); - } - - /** - * Wait for the asynchronous operation to complete with the specified timeout - * uninterruptibly. - * - * @param timeout The number of time units to wait - * @param unit The {@link TimeUnit} for waiting - * @return {@code true} if the operation is completed. - * @see #awaitUninterruptibly(long) - */ - default boolean awaitUninterruptibly(long timeout, TimeUnit unit) { - return awaitUninterruptibly(unit.toMillis(timeout)); - } - - /** - * Wait for the asynchronous operation to complete with the specified timeout - * uninterruptibly. - * - * @param timeoutMillis Wait time in milliseconds - * @return {@code true} if the operation is finished. - */ - boolean awaitUninterruptibly(long timeoutMillis); - - /** - * @return {@code true} if the asynchronous operation is completed. <B>Note:</B> - * it is up to the <B>caller</B> to determine whether it was a successful or - * failed completion. - */ - boolean isDone(); -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java index 7dd7f86..2342e45 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java @@ -29,7 +29,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.apache.sshd.agent.SshAgentFactory; -import org.apache.sshd.common.AttributeStore; import org.apache.sshd.common.Factory; import org.apache.sshd.common.FactoryManager; import org.apache.sshd.common.NamedFactory; @@ -165,11 +164,6 @@ public abstract class AbstractFactoryManager extends AbstractKexFactoryManager i } @Override - public <T> T resolveAttribute(AttributeKey<T> key) { - return AttributeStore.resolveAttribute(this, key); - } - - @Override public PropertyResolver getParentPropertyResolver() { return parentResolver; } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java deleted file mode 100644 index 077d199..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractKeyPairProvider.java +++ /dev/null @@ -1,32 +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.keyprovider; - -import org.apache.sshd.common.util.logging.AbstractLoggingBean; - -/** - * Provides a default implementation for some {@link KeyPairProvider} methods - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractKeyPairProvider extends AbstractLoggingBean implements KeyPairProvider { - protected AbstractKeyPairProvider() { - super(); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java deleted file mode 100644 index e4e941d..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/AbstractResourceKeyPairProvider.java +++ /dev/null @@ -1,234 +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.keyprovider; - -import java.io.IOException; -import java.io.InputStream; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.security.PublicKey; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.TreeMap; -import java.util.TreeSet; - -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.ValidateUtils; -import org.apache.sshd.common.util.security.SecurityUtils; - -/** - * @param <R> Type of resource from which the {@link KeyPair} is generated - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPairProvider { - private FilePasswordProvider passwordFinder; - /* - * NOTE: the map is case insensitive even for Linux, as it is (very) bad - * practice to have 2 key files that differ from one another only in their - * case... - */ - private final Map<String, KeyPair> cacheMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - - protected AbstractResourceKeyPairProvider() { - super(); - } - - public FilePasswordProvider getPasswordFinder() { - return passwordFinder; - } - - public void setPasswordFinder(FilePasswordProvider passwordFinder) { - this.passwordFinder = passwordFinder; - } - - /** - * Checks which of the new resources we already loaded and can keep the - * associated key pair - * - * @param resources The collection of new resources - can be {@code null}/empty - * in which case the cache is cleared - */ - protected void resetCacheMap(Collection<?> resources) { - // if have any cached pairs then see what we can keep from previous load - Collection<String> toDelete = Collections.emptySet(); - synchronized (cacheMap) { - if (cacheMap.size() <= 0) { - return; // already empty - nothing to keep - } - - if (GenericUtils.isEmpty(resources)) { - cacheMap.clear(); - return; - } - - for (Object r : resources) { - String resourceKey = ValidateUtils.checkNotNullAndNotEmpty(Objects.toString(r, null), "No resource key value"); - if (cacheMap.containsKey(resourceKey)) { - continue; - } - - if (toDelete.isEmpty()) { - toDelete = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - } - - if (!toDelete.add(resourceKey)) { - continue; // debug breakpoint - } - } - - if (GenericUtils.size(toDelete) > 0) { - toDelete.forEach(cacheMap::remove); - } - } - - if (log.isDebugEnabled()) { - log.debug("resetCacheMap(" + resources + ") removed previous cached keys for " + toDelete); - } - } - - protected Iterable<KeyPair> loadKeys(final Collection<? extends R> resources) { - if (GenericUtils.isEmpty(resources)) { - return Collections.emptyList(); - } else { - return () -> new KeyPairIterator(resources); - } - } - - protected KeyPair doLoadKey(R resource) throws IOException, GeneralSecurityException { - String resourceKey = ValidateUtils.checkNotNullAndNotEmpty(Objects.toString(resource, null), "No resource string value"); - KeyPair kp; - synchronized (cacheMap) { - // check if lucky enough to have already loaded this file - kp = cacheMap.get(resourceKey); - } - - if (kp != null) { - if (log.isTraceEnabled()) { - PublicKey key = kp.getPublic(); - log.trace("doLoadKey({}) use cached key {}-{}", - resourceKey, KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key)); - } - return kp; - } - - kp = doLoadKey(resourceKey, resource, getPasswordFinder()); - if (kp != null) { - boolean reusedKey; - synchronized (cacheMap) { - // if somebody else beat us to it, use the cached key - just in case file contents changed - reusedKey = cacheMap.containsKey(resourceKey); - if (reusedKey) { - kp = cacheMap.get(resourceKey); - } else { - cacheMap.put(resourceKey, kp); - } - } - - if (log.isDebugEnabled()) { - PublicKey key = kp.getPublic(); - log.debug("doLoadKey({}) {} {}-{}", - resourceKey, reusedKey ? "re-loaded" : "loaded", - KeyUtils.getKeyType(key), KeyUtils.getFingerPrint(key)); - } - } else { - if (log.isDebugEnabled()) { - log.debug("doLoadKey({}) no key loaded", resourceKey); - } - } - - return kp; - } - - protected KeyPair doLoadKey(String resourceKey, R resource, FilePasswordProvider provider) throws IOException, GeneralSecurityException { - try (InputStream inputStream = openKeyPairResource(resourceKey, resource)) { - return doLoadKey(resourceKey, inputStream, provider); - } - } - - protected abstract InputStream openKeyPairResource(String resourceKey, R resource) throws IOException; - - protected KeyPair doLoadKey(String resourceKey, InputStream inputStream, FilePasswordProvider provider) - throws IOException, GeneralSecurityException { - return SecurityUtils.loadKeyPairIdentity(resourceKey, inputStream, provider); - } - - protected class KeyPairIterator implements Iterator<KeyPair> { - private final Iterator<? extends R> iterator; - private KeyPair nextKeyPair; - private boolean nextKeyPairSet; - - protected KeyPairIterator(Collection<? extends R> resources) { - iterator = resources.iterator(); - } - - @Override - public boolean hasNext() { - return nextKeyPairSet || setNextObject(); - } - - @Override - public KeyPair next() { - if (!nextKeyPairSet) { - if (!setNextObject()) { - throw new NoSuchElementException("Out of files to try"); - } - } - nextKeyPairSet = false; - return nextKeyPair; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("loadKeys(files) Iterator#remove() N/A"); - } - - @SuppressWarnings("synthetic-access") - private boolean setNextObject() { - boolean debugEnabled = log.isDebugEnabled(); - while (iterator.hasNext()) { - R r = iterator.next(); - try { - nextKeyPair = doLoadKey(r); - } catch (Throwable e) { - log.warn("Failed (" + e.getClass().getSimpleName() + ")" - + " to load key resource=" + r + ": " + e.getMessage()); - if (debugEnabled) { - log.debug("Key resource=" + r + " load failure details", e); - } - nextKeyPair = null; - continue; - } - - if (nextKeyPair != null) { - nextKeyPairSet = true; - return true; - } - } - - return false; - } - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java deleted file mode 100644 index 6e8da54..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/ClassLoadableResourceKeyPairProvider.java +++ /dev/null @@ -1,113 +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.keyprovider; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.StreamCorruptedException; -import java.security.KeyPair; -import java.util.Collection; -import java.util.Collections; - -import org.apache.sshd.common.util.ValidateUtils; -import org.apache.sshd.common.util.threads.ThreadUtils; - -/** - * This provider loads private keys from the specified resources that - * are accessible via {@link ClassLoader#getResourceAsStream(String)}. - * If no loader configured via {@link #setResourceLoader(ClassLoader)}, then - * {@link ThreadUtils#resolveDefaultClassLoader(Class)} is used - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class ClassLoadableResourceKeyPairProvider extends AbstractResourceKeyPairProvider<String> { - private ClassLoader classLoader; - private Collection<String> resources; - - public ClassLoadableResourceKeyPairProvider() { - this(Collections.emptyList()); - } - - public ClassLoadableResourceKeyPairProvider(ClassLoader cl) { - this(cl, Collections.emptyList()); - } - - public ClassLoadableResourceKeyPairProvider(String res) { - this(Collections.singletonList(ValidateUtils.checkNotNullAndNotEmpty(res, "No resource specified"))); - } - - public ClassLoadableResourceKeyPairProvider(ClassLoader cl, String res) { - this(cl, Collections.singletonList(ValidateUtils.checkNotNullAndNotEmpty(res, "No resource specified"))); - } - - public ClassLoadableResourceKeyPairProvider(Collection<String> resources) { - this.classLoader = ThreadUtils.resolveDefaultClassLoader(getClass()); - this.resources = (resources == null) ? Collections.emptyList() : resources; - } - - public ClassLoadableResourceKeyPairProvider(ClassLoader cl, Collection<String> resources) { - this.classLoader = cl; - this.resources = (resources == null) ? Collections.emptyList() : resources; - } - - public Collection<String> getResources() { - return resources; - } - - public void setResources(Collection<String> resources) { - this.resources = (resources == null) ? Collections.emptyList() : resources; - } - - public ClassLoader getResourceLoader() { - return classLoader; - } - - public void setResourceLoader(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - @Override - public Iterable<KeyPair> loadKeys() { - return loadKeys(getResources()); - } - - @Override - protected InputStream openKeyPairResource(String resourceKey, String resource) throws IOException { - ClassLoader cl = resolveClassLoader(); - if (cl == null) { - throw new StreamCorruptedException("No resource loader for " + resource); - } - - InputStream input = cl.getResourceAsStream(resource); - if (input == null) { - throw new FileNotFoundException("Cannot find resource " + resource); - } - - return input; - } - - protected ClassLoader resolveClassLoader() { - ClassLoader cl = getResourceLoader(); - if (cl == null) { - cl = ThreadUtils.resolveDefaultClassLoader(getClass()); - } - return cl; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.java deleted file mode 100644 index c4aae97..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/FileKeyPairProvider.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.keyprovider; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.GeneralSecurityException; -import java.security.KeyPair; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Objects; - -import org.apache.sshd.common.util.GenericUtils; -import org.apache.sshd.common.util.io.IoUtils; - -/** - * This host key provider loads private keys from the specified files. The - * loading is <U>lazy</U> - i.e., a file is not loaded until it is actually - * required. Once required though, its loaded {@link KeyPair} result is - * <U>cached</U> and not re-loaded. - * - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class FileKeyPairProvider extends AbstractResourceKeyPairProvider<Path> { - private Collection<? extends Path> files; - - public FileKeyPairProvider() { - super(); - } - - public FileKeyPairProvider(Path path) { - this(Collections.singletonList(Objects.requireNonNull(path, "No path provided"))); - } - - public FileKeyPairProvider(Path... files) { - this(Arrays.asList(files)); - } - - public FileKeyPairProvider(Collection<? extends Path> files) { - this.files = files; - } - - public Collection<? extends Path> getPaths() { - return files; - } - - public void setFiles(Collection<File> files) { - setPaths(GenericUtils.map(files, File::toPath)); - } - - public void setPaths(Collection<? extends Path> paths) { - // use absolute path in order to have unique cache keys - Collection<Path> resolved = GenericUtils.map(paths, Path::toAbsolutePath); - resetCacheMap(resolved); - files = resolved; - } - - @Override - public Iterable<KeyPair> loadKeys() { - return loadKeys(getPaths()); - } - - @Override - protected KeyPair doLoadKey(Path resource) throws IOException, GeneralSecurityException { - return super.doLoadKey((resource == null) ? null : resource.toAbsolutePath()); - } - - @Override - protected InputStream openKeyPairResource(String resourceKey, Path resource) throws IOException { - return Files.newInputStream(resource, IoUtils.EMPTY_OPEN_OPTIONS); - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java deleted file mode 100644 index 2ef4fa2..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java +++ /dev/null @@ -1,204 +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.keyprovider; - -import java.security.KeyPair; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.function.Function; -import java.util.function.Supplier; - -import org.apache.sshd.client.session.ClientSession; -import org.apache.sshd.common.util.GenericUtils; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -@FunctionalInterface -public interface KeyIdentityProvider { - /** - * An "empty" implementation of {@link KeyIdentityProvider} that - * returns an empty group of key pairs - */ - KeyIdentityProvider EMPTY_KEYS_PROVIDER = new KeyIdentityProvider() { - @Override - public Iterable<KeyPair> loadKeys() { - return Collections.emptyList(); - } - - @Override - public String toString() { - return "EMPTY"; - } - }; - - /** - * Invokes {@link KeyIdentityProvider#loadKeys()} and returns the result - ignores - * {@code null} providers (i.e., returns an empty iterable instance) - */ - Function<KeyIdentityProvider, Iterable<KeyPair>> LOADER = p -> - (p == null) ? Collections.<KeyPair>emptyList() : p.loadKeys(); - - /** - * Load available keys. - * - * @return an {@link Iterable} instance of available keys - ignored if {@code null} - */ - Iterable<KeyPair> loadKeys(); - - /** - * 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 - ? EMPTY_KEYS_PROVIDER - : 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> iteratorOf(ClientSession session) { - return iteratorOf(providerOf(session)); - } - - /** - * Creates a "unified" {@link Iterator} of {@link KeyPair}s out of 2 possible - * {@link KeyIdentityProvider} - * - * @param identities The registered keys identities - * @param keys Extra available key pairs - * @return The wrapping iterator - * @see #resolveKeyIdentityProvider(KeyIdentityProvider, KeyIdentityProvider) - */ - static Iterator<KeyPair> iteratorOf(KeyIdentityProvider identities, KeyIdentityProvider keys) { - return iteratorOf(resolveKeyIdentityProvider(identities, keys)); - } - - /** - * Resolves a non-{@code null} iterator of the available keys - * - * @param provider The {@link KeyIdentityProvider} - ignored if {@code null} - * @return A non-{@code null} iterator - which may be empty if no provider or no keys - */ - static Iterator<KeyPair> iteratorOf(KeyIdentityProvider provider) { - return GenericUtils.iteratorOf((provider == null) ? null : provider.loadKeys()); - } - - /** - * <P>Creates a "unified" {@link KeyIdentityProvider} out of 2 possible ones - * as follows:</P></BR> - * <UL> - * <LI>If both are {@code null} then return {@code null}.</LI> - * <LI>If either one is {@code null} then use the non-{@code null} one.</LI> - * <LI>If both are the same instance then use it.</U> - * <LI>Otherwise, returns a wrapper that groups both providers.</LI> - * </UL> - * @param identities The registered key pair identities - * @param keys The extra available key pairs - * @return The resolved provider - * @see #multiProvider(KeyIdentityProvider...) - */ - static KeyIdentityProvider resolveKeyIdentityProvider(KeyIdentityProvider identities, KeyIdentityProvider keys) { - if ((keys == null) || (identities == keys)) { - return identities; - } else if (identities == null) { - return keys; - } else { - return multiProvider(identities, keys); - } - } - - /** - * Wraps a group of {@link KeyIdentityProvider} into a single one - * - * @param providers The providers - ignored if {@code null}/empty (i.e., returns - * {@link #EMPTY_KEYS_PROVIDER}) - * @return The wrapping provider - * @see #multiProvider(Collection) - */ - static KeyIdentityProvider multiProvider(KeyIdentityProvider... providers) { - return multiProvider(GenericUtils.asList(providers)); - } - - /** - * Wraps a group of {@link KeyIdentityProvider} into a single one - * - * @param providers The providers - ignored if {@code null}/empty (i.e., returns - * {@link #EMPTY_KEYS_PROVIDER}) - * @return The wrapping provider - */ - static KeyIdentityProvider multiProvider(Collection<? extends KeyIdentityProvider> providers) { - return GenericUtils.isEmpty(providers) ? EMPTY_KEYS_PROVIDER : wrapKeyPairs(iterableOf(providers)); - } - - /** - * Wraps a group of {@link KeyIdentityProvider} into an {@link Iterable} of {@link KeyPair}s - * - * @param providers The group of providers - ignored if {@code null}/empty (i.e., returns an - * empty iterable instance) - * @return The wrapping iterable - */ - static Iterable<KeyPair> iterableOf(Collection<? extends KeyIdentityProvider> providers) { - Iterable<Supplier<Iterable<KeyPair>>> keysSuppliers = - GenericUtils.<KeyIdentityProvider, Supplier<Iterable<KeyPair>>>wrapIterable(providers, p -> p::loadKeys); - return GenericUtils.multiIterableSuppliers(keysSuppliers); - } - - /** - * Wraps a group of {@link KeyPair}s into a {@link KeyIdentityProvider} - * - * @param pairs The key pairs - ignored if {@code null}/empty (i.e., returns - * {@link #EMPTY_KEYS_PROVIDER}). - * @return The provider wrapper - */ - static KeyIdentityProvider wrapKeyPairs(KeyPair... pairs) { - return wrapKeyPairs(GenericUtils.asList(pairs)); - } - - /** - * Wraps a group of {@link KeyPair}s into a {@link KeyIdentityProvider} - * - * @param pairs The key pairs {@link Iterable} - ignored if {@code null} (i.e., returns - * {@link #EMPTY_KEYS_PROVIDER}). - * @return The provider wrapper - */ - static KeyIdentityProvider wrapKeyPairs(Iterable<KeyPair> pairs) { - return (pairs == null) ? EMPTY_KEYS_PROVIDER : () -> pairs; - } -}
