From 73883a5c266ee6029ca49e19d18c08516b61aa38 Mon Sep 17 00:00:00 2001 From: Lyor Goldstein Date: Fri, 26 Feb 2021 13:04:49 +0200 Subject: [PATCH] Moved some helper methods and classes to more natural locations --- CHANGES.md | 1 + .../sshd/cli/client/SftpCommandMain.java | 6 +- .../sshd/cli/client/SshClientCliSupport.java | 11 +- .../sshd/cli/client/SshKeyScanMain.java | 14 +- .../client/config/hosts/HostConfigEntry.java | 15 +- .../sshd/common/AttributeRepository.java | 6 +- .../apache/sshd/common/PropertyResolver.java | 14 + .../sshd/common/PropertyResolverUtils.java | 7 +- .../apache/sshd/common/channel/PtyMode.java | 11 +- .../sshd/common/config/TimeValueConfig.java | 3 +- .../config/keys/AuthorizedKeyEntry.java | 5 +- .../common/config/keys/IdentityUtils.java | 7 +- .../sshd/common/config/keys/KeyUtils.java | 4 +- .../impl/AbstractPublicKeyEntryDecoder.java | 4 +- .../impl/SkECDSAPublicKeyEntryDecoder.java | 2 +- .../impl/SkED25519PublicKeyEntryDecoder.java | 2 +- .../loader/PrivateKeyEncryptionContext.java | 3 +- .../loader/openssh/kdf/BCryptKdfOptions.java | 6 +- .../pem/AbstractPEMResourceKeyPairParser.java | 8 +- .../keys}/u2f/SecurityKeyPublicKey.java | 2 +- .../keys}/u2f/SkED25519PublicKey.java | 2 +- .../keys}/u2f/SkEcdsaPublicKey.java | 2 +- .../sshd/common/future/AbstractSshFuture.java | 6 +- .../common/kex/extension/KexExtensions.java | 3 +- .../keyprovider/KeyIdentityProvider.java | 5 +- .../AbstractSecurityKeySignature.java | 2 +- .../common/signature/SignatureFactory.java | 3 +- .../sshd/common/util/EventListenerUtils.java | 4 +- .../sshd/common/util/ExceptionUtils.java | 162 +++++++++++ .../apache/sshd/common/util/GenericUtils.java | 251 +----------------- .../sshd/common/util/MapEntryUtils.java | 113 ++++++++ .../sshd/common/util/ValidateUtils.java | 2 +- .../keys/SkECBufferPublicKeyParser.java | 2 +- .../keys/SkED25519BufferPublicKeyParser.java | 2 +- ...utoCloseableDelegateInvocationHandler.java | 3 +- .../util/{ => functors}/Int2IntFunction.java | 4 +- .../common/util/functors/UnaryEquator.java | 12 +- .../apache/sshd/common/util/io/IoUtils.java | 3 +- .../apache/sshd/common/util/io/PathUtils.java | 2 +- .../util/{ => io/functors}/Invoker.java | 7 +- .../common/util/net/SshdSocketAddress.java | 3 +- .../util/security/SecurityEntityFactory.java | 8 +- .../common/util/security/SecurityUtils.java | 5 +- ...BouncyCastleSecurityProviderRegistrar.java | 3 +- .../eddsa/EdDSASecurityProviderRegistrar.java | 4 +- .../java/org/apache/sshd/server/Signal.java | 9 +- .../config/hosts/HostConfigEntryTest.java | 5 +- .../config/keys/ClientIdentityTest.java | 3 +- .../sshd/common/VersionPropertiesTest.java | 3 +- .../sshd/common/channel/PtyModeTest.java | 4 +- .../config/keys/BuiltinIdentitiesTest.java | 3 +- .../keyprovider/KeyPairProviderTest.java | 3 +- .../sshd/common/util/GenericUtilsTest.java | 8 +- .../sshd/common/util/Int2IntFunctionTest.java | 1 + .../sshd/util/test/JUnitTestSupport.java | 5 +- .../InteractivePasswordIdentityProvider.java | 5 +- .../compression/DeflatingInputStream.java | 10 +- .../agent/local/ChannelAgentForwarding.java | 4 +- .../agent/unix/ChannelAgentForwarding.java | 3 +- .../org/apache/sshd/client/SshClient.java | 12 +- .../client/channel/AbstractClientChannel.java | 4 +- .../channel/PtyCapableChannelSession.java | 9 +- .../config/SshClientConfigFileReader.java | 3 +- .../client/session/AbstractClientSession.java | 3 +- .../AbstractSimpleClientSessionCreator.java | 6 +- .../sshd/common/channel/AbstractChannel.java | 15 +- .../channel/BufferedIoOutputStream.java | 4 +- .../sshd/common/forward/DefaultForwarder.java | 23 +- .../sshd/common/io/nio2/Nio2Connector.java | 6 +- .../sshd/common/io/nio2/Nio2Session.java | 4 +- .../DefaultClientKexExtensionHandler.java | 10 +- .../helpers/AbstractConnectionService.java | 2 +- .../session/helpers/AbstractSession.java | 5 +- .../common/session/helpers/SessionHelper.java | 34 +-- ...rizedKeyEntriesPublickeyAuthenticator.java | 3 +- .../server/channel/AbstractServerChannel.java | 4 +- .../server/channel/PuttyRequestHandler.java | 3 +- .../config/SshServerConfigFileReader.java | 5 +- .../server/config/keys/ServerIdentity.java | 3 +- .../server/forward/TcpipServerChannel.java | 8 +- .../global/CancelTcpipForwardHandler.java | 2 +- .../server/global/TcpipForwardHandler.java | 2 +- .../server/session/AbstractServerSession.java | 3 +- .../server/shell/InvertedShellWrapper.java | 5 +- .../sshd/server/shell/ProcessShell.java | 3 +- .../KnownHostsServerKeyVerifierTest.java | 3 +- .../common/PropertyResolverUtilsTest.java | 4 +- ...KeyboardInteractiveAuthenticationTest.java | 3 +- .../org/apache/sshd/server/ServerTest.java | 3 +- .../config/keys/ServerIdentityTest.java | 3 +- .../git/transport/GitSshdSessionFactory.java | 6 +- .../ldap/LdapPasswordAuthenticatorTest.java | 4 +- .../ldap/LdapPublickeyAuthenticatorTest.java | 4 +- .../org/apache/sshd/mina/MinaService.java | 4 +- .../org/apache/sshd/mina/MinaSession.java | 4 +- .../org/apache/sshd/netty/NettyIoSession.java | 3 +- .../openpgp/PGPAuthorizedEntriesTracker.java | 3 +- .../PGPAuthorizedKeyEntriesLoader.java | 3 +- .../sshd/openpgp/PGPPublicRingWatcher.java | 10 +- .../openpgp/PGPPublicRingWatcherTest.java | 8 +- .../apache/sshd/putty/PuttyKeyUtilsTest.java | 3 +- .../sshd/scp/client/SimpleScpClientImpl.java | 4 +- .../apache/sshd/sftp/client/SftpClient.java | 5 +- .../helpers/AbstractSftpClientExtension.java | 3 +- .../client/fs/SftpFileSystemProvider.java | 11 +- .../sftp/client/impl/DefaultSftpClient.java | 3 +- .../client/impl/SimpleSftpClientImpl.java | 10 +- .../apache/sshd/sftp/common/SftpHelper.java | 9 +- .../common/extensions/AclSupportedParser.java | 5 +- .../sftp/common/extensions/ParserUtils.java | 7 +- .../AbstractSftpEventListenerAdapter.java | 4 +- .../server/AbstractSftpSubsystemHelper.java | 17 +- .../apache/sshd/sftp/server/FileHandle.java | 3 +- .../org/apache/sshd/sftp/client/SftpTest.java | 3 +- .../sshd/sftp/client/SftpVersionsTest.java | 13 +- .../sftp/client/fs/SftpFileSystemTest.java | 3 +- .../ApacheSshdSftpSessionFactory.java | 6 +- .../spring/integration/SpringSftpSession.java | 7 +- 118 files changed, 649 insertions(+), 523 deletions(-) rename sshd-common/src/main/java/org/apache/sshd/common/{ => config/keys}/u2f/SecurityKeyPublicKey.java (95%) rename sshd-common/src/main/java/org/apache/sshd/common/{ => config/keys}/u2f/SkED25519PublicKey.java (97%) rename sshd-common/src/main/java/org/apache/sshd/common/{ => config/keys}/u2f/SkEcdsaPublicKey.java (97%) create mode 100644 sshd-common/src/main/java/org/apache/sshd/common/util/ExceptionUtils.java rename sshd-common/src/main/java/org/apache/sshd/common/util/{ => functors}/Int2IntFunction.java (95%) rename sshd-common/src/main/java/org/apache/sshd/common/util/{ => io/functors}/Invoker.java (95%) diff --git a/CHANGES.md b/CHANGES.md index 131c6d0d9..a909dfd38 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ ## Major code re-factoring * [SSHD-1133](https://issues.apache.org/jira/browse/SSHD-1133) Re-factored locations and names of `ServerSession` and server-side `ChannelSession` related classes +* Moved some helper methods and classes to more natural locations ## Potential compatibility issues diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java index c827fdef8..79cbc57be 100644 --- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java +++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SftpCommandMain.java @@ -58,7 +58,9 @@ import org.apache.sshd.common.mac.MacFactory; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.signature.SignatureFactory; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.OsUtils; import org.apache.sshd.common.util.ReflectionUtils; import org.apache.sshd.common.util.ValidateUtils; @@ -287,7 +289,7 @@ public static SftpClientFactory resolveSftpClientFactory(ClientSession session) .append(" to instantiate ").append(factoryName) .append(": ").println(t.getMessage()); System.err.flush(); - throw GenericUtils.toRuntimeException(t, true); + throw ExceptionUtils.toRuntimeException(t, true); } } @@ -540,7 +542,7 @@ public boolean executeCommand( Map extensions = sftp.getServerExtensions(); Map parsed = ParserUtils.parse(extensions); - if (GenericUtils.size(extensions) > 0) { + if (MapEntryUtils.size(extensions) > 0) { stdout.println(); } diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java index 87bc6d5f5..4af2024e3 100644 --- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java +++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientCliSupport.java @@ -78,6 +78,7 @@ import org.apache.sshd.common.keyprovider.FileKeyPairProvider; import org.apache.sshd.common.mac.Mac; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.OsUtils; import org.apache.sshd.common.util.ReflectionUtils; import org.apache.sshd.common.util.ValidateUtils; @@ -311,7 +312,7 @@ public static Path resolveIdentityFile(String id) throws IOException { } public static Map resolveClientEnvironment(Map options) { - if (GenericUtils.isEmpty(options)) { + if (MapEntryUtils.isEmpty(options)) { return Collections.emptyMap(); } @@ -350,7 +351,7 @@ public static PtyChannelConfiguration resolveClientPtyOptions(PropertyResolver r public static PtyChannelConfiguration resolveClientPtyOptions(Map options) throws IOException, InterruptedException { - Object v = GenericUtils.isEmpty(options) + Object v = MapEntryUtils.isEmpty(options) ? null : options.get(SshClientConfigFileReader.REQUEST_TTY_OPTION); String s = Objects.toString(v, "auto"); @@ -367,7 +368,7 @@ public static PtyChannelConfiguration resolveClientPtyOptions(Map opt // TODO add support for height/width, rows/columns and TERM(inal) type Map ptyModes = resolveClientPtyModes(options); - if (GenericUtils.isNotEmpty(ptyModes)) { + if (MapEntryUtils.isNotEmpty(ptyModes)) { config.setPtyModes(ptyModes); } @@ -376,7 +377,7 @@ public static PtyChannelConfiguration resolveClientPtyOptions(Map opt public static Map resolveClientPtyModes(Map options) throws IOException, InterruptedException { - Object v = GenericUtils.isEmpty(options) ? null : options.get(PtyMode.class.getSimpleName()); + Object v = MapEntryUtils.isEmpty(options) ? null : options.get(PtyMode.class.getSimpleName()); String s = Objects.toString(v, null); if (GenericUtils.isEmpty(s)) { return Collections.emptyMap(); @@ -473,7 +474,7 @@ public static SshClient setupClient( setupSessionExtensions(client, resolver, stdin, stdout, stderr); Map options = resolver.getProperties(); - if (GenericUtils.isNotEmpty(options)) { + if (MapEntryUtils.isNotEmpty(options)) { Map props = client.getProperties(); props.putAll(options); } diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshKeyScanMain.java b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshKeyScanMain.java index d9f7f45d3..068693880 100644 --- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshKeyScanMain.java +++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshKeyScanMain.java @@ -77,7 +77,9 @@ import org.apache.sshd.common.session.SessionListener; import org.apache.sshd.common.signature.BuiltinSignatures; import org.apache.sshd.common.signature.Signature; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.io.IoUtils; import org.apache.sshd.common.util.io.NoCloseInputStream; @@ -199,8 +201,8 @@ public Void call() throws Exception { } } - ValidateUtils.checkTrue(!GenericUtils.isEmpty(pairsMap), "No client key pairs"); - ValidateUtils.checkTrue(!GenericUtils.isEmpty(sigFactories), "No signature factories"); + ValidateUtils.checkTrue(!MapEntryUtils.isEmpty(pairsMap), "No client key pairs"); + ValidateUtils.checkTrue(!MapEntryUtils.isEmpty(sigFactories), "No signature factories"); Exception err = null; try { @@ -272,7 +274,7 @@ public void welcome(ClientSession session, String banner, String lang) { if (isEnabledLevel(Level.FINE)) { log(Level.FINE, "Failed to retrieve keys from " + h, e); } - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } finally { currentHostFingerprints.clear(); } @@ -283,7 +285,7 @@ public void welcome(ClientSession session, String banner, String lang) { try { close(); } catch (IOException e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } } @@ -600,7 +602,7 @@ public void close() throws IOException { try { input.close(); } catch (IOException e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } finally { input = null; } @@ -610,7 +612,7 @@ public void close() throws IOException { try { client.close(); } catch (IOException e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } finally { try { client.stop(); diff --git a/sshd-common/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntry.java b/sshd-common/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntry.java index 3ae8828a4..60927decc 100644 --- a/sshd-common/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntry.java +++ b/sshd-common/src/main/java/org/apache/sshd/client/config/hosts/HostConfigEntry.java @@ -51,6 +51,7 @@ import org.apache.sshd.common.config.keys.IdentityUtils; import org.apache.sshd.common.config.keys.PublicKeyEntry; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.MapEntryUtils.NavigableMapBuilder; import org.apache.sshd.common.util.OsUtils; import org.apache.sshd.common.util.ValidateUtils; @@ -308,7 +309,7 @@ public String getProperty(String name) { public String getProperty(String name, String defaultValue) { String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); Map props = getProperties(); - if (GenericUtils.isEmpty(props)) { + if (MapEntryUtils.isEmpty(props)) { return defaultValue; } @@ -342,7 +343,7 @@ public boolean processGlobalValues(HostConfigEntry globalEntry) { modified = updateGlobalIdentityOnly(globalEntry.isIdentitiesOnly()) || modified; Map updated = updateGlobalProperties(globalEntry.getProperties()); - modified = (GenericUtils.size(updated) > 0) || modified; + modified = (MapEntryUtils.size(updated) > 0) || modified; return modified; } @@ -354,7 +355,7 @@ public boolean processGlobalValues(HostConfigEntry globalEntry) { * @return A {@link Map} of the updated properties */ public Map updateGlobalProperties(Map props) { - if (GenericUtils.isEmpty(props)) { + if (MapEntryUtils.isEmpty(props)) { return Collections.emptyMap(); } @@ -545,7 +546,7 @@ public String setProperty(String name, String value) { } String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); - if (GenericUtils.isEmpty(properties)) { + if (MapEntryUtils.isEmpty(properties)) { properties = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); } @@ -559,7 +560,7 @@ public String setProperty(String name, String value) { public String removeProperty(String name) { String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); Map props = getProperties(); - if (GenericUtils.isEmpty(props)) { + if (MapEntryUtils.isEmpty(props)) { return null; } else { return props.remove(key); @@ -618,7 +619,7 @@ public static A appendNonEmptyPort(A sb, String name, int * @see #appendNonEmptyProperty(Appendable, String, Object) */ public static A appendNonEmptyProperties(A sb, Map props) throws IOException { - if (GenericUtils.isEmpty(props)) { + if (MapEntryUtils.isEmpty(props)) { return sb; } @@ -741,7 +742,7 @@ public static HostConfigEntry normalizeEntry( normal.setProxyJump(entry.resolveProxyJump(proxyJump)); Map props = entry.getProperties(); - if (GenericUtils.size(props) > 0) { + if (MapEntryUtils.size(props) > 0) { normal.setProperties( NavigableMapBuilder. builder(String.CASE_INSENSITIVE_ORDER) .putAll(props) diff --git a/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java b/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java index bd9e561a8..45613fa1f 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/AttributeRepository.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.Objects; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; /** * @author Apache MINA SSHD Project @@ -111,12 +111,12 @@ public int getAttributesCount() { @SuppressWarnings("unchecked") public T getAttribute(AttributeKey key) { Objects.requireNonNull(key, "No key provided"); - return GenericUtils.isEmpty(attributes) ? null : (T) attributes.get(key); + return MapEntryUtils.isEmpty(attributes) ? null : (T) attributes.get(key); } @Override public Collection> attributeKeys() { - return GenericUtils.isEmpty(attributes) + return MapEntryUtils.isEmpty(attributes) ? Collections.emptySet() : new HashSet<>(attributes.keySet()); } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java b/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java index 64ddffca3..bf8982df2 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolver.java @@ -23,6 +23,8 @@ import java.util.Collections; import java.util.Map; +import org.apache.sshd.common.util.MapEntryUtils; + /** * Indicates an entity that can be configured using properties. The properties are simple name-value pairs where the * actual value type depends on the property. Some automatic conversions may be available - e.g., from a string to a @@ -48,6 +50,11 @@ public Map getProperties() { return Collections.emptyMap(); } + @Override + public boolean isEmpty() { + return true; + } + @Override public String toString() { return "EMPTY"; @@ -81,6 +88,10 @@ public String toString() { */ Map getProperties(); + default boolean isEmpty() { + return MapEntryUtils.isEmpty(getProperties()); + } + default long getLongProperty(String name, long def) { return PropertyResolverUtils.getLongProperty(this, name, def); } @@ -122,4 +133,7 @@ default Charset getCharset(String name, Charset defaultValue) { return (value == null) ? defaultValue : PropertyResolverUtils.toCharset(value); } + static boolean isEmpty(PropertyResolver resolver) { + return (resolver == null) || resolver.isEmpty(); + } } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolverUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolverUtils.java index a42cd1ced..0c19d8e17 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolverUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/PropertyResolverUtils.java @@ -30,6 +30,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.ValidateUtils; /** @@ -128,7 +129,7 @@ public static Long getLong(Map props, String name) { *
  • If the value is {@code null} then returns {@code null}.
  • * *
  • If the value is already a {@link Long} then it is returned as such.
  • - * + * *
  • If value is a {@link Number} then its {@link Number#longValue()} is wrapped as a {@link Long}
  • * *
  • Otherwise, the value's {@code toString()} is parsed as a {@link Long}
  • @@ -317,7 +318,7 @@ public static Boolean getBoolean(Map props, String name) { *
  • Otherwise, throws an {@link UnsupportedOperationException}
  • *

    * - * + * * @param value The value to be converted * @return The result - {@code null} if {@code null} or an empty string * @throws UnsupportedOperationException If value cannot be converted to a boolean - e.g., a number. @@ -504,7 +505,7 @@ public static Map resolvePropertiesSource(PropertyResolver resol } public static PropertyResolver toPropertyResolver(Properties props) { - if (GenericUtils.isEmpty(props)) { + if (MapEntryUtils.isEmpty(props)) { return PropertyResolver.EMPTY; } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java b/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java index b79c11d6c..0f0a1a244 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java @@ -30,6 +30,7 @@ import java.util.function.ToIntFunction; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; /** * A enum describing the tty modes according to RFC 4254 - @@ -294,7 +295,7 @@ public enum PtyMode { public static final Set MODES = Collections.unmodifiableSet(EnumSet.allOf(PtyMode.class)); public static final NavigableMap COMMANDS = Collections.unmodifiableNavigableMap( - GenericUtils.toSortedMap(MODES, PtyMode::toInt, Function.identity(), Comparator.naturalOrder())); + MapEntryUtils.toSortedMap(MODES, PtyMode::toInt, Function.identity(), Comparator.naturalOrder())); /** * A {@code null}-safe {@link ToIntFunction} that returns the {@link PtyMode#toInt()} value and (-1) for @@ -304,7 +305,7 @@ public enum PtyMode { /** * A {@code null}-safe {@link Comparator} of {@link PtyMode} values according to their {@link PtyMode#toInt()} value - * + * * @see #OPCODE_EXTRACTOR */ public static final Comparator BY_OPCODE = new Comparator() { @@ -385,7 +386,7 @@ public static Set resolveEnabledOptions(Map modes, PtyMode. * @see #getBooleanSettingValue(Map, PtyMode) */ public static Set resolveEnabledOptions(Map modes, Collection options) { - if (GenericUtils.isEmpty(modes) || GenericUtils.isEmpty(options)) { + if (MapEntryUtils.isEmpty(modes) || GenericUtils.isEmpty(options)) { return Collections.emptySet(); } @@ -413,7 +414,7 @@ public static Set resolveEnabledOptions(Map modes, Collecti * @see #getBooleanSettingValue(Object) */ public static boolean getBooleanSettingValue(Map modes, PtyMode m) { - if ((m == null) || GenericUtils.isEmpty(modes)) { + if ((m == null) || MapEntryUtils.isEmpty(modes)) { return false; } else { return getBooleanSettingValue(modes.get(m)); @@ -441,7 +442,7 @@ public static boolean getBooleanSettingValue(Map modes, PtyMode m) { */ public static boolean getBooleanSettingValue( Map modes, Collection enablers, boolean defaultValue) { - if (GenericUtils.isEmpty(modes) || GenericUtils.isEmpty(enablers)) { + if (MapEntryUtils.isEmpty(modes) || GenericUtils.isEmpty(enablers)) { return defaultValue; } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java b/sshd-common/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java index 9652a9083..0e84f86cc 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java @@ -27,6 +27,7 @@ import java.util.concurrent.TimeUnit; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; /** * @author Apache MINA SSHD Project @@ -159,7 +160,7 @@ public static Map parse(String s) throws IllegalArgumentE * @throws IllegalArgumentException If negative count for a time unit */ public static long durationOf(Map spec) throws IllegalArgumentException { - if (GenericUtils.isEmpty(spec)) { + if (MapEntryUtils.isEmpty(spec)) { return -1L; } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java index b584b40da..262813677 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntry.java @@ -43,6 +43,7 @@ import org.apache.sshd.common.session.SessionContext; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.io.NoCloseInputStream; import org.apache.sshd.common.util.io.NoCloseReader; @@ -113,7 +114,7 @@ public PublicKey appendPublicKey( SessionContext session, Appendable sb, PublicKeyEntryResolver fallbackResolver) throws IOException, GeneralSecurityException { Map options = getLoginOptions(); - if (!GenericUtils.isEmpty(options)) { + if (MapEntryUtils.isNotEmpty(options)) { int index = 0; // Cannot use forEach because the index value is not effectively final for (Map.Entry oe : options.entrySet()) { @@ -160,7 +161,7 @@ public String toString() { String entry = super.toString(); String kc = getComment(); Map ko = getLoginOptions(); - return (GenericUtils.isEmpty(ko) ? "" : ko.toString() + " ") + return (MapEntryUtils.isEmpty(ko) ? "" : ko.toString() + " ") + entry + (GenericUtils.isEmpty(kc) ? "" : " " + kc); } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java index 370b5f953..b353dbc93 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/IdentityUtils.java @@ -35,6 +35,7 @@ import org.apache.sshd.common.keyprovider.MappedKeyPairProvider; import org.apache.sshd.common.session.SessionContext; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.io.resource.PathResource; import org.apache.sshd.common.util.security.SecurityUtils; @@ -91,7 +92,7 @@ public static String getIdentityFileName(String prefix, String type, String suff * @see BuiltinIdentities */ public static KeyPairProvider createKeyPairProvider(Map ids, boolean supportedOnly) { - if (GenericUtils.isEmpty(ids)) { + if (MapEntryUtils.isEmpty(ids)) { return null; } @@ -117,7 +118,7 @@ public static KeyPairProvider createKeyPairProvider(Map ids, bo } }); - if (GenericUtils.isEmpty(pairsMap)) { + if (MapEntryUtils.isEmpty(pairsMap)) { return null; } else { return new MappedKeyPairProvider(pairsMap); @@ -142,7 +143,7 @@ public static KeyPairProvider createKeyPairProvider(Map ids, bo public static NavigableMap loadIdentities( SessionContext session, Map paths, FilePasswordProvider provider, OpenOption... options) throws IOException, GeneralSecurityException { - if (GenericUtils.isEmpty(paths)) { + if (MapEntryUtils.isEmpty(paths)) { return Collections.emptyNavigableMap(); } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java index 19d6a0e99..8283d4bee 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java @@ -72,13 +72,13 @@ import org.apache.sshd.common.config.keys.impl.RSAPublicKeyDecoder; import org.apache.sshd.common.config.keys.impl.SkECDSAPublicKeyEntryDecoder; import org.apache.sshd.common.config.keys.impl.SkED25519PublicKeyEntryDecoder; +import org.apache.sshd.common.config.keys.u2f.SkED25519PublicKey; +import org.apache.sshd.common.config.keys.u2f.SkEcdsaPublicKey; import org.apache.sshd.common.digest.BuiltinDigests; import org.apache.sshd.common.digest.Digest; import org.apache.sshd.common.digest.DigestFactory; import org.apache.sshd.common.digest.DigestUtils; import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.u2f.SkED25519PublicKey; -import org.apache.sshd.common.u2f.SkEcdsaPublicKey; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.MapEntryUtils.NavigableMapBuilder; import org.apache.sshd.common.util.OsUtils; diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPublicKeyEntryDecoder.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPublicKeyEntryDecoder.java index 371500f7f..f0ebec6dd 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPublicKeyEntryDecoder.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/AbstractPublicKeyEntryDecoder.java @@ -26,7 +26,7 @@ import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.config.keys.PublicKeyEntryDecoder; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; /** * Useful base class implementation for a decoder of an {@code OpenSSH} encoded key data @@ -43,7 +43,7 @@ protected AbstractPublicKeyEntryDecoder(Class pubType, Class prvType, } protected final boolean parseBooleanHeader(Map headers, String propertyKey, boolean defaultVal) { - if (GenericUtils.isEmpty(headers) || !headers.containsKey(propertyKey)) { + if (MapEntryUtils.isEmpty(headers) || !headers.containsKey(propertyKey)) { return defaultVal; } String stringVal = headers.get(propertyKey); diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkECDSAPublicKeyEntryDecoder.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkECDSAPublicKeyEntryDecoder.java index 7c1f865be..5974b8fbf 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkECDSAPublicKeyEntryDecoder.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkECDSAPublicKeyEntryDecoder.java @@ -35,8 +35,8 @@ import org.apache.sshd.common.cipher.ECCurves; import org.apache.sshd.common.config.keys.KeyEntryResolver; +import org.apache.sshd.common.config.keys.u2f.SkEcdsaPublicKey; import org.apache.sshd.common.session.SessionContext; -import org.apache.sshd.common.u2f.SkEcdsaPublicKey; /** * @author Apache MINA SSHD Project diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java index eca03c7c9..550e1b925 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/impl/SkED25519PublicKeyEntryDecoder.java @@ -34,9 +34,9 @@ import net.i2p.crypto.eddsa.EdDSAPublicKey; import org.apache.sshd.common.config.keys.KeyEntryResolver; +import org.apache.sshd.common.config.keys.u2f.SkED25519PublicKey; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.session.SessionContext; -import org.apache.sshd.common.u2f.SkED25519PublicKey; import org.apache.sshd.common.util.security.eddsa.Ed25519PublicKeyDecoder; /** diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyEncryptionContext.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyEncryptionContext.java index 1399ff852..78efb2e63 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyEncryptionContext.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/PrivateKeyEncryptionContext.java @@ -33,6 +33,7 @@ import org.apache.sshd.common.auth.MutablePassword; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.ValidateUtils; /** @@ -45,7 +46,7 @@ public class PrivateKeyEncryptionContext implements MutablePassword, Cloneable { = Stream.of(AESPrivateKeyObfuscator.INSTANCE, DESPrivateKeyObfuscator.INSTANCE) .collect(Collectors.toMap( AbstractPrivateKeyObfuscator::getCipherName, Function.identity(), - GenericUtils.throwingMerger(), () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER))); + MapEntryUtils.throwingMerger(), () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER))); private String cipherName; private String cipherType; diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/kdf/BCryptKdfOptions.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/kdf/BCryptKdfOptions.java index 9fbc35ec8..5937b0e85 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/kdf/BCryptKdfOptions.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/openssh/kdf/BCryptKdfOptions.java @@ -40,7 +40,7 @@ import org.apache.sshd.common.config.keys.KeyEntryResolver; import org.apache.sshd.common.config.keys.loader.openssh.OpenSSHKdfOptions; import org.apache.sshd.common.session.SessionContext; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.NumberUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.BufferUtils; @@ -144,12 +144,12 @@ public byte[] decodePrivateKeyBytes( Arrays.fill(iv, (byte) 0); } } catch (RuntimeException e) { - Throwable t = GenericUtils.peelException(e); + Throwable t = ExceptionUtils.peelException(e); Throwable err = null; if ((t instanceof IOException) || (t instanceof GeneralSecurityException)) { err = t; } else { - t = GenericUtils.resolveExceptionCause(e); + t = ExceptionUtils.resolveExceptionCause(e); if ((t instanceof IOException) || (t instanceof GeneralSecurityException)) { err = t; } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java index d659b7b80..79109c271 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java @@ -45,6 +45,8 @@ import org.apache.sshd.common.config.keys.loader.PrivateKeyObfuscator; import org.apache.sshd.common.session.SessionContext; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; +import org.apache.sshd.common.util.NumberUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.BufferUtils; @@ -91,7 +93,7 @@ public Collection extractKeyPairs( byte[] initVector = null; String algInfo = null; int dataStartIndex = -1; - boolean hdrsAvailable = GenericUtils.isNotEmpty(headers); + boolean hdrsAvailable = MapEntryUtils.isNotEmpty(headers); for (int index = 0; index < lines.size(); index++) { String line = GenericUtils.trimToEmpty(lines.get(index)); if (GenericUtils.isEmpty(line)) { @@ -108,7 +110,7 @@ public Collection extractKeyPairs( String hdrName = line.substring(0, headerPos).trim(); String hdrValue = line.substring(headerPos + 1).trim(); if (!hdrsAvailable) { - Map accHeaders = GenericUtils.isEmpty(headers) + Map accHeaders = MapEntryUtils.isEmpty(headers) ? new TreeMap<>(String.CASE_INSENSITIVE_ORDER) : headers; accHeaders.put(hdrName, hdrValue); @@ -216,7 +218,7 @@ protected byte[] applyPrivateKeyCipher( if (encryptIt) { byte[] initVector = encContext.getInitVector(); - if (GenericUtils.isEmpty(initVector)) { + if (NumberUtils.isEmpty(initVector)) { initVector = o.generateInitializationVector(encContext); encContext.setInitVector(initVector); } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/u2f/SecurityKeyPublicKey.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SecurityKeyPublicKey.java similarity index 95% rename from sshd-common/src/main/java/org/apache/sshd/common/u2f/SecurityKeyPublicKey.java rename to sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SecurityKeyPublicKey.java index 9496aec36..314d84853 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/u2f/SecurityKeyPublicKey.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SecurityKeyPublicKey.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sshd.common.u2f; +package org.apache.sshd.common.config.keys.u2f; import java.security.PublicKey; diff --git a/sshd-common/src/main/java/org/apache/sshd/common/u2f/SkED25519PublicKey.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SkED25519PublicKey.java similarity index 97% rename from sshd-common/src/main/java/org/apache/sshd/common/u2f/SkED25519PublicKey.java rename to sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SkED25519PublicKey.java index 15735296e..5184242e2 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/u2f/SkED25519PublicKey.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SkED25519PublicKey.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sshd.common.u2f; +package org.apache.sshd.common.config.keys.u2f; import net.i2p.crypto.eddsa.EdDSAPublicKey; diff --git a/sshd-common/src/main/java/org/apache/sshd/common/u2f/SkEcdsaPublicKey.java b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SkEcdsaPublicKey.java similarity index 97% rename from sshd-common/src/main/java/org/apache/sshd/common/u2f/SkEcdsaPublicKey.java rename to sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SkEcdsaPublicKey.java index 41d31667b..355cac3a9 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/u2f/SkEcdsaPublicKey.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/config/keys/u2f/SkEcdsaPublicKey.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sshd.common.u2f; +package org.apache.sshd.common.config.keys.u2f; import java.security.interfaces.ECPublicKey; diff --git a/sshd-common/src/main/java/org/apache/sshd/common/future/AbstractSshFuture.java b/sshd-common/src/main/java/org/apache/sshd/common/future/AbstractSshFuture.java index 246c0a6cb..650d9e1ae 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/future/AbstractSshFuture.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/future/AbstractSshFuture.java @@ -25,7 +25,7 @@ import java.util.function.Function; import org.apache.sshd.common.SshException; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.logging.AbstractLoggingBean; /** @@ -120,13 +120,13 @@ protected R verifyResult(Class expectedType, long timeout) thro } if (Throwable.class.isAssignableFrom(actualType)) { - Throwable t = GenericUtils.peelException((Throwable) value); + Throwable t = ExceptionUtils.peelException((Throwable) value); if (t instanceof SshException) { throw new SshException(((SshException) t).getDisconnectCode(), t.getMessage(), t); } - Throwable cause = GenericUtils.resolveExceptionCause(t); + Throwable cause = ExceptionUtils.resolveExceptionCause(t); throw formatExceptionMessage( msg -> new SshException(msg, cause), "Failed (%s) to execute: %s", diff --git a/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java b/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java index 7741551e2..bc21f2e30 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/kex/extension/KexExtensions.java @@ -42,6 +42,7 @@ import org.apache.sshd.common.kex.extension.parser.NoFlowControl; import org.apache.sshd.common.kex.extension.parser.ServerSignatureAlgorithms; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.Readable; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; @@ -72,7 +73,7 @@ public final class KexExtensions { DelayCompression.INSTANCE) .collect(Collectors.toMap( NamedResource::getName, Function.identity(), - GenericUtils.throwingMerger(), () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER))); + MapEntryUtils.throwingMerger(), () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER))); private KexExtensions() { throw new UnsupportedOperationException("No instance allowed"); diff --git a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java index af67047be..ea08b6d24 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/keyprovider/KeyIdentityProvider.java @@ -28,6 +28,7 @@ import org.apache.sshd.common.session.SessionContext; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.functors.UnaryEquator; /** * @author Apache MINA SSHD Project @@ -65,7 +66,7 @@ public String toString() { * @return {@code true} if instance is {@code null} or the {@link #EMPTY_KEYS_PROVIDER} */ static boolean isEmpty(KeyIdentityProvider provider) { - return (provider == null) || GenericUtils.isSameReference(provider, EMPTY_KEYS_PROVIDER); + return (provider == null) || UnaryEquator.isSameReference(provider, EMPTY_KEYS_PROVIDER); } /** @@ -87,7 +88,7 @@ static boolean isEmpty(KeyIdentityProvider provider) { */ static KeyIdentityProvider resolveKeyIdentityProvider( KeyIdentityProvider identities, KeyIdentityProvider keys) { - if (isEmpty(keys) || GenericUtils.isSameReference(identities, keys)) { + if (isEmpty(keys) || UnaryEquator.isSameReference(identities, keys)) { // Prefer EMPTY over null return (identities == null) ? keys : identities; } else if (isEmpty(identities)) { diff --git a/sshd-common/src/main/java/org/apache/sshd/common/signature/AbstractSecurityKeySignature.java b/sshd-common/src/main/java/org/apache/sshd/common/signature/AbstractSecurityKeySignature.java index 874565689..66bebb264 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/signature/AbstractSecurityKeySignature.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/signature/AbstractSecurityKeySignature.java @@ -24,8 +24,8 @@ import java.security.PrivateKey; import java.security.PublicKey; +import org.apache.sshd.common.config.keys.u2f.SecurityKeyPublicKey; import org.apache.sshd.common.session.SessionContext; -import org.apache.sshd.common.u2f.SecurityKeyPublicKey; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; import org.apache.sshd.common.util.security.SecurityUtils; diff --git a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureFactory.java b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureFactory.java index 5a7e86c7c..b88178edb 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureFactory.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/signature/SignatureFactory.java @@ -40,6 +40,7 @@ import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.security.SecurityUtils; /** @@ -163,7 +164,7 @@ static int resolvePreferredSignaturePosition( static int resolvePreferredSignaturePosition( List preferredOrder, int prefValue, Map posMap) { - if (GenericUtils.isEmpty(preferredOrder) || (prefValue < 0) || GenericUtils.isEmpty(posMap)) { + if (GenericUtils.isEmpty(preferredOrder) || (prefValue < 0) || MapEntryUtils.isEmpty(posMap)) { return -1; } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/EventListenerUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/EventListenerUtils.java index ffc719fc6..f28c4f3df 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/EventListenerUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/EventListenerUtils.java @@ -198,8 +198,8 @@ public static T proxyWrapper( try { method.invoke(l, args); } catch (Throwable t) { - Throwable e = GenericUtils.peelException(t); - err = GenericUtils.accumulateException(err, e); + Throwable e = ExceptionUtils.peelException(t); + err = ExceptionUtils.accumulateException(err, e); } } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/ExceptionUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/ExceptionUtils.java new file mode 100644 index 000000000..64aae6821 --- /dev/null +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/ExceptionUtils.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sshd.common.util; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.concurrent.ExecutionException; + +import javax.management.MBeanException; +import javax.management.ReflectionException; + +/** + * @author Apache MINA SSHD Project + */ +public final class ExceptionUtils { + private ExceptionUtils() { + throw new UnsupportedOperationException("No instance"); + } + + public static void rethrowAsIoException(Throwable e) throws IOException { + if (e instanceof IOException) { + throw (IOException) e; + } else if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else if (e instanceof Error) { + throw (Error) e; + } else { + throw new IOException(e); + } + } + + /** + * Used to "accumulate" exceptions of the same type. If the current exception is {@code null} then + * the new one becomes the current, otherwise the new one is added as a suppressed exception to the current + * one + * + * @param The exception type + * @param current The current exception + * @param extra The extra/new exception + * @return The resolved exception + * @see Throwable#addSuppressed(Throwable) + */ + public static T accumulateException(T current, T extra) { + if (current == null) { + return extra; + } + + if ((extra == null) || (extra == current)) { + return current; + } + + current.addSuppressed(extra); + return current; + } + + /** + * @param t The original {@link Throwable} - ignored if {@code null} + * @return If {@link Throwable#getCause()} is non-{@code null} then the cause, otherwise the original exception - + * {@code null} if the original exception was {@code null} + */ + public static Throwable resolveExceptionCause(Throwable t) { + if (t == null) { + return t; + } + + Throwable c = t.getCause(); + if (c == null) { + return t; + } else { + return c; + } + } + + /** + * Attempts to get to the "effective" exception being thrown, by taking care of some known exceptions that + * wrap the original thrown one. + * + * @param t The original {@link Throwable} - ignored if {@code null} + * @return The effective exception - same as input if not a wrapper + */ + public static Throwable peelException(Throwable t) { + // NOTE: check order is important - e.g., InvocationTargetException extends ReflectiveOperationException + if (t == null) { + return t; + } else if (t instanceof UndeclaredThrowableException) { + Throwable wrapped = ((UndeclaredThrowableException) t).getUndeclaredThrowable(); + // according to the Javadoc it may be null, in which case 'getCause' + // might contain the information we need + if (wrapped != null) { + return peelException(wrapped); + } + + wrapped = t.getCause(); + if (wrapped != t) { // make sure it is a real cause + return peelException(wrapped); + } + } else if (t instanceof InvocationTargetException) { + Throwable target = ((InvocationTargetException) t).getTargetException(); + if (target != null) { + return peelException(target); + } + } else if (t instanceof ReflectionException) { + Throwable target = ((ReflectionException) t).getTargetException(); + if (target != null) { + return peelException(target); + } + } else if (t instanceof ExecutionException) { + Throwable wrapped = resolveExceptionCause(t); + if (wrapped != null) { + return peelException(wrapped); + } + } else if (t instanceof MBeanException) { + Throwable target = ((MBeanException) t).getTargetException(); + if (target != null) { + return peelException(target); + } + } + + return t; // no special handling required or available + } + + /** + * Converts a thrown generic exception to a {@link RuntimeException} + * + * @param t The original thrown exception + * @param peelThrowable Whether to determine the root cause by "peeling" any enclosing exceptions + * @return The thrown cause if already a runtime exception, otherwise a runtime exception of the + * resolved exception as its cause + * @see #peelException(Throwable) + */ + public static RuntimeException toRuntimeException(Throwable t, boolean peelThrowable) { + Throwable e = peelThrowable ? peelException(t) : t; + if (e instanceof RuntimeException) { + return (RuntimeException) e; + } + + return new RuntimeException(e); + } + + public static RuntimeException toRuntimeException(Throwable t) { + return toRuntimeException(t, true); + } + +} diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java index 181a902aa..11da272bf 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/GenericUtils.java @@ -19,9 +19,6 @@ package org.apache.sshd.common.util; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.UndeclaredThrowableException; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -34,17 +31,12 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.NavigableMap; import java.util.NavigableSet; import java.util.Objects; import java.util.Set; import java.util.SortedSet; -import java.util.TreeMap; import java.util.TreeSet; -import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BinaryOperator; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -54,9 +46,6 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -import javax.management.MBeanException; -import javax.management.ReflectionException; - import org.apache.sshd.common.util.functors.UnaryEquator; /** @@ -88,9 +77,6 @@ public final class GenericUtils { public static final String QUOTES = "\"'"; - @SuppressWarnings("rawtypes") - private static final Supplier CASE_INSENSITIVE_MAP_FACTORY = () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - private GenericUtils() { throw new UnsupportedOperationException("No instance"); } @@ -185,7 +171,7 @@ public static int hashCode(String s, Boolean useUppercase) { } public static int safeCompare(String s1, String s2, boolean caseSensitive) { - if (isSameReference(s1, s2)) { + if (UnaryEquator.isSameReference(s1, s2)) { return 0; } else if (s1 == null) { return +1; // push null(s) to end @@ -198,10 +184,6 @@ public static int safeCompare(String s1, String s2, boolean caseSensitive) { } } - public static boolean isSameReference(T o1, T o2) { - return o1 == o2; - } - public static int length(CharSequence cs) { return cs == null ? 0 : cs.length(); } @@ -362,18 +344,6 @@ public static boolean equals(Collection c1, Collection c2) { && c2.containsAll(c1); } - public static int size(Map m) { - return (m == null) ? 0 : m.size(); - } - - public static boolean isEmpty(Map m) { - return size(m) <= 0; - } - - public static boolean isNotEmpty(Map m) { - return !isEmpty(m); - } - @SafeVarargs public static int length(T... a) { return (a == null) ? 0 : a.length; @@ -401,8 +371,7 @@ public static boolean isNotEmpty(Iterator iter) { return !isEmpty(iter); } - @SafeVarargs - public static boolean isEmpty(T... a) { + public static boolean isEmpty(T[] a) { return length(a) <= 0; } @@ -566,25 +535,6 @@ public static NavigableSet mapSort( return stream(values).map(mapper).collect(toSortedSet(comparator)); } - public static NavigableMap toSortedMap( - Iterable values, Function keyMapper, - Function valueMapper, Comparator comparator) { - return stream(values).collect(toSortedMap(keyMapper, valueMapper, comparator)); - } - - public static Collector> toSortedMap( - Function keyMapper, - Function valueMapper, - Comparator comparator) { - return Collectors.toMap(keyMapper, valueMapper, throwingMerger(), () -> new TreeMap<>(comparator)); - } - - public static BinaryOperator throwingMerger() { - return (u, v) -> { - throw new IllegalStateException(String.format("Duplicate key %s", u)); - }; - } - public static Collector> toSortedSet(Comparator comparator) { return Collectors.toCollection(() -> new TreeSet<>(comparator)); } @@ -661,79 +611,6 @@ public static NavigableSet asSortedSet( return set; } - /** - * @param Type of mapped value - * @return A {@link Supplier} that returns a new {@link NavigableMap} whenever its {@code get()} method - * is invoked - */ - @SuppressWarnings("unchecked") - public static Supplier> caseInsensitiveMap() { - return CASE_INSENSITIVE_MAP_FACTORY; - } - - /** - * Flips between keys and values of an input map - * - * @param Original map key type - * @param Original map value type - * @param Flipped map type - * @param map The original map to flip - * @param mapCreator The creator of the target map - * @param allowDuplicates Whether to ignore duplicates on flip - * @return The flipped map result - * @throws IllegalArgumentException if allowDuplicates is {@code false} and a duplicate value found in the - * original map. - */ - public static > M flipMap( - Map map, Supplier mapCreator, boolean allowDuplicates) { - M result = Objects.requireNonNull(mapCreator.get(), "No map created"); - map.forEach((key, value) -> { - K prev = result.put(value, key); - if ((prev != null) && (!allowDuplicates)) { - ValidateUtils.throwIllegalArgumentException("Multiple values for key=%s: current=%s, previous=%s", value, key, - prev); - } - }); - - return result; - } - - @SafeVarargs - public static > M mapValues( - Function keyMapper, Supplier mapCreator, V... values) { - return mapValues(keyMapper, mapCreator, isEmpty(values) ? Collections.emptyList() : Arrays.asList(values)); - } - - /** - * Creates a map out of a group of values - * - * @param The key type - * @param The value type - * @param The result {@link Map} type - * @param keyMapper The {@link Function} that generates a key for a given value. If the returned key is - * {@code null} then the value is not mapped - * @param mapCreator The {@link Supplier} used to create/retrieve the result map - provided non-empty group of - * values - * @param values The values to be mapped - * @return The resulting {@link Map} - Note: no validation is made to ensure that 2 (or more) - * values are not mapped to the same key - */ - public static > M mapValues( - Function keyMapper, - Supplier mapCreator, - Collection values) { - M map = mapCreator.get(); - for (V v : values) { - K k = keyMapper.apply(v); - if (k == null) { - continue; // debug breakpoint - } - map.put(k, v); - } - - return map; - } - @SafeVarargs public static T findFirstMatchingMember(Predicate acceptor, T... values) { return findFirstMatchingMember(acceptor, @@ -816,130 +693,6 @@ public static CharSequence stripDelimiters(CharSequence s, char delim) { } } - public static RuntimeException toRuntimeException(Throwable t) { - return toRuntimeException(t, true); - } - - /** - * Converts a thrown generic exception to a {@link RuntimeException} - * - * @param t The original thrown exception - * @param peelThrowable Whether to determine the root cause by "peeling" any enclosing exceptions - * @return The thrown cause if already a runtime exception, otherwise a runtime exception of the - * resolved exception as its cause - * @see #peelException(Throwable) - */ - public static RuntimeException toRuntimeException(Throwable t, boolean peelThrowable) { - Throwable e = peelThrowable ? peelException(t) : t; - if (e instanceof RuntimeException) { - return (RuntimeException) e; - } - - return new RuntimeException(e); - } - - /** - * Attempts to get to the "effective" exception being thrown, by taking care of some known exceptions that - * wrap the original thrown one. - * - * @param t The original {@link Throwable} - ignored if {@code null} - * @return The effective exception - same as input if not a wrapper - */ - public static Throwable peelException(Throwable t) { - // NOTE: check order is important - e.g., InvocationTargetException extends ReflectiveOperationException - if (t == null) { - return t; - } else if (t instanceof UndeclaredThrowableException) { - Throwable wrapped = ((UndeclaredThrowableException) t).getUndeclaredThrowable(); - // according to the Javadoc it may be null, in which case 'getCause' - // might contain the information we need - if (wrapped != null) { - return peelException(wrapped); - } - - wrapped = t.getCause(); - if (wrapped != t) { // make sure it is a real cause - return peelException(wrapped); - } - } else if (t instanceof InvocationTargetException) { - Throwable target = ((InvocationTargetException) t).getTargetException(); - if (target != null) { - return peelException(target); - } - } else if (t instanceof ReflectionException) { - Throwable target = ((ReflectionException) t).getTargetException(); - if (target != null) { - return peelException(target); - } - } else if (t instanceof ExecutionException) { - Throwable wrapped = resolveExceptionCause(t); - if (wrapped != null) { - return peelException(wrapped); - } - } else if (t instanceof MBeanException) { - Throwable target = ((MBeanException) t).getTargetException(); - if (target != null) { - return peelException(target); - } - } - - return t; // no special handling required or available - } - - /** - * @param t The original {@link Throwable} - ignored if {@code null} - * @return If {@link Throwable#getCause()} is non-{@code null} then the cause, otherwise the original exception - - * {@code null} if the original exception was {@code null} - */ - public static Throwable resolveExceptionCause(Throwable t) { - if (t == null) { - return t; - } - - Throwable c = t.getCause(); - if (c == null) { - return t; - } else { - return c; - } - } - - /** - * Used to "accumulate" exceptions of the same type. If the current exception is {@code null} then - * the new one becomes the current, otherwise the new one is added as a suppressed exception to the current - * one - * - * @param The exception type - * @param current The current exception - * @param extra The extra/new exception - * @return The resolved exception - * @see Throwable#addSuppressed(Throwable) - */ - public static T accumulateException(T current, T extra) { - if (current == null) { - return extra; - } - - if ((extra == null) || (extra == current)) { - return current; - } - - current.addSuppressed(extra); - return current; - } - - public static void rethrowAsIoException(Throwable e) throws IOException { - if (e instanceof IOException) { - throw (IOException) e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else if (e instanceof Error) { - throw (Error) e; - } else { - throw new IOException(e); - } - } - /** * Wraps a value into a {@link Supplier} * diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/MapEntryUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/MapEntryUtils.java index d17b4a473..02583326d 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/MapEntryUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/MapEntryUtils.java @@ -18,6 +18,8 @@ */ package org.apache.sshd.common.util; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.EnumMap; @@ -26,7 +28,11 @@ import java.util.NavigableMap; import java.util.Objects; import java.util.TreeMap; +import java.util.function.BinaryOperator; +import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.Collectors; /** * Represents an un-modifiable pair of values @@ -41,6 +47,9 @@ public final class MapEntryUtils { return k1.compareTo(k2); }; + @SuppressWarnings("rawtypes") + private static final Supplier CASE_INSENSITIVE_MAP_FACTORY = () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + private MapEntryUtils() { throw new UnsupportedOperationException("No instance"); } @@ -218,4 +227,108 @@ public static , V> EnumMapBuilder builder(Class keyTy return new EnumMapBuilder<>(keyType); } } + + public static int size(Map m) { + return (m == null) ? 0 : m.size(); + } + + public static boolean isEmpty(Map m) { + return size(m) <= 0; + } + + public static boolean isNotEmpty(Map m) { + return !isEmpty(m); + } + + /** + * @param Type of mapped value + * @return A {@link Supplier} that returns a new {@link NavigableMap} whenever its {@code get()} method + * is invoked + */ + @SuppressWarnings("unchecked") + public static Supplier> caseInsensitiveMap() { + return CASE_INSENSITIVE_MAP_FACTORY; + } + + /** + * Flips between keys and values of an input map + * + * @param Original map key type + * @param Original map value type + * @param Flipped map type + * @param map The original map to flip + * @param mapCreator The creator of the target map + * @param allowDuplicates Whether to ignore duplicates on flip + * @return The flipped map result + * @throws IllegalArgumentException if allowDuplicates is {@code false} and a duplicate value found in the + * original map. + */ + public static > M flipMap( + Map map, Supplier mapCreator, boolean allowDuplicates) { + M result = Objects.requireNonNull(mapCreator.get(), "No map created"); + map.forEach((key, value) -> { + K prev = result.put(value, key); + if ((prev != null) && (!allowDuplicates)) { + ValidateUtils.throwIllegalArgumentException("Multiple values for key=%s: current=%s, previous=%s", value, key, + prev); + } + }); + + return result; + } + + @SafeVarargs + public static > M mapValues( + Function keyMapper, Supplier mapCreator, V... values) { + return mapValues(keyMapper, mapCreator, GenericUtils.isEmpty(values) ? Collections.emptyList() : Arrays.asList(values)); + } + + /** + * Creates a map out of a group of values + * + * @param The key type + * @param The value type + * @param The result {@link Map} type + * @param keyMapper The {@link Function} that generates a key for a given value. If the returned key is + * {@code null} then the value is not mapped + * @param mapCreator The {@link Supplier} used to create/retrieve the result map - provided non-empty group of + * values + * @param values The values to be mapped + * @return The resulting {@link Map} - Note: no validation is made to ensure that 2 (or more) + * values are not mapped to the same key + */ + public static > M mapValues( + Function keyMapper, + Supplier mapCreator, + Collection values) { + M map = mapCreator.get(); + for (V v : values) { + K k = keyMapper.apply(v); + if (k == null) { + continue; // debug breakpoint + } + map.put(k, v); + } + + return map; + } + + public static NavigableMap toSortedMap( + Iterable values, Function keyMapper, + Function valueMapper, Comparator comparator) { + return GenericUtils.stream(values).collect(toSortedMap(keyMapper, valueMapper, comparator)); + } + + public static Collector> toSortedMap( + Function keyMapper, + Function valueMapper, + Comparator comparator) { + return Collectors.toMap(keyMapper, valueMapper, throwingMerger(), () -> new TreeMap<>(comparator)); + } + + public static BinaryOperator throwingMerger() { + return (u, v) -> { + throw new IllegalStateException(String.format("Duplicate key %s", u)); + }; + } } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java index 35f46d942..5b3cb3899 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/ValidateUtils.java @@ -71,7 +71,7 @@ public static String checkNotNullAndNotEmpty(String t, String message, Object... public static > M checkNotNullAndNotEmpty(M t, String message, Object... args) { t = checkNotNull(t, message, args); - checkTrue(GenericUtils.size(t) > 0, message, args); + checkTrue(MapEntryUtils.size(t) > 0, message, args); return t; } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkECBufferPublicKeyParser.java b/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkECBufferPublicKeyParser.java index 9d1dbeecb..682b1ef72 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkECBufferPublicKeyParser.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkECBufferPublicKeyParser.java @@ -24,7 +24,7 @@ import org.apache.sshd.common.cipher.ECCurves; import org.apache.sshd.common.config.keys.impl.SkECDSAPublicKeyEntryDecoder; -import org.apache.sshd.common.u2f.SkEcdsaPublicKey; +import org.apache.sshd.common.config.keys.u2f.SkEcdsaPublicKey; import org.apache.sshd.common.util.buffer.Buffer; /** diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkED25519BufferPublicKeyParser.java b/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkED25519BufferPublicKeyParser.java index 5a58f3d28..c905e7727 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkED25519BufferPublicKeyParser.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/buffer/keys/SkED25519BufferPublicKeyParser.java @@ -24,8 +24,8 @@ import net.i2p.crypto.eddsa.EdDSAPublicKey; import org.apache.sshd.common.config.keys.impl.SkED25519PublicKeyEntryDecoder; +import org.apache.sshd.common.config.keys.u2f.SkED25519PublicKey; import org.apache.sshd.common.keyprovider.KeyPairProvider; -import org.apache.sshd.common.u2f.SkED25519PublicKey; import org.apache.sshd.common.util.buffer.Buffer; /** diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/closeable/AutoCloseableDelegateInvocationHandler.java b/sshd-common/src/main/java/org/apache/sshd/common/util/closeable/AutoCloseableDelegateInvocationHandler.java index e6914d57b..1d3303dae 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/closeable/AutoCloseableDelegateInvocationHandler.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/closeable/AutoCloseableDelegateInvocationHandler.java @@ -24,6 +24,7 @@ import java.lang.reflect.Modifier; import java.util.Objects; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ProxyUtils; import org.apache.sshd.common.util.logging.LoggingUtils; @@ -85,7 +86,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl Logger log = LoggerFactory.getLogger(closerType); LoggingUtils.debug(log, "invoke({}#{}) failed ({}) to execute: {}", closerType.getSimpleName(), method.getName(), t.getClass().getSimpleName(), t.getMessage(), t); - err = GenericUtils.accumulateException(err, t); + err = ExceptionUtils.accumulateException(err, t); } } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/Int2IntFunction.java b/sshd-common/src/main/java/org/apache/sshd/common/util/functors/Int2IntFunction.java similarity index 95% rename from sshd-common/src/main/java/org/apache/sshd/common/util/Int2IntFunction.java rename to sshd-common/src/main/java/org/apache/sshd/common/util/functors/Int2IntFunction.java index 490abb007..64b202274 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/Int2IntFunction.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/functors/Int2IntFunction.java @@ -17,10 +17,12 @@ * under the License. */ -package org.apache.sshd.common.util; +package org.apache.sshd.common.util.functors; import java.util.function.IntUnaryOperator; +import org.apache.sshd.common.util.ValidateUtils; + /** * @author Apache MINA SSHD Project */ diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/functors/UnaryEquator.java b/sshd-common/src/main/java/org/apache/sshd/common/util/functors/UnaryEquator.java index 4cfb6f266..a073d2c51 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/functors/UnaryEquator.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/functors/UnaryEquator.java @@ -23,11 +23,9 @@ import java.util.Objects; import java.util.function.BiPredicate; -import org.apache.sshd.common.util.GenericUtils; - /** * Checks equality between 2 entities of same type - * + * * @param Type of compared entity * @author Apache MINA SSHD Project */ @@ -67,6 +65,10 @@ default UnaryEquator negate() { return (t1, t2) -> !this.test(t1, t2); } + static boolean isSameReference(T o1, T o2) { + return o1 == o2; + } + /** * @param Type of entity * @return The default equality checker @@ -79,10 +81,10 @@ static UnaryEquator defaultEquality() { /** * @param Type of entity * @return An equator that checks reference equality - * @see GenericUtils#isSameReference(Object, Object) + * @see UnaryEquator#isSameReference(Object, Object) */ static UnaryEquator referenceEquality() { - return GenericUtils::isSameReference; + return UnaryEquator::isSameReference; } /** diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/IoUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/IoUtils.java index f969a6242..f1e394dae 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/io/IoUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/IoUtils.java @@ -49,6 +49,7 @@ import java.util.Objects; import java.util.Set; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.OsUtils; @@ -190,7 +191,7 @@ public static IOException closeQuietly(Collection closeable c.close(); } } catch (IOException e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/PathUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/PathUtils.java index 30bfd88d7..52fec2318 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/io/PathUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/PathUtils.java @@ -61,7 +61,7 @@ private PathUtils() { * non-{@code null}-s */ public static int safeCompareFilename(Path p1, Path p2, boolean caseSensitive) { - if (GenericUtils.isSameReference(p1, p2)) { + if (UnaryEquator.isSameReference(p1, p2)) { return 0; } else if (p1 == null) { return 1; diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/Invoker.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/functors/Invoker.java similarity index 95% rename from sshd-common/src/main/java/org/apache/sshd/common/util/Invoker.java rename to sshd-common/src/main/java/org/apache/sshd/common/util/io/functors/Invoker.java index 270c3c822..cf9f0baa2 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/Invoker.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/functors/Invoker.java @@ -16,12 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sshd.common.util; +package org.apache.sshd.common.util.io.functors; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Collection; import java.util.Map; +import org.apache.sshd.common.util.ExceptionUtils; +import org.apache.sshd.common.util.GenericUtils; + /** * The complement to the {@code Callable} interface - accepts one argument and possibly throws something * @@ -76,7 +79,7 @@ static void invokeAll( try { i.invoke(arg); } catch (Throwable t) { - err = GenericUtils.accumulateException(err, t); + err = ExceptionUtils.accumulateException(err, t); } } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/net/SshdSocketAddress.java b/sshd-common/src/main/java/org/apache/sshd/common/util/net/SshdSocketAddress.java index 701e76184..9078570d5 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/net/SshdSocketAddress.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/net/SshdSocketAddress.java @@ -36,6 +36,7 @@ import java.util.Set; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.NumberUtils; import org.apache.sshd.common.util.ValidateUtils; @@ -704,7 +705,7 @@ public static V removeByOptionalWildcardAddress(Map Map.Entry findMatchingOptionalWildcardEntry( Map map, SshdSocketAddress address) { - if (GenericUtils.isEmpty(map) || (address == null)) { + if (MapEntryUtils.isEmpty(map) || (address == null)) { return null; } diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java index e42578320..7ee9f9b24 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityEntityFactory.java @@ -24,7 +24,7 @@ import java.security.Provider; import java.util.Objects; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.ValidateUtils; /** @@ -90,7 +90,7 @@ public F getInstance(String algorithm) throws GeneralSecurityException { Object value = m.invoke(null, algorithm); return entityType.cast(value); } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); if (e instanceof GeneralSecurityException) { throw (GeneralSecurityException) e; } else if (e instanceof RuntimeException) { @@ -130,7 +130,7 @@ public F getInstance(String algorithm) throws GeneralSecurityException { Object value = m.invoke(null, algorithm, name); return entityType.cast(value); } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); if (e instanceof GeneralSecurityException) { throw (GeneralSecurityException) e; } else if (e instanceof RuntimeException) { @@ -171,7 +171,7 @@ public F getInstance(String algorithm) throws GeneralSecurityException { Object value = m.invoke(null, algorithm, provider); return entityType.cast(value); } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); if (e instanceof GeneralSecurityException) { throw (GeneralSecurityException) e; } else if (e instanceof RuntimeException) { diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java index d26a1d1e8..7acb34fb7 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java @@ -69,6 +69,7 @@ import org.apache.sshd.common.random.JceRandomFactory; import org.apache.sshd.common.random.RandomFactory; import org.apache.sshd.common.session.SessionContext; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; @@ -429,7 +430,7 @@ private static void register() { r = ThreadUtils.createDefaultInstance(SecurityUtils.class, SecurityProviderRegistrar.class, registrarClass); } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); logger.error("Failed ({}) to create default {} registrar instance: {}", e.getClass().getSimpleName(), registrarClass, e.getMessage()); if (e instanceof RuntimeException) { @@ -724,7 +725,7 @@ public static SecurityEntityFactory createSecurityEntityFactory( try { return SecurityEntityFactory.toFactory(entityType, registrar, getDefaultProviderChoice()); } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); if (e instanceof RuntimeException) { throw (RuntimeException) e; } else if (e instanceof Error) { diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java index ede8ebfec..7d36f22c4 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/bouncycastle/BouncyCastleSecurityProviderRegistrar.java @@ -25,6 +25,7 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ReflectionUtils; import org.apache.sshd.common.util.security.AbstractSecurityProviderRegistrar; @@ -60,7 +61,7 @@ public Provider getSecurityProvider() { try { return getOrCreateProvider(PROVIDER_CLASS); } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); log.error("getSecurityProvider({}) failed ({}) to instantiate {}: {}", getName(), e.getClass().getSimpleName(), PROVIDER_CLASS, e.getMessage()); if (e instanceof RuntimeException) { diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java index 431a04c11..8154b7213 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/security/eddsa/EdDSASecurityProviderRegistrar.java @@ -25,7 +25,7 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.ReflectionUtils; import org.apache.sshd.common.util.security.AbstractSecurityProviderRegistrar; import org.apache.sshd.common.util.security.SecurityUtils; @@ -58,7 +58,7 @@ public Provider getSecurityProvider() { try { return getOrCreateProvider(PROVIDER_CLASS); } catch (ReflectiveOperationException t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); log.error("getSecurityProvider({}) failed ({}) to instantiate {}: {}", getName(), e.getClass().getSimpleName(), PROVIDER_CLASS, e.getMessage()); if (e instanceof RuntimeException) { diff --git a/sshd-common/src/main/java/org/apache/sshd/server/Signal.java b/sshd-common/src/main/java/org/apache/sshd/server/Signal.java index c248576f2..d8418ca9e 100644 --- a/sshd-common/src/main/java/org/apache/sshd/server/Signal.java +++ b/sshd-common/src/main/java/org/apache/sshd/server/Signal.java @@ -26,6 +26,7 @@ import java.util.function.Function; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; /** * System signals definition that the shell can receive. @@ -69,20 +70,20 @@ public enum Signal { /** * An un-modifiable case-insensitive {@link NavigableMap} of the names of all available {@link Signal}s - * + * * @see #SIGNALS */ public static final NavigableMap NAME_LOOKUP_TABLE = Collections.unmodifiableNavigableMap( - GenericUtils.toSortedMap(SIGNALS, Signal::name, Function.identity(), String.CASE_INSENSITIVE_ORDER)); + MapEntryUtils.toSortedMap(SIGNALS, Signal::name, Function.identity(), String.CASE_INSENSITIVE_ORDER)); /** * An un-modifiable {@link NavigableMap} of the numeric values of all available {@link Signal}s - * + * * @see #SIGNALS * @see #getNumeric() */ public static final NavigableMap NUMERIC_LOOKUP_TABLE = Collections.unmodifiableNavigableMap( - GenericUtils.toSortedMap(SIGNALS, Signal::getNumeric, Function.identity(), Comparator.naturalOrder())); + MapEntryUtils.toSortedMap(SIGNALS, Signal::getNumeric, Function.identity(), Comparator.naturalOrder())); private final int numeric; diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryTest.java index df9804c73..1dc9fcef2 100644 --- a/sshd-common/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/client/config/hosts/HostConfigEntryTest.java @@ -28,6 +28,7 @@ import java.util.regex.Pattern; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.util.test.JUnitTestSupport; import org.apache.sshd.util.test.NoIoTestCase; import org.junit.FixMethodOrder; @@ -261,7 +262,7 @@ public void testReadGlobalHostsConfigEntries() throws IOException { assertTrue("No target port for " + entry, entry.getPort() > 0); assertFalse("No username for " + entry, GenericUtils.isEmpty(entry.getUsername())); assertFalse("No identities for " + entry, GenericUtils.isEmpty(entry.getIdentities())); - assertFalse("No properties for " + entry, GenericUtils.isEmpty(entry.getProperties())); + assertFalse("No properties for " + entry, MapEntryUtils.isEmpty(entry.getProperties())); } } @@ -327,7 +328,7 @@ private static > C validateHostConfigEntri for (HostConfigEntry entry : entries) { assertFalse("No pattern for " + entry, GenericUtils.isEmpty(entry.getHost())); - assertFalse("No extra properties for " + entry, GenericUtils.isEmpty(entry.getProperties())); + assertFalse("No extra properties for " + entry, MapEntryUtils.isEmpty(entry.getProperties())); } return entries; diff --git a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java index 9d4e0d6bb..260afb73c 100644 --- a/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/client/config/keys/ClientIdentityTest.java @@ -32,6 +32,7 @@ import org.apache.sshd.common.config.keys.IdentityUtils; import org.apache.sshd.common.keyprovider.KeyIdentityProvider; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.io.IoUtils; import org.apache.sshd.util.test.JUnitTestSupport; import org.apache.sshd.util.test.NoIoTestCase; @@ -76,7 +77,7 @@ public void testLoadClientIdentities() throws Exception { false, // don't be strict null, // none of the files is password protected options); - assertEquals("Mismatched loaded ids count", GenericUtils.size(expected), GenericUtils.size(ids)); + assertEquals("Mismatched loaded ids count", GenericUtils.size(expected), MapEntryUtils.size(ids)); Collection pairs = new ArrayList<>(ids.size()); for (BuiltinIdentities type : BuiltinIdentities.VALUES) { diff --git a/sshd-common/src/test/java/org/apache/sshd/common/VersionPropertiesTest.java b/sshd-common/src/test/java/org/apache/sshd/common/VersionPropertiesTest.java index 2d17a1db3..e49b36250 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/VersionPropertiesTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/VersionPropertiesTest.java @@ -23,6 +23,7 @@ import org.apache.sshd.common.config.VersionProperties; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.util.test.JUnitTestSupport; import org.apache.sshd.util.test.NoIoTestCase; import org.junit.FixMethodOrder; @@ -43,7 +44,7 @@ public VersionPropertiesTest() { @Test public void testNonEmptyProperties() { Map props = VersionProperties.getVersionProperties(); - assertTrue(GenericUtils.isNotEmpty(props)); + assertTrue(MapEntryUtils.isNotEmpty(props)); } @Test diff --git a/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java index 69ae5e87f..3eb7fd21a 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java @@ -23,7 +23,7 @@ import java.util.Map; import java.util.Set; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.util.test.JUnitTestSupport; import org.apache.sshd.util.test.NoIoTestCase; import org.junit.FixMethodOrder; @@ -50,7 +50,7 @@ public void testOpcodeExtractorOnNull() { public void testEnabledOptions() { Set expected = EnumSet.of(PtyMode.ECHO, PtyMode.CS8, PtyMode.ICANON); Map modes = PtyMode.createEnabledOptions(expected); - assertEquals("Mismatched modes size", expected.size(), GenericUtils.size(modes)); + assertEquals("Mismatched modes size", expected.size(), MapEntryUtils.size(modes)); for (PtyMode m : expected) { assertSame("Mismatched setting for " + m, PtyMode.TRUE_SETTING, modes.get(m)); diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java index b59299a9c..b5aeb9530 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/BuiltinIdentitiesTest.java @@ -29,6 +29,7 @@ import java.util.List; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.functors.UnaryEquator; import org.apache.sshd.common.util.security.SecurityUtils; import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory; import org.apache.sshd.util.test.JUnitTestSupport; @@ -126,7 +127,7 @@ public void testNonEmptySupportedKeyTypeNames() { public void testNoOverlappingKeyTypeNamesWithOtherIdentities() { Collection current = expected.getSupportedKeyTypes(); for (BuiltinIdentities identity : BuiltinIdentities.VALUES) { - if (GenericUtils.isSameReference(expected, identity)) { + if (UnaryEquator.isSameReference(expected, identity)) { continue; } diff --git a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java index 8e62fa0b0..18d534b58 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/keyprovider/KeyPairProviderTest.java @@ -29,6 +29,7 @@ import java.util.function.Function; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.util.test.JUnitTestSupport; import org.apache.sshd.util.test.NoIoTestCase; import org.junit.FixMethodOrder; @@ -63,7 +64,7 @@ public void testMapToKeyPairProvider() throws IOException, GeneralSecurityExcept PublicKey pubKey = Mockito.mock(PublicKey.class); PrivateKey prvKey = Mockito.mock(PrivateKey.class); String[] testKeys = { getCurrentTestName(), getClass().getSimpleName() }; - Map pairsMap = GenericUtils.toSortedMap( + Map pairsMap = MapEntryUtils.toSortedMap( Arrays.asList(testKeys), Function.identity(), k -> new KeyPair(pubKey, prvKey), diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java index f8bb6aea3..ce64af197 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java @@ -131,11 +131,11 @@ public void testStripDelimitersOnlyIfOnBothEnds() { @Test public void testAccumulateExceptionOnNullValues() { - assertNull("Unexpected null/null result", GenericUtils.accumulateException(null, null)); + assertNull("Unexpected null/null result", ExceptionUtils.accumulateException(null, null)); Throwable expected = new NoSuchMethodException(getClass().getName() + "#" + getCurrentTestName()); - assertSame("Mismatched null/extra result", expected, GenericUtils.accumulateException(null, expected)); - assertSame("Mismatched current/null result", expected, GenericUtils.accumulateException(expected, null)); + assertSame("Mismatched null/extra result", expected, ExceptionUtils.accumulateException(null, expected)); + assertSame("Mismatched current/null result", expected, ExceptionUtils.accumulateException(expected, null)); } @Test @@ -147,7 +147,7 @@ public void testAccumulateExceptionOnExistingCurrent() { }; RuntimeException current = new UnsupportedOperationException("top"); for (RuntimeException extra : expected) { - RuntimeException actual = GenericUtils.accumulateException(current, extra); + RuntimeException actual = ExceptionUtils.accumulateException(current, extra); assertSame("Mismatched returned actual exception", current, actual); } diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/Int2IntFunctionTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/Int2IntFunctionTest.java index b0c48ca90..b6238e0b9 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/util/Int2IntFunctionTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/util/Int2IntFunctionTest.java @@ -22,6 +22,7 @@ import java.util.Random; import java.util.function.IntUnaryOperator; +import org.apache.sshd.common.util.functors.Int2IntFunction; import org.apache.sshd.util.test.JUnitTestSupport; import org.apache.sshd.util.test.NoIoTestCase; import org.junit.FixMethodOrder; diff --git a/sshd-common/src/test/java/org/apache/sshd/util/test/JUnitTestSupport.java b/sshd-common/src/test/java/org/apache/sshd/util/test/JUnitTestSupport.java index ff3a329f9..3a0bf0ea3 100644 --- a/sshd-common/src/test/java/org/apache/sshd/util/test/JUnitTestSupport.java +++ b/sshd-common/src/test/java/org/apache/sshd/util/test/JUnitTestSupport.java @@ -57,6 +57,7 @@ import org.apache.sshd.common.config.keys.KeyUtils; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.io.IoUtils; import org.apache.sshd.common.util.logging.LoggingUtils; import org.junit.Assert; @@ -428,8 +429,8 @@ public static void assertMapEquals( public static void assertMapEquals( String message, Map expected, Map actual, BiPredicate equator) { - int numItems = GenericUtils.size(expected); - assertEquals(message + "[size]", numItems, GenericUtils.size(actual)); + int numItems = MapEntryUtils.size(expected); + assertEquals(message + "[size]", numItems, MapEntryUtils.size(actual)); if (numItems > 0) { expected.forEach((key, expValue) -> { diff --git a/sshd-contrib/src/main/java/org/apache/sshd/contrib/client/auth/password/InteractivePasswordIdentityProvider.java b/sshd-contrib/src/main/java/org/apache/sshd/contrib/client/auth/password/InteractivePasswordIdentityProvider.java index 4f0846fe5..769d65698 100644 --- a/sshd-contrib/src/main/java/org/apache/sshd/contrib/client/auth/password/InteractivePasswordIdentityProvider.java +++ b/sshd-contrib/src/main/java/org/apache/sshd/contrib/client/auth/password/InteractivePasswordIdentityProvider.java @@ -29,6 +29,7 @@ import org.apache.sshd.client.session.ClientSessionHolder; import org.apache.sshd.common.session.SessionHolder; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.functors.UnaryEquator; /** *

    @@ -110,7 +111,7 @@ public boolean hasNext() { nextPassword.set(password); } - return !GenericUtils.isSameReference(password, EOF); + return !UnaryEquator.isSameReference(password, EOF); } @Override @@ -120,7 +121,7 @@ public String next() { throw new IllegalStateException("hasNext() not called before next()"); } - if (GenericUtils.isSameReference(password, EOF)) { + if (UnaryEquator.isSameReference(password, EOF)) { throw new NoSuchElementException("All passwords exhausted"); } diff --git a/sshd-contrib/src/main/java/org/apache/sshd/contrib/common/compression/DeflatingInputStream.java b/sshd-contrib/src/main/java/org/apache/sshd/contrib/common/compression/DeflatingInputStream.java index 9f80d2324..ff4cd5e5d 100644 --- a/sshd-contrib/src/main/java/org/apache/sshd/contrib/common/compression/DeflatingInputStream.java +++ b/sshd-contrib/src/main/java/org/apache/sshd/contrib/common/compression/DeflatingInputStream.java @@ -25,7 +25,7 @@ import java.io.StreamCorruptedException; import java.util.Objects; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.io.IoUtils; import org.apache.sshd.contrib.common.util.io.ExposedBufferByteArrayOutputStream; @@ -159,25 +159,25 @@ public void close() throws IOException { try { compressor.close(); } catch (IOException e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } try { baos.close(); } catch (IOException e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } try { inputStream.close(); } catch (IOException e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } try { super.close(); } catch (IOException e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } if (err != null) { diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java index 60bf0bd2d..a91b1a271 100644 --- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java +++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java @@ -33,7 +33,7 @@ import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.channel.ChannelOutputStream; import org.apache.sshd.common.session.Session; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; @@ -69,7 +69,7 @@ protected OpenFuture doInit(Buffer buffer) { signalChannelOpenSuccess(); f.setOpened(); } catch (Throwable t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); changeEvent = e.getClass().getSimpleName(); signalChannelOpenFailure(e); f.setException(e); diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java index bbafa7b43..181ae864b 100644 --- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java +++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java @@ -30,6 +30,7 @@ import org.apache.sshd.common.Closeable; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.channel.ChannelOutputStream; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; @@ -100,7 +101,7 @@ protected OpenFuture doInit(Buffer buffer) { signalChannelOpenSuccess(); f.setOpened(); } catch (Throwable t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); signalChannelOpenFailure(e); f.setException(e); } diff --git a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java index e4cde28a8..d5fa90605 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/SshClient.java @@ -87,8 +87,10 @@ import org.apache.sshd.common.keyprovider.KeyIdentityProvider; import org.apache.sshd.common.keyprovider.KeyPairProvider; import org.apache.sshd.common.session.helpers.AbstractSession; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; +import org.apache.sshd.common.util.functors.UnaryEquator; import org.apache.sshd.common.util.io.resource.PathResource; import org.apache.sshd.common.util.net.SshdSocketAddress; import org.apache.sshd.core.CoreModuleProperties; @@ -755,7 +757,7 @@ protected void setupDefaultSessionIdentities( // check if session listener intervened KeyIdentityProvider kpSession = session.getKeyIdentityProvider(); KeyIdentityProvider kpClient = getKeyIdentityProvider(); - if (GenericUtils.isSameReference(kpSession, kpClient)) { + if (UnaryEquator.isSameReference(kpSession, kpClient)) { if (debugEnabled) { log.debug("setupDefaultSessionIdentities({}) key identity provider override in session listener", session); } @@ -763,7 +765,7 @@ protected void setupDefaultSessionIdentities( // Prefer the extra identities to come first since they were probably indicate by the host-config entry KeyIdentityProvider kpEffective = KeyIdentityProvider.resolveKeyIdentityProvider(extraIdentities, kpSession); - if (!GenericUtils.isSameReference(kpSession, kpEffective)) { + if (!UnaryEquator.isSameReference(kpSession, kpEffective)) { if (debugEnabled) { log.debug("setupDefaultSessionIdentities({}) key identity provider enhanced", session); } @@ -772,7 +774,7 @@ protected void setupDefaultSessionIdentities( PasswordIdentityProvider passSession = session.getPasswordIdentityProvider(); PasswordIdentityProvider passClient = getPasswordIdentityProvider(); - if (!GenericUtils.isSameReference(passSession, passClient)) { + if (!UnaryEquator.isSameReference(passSession, passClient)) { if (debugEnabled) { log.debug("setupDefaultSessionIdentities({}) password provider override", session); } @@ -853,13 +855,13 @@ public void close() throws IOException { try { client.close(); } catch (Exception e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } try { client.stop(); } catch (Exception e) { - err = GenericUtils.accumulateException(err, e); + err = ExceptionUtils.accumulateException(err, e); } if (err != null) { diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java index c82c404b0..d960388ce 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java @@ -49,7 +49,7 @@ import org.apache.sshd.common.io.IoOutputStream; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.EventNotifier; -import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ExceptionUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; @@ -359,7 +359,7 @@ public void handleOpenSuccess(int recipient, long rwSize, long packetSize, Buffe this.opened.set(true); this.openFuture.setOpened(); } catch (Throwable t) { - Throwable e = GenericUtils.peelException(t); + Throwable e = ExceptionUtils.peelException(t); changeEvent = e.getClass().getName(); signalChannelOpenFailure(e); this.openFuture.setException(e); diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java index 4a70dc467..88f8f03ca 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/PtyCapableChannelSession.java @@ -31,6 +31,7 @@ import org.apache.sshd.common.channel.PtyMode; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.MapEntryUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; @@ -45,7 +46,7 @@ *

    * A typical code snippet would be: *

    - * + * *
      * 
      * try (client = SshClient.setUpDefaultClient()) {
    @@ -93,7 +94,7 @@ public PtyCapableChannelSession(
             this.config = PtyChannelConfigurationMutator.copyConfiguration(
                     configHolder, new PtyChannelConfiguration());
             this.config.setPtyType(resolvePtyType(this.config));
    -        if (GenericUtils.isNotEmpty(env)) {
    +        if (MapEntryUtils.isNotEmpty(env)) {
                 for (Map.Entry ee : env.entrySet()) {
                     setEnv(ee.getKey(), ee.getValue());
                 }
    @@ -275,7 +276,7 @@ protected void doOpenPty() throws IOException {
                 buffer.putInt(getPtyWidth());
     
                 Map ptyModes = getPtyModes();
    -            int numModes = GenericUtils.size(ptyModes);
    +            int numModes = MapEntryUtils.size(ptyModes);
                 Buffer modes = new ByteArrayBuffer(numModes * (1 + Integer.BYTES) + Long.SIZE, false);
                 if (numModes > 0) {
                     ptyModes.forEach((mode, value) -> {
    @@ -288,7 +289,7 @@ protected void doOpenPty() throws IOException {
                 writePacket(buffer);
             }
     
    -        if (GenericUtils.size(env) > 0) {
    +        if (MapEntryUtils.size(env) > 0) {
                 if (debugEnabled) {
                     log.debug("doOpenPty({}) Send SSH_MSG_CHANNEL_REQUEST env: {}", this, env);
                 }
    diff --git a/sshd-core/src/main/java/org/apache/sshd/client/config/SshClientConfigFileReader.java b/sshd-core/src/main/java/org/apache/sshd/client/config/SshClientConfigFileReader.java
    index 742cda469..24878ea92 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/client/config/SshClientConfigFileReader.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/client/config/SshClientConfigFileReader.java
    @@ -30,6 +30,7 @@
     import org.apache.sshd.common.config.SshConfigFileReader;
     import org.apache.sshd.common.session.SessionHeartbeatController.HeartbeatType;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.core.CoreModuleProperties;
     
     /**
    @@ -79,7 +80,7 @@ public static  C setupClientHeartbeat(C client, PropertyRes
         }
     
         public static  C setupClientHeartbeat(C client, Map options) {
    -        if ((client == null) || GenericUtils.isEmpty(options)) {
    +        if ((client == null) || MapEntryUtils.isEmpty(options)) {
                 return client;
             }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
    index b81ac20b7..c40ca7f6f 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/client/session/AbstractClientSession.java
    @@ -71,6 +71,7 @@
     import org.apache.sshd.common.session.SessionDisconnectHandler;
     import org.apache.sshd.common.session.helpers.AbstractConnectionService;
     import org.apache.sshd.common.session.helpers.AbstractSession;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
    @@ -689,7 +690,7 @@ public KeyExchangeFuture switchToNoneCipher() throws IOException {
                             setKexSeed(seed);
                         }
                     } catch (Exception e) {
    -                    GenericUtils.rethrowAsIoException(e);
    +                    ExceptionUtils.rethrowAsIoException(e);
                     }
                 }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java b/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java
    index e32bf2818..dd0813024 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/client/simple/AbstractSimpleClientSessionCreator.java
    @@ -31,7 +31,7 @@
     import org.apache.sshd.client.session.ClientSession;
     import org.apache.sshd.client.session.ClientSessionCreator;
     import org.apache.sshd.common.AttributeRepository;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     
     /**
    @@ -120,13 +120,13 @@ protected ClientSession authSession(ClientSession clientSession) throws IOExcept
                 auth.verify(getAuthenticationTimeout());
                 session = null; // disable auto-close
             } catch (IOException e) {
    -            err = GenericUtils.accumulateException(err, e);
    +            err = ExceptionUtils.accumulateException(err, e);
             } finally {
                 if (session != null) {
                     try {
                         session.close();
                     } catch (IOException e) {
    -                    err = GenericUtils.accumulateException(err, e);
    +                    err = ExceptionUtils.accumulateException(err, e);
                     }
                 }
             }
    diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
    index f888d74c6..01238f7ce 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
    @@ -51,15 +51,16 @@
     import org.apache.sshd.common.session.ConnectionService;
     import org.apache.sshd.common.session.Session;
     import org.apache.sshd.common.util.EventListenerUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
    -import org.apache.sshd.common.util.Int2IntFunction;
    -import org.apache.sshd.common.util.Invoker;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.buffer.BufferUtils;
     import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
     import org.apache.sshd.common.util.closeable.IoBaseCloseable;
    +import org.apache.sshd.common.util.functors.Int2IntFunction;
     import org.apache.sshd.common.util.io.IoUtils;
    +import org.apache.sshd.common.util.io.functors.Invoker;
     import org.apache.sshd.common.util.threads.CloseableExecutorService;
     import org.apache.sshd.common.util.threads.ExecutorServiceCarrier;
     import org.apache.sshd.core.CoreModuleProperties;
    @@ -381,7 +382,7 @@ protected void signalChannelInitialized() throws IOException {
     
                 notifyStateChanged("init");
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 if (e instanceof IOException) {
                     throw (IOException) e;
                 } else if (e instanceof RuntimeException) {
    @@ -455,7 +456,7 @@ protected void signalChannelOpenFailure(Throwable reason) {
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable ignored = GenericUtils.peelException(err);
    +            Throwable ignored = ExceptionUtils.peelException(err);
                 debug("signalChannelOpenFailure({}) failed ({}) to inform listener of open failure={}: {}", this,
                         ignored.getClass().getSimpleName(), reason.getClass().getSimpleName(), ignored.getMessage(),
                         ignored);
    @@ -477,7 +478,7 @@ protected void notifyStateChanged(String hint) {
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("notifyStateChanged({})[{}] {} while signal channel state change: {}", this, hint,
                         e.getClass().getSimpleName(), e.getMessage(), e);
             } finally {
    @@ -726,7 +727,7 @@ public void signalChannelClosed(Throwable reason) {
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("signalChannelClosed({}) {} while signal channel closed: {}", this, e.getClass().getSimpleName(),
                         e.getMessage(), e);
             } finally {
    @@ -757,7 +758,7 @@ protected void invokeChannelSignaller(Invoker invoker) th
                 try {
                     invoker.invoke(l);
                 } catch (Throwable t) {
    -                err = GenericUtils.accumulateException(err, t);
    +                err = ExceptionUtils.accumulateException(err, t);
                 }
             }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java
    index e8b81d8b2..477852e67 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/BufferedIoOutputStream.java
    @@ -34,10 +34,10 @@
     import org.apache.sshd.common.future.SshFutureListener;
     import org.apache.sshd.common.io.IoOutputStream;
     import org.apache.sshd.common.io.IoWriteFuture;
    -import org.apache.sshd.common.util.GenericUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
    +import org.apache.sshd.common.util.functors.UnaryEquator;
     import org.apache.sshd.core.CoreModuleProperties;
     
     /**
    @@ -167,7 +167,7 @@ protected void startWriting() throws IOException {
                 IoWriteFutureImpl currentFuture = currentWrite.getAndSet(null);
                 for (IoWriteFutureImpl pendingWrite : writes) {
                     // Checking reference by design
    -                if (GenericUtils.isSameReference(pendingWrite, currentFuture)) {
    +                if (UnaryEquator.isSameReference(pendingWrite, currentFuture)) {
                         continue;   // will be taken care of when its listener is eventually called
                     }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwarder.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwarder.java
    index c1d24f1df..1c25ec184 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwarder.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwarder.java
    @@ -58,13 +58,14 @@
     import org.apache.sshd.common.session.Session;
     import org.apache.sshd.common.session.SessionHolder;
     import org.apache.sshd.common.util.EventListenerUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
    -import org.apache.sshd.common.util.Invoker;
     import org.apache.sshd.common.util.Readable;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
     import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
    +import org.apache.sshd.common.util.io.functors.Invoker;
     import org.apache.sshd.common.util.net.SshdSocketAddress;
     import org.apache.sshd.core.CoreModuleProperties;
     import org.apache.sshd.server.forward.TcpForwardingFilter;
    @@ -874,15 +875,15 @@ protected void invokePortEventListenerSignaller(InvokerNote: experimental - used for development purposes and as an example
    - * 
    + *
      * @author Apache MINA SSHD Project
      */
     public class DefaultClientKexExtensionHandler extends AbstractLoggingBean implements KexExtensionHandler {
    @@ -91,7 +93,7 @@ public boolean isKexExtensionsAvailable(Session session, AvailabilityPhase phase
             // Check if client already sent its proposal - if not, we can still influence it
             Map clientProposal = session.getAttribute(CLIENT_PROPOSAL_KEY);
             Map serverProposal = session.getAttribute(SERVER_PROPOSAL_KEY);
    -        if (GenericUtils.isNotEmpty(clientProposal)) {
    +        if (MapEntryUtils.isNotEmpty(clientProposal)) {
                 if (debugEnabled) {
                     log.debug("isKexExtensionsAvailable({})[{}] already sent proposal={} (server={})",
                             session, phase, clientProposal, serverProposal);
    @@ -108,7 +110,7 @@ public boolean isKexExtensionsAvailable(Session session, AvailabilityPhase phase
              *
              * Therefore we want to be sure the server declared its support for extensions before we declare ours.
              */
    -        if (GenericUtils.isEmpty(serverProposal)) {
    +        if (MapEntryUtils.isEmpty(serverProposal)) {
                 if (debugEnabled) {
                     log.debug("isKexExtensionsAvailable({})[{}] no server proposal", session, phase);
                 }
    @@ -164,7 +166,7 @@ public List> updateAvailableSignatureFactories(
                 throws IOException {
             List> available = session.getSignatureFactories();
             List> updated = resolveUpdatedSignatureFactories(session, available, extraAlgos);
    -        if (!GenericUtils.isSameReference(available, updated)) {
    +        if (!UnaryEquator.isSameReference(available, updated)) {
                 if (log.isDebugEnabled()) {
                     log.debug("updateAvailableSignatureFactories({}) available={}, updated={}",
                             session, available, updated);
    diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java
    index d1f3ac01b..147ef16f7 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java
    @@ -62,10 +62,10 @@
     import org.apache.sshd.common.session.UnknownChannelReferenceHandler;
     import org.apache.sshd.common.util.EventListenerUtils;
     import org.apache.sshd.common.util.GenericUtils;
    -import org.apache.sshd.common.util.Int2IntFunction;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
    +import org.apache.sshd.common.util.functors.Int2IntFunction;
     import org.apache.sshd.core.CoreModuleProperties;
     import org.apache.sshd.server.x11.DefaultX11ForwardSupport;
     import org.apache.sshd.server.x11.X11ForwardSupport;
    diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
    index 41eae682c..7a01066e0 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java
    @@ -79,6 +79,7 @@
     import org.apache.sshd.common.session.SessionListener;
     import org.apache.sshd.common.session.SessionWorkBuffer;
     import org.apache.sshd.common.util.EventListenerUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
     import org.apache.sshd.common.util.NumberUtils;
     import org.apache.sshd.common.util.Readable;
    @@ -898,7 +899,7 @@ public IoWriteFuture writePacket(Buffer buffer) throws IOException {
                                                   + " to check re-key necessity: " + e.getMessage()),
                             e);
                 } catch (Exception e) {
    -                GenericUtils.rethrowAsIoException(e);
    +                ExceptionUtils.rethrowAsIoException(e);
                 }
             }
         }
    @@ -2119,7 +2120,7 @@ public KeyExchangeFuture reExchangeKeys() throws IOException {
                                               + " to generate keys for exchange: " + e.getMessage()),
                         e);
             } catch (Exception e) {
    -            GenericUtils.rethrowAsIoException(e);
    +            ExceptionUtils.rethrowAsIoException(e);
                 return null;    // actually dead code
             }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
    index 4de89bfdd..09a7a47b3 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/SessionHelper.java
    @@ -66,12 +66,14 @@
     import org.apache.sshd.common.session.SessionListener;
     import org.apache.sshd.common.session.UnknownChannelReferenceHandler;
     import org.apache.sshd.common.session.helpers.TimeoutIndicator.TimeoutStatus;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
    -import org.apache.sshd.common.util.Invoker;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.buffer.BufferUtils;
     import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
    +import org.apache.sshd.common.util.io.functors.Invoker;
     import org.apache.sshd.common.util.net.SshdSocketAddress;
     import org.apache.sshd.core.CoreModuleProperties;
     
    @@ -217,7 +219,7 @@ public void setAuthenticated() throws IOException {
             try {
                 signalSessionEvent(SessionListener.Event.Authenticated);
             } catch (Exception e) {
    -            GenericUtils.rethrowAsIoException(e);
    +            ExceptionUtils.rethrowAsIoException(e);
             }
         }
     
    @@ -571,7 +573,7 @@ protected void signalSessionEstablished(IoSession ioSession) throws Exception {
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("Failed ({}) to announce session={} established: {}",
                         e.getClass().getSimpleName(), ioSession, e.getMessage(), e);
                 if (e instanceof Exception) {
    @@ -596,7 +598,7 @@ protected void signalSessionCreated(IoSession ioSession) throws Exception {
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("Failed ({}) to announce session={} created: {}",
                         e.getClass().getSimpleName(), ioSession, e.getMessage(), e);
                 if (e instanceof Exception) {
    @@ -621,7 +623,7 @@ protected void signalSendIdentification(String version, List extraLines)
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 if (e instanceof Exception) {
                     throw (Exception) e;
                 } else {
    @@ -645,7 +647,7 @@ protected void signalReadPeerIdentificationLine(String line, List extraL
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("signalReadPeerIdentificationLine({}) Failed ({}) to announce peer={}: {}",
                         this, e.getClass().getSimpleName(), line, e.getMessage(), e);
                 if (e instanceof Exception) {
    @@ -672,7 +674,7 @@ protected void signalPeerIdentificationReceived(String version, List ext
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("signalPeerIdentificationReceived({}) Failed ({}) to announce peer={}: {}",
                         this, e.getClass().getSimpleName(), version, e.getMessage(), e);
                 if (e instanceof Exception) {
    @@ -705,7 +707,7 @@ protected void signalSessionEvent(SessionListener.Event event) throws Exception
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable t = GenericUtils.peelException(err);
    +            Throwable t = ExceptionUtils.peelException(err);
                 debug("sendSessionEvent({})[{}] failed ({}) to inform listeners: {}",
                         this, event, t.getClass().getSimpleName(), t.getMessage(), t);
                 if (t instanceof Exception) {
    @@ -740,7 +742,7 @@ protected void invokeSessionSignaller(Invoker invoker) th
                 try {
                     invoker.invoke(l);
                 } catch (Throwable t) {
    -                err = GenericUtils.accumulateException(err, t);
    +                err = ExceptionUtils.accumulateException(err, t);
                 }
             }
     
    @@ -1005,7 +1007,7 @@ protected Map mergeProposals(
                     current.clear(); // debug breakpoint
                 }
     
    -            if (GenericUtils.isEmpty(proposal)) {
    +            if (MapEntryUtils.isEmpty(proposal)) {
                     return proposal; // debug breakpoint
                 }
     
    @@ -1022,7 +1024,7 @@ protected void signalNegotiationOptionsCreated(Map pr
                     return null;
                 });
             } catch (Throwable t) {
    -            Throwable err = GenericUtils.peelException(t);
    +            Throwable err = ExceptionUtils.peelException(t);
                 if (err instanceof RuntimeException) {
                     throw (RuntimeException) err;
                 } else if (err instanceof Error) {
    @@ -1049,7 +1051,7 @@ protected void signalNegotiationStart(
                     return null;
                 });
             } catch (Throwable t) {
    -            Throwable err = GenericUtils.peelException(t);
    +            Throwable err = ExceptionUtils.peelException(t);
                 if (err instanceof RuntimeException) {
                     throw (RuntimeException) err;
                 } else if (err instanceof Error) {
    @@ -1078,7 +1080,7 @@ protected void signalNegotiationEnd(
                     return null;
                 });
             } catch (Throwable t) {
    -            Throwable err = GenericUtils.peelException(t);
    +            Throwable err = ExceptionUtils.peelException(t);
                 if (err instanceof RuntimeException) {
                     throw (RuntimeException) err;
                 } else if (err instanceof Error) {
    @@ -1196,7 +1198,7 @@ protected void signalDisconnect(int code, String msg, String lang, boolean initi
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("signalDisconnect({}) {}: {}",
                         this, e.getClass().getSimpleName(), e.getMessage(), e);
             }
    @@ -1256,7 +1258,7 @@ protected void signalExceptionCaught(Throwable t) {
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("signalExceptionCaught({}) {}: {}",
                         this, e.getClass().getSimpleName(), e.getMessage(), e);
             }
    @@ -1277,7 +1279,7 @@ protected void signalSessionClosed() {
                     return null;
                 });
             } catch (Throwable err) {
    -            Throwable e = GenericUtils.peelException(err);
    +            Throwable e = ExceptionUtils.peelException(err);
                 debug("signalSessionClosed({}) {} while signal session closed: {}",
                         this, e.getClass().getSimpleName(), e.getMessage(), e);
                 // Do not re-throw since session closed anyway
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/AuthorizedKeyEntriesPublickeyAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/AuthorizedKeyEntriesPublickeyAuthenticator.java
    index 806497193..de11dbda9 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/AuthorizedKeyEntriesPublickeyAuthenticator.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/pubkey/AuthorizedKeyEntriesPublickeyAuthenticator.java
    @@ -32,6 +32,7 @@
     import org.apache.sshd.common.config.keys.KeyUtils;
     import org.apache.sshd.common.config.keys.PublicKeyEntryResolver;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
     import org.apache.sshd.server.session.ServerSession;
     
    @@ -78,7 +79,7 @@ public Object getId() {
     
         @Override
         public boolean authenticate(String username, PublicKey key, ServerSession session) {
    -        if (GenericUtils.isEmpty(resolvedKeys)) {
    +        if (MapEntryUtils.isEmpty(resolvedKeys)) {
                 if (log.isDebugEnabled()) {
                     log.debug("authenticate(" + username + ")[" + session + "] no entries");
                 }
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java
    index 45839424c..788ac55ba 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java
    @@ -33,7 +33,7 @@
     import org.apache.sshd.common.channel.RequestHandler;
     import org.apache.sshd.common.channel.Window;
     import org.apache.sshd.common.session.Session;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.threads.CloseableExecutorService;
     
    @@ -87,7 +87,7 @@ protected OpenFuture doInit(Buffer buffer) {
                 signalChannelOpenSuccess();
                 f.setOpened();
             } catch (Throwable t) {
    -            Throwable e = GenericUtils.peelException(t);
    +            Throwable e = ExceptionUtils.peelException(t);
                 changeEvent = e.getClass().getSimpleName();
                 signalChannelOpenFailure(e);
                 f.setException(e);
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java
    index 8ad6254a4..310a8e47c 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/PuttyRequestHandler.java
    @@ -29,6 +29,7 @@
     import org.apache.sshd.common.session.Session;
     import org.apache.sshd.common.session.SessionContext;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     
     /**
    @@ -113,7 +114,7 @@ public static boolean isPuttyClient(String clientVersion) {
     
         public static Map resolveShellTtyOptions(Map modes) {
             Map resolved = PtyMode.createEnabledOptions(PUTTY_OPTIONS);
    -        if (GenericUtils.size(modes) > 0) {
    +        if (MapEntryUtils.size(modes) > 0) {
                 resolved.putAll(modes); // TODO consider adding only non-overriding options
             }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/config/SshServerConfigFileReader.java b/sshd-core/src/main/java/org/apache/sshd/server/config/SshServerConfigFileReader.java
    index 9eb79aa32..8a7057efc 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/config/SshServerConfigFileReader.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/config/SshServerConfigFileReader.java
    @@ -29,6 +29,7 @@
     import org.apache.sshd.common.config.SshConfigFileReader;
     import org.apache.sshd.common.session.SessionHeartbeatController.HeartbeatType;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.core.CoreModuleProperties;
     import org.apache.sshd.server.ServerBuilder;
    @@ -81,7 +82,7 @@ public static  S setupServerHeartbeat(S server,
         }
     
         public static  S setupServerHeartbeat(S server, Map options) {
    -        if ((server == null) || GenericUtils.isEmpty(options)) {
    +        if ((server == null) || MapEntryUtils.isEmpty(options)) {
                 return server;
             }
     
    @@ -110,7 +111,7 @@ public static  S configure(
         }
     
         public static ForwardingFilter resolveServerForwarding(PropertyResolver options) {
    -        if (GenericUtils.isEmpty(options)) {
    +        if (PropertyResolver.isEmpty(options)) {
                 return AcceptAllForwardingFilter.INSTANCE;
             }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java
    index 8b08ca9ac..c1b38a9de 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/config/keys/ServerIdentity.java
    @@ -36,6 +36,7 @@
     import org.apache.sshd.common.config.keys.IdentityUtils;
     import org.apache.sshd.common.keyprovider.KeyPairProvider;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.io.IoUtils;
     import org.apache.sshd.server.SshServer;
    @@ -154,7 +155,7 @@ public static Map findCertificates(Properties props, LinkOption...
     
         private static Map getLocations(String configPropKey, Properties props, LinkOption... options)
                 throws IOException {
    -        if (GenericUtils.isEmpty(props)) {
    +        if (MapEntryUtils.isEmpty(props)) {
                 return Collections.emptyMap();
             }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
    index 0581ed4cf..7ea6c7221 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java
    @@ -52,7 +52,7 @@
     import org.apache.sshd.common.io.IoSession;
     import org.apache.sshd.common.io.IoWriteFuture;
     import org.apache.sshd.common.session.Session;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.Readable;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
    @@ -305,12 +305,12 @@ protected void handleChannelConnectResult(OpenFuture f, IoConnectFuture future)
                     return;
                 }
     
    -            Throwable problem = GenericUtils.peelException(future.getException());
    +            Throwable problem = ExceptionUtils.peelException(future.getException());
                 if (problem != null) {
                     handleChannelOpenFailure(f, problem);
                 }
             } catch (RuntimeException t) {
    -            Throwable e = GenericUtils.peelException(t);
    +            Throwable e = ExceptionUtils.peelException(t);
                 signalChannelOpenFailure(e);
                 try {
                     f.setException(e);
    @@ -328,7 +328,7 @@ protected void handleChannelOpenSuccess(OpenFuture f, IoSession session) {
                 signalChannelOpenSuccess();
                 f.setOpened();
             } catch (Throwable t) {
    -            Throwable e = GenericUtils.peelException(t);
    +            Throwable e = ExceptionUtils.peelException(t);
                 changeEvent = e.getClass().getSimpleName();
                 signalChannelOpenFailure(e);
                 f.setException(e);
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java b/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
    index d06fb0a2f..a2fc22628 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/global/CancelTcpipForwardHandler.java
    @@ -26,8 +26,8 @@
     import org.apache.sshd.common.session.ConnectionService;
     import org.apache.sshd.common.session.Session;
     import org.apache.sshd.common.session.helpers.AbstractConnectionServiceRequestHandler;
    -import org.apache.sshd.common.util.Int2IntFunction;
     import org.apache.sshd.common.util.buffer.Buffer;
    +import org.apache.sshd.common.util.functors.Int2IntFunction;
     import org.apache.sshd.common.util.net.SshdSocketAddress;
     
     /**
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java b/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
    index 9ccac7d2e..b64d1b242 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/global/TcpipForwardHandler.java
    @@ -26,8 +26,8 @@
     import org.apache.sshd.common.session.ConnectionService;
     import org.apache.sshd.common.session.Session;
     import org.apache.sshd.common.session.helpers.AbstractConnectionServiceRequestHandler;
    -import org.apache.sshd.common.util.Int2IntFunction;
     import org.apache.sshd.common.util.buffer.Buffer;
    +import org.apache.sshd.common.util.functors.Int2IntFunction;
     import org.apache.sshd.common.util.net.SshdSocketAddress;
     
     /**
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
    index 5cff5f9cd..bb0fbe553 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/session/AbstractServerSession.java
    @@ -56,6 +56,7 @@
     import org.apache.sshd.common.session.helpers.AbstractSession;
     import org.apache.sshd.common.signature.SignatureFactory;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
    @@ -552,7 +553,7 @@ public int getActiveSessionCountForUser(String userName) {
             IoSession networkSession = getIoSession();
             IoService service = networkSession.getService();
             Map sessionsMap = service.getManagedSessions();
    -        if (GenericUtils.isEmpty(sessionsMap)) {
    +        if (MapEntryUtils.isEmpty(sessionsMap)) {
                 return 0;
             }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java b/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java
    index 29b657384..02762c558 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java
    @@ -27,6 +27,7 @@
     import java.util.concurrent.ExecutorService;
     
     import org.apache.sshd.common.RuntimeSshException;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
    @@ -148,7 +149,7 @@ public synchronized void destroy(ChannelSession channel) throws Exception {
             } catch (Throwable e) {
                 warn("destroy({}) failed ({}) to destroy shell: {}",
                         this, e.getClass().getSimpleName(), e.getMessage(), e);
    -            err = GenericUtils.accumulateException(err, e);
    +            err = ExceptionUtils.accumulateException(err, e);
             }
     
             if (shutdownExecutor && (executor instanceof ExecutorService)) {
    @@ -157,7 +158,7 @@ public synchronized void destroy(ChannelSession channel) throws Exception {
                 } catch (Exception e) {
                     warn("destroy({}) failed ({}) to shut down executor: {}",
                             this, e.getClass().getSimpleName(), e.getMessage(), e);
    -                err = GenericUtils.accumulateException(err, e);
    +                err = ExceptionUtils.accumulateException(err, e);
                 }
             }
     
    diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShell.java b/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShell.java
    index 0bb881c91..32a93ccf8 100644
    --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShell.java
    +++ b/sshd-core/src/main/java/org/apache/sshd/server/shell/ProcessShell.java
    @@ -31,6 +31,7 @@
     
     import org.apache.sshd.common.channel.PtyMode;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.io.IoUtils;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
    @@ -100,7 +101,7 @@ public void start(ChannelSession channel, Environment env) throws IOException {
             }
     
             ProcessBuilder builder = new ProcessBuilder(command);
    -        if (GenericUtils.size(varsMap) > 0) {
    +        if (MapEntryUtils.size(varsMap) > 0) {
                 try {
                     Map procEnv = builder.environment();
                     procEnv.putAll(varsMap);
    diff --git a/sshd-core/src/test/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifierTest.java b/sshd-core/src/test/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifierTest.java
    index 98fd5b07b..67cdba0c8 100644
    --- a/sshd-core/src/test/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifierTest.java
    +++ b/sshd-core/src/test/java/org/apache/sshd/client/keyverifier/KnownHostsServerKeyVerifierTest.java
    @@ -50,6 +50,7 @@
     import org.apache.sshd.common.mac.Mac;
     import org.apache.sshd.common.random.JceRandomFactory;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.net.SshdSocketAddress;
     import org.apache.sshd.util.test.BaseTestSupport;
    @@ -395,7 +396,7 @@ private void testUpdateSameHostWithDifferentPorts(int port1, int port2, boolean
             assertTrue("Accepted on port=" + port2 + " ?", accepted2);
     
             Map updatedKeys = loadEntries(path);
    -        assertEquals("Mismatched total entries count", 2, GenericUtils.size(updatedKeys));
    +        assertEquals("Mismatched total entries count", 2, MapEntryUtils.size(updatedKeys));
         }
     
         private Path createKnownHostsCopy() throws IOException {
    diff --git a/sshd-core/src/test/java/org/apache/sshd/common/PropertyResolverUtilsTest.java b/sshd-core/src/test/java/org/apache/sshd/common/PropertyResolverUtilsTest.java
    index 323fbaf0e..92471c924 100644
    --- a/sshd-core/src/test/java/org/apache/sshd/common/PropertyResolverUtilsTest.java
    +++ b/sshd-core/src/test/java/org/apache/sshd/common/PropertyResolverUtilsTest.java
    @@ -29,7 +29,7 @@
     import java.util.concurrent.TimeUnit;
     
     import org.apache.sshd.common.session.Session;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.util.test.JUnitTestSupport;
     import org.apache.sshd.util.test.NoIoTestCase;
     import org.junit.FixMethodOrder;
    @@ -66,7 +66,7 @@ public void testResolveAndUpdateClosestPropertyValue() {
         public void testSyspropsResolver() {
             PropertyResolver resolver = SyspropsMapWrapper.SYSPROPS_RESOLVER;
             Map props = resolver.getProperties();
    -        assertTrue("Unexpected initial resolver values: " + props, GenericUtils.isEmpty(props));
    +        assertTrue("Unexpected initial resolver values: " + props, MapEntryUtils.isEmpty(props));
     
             final String propName = getCurrentTestName();
             assertNull("Unexpected initial resolved value", PropertyResolverUtils.getObject(resolver, propName));
    diff --git a/sshd-core/src/test/java/org/apache/sshd/common/auth/KeyboardInteractiveAuthenticationTest.java b/sshd-core/src/test/java/org/apache/sshd/common/auth/KeyboardInteractiveAuthenticationTest.java
    index feeabf381..5a3785724 100644
    --- a/sshd-core/src/test/java/org/apache/sshd/common/auth/KeyboardInteractiveAuthenticationTest.java
    +++ b/sshd-core/src/test/java/org/apache/sshd/common/auth/KeyboardInteractiveAuthenticationTest.java
    @@ -32,6 +32,7 @@
     import org.apache.sshd.client.session.ClientSession;
     import org.apache.sshd.common.keyprovider.KeyPairProvider;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.MapEntryUtils.NavigableMapBuilder;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.core.CoreModuleProperties;
    @@ -161,7 +162,7 @@ public boolean authenticate(
                         ServerSession session, String username, List responses)
                         throws Exception {
                     assertEquals("Unexpected authenticate call", 1, authCount.incrementAndGet());
    -                assertEquals("Mismatched number of responses", GenericUtils.size(rspMap), GenericUtils.size(responses));
    +                assertEquals("Mismatched number of responses", MapEntryUtils.size(rspMap), GenericUtils.size(responses));
     
                     int index = 0;
                     // Cannot use forEach because the index is not effectively final
    diff --git a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
    index c70e303ec..f9f1eadfe 100644
    --- a/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
    +++ b/sshd-core/src/test/java/org/apache/sshd/server/ServerTest.java
    @@ -65,6 +65,7 @@
     import org.apache.sshd.common.session.helpers.TimeoutIndicator;
     import org.apache.sshd.common.session.helpers.TimeoutIndicator.TimeoutStatus;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.MapEntryUtils.NavigableMapBuilder;
     import org.apache.sshd.common.util.OsUtils;
     import org.apache.sshd.core.CoreModuleProperties;
    @@ -774,7 +775,7 @@ public void start(ChannelSession channel, Environment env) throws IOException {
             assertNotNull("No environment set", cmdEnv);
     
             Map vars = cmdEnv.getEnv();
    -        assertTrue("Mismatched vars count", GenericUtils.size(vars) >= GenericUtils.size(expected));
    +        assertTrue("Mismatched vars count", MapEntryUtils.size(vars) >= MapEntryUtils.size(expected));
             expected.forEach((key, expValue) -> {
                 String actValue = vars.get(key);
                 assertEquals("Mismatched value for " + key, expValue, actValue);
    diff --git a/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java b/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java
    index 1665dc922..fb57a6dda 100644
    --- a/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java
    +++ b/sshd-core/src/test/java/org/apache/sshd/server/config/keys/ServerIdentityTest.java
    @@ -33,6 +33,7 @@
     import org.apache.sshd.common.config.keys.IdentityUtils;
     import org.apache.sshd.common.keyprovider.KeyPairProvider;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.io.IoUtils;
     import org.apache.sshd.util.test.BaseTestSupport;
     import org.apache.sshd.util.test.NoIoTestCase;
    @@ -78,7 +79,7 @@ public void testLoadServerIdentities() throws Exception {
             props.setProperty(ServerIdentity.HOST_KEY_CONFIG_PROP, GenericUtils.join(paths, ','));
     
             Map ids = ServerIdentity.loadIdentities(props, options);
    -        assertEquals("Mismatched loaded ids count", GenericUtils.size(paths), GenericUtils.size(ids));
    +        assertEquals("Mismatched loaded ids count", GenericUtils.size(paths), MapEntryUtils.size(ids));
     
             Collection pairs = new ArrayList<>(ids.size());
             for (BuiltinIdentities type : BuiltinIdentities.VALUES) {
    diff --git a/sshd-git/src/main/java/org/apache/sshd/git/transport/GitSshdSessionFactory.java b/sshd-git/src/main/java/org/apache/sshd/git/transport/GitSshdSessionFactory.java
    index c793ab35e..f4b0b81f7 100644
    --- a/sshd-git/src/main/java/org/apache/sshd/git/transport/GitSshdSessionFactory.java
    +++ b/sshd-git/src/main/java/org/apache/sshd/git/transport/GitSshdSessionFactory.java
    @@ -25,7 +25,7 @@
     import org.apache.sshd.client.session.ClientSession;
     import org.apache.sshd.client.session.ClientSessionHolder;
     import org.apache.sshd.common.session.SessionHolder;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.functors.UnaryEquator;
     import org.eclipse.jgit.errors.TransportException;
     import org.eclipse.jgit.transport.CredentialsProvider;
     import org.eclipse.jgit.transport.RemoteSession;
    @@ -113,7 +113,7 @@ protected ClientSession createClientSession(
                     @Override
                     protected void disconnectSession(ClientSession sessionInstance) {
                         ClientSession thisSession = getClientSession();
    -                    if (GenericUtils.isSameReference(thisSession, sessionInstance)) {
    +                    if (UnaryEquator.isSameReference(thisSession, sessionInstance)) {
                             return; // do not use the session instance we were given
                         }
     
    @@ -123,7 +123,7 @@ protected void disconnectSession(ClientSession sessionInstance) {
                     @Override
                     protected void disconnectClient(SshClient clientInstance) {
                         SshClient thisClient = getClient();
    -                    if (GenericUtils.isSameReference(thisClient, clientInstance)) {
    +                    if (UnaryEquator.isSameReference(thisClient, clientInstance)) {
                             return; // do not close the client the user gave us
                         }
     
    diff --git a/sshd-ldap/src/test/java/org/apache/sshd/ldap/LdapPasswordAuthenticatorTest.java b/sshd-ldap/src/test/java/org/apache/sshd/ldap/LdapPasswordAuthenticatorTest.java
    index a40978ca0..13b260da7 100644
    --- a/sshd-ldap/src/test/java/org/apache/sshd/ldap/LdapPasswordAuthenticatorTest.java
    +++ b/sshd-ldap/src/test/java/org/apache/sshd/ldap/LdapPasswordAuthenticatorTest.java
    @@ -27,7 +27,7 @@
     import org.apache.directory.server.core.annotations.CreateDS;
     import org.apache.directory.server.core.annotations.CreatePartition;
     import org.apache.directory.server.core.integ.CreateLdapServerRule;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.server.session.ServerSession;
     import org.junit.ClassRule;
     import org.junit.FixMethodOrder;
    @@ -59,7 +59,7 @@ public LdapPasswordAuthenticatorTest() {
         public void testPasswordComparison() throws Exception {
             usersMap = populateUsers(serverRule.getLdapServer().getDirectoryService(),
                     LdapPasswordAuthenticatorTest.class, LdapPasswordAuthenticator.DEFAULT_PASSWORD_ATTR_NAME);
    -        assertFalse("No users retrieved", GenericUtils.isEmpty(usersMap));
    +        assertFalse("No users retrieved", MapEntryUtils.isEmpty(usersMap));
     
             LdapPasswordAuthenticator auth = new LdapPasswordAuthenticator();
             auth.setHost(getHost(serverRule.getLdapServer()));
    diff --git a/sshd-ldap/src/test/java/org/apache/sshd/ldap/LdapPublickeyAuthenticatorTest.java b/sshd-ldap/src/test/java/org/apache/sshd/ldap/LdapPublickeyAuthenticatorTest.java
    index b7f1ac79e..1d899e714 100644
    --- a/sshd-ldap/src/test/java/org/apache/sshd/ldap/LdapPublickeyAuthenticatorTest.java
    +++ b/sshd-ldap/src/test/java/org/apache/sshd/ldap/LdapPublickeyAuthenticatorTest.java
    @@ -35,7 +35,7 @@
     import org.apache.sshd.common.config.keys.AuthorizedKeyEntry;
     import org.apache.sshd.common.config.keys.KeyUtils;
     import org.apache.sshd.common.config.keys.PublicKeyEntryResolver;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.server.session.ServerSession;
     import org.junit.ClassRule;
     import org.junit.FixMethodOrder;
    @@ -69,7 +69,7 @@ public LdapPublickeyAuthenticatorTest() {
         public void testPublicKeyComparison() throws Exception {
             Map credentials = populateUsers(serverRule.getLdapServer().getDirectoryService(),
                     LdapPublickeyAuthenticatorTest.class, TEST_ATTR_NAME);
    -        assertFalse("No keys retrieved", GenericUtils.isEmpty(credentials));
    +        assertFalse("No keys retrieved", MapEntryUtils.isEmpty(credentials));
     
             // Cannot use forEach because of the potential GeneraSecurityException being thrown
             for (Map.Entry ce : credentials.entrySet()) {
    diff --git a/sshd-mina/src/main/java/org/apache/sshd/mina/MinaService.java b/sshd-mina/src/main/java/org/apache/sshd/mina/MinaService.java
    index 99f471204..77c0a9aaf 100644
    --- a/sshd-mina/src/main/java/org/apache/sshd/mina/MinaService.java
    +++ b/sshd-mina/src/main/java/org/apache/sshd/mina/MinaService.java
    @@ -37,7 +37,7 @@
     import org.apache.sshd.common.FactoryManager;
     import org.apache.sshd.common.Property;
     import org.apache.sshd.common.io.IoServiceEventListener;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.Readable;
     import org.apache.sshd.common.util.closeable.AbstractCloseable;
     import org.apache.sshd.core.CoreModuleProperties;
    @@ -213,7 +213,7 @@ protected void configure(SocketSessionConfig config) {
     
         protected void handleConfigurationError(
                 SocketSessionConfig config, Property property, Object propValue, RuntimeIoException t) {
    -        Throwable e = GenericUtils.resolveExceptionCause(t);
    +        Throwable e = ExceptionUtils.resolveExceptionCause(t);
             log.warn("handleConfigurationError({}={}) failed ({}) to configure: {}",
                     property.getName(), propValue, e.getClass().getSimpleName(), e.getMessage());
         }
    diff --git a/sshd-mina/src/main/java/org/apache/sshd/mina/MinaSession.java b/sshd-mina/src/main/java/org/apache/sshd/mina/MinaSession.java
    index 04c7ea7ae..722d82e08 100644
    --- a/sshd-mina/src/main/java/org/apache/sshd/mina/MinaSession.java
    +++ b/sshd-mina/src/main/java/org/apache/sshd/mina/MinaSession.java
    @@ -39,7 +39,7 @@
     import org.apache.sshd.common.io.IoService;
     import org.apache.sshd.common.io.IoSession;
     import org.apache.sshd.common.io.IoWriteFuture;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.NumberUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.closeable.AbstractInnerCloseable;
    @@ -228,7 +228,7 @@ public void shutdownOutputStream() throws IOException {
             try {
                 channel = (Channel) NIO_SESSION_CHANNEL_FIELD.get(session);
             } catch (Exception t) {
    -            Throwable e = GenericUtils.peelException(t);
    +            Throwable e = ExceptionUtils.peelException(t);
                 log.warn("shudownOutputStream({}) failed ({}) to retrieve embedded channel: {}",
                         session, e.getClass().getSimpleName(), e.getMessage());
                 return;
    diff --git a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoSession.java b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoSession.java
    index 01ab21d0c..143e66191 100644
    --- a/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoSession.java
    +++ b/sshd-netty/src/main/java/org/apache/sshd/netty/NettyIoSession.java
    @@ -47,6 +47,7 @@
     import org.apache.sshd.common.io.IoService;
     import org.apache.sshd.common.io.IoSession;
     import org.apache.sshd.common.io.IoWriteFuture;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.closeable.AbstractCloseable;
    @@ -186,7 +187,7 @@ public void shutdownOutputStream() throws IOException {
             try {
                 channel = (SelectableChannel) NIO_JAVA_CHANNEL_METHOD.invoke(ch, GenericUtils.EMPTY_OBJECT_ARRAY);
             } catch (Exception t) {
    -            Throwable e = GenericUtils.peelException(t);
    +            Throwable e = ExceptionUtils.peelException(t);
                 log.warn("shudownOutputStream({}) failed ({}) to retrieve embedded channel: {}",
                         this, e.getClass().getSimpleName(), e.getMessage());
                 return;
    diff --git a/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPAuthorizedEntriesTracker.java b/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPAuthorizedEntriesTracker.java
    index 70b0f93a2..8788b1876 100644
    --- a/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPAuthorizedEntriesTracker.java
    +++ b/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPAuthorizedEntriesTracker.java
    @@ -38,6 +38,7 @@
     import org.apache.sshd.common.config.keys.KeyUtils;
     import org.apache.sshd.common.session.SessionContext;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.io.resource.PathResource;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
     import org.apache.sshd.common.util.security.SecurityUtils;
    @@ -123,7 +124,7 @@ public List loadMatchingKeyFingerprints(
                 PathResource resourceKey = f.toPathResource();
                 Key container = f.loadPublicKey(session, resourceKey, provider);
                 Map fpMap = PGPUtils.mapSubKeysByFingerprint(container);
    -            int numSubKeys = GenericUtils.size(fpMap);
    +            int numSubKeys = MapEntryUtils.size(fpMap);
                 Collection matches = (numSubKeys <= 0)
                         ? Collections.emptyList()
                         : fpMap.entrySet()
    diff --git a/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPAuthorizedKeyEntriesLoader.java b/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPAuthorizedKeyEntriesLoader.java
    index 3f9225ce1..11fcdacc8 100644
    --- a/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPAuthorizedKeyEntriesLoader.java
    +++ b/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPAuthorizedKeyEntriesLoader.java
    @@ -36,6 +36,7 @@
     import org.apache.sshd.common.keyprovider.KeyTypeIndicator;
     import org.apache.sshd.common.session.SessionContext;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.bouncycastle.openpgp.PGPException;
     
     /**
    @@ -82,7 +83,7 @@ default List resolveAuthorizedEntries(
                 SessionContext session, Collection entries, PublicKeyEntryResolver fallbackResolver)
                 throws IOException, GeneralSecurityException, PGPException {
             Map> typesMap = KeyTypeIndicator.groupByKeyType(entries);
    -        if (GenericUtils.isEmpty(typesMap)) {
    +        if (MapEntryUtils.isEmpty(typesMap)) {
                 return Collections.emptyList();
             }
     
    diff --git a/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPPublicRingWatcher.java b/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPPublicRingWatcher.java
    index 8855e7d8b..76113385a 100644
    --- a/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPPublicRingWatcher.java
    +++ b/sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPPublicRingWatcher.java
    @@ -41,6 +41,8 @@
     import org.apache.sshd.common.config.keys.KeyUtils;
     import org.apache.sshd.common.session.SessionContext;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
    +import org.apache.sshd.common.util.functors.UnaryEquator;
     import org.apache.sshd.common.util.io.ModifiableFileWatcher;
     import org.apache.sshd.common.util.io.resource.IoResource;
     import org.apache.sshd.common.util.io.resource.PathResource;
    @@ -86,7 +88,7 @@ public List loadMatchingKeyFingerprints(
             }
     
             Map keysMap = resolveRingKeys(session);
    -        if (GenericUtils.isEmpty(keysMap)) {
    +        if (MapEntryUtils.isEmpty(keysMap)) {
                 return Collections.emptyList();
             }
     
    @@ -109,7 +111,7 @@ public List loadMatchingKeyFingerprints(
         protected NavigableMap resolveRingKeys(SessionContext session)
                 throws IOException, GeneralSecurityException, PGPException {
             NavigableMap keysMap = ringKeys.get();
    -        if (GenericUtils.isEmpty(keysMap) || checkReloadRequired()) {
    +        if (MapEntryUtils.isEmpty(keysMap) || checkReloadRequired()) {
                 ringKeys.set(Collections.emptyNavigableMap()); // mark stale
     
                 if (!exists()) {
    @@ -119,7 +121,7 @@ protected NavigableMap resolveRingKeys(SessionContext session
                 Path file = getPath();
                 keysMap = reloadRingKeys(session, new PathResource(file));
     
    -            int numKeys = GenericUtils.size(keysMap);
    +            int numKeys = MapEntryUtils.size(keysMap);
                 if (log.isDebugEnabled()) {
                     log.debug("resolveRingKeys({}) reloaded {} keys from {}", session, numKeys, file);
                 }
    @@ -184,7 +186,7 @@ protected NavigableMap reloadRingKeys(
                         PublicKey effective = handleDuplicateKeyFingerprint(session, resourceKey, fp, sk, prev, pubKey);
                         if (effective == null) {
                             keysMap.remove(fp);
    -                    } else if (!GenericUtils.isSameReference(effective, pubKey)) {
    +                    } else if (!UnaryEquator.isSameReference(effective, pubKey)) {
                             keysMap.put(fp, effective);
                         }
                     }
    diff --git a/sshd-openpgp/src/test/java/org/apache/sshd/openpgp/PGPPublicRingWatcherTest.java b/sshd-openpgp/src/test/java/org/apache/sshd/openpgp/PGPPublicRingWatcherTest.java
    index 90868eb0b..fb8ebd77a 100644
    --- a/sshd-openpgp/src/test/java/org/apache/sshd/openpgp/PGPPublicRingWatcherTest.java
    +++ b/sshd-openpgp/src/test/java/org/apache/sshd/openpgp/PGPPublicRingWatcherTest.java
    @@ -25,7 +25,7 @@
     import java.util.NavigableMap;
     
     import org.apache.sshd.common.config.keys.KeyUtils;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.io.resource.PathResource;
     import org.apache.sshd.util.test.CommonTestSupportUtils;
     import org.apache.sshd.util.test.JUnitTestSupport;
    @@ -62,7 +62,7 @@ public void testV1ResourcesKeyPath() throws Exception {
                     detectSourcesFolder(), TEST_SUBFOLDER, RESOURCES_SUBFOLDER, "keyring");
             Path file = dir.resolve(PGPPublicRingWatcher.GPG_V1_PUBLIC_RING_FILENAME);
             Map keys = testPublicRingWatcher(file);
    -        assertFalse("No keys extracted", GenericUtils.isEmpty(keys));
    +        assertFalse("No keys extracted", MapEntryUtils.isEmpty(keys));
         }
     
         @Test
    @@ -71,13 +71,13 @@ public void testV2ResourcesKeyPath() throws Exception {
                     detectSourcesFolder(), TEST_SUBFOLDER, RESOURCES_SUBFOLDER, "kbx2ring");
             Path file = dir.resolve(PGPPublicRingWatcher.GPG_V2_PUBLIC_RING_FILENAME);
             Map keys = testPublicRingWatcher(file);
    -        assertFalse("No keys extracted", GenericUtils.isEmpty(keys));
    +        assertFalse("No keys extracted", MapEntryUtils.isEmpty(keys));
         }
     
         private NavigableMap testPublicRingWatcher(Path file) throws Exception {
             PGPPublicRingWatcher watcher = new PGPPublicRingWatcher(file);
             NavigableMap keys = watcher.reloadRingKeys(null, new PathResource(file));
    -        int numKeys = GenericUtils.size(keys);
    +        int numKeys = MapEntryUtils.size(keys);
             outputDebugMessage("%s: Loaded %d keys from %s", getCurrentTestName(), numKeys, file);
     
             if (numKeys > 0) {
    diff --git a/sshd-putty/src/test/java/org/apache/sshd/putty/PuttyKeyUtilsTest.java b/sshd-putty/src/test/java/org/apache/sshd/putty/PuttyKeyUtilsTest.java
    index 239f3a073..25dd011a4 100644
    --- a/sshd-putty/src/test/java/org/apache/sshd/putty/PuttyKeyUtilsTest.java
    +++ b/sshd-putty/src/test/java/org/apache/sshd/putty/PuttyKeyUtilsTest.java
    @@ -38,6 +38,7 @@
     import org.apache.sshd.common.config.keys.loader.openssh.OpenSSHKeyPairResourceParser;
     import org.apache.sshd.common.session.SessionContext;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.functors.UnaryEquator;
     import org.apache.sshd.common.util.io.IoUtils;
     import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
     import org.apache.sshd.util.test.JUnitTestSupport;
    @@ -88,7 +89,7 @@ public static List parameters() {
         public void testCanDecodePuttyKeyFile() throws IOException, GeneralSecurityException {
             for (String resource : new String[] { regularFile, encryptedFile }) {
                 URL url = getClass().getResource(resource);
    -            if (GenericUtils.isSameReference(regularFile, resource)) {
    +            if (UnaryEquator.isSameReference(regularFile, resource)) {
                     assertNotNull("Missing test resource: " + resource, url);
                 } else {
                     if (url == null) {
    diff --git a/sshd-scp/src/main/java/org/apache/sshd/scp/client/SimpleScpClientImpl.java b/sshd-scp/src/main/java/org/apache/sshd/scp/client/SimpleScpClientImpl.java
    index 54b865f34..a970e8c48 100644
    --- a/sshd-scp/src/main/java/org/apache/sshd/scp/client/SimpleScpClientImpl.java
    +++ b/sshd-scp/src/main/java/org/apache/sshd/scp/client/SimpleScpClientImpl.java
    @@ -26,7 +26,7 @@
     
     import org.apache.sshd.client.session.ClientSession;
     import org.apache.sshd.client.simple.SimpleClient;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.io.functors.IOFunction;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
     
    @@ -109,7 +109,7 @@ protected CloseableScpClient createScpClient(ClientSession session) throws IOExc
                     e.addSuppressed(t);
                 }
     
    -            GenericUtils.rethrowAsIoException(e);
    +            ExceptionUtils.rethrowAsIoException(e);
                 return null;    // actually dead code...
             }
         }
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/SftpClient.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/SftpClient.java
    index 47bafb34f..b207f31b4 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/SftpClient.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/SftpClient.java
    @@ -47,6 +47,7 @@
     import org.apache.sshd.common.util.GenericUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.BufferUtils;
    +import org.apache.sshd.common.util.functors.UnaryEquator;
     import org.apache.sshd.sftp.SftpModuleProperties;
     import org.apache.sshd.sftp.client.extensions.BuiltinSftpClientExtensions;
     import org.apache.sshd.sftp.client.extensions.SftpClientExtension;
    @@ -465,7 +466,7 @@ public String toString() {
     
         class DirEntry {
             public static final Comparator BY_CASE_SENSITIVE_FILENAME = (e1, e2) -> {
    -            if (GenericUtils.isSameReference(e1, e2)) {
    +            if (UnaryEquator.isSameReference(e1, e2)) {
                     return 0;
                 } else if (e1 == null) {
                     return 1;
    @@ -477,7 +478,7 @@ class DirEntry {
             };
     
             public static final Comparator BY_CASE_INSENSITIVE_FILENAME = (e1, e2) -> {
    -            if (GenericUtils.isSameReference(e1, e2)) {
    +            if (UnaryEquator.isSameReference(e1, e2)) {
                     return 0;
                 } else if (e1 == null) {
                     return 1;
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/extensions/helpers/AbstractSftpClientExtension.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/extensions/helpers/AbstractSftpClientExtension.java
    index e57579aca..61a5cbf02 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/extensions/helpers/AbstractSftpClientExtension.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/extensions/helpers/AbstractSftpClientExtension.java
    @@ -28,6 +28,7 @@
     
     import org.apache.sshd.common.SshException;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
    @@ -53,7 +54,7 @@ protected AbstractSftpClientExtension(String name, SftpClient client, RawSftpCli
         }
     
         protected AbstractSftpClientExtension(String name, SftpClient client, RawSftpClient raw, Map extensions) {
    -        this(name, client, raw, GenericUtils.isNotEmpty(extensions) && extensions.containsKey(name));
    +        this(name, client, raw, MapEntryUtils.isNotEmpty(extensions) && extensions.containsKey(name));
         }
     
         protected AbstractSftpClientExtension(String name, SftpClient client, RawSftpClient raw, boolean supported) {
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/fs/SftpFileSystemProvider.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/fs/SftpFileSystemProvider.java
    index 7c3e9c13b..c5e0f0daf 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/fs/SftpFileSystemProvider.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/fs/SftpFileSystemProvider.java
    @@ -81,6 +81,7 @@
     import org.apache.sshd.common.auth.MutableBasicCredentials;
     import org.apache.sshd.common.io.IoSession;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.NumberUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.io.IoUtils;
    @@ -232,7 +233,7 @@ public SftpFileSystem newFileSystem(URI uri, Map env) throws IOExcept
                     session = initializer.createClientSession(this, context);
     
                     // Make any extra configuration parameters available to the session
    -                if (GenericUtils.size(params) > 0) {
    +                if (MapEntryUtils.size(params) > 0) {
                         // Cannot use forEach because the session is not effectively final
                         for (Map.Entry pe : params.entrySet()) {
                             String key = pe.getKey();
    @@ -312,9 +313,9 @@ protected SftpVersionSelector resolveSftpVersionSelector(
     
         // NOTE: URI parameters override environment ones
         public static Map resolveFileSystemParameters(Map env, Map uriParams) {
    -        if (GenericUtils.isEmpty(env)) {
    -            return GenericUtils.isEmpty(uriParams) ? Collections.emptyMap() : uriParams;
    -        } else if (GenericUtils.isEmpty(uriParams)) {
    +        if (MapEntryUtils.isEmpty(env)) {
    +            return MapEntryUtils.isEmpty(uriParams) ? Collections.emptyMap() : uriParams;
    +        } else if (MapEntryUtils.isEmpty(uriParams)) {
                 return Collections.unmodifiableMap(env);
             }
     
    @@ -1329,7 +1330,7 @@ public static URI createFileSystemURI(String host, int port, String username, St
             ValidateUtils.checkNotNullAndNotEmpty(host, "No host provided");
     
             String queryPart = null;
    -        int numParams = GenericUtils.size(params);
    +        int numParams = MapEntryUtils.size(params);
             if (numParams > 0) {
                 StringBuilder sb = new StringBuilder(numParams * Short.SIZE);
                 for (Map.Entry pe : params.entrySet()) {
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/DefaultSftpClient.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/DefaultSftpClient.java
    index ccc15d0de..1df279c15 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/DefaultSftpClient.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/DefaultSftpClient.java
    @@ -52,6 +52,7 @@
     import org.apache.sshd.common.session.ConnectionService;
     import org.apache.sshd.common.session.Session;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
    @@ -488,7 +489,7 @@ public int negotiateVersion(SftpVersionSelector selector) throws IOException {
             List availableVersions = Collections.emptyList();
             if ((GenericUtils.size(extensions) > 0)
                     && extensions.contains(SftpConstants.EXT_VERSION_SELECT)) {
    -            Versions vers = GenericUtils.isEmpty(parsed)
    +            Versions vers = MapEntryUtils.isEmpty(parsed)
                         ? null
                         : (Versions) parsed.get(SftpConstants.EXT_VERSIONS);
                 availableVersions = (vers == null)
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/SimpleSftpClientImpl.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/SimpleSftpClientImpl.java
    index 8cf82b065..c91e4b845 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/SimpleSftpClientImpl.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/SimpleSftpClientImpl.java
    @@ -25,7 +25,7 @@
     
     import org.apache.sshd.client.session.ClientSession;
     import org.apache.sshd.client.simple.SimpleClient;
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.io.functors.IOFunction;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
     import org.apache.sshd.sftp.client.SftpClient;
    @@ -102,7 +102,7 @@ protected SftpClient createSftpClient(ClientSession session) throws IOException
                     client = null; // disable auto-close at finally block
                     return closer;
                 } catch (Exception e) {
    -                err = GenericUtils.accumulateException(err, e);
    +                err = ExceptionUtils.accumulateException(err, e);
                 } finally {
                     if (client != null) {
                         try {
    @@ -110,12 +110,12 @@ protected SftpClient createSftpClient(ClientSession session) throws IOException
                         } catch (Exception t) {
                             debug("createSftpClient({}) failed ({}) to close client: {}",
                                     session, t.getClass().getSimpleName(), t.getMessage(), t);
    -                        err = GenericUtils.accumulateException(err, t);
    +                        err = ExceptionUtils.accumulateException(err, t);
                         }
                     }
                 }
             } catch (Exception e) {
    -            err = GenericUtils.accumulateException(err, e);
    +            err = ExceptionUtils.accumulateException(err, e);
             }
     
             // This point is reached if error occurred
    @@ -127,7 +127,7 @@ protected SftpClient createSftpClient(ClientSession session) throws IOException
             } catch (Exception e) {
                 debug("createSftpClient({}) failed ({}) to close session: {}",
                         session, e.getClass().getSimpleName(), e.getMessage(), e);
    -            err = GenericUtils.accumulateException(err, e);
    +            err = ExceptionUtils.accumulateException(err, e);
             }
     
             if (err instanceof IOException) {
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/SftpHelper.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/SftpHelper.java
    index 3d9f7a37b..68b67f765 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/SftpHelper.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/SftpHelper.java
    @@ -56,6 +56,7 @@
     import org.apache.sshd.common.PropertyResolver;
     import org.apache.sshd.common.SshConstants;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.OsUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
    @@ -414,7 +415,7 @@ public static int permissionsToFileType(int perms) {
     
         /**
          * Converts a file type into a POSIX permission mask value
    -     * 
    +     *
          * @param  type File type - see {@code SSH_FILEXFER_TYPE_xxx} values
          * @return      The matching POSIX permission mask value
          */
    @@ -655,7 +656,7 @@ public static NavigableMap readExtensions(Buffer buffer) {
         }
     
         public static  B writeExtensions(B buffer, Map extensions) {
    -        int numExtensions = GenericUtils.size(extensions);
    +        int numExtensions = MapEntryUtils.size(extensions);
             buffer.putInt(numExtensions);
             if (numExtensions <= 0) {
                 return buffer;
    @@ -676,7 +677,7 @@ public static  B writeExtensions(B buffer, Map extension
         }
     
         public static NavigableMap toStringExtensions(Map extensions) {
    -        if (GenericUtils.isEmpty(extensions)) {
    +        if (MapEntryUtils.isEmpty(extensions)) {
                 return Collections.emptyNavigableMap();
             }
     
    @@ -695,7 +696,7 @@ public static NavigableMap toStringExtensions(Map ext
         }
     
         public static NavigableMap toBinaryExtensions(Map extensions) {
    -        if (GenericUtils.isEmpty(extensions)) {
    +        if (MapEntryUtils.isEmpty(extensions)) {
                 return Collections.emptyNavigableMap();
             }
     
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/AclSupportedParser.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/AclSupportedParser.java
    index a251ad218..f46266494 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/AclSupportedParser.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/AclSupportedParser.java
    @@ -32,6 +32,7 @@
     
     import org.apache.sshd.common.SshConstants;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
     import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
    @@ -112,8 +113,8 @@ private static final class LazyAclCapabilityNameHolder {
                 private static final NavigableMap ACL_VALUES_MAP
                         = LoggingUtils.generateMnemonicMap(SftpConstants.class, ACL_CAP_NAME_PREFIX);
                 private static final NavigableMap ACL_NAMES_MAP = Collections.unmodifiableNavigableMap(
    -                    GenericUtils.flipMap(
    -                            ACL_VALUES_MAP, GenericUtils.caseInsensitiveMap(), false));
    +                    MapEntryUtils.flipMap(
    +                            ACL_VALUES_MAP, MapEntryUtils.caseInsensitiveMap(), false));
     
                 private LazyAclCapabilityNameHolder() {
                     throw new UnsupportedOperationException("No instance allowed");
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/ParserUtils.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/ParserUtils.java
    index a3f77b648..d048aa657 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/ParserUtils.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/common/extensions/ParserUtils.java
    @@ -35,6 +35,7 @@
     
     import org.apache.sshd.common.NamedResource;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.sftp.common.extensions.Supported2Parser.Supported2;
     import org.apache.sshd.sftp.common.extensions.SupportedParser.Supported;
     import org.apache.sshd.sftp.common.extensions.openssh.FstatVfsExtensionParser;
    @@ -69,7 +70,7 @@ Arrays.> asList(
                 BUILT_IN_PARSERS.stream()
                         .collect(Collectors.toMap(
                                 NamedResource::getName, Function.identity(),
    -                            GenericUtils.throwingMerger(), () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER))));
    +                            MapEntryUtils.throwingMerger(), () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER))));
     
         private ParserUtils() {
             throw new UnsupportedOperationException("No instance");
    @@ -136,7 +137,7 @@ public static List> getRegisteredParsers() {
         }
     
         public static Set supportedExtensions(Map parsed) {
    -        if (GenericUtils.isEmpty(parsed)) {
    +        if (MapEntryUtils.isEmpty(parsed)) {
                 return Collections.emptySet();
             }
     
    @@ -165,7 +166,7 @@ public static Set supportedExtensions(Map parsed) {
          * @see               ExtensionParser#parse(byte[])
          */
         public static Map parse(Map extensions) {
    -        if (GenericUtils.isEmpty(extensions)) {
    +        if (MapEntryUtils.isEmpty(extensions)) {
                 return Collections.emptyMap();
             }
     
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpEventListenerAdapter.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpEventListenerAdapter.java
    index 80225b96b..9d4fd4f5c 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpEventListenerAdapter.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpEventListenerAdapter.java
    @@ -26,7 +26,7 @@
     import java.util.Collection;
     import java.util.Map;
     
    -import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
     import org.apache.sshd.server.session.ServerSession;
     
    @@ -76,7 +76,7 @@ public void open(ServerSession session, String remoteHandle, Handle localHandle)
         @Override
         public void readEntries(ServerSession session, String remoteHandle, DirectoryHandle localHandle, Map entries)
                 throws IOException {
    -        int numEntries = GenericUtils.size(entries);
    +        int numEntries = MapEntryUtils.size(entries);
             if (log.isDebugEnabled()) {
                 log.debug("read(" + session + ")[" + localHandle.getFile() + "] " + numEntries + " entries");
             }
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpSubsystemHelper.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpSubsystemHelper.java
    index 0d539fb07..926fb2c25 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpSubsystemHelper.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/AbstractSftpSubsystemHelper.java
    @@ -77,6 +77,7 @@
     import org.apache.sshd.common.session.Session;
     import org.apache.sshd.common.util.EventListenerUtils;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.MapEntryUtils.NavigableMapBuilder;
     import org.apache.sshd.common.util.NumberUtils;
     import org.apache.sshd.common.util.OsUtils;
    @@ -1744,7 +1745,7 @@ protected void appendExtensions(Buffer buffer, String supportedVersions) {
             appendAclSupportedExtension(buffer, session);
     
             Map extensions = getSupportedClientExtensions(session);
    -        int numExtensions = GenericUtils.size(extensions);
    +        int numExtensions = MapEntryUtils.size(extensions);
             List extras = (numExtensions <= 0) ? Collections.emptyList() : new ArrayList<>(numExtensions);
             if (numExtensions > 0) {
                 boolean debugEnabled = log.isDebugEnabled();
    @@ -1963,7 +1964,7 @@ protected String resolveNewlineValue(ServerSession session) {
          */
         protected void appendVendorIdExtension(
                 Buffer buffer, Map versionProperties, ServerSession session) {
    -        if (GenericUtils.isEmpty(versionProperties)) {
    +        if (MapEntryUtils.isEmpty(versionProperties)) {
                 return;
             }
     
    @@ -2321,13 +2322,13 @@ protected NavigableMap getAttributes(Path file, int flags, LinkO
     
             for (String v : views) {
                 Map ta = readFileAttributes(file, v, options);
    -            if (GenericUtils.isNotEmpty(ta)) {
    +            if (MapEntryUtils.isNotEmpty(ta)) {
                     attrs.putAll(ta);
                 }
             }
     
             Map completions = resolveMissingFileAttributes(file, flags, attrs, options);
    -        if (GenericUtils.isNotEmpty(completions)) {
    +        if (MapEntryUtils.isNotEmpty(completions)) {
                 attrs.putAll(completions);
             }
     
    @@ -2360,7 +2361,7 @@ protected NavigableMap resolveMissingFileAttributes(
             // Cannot use forEach because the attrs variable is not effectively final
             for (Map.Entry> re : SftpFileSystemAccessor.FILEATTRS_RESOLVERS.entrySet()) {
                 String name = re.getKey();
    -            Object value = GenericUtils.isEmpty(current) ? null : current.get(name);
    +            Object value = MapEntryUtils.isEmpty(current) ? null : current.get(name);
                 FileInfoExtractor x = re.getValue();
                 try {
                     Object resolved = resolveMissingFileAttributeValue(file, name, value, x, options);
    @@ -2405,7 +2406,7 @@ protected NavigableMap addMissingAttribute(
                 Path file, NavigableMap current,
                 String name, FileInfoExtractor x, LinkOption... options)
                 throws IOException {
    -        Object value = GenericUtils.isEmpty(current) ? null : current.get(name);
    +        Object value = MapEntryUtils.isEmpty(current) ? null : current.get(name);
             if (value != null) { // already have the value
                 return current;
             }
    @@ -2431,7 +2432,7 @@ protected NavigableMap readFileAttributes(
                 SftpFileSystemAccessor accessor = getFileSystemAccessor();
                 Map attrs = accessor.readFileAttributes(
                         getServerSession(), this, file, view, options);
    -            if (GenericUtils.isEmpty(attrs)) {
    +            if (MapEntryUtils.isEmpty(attrs)) {
                     return Collections.emptyNavigableMap();
                 }
     
    @@ -2664,7 +2665,7 @@ protected void setFileOwnership(
         protected void setFileExtensions(
                 Path file, Map extensions, LinkOption... options)
                 throws IOException {
    -        if (GenericUtils.isEmpty(extensions)) {
    +        if (MapEntryUtils.isEmpty(extensions)) {
                 return;
             }
     
    diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/FileHandle.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/FileHandle.java
    index 40c105604..a88f7b58e 100644
    --- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/FileHandle.java
    +++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/FileHandle.java
    @@ -36,6 +36,7 @@
     import java.util.Set;
     
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.io.IoUtils;
     import org.apache.sshd.server.session.ServerSession;
     import org.apache.sshd.sftp.common.SftpConstants;
    @@ -187,7 +188,7 @@ public void unlock(long offset, long length) throws IOException {
         }
     
         public static Collection> toFileAttributes(Map attrs) {
    -        if (GenericUtils.isEmpty(attrs)) {
    +        if (MapEntryUtils.isEmpty(attrs)) {
                 return Collections.emptyList();
             }
     
    diff --git a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
    index 8739088e9..c67497eda 100644
    --- a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
    +++ b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
    @@ -71,6 +71,7 @@
     import org.apache.sshd.common.random.Random;
     import org.apache.sshd.common.session.SessionContext;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.OsUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.buffer.Buffer;
    @@ -750,7 +751,7 @@ public void read(
                 @Override
                 public void readEntries(
                         ServerSession session, String remoteHandle, DirectoryHandle localHandle, Map entries) {
    -                int numEntries = GenericUtils.size(entries);
    +                int numEntries = MapEntryUtils.size(entries);
                     entriesCount.addAndGet(numEntries);
     
                     if (log.isDebugEnabled()) {
    diff --git a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpVersionsTest.java b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpVersionsTest.java
    index e71510e25..feee7348d 100644
    --- a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpVersionsTest.java
    +++ b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpVersionsTest.java
    @@ -46,6 +46,7 @@
     
     import org.apache.sshd.client.session.ClientSession;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.MapEntryUtils.NavigableMapBuilder;
     import org.apache.sshd.server.channel.ChannelSession;
     import org.apache.sshd.server.command.Command;
    @@ -232,7 +233,7 @@ public Command createSubsystem(ChannelSession channel) throws IOException {
                         protected NavigableMap resolveFileAttributes(Path file, int flags, LinkOption... options)
                                 throws IOException {
                             NavigableMap attrs = super.resolveFileAttributes(file, flags, options);
    -                        if (GenericUtils.isEmpty(attrs)) {
    +                        if (MapEntryUtils.isEmpty(attrs)) {
                                 attrs = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
                             }
     
    @@ -268,7 +269,7 @@ protected void setFileAccessControl(Path file, List aclActual, LinkOpt
                 @Override
                 public void modifyingAttributes(ServerSession session, Path path, Map attrs) {
                     @SuppressWarnings("unchecked")
    -                List aclActual = GenericUtils.isEmpty(attrs) ? null : (List) attrs.get("acl");
    +                List aclActual = MapEntryUtils.isEmpty(attrs) ? null : (List) attrs.get("acl");
                     if (getTestedVersion() > SftpConstants.SFTP_V3) {
                         assertListEquals("Mismatched modifying ACL for file=" + path, aclExpected, aclActual);
                     } else {
    @@ -280,7 +281,7 @@ public void modifyingAttributes(ServerSession session, Path path, Map
                 public void modifiedAttributes(
                         ServerSession session, Path path, Map attrs, Throwable thrown) {
                     @SuppressWarnings("unchecked")
    -                List aclActual = GenericUtils.isEmpty(attrs) ? null : (List) attrs.get("acl");
    +                List aclActual = MapEntryUtils.isEmpty(attrs) ? null : (List) attrs.get("acl");
                     if (getTestedVersion() > SftpConstants.SFTP_V3) {
                         assertListEquals("Mismatched modified ACL for file=" + path, aclExpected, aclActual);
                     } else {
    @@ -351,7 +352,7 @@ public Command createSubsystem(ChannelSession channel) throws IOException {
                         protected NavigableMap resolveFileAttributes(Path file, int flags, LinkOption... options)
                                 throws IOException {
                             NavigableMap attrs = super.resolveFileAttributes(file, flags, options);
    -                        if (GenericUtils.isEmpty(attrs)) {
    +                        if (MapEntryUtils.isEmpty(attrs)) {
                                 attrs = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
                             }
     
    @@ -396,7 +397,7 @@ protected void setFileExtensions(Path file, Map extensions, Link
                 public void modifyingAttributes(ServerSession session, Path path, Map attrs) {
                     @SuppressWarnings("unchecked")
                     Map actExtensions
    -                        = GenericUtils.isEmpty(attrs) ? null : (Map) attrs.get("extended");
    +                        = MapEntryUtils.isEmpty(attrs) ? null : (Map) attrs.get("extended");
                     assertExtensionsMapEquals("modifying(" + path + ")", expExtensions, actExtensions);
                 }
     
    @@ -404,7 +405,7 @@ public void modifyingAttributes(ServerSession session, Path path, Map
                 public void modifiedAttributes(ServerSession session, Path path, Map attrs, Throwable thrown) {
                     @SuppressWarnings("unchecked")
                     Map actExtensions
    -                        = GenericUtils.isEmpty(attrs) ? null : (Map) attrs.get("extended");
    +                        = MapEntryUtils.isEmpty(attrs) ? null : (Map) attrs.get("extended");
                     assertExtensionsMapEquals("modified(" + path + ")", expExtensions, actExtensions);
                 }
             });
    diff --git a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/fs/SftpFileSystemTest.java b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/fs/SftpFileSystemTest.java
    index 12552ed45..76abb45e3 100644
    --- a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/fs/SftpFileSystemTest.java
    +++ b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/fs/SftpFileSystemTest.java
    @@ -53,6 +53,7 @@
     
     import org.apache.sshd.client.session.ClientSession;
     import org.apache.sshd.common.session.Session;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
     import org.apache.sshd.common.util.MapEntryUtils.MapBuilder;
     import org.apache.sshd.common.util.OsUtils;
    @@ -271,7 +272,7 @@ public void testMultipleFileStoresOnSameProvider() throws IOException {
                     try {
                         fs.close();
                     } catch (IOException e) {
    -                    err = GenericUtils.accumulateException(err, e);
    +                    err = ExceptionUtils.accumulateException(err, e);
                     }
                 }
     
    diff --git a/sshd-spring-sftp/src/main/java/org/apache/sshd/sftp/spring/integration/ApacheSshdSftpSessionFactory.java b/sshd-spring-sftp/src/main/java/org/apache/sshd/sftp/spring/integration/ApacheSshdSftpSessionFactory.java
    index f43c84921..f0e1dc73f 100644
    --- a/sshd-spring-sftp/src/main/java/org/apache/sshd/sftp/spring/integration/ApacheSshdSftpSessionFactory.java
    +++ b/sshd-spring-sftp/src/main/java/org/apache/sshd/sftp/spring/integration/ApacheSshdSftpSessionFactory.java
    @@ -42,7 +42,9 @@
     import org.apache.sshd.common.config.keys.loader.pem.PEMResourceParserUtils;
     import org.apache.sshd.common.future.CloseFuture;
     import org.apache.sshd.common.future.SshFutureListener;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
    +import org.apache.sshd.common.util.MapEntryUtils;
     import org.apache.sshd.common.util.ValidateUtils;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
     import org.apache.sshd.sftp.client.SftpClient;
    @@ -429,7 +431,7 @@ public Session getSession() {
                     }
                 }
             } catch (Exception e) {
    -            throw GenericUtils.toRuntimeException(e);
    +            throw ExceptionUtils.toRuntimeException(e);
             }
         }
     
    @@ -482,7 +484,7 @@ protected ClientSession createClientSession(String hostname, String username, in
         }
     
         protected ClientSession configureClientSessionProperties(ClientSession session, Properties props) throws IOException {
    -        if (GenericUtils.isEmpty(props)) {
    +        if (MapEntryUtils.isEmpty(props)) {
                 return session;
             }
     
    diff --git a/sshd-spring-sftp/src/main/java/org/apache/sshd/sftp/spring/integration/SpringSftpSession.java b/sshd-spring-sftp/src/main/java/org/apache/sshd/sftp/spring/integration/SpringSftpSession.java
    index 07ef294d8..ee4214075 100644
    --- a/sshd-spring-sftp/src/main/java/org/apache/sshd/sftp/spring/integration/SpringSftpSession.java
    +++ b/sshd-spring-sftp/src/main/java/org/apache/sshd/sftp/spring/integration/SpringSftpSession.java
    @@ -30,6 +30,7 @@
     import java.util.stream.Collectors;
     
     import org.apache.sshd.common.io.IoSession;
    +import org.apache.sshd.common.util.ExceptionUtils;
     import org.apache.sshd.common.util.GenericUtils;
     import org.apache.sshd.common.util.logging.AbstractLoggingBean;
     import org.apache.sshd.common.util.net.SshdSocketAddress;
    @@ -100,17 +101,17 @@ public void close() {
                 SftpClient client = getClientInstance();
                 closeClientInstance(client);
             } catch (Exception e) {
    -            err = GenericUtils.accumulateException(err, e);
    +            err = ExceptionUtils.accumulateException(err, e);
             }
     
             try {
                 closeSessionInstance(getSessionCloser());
             } catch (Exception e) {
    -            err = GenericUtils.accumulateException(err, e);
    +            err = ExceptionUtils.accumulateException(err, e);
             }
     
             if (err != null) {
    -            throw GenericUtils.toRuntimeException(err);
    +            throw ExceptionUtils.toRuntimeException(err);
             }
         }