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 <lgoldst...@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:d...@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:d...@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:d...@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:d...@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:d...@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:d...@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:d...@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:d...@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>