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 2020/12/11 08:51:29 UTC
[mina-sshd] 04/15: [SSHD-1109] Provide full slf4j logger
capabilities to CliLogger + use it in all CLI classes
This is an automated email from the ASF dual-hosted git repository.
lgoldstein pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit b844cdf48ed3e21ba7438ae0bc99221037a78e8a
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Thu Dec 10 07:36:49 2020 +0200
[SSHD-1109] Provide full slf4j logger capabilities to CliLogger + use it in all CLI classes
---
CHANGES.md | 1 +
.../main/java/org/apache/sshd/cli/CliLogger.java | 147 +++++++++++++++-
.../main/java/org/apache/sshd/cli/CliSupport.java | 185 ++++-----------------
.../org/apache/sshd/cli/client/ScpCommandMain.java | 36 ++--
.../apache/sshd/cli/client/SftpCommandMain.java | 17 +-
.../sshd/cli/client/SshClientCliSupport.java | 27 +--
.../org/apache/sshd/cli/client/SshClientMain.java | 31 ++--
.../sshd/cli/server/SshServerCliSupport.java | 23 ++-
.../org/apache/sshd/cli/server/SshServerMain.java | 16 +-
.../helper/ScpCommandTransferEventListener.java | 37 +++--
.../server/helper/ServerEventListenerHelper.java | 43 +----
.../helper/ServerPortForwardingEventListener.java | 37 +++--
.../helper/SftpServerSubSystemEventListener.java | 33 ++--
.../apache/sshd/cli/client/ChannelExecMain.java | 4 +-
.../org/apache/sshd/cli/server/SshFsMounter.java | 3 +-
.../sshd/common/util/io/NullPrintStream.java | 172 +++++++++++++++++++
.../common/util/logging/AbstractLoggingBean.java | 12 +-
.../sshd/common/util/logging/LoggerSkeleton.java | 169 +++++++++++++++++++
.../sshd/common/util/logging/LoggingUtils.java | 19 +++
.../util/logging/SimplifiedLoggerSkeleton.java | 103 ++++++++++++
sshd-mina/pom.xml | 1 +
21 files changed, 818 insertions(+), 298 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 054fcf4..10cf108 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -18,6 +18,7 @@
* [SSHD-1085](https://issues.apache.org/jira/browse/SSHD-1085) Added `CliLogger` + more verbosity on `SshClientMain`
* [SSHD-1109](https://issues.apache.org/jira/browse/SSHD-1109) Route tests JUL logging via SLF4JBridgeHandler
+* [SSHD-1109](https://issues.apache.org/jira/browse/SSHD-1109) Provide full slf4j logger capabilities to CliLogger + use it in all CLI classes
## Behavioral changes and enhancements
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/CliLogger.java b/sshd-cli/src/main/java/org/apache/sshd/cli/CliLogger.java
index 904bde8..04c2019 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/CliLogger.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/CliLogger.java
@@ -20,24 +20,38 @@
package org.apache.sshd.cli;
import java.io.PrintStream;
+import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.logging.Level;
+import org.apache.sshd.common.PropertyResolver;
+import org.apache.sshd.common.PropertyResolverUtils;
+import org.apache.sshd.common.config.ConfigFileReaderSupport;
+import org.apache.sshd.common.config.LogLevelValue;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.io.NullPrintStream;
import org.apache.sshd.common.util.logging.SimplifiedLog;
+import org.apache.sshd.common.util.logging.SimplifiedLoggerSkeleton;
+import org.slf4j.Logger;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
-public class CliLogger implements SimplifiedLog {
+public class CliLogger extends SimplifiedLoggerSkeleton {
public static final DateFormat LOG_TIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
+ private static final long serialVersionUID = -3785762030194772776L;
+ private static final NullPrintStream NULL_PRINT_STREAM = new NullPrintStream();
+
protected final Level threshold;
protected final PrintStream logStream;
- public CliLogger(Level threshold, PrintStream logStream) {
+ protected CliLogger(String name, Level threshold, PrintStream logStream) {
+ super(name);
+
this.threshold = threshold;
this.logStream = logStream;
}
@@ -49,10 +63,16 @@ public class CliLogger implements SimplifiedLog {
@Override
public void log(Level level, Object msg, Throwable err) {
- if (!isEnabledLevel(level)) {
- return;
+ if (isEnabledLevel(level)) {
+ log(logStream, level, msg, err);
}
+ }
+ public static void log(PrintStream logStream, Level level, Object msg) {
+ log(logStream, level, msg, null);
+ }
+
+ public static void log(PrintStream logStream, Level level, Object msg, Throwable err) {
Date now = new Date();
String time;
synchronized (LOG_TIME_FORMATTER) {
@@ -63,8 +83,123 @@ public class CliLogger implements SimplifiedLog {
.append(' ').append(Thread.currentThread().getName())
.append(' ').append(Objects.toString(msg))
.println();
- if (err != null) {
- err.printStackTrace(logStream);
+ printStackTrace(logStream, err);
+ }
+
+ /**
+ * Looks for the {@link ConfigFileReaderSupport#LOG_LEVEL_CONFIG_PROP} in the options. If found, then uses it as the
+ * result. Otherwise, invokes {@link #resolveLoggingVerbosity(String...)}
+ *
+ * @param resolver The {@code -o} options specified by the user
+ * @param args The command line arguments
+ * @return The resolved verbosity level
+ */
+ public static Level resolveLoggingVerbosity(PropertyResolver resolver, String... args) {
+ String levelValue = PropertyResolverUtils.getString(
+ resolver, ConfigFileReaderSupport.LOG_LEVEL_CONFIG_PROP);
+ if (GenericUtils.isEmpty(levelValue)) {
+ return resolveLoggingVerbosity(args);
}
+
+ LogLevelValue level = LogLevelValue.fromName(levelValue);
+ if (level == null) {
+ throw new IllegalArgumentException(
+ "Unknown " + ConfigFileReaderSupport.LOG_LEVEL_CONFIG_PROP + " option value: " + levelValue);
+ }
+
+ return level.getLoggingLevel();
+ }
+
+ public static Level resolveLoggingVerbosity(String... args) {
+ return resolveLoggingVerbosity(args, GenericUtils.length(args));
+ }
+
+ public static Level resolveLoggingVerbosity(String[] args, int maxIndex) {
+ for (int index = 0; index < maxIndex; index++) {
+ String argName = args[index];
+ if ("-v".equals(argName)) {
+ return Level.INFO;
+ } else if ("-vv".equals(argName)) {
+ return Level.FINE;
+ } else if ("-vvv".equals(argName)) {
+ return Level.FINEST;
+ }
+ }
+
+ return Level.CONFIG;
+ }
+
+ public static Logger resolveSystemLogger(Class<?> clazz, Level threshold) {
+ return resolveSystemLogger(clazz.getName(), threshold);
+ }
+
+ public static Logger resolveSystemLogger(String name, Level threshold) {
+ return resolveLogger(name, threshold, System.out, System.err);
+ }
+
+ public static Logger resolveLogger(Class<?> clazz, Level threshold, PrintStream stdout, PrintStream stderr) {
+ return resolveLogger(clazz.getSimpleName(), threshold, stdout, stderr);
+ }
+
+ public static Logger resolveLogger(String name, Level threshold, PrintStream stdout, PrintStream stderr) {
+ PrintStream logStream = resolvePrintStream(threshold, stdout, stderr);
+ return getLogger(name, threshold, logStream);
+ }
+
+ public static boolean showError(PrintStream stderr, String message) {
+ stderr.append("ERROR: ").println(message);
+ return true;
+ }
+
+ public static boolean isEnabledVerbosityLogging(Level level) {
+ if ((level == null) || Level.OFF.equals(level) || Level.CONFIG.equals(level)
+ || Level.SEVERE.equals(level) || Level.WARNING.equals(level)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static PrintStream resolvePrintStream(Level threshold, PrintStream stdout, PrintStream stderr) {
+ if (isEnabledVerbosityLogging(threshold)) {
+ return Level.INFO.equals(threshold) ? stderr : stdout;
+ } else {
+ return NULL_PRINT_STREAM;
+ }
+ }
+
+ public static <T extends Throwable> T printStackTrace(Appendable out, T reason) {
+ if ((reason == null) || (out == null)) {
+ return reason;
+ }
+
+ if (out instanceof PrintStream) {
+ reason.printStackTrace((PrintStream) out);
+ } else if (out instanceof PrintWriter) {
+ reason.printStackTrace((PrintWriter) out);
+ }
+
+ return reason;
+ }
+
+ public static Logger getSystemLogger(Class<?> clazz, Level threshold) {
+ return getSystemLogger(clazz.getName(), threshold);
+ }
+
+ public static Logger getSystemLogger(String name, Level threshold) {
+ return getLogger(name, threshold, resolveSystemPrintStream(threshold));
+ }
+
+ public static PrintStream resolveSystemPrintStream(Level threshold) {
+ return resolvePrintStream(threshold, System.out, System.err);
+ }
+
+ public static Logger getLogger(Class<?> clazz, Level threshold, PrintStream logStream) {
+ return getLogger(clazz.getSimpleName(), threshold, logStream);
+ }
+
+ public static Logger getLogger(String name, Level threshold, PrintStream logStream) {
+ return ((threshold == null) || Level.OFF.equals(threshold))
+ ? SimplifiedLoggerSkeleton.EMPTY : new CliLogger(name, threshold, logStream);
}
}
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java
index aafce0c..f7306e7 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java
@@ -20,14 +20,12 @@ package org.apache.sshd.cli;
import java.io.IOException;
import java.io.PrintStream;
-import java.io.PrintWriter;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.logging.Level;
import org.apache.sshd.common.AttributeRepository;
@@ -44,7 +42,6 @@ import org.apache.sshd.common.compression.BuiltinCompressions;
import org.apache.sshd.common.compression.Compression;
import org.apache.sshd.common.config.CompressionConfigValue;
import org.apache.sshd.common.config.ConfigFileReaderSupport;
-import org.apache.sshd.common.config.LogLevelValue;
import org.apache.sshd.common.helpers.AbstractFactoryManager;
import org.apache.sshd.common.io.BuiltinIoServiceFactoryFactories;
import org.apache.sshd.common.io.IoAcceptor;
@@ -58,6 +55,7 @@ import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.common.session.SessionListener;
import org.apache.sshd.common.util.GenericUtils;
+import org.slf4j.Logger;
/**
* Provides common utilities for SSH client/server execution from the CLI
@@ -71,20 +69,6 @@ public abstract class CliSupport {
super();
}
- public static boolean showError(PrintStream stderr, String message) {
- stderr.append("ERROR: ").println(message);
- return true;
- }
-
- public static boolean isEnabledVerbosityLogging(Level level) {
- if ((level == null) || Level.OFF.equals(level) || Level.CONFIG.equals(level)
- || Level.SEVERE.equals(level) || Level.WARNING.equals(level)) {
- return false;
- }
-
- return true;
- }
-
public static <
S extends SessionContext,
M extends UserAuthInstance<S>, F extends UserAuthMethodFactory<S, M>,
@@ -160,39 +144,22 @@ public abstract class CliSupport {
manager.setIoServiceFactoryFactory(factory.create());
- if (!isEnabledVerbosityLogging(level)) {
- return manager;
+ Logger logger = CliLogger.resolveLogger(CliSupport.class, level, stdout, stderr);
+ if (logger.isInfoEnabled()) {
+ manager.setIoServiceEventListener(createLoggingIoServiceEventListener(logger));
+ manager.addSessionListener(createLoggingSessionListener(logger));
}
-
- PrintStream out = Level.INFO.equals(level) ? stderr : stdout;
- manager.setIoServiceEventListener(createLoggingIoServiceEventListener(out));
- manager.addSessionListener(createLoggingSessionListener(out));
return manager;
}
- public static void printStackTrace(Appendable out, Throwable reason) {
- if ((reason == null) || (out == null)) {
- return;
- }
-
- if (out instanceof PrintStream) {
- reason.printStackTrace((PrintStream) out);
- } else if (out instanceof PrintWriter) {
- reason.printStackTrace((PrintWriter) out);
- }
- }
-
@SuppressWarnings("checkstyle:anoninnerlength")
- public static IoServiceEventListener createLoggingIoServiceEventListener(Appendable out) {
+ public static IoServiceEventListener createLoggingIoServiceEventListener(Logger logger) {
return new IoServiceEventListener() {
@Override
public void connectionEstablished(
IoConnector connector, SocketAddress local, AttributeRepository context, SocketAddress remote)
throws IOException {
- out.append("Connection established via ").append(Objects.toString(connector))
- .append("- local=").append(Objects.toString(local))
- .append(", remote=").append(Objects.toString(remote))
- .append(System.lineSeparator());
+ logger.info("Connection established via {} - local={}, remote={}", connector, local, remote);
}
@Override
@@ -200,13 +167,11 @@ public abstract class CliSupport {
IoConnector connector, SocketAddress local, AttributeRepository context,
SocketAddress remote, Throwable reason)
throws IOException {
- out.append("Abort established connection ").append(Objects.toString(connector))
- .append(" - local=").append(Objects.toString(local))
- .append(", remote=").append(Objects.toString(remote))
- .append(": (").append(reason.getClass().getSimpleName()).append(')')
- .append(' ').append(reason.getMessage())
- .append(System.lineSeparator());
- printStackTrace(out, reason);
+ logger.info("Abort established connection {} - local={}, remote={}", connector, local, remote);
+ if (reason != null) {
+ logger.warn(" {}: {}", reason.getClass().getSimpleName(), reason.getMessage());
+ logger.error(reason.getClass().getSimpleName(), reason);
+ }
}
@Override
@@ -214,11 +179,7 @@ public abstract class CliSupport {
IoAcceptor acceptor, SocketAddress local,
SocketAddress remote, SocketAddress service)
throws IOException {
- out.append("Connection accepted via ").append(Objects.toString(acceptor))
- .append(" - local=").append(Objects.toString(local))
- .append(", remote=").append(Objects.toString(remote))
- .append(", service=").append(Objects.toString(service))
- .append(System.lineSeparator());
+ logger.info("Connection accepted via {} - local={}, remote={}, service={}", acceptor, local, remote, service);
}
@Override
@@ -226,35 +187,26 @@ public abstract class CliSupport {
IoAcceptor acceptor, SocketAddress local, SocketAddress remote,
SocketAddress service, Throwable reason)
throws IOException {
- out.append("Abort accepted connection ").append(Objects.toString(acceptor))
- .append(" - local=").append(Objects.toString(local))
- .append(", remote=").append(Objects.toString(remote))
- .append(", service=").append(Objects.toString(service))
- .append(": (").append(reason.getClass().getSimpleName()).append(')')
- .append(' ').append(reason.getMessage())
- .append(System.lineSeparator());
- printStackTrace(out, reason);
+ logger.info("Abort accepted connection {} - local={}, remote={}, service={}", acceptor, local, remote, service);
+ if (reason != null) {
+ logger.warn(" {}: {}", reason.getClass().getSimpleName(), reason.getMessage());
+ logger.error(reason.getClass().getSimpleName(), reason);
+ }
}
};
}
@SuppressWarnings("checkstyle:anoninnerlength")
- public static SessionListener createLoggingSessionListener(Appendable out) {
+ public static SessionListener createLoggingSessionListener(Logger logger) {
return new SessionListener() {
@Override
public void sessionPeerIdentificationReceived(
Session session, String version, List<String> extraLines) {
- try {
- out.append(Objects.toString(session))
- .append(" peer identification=").append(version)
- .append(System.lineSeparator());
- if (GenericUtils.isNotEmpty(extraLines)) {
- for (String l : extraLines) {
- out.append(" => ").append(l).append(System.lineSeparator());
- }
+ logger.info("{} peer identification={}", session, version);
+ if (GenericUtils.isNotEmpty(extraLines)) {
+ for (String l : extraLines) {
+ logger.info(" => {}", l);
}
- } catch (IOException e) {
- // ignored
}
}
@@ -269,90 +221,25 @@ public abstract class CliSupport {
return;
}
- try {
- out.append(Objects.toString(session))
- .append(" KEX negotiation results:")
- .append(System.lineSeparator());
- for (KexProposalOption opt : KexProposalOption.VALUES) {
- String value = negotiatedOptions.get(opt);
- out.append(" ").append(opt.getDescription())
- .append(": ").append(value)
- .append(System.lineSeparator());
- }
- } catch (IOException e) {
- // ignored
+ logger.info("{} KEX negotiation results:", session);
+ for (KexProposalOption opt : KexProposalOption.VALUES) {
+ logger.info(" {}: {}", opt.getDescription(), negotiatedOptions.get(opt));
}
}
@Override
public void sessionException(Session session, Throwable t) {
- try {
- out.append(Objects.toString(session))
- .append(' ').append(t.getClass().getSimpleName())
- .append(": ").append(t.getMessage())
- .append(System.lineSeparator());
- printStackTrace(out, t);
- } catch (IOException e) {
- // ignored
- }
+ logger.error("{} {}: {}", session, t.getClass().getSimpleName(), t.getMessage());
+ logger.error(t.getClass().getSimpleName(), t);
}
@Override
public void sessionClosed(Session session) {
- try {
- out.append(Objects.toString(session))
- .append(" closed")
- .append(System.lineSeparator());
- } catch (IOException e) {
- // ignored
- }
+ logger.info("{} closed", session);
}
};
}
- public static Level resolveLoggingVerbosity(String... args) {
- return resolveLoggingVerbosity(args, GenericUtils.length(args));
- }
-
- public static Level resolveLoggingVerbosity(String[] args, int maxIndex) {
- for (int index = 0; index < maxIndex; index++) {
- String argName = args[index];
- if ("-v".equals(argName)) {
- return Level.INFO;
- } else if ("-vv".equals(argName)) {
- return Level.FINE;
- } else if ("-vvv".equals(argName)) {
- return Level.FINEST;
- }
- }
-
- return Level.CONFIG;
- }
-
- /**
- * Looks for the {@link ConfigFileReaderSupport#LOG_LEVEL_CONFIG_PROP} in the options. If found, then uses it as the
- * result. Otherwise, invokes {@link #resolveLoggingVerbosity(String...)}
- *
- * @param resolver The {@code -o} options specified by the user
- * @param args The command line arguments
- * @return The resolved verbosity level
- */
- public static Level resolveLoggingVerbosity(PropertyResolver resolver, String... args) {
- String levelValue = PropertyResolverUtils.getString(
- resolver, ConfigFileReaderSupport.LOG_LEVEL_CONFIG_PROP);
- if (GenericUtils.isEmpty(levelValue)) {
- return resolveLoggingVerbosity(args);
- }
-
- LogLevelValue level = LogLevelValue.fromName(levelValue);
- if (level == null) {
- throw new IllegalArgumentException(
- "Unknown " + ConfigFileReaderSupport.LOG_LEVEL_CONFIG_PROP + " option value: " + levelValue);
- }
-
- return level.getLoggingLevel();
- }
-
public static List<NamedFactory<Compression>> setupCompressions(PropertyResolver options, PrintStream stderr) {
String argVal = PropertyResolverUtils.getString(
options, ConfigFileReaderSupport.COMPRESSION_PROP);
@@ -362,7 +249,7 @@ public abstract class CliSupport {
NamedFactory<Compression> value = CompressionConfigValue.fromName(argVal);
if (value == null) {
- showError(stderr, "Unknown compression configuration value: " + argVal);
+ CliLogger.showError(stderr, "Unknown compression configuration value: " + argVal);
return null;
}
@@ -372,14 +259,14 @@ public abstract class CliSupport {
public static List<NamedFactory<Compression>> setupCompressions(
String argName, String argVal, List<NamedFactory<Compression>> current, PrintStream stderr) {
if (GenericUtils.size(current) > 0) {
- showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current));
+ CliLogger.showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current));
return null;
}
BuiltinCompressions.ParseResult result = BuiltinCompressions.parseCompressionsList(argVal);
Collection<? extends NamedFactory<Compression>> available = result.getParsedFactories();
if (GenericUtils.isEmpty(available)) {
- showError(stderr, "No known compressions in " + argVal);
+ CliLogger.showError(stderr, "No known compressions in " + argVal);
return null;
}
@@ -403,14 +290,14 @@ public abstract class CliSupport {
public static List<NamedFactory<Mac>> setupMacs(
String argName, String argVal, List<NamedFactory<Mac>> current, PrintStream stderr) {
if (GenericUtils.size(current) > 0) {
- showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current));
+ CliLogger.showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current));
return null;
}
BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(argVal);
Collection<? extends NamedFactory<Mac>> available = result.getParsedFactories();
if (GenericUtils.isEmpty(available)) {
- showError(stderr, "No known MACs in " + argVal);
+ CliLogger.showError(stderr, "No known MACs in " + argVal);
return null;
}
@@ -435,14 +322,14 @@ public abstract class CliSupport {
public static List<NamedFactory<Cipher>> setupCiphers(
String argName, String argVal, List<NamedFactory<Cipher>> current, PrintStream stderr) {
if (GenericUtils.size(current) > 0) {
- showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current));
+ CliLogger.showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current));
return null;
}
BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(argVal);
Collection<? extends NamedFactory<Cipher>> available = result.getParsedFactories();
if (GenericUtils.isEmpty(available)) {
- showError(stderr, "WARNING: No known ciphers in " + argVal);
+ CliLogger.showError(stderr, "WARNING: No known ciphers in " + argVal);
return null;
}
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java b/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java
index 3990cd9..8b14d4b 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java
@@ -37,7 +37,7 @@ import java.util.List;
import java.util.Set;
import java.util.logging.Level;
-import org.apache.sshd.cli.CliSupport;
+import org.apache.sshd.cli.CliLogger;
import org.apache.sshd.client.ClientFactoryManager;
import org.apache.sshd.client.auth.AuthenticationIdentitiesProvider;
import org.apache.sshd.client.config.hosts.HostConfigEntry;
@@ -58,6 +58,7 @@ import org.apache.sshd.scp.common.helpers.ScpAckInfo;
import org.apache.sshd.scp.common.helpers.ScpReceiveDirCommandDetails;
import org.apache.sshd.scp.common.helpers.ScpReceiveFileCommandDetails;
import org.apache.sshd.scp.common.helpers.ScpTimestampCommandDetails;
+import org.slf4j.Logger;
/**
* @see <A HREF="https://man7.org/linux/man-pages/man1/scp.1.html">SCP(1) - manual page</A>
@@ -95,7 +96,7 @@ public class ScpCommandMain extends SshClientCliSupport {
if (isArgumentedOption(SCP_PORT_OPTION, argName) || "-creator".equals(argName)) {
index++;
if (index >= numArgs) {
- error = showError(stderr, "option requires an argument: " + argName);
+ error = CliLogger.showError(stderr, "option requires an argument: " + argName);
break;
}
@@ -109,32 +110,32 @@ public class ScpCommandMain extends SshClientCliSupport {
threeWay = true;
effective.add(argName);
} else if (argName.charAt(0) == '-') {
- error = showError(stderr, "Unknown option: " + argName);
+ error = CliLogger.showError(stderr, "Unknown option: " + argName);
break;
} else {
index++;
if (index >= numArgs) {
- error = showError(stderr, "Not enough arguments");
+ error = CliLogger.showError(stderr, "Not enough arguments");
break;
}
ScpLocation source = new ScpLocation(argName);
ScpLocation target = new ScpLocation(args[index]);
if (index < (numArgs - 1)) {
- error = showError(stderr, "Unexpected extra arguments");
+ error = CliLogger.showError(stderr, "Unexpected extra arguments");
break;
}
if (threeWay) {
if (source.isLocal() || target.isLocal()) {
- error = showError(stderr, "Both targets must be remote for the 3-way copy option");
+ error = CliLogger.showError(stderr, "Both targets must be remote for the 3-way copy option");
break;
}
adjustRemoteTargetArguments(source, source, target, effective);
} else {
if (source.isLocal() == target.isLocal()) {
- error = showError(stderr, "Both targets are either remote or local");
+ error = CliLogger.showError(stderr, "Both targets are either remote or local");
break;
}
@@ -176,7 +177,7 @@ public class ScpCommandMain extends SshClientCliSupport {
if ("-creator".equals(argName)) {
index++;
if (index >= numArgs) {
- showError(stderr, "option requires an argument: " + argName);
+ CliLogger.showError(stderr, "option requires an argument: " + argName);
return null;
}
@@ -260,6 +261,8 @@ public class ScpCommandMain extends SshClientCliSupport {
try {
if (!quiet) {
creator.setScpTransferEventListener(new ScpTransferEventListener() {
+ private final Logger log = CliLogger.resolveLogger(ScpCommandMain.class, level, stdout, stderr);
+
@Override
public void startFolderEvent(
Session session, FileOperation op, Path file, Set<PosixFilePermission> perms) {
@@ -297,21 +300,14 @@ public class ScpCommandMain extends SshClientCliSupport {
private void logEvent(
String name, Session session, FileOperation op, Path file, long length,
Collection<PosixFilePermission> perms, Throwable thrown) {
- PrintStream ps = (thrown == null) ? stdout : stderr;
- ps.append(" ").append(name)
- .append('[').append(session.toString()).append(']')
- .append('[').append(op.name()).append(']')
- .append(' ').append(file.toString());
- if (length > 0L) {
- ps.append(' ').append("length=").append(Long.toString(length));
+ if (!log.isInfoEnabled()) {
+ return;
}
- ps.append(' ').append(String.valueOf(perms));
+ log.info("{} - [{}][{}] (length={}) {} {}", name, session, op, file, length, perms);
if (thrown != null) {
- ps.append(" - ").append(thrown.getClass().getSimpleName()).append(": ")
- .append(thrown.getMessage());
+ log.error("{} - {}: {}", name, thrown.getClass().getSimpleName(), thrown.getMessage());
}
- ps.println();
}
});
}
@@ -452,7 +448,7 @@ public class ScpCommandMain extends SshClientCliSupport {
int numArgs = GenericUtils.length(args);
// see the way normalizeCommandArguments works...
if (numArgs >= 2) {
- level = CliSupport.resolveLoggingVerbosity(args, numArgs - 2);
+ level = CliLogger.resolveLoggingVerbosity(args, numArgs - 2);
logStream = resolveLoggingTargetStream(stdout, stderr, args, numArgs - 2);
if (logStream != null) {
setupLogging(level, stdout, stderr, logStream);
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 42a4d1f..eb560dd 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
@@ -42,7 +42,7 @@ import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
-import org.apache.sshd.cli.CliSupport;
+import org.apache.sshd.cli.CliLogger;
import org.apache.sshd.cli.client.helper.SftpFileTransferProgressOutputStream;
import org.apache.sshd.client.ClientFactoryManager;
import org.apache.sshd.client.session.ClientSession;
@@ -79,6 +79,7 @@ import org.apache.sshd.sftp.common.SftpConstants;
import org.apache.sshd.sftp.common.SftpException;
import org.apache.sshd.sftp.common.extensions.ParserUtils;
import org.apache.sshd.sftp.common.extensions.openssh.StatVfsExtensionParser;
+import org.slf4j.Logger;
/**
* TODO Add javadoc
@@ -317,7 +318,7 @@ public class SftpCommandMain extends SshClientCliSupport implements Channel {
PrintStream stderr = System.err;
OutputStream logStream = stderr;
try (BufferedReader stdin = new BufferedReader(new InputStreamReader(new NoCloseInputStream(System.in)))) {
- Level level = CliSupport.resolveLoggingVerbosity(args);
+ Level level = CliLogger.resolveLoggingVerbosity(args);
logStream = resolveLoggingTargetStream(stdout, stderr, args);
if (logStream != null) {
setupLogging(level, stdout, stderr, logStream);
@@ -336,13 +337,17 @@ public class SftpCommandMain extends SshClientCliSupport implements Channel {
try {
SftpClientFactory clientFactory = resolveSftpClientFactory(session);
- if ((level != null) && (level.intValue() <= Level.INFO.intValue())) {
- stdout.append("Using factory=").println(clientFactory.getClass().getSimpleName());
+ Logger logger = (logStream != null)
+ ? CliLogger.getLogger(SftpCommandMain.class, level,
+ (logStream instanceof PrintStream) ? (PrintStream) logStream : new PrintStream(logStream))
+ : CliLogger.resolveSystemLogger(SftpCommandMain.class, level);
+ if (logger.isInfoEnabled()) {
+ logger.info("Using factory={}", clientFactory.getClass().getSimpleName());
}
SftpVersionSelector versionSelector = resolveVersionSelector(session);
- if ((level != null) && (level.intValue() <= Level.INFO.intValue())) {
- stdout.append("Using version selector=").println(versionSelector);
+ if (logger.isInfoEnabled()) {
+ logger.info("Using version selector={}", versionSelector);
}
try (SftpClient sftpClient = clientFactory.createSftpClient(session, versionSelector);
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 8947388..9fbd052 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
@@ -43,6 +43,7 @@ import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
+import org.apache.sshd.cli.CliLogger;
import org.apache.sshd.cli.CliSupport;
import org.apache.sshd.client.ClientAuthenticationManager;
import org.apache.sshd.client.ClientBuilder;
@@ -135,7 +136,7 @@ public abstract class SshClientCliSupport extends CliSupport {
if (isArgumentedOption(portOption, argName)) {
i++;
if (i >= numArgs) {
- error = showError(stderr, "option requires an argument: " + argName);
+ error = CliLogger.showError(stderr, "option requires an argument: " + argName);
break;
}
@@ -144,24 +145,24 @@ public abstract class SshClientCliSupport extends CliSupport {
if (portOption.equals(argName)) {
if (port > 0) {
- error = showError(stderr, argName + " option value re-specified: " + port);
+ error = CliLogger.showError(stderr, argName + " option value re-specified: " + port);
break;
}
port = Integer.parseInt(argVal);
if (port <= 0) {
- error = showError(stderr, "Bad option value for " + argName + ": " + port);
+ error = CliLogger.showError(stderr, "Bad option value for " + argName + ": " + port);
break;
}
} else if ("-J".equals(argName)) {
if (proxyJump != null) {
- error = showError(stderr, argName + " option value re-specified: " + proxyJump);
+ error = CliLogger.showError(stderr, argName + " option value re-specified: " + proxyJump);
break;
}
proxyJump = argVal;
} else if ("-w".equals(argName)) {
if (GenericUtils.length(password) > 0) {
- error = showError(stderr, argName + " option value re-specified: " + password);
+ error = CliLogger.showError(stderr, argName + " option value re-specified: " + password);
break;
}
password = argVal;
@@ -190,7 +191,7 @@ public abstract class SshClientCliSupport extends CliSupport {
String opt = argVal;
int idx = opt.indexOf('=');
if (idx <= 0) {
- error = showError(stderr, "bad syntax for option: " + opt);
+ error = CliLogger.showError(stderr, "bad syntax for option: " + opt);
break;
}
@@ -204,7 +205,7 @@ public abstract class SshClientCliSupport extends CliSupport {
}
} else if ("-l".equals(argName)) {
if (login != null) {
- error = showError(stderr, argName + " option value re-specified: " + port);
+ error = CliLogger.showError(stderr, argName + " option value re-specified: " + port);
break;
}
@@ -221,7 +222,7 @@ public abstract class SshClientCliSupport extends CliSupport {
login = host.substring(0, pos);
host = host.substring(pos + 1);
} else {
- error = showError(stderr, "Login already specified using -l option (" + login + "): " + host);
+ error = CliLogger.showError(stderr, "Login already specified using -l option (" + login + "): " + host);
break;
}
}
@@ -229,7 +230,7 @@ public abstract class SshClientCliSupport extends CliSupport {
}
if ((!error) && GenericUtils.isEmpty(host)) {
- error = showError(stderr, "Hostname not specified");
+ error = CliLogger.showError(stderr, "Hostname not specified");
}
if (error) {
@@ -461,7 +462,7 @@ public abstract class SshClientCliSupport extends CliSupport {
try {
setupSessionIdentities(client, identities, stdin, stdout, stderr);
} catch (Throwable t) { // show but do not fail the setup - maybe a password can be used
- showError(stderr, t.getClass().getSimpleName() + " while loading user keys: " + t.getMessage());
+ CliLogger.showError(stderr, t.getClass().getSimpleName() + " while loading user keys: " + t.getMessage());
}
setupServerKeyVerifier(client, resolver, stdin, stdout, stderr);
@@ -476,7 +477,7 @@ public abstract class SshClientCliSupport extends CliSupport {
}
return client;
} catch (Throwable t) {
- showError(stderr, "Failed (" + t.getClass().getSimpleName() + ") to setup client: " + t.getMessage());
+ CliLogger.showError(stderr, "Failed (" + t.getClass().getSimpleName() + ") to setup client: " + t.getMessage());
client.close();
return null;
}
@@ -649,7 +650,7 @@ public abstract class SshClientCliSupport extends CliSupport {
String argName = args[index];
if ("-E".equals(argName)) {
if ((index + 1) >= maxIndex) {
- showError(stderr, "Missing " + argName + " option argument");
+ CliLogger.showError(stderr, "Missing " + argName + " option argument");
return null;
}
@@ -662,7 +663,7 @@ public abstract class SshClientCliSupport extends CliSupport {
Path path = Paths.get(argVal).normalize().toAbsolutePath();
return Files.newOutputStream(path);
} catch (IOException e) {
- showError(stderr,
+ CliLogger.showError(stderr,
"Failed (" + e.getClass().getSimpleName() + ") to open " + argVal + ": " + e.getMessage());
return null;
}
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientMain.java b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientMain.java
index 89740ce..20f86fa 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientMain.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/client/SshClientMain.java
@@ -32,7 +32,6 @@ import java.util.Map;
import java.util.logging.Level;
import org.apache.sshd.cli.CliLogger;
-import org.apache.sshd.cli.CliSupport;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ClientChannel;
@@ -44,6 +43,7 @@ import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.io.NoCloseInputStream;
import org.apache.sshd.common.util.io.NoCloseOutputStream;
import org.apache.sshd.common.util.net.SshdSocketAddress;
+import org.slf4j.Logger;
/**
* TODO Add javadoc
@@ -74,7 +74,7 @@ public class SshClientMain extends SshClientCliSupport {
// handled by 'setupClientSession'
if (GenericUtils.isEmpty(command) && isArgumentedOption("-p", argName)) {
if ((i + 1) >= numArgs) {
- error = showError(stderr, "option requires an argument: " + argName);
+ error = CliLogger.showError(stderr, "option requires an argument: " + argName);
break;
}
@@ -89,17 +89,17 @@ public class SshClientMain extends SshClientCliSupport {
if (GenericUtils.isEmpty(command) && "-D".equals(argName)) {
if ((i + 1) >= numArgs) {
- error = showError(stderr, "option requires an argument: " + argName);
+ error = CliLogger.showError(stderr, "option requires an argument: " + argName);
break;
}
if (socksPort > 0) {
- error = showError(stderr, argName + " option value re-specified: " + socksPort);
+ error = CliLogger.showError(stderr, argName + " option value re-specified: " + socksPort);
break;
}
socksPort = Integer.parseInt(args[++i]);
if (socksPort <= 0) {
- error = showError(stderr, "Bad option value for " + argName + ": " + socksPort);
+ error = CliLogger.showError(stderr, "Bad option value for " + argName + ": " + socksPort);
break;
}
} else if (GenericUtils.isEmpty(command) && "-A".equals(argName)) {
@@ -107,7 +107,7 @@ public class SshClientMain extends SshClientCliSupport {
} else if (GenericUtils.isEmpty(command) && "-a".equals(argName)) {
agentForward = false;
} else {
- level = CliSupport.resolveLoggingVerbosity(args, i);
+ level = CliLogger.resolveLoggingVerbosity(args, i);
logStream = resolveLoggingTargetStream(stdout, stderr, args, i);
if (logStream == null) {
error = true;
@@ -147,7 +147,7 @@ public class SshClientMain extends SshClientCliSupport {
return;
}
- CliLogger logger = new CliLogger(level, System.err);
+ Logger logger = CliLogger.resolveSystemLogger(SshClientMain.class, level);
boolean verbose = logger.isInfoEnabled();
try (SshClient client = (SshClient) session.getFactoryManager()) {
/*
@@ -160,8 +160,7 @@ public class SshClientMain extends SshClientCliSupport {
try {
if (socksPort >= 0) {
if (verbose) {
- logger.info(
- "Start dynamic port forwarding to " + SshdSocketAddress.LOCALHOST_NAME + ":" + socksPort);
+ logger.info("Start dynamic port forwarding to {}:{}", SshdSocketAddress.LOCALHOST_NAME, socksPort);
}
session.startDynamicPortForwarding(
@@ -183,8 +182,8 @@ public class SshClientMain extends SshClientCliSupport {
}
if (logger.isDebugEnabled()) {
- logger.debug("PTY=" + ptyConfig + " for command=" + cmdValue);
- logger.debug("ENV=" + env + " for command=" + cmdValue);
+ logger.debug("PTY={} for command={}", ptyConfig, cmdValue);
+ logger.debug("ENV={} for command={}", env, cmdValue);
}
try (OutputStream channelOut = new NoCloseOutputStream(System.out);
@@ -194,21 +193,21 @@ public class SshClientMain extends SshClientCliSupport {
Duration maxWait = CliClientModuleProperties.CHANNEL_OPEN_TIMEOUT.getRequired(channel);
if (verbose) {
- logger.info("Wait " + maxWait + " for open channel for command=" + cmdValue);
+ logger.info("Wait {} for open channel for command={}", maxWait, cmdValue);
}
channel.open().verify(maxWait);
if (verbose) {
- logger.info("Channel opened for command=" + cmdValue);
+ logger.info("Channel opened for command={}", cmdValue);
}
Collection<ClientChannelEvent> result = channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L);
if (verbose) {
- logger.info("command=" + cmdValue + " - waitFor result=" + result);
+ logger.info("command={} - waitFor result={}", cmdValue, result);
if (result.contains(ClientChannelEvent.EXIT_SIGNAL)) {
- logger.info(" " + ClientChannelEvent.EXIT_SIGNAL + "=" + channel.getExitSignal());
+ logger.info(" {}={}", ClientChannelEvent.EXIT_SIGNAL, channel.getExitSignal());
}
if (result.contains(ClientChannelEvent.EXIT_STATUS)) {
- logger.info(" " + ClientChannelEvent.EXIT_STATUS + "=" + channel.getExitStatus());
+ logger.info(" {}={}", ClientChannelEvent.EXIT_STATUS, channel.getExitStatus());
}
}
} finally {
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
index 6b3340b..0c00435 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerCliSupport.java
@@ -37,6 +37,7 @@ import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.apache.sshd.cli.CliLogger;
import org.apache.sshd.cli.CliSupport;
import org.apache.sshd.cli.server.helper.ScpCommandTransferEventListener;
import org.apache.sshd.cli.server.helper.ServerPortForwardingEventListener;
@@ -54,6 +55,7 @@ import org.apache.sshd.common.util.io.resource.PathResource;
import org.apache.sshd.common.util.security.SecurityUtils;
import org.apache.sshd.common.util.threads.ThreadUtils;
import org.apache.sshd.core.CoreModuleProperties;
+import org.apache.sshd.scp.common.ScpTransferEventListener;
import org.apache.sshd.scp.server.ScpCommandFactory;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.server.SshServer;
@@ -68,6 +70,7 @@ import org.apache.sshd.server.subsystem.SubsystemFactory;
import org.apache.sshd.sftp.common.SftpConstants;
import org.apache.sshd.sftp.server.SftpEventListener;
import org.apache.sshd.sftp.server.SftpSubsystemFactory;
+import org.slf4j.Logger;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
@@ -155,8 +158,9 @@ public abstract class SshServerCliSupport extends CliSupport {
SshServer server, Level level, PrintStream stdout, PrintStream stderr, PropertyResolver options) {
ForwardingFilter forwardFilter = SshServerConfigFileReader.resolveServerForwarding(options);
server.setForwardingFilter(forwardFilter);
- if (isEnabledVerbosityLogging(level)) {
- server.addPortForwardingEventListener(new ServerPortForwardingEventListener(stdout, stderr));
+ if (CliLogger.isEnabledVerbosityLogging(level)) {
+ Logger logger = CliLogger.resolveLogger(SshServerCliSupport.class, level, stdout, stderr);
+ server.addPortForwardingEventListener(new ServerPortForwardingEventListener(logger));
}
return forwardFilter;
}
@@ -202,7 +206,8 @@ public abstract class SshServerCliSupport extends CliSupport {
if (SftpConstants.SFTP_SUBSYSTEM_NAME.equalsIgnoreCase(nameList)) {
SubsystemFactory factory = registerSubsystemFactoryListeners(
server, level, stdout, stderr, options, new SftpSubsystemFactory());
- stdout.println("Using built-in SFTP subsystem");
+ PrintStream logStream = CliLogger.resolvePrintStream(level, stdout, stderr);
+ CliLogger.log(logStream, level, "Using built-in SFTP subsystem");
return Collections.singletonList(factory);
}
@@ -232,8 +237,9 @@ public abstract class SshServerCliSupport extends CliSupport {
F factory)
throws Exception {
if (factory instanceof SftpSubsystemFactory) {
- if (isEnabledVerbosityLogging(level)) {
- SftpEventListener listener = new SftpServerSubSystemEventListener(stdout, stderr);
+ if (CliLogger.isEnabledVerbosityLogging(level)) {
+ Logger logger = CliLogger.resolveLogger(SftpEventListener.class, level, stdout, stderr);
+ SftpEventListener listener = new SftpServerSubSystemEventListener(logger);
((SftpSubsystemFactory) factory).addSftpEventListener(listener);
}
@@ -309,12 +315,13 @@ public abstract class SshServerCliSupport extends CliSupport {
}
public static ScpCommandFactory createScpCommandFactory(
- Level level, Appendable stdout, Appendable stderr, ShellFactory delegateShellFactory) {
+ Level level, PrintStream stdout, PrintStream stderr, ShellFactory delegateShellFactory) {
ScpCommandFactory.Builder scp = new ScpCommandFactory.Builder()
.withDelegate(ProcessShellCommandFactory.INSTANCE)
.withDelegateShellFactory(delegateShellFactory);
- if (isEnabledVerbosityLogging(level)) {
- scp.addEventListener(new ScpCommandTransferEventListener(stdout, stderr));
+ if (CliLogger.isEnabledVerbosityLogging(level)) {
+ Logger logger = CliLogger.resolveLogger(ScpTransferEventListener.class, level, stdout, stderr);
+ scp.addEventListener(new ScpCommandTransferEventListener(logger));
}
return scp.build();
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
index 27e48b6..69b417e 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/SshServerMain.java
@@ -19,6 +19,7 @@
package org.apache.sshd.cli.server;
+import java.io.PrintStream;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.LinkedList;
@@ -29,6 +30,7 @@ import java.util.TreeMap;
import java.util.logging.Level;
import java.util.stream.Collectors;
+import org.apache.sshd.cli.CliLogger;
import org.apache.sshd.common.NamedResource;
import org.apache.sshd.common.PropertyResolver;
import org.apache.sshd.common.PropertyResolverUtils;
@@ -46,6 +48,7 @@ import org.apache.sshd.server.config.keys.ServerIdentity;
import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;
import org.apache.sshd.server.shell.ShellFactory;
import org.apache.sshd.server.subsystem.SubsystemFactory;
+import org.slf4j.Logger;
/**
* TODO Add javadoc
@@ -158,7 +161,8 @@ public class SshServerMain extends SshServerCliSupport {
}
PropertyResolver resolver = PropertyResolverUtils.toPropertyResolver(options);
- Level level = resolveLoggingVerbosity(resolver, args);
+ Level level = CliLogger.resolveLoggingVerbosity(resolver, args);
+ Logger logger = CliLogger.resolveSystemLogger(SshServerMain.class, level);
SshServer sshd = error
? null
: setupIoServiceFactory(
@@ -192,7 +196,9 @@ public class SshServerMain extends SshServerCliSupport {
ShellFactory shellFactory = resolveShellFactory(level, System.out, System.err, resolver);
if (shellFactory != null) {
- System.out.append("Using shell=").println(shellFactory.getClass().getName());
+ if (logger.isInfoEnabled()) {
+ logger.info("Using shell={}", shellFactory.getClass().getName());
+ }
sshd.setShellFactory(shellFactory);
}
@@ -204,7 +210,9 @@ public class SshServerMain extends SshServerCliSupport {
List<SubsystemFactory> subsystems = resolveServerSubsystems(sshd, level, System.out, System.err, resolver);
if (GenericUtils.isNotEmpty(subsystems)) {
- System.out.append("Setup subsystems=").println(NamedResource.getNames(subsystems));
+ if (logger.isInfoEnabled()) {
+ logger.info("Setup subsystems={}", NamedResource.getNames(subsystems));
+ }
sshd.setSubsystemFactories(subsystems);
}
@@ -215,7 +223,7 @@ public class SshServerMain extends SshServerCliSupport {
}
private static CommandFactory setupCommandFactory(
- SshServer sshd, Level level, Appendable stdout, Appendable stderr, ShellFactory shellFactory) {
+ SshServer sshd, Level level, PrintStream stdout, PrintStream stderr, ShellFactory shellFactory) {
ScpCommandFactory scpFactory;
if (shellFactory instanceof ScpCommandFactory) {
scpFactory = (ScpCommandFactory) shellFactory;
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ScpCommandTransferEventListener.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ScpCommandTransferEventListener.java
index 85b9261..9dfed05 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ScpCommandTransferEventListener.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ScpCommandTransferEventListener.java
@@ -26,7 +26,9 @@ import java.util.Set;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.scp.common.ScpTransferEventListener;
+import org.apache.sshd.scp.common.helpers.ScpAckInfo;
import org.apache.sshd.scp.server.ScpCommandFactory;
+import org.slf4j.Logger;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
@@ -34,15 +36,17 @@ import org.apache.sshd.scp.server.ScpCommandFactory;
public class ScpCommandTransferEventListener
extends ServerEventListenerHelper
implements ScpTransferEventListener {
- public ScpCommandTransferEventListener(Appendable stdout, Appendable stderr) {
- super(ScpCommandFactory.SCP_FACTORY_NAME, stdout, stderr);
+ public ScpCommandTransferEventListener(Logger logger) {
+ super(ScpCommandFactory.SCP_FACTORY_NAME, logger);
}
@Override
public void startFileEvent(
Session session, FileOperation op, Path file, long length, Set<PosixFilePermission> perms)
throws IOException {
- outputDebugMessage("startFileEvent(%s)[%s] len=%d, perms=%s: %s", session, op, length, perms, file);
+ if (log.isInfoEnabled()) {
+ log.info("startFileEvent({})[{}] len={}, perms={}: {}", session, op, length, perms, file);
+ }
}
@Override
@@ -50,17 +54,19 @@ public class ScpCommandTransferEventListener
Session session, FileOperation op, Path file, long length, Set<PosixFilePermission> perms, Throwable thrown)
throws IOException {
if (thrown != null) {
- outputErrorMessage("endFileEvent(%s)[%s] failed (%s) len=%d, perms=%s [%s]: %s",
+ log.error("endFileEvent({})[{}] failed ({}) len={}, perms={} [{}]: {}",
session, op, thrown.getClass().getSimpleName(), length, perms, file, thrown.getMessage());
- } else {
- outputDebugMessage("endFileEvent(%s)[%s] len=%d, perms=%s: %s", session, op, length, perms, file);
+ } else if (log.isInfoEnabled()) {
+ log.info("endFileEvent({})[{}] len={}, perms={}: {}", session, op, length, perms, file);
}
}
@Override
public void startFolderEvent(Session session, FileOperation op, Path file, Set<PosixFilePermission> perms)
throws IOException {
- outputDebugMessage("startFolderEvent(%s)[%s] perms=%s: %s", session, op, perms, file);
+ if (log.isInfoEnabled()) {
+ log.info("startFolderEvent({})[{}] perms={}: {}", session, op, perms, file);
+ }
}
@Override
@@ -68,10 +74,21 @@ public class ScpCommandTransferEventListener
Session session, FileOperation op, Path file, Set<PosixFilePermission> perms, Throwable thrown)
throws IOException {
if (thrown != null) {
- outputErrorMessage("endFolderEvent(%s)[%s] failed (%s) perms=%s [%s]: %s",
+ log.error("endFolderEvent({})[{}] failed ({}) perms={} [{}]: {}",
session, op, thrown.getClass().getSimpleName(), perms, file, thrown.getMessage());
- } else {
- outputDebugMessage("endFolderEvent(%s)[%s] lperms=%s: %s", session, op, perms, file);
+ } else if (log.isInfoEnabled()) {
+ log.info("endFolderEvent({})[{}] perms={}: {}", session, op, perms, file);
+ }
+ }
+
+ @Override
+ public void handleFileEventAckInfo(
+ Session session, FileOperation op, Path file, long length,
+ Set<PosixFilePermission> perms, ScpAckInfo ackInfo)
+ throws IOException {
+ if (log.isInfoEnabled()) {
+ log.info("handleFileEventAckInfo({})[{}] perms={}, length={}, ACK={}: {}",
+ session, op, perms, length, ackInfo, file);
}
}
}
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ServerEventListenerHelper.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ServerEventListenerHelper.java
index f3417ea..b79bccd 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ServerEventListenerHelper.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ServerEventListenerHelper.java
@@ -19,52 +19,21 @@
package org.apache.sshd.cli.server.helper;
-import java.io.Flushable;
-import java.io.IOException;
-import java.util.Objects;
-
import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.util.logging.AbstractLoggingBean;
+import org.slf4j.Logger;
-public abstract class ServerEventListenerHelper implements NamedResource {
+public abstract class ServerEventListenerHelper extends AbstractLoggingBean implements NamedResource {
private final String name;
- private final Appendable stdout;
- private final Appendable stderr;
- public ServerEventListenerHelper(String name, Appendable stdout, Appendable stderr) {
+ public ServerEventListenerHelper(String name, Logger logger) {
+ super(logger);
+
this.name = name;
- this.stdout = Objects.requireNonNull(stdout, "No output target");
- this.stderr = Objects.requireNonNull(stderr, "No error target");
}
@Override
public String getName() {
return name;
}
-
- public Appendable getStdout() {
- return stdout;
- }
-
- public Appendable getStderr() {
- return stderr;
- }
-
- protected String outputErrorMessage(String format, Object... args) throws IOException {
- return outputMessage(getStderr(), format, args);
- }
-
- protected String outputDebugMessage(String format, Object... args) throws IOException {
- return outputMessage(getStdout(), format, args);
- }
-
- protected String outputMessage(Appendable out, String format, Object... args) throws IOException {
- String message = String.format(format, args);
- out.append(getName())
- .append(": ").append(message)
- .append(System.lineSeparator());
- if (out instanceof Flushable) {
- ((Flushable) out).flush();
- }
- return message;
- }
}
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ServerPortForwardingEventListener.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ServerPortForwardingEventListener.java
index c6afab4..cdcd976 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ServerPortForwardingEventListener.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/ServerPortForwardingEventListener.java
@@ -24,10 +24,11 @@ import java.io.IOException;
import org.apache.sshd.common.forward.PortForwardingEventListener;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.util.net.SshdSocketAddress;
+import org.slf4j.Logger;
public class ServerPortForwardingEventListener extends ServerEventListenerHelper implements PortForwardingEventListener {
- public ServerPortForwardingEventListener(Appendable stdout, Appendable stderr) {
- super("PORT-FWD", stdout, stderr);
+ public ServerPortForwardingEventListener(Logger logger) {
+ super("PORT-FWD", logger);
}
@Override
@@ -36,11 +37,13 @@ public class ServerPortForwardingEventListener extends ServerEventListenerHelper
boolean localForwarding, SshdSocketAddress boundAddress, Throwable reason)
throws IOException {
if (reason == null) {
- outputDebugMessage("Estalibshed explicit tunnel for session=%s: local=%s, remote=%s, bound=%s, localForward=%s",
- session, local, remote, boundAddress, localForwarding);
+ if (log.isInfoEnabled()) {
+ log.info("Estalibshed explicit tunnel for session={}: local={}, remote={}, bound={}, localForward={}",
+ session, local, remote, boundAddress, localForwarding);
+ }
} else {
- outputErrorMessage(
- "Failed (%s) to establish explicit tunnel for session=%s, local=%s, remote=%s, bound=%s, localForward=%s: %s",
+ log.error(
+ "Failed ({}) to establish explicit tunnel for session={}, local={}, remote={}, bound={}, localForward={}: {}",
reason.getClass().getSimpleName(), session, local, remote, boundAddress, localForwarding,
reason.getMessage());
}
@@ -52,11 +55,13 @@ public class ServerPortForwardingEventListener extends ServerEventListenerHelper
Throwable reason)
throws IOException {
if (reason == null) {
- outputDebugMessage("Torn down explicit tunnel for session=%s: address=%s, remote=%s, localForward=%s",
- session, address, remoteAddress, localForwarding);
+ if (log.isInfoEnabled()) {
+ log.info("Torn down explicit tunnel for session={}: address={}, remote={}, localForward={}",
+ session, address, remoteAddress, localForwarding);
+ }
} else {
- outputErrorMessage(
- "Failed (%s) to tear down explicit tunnel for session=%s, address=%s, remote=%s, localForward=%s: %s",
+ log.error(
+ "Failed ({}) to tear down explicit tunnel for session={}, address={}, remote={}, localForward={}: {}",
reason.getClass().getSimpleName(), session, address, remoteAddress, localForwarding, reason.getMessage());
}
}
@@ -66,9 +71,11 @@ public class ServerPortForwardingEventListener extends ServerEventListenerHelper
Session session, SshdSocketAddress local, SshdSocketAddress boundAddress, Throwable reason)
throws IOException {
if (reason == null) {
- outputDebugMessage("Estalibshed dynamic tunnel for session=%s: local=%s, bound=%s", session, local, boundAddress);
+ if (log.isInfoEnabled()) {
+ log.info("Estalibshed dynamic tunnel for session={}: local={}, bound={}", session, local, boundAddress);
+ }
} else {
- outputErrorMessage("Failed (%s) to establish dynamic tunnel for session=%s, bound=%s: %s",
+ log.error("Failed ({}) to establish dynamic tunnel for session={}, bound={}: {}",
reason.getClass().getSimpleName(), session, local, boundAddress, reason.getMessage());
}
}
@@ -78,9 +85,11 @@ public class ServerPortForwardingEventListener extends ServerEventListenerHelper
Session session, SshdSocketAddress address, Throwable reason)
throws IOException {
if (reason == null) {
- outputDebugMessage("Tornd down dynamic tunnel for session=%s: address=%s", session);
+ if (log.isInfoEnabled()) {
+ log.info("Torn down dynamic tunnel for session={}: address={}", session);
+ }
} else {
- outputErrorMessage("Failed (%s) to tear down dynamic tunnel for session=%s, address=%s: %s",
+ log.error("Failed ({}) to tear down dynamic tunnel for session={}, address={}: {}",
reason.getClass().getSimpleName(), session, address, reason.getMessage());
}
}
diff --git a/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/SftpServerSubSystemEventListener.java b/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/SftpServerSubSystemEventListener.java
index 280a674..c534379 100644
--- a/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/SftpServerSubSystemEventListener.java
+++ b/sshd-cli/src/main/java/org/apache/sshd/cli/server/helper/SftpServerSubSystemEventListener.java
@@ -28,23 +28,28 @@ import java.util.Map;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.sftp.common.SftpConstants;
import org.apache.sshd.sftp.server.SftpEventListener;
+import org.slf4j.Logger;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class SftpServerSubSystemEventListener extends ServerEventListenerHelper implements SftpEventListener {
- public SftpServerSubSystemEventListener(Appendable stdout, Appendable stderr) {
- super(SftpConstants.SFTP_SUBSYSTEM_NAME, stdout, stderr);
+ public SftpServerSubSystemEventListener(Logger logger) {
+ super(SftpConstants.SFTP_SUBSYSTEM_NAME, logger);
}
@Override
public void initialized(ServerSession session, int version) throws IOException {
- outputDebugMessage("Session %s initialized - version=%d", session, version);
+ if (log.isInfoEnabled()) {
+ log.info("Session {} initialized - version={}", session, version);
+ }
}
@Override
public void destroying(ServerSession session) throws IOException {
- outputDebugMessage("Session destroyed: %s", session);
+ if (log.isInfoEnabled()) {
+ log.info("Session destroyed: {}", session);
+ }
}
@Override
@@ -52,9 +57,11 @@ public class SftpServerSubSystemEventListener extends ServerEventListenerHelper
ServerSession session, Path path, Map<String, ?> attrs, Throwable thrown)
throws IOException {
if (thrown == null) {
- outputDebugMessage("Session %s created directory %s with attributes=%s", session, path, attrs);
+ if (log.isInfoEnabled()) {
+ log.info("Session {} created directory {} with attributes={}", session, path, attrs);
+ }
} else {
- outputErrorMessage("Failed (%s) to create directory %s in session %s: %s",
+ log.error("Failed ({}) to create directory {} in session {}: {}",
thrown.getClass().getSimpleName(), path, session, thrown.getMessage());
}
}
@@ -64,10 +71,12 @@ public class SftpServerSubSystemEventListener extends ServerEventListenerHelper
ServerSession session, Path srcPath, Path dstPath, Collection<CopyOption> opts, Throwable thrown)
throws IOException {
if (thrown == null) {
- outputDebugMessage("Session %s moved %s to %s with options=%s",
- session, srcPath, dstPath, opts);
+ if (log.isInfoEnabled()) {
+ log.info("Session {} moved {} to {} with options={}",
+ session, srcPath, dstPath, opts);
+ }
} else {
- outputErrorMessage("Failed (%s) to move %s to %s using options=%s in session %s: %s",
+ log.error("Failed ({}) to move {} to {} using options={} in session {}: {}",
thrown.getClass().getSimpleName(), srcPath, dstPath, opts, session, thrown.getMessage());
}
}
@@ -75,9 +84,11 @@ public class SftpServerSubSystemEventListener extends ServerEventListenerHelper
@Override
public void removed(ServerSession session, Path path, boolean isDirectory, Throwable thrown) throws IOException {
if (thrown == null) {
- outputDebugMessage("Session %s removed %s", session, path);
+ if (log.isInfoEnabled()) {
+ log.info("Session {} removed {}", session, path);
+ }
} else {
- outputErrorMessage("Failed (%s) to remove %s in session %s: %s",
+ log.error("Failed ({}) to remove {} in session {}: {}",
thrown.getClass().getSimpleName(), path, session, thrown.getMessage());
}
}
diff --git a/sshd-cli/src/test/java/org/apache/sshd/cli/client/ChannelExecMain.java b/sshd-cli/src/test/java/org/apache/sshd/cli/client/ChannelExecMain.java
index 45424d4..e1cfc31 100644
--- a/sshd-cli/src/test/java/org/apache/sshd/cli/client/ChannelExecMain.java
+++ b/sshd-cli/src/test/java/org/apache/sshd/cli/client/ChannelExecMain.java
@@ -24,7 +24,7 @@ import java.io.InputStreamReader;
import java.io.PrintStream;
import java.nio.charset.Charset;
-import org.apache.sshd.cli.CliSupport;
+import org.apache.sshd.cli.CliLogger;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.util.GenericUtils;
@@ -79,7 +79,7 @@ public class ChannelExecMain extends BaseTestSupport {
try (BufferedReader stdin = new BufferedReader(
new InputStreamReader(new NoCloseInputStream(System.in), Charset.defaultCharset()))) {
ClientSession session = SshClientCliSupport.setupClientSession("-P", stdin,
- CliSupport.resolveLoggingVerbosity(args), stdout, stderr, args);
+ CliLogger.resolveLoggingVerbosity(args), stdout, stderr, args);
if (session == null) {
System.err.println("usage: channelExec [-i identity] [-l login] [-P port] [-o option=value]"
+ " [-J proxyJump] [-w password] [-c cipherlist] [-m maclist] [-C] hostname/user@host");
diff --git a/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java b/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
index d42ff7d..d7e29b7 100644
--- a/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
+++ b/sshd-cli/src/test/java/org/apache/sshd/cli/server/SshFsMounter.java
@@ -34,6 +34,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.logging.Level;
+import org.apache.sshd.cli.CliLogger;
import org.apache.sshd.cli.CliSupport;
import org.apache.sshd.common.PropertyResolver;
import org.apache.sshd.common.PropertyResolverUtils;
@@ -297,7 +298,7 @@ public final class SshFsMounter extends SshServerCliSupport {
}
PropertyResolver resolver = PropertyResolverUtils.toPropertyResolver(options);
- Level level = resolveLoggingVerbosity(resolver, args);
+ Level level = CliLogger.resolveLoggingVerbosity(resolver, args);
SshServer sshd = error
? null : setupIoServiceFactory(
CoreTestSupportUtils.setupTestServer(SshFsMounter.class), resolver,
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/NullPrintStream.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/NullPrintStream.java
new file mode 100644
index 0000000..a21c5d2
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/io/NullPrintStream.java
@@ -0,0 +1,172 @@
+/*
+ * 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.PrintStream;
+import java.util.Locale;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class NullPrintStream extends PrintStream {
+ public NullPrintStream() {
+ super(new NullOutputStream());
+ }
+
+ @Override
+ public void write(int b) {
+ // ignored
+ }
+
+ @Override
+ public void write(byte[] buf, int off, int len) {
+ // ignored
+ }
+
+ @Override
+ public void print(boolean b) {
+ // ignored
+ }
+
+ @Override
+ public void print(char c) {
+ append(c);
+ }
+
+ @Override
+ public void print(int i) {
+ print((long) i);
+ }
+
+ @Override
+ public void print(long l) {
+ // ignored
+ }
+
+ @Override
+ public void print(float f) {
+ print((double) f);
+ }
+
+ @Override
+ public void print(double d) {
+ // ignored
+ }
+
+ @Override
+ public void print(char[] s) {
+ // ignored
+ }
+
+ @Override
+ public void print(String s) {
+ // ignored
+ }
+
+ @Override
+ public void print(Object obj) {
+ // ignored
+ }
+
+ @Override
+ public void println() {
+ // ignored
+ }
+
+ @Override
+ public void println(boolean x) {
+ // ignored
+ }
+
+ @Override
+ public void println(char x) {
+ // ignored
+ }
+
+ @Override
+ public void println(int x) {
+ // ignored
+ }
+
+ @Override
+ public void println(long x) {
+ // ignored
+ }
+
+ @Override
+ public void println(float x) {
+ // ignored
+ }
+
+ @Override
+ public void println(double x) {
+ // ignored
+ }
+
+ @Override
+ public void println(char[] x) {
+ // ignored
+ }
+
+ @Override
+ public void println(String x) {
+ // ignored
+ }
+
+ @Override
+ public void println(Object x) {
+ // ignored
+ }
+
+ @Override
+ public PrintStream printf(String format, Object... args) {
+ return printf(Locale.getDefault(), format, args);
+ }
+
+ @Override
+ public PrintStream printf(Locale l, String format, Object... args) {
+ return format(l, format, args);
+ }
+
+ @Override
+ public PrintStream format(String format, Object... args) {
+ return format(Locale.getDefault(), format, args);
+ }
+
+ @Override
+ public PrintStream format(Locale l, String format, Object... args) {
+ return this;
+ }
+
+ @Override
+ public PrintStream append(CharSequence csq) {
+ return append(csq, 0, csq.length());
+ }
+
+ @Override
+ public PrintStream append(CharSequence csq, int start, int end) {
+ return this;
+ }
+
+ @Override
+ public PrintStream append(char c) {
+ return this;
+ }
+}
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/logging/AbstractLoggingBean.java b/sshd-common/src/main/java/org/apache/sshd/common/util/logging/AbstractLoggingBean.java
index 3f31e81..08a5230 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/logging/AbstractLoggingBean.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/logging/AbstractLoggingBean.java
@@ -37,9 +37,11 @@ public abstract class AbstractLoggingBean {
/**
* Default constructor - creates a logger using the full class name
+ *
+ * @see #AbstractLoggingBean(Logger)
*/
protected AbstractLoggingBean() {
- this("");
+ this((Logger) null);
}
/**
@@ -56,6 +58,14 @@ public abstract class AbstractLoggingBean {
log = LoggerFactory.getLogger(name);
}
+ /**
+ * @param logger The {@link Logger} instance to use - if {@code null} then one is retrieved using the full class
+ * name
+ */
+ protected AbstractLoggingBean(Logger logger) {
+ log = (logger == null) ? LoggerFactory.getLogger(getClass()) : logger;
+ }
+
protected SimplifiedLog getSimplifiedLogger() {
SimplifiedLog logger;
synchronized (simplifiedLog) {
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/logging/LoggerSkeleton.java b/sshd-common/src/main/java/org/apache/sshd/common/util/logging/LoggerSkeleton.java
new file mode 100644
index 0000000..50b320a
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/logging/LoggerSkeleton.java
@@ -0,0 +1,169 @@
+/*
+ * 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.logging;
+
+import org.slf4j.helpers.MarkerIgnoringBase;
+
+/**
+ * Provides some more default implementations for {@link org.slf4j.Logger} interface methods
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class LoggerSkeleton extends MarkerIgnoringBase {
+ private static final long serialVersionUID = 1129569061632973648L;
+
+ protected LoggerSkeleton(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void error(String format, Object arg) {
+ if (isErrorEnabled()) {
+ error(format, new Object[] { arg });
+ }
+ }
+
+ @Override
+ public void error(String format, Object arg1, Object arg2) {
+ if (isErrorEnabled()) {
+ error(format, new Object[] { arg1, arg2 });
+ }
+ }
+
+ @Override
+ public void error(String format, Object... arguments) {
+ if (isErrorEnabled()) {
+ error(LoggingUtils.formatMessage(format, arguments));
+ }
+ }
+
+ @Override
+ public void error(String msg) {
+ error(msg, (Throwable) null);
+ }
+
+ @Override
+ public void warn(String format, Object arg) {
+ if (isWarnEnabled()) {
+ warn(format, new Object[] { arg });
+ }
+ }
+
+ @Override
+ public void warn(String format, Object arg1, Object arg2) {
+ if (isWarnEnabled()) {
+ warn(format, new Object[] { arg1, arg2 });
+ }
+ }
+
+ @Override
+ public void warn(String format, Object... arguments) {
+ if (isWarnEnabled()) {
+ warn(LoggingUtils.formatMessage(format, arguments));
+ }
+ }
+
+ @Override
+ public void warn(String msg) {
+ warn(msg, (Throwable) null);
+ }
+
+ @Override
+ public void info(String format, Object arg) {
+ if (isInfoEnabled()) {
+ info(format, new Object[] { arg });
+ }
+ }
+
+ @Override
+ public void info(String format, Object arg1, Object arg2) {
+ if (isInfoEnabled()) {
+ info(format, new Object[] { arg1, arg2 });
+ }
+ }
+
+ @Override
+ public void info(String format, Object... arguments) {
+ if (isInfoEnabled()) {
+ info(LoggingUtils.formatMessage(format, arguments));
+ }
+ }
+
+ @Override
+ public void info(String msg) {
+ if (isInfoEnabled()) {
+ info(msg, (Throwable) null);
+ }
+ }
+
+ @Override
+ public void debug(String format, Object arg) {
+ if (isDebugEnabled()) {
+ debug(format, new Object[] { arg });
+ }
+ }
+
+ @Override
+ public void debug(String format, Object arg1, Object arg2) {
+ if (isDebugEnabled()) {
+ debug(format, new Object[] { arg1, arg2 });
+ }
+ }
+
+ @Override
+ public void debug(String format, Object... arguments) {
+ if (isDebugEnabled()) {
+ debug(LoggingUtils.formatMessage(format, arguments));
+ }
+ }
+
+ @Override
+ public void debug(String msg) {
+ if (isDebugEnabled()) {
+ debug(msg, (Throwable) null);
+ }
+ }
+
+ @Override
+ public void trace(String format, Object arg) {
+ if (isTraceEnabled()) {
+ trace(format, new Object[] { arg });
+ }
+ }
+
+ @Override
+ public void trace(String format, Object arg1, Object arg2) {
+ if (isTraceEnabled()) {
+ trace(format, new Object[] { arg1, arg2 });
+ }
+ }
+
+ @Override
+ public void trace(String format, Object... arguments) {
+ if (isTraceEnabled()) {
+ trace(LoggingUtils.formatMessage(format, arguments));
+ }
+ }
+
+ @Override
+ public void trace(String msg) {
+ trace(msg, (Throwable) null);
+ }
+}
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/logging/LoggingUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/logging/LoggingUtils.java
index 3d592b5..263924b 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/util/logging/LoggingUtils.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/logging/LoggingUtils.java
@@ -38,6 +38,8 @@ import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.NumberUtils;
import org.apache.sshd.common.util.ReflectionUtils;
import org.slf4j.Logger;
+import org.slf4j.helpers.FormattingTuple;
+import org.slf4j.helpers.MessageFormatter;
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
@@ -505,6 +507,23 @@ public final class LoggingUtils {
};
}
+ /**
+ * Formats an {@code slf4j} message using its formatting structure - mainly the usage of <U>positional</U> arguments
+ * - e.g., "Value1={}, Value2={}, ..."
+ *
+ * @param format The formatting instructions - ignored if {@code null}/empty
+ * @param arguments The formatting arguments - ignored if {@code null}/empty
+ * @return The formatted message - or the format itself if no arguments or no format string
+ */
+ public static String formatMessage(String format, Object... arguments) {
+ if (GenericUtils.isEmpty(format) || GenericUtils.isEmpty(arguments)) {
+ return format;
+ }
+
+ FormattingTuple tuple = MessageFormatter.arrayFormat(format, arguments, null);
+ return tuple.getMessage();
+ }
+
public static void debug(Logger log, String message, Object o1, Object o2, Throwable t) {
if (log.isTraceEnabled() && (t != null)) {
log.debug(message, o1, o2, t);
diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/logging/SimplifiedLoggerSkeleton.java b/sshd-common/src/main/java/org/apache/sshd/common/util/logging/SimplifiedLoggerSkeleton.java
new file mode 100644
index 0000000..c890696
--- /dev/null
+++ b/sshd-common/src/main/java/org/apache/sshd/common/util/logging/SimplifiedLoggerSkeleton.java
@@ -0,0 +1,103 @@
+/*
+ * 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.logging;
+
+import java.util.logging.Level;
+
+/**
+ * Routes the effective logging to the {@link SimplifiedLog} methods.
+ *
+ * <B>Note:</B> we need the explicit overrides even though they are defined in {@link SimplifiedLog} as {@code default}
+ * since they are defined as {@code abstract} in the {@code slf4j Logger} interface
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class SimplifiedLoggerSkeleton extends LoggerSkeleton implements SimplifiedLog {
+ public static final SimplifiedLoggerSkeleton EMPTY = new SimplifiedLoggerSkeleton("EMPTY") {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public boolean isEnabledLevel(Level level) {
+ return false;
+ }
+
+ @Override
+ public void log(Level level, Object message, Throwable t) {
+ return;
+ }
+
+ };
+
+ private static final long serialVersionUID = 9207771015837755402L;
+
+ protected SimplifiedLoggerSkeleton(String name) {
+ super(name);
+ }
+
+ @Override
+ public boolean isErrorEnabled() {
+ return SimplifiedLog.super.isErrorEnabled();
+ }
+
+ @Override
+ public void error(String msg, Throwable err) {
+ SimplifiedLog.super.error(msg, err);
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ return SimplifiedLog.super.isWarnEnabled();
+ }
+
+ @Override
+ public void warn(String msg, Throwable err) {
+ SimplifiedLog.super.warn(msg, err);
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ return SimplifiedLog.super.isInfoEnabled();
+ }
+
+ @Override
+ public void info(String msg, Throwable err) {
+ SimplifiedLog.super.info(msg, err);
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ return SimplifiedLog.super.isDebugEnabled();
+ }
+
+ @Override
+ public void debug(String msg, Throwable err) {
+ SimplifiedLog.super.debug(msg, err);
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return SimplifiedLog.super.isTraceEnabled();
+ }
+
+ @Override
+ public void trace(String msg, Throwable err) {
+ SimplifiedLog.super.trace(msg, err);
+ }
+}
diff --git a/sshd-mina/pom.xml b/sshd-mina/pom.xml
index d2f0db8..1d8e4f2 100644
--- a/sshd-mina/pom.xml
+++ b/sshd-mina/pom.xml
@@ -126,6 +126,7 @@
<exclude>**/CipherTest.java</exclude>
<exclude>**/CompressionTest.java</exclude>
<exclude>**/NoServerNoClientTest.java</exclude>
+ <exclude>**/OpenSSHCertificateTest.java</exclude>
<!-- exclude>**/PortForwardingTest.java</exclude -->
<exclude>**/MacTest.java</exclude>
<exclude>**/SpringConfigTest.java</exclude>