You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/05/06 16:01:01 UTC
[2/2] mina-sshd git commit: [SSHD-327] Support for OpenSSH config
file in ~/.ssh/config
[SSHD-327] Support for OpenSSH config file in ~/.ssh/config
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/99ebcc95
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/99ebcc95
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/99ebcc95
Branch: refs/heads/master
Commit: 99ebcc9511b5bd9d5c678f54c8833b7651562975
Parents: abec3d8
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Wed May 6 17:00:50 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Wed May 6 17:00:50 2015 +0300
----------------------------------------------------------------------
pom.xml | 1 +
.../main/java/org/apache/sshd/SshBuilder.java | 2 +-
.../main/java/org/apache/sshd/SshClient.java | 7 +-
.../sshd/client/scp/AbstractScpClient.java | 10 +-
.../sshd/client/scp/DefaultScpClient.java | 16 +-
.../client/sftp/SftpFileSystemProvider.java | 3 +-
.../sshd/common/cipher/BuiltinCiphers.java | 42 ++
.../common/compression/BuiltinCompressions.java | 8 +-
.../common/config/AllowTcpForwardingValue.java | 62 +++
.../common/config/CompressionConfigValue.java | 78 ++++
.../sshd/common/config/LogLevelValue.java | 55 +++
.../sshd/common/config/SshConfigFileReader.java | 460 +++++++++++++++++++
.../sshd/common/config/SyslogFacilityValue.java | 50 ++
.../sshd/common/config/TimeValueConfig.java | 175 +++++++
.../sshd/common/digest/BuiltinDigests.java | 6 +-
.../sshd/common/kex/BuiltinDHFactories.java | 42 ++
.../org/apache/sshd/common/mac/BuiltinMacs.java | 44 +-
.../common/signature/BuiltinSignatures.java | 45 +-
.../apache/sshd/common/util/GenericUtils.java | 90 ++++
.../common/util/LoggingFilterOutputStream.java | 57 ---
.../sshd/common/util/NoCloseInputStream.java | 39 --
.../sshd/common/util/NoCloseOutputStream.java | 41 --
.../apache/sshd/common/util/ValidateUtils.java | 28 +-
.../util/io/LoggingFilterOutputStream.java | 58 +++
.../sshd/common/util/io/NoCloseInputStream.java | 47 ++
.../common/util/io/NoCloseOutputStream.java | 47 ++
.../sshd/common/util/io/NoCloseReader.java | 46 ++
.../sshd/common/util/io/NoCloseWriter.java | 46 ++
.../sshd/server/channel/ChannelSession.java | 2 +-
.../sshd/server/channel/PipeDataReceiver.java | 2 +-
.../test/java/org/apache/sshd/ClientTest.java | 2 +-
.../java/org/apache/sshd/WindowAdjustTest.java | 3 +-
.../common/config/SshConfigFileReaderTest.java | 120 +++++
.../sshd/common/config/TimeValueConfigTest.java | 52 +++
.../common/util/EventListenerUtilsTest.java | 1 +
.../sshd/common/util/GenericUtilsTest.java | 58 +++
.../org/apache/sshd/common/config/sshd_config | 87 ++++
37 files changed, 1754 insertions(+), 178 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 1cad3eb..7795da5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -457,6 +457,7 @@
<excludes>
<exclude>**/*.iml</exclude>
<exclude>src/docs/**</exclude>
+ <exclude>src/test/resources/**</exclude>
<exclude>**/stty-output-*.txt</exclude>
<exclude>**/big-msg.txt</exclude>
<exclude>sshd-sftp/**</exclude>
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
index c486727..4daf088 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
@@ -82,7 +82,7 @@ public class SshBuilder {
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
- protected static class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder<T, S>> implements ObjectBuilder<T> {
+ public static class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder<T, S>> implements ObjectBuilder<T> {
protected Factory<T> factory = null;
protected List<NamedFactory<KeyExchange>> keyExchangeFactories = null;
protected List<NamedFactory<Cipher>> cipherFactories = null;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
index b3c102e..12337a8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -61,16 +61,17 @@ import org.apache.sshd.common.Factory;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.SshdSocketAddress;
+import org.apache.sshd.common.config.SshConfigFileReader;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.DefaultIoServiceFactoryFactory;
import org.apache.sshd.common.io.IoConnectFuture;
import org.apache.sshd.common.io.IoConnector;
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
import org.apache.sshd.common.session.AbstractSession;
-import org.apache.sshd.common.util.NoCloseInputStream;
-import org.apache.sshd.common.util.NoCloseOutputStream;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.common.util.ThreadUtils;
+import org.apache.sshd.common.util.io.NoCloseInputStream;
+import org.apache.sshd.common.util.io.NoCloseOutputStream;
import org.bouncycastle.openssl.PasswordFinder;
/**
@@ -349,7 +350,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
}
root.addHandler(fh);
- int port = 22;
+ int port = SshConfigFileReader.DEFAULT_PORT;
String host = null;
String login = System.getProperty("user.name");
boolean agentForward = false;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/client/scp/AbstractScpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/scp/AbstractScpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/scp/AbstractScpClient.java
index b249bc7..f005d2f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/scp/AbstractScpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/scp/AbstractScpClient.java
@@ -49,8 +49,8 @@ public abstract class AbstractScpClient implements ScpClient {
@Override
public void download(String[] remote, String local, Collection<Option> options) throws IOException {
- local = ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s");
- remote = ValidateUtils.checkNotNullAndNotEmpty(remote, "Invalid argument remote: %s");
+ local = ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s", local);
+ remote = ValidateUtils.checkNotNullAndNotEmpty(remote, "Invalid argument remote: %s", (Object) remote);
if (remote.length > 1) {
options = addTargetIsDirectory(options);
@@ -68,7 +68,7 @@ public abstract class AbstractScpClient implements ScpClient {
@Override
public void download(String[] remote, Path local, Collection<Option> options) throws IOException {
- remote = ValidateUtils.checkNotNullAndNotEmpty(remote, "Invalid argument remote: %s");
+ remote = ValidateUtils.checkNotNullAndNotEmpty(remote, "Invalid argument remote: %s", (Object) remote);
if (remote.length > 1) {
options = addTargetIsDirectory(options);
@@ -91,7 +91,7 @@ public abstract class AbstractScpClient implements ScpClient {
@Override
public void upload(String local, String remote, Collection<Option> options) throws IOException {
- upload(new String[] { ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s") }, remote, options);
+ upload(new String[] { ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s", local) }, remote, options);
}
@Override
@@ -106,7 +106,7 @@ public abstract class AbstractScpClient implements ScpClient {
@Override
public void upload(Path local, String remote, Collection<Option> options) throws IOException {
- upload(new Path[] { ValidateUtils.checkNotNull(local, "Invalid local argument: %s") }, remote, GenericUtils.isEmpty(options) ? Collections.<Option>emptySet() : GenericUtils.of(options));
+ upload(new Path[] { ValidateUtils.checkNotNull(local, "Invalid local argument: %s", local) }, remote, GenericUtils.isEmpty(options) ? Collections.<Option>emptySet() : GenericUtils.of(options));
}
@Override
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
index ee2d01f..e42cf80 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
@@ -55,7 +55,7 @@ public class DefaultScpClient extends AbstractScpClient {
@Override
public void download(String remote, String local, Collection<Option> options) throws IOException {
- local = ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s");
+ local = ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s", local);
FileSystemFactory factory = clientSession.getFactoryManager().getFileSystemFactory();
FileSystem fs = factory.createFileSystem(clientSession);
@@ -72,13 +72,13 @@ public class DefaultScpClient extends AbstractScpClient {
@Override
public void download(String remote, Path local, Collection<Option> options) throws IOException {
- local = ValidateUtils.checkNotNull(local, "Invalid argument local: %s");
+ local = ValidateUtils.checkNotNull(local, "Invalid argument local: %s", local);
download(remote, local.getFileSystem(), local, options);
}
protected void download(String remote, FileSystem fs, Path local, Collection<Option> options) throws IOException {
- local = ValidateUtils.checkNotNull(local, "Invalid argument local: %s");
- remote = ValidateUtils.checkNotNullAndNotEmpty(remote, "Invalid argument remote: %s");
+ local = ValidateUtils.checkNotNull(local, "Invalid argument local: %s", local);
+ remote = ValidateUtils.checkNotNullAndNotEmpty(remote, "Invalid argument remote: %s", remote);
LinkOption[] opts = IoUtils.getLinkOptions(false);
if (Files.isDirectory(local, opts)) {
@@ -133,7 +133,7 @@ public class DefaultScpClient extends AbstractScpClient {
@Override
public void upload(String[] local, String remote, Collection<Option> options) throws IOException {
- final Collection<String> paths=Arrays.asList(ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s"));
+ final Collection<String> paths=Arrays.asList(ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s", (Object) local));
runUpload(remote, options, paths, new ScpOperationExecutor<String>() {
public void execute(ScpHelper helper, Collection<String> local, Collection<Option> options) throws IOException {
helper.send(local,
@@ -146,7 +146,7 @@ public class DefaultScpClient extends AbstractScpClient {
@Override
public void upload(Path[] local, String remote, Collection<Option> options) throws IOException {
- final Collection<Path> paths=Arrays.asList(ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s"));
+ final Collection<Path> paths=Arrays.asList(ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s", local));
runUpload(remote, options, paths, new ScpOperationExecutor<Path>() {
public void execute(ScpHelper helper, Collection<Path> local, Collection<Option> options) throws IOException {
helper.sendPaths(local,
@@ -158,8 +158,8 @@ public class DefaultScpClient extends AbstractScpClient {
}
protected <T> void runUpload(String remote, Collection<Option> options, Collection<T> local, ScpOperationExecutor<T> executor) throws IOException {
- local = ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s");
- remote = ValidateUtils.checkNotNullAndNotEmpty(remote, "Invalid argument remote: %s");
+ local = ValidateUtils.checkNotNullAndNotEmpty(local, "Invalid argument local: %s", local);
+ remote = ValidateUtils.checkNotNullAndNotEmpty(remote, "Invalid argument remote: %s", remote);
if (local.size() > 1) {
options = addTargetIsDirectory(options);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
index 8ffa4d8..c765712 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
@@ -68,6 +68,7 @@ import org.apache.sshd.client.SftpClient;
import org.apache.sshd.client.SftpClient.Attributes;
import org.apache.sshd.client.SftpException;
import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.config.SshConfigFileReader;
import org.apache.sshd.common.sftp.SftpConstants;
import org.apache.sshd.common.util.IoUtils;
@@ -124,7 +125,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
String[] ui = userInfo.split(":");
ClientSession session;
try {
- session = client.connect(ui[0], host, uri.getPort() > 0 ? uri.getPort() : 22)
+ session = client.connect(ui[0], host, uri.getPort() > 0 ? uri.getPort() : SshConfigFileReader.DEFAULT_PORT)
.await().getSession();
} catch (InterruptedException e) {
throw new InterruptedIOException();
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
index 52cef83..2ff52a0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/cipher/BuiltinCiphers.java
@@ -19,14 +19,19 @@
package org.apache.sshd.common.cipher;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.List;
import java.util.Set;
import org.apache.sshd.common.Cipher;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.OptionalFeature;
import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
/**
* Provides easy access to the currently implemented ciphers
@@ -72,6 +77,11 @@ public enum BuiltinCiphers implements NamedFactory<Cipher>, OptionalFeature {
return factoryName;
}
+ @Override
+ public final String toString() {
+ return getName();
+ }
+
BuiltinCiphers(String factoryName, int ivsize, int blocksize, String algorithm, String transformation) {
this.factoryName = factoryName;
this.ivsize = ivsize;
@@ -192,6 +202,38 @@ public enum BuiltinCiphers implements NamedFactory<Cipher>, OptionalFeature {
return null;
}
+ /**
+ * @param ciphers A comma-separated list of ciphers' names - ignored
+ * if {@code null}/empty
+ * @return A {@link List} of all the {@link NamedFactory}-ies whose
+ * name appears in the string and represent a built-in cipher. Any
+ * unknown name is <U>ignored</U>. The order of the returned result
+ * is the same as the original order - bar the unknown ciphers.
+ * <B>Note:</B> it is up to caller to ensure that the list does not
+ * contain duplicates
+ */
+ public static final List<NamedFactory<Cipher>> parseCiphersList(String ciphers) {
+ return parseCiphersList(GenericUtils.split(ciphers, ','));
+ }
+
+ public static final List<NamedFactory<Cipher>> parseCiphersList(String ... ciphers) {
+ return parseCiphersList(GenericUtils.isEmpty((Object[]) ciphers) ? Collections.<String>emptyList() : Arrays.asList(ciphers));
+ }
+
+ public static final List<NamedFactory<Cipher>> parseCiphersList(Collection<String> ciphers) {
+ if (GenericUtils.isEmpty(ciphers)) {
+ return Collections.emptyList();
+ }
+
+ List<NamedFactory<Cipher>> result=new ArrayList<NamedFactory<Cipher>>(ciphers.size());
+ for (String name : ciphers) {
+ BuiltinCiphers c=ValidateUtils.checkNotNull(fromFactoryName(name), "Bad factory name (%s) in %s", name, ciphers);
+ result.add(c);
+ }
+
+ return result;
+ }
+
public static final class Constants {
public static final String NONE = "none";
public static final String AES128_CBC = "aes128-cbc";
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java b/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
index e745dfb..bb0c8f8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/compression/BuiltinCompressions.java
@@ -51,11 +51,17 @@ public enum BuiltinCompressions implements NamedFactory<Compression>, OptionalFe
};
private final String name;
+
@Override
public final String getName() {
return name;
}
-
+
+ @Override
+ public final String toString() {
+ return getName();
+ }
+
public final boolean isSupported() {
return true;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/config/AllowTcpForwardingValue.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/AllowTcpForwardingValue.java b/sshd-core/src/main/java/org/apache/sshd/common/config/AllowTcpForwardingValue.java
new file mode 100644
index 0000000..85383fb
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/AllowTcpForwardingValue.java
@@ -0,0 +1,62 @@
+/*
+ * 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.config;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <A HREF="http://www.freebsd.org/cgi/man.cgi?query=sshd_config&sektion=5">sshd_config(5) section</A>
+ */
+public enum AllowTcpForwardingValue {
+ ALL,
+ NONE,
+ LOCAL,
+ REMOTE;
+
+ public static final Set<AllowTcpForwardingValue> VALUES=
+ Collections.unmodifiableSet(EnumSet.allOf(AllowTcpForwardingValue.class));
+ // NOTE: it also interprets "yes" as "all" and "no" as "none"
+ public static final AllowTcpForwardingValue fromString(String s) {
+ if (GenericUtils.isEmpty(s)) {
+ return null;
+ }
+
+ if ("yes".equalsIgnoreCase(s)) {
+ return ALL;
+ }
+
+ if ("no".equalsIgnoreCase(s)) {
+ return NONE;
+ }
+
+ for (AllowTcpForwardingValue v : VALUES) {
+ if (s.equalsIgnoreCase(v.name())) {
+ return v;
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java b/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java
new file mode 100644
index 0000000..bb94f57
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/CompressionConfigValue.java
@@ -0,0 +1,78 @@
+/*
+ * 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.config;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.compression.BuiltinCompressions;
+import org.apache.sshd.common.compression.Compression;
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * Provides a "bridge" between the configuration values and the
+ * actual {@link NamedFactory} for the {@link Compression}.
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public enum CompressionConfigValue implements NamedFactory<Compression> {
+ YES(BuiltinCompressions.zlib),
+ NO(BuiltinCompressions.none),
+ DELAYED(BuiltinCompressions.delayedZlib);
+
+ private final NamedFactory<Compression> factory;
+
+ @Override
+ public final String getName() {
+ return factory.getName();
+ }
+
+ @Override
+ public final Compression create() {
+ return factory.create();
+ }
+
+ @Override
+ public final String toString() {
+ return getName();
+ }
+
+ CompressionConfigValue(NamedFactory<Compression> delegate) {
+ factory = delegate;
+ }
+
+ public static final Set<CompressionConfigValue> VALUES=
+ Collections.unmodifiableSet(EnumSet.allOf(CompressionConfigValue.class));
+
+ public static final CompressionConfigValue fromName(String n) {
+ if (GenericUtils.isEmpty(n)) {
+ return null;
+ }
+
+ for (CompressionConfigValue v : VALUES) {
+ if (n.equalsIgnoreCase(v.name())) {
+ return v;
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/config/LogLevelValue.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/LogLevelValue.java b/sshd-core/src/main/java/org/apache/sshd/common/config/LogLevelValue.java
new file mode 100644
index 0000000..168c91e
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/LogLevelValue.java
@@ -0,0 +1,55 @@
+/*
+ * 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.config;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <A HREF="http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html"><I>LogLevel</I> configuration value</A>
+ */
+public enum LogLevelValue {
+ /*
+ * NOTE(s):
+ * 1. DEBUG and DEBUG1 are EQUIVALENT
+ * 2. Order is important (!!!)
+ */
+ QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, DEBUG3;
+
+ public static final Set<LogLevelValue> VALUES=
+ Collections.unmodifiableSet(EnumSet.allOf(LogLevelValue.class));
+ public static final LogLevelValue fromName(String n) {
+ if (GenericUtils.isEmpty(n)) {
+ return null;
+ }
+
+ for (LogLevelValue l : VALUES) {
+ if (n.equalsIgnoreCase(l.name())) {
+ return l;
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java b/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
new file mode 100644
index 0000000..45c7aff
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/SshConfigFileReader.java
@@ -0,0 +1,460 @@
+/*
+ * 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.config;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StreamCorruptedException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.common.AbstractFactoryManager;
+import org.apache.sshd.common.Cipher;
+import org.apache.sshd.common.KeyPairProvider;
+import org.apache.sshd.common.Mac;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.cipher.BuiltinCiphers;
+import org.apache.sshd.common.compression.Compression;
+import org.apache.sshd.common.kex.BuiltinDHFactories;
+import org.apache.sshd.common.kex.DHFactory;
+import org.apache.sshd.common.mac.BuiltinMacs;
+import org.apache.sshd.common.signature.BuiltinSignatures;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.io.NoCloseInputStream;
+import org.apache.sshd.common.util.io.NoCloseReader;
+
+/**
+ * Reads and interprets some useful configurations from an OpenSSH
+ * configuration file.
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <a href="https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5">ssh_config(5)</a>
+ */
+public class SshConfigFileReader {
+ public static final char COMMENT_CHAR='#';
+
+ // Some well known configuration properties names and values
+ public static final String BANNER_CONFIG_PROP="Banner";
+ public static final String COMPRESSION_PROP="Compression";
+ public static final String DEFAULT_COMPRESSION=CompressionConfigValue.NO.getName();
+ public static final String ALLOW_TCP_FORWARDING_CONFIG_PROP="AllowTcpForwarding";
+ public static final String DEFAULT_TCP_FORWARDING="yes";
+ public static final boolean DEFAULT_TCP_FORWARDING_VALUE=parseBooleanValue(DEFAULT_TCP_FORWARDING);
+ public static final String ALLOW_AGENT_FORWARDING_CONFIG_PROP="AllowAgentForwarding";
+ public static final String DEFAULT_AGENT_FORWARDING="yes";
+ public static final boolean DEFAULT_AGENT_FORWARDING_VALUE=parseBooleanValue(DEFAULT_AGENT_FORWARDING);
+ public static final String ALLOW_X11_FORWARDING_CONFIG_PROP="X11Forwarding";
+ public static final String DEFAULT_X11_FORWARDING="yes";
+ public static final boolean DEFAULT_X11_FORWARDING_VALUE=parseBooleanValue(DEFAULT_X11_FORWARDING);
+ public static final String MAX_SESSIONS_CONFIG_PROP="MaxSessions";
+ public static final int DEFAULT_MAX_SESSIONS=10;
+ public static final String HOST_KEY_CONFIG_PROP="HostKey";
+ public static final String PASSWORD_AUTH_CONFIG_PROP="PasswordAuthentication";
+ public static final String DEFAULT_PASSWORD_AUTH="no";
+ public static final boolean DEFAULT_PASSWORD_AUTH_VALUE=parseBooleanValue(DEFAULT_PASSWORD_AUTH);
+ public static final String LISTEN_ADDRESS_CONFIG_PROP="ListenAddress";
+ public static final String DEFAULT_BIND_ADDRESS="0.0.0.0";
+ public static final String PORT_CONFIG_PROP="Port";
+ public static final int DEFAULT_PORT=22;
+ public static final String KEEP_ALIVE_CONFIG_PROP="TCPKeepAlive";
+ public static final boolean DEFAULT_KEEP_ALIVE=true;
+ public static final String USE_DNS_CONFIG_PROP="UseDNS";
+ // NOTE: the usual default is TRUE
+ public static final boolean DEFAULT_USE_DNS=true;
+ public static final String PUBKEY_AUTH_CONFIG_PROP="PubkeyAuthentication";
+ public static final String DEFAULT_PUBKEY_AUTH="yes";
+ public static final boolean DEFAULT_PUBKEY_AUTH_VALUE=parseBooleanValue(DEFAULT_PUBKEY_AUTH);
+ public static final String AUTH_KEYS_FILE_CONFIG_PROP="AuthorizedKeysFile";
+ public static final String MAX_AUTH_TRIES_CONFIG_PROP="MaxAuthTries";
+ public static final int DEFAULT_MAX_AUTH_TRIES=6;
+ public static final String MAX_STARTUPS_CONFIG_PROP= "MaxStartups";
+ public static final int DEFAULT_MAX_STARTUPS=10;
+ public static final String LOGIN_GRACE_TIME_CONFIG_PROP="LoginGraceTime";
+ public static final long DEFAULT_LOGIN_GRACE_TIME=TimeUnit.SECONDS.toMillis(120);
+ public static final String KEY_REGENERATE_INTERVAL_CONFIG_PROP="KeyRegenerationInterval";
+ public static final long DEFAULT_REKEY_TIME_LIMIT=TimeUnit.HOURS.toMillis(1L);
+ // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
+ public static final String CIPHERS_CONFIG_PROP="Ciphers";
+ public static final String DEFAULT_CIPHERS=
+ "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour";
+ // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
+ public static final String MACS_CONFIG_PROP="MACs";
+ public static final String DEFAULT_MACS=
+ "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-sha1-96,hmac-md5-96,hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,hmac-sha2-512-96";
+ // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
+ public static final String KEX_ALGORITHMS_CONFIG_PROP="KexAlgorithms";
+ public static final String DEFAULT_KEX_ALGORITHMS=
+ "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521"
+ + "," + "diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1"
+ + "," + "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
+ ;
+ // see http://linux.die.net/man/5/ssh_config
+ public static final String HOST_KEY_ALGORITHMS_CONFIG_PROP="HostKeyAlgorithms";
+ // see https://tools.ietf.org/html/rfc5656
+ public static final String DEFAULT_HOST_KEY_ALGORITHMS=
+ KeyPairProvider.SSH_RSA
+ + "," + KeyPairProvider.SSH_DSS
+ ;
+ // see http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html
+ public static final String LOG_LEVEL_CONFIG_PROP="LogLevel";
+ public static final LogLevelValue DEFAULT_LOG_LEVEL=LogLevelValue.INFO;
+ // see https://www.freebsd.org/cgi/man.cgi?query=sshd_config&sektion=5
+ public static final String SYSLOG_FACILITY_CONFIG_PROP="SyslogFacility";
+ public static final SyslogFacilityValue DEFAULT_SYSLOG_FACILITY=SyslogFacilityValue.AUTH;
+ public static final String SUBSYSTEM_CONFIG_PROP="Subsystem";
+
+ public static final Properties readConfigFile(File file) throws IOException {
+ try(InputStream input=new FileInputStream(file)) {
+ return readConfigFile(input, true);
+ }
+ }
+
+ public static final Properties readConfigFile(URL url) throws IOException {
+ try(InputStream input=url.openStream()) {
+ return readConfigFile(input, true);
+ }
+ }
+
+ public static final Properties readConfigFile(String path) throws IOException {
+ try(InputStream input=new FileInputStream(path)) {
+ return readConfigFile(input, true);
+ }
+ }
+
+ public static final Properties readConfigFile(InputStream input, boolean okToClose) throws IOException {
+ try(Reader reader=new InputStreamReader(NoCloseInputStream.resolveInputStream(input, okToClose), StandardCharsets.UTF_8)) {
+ return readConfigFile(reader, true);
+ }
+ }
+
+ public static final Properties readConfigFile(Reader reader, boolean okToClose) throws IOException {
+ try(BufferedReader buf=new BufferedReader(NoCloseReader.resolveReader(reader, okToClose))) {
+ return readConfigFile(buf);
+ }
+ }
+
+ /**
+ * Reads the configuration file contents into a {@link Properties} instance.
+ * <B>Note:</B> multiple keys value are concatenated using a comma - it is up to
+ * the caller to know which keys are expected to have multiple values and handle
+ * the split accordingly
+ * @param rdr The {@link BufferedReader} for reading the file
+ * @return The read properties
+ * @throws IOException If failed to read or malformed content
+ */
+ public static final Properties readConfigFile(BufferedReader rdr) throws IOException {
+ Properties props=new Properties();
+ int lineNumber=1;
+ for (String line=rdr.readLine(); line != null; line=rdr.readLine(), lineNumber++) {
+ line = GenericUtils.trimToEmpty(line);
+ if (GenericUtils.isEmpty(line)) {
+ continue;
+ }
+
+ int pos=line.indexOf(COMMENT_CHAR);
+ if (pos == 0) {
+ continue;
+ }
+
+ if (pos > 0) {
+ line = line.substring(0, pos);
+ line = line.trim();
+ }
+
+ /*
+ * Some options use '=', others use ' ' - try both
+ * NOTE: we do not validate the format for each option separately
+ */
+ if ((pos=line.indexOf(' ')) < 0) {
+ pos = line.indexOf('=');
+ }
+
+ if (pos < 0) {
+ throw new StreamCorruptedException("No delimiter at line " + lineNumber + ": " + line);
+ }
+
+ String key=line.substring(0, pos);
+ String value=line.substring(pos + 1).trim();
+ // see if need to concatenate multi-valued keys
+ String prev=props.getProperty(key);
+ if (!GenericUtils.isEmpty(prev)) {
+ value = prev + "," + value;
+ }
+
+ props.setProperty(key, value);
+ }
+
+ return props;
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @param name The property name
+ * @param defaultValue The default value to return if the specified property
+ * does not exist in the properties map or is an empty string
+ * @return The resolved property
+ * @throws NumberFormatException if malformed value
+ */
+ public static final long getLongProperty(Properties props, String name, long defaultValue) {
+ String value = (props == null) ? null : props.getProperty(name);
+ if (GenericUtils.isEmpty(value)) {
+ return defaultValue;
+ } else {
+ return Long.parseLong(value);
+ }
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @param name The property name
+ * @return The {@link Long} value or {@code null} if property not found or
+ * empty string
+ * @throws NumberFormatException if malformed value
+ */
+ public static final Long getLong(Properties props, String name) {
+ String value = (props == null) ? null : props.getProperty(name);
+ if (GenericUtils.isEmpty(value)) {
+ return null;
+ } else {
+ return Long.valueOf(value);
+ }
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @param name The property name
+ * @param defaultValue The default value to return if the specified property
+ * does not exist in the properties map or is an empty string
+ * @return The resolved property
+ * @throws NumberFormatException if malformed value
+ */
+ public static final int getIntProperty(Properties props, String name, int defaultValue) {
+ String value = (props == null) ? null : props.getProperty(name);
+ if (GenericUtils.isEmpty(value)) {
+ return defaultValue;
+ } else {
+ return Integer.parseInt(value);
+ }
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @param name The property name
+ * @return The {@link Integer} value or {@code null} if property not found or
+ * empty string
+ * @throws NumberFormatException if malformed value
+ */
+ public static final Integer getInteger(Properties props, String name) {
+ String value = (props == null) ? null : props.getProperty(name);
+ if (GenericUtils.isEmpty(value)) {
+ return null;
+ } else {
+ return Integer.valueOf(value);
+ }
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @param name The property name
+ * @param defaultValue The default value to return if the specified property
+ * does not exist in the properties map or is an empty string
+ * @return The resolved property
+ * @throws NumberFormatException if malformed value
+ */
+ public static final boolean getBooleanProperty(Properties props, String name, boolean defaultValue) {
+ String value = (props == null) ? null : props.getProperty(name);
+ if (GenericUtils.isEmpty(value)) {
+ return defaultValue;
+ } else {
+ return parseBooleanValue(value);
+ }
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @param name The property name
+ * @return The {@link Boolean} value or {@code null} if property not found or
+ * empty string
+ * @throws NumberFormatException if malformed value
+ */
+ public static final Boolean getBoolean(Properties props, String name) {
+ String value = (props == null) ? null : props.getProperty(name);
+ if (GenericUtils.isEmpty(value)) {
+ return null;
+ } else {
+ return Boolean.valueOf(parseBooleanValue(value));
+ }
+ }
+
+ /**
+ * @param v The value to parse - if {@code null}/empty then the default
+ * value is returned, otherwise {@link #parseBooleanValue(String)} is used
+ * @param defaultValue The default value to return if {@code null}/empty
+ * input string
+ * @return The result
+ */
+ public static final boolean parseBooleanValue(String v, boolean defaultValue) {
+ if (GenericUtils.isEmpty(v)) {
+ return defaultValue;
+ } else {
+ return parseBooleanValue(v);
+ }
+ }
+
+ /**
+ * @param v Checks if the value is "yes", "y"
+ * or "on" or "true".
+ * @return The result - <B>Note:</B> {@code null}/empty values are
+ * intrepreted as {@code false}
+ */
+ public static final boolean parseBooleanValue(String v) {
+ if ("yes".equalsIgnoreCase(v)
+ || "y".equalsIgnoreCase(v)
+ || "on".equalsIgnoreCase(v)
+ || "true".equalsIgnoreCase(v)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @return A {@link List} of all the {@link NamedFactory}-ies whose
+ * name appears in the string and represent a built-in cipher. Any
+ * unknown name is <U>ignored</U>. The order of the returned result
+ * is the same as the original order - bar the unknown ciphers.
+ * <B>Note:</B> it is up to caller to ensure that the list does not
+ * contain duplicates
+ * @see #CIPHERS_CONFIG_PROP
+ * @see BuiltinCiphers#parseCiphersList(String)
+ */
+ public static final List<NamedFactory<Cipher>> getCiphers(Properties props) {
+ return BuiltinCiphers.parseCiphersList((props == null) ? null : props.getProperty(CIPHERS_CONFIG_PROP));
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @return A {@link List} of all the {@link NamedFactory}-ies whose
+ * name appears in the string and represent a built-in MAC. Any
+ * unknown name is <U>ignored</U>. The order of the returned result
+ * is the same as the original order - bar the unknown MACs.
+ * <B>Note:</B> it is up to caller to ensure that the list does not
+ * contain duplicates
+ * @see #MACS_CONFIG_PROP
+ * @see BuiltinMacs#parseMacsList(String)
+ */
+ public static final List<NamedFactory<Mac>> getMacs(Properties props) {
+ return BuiltinMacs.parseMacsList((props == null) ? null : props.getProperty(MACS_CONFIG_PROP));
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @return A {@link List} of all the {@link NamedFactory} whose
+ * name appears in the string and represent a built-in signature. Any
+ * unknown name is <U>ignored</I>. The order of the returned result
+ * is the same as the original order - bar the unknown signatures.
+ * <B>Note:</B> it is up to caller to ensure that the list does not
+ * contain duplicates
+ * @see #HOST_KEY_ALGORITHMS_CONFIG_PROP
+ * @see BuiltinSignatures#parseSignatureList(String)
+ */
+ public static final List<NamedFactory<Signature>> getSignatures(Properties props) {
+ return BuiltinSignatures.parseSignatureList((props == null) ? null : props.getProperty(HOST_KEY_ALGORITHMS_CONFIG_PROP));
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @return A {@link List} of all the {@link DHFactory}-ies whose
+ * name appears in the string and represent a built-in value. Any
+ * unknown name is <U>ignored</U>. The order of the returned result
+ * is the same as the original order - bar the unknown ones.
+ * <B>Note:</B> it is up to caller to ensure that the list does not
+ * contain duplicates
+ * @see #KEX_ALGORITHMS_CONFIG_PROP
+ * @see BuiltinDHFactories#parseDHFactoriesList(String)
+ */
+ public static final List<DHFactory> getKexFactories(Properties props) {
+ return BuiltinDHFactories.parseDHFactoriesList((props == null) ? null : props.getProperty(KEX_ALGORITHMS_CONFIG_PROP));
+ }
+
+ /**
+ * @param props The {@link Properties} - ignored if {@code null}/empty
+ * @return The matching {@link NamedFactory} for the configured value.
+ * {@code null} if no configuration or unknown name specified
+ */
+ public static final NamedFactory<Compression> getCompression(Properties props) {
+ return CompressionConfigValue.fromName((props == null) ? null : props.getProperty(COMPRESSION_PROP));
+ }
+
+ /**
+ * <P>Configures an {@link AbstractFactoryManager} with the values read from
+ * some configuration. Currently it configures:</P></BR>
+ * <UL>
+ * <LI>The {@link Cipher}s - via the {@link #CIPHERS_CONFIG_PROP}</LI>
+ * <LI>The {@link Mac}s - via the {@link #MACS_CONFIG_PROP}</LI>
+ * <LI>The {@link Signature}s - via the {@link #HOST_KEY_ALGORITHMS_CONFIG_PROP}</LI>
+ * <LI>The {@link Compression} - via the {@link #COMPRESSION_PROP}</LI>
+ * </UL>
+ * @param manager The {@link AbstractFactoryManager} to configure
+ * @param props The {@link Properties} to use for configuration - <B>Note:</B>
+ * if any known configuration value has a default and does not appear in the
+ * properties, the default is used
+ * @return The configured manager
+ */
+ public static final <M extends AbstractFactoryManager> M configure(M manager, Properties props) {
+ ValidateUtils.checkNotNull(manager, "No manager to configure", GenericUtils.EMPTY_OBJECT_ARRAY);
+ ValidateUtils.checkNotNull(props, "No properties to configure", GenericUtils.EMPTY_OBJECT_ARRAY);
+
+ {
+ String value=props.getProperty(HOST_KEY_ALGORITHMS_CONFIG_PROP, DEFAULT_HOST_KEY_ALGORITHMS);
+ manager.setSignatureFactories(ValidateUtils.checkNotNullAndNotEmpty(BuiltinSignatures.parseSignatureList(value), "Bad signatures: %s", value));
+ }
+
+ {
+ String value=props.getProperty(MACS_CONFIG_PROP, DEFAULT_MACS);
+ manager.setMacFactories(ValidateUtils.checkNotNullAndNotEmpty(BuiltinMacs.parseMacsList(value), "Bad MAC(s): %s", value));
+ }
+
+ {
+ String value=props.getProperty(CIPHERS_CONFIG_PROP, DEFAULT_CIPHERS);
+ manager.setCipherFactories(ValidateUtils.checkNotNullAndNotEmpty(BuiltinCiphers.parseCiphersList(value), "Bad ciphers(s): %s", value));
+ }
+
+ {
+ String value=props.getProperty(COMPRESSION_PROP, DEFAULT_COMPRESSION);
+ manager.setCompressionFactories(
+ Collections.<NamedFactory<Compression>>singletonList(
+ ValidateUtils.checkNotNull(CompressionConfigValue.fromName(value), "Bad compression: %s", value)));
+ }
+
+ return manager;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java b/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
new file mode 100644
index 0000000..7ae4b36
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/SyslogFacilityValue.java
@@ -0,0 +1,50 @@
+/*
+ * 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.config;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <A HREF="https://www.freebsd.org/cgi/man.cgi?query=sshd_config&sektion=5"><I>SyslogFacility</I> configuration value</A>
+ */
+public enum SyslogFacilityValue {
+ DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7;
+
+ public static final Set<SyslogFacilityValue> VALUES=
+ Collections.unmodifiableSet(EnumSet.allOf(SyslogFacilityValue.class));
+ public static final SyslogFacilityValue fromName(String n) {
+ if (GenericUtils.isEmpty(n)) {
+ return null;
+ }
+
+ for (SyslogFacilityValue f : VALUES) {
+ if (n.equalsIgnoreCase(f.name())) {
+ return f;
+ }
+ }
+
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java b/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
new file mode 100644
index 0000000..6430325
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/config/TimeValueConfig.java
@@ -0,0 +1,175 @@
+/*
+ * 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.config;
+
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.common.util.GenericUtils;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ * @see <A HREF="http://unixhelp.ed.ac.uk/CGI/man-cgi?sshd_config+5">Time formats for SSH configuration values</A>
+ */
+public enum TimeValueConfig {
+ SECONDS('s', 'S', TimeUnit.SECONDS.toMillis(1L)),
+ MINUTES('m', 'M', TimeUnit.MINUTES.toMillis(1L)),
+ HOURS('h', 'H', TimeUnit.HOURS.toMillis(1L)),
+ DAYS('d', 'D', TimeUnit.DAYS.toMillis(1L)),
+ WEEKS('w', 'W', TimeUnit.DAYS.toMillis(7L));
+
+ private final char loChar, hiChar;
+ public final char getLowerCaseValue() {
+ return loChar;
+ }
+
+ public final char getUpperCaseValue() {
+ return hiChar;
+ }
+
+ private final long interval;
+ public final long getInterval() {
+ return interval;
+ }
+
+ TimeValueConfig(char lo, char hi, long duration) {
+ loChar = lo;
+ hiChar = hi;
+ interval = duration;
+ }
+
+ public static final Set<TimeValueConfig> VALUES=
+ Collections.unmodifiableSet(EnumSet.allOf(TimeValueConfig.class));
+ public static final TimeValueConfig fromValueChar(char ch) {
+ if ((ch <= ' ') || (ch >= 0x7F)) {
+ return null;
+ }
+
+ for (TimeValueConfig v : VALUES) {
+ if ((v.getLowerCaseValue() == ch) || (v.getUpperCaseValue() == ch)) {
+ return v;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param s A time specification
+ * @return The specified duration in milliseconds
+ * @see #parse(String)
+ * @see #durationOf(Map)
+ */
+ public static final long durationOf(String s) {
+ Map<TimeValueConfig,Long> spec=parse(s);
+ return durationOf(spec);
+ }
+
+ /**
+ * @param s An input time specification containing possibly mixed numbers
+ * and units - e.g., {@code 3h10m} to indicate 3 hours and 10 minutes
+ * @return A {@link Map} specifying for each time unit its count
+ * @throws NumberFormatException If bad numbers found - e.g., negative counts
+ * @throws IllegalArgumentException If bad format - e.g., unknown unit
+ */
+ public static final Map<TimeValueConfig,Long> parse(String s) throws NumberFormatException, IllegalArgumentException {
+ if (GenericUtils.isEmpty(s)) {
+ return Collections.emptyMap();
+ }
+
+ int lastPos=0;
+ Map<TimeValueConfig,Long> spec=new EnumMap<TimeValueConfig,Long>(TimeValueConfig.class);
+ for (int curPos=0; curPos < s.length(); curPos++) {
+ char ch=s.charAt(curPos);
+ if ((ch >= '0') && (ch <= '9')) {
+ continue;
+ }
+
+ if (curPos <= lastPos) {
+ throw new IllegalArgumentException("parse(" + s + ") missing count value at index=" + curPos);
+ }
+
+ TimeValueConfig c=fromValueChar(ch);
+ if (c == null) {
+ throw new IllegalArgumentException("parse(" + s + ") unknown time value character: " + String.valueOf(ch));
+ }
+
+ String v=s.substring(lastPos, curPos);
+ Long count=Long.valueOf(v);
+ if (count.longValue() < 0L) {
+ throw new IllegalArgumentException("parse(" + s + ") negative count (" + v + ") for " + c.name());
+ }
+
+ Long prev=spec.put(c, count);
+ if (prev != null) {
+ throw new IllegalArgumentException("parse(" + s + ") " + c.name() + " value re-specified: current=" + count + ", previous=" + prev);
+ }
+
+ if ((lastPos=curPos+1) >= s.length()) {
+ break;
+ }
+ }
+
+ if (lastPos < s.length()) {
+ String v=s.substring(lastPos);
+ Long count=Long.valueOf(v);
+ if (count.longValue() < 0L) {
+ throw new IllegalArgumentException("parse(" + s + ") negative count (" + v + ") for last component");
+ }
+
+ Long prev=spec.put(SECONDS, count);
+ if (prev != null) {
+ throw new IllegalArgumentException("parse(" + s + ") last component (" + SECONDS.name() + ") value re-specified: current=" + count + ", previous=" + prev);
+ }
+ }
+
+ return spec;
+ }
+
+ /**
+ * @param spec The {@link Map} specifying the count for each {@link TimeValueConfig}
+ * @return The total duration in milliseconds
+ * @throws IllegalArgumentException If negative count for a time unit
+ */
+ public static final long durationOf(Map<TimeValueConfig,? extends Number> spec) throws IllegalArgumentException {
+ if (GenericUtils.isEmpty(spec)) {
+ return (-1L);
+ }
+
+ long total=0L;
+ for (Map.Entry<TimeValueConfig,? extends Number> se : spec.entrySet()) {
+ TimeValueConfig v=se.getKey();
+ Number c=se.getValue();
+ long factor=c.longValue();
+ if (factor < 0L) {
+ throw new IllegalArgumentException("valueOf(" + spec + ") bad factor (" + c + ") for " + v.name());
+ }
+
+ long added=v.getInterval() * factor;
+ total += added;
+ }
+
+ return total;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java b/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
index bb57f4c..8b342ba 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/digest/BuiltinDigests.java
@@ -71,11 +71,15 @@ public enum BuiltinDigests implements NamedFactory<Digest> {
return factoryName;
}
+ @Override
+ public final String toString() {
+ return getName();
+ }
+
BuiltinDigests(String facName) {
factoryName = facName;
}
-
public static final Set<BuiltinDigests> VALUES =
Collections.unmodifiableSet(EnumSet.allOf(BuiltinDigests.class));
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
index 7dc630d..452dc5f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/BuiltinDHFactories.java
@@ -20,8 +20,12 @@
package org.apache.sshd.common.kex;
import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.List;
import java.util.Set;
import org.apache.sshd.common.OptionalFeature;
@@ -29,6 +33,7 @@ import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.digest.BuiltinDigests;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.common.util.ValidateUtils;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
@@ -149,6 +154,11 @@ public enum BuiltinDHFactories implements DHFactory, OptionalFeature {
return true;
}
+ @Override
+ public final String toString() {
+ return getName();
+ }
+
BuiltinDHFactories(String name) {
factoryName = name;
}
@@ -180,6 +190,38 @@ public enum BuiltinDHFactories implements DHFactory, OptionalFeature {
return false;
}
+ /**
+ * @param factories A comma-separated list of ciphers' names - ignored
+ * if {@code null}/empty
+ * @return A {@link List} of all the {@link DHFactory}-ies whose
+ * name appears in the string and represent a built-in value. Any
+ * unknown name is <U>ignored</U>. The order of the returned result
+ * is the same as the original order - bar the unknown ones.
+ * <B>Note:</B> it is up to caller to ensure that the list does not
+ * contain duplicates
+ */
+ public static final List<DHFactory> parseDHFactoriesList(String factories) {
+ return parseDHFactoriesList(GenericUtils.split(factories, ','));
+ }
+
+ public static final List<DHFactory> parseDHFactoriesList(String ... factories) {
+ return parseDHFactoriesList(GenericUtils.isEmpty((Object[]) factories) ? Collections.<String>emptyList() : Arrays.asList(factories));
+ }
+
+ public static final List<DHFactory> parseDHFactoriesList(Collection<String> factories) {
+ if (GenericUtils.isEmpty(factories)) {
+ return Collections.emptyList();
+ }
+
+ List<DHFactory> result=new ArrayList<DHFactory>(factories.size());
+ for (String name : factories) {
+ DHFactory c=ValidateUtils.checkNotNull(fromFactoryName(name), "Unknown factory name (%s) in %s", name, factories);
+ result.add(c);
+ }
+
+ return result;
+ }
+
public static final class Constants {
public static final String DIFFIE_HELLMAN_GROUP1_SHA1 = "diffie-hellman-group1-sha1";
public static final String DIFFIE_HELLMAN_GROUP14_SHA1 = "diffie-hellman-group14-sha1";
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java b/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
index 75f6c4c..e8d9239 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/mac/BuiltinMacs.java
@@ -19,8 +19,12 @@
package org.apache.sshd.common.mac;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.List;
import java.util.Set;
import org.apache.sshd.common.Digest;
@@ -28,6 +32,7 @@ import org.apache.sshd.common.Mac;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.OptionalFeature;
import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
/**
* Provides easy access to the currently implemented macs
@@ -84,6 +89,11 @@ public enum BuiltinMacs implements NamedFactory<Mac>, OptionalFeature {
return true;
}
+ @Override
+ public final String toString() {
+ return getName();
+ }
+
BuiltinMacs(String facName) {
factoryName = facName;
}
@@ -111,7 +121,7 @@ public enum BuiltinMacs implements NamedFactory<Mac>, OptionalFeature {
}
/**
- * @param factory The {@link org.apache.sshd.common.NamedFactory} for the cipher - ignored if {@code null}
+ * @param factory The {@link org.apache.sshd.common.NamedFactory} for the Mac - ignored if {@code null}
* @return The matching {@link org.apache.sshd.common.mac.BuiltinMacs} whose factory name matches
* (case <U>insensitive</U>) the digest factory name
* @see #fromFactoryName(String)
@@ -143,6 +153,38 @@ public enum BuiltinMacs implements NamedFactory<Mac>, OptionalFeature {
return null;
}
+ /**
+ * @param macs A comma-separated list of MACs' names - ignored
+ * if {@code null}/empty
+ * @return A {@link List} of all the {@link NamedFactory}-ies whose
+ * name appears in the string and represent a built-in MAC. Any
+ * unknown name is <U>ignored</U>. The order of the returned result
+ * is the same as the original order - bar the unknown MACs.
+ * <B>Note:</B> it is up to caller to ensure that the list does not
+ * contain duplicates
+ */
+ public static final List<NamedFactory<Mac>> parseMacsList(String macs) {
+ return parseMacsList(GenericUtils.split(macs, ','));
+ }
+
+ public static final List<NamedFactory<Mac>> parseMacsList(String ... macs) {
+ return parseMacsList(GenericUtils.isEmpty((Object[]) macs) ? Collections.<String>emptyList() : Arrays.asList(macs));
+ }
+
+ public static final List<NamedFactory<Mac>> parseMacsList(Collection<String> macs) {
+ if (GenericUtils.isEmpty(macs)) {
+ return Collections.emptyList();
+ }
+
+ List<NamedFactory<Mac>> result=new ArrayList<NamedFactory<Mac>>(macs.size());
+ for (String name : macs) {
+ BuiltinMacs m=ValidateUtils.checkNotNull(fromFactoryName(name), "Bad factory name (%s) in %s", name, macs);
+ result.add(m);
+ }
+
+ return result;
+ }
+
public static final class Constants {
public static final String HMAC_MD5 = "hmac-md5";
public static final String HMAC_MD5_96 = "hmac-md5-96";
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
index 86c85ad..2aee77d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/signature/BuiltinSignatures.java
@@ -20,8 +20,12 @@
package org.apache.sshd.common.signature;
import java.security.spec.ECParameterSpec;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.List;
import java.util.Set;
import org.apache.sshd.common.Digest;
@@ -32,10 +36,10 @@ import org.apache.sshd.common.Signature;
import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.SecurityUtils;
+import org.apache.sshd.common.util.ValidateUtils;
/**
- * Provides easy access to the currently implemented macs
- *
+ * Provides easy access to the currently implemented signatures
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public enum BuiltinSignatures implements NamedFactory<Signature>, OptionalFeature {
@@ -103,6 +107,11 @@ public enum BuiltinSignatures implements NamedFactory<Signature>, OptionalFeatur
return factoryName;
}
+ @Override
+ public final String toString() {
+ return getName();
+ }
+
BuiltinSignatures(String facName) {
factoryName = facName;
}
@@ -166,4 +175,36 @@ public enum BuiltinSignatures implements NamedFactory<Signature>, OptionalFeatur
return null;
}
+
+ /**
+ * @param sigs A comma-separated list of signatures' names - ignored
+ * if {@code null}/empty
+ * @return A {@link List} of all the {@link NamedFactory} whose
+ * name appears in the string and represent a built-in signature. Any
+ * unknown name is <U>ignored</I>. The order of the returned result
+ * is the same as the original order - bar the unknown signatures.
+ * <B>Note:</B> it is up to caller to ensure that the list does not
+ * contain duplicates
+ */
+ public static final List<NamedFactory<Signature>> parseSignatureList(String sigs) {
+ return parseSignatureList(GenericUtils.split(sigs, ','));
+ }
+
+ public static final List<NamedFactory<Signature>> parseSignatureList(String ... sigs) {
+ return parseSignatureList(GenericUtils.isEmpty((Object[]) sigs) ? Collections.<String>emptyList() : Arrays.asList(sigs));
+ }
+
+ public static final List<NamedFactory<Signature>> parseSignatureList(Collection<String> sigs) {
+ if (GenericUtils.isEmpty(sigs)) {
+ return Collections.emptyList();
+ }
+
+ List<NamedFactory<Signature>> result=new ArrayList<NamedFactory<Signature>>(sigs.size());
+ for (String name : sigs) {
+ BuiltinSignatures s=ValidateUtils.checkNotNull(fromFactoryName(name), "Bad factory name (%s) in %s", name, sigs);
+ result.add(s);
+ }
+
+ return result;
+ }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
index e728c8c..345916a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
@@ -23,13 +23,18 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class GenericUtils {
+ public static final String[] EMPTY_STRING_ARRAY={ };
+ public static final Object[] EMPTY_OBJECT_ARRAY={ };
public static final String trimToEmpty(String s) {
if (s == null) {
@@ -54,6 +59,91 @@ public class GenericUtils {
return false;
}
}
+
+ // a List would be better, but we want to be compatible with String.split(...)
+ public static final String[] split(String s, char ch) {
+ if (isEmpty(s)) {
+ return EMPTY_STRING_ARRAY;
+ }
+
+ int lastPos=0, curPos=s.indexOf(ch);
+ if (curPos < 0) {
+ return new String[] { s };
+ }
+
+ Collection<String> values=new LinkedList<String>();
+ do {
+ String v=s.substring(lastPos, curPos);
+ values.add(v);
+
+ // skip separator
+ if ((lastPos = curPos + 1) >= s.length()) {
+ break;
+ }
+
+ if ((curPos = s.indexOf(ch, lastPos)) < lastPos) {
+ break; // no more separators
+ }
+ } while(curPos < s.length());
+
+ // check if any leftovers
+ if (lastPos < s.length()) {
+ String v=s.substring(lastPos);
+ values.add(v);
+ }
+
+ return values.toArray(new String[values.size()]);
+ }
+
+ public static final <T> String join(T[] values, char ch) {
+ return join(isEmpty(values) ? Collections.<T>emptyList() : Arrays.asList(values), ch);
+ }
+
+ public static final String join(Iterable<?> iter, char ch) {
+ return join((iter == null) ? null : iter.iterator(), ch);
+ }
+
+ public static final String join(Iterator<?> iter, char ch) {
+ if ((iter == null) || (!iter.hasNext())) {
+ return "";
+ }
+
+ StringBuilder sb=new StringBuilder();
+ do { // we already asked hasNext...
+ Object o=iter.next();
+ if (sb.length() > 0) {
+ sb.append(ch);
+ }
+ sb.append(Objects.toString(o));
+ } while(iter.hasNext());
+
+ return sb.toString();
+ }
+
+ public static final <T> String join(T[] values, CharSequence sep) {
+ return join(isEmpty(values) ? Collections.<T>emptyList() : Arrays.asList(values), sep);
+ }
+
+ public static final String join(Iterable<?> iter, CharSequence sep) {
+ return join((iter == null) ? null : iter.iterator(), sep);
+ }
+
+ public static final String join(Iterator<?> iter, CharSequence sep) {
+ if ((iter == null) || (!iter.hasNext())) {
+ return "";
+ }
+
+ StringBuilder sb=new StringBuilder();
+ do { // we already asked hasNext...
+ Object o=iter.next();
+ if (sb.length() > 0) {
+ sb.append(sep);
+ }
+ sb.append(Objects.toString(o));
+ } while(iter.hasNext());
+
+ return sb.toString();
+ }
public static final int size(Collection<?> c) {
if (c == null) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/util/LoggingFilterOutputStream.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/LoggingFilterOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/util/LoggingFilterOutputStream.java
deleted file mode 100644
index 772315f..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/LoggingFilterOutputStream.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.common.util;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.slf4j.Logger;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class LoggingFilterOutputStream extends FilterOutputStream {
-
- private final String msg;
- private final Logger log;
-
- public LoggingFilterOutputStream(OutputStream out, String msg, Logger log) {
- super(out);
- this.msg = msg;
- this.log = log;
- }
-
- @Override
- public void write(int b) throws IOException {
- byte[] d = new byte[1];
- d[0] = (byte) b;
- write(d, 0, 1);
- }
-
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- if (log != null && log.isTraceEnabled()) {
- log.trace("{} {}", msg, BufferUtils.printHex(b, off, len));
- }
- out.write(b, off, len);
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/util/NoCloseInputStream.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/NoCloseInputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/util/NoCloseInputStream.java
deleted file mode 100644
index 6692ff3..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/NoCloseInputStream.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.common.util;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class NoCloseInputStream extends FilterInputStream {
-
- public NoCloseInputStream(InputStream in) {
- super(in);
- }
-
- @Override
- public void close() throws IOException {
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/util/NoCloseOutputStream.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/NoCloseOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/util/NoCloseOutputStream.java
deleted file mode 100644
index 4b7e273..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/NoCloseOutputStream.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.common.util;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * TODO Add javadoc
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class NoCloseOutputStream extends FilterOutputStream {
-
- public NoCloseOutputStream(OutputStream out) {
- super(out);
- }
-
-
- @Override
- public void close() throws IOException {
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
index 2d7685b..f856ea9 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/ValidateUtils.java
@@ -26,43 +26,43 @@ import java.util.Map;
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class ValidateUtils {
- public static final <T> T checkNotNull(T t, String message) {
+ public static final <T> T checkNotNull(T t, String message, Object ... args) {
if (t == null) {
- throw new IllegalStateException(String.format(message, t));
+ throw new IllegalStateException(String.format(message, args));
}
return t;
}
- public static final String checkNotNullAndNotEmpty(String t, String message) {
- t = checkNotNull(t, message).trim();
+ public static final String checkNotNullAndNotEmpty(String t, String message, Object ... args) {
+ t = checkNotNull(t, message, args).trim();
if (t.isEmpty()) {
- throw new IllegalArgumentException(String.format(message, t));
+ throw new IllegalArgumentException(String.format(message, args));
}
return t;
}
- public static final <K,V,M extends Map<K,V>> M checkNotNullAndNotEmpty(M t, String message) {
- t = checkNotNull(t, message);
+ public static final <K,V,M extends Map<K,V>> M checkNotNullAndNotEmpty(M t, String message, Object ... args) {
+ t = checkNotNull(t, message, args);
if (GenericUtils.size(t) <= 0) {
- throw new IllegalArgumentException(String.format(message, t));
+ throw new IllegalArgumentException(String.format(message, args));
}
return t;
}
- public static final <T,C extends Collection<T>> C checkNotNullAndNotEmpty(C t, String message) {
- t = checkNotNull(t, message);
+ public static final <T,C extends Collection<T>> C checkNotNullAndNotEmpty(C t, String message, Object ... args) {
+ t = checkNotNull(t, message, args);
if (GenericUtils.size(t) <= 0) {
- throw new IllegalArgumentException(String.format(message, t));
+ throw new IllegalArgumentException(String.format(message, args));
}
return t;
}
- public static final <T> T[] checkNotNullAndNotEmpty(T[] t, String message) {
- t = checkNotNull(t, message);
+ public static final <T> T[] checkNotNullAndNotEmpty(T[] t, String message, Object ... args) {
+ t = checkNotNull(t, message, args);
if (GenericUtils.length(t) <= 0) {
- throw new IllegalArgumentException(String.format(message, t));
+ throw new IllegalArgumentException(String.format(message, t, args));
}
return t;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/util/io/LoggingFilterOutputStream.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/io/LoggingFilterOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/util/io/LoggingFilterOutputStream.java
new file mode 100644
index 0000000..ab1676e
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/io/LoggingFilterOutputStream.java
@@ -0,0 +1,58 @@
+/*
+ * 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.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.sshd.common.util.BufferUtils;
+import org.slf4j.Logger;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class LoggingFilterOutputStream extends FilterOutputStream {
+
+ private final String msg;
+ private final Logger log;
+
+ public LoggingFilterOutputStream(OutputStream out, String msg, Logger log) {
+ super(out);
+ this.msg = msg;
+ this.log = log;
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ byte[] d = new byte[1];
+ d[0] = (byte) b;
+ write(d, 0, 1);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ if (log != null && log.isTraceEnabled()) {
+ log.trace("{} {}", msg, BufferUtils.printHex(b, off, len));
+ }
+ out.write(b, off, len);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/99ebcc95/sshd-core/src/main/java/org/apache/sshd/common/util/io/NoCloseInputStream.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/io/NoCloseInputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/util/io/NoCloseInputStream.java
new file mode 100644
index 0000000..2840c95
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/io/NoCloseInputStream.java
@@ -0,0 +1,47 @@
+/*
+ * 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.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class NoCloseInputStream extends FilterInputStream {
+ public NoCloseInputStream(InputStream in) {
+ super(in);
+ }
+
+ @Override
+ public void close() throws IOException {
+ // ignored
+ }
+
+ public static final InputStream resolveInputStream(InputStream input, boolean okToClose) {
+ if ((input == null) || okToClose) {
+ return input;
+ } else {
+ return new NoCloseInputStream(input);
+ }
+ }
+}