diff --git a/README.md b/README.md index 33f249495..0f1a66878 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![Build Status](https://travis-ci.com/hivemq/mqtt-cli.svg?branch=develop)](https://travis-ci.com/hivemq/mqtt-cli) [![picocli](https://img.shields.io/github/downloads/hivemq/mqtt-cli/total)](https://github.com/hivemq/mqtt-cli/releases) [![picocli](https://img.shields.io/github/license/hivemq/mqtt-cli)](https://github.com/hivemq/mqtt-cli/blob/develop/LICENSE) -[![picocli](https://img.shields.io/badge/hivemq--mqtt--client-1.1.1-green)](https://github.com/hivemq/hivemq-mqtt-client) +[![picocli](https://img.shields.io/badge/hivemq--mqtt--client-1.1.3-green)](https://github.com/hivemq/hivemq-mqtt-client) [![picocli](https://img.shields.io/badge/picocli-4.0.4-green.svg)](https://github.com/remkop/picocli) MQTT 5.0 and 3.1.1 compatible and feature-rich MQTT Command Line Interface diff --git a/build.gradle b/build.gradle index fb475de94..d6173789d 100644 --- a/build.gradle +++ b/build.gradle @@ -120,8 +120,8 @@ ext { jline3JansiVersion = '3.12.1' daggerVersion = '2.21' guavaVersion ='27.0.1-jre' - hivemqclientVersion = '1.1.1' - tinylogVersion = '1.3.6' + hivemqclientVersion = '1.1.3' + tinylogVersion = '2.0.1' jcToolsVersion = '2.1.2' jetbrainsAnnotationsVersion = '17.0.0' bouncycastleVersion='1.62' @@ -146,7 +146,8 @@ dependencies { implementation group: 'info.picocli', name: 'picocli-codegen', version: picocliVersion implementation group: 'com.google.guava', name: 'guava', version: guavaVersion - implementation group: 'org.tinylog', name: 'tinylog', version: tinylogVersion + implementation "org.tinylog:tinylog-api:$tinylogVersion" + implementation "org.tinylog:tinylog-impl:$tinylogVersion" implementation group: 'org.jetbrains', name: 'annotations', version: jetbrainsAnnotationsVersion implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: bouncycastleVersion @@ -216,8 +217,8 @@ forbiddenApisMain { } forbiddenApis { - bundledSignatures = ['jdk-system-out'] - ignoreFailures = true + bundledSignatures = ['jdk-deprecated', 'jdk-non-portable', 'jdk-reflection' ] + ignoreFailures = false } //disable diff --git a/src/main/java/com/hivemq/cli/DefaultCLIProperties.java b/src/main/java/com/hivemq/cli/DefaultCLIProperties.java index 0a665b9d3..541a59875 100644 --- a/src/main/java/com/hivemq/cli/DefaultCLIProperties.java +++ b/src/main/java/com/hivemq/cli/DefaultCLIProperties.java @@ -24,7 +24,7 @@ import com.hivemq.client.mqtt.MqttVersion; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Level; +import org.tinylog.Level; import javax.inject.Singleton; import java.io.*; @@ -49,7 +49,7 @@ public class DefaultCLIProperties { private static final String MQTT_VERSION = "mqtt.version"; private static final String HOST = "mqtt.host"; private static final String PORT = "mqtt.port"; - private static final String DEBUG_LEVEL_SHELL = "debug.level.shell"; + private static final String LOGFILE_DEBUG_LEVEL = "logfile.level"; private static final String CLIENT_ID_PREFIX = "client.id.prefix"; private static final String CLIENT_ID_LENGTH = "client.id.length"; private static final String SUBSCRIBE_OUTPUT_FILE = "client.subscribe.output"; @@ -67,7 +67,7 @@ public class DefaultCLIProperties { put(MQTT_VERSION, "5"); put(HOST, "localhost"); put(PORT, "1883"); - put(DEBUG_LEVEL_SHELL, "verbose"); + put(LOGFILE_DEBUG_LEVEL, "debug"); put(CLIENT_ID_PREFIX, "mqtt"); put(CLIENT_ID_LENGTH, "8"); put(SUBSCRIBE_OUTPUT_FILE, null); @@ -181,16 +181,18 @@ public int getPort() { } @NotNull - public Level getShellDebugLevel() { - final String shellDebugLevel = propertyToValue.get(DEBUG_LEVEL_SHELL); - switch (shellDebugLevel.toLowerCase()) { + public Level getLogfileDebugLevel() { + final String debugLevel = propertyToValue.get(LOGFILE_DEBUG_LEVEL); + switch (debugLevel.toLowerCase()) { case "trace": case "verbose": return Level.TRACE; case "debug": return Level.DEBUG; case "info": return Level.INFO; + case "warn": return Level.WARN; + case "error": return Level.ERROR; } - throw new IllegalArgumentException("'" + shellDebugLevel + "' is not a valid debug level"); + throw new IllegalArgumentException("'" + debugLevel + "' is not a valid debug level"); } @NotNull diff --git a/src/main/java/com/hivemq/cli/MqttCLIMain.java b/src/main/java/com/hivemq/cli/MqttCLIMain.java index a14cecdd8..78b5d780d 100644 --- a/src/main/java/com/hivemq/cli/MqttCLIMain.java +++ b/src/main/java/com/hivemq/cli/MqttCLIMain.java @@ -23,10 +23,6 @@ import com.hivemq.client.mqtt.MqttClient; import com.hivemq.client.mqtt.mqtt3.Mqtt3Client; import com.hivemq.client.mqtt.mqtt5.Mqtt5Client; -import org.pmw.tinylog.Configurator; -import org.pmw.tinylog.Level; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.writers.ConsoleWriter; import picocli.CommandLine; import java.security.Security; @@ -42,12 +38,6 @@ public static void main(final String[] args) { Security.setProperty("crypto.policy", "unlimited"); - Configurator.defaultConfig() - .writer(new ConsoleWriter()) - .formatPattern("{context:identifier}: {message}") - .level(Level.INFO) - .activate(); - MQTTCLI = DaggerMqttCLI.create(); final CommandLine commandLine = MQTTCLI.cli(); final DefaultCLIProperties defaultCLIProperties = MQTTCLI.defaultCLIProperties(); @@ -55,7 +45,7 @@ public static void main(final String[] args) { try { defaultCLIProperties.init(); } catch (Exception e) { - Logger.error(e.getMessage()); + System.err.println(e.getMessage()); System.exit(-1); } diff --git a/src/main/java/com/hivemq/cli/commands/AbstractCommand.java b/src/main/java/com/hivemq/cli/commands/AbstractCommand.java index 6ef9da1ad..03831373d 100644 --- a/src/main/java/com/hivemq/cli/commands/AbstractCommand.java +++ b/src/main/java/com/hivemq/cli/commands/AbstractCommand.java @@ -17,9 +17,6 @@ package com.hivemq.cli.commands; -import com.hivemq.cli.commands.CliCommand; -import org.pmw.tinylog.Configurator; -import org.pmw.tinylog.Level; import picocli.CommandLine; @CommandLine.Command(sortOptions = false, @@ -39,7 +36,6 @@ private void activateDebugMode(final boolean debug) { if (debug && !verbose) { this.debug = true; - Configurator.currentConfig().level(Level.DEBUG).activate(); } } @@ -49,7 +45,6 @@ private void activateVerboseMode(final boolean verbose) { if (verbose) { this.verbose = true; debug = true; - Configurator.currentConfig().level(Level.TRACE).activate(); } else { this.verbose = false; } diff --git a/src/main/java/com/hivemq/cli/commands/AbstractCommonFlags.java b/src/main/java/com/hivemq/cli/commands/AbstractCommonFlags.java index d8c4e2cf5..01565d0da 100644 --- a/src/main/java/com/hivemq/cli/commands/AbstractCommonFlags.java +++ b/src/main/java/com/hivemq/cli/commands/AbstractCommonFlags.java @@ -16,6 +16,7 @@ */ package com.hivemq.cli.commands; +import com.google.common.base.Throwables; import com.hivemq.cli.DefaultCLIProperties; import com.hivemq.cli.MqttCLIMain; import com.hivemq.cli.converters.*; @@ -24,7 +25,7 @@ import com.hivemq.client.mqtt.MqttWebSocketConfig; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; +import org.tinylog.Logger; import picocli.CommandLine; import javax.net.ssl.KeyManagerFactory; @@ -111,7 +112,7 @@ public void setDefaultOptions() { try { password = defaultCLIProperties.getPassword(); } catch (Exception e) { - logPropertiesException(e, "Default password could not be loaded."); + Logger.error(e,"Default password could not be loaded ({})", Throwables.getRootCause(e).getMessage()); } } @@ -119,7 +120,7 @@ public void setDefaultOptions() { try { clientCertificate = defaultCLIProperties.getClientCertificate(); } catch (Exception e) { - logPropertiesException(e, "Default client certificate could not be loaded."); + Logger.error(e,"Default client certificate could not be loaded ({})", Throwables.getRootCause(e).getMessage()); } } @@ -127,7 +128,7 @@ public void setDefaultOptions() { try { clientPrivateKey = defaultCLIProperties.getClientPrivateKey(); } catch (Exception e) { - logPropertiesException(e, "Default client private key could not be loaded."); + Logger.error(e,"Default client private key could not be loaded ({})", Throwables.getRootCause(e).getMessage()); } } @@ -141,7 +142,7 @@ public void setDefaultOptions() { certificates.add(defaultServerCertificate); } } catch (Exception e) { - logPropertiesException(e, "Default server certificate could not be loaded."); + Logger.error(e,"Default server certificate could not be loaded ({})", Throwables.getRootCause(e).getMessage()); } } @@ -154,34 +155,13 @@ public void setDefaultOptions() { return doBuildSslConfig(); } catch (Exception e) { - logPropertiesException(e); + Logger.error(e, Throwables.getRootCause(e).getMessage()); } } return null; } - private void logPropertiesException(final @NotNull Exception e) { - if (isVerbose()) { - Logger.trace(e); - } - else if (isDebug()) { - Logger.debug(e.getMessage()); - } - Logger.error(MqttUtils.getRootCause(e).getMessage()); - } - - private void logPropertiesException(final @NotNull Exception e, final @NotNull String message) { - if (isVerbose()) { - Logger.trace(e); - } - else if (isDebug()) { - Logger.debug(e.getMessage()); - } - Logger.error(message + " ({})", MqttUtils.getRootCause(e).getMessage()); - } - - private boolean useBuiltSslConfig() { return certificates != null || certificatesFromDir != null || @@ -285,20 +265,14 @@ public String toString() { public String commonOptions() { return super.toString() + - ", user='" + user + '\'' + - ", keepAlive=" + keepAlive + - ", cleanStart=" + cleanStart + + (user != null ? (", user=" + user) : "") + + (keepAlive != null ? (", keepAlive=" + keepAlive) : "") + + (cleanStart != null ? (", cleanStart=" + cleanStart) : "") + ", useDefaultSsl=" + useSsl + - ", sslConfig=" + (getSslConfig() != null) + + (getSslConfig() != null ? (", sslConfig=" + getSslConfig()) : "") + ", useWebSocket=" + useWebSocket + - ", webSocketPath=" + webSocketPath + - ", " + getWillOptions(); - } - - // GETTER AND SETTER - - public void setUseSsl(final boolean useSsl) { - this.useSsl = useSsl; + (webSocketPath != null ? (", webSocketPath=" + webSocketPath) : "") + + getWillOptions(); } @Nullable @@ -315,28 +289,16 @@ public ByteBuffer getPassword() { return password; } - public void setPassword(final @Nullable ByteBuffer password) { - this.password = password; - } - @Nullable public Integer getKeepAlive() { return keepAlive; } - public void setKeepAlive(final @Nullable Integer keepAlive) { - this.keepAlive = keepAlive; - } - @Nullable public Boolean getCleanStart() { return cleanStart; } - public void setCleanStart(final @Nullable Boolean cleanStart) { - this.cleanStart = cleanStart; - } - @Nullable public MqttWebSocketConfig getWebSocketConfig() { if (useWebSocket) { diff --git a/src/main/java/com/hivemq/cli/commands/AbstractConnectRestrictionFlags.java b/src/main/java/com/hivemq/cli/commands/AbstractConnectRestrictionFlags.java index f47417c0b..af6fdc11e 100644 --- a/src/main/java/com/hivemq/cli/commands/AbstractConnectRestrictionFlags.java +++ b/src/main/java/com/hivemq/cli/commands/AbstractConnectRestrictionFlags.java @@ -19,7 +19,7 @@ import com.hivemq.client.mqtt.MqttVersion; import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5ConnectRestrictions; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; +import org.tinylog.Logger; import picocli.CommandLine; public abstract class AbstractConnectRestrictionFlags extends AbstractWillFlags implements ConnectRestrictions { @@ -97,14 +97,14 @@ public void logUnusedOptions() { } public String connectRestrictionOptions() { - return "receiveMaximum=" + receiveMaximum + - ", sendMaximum=" + sendMaximum + - ", maximumPacketSize=" + maximumPacketSize + - ", sendMaximumPacketSize=" + sendMaximumPacketSize + - ", topicAliasMaximum=" + topicAliasMaximum + - ", sendTopicAliasMaximum=" + sendTopicAliasMaximum + - ", requestProblemInformation=" + requestProblemInformation + - ", requestResponseInformation=" + requestResponseInformation; + return (receiveMaximum != null ? (", receiveMaximum=" + receiveMaximum) : "") + + (sendMaximum != null ? (", sendMaximum=" + sendMaximum) : "") + + (maximumPacketSize != null ? (", maximumPacketSize=" + maximumPacketSize) : "") + + (sendMaximumPacketSize != null ? (", sendMaximumPacketSize=" + sendMaximumPacketSize) : "") + + (topicAliasMaximum != null ? (", topicAliasMaximum=" + topicAliasMaximum) : "") + + (sendTopicAliasMaximum != null ? (", sendTopicAliasMaximum=" + sendTopicAliasMaximum) : "") + + (requestProblemInformation != null ? (", requestProblemInformation=" + requestProblemInformation) : "") + + (requestResponseInformation != null ? (", requestResponseInformation=" + requestResponseInformation) : ""); } @Nullable @@ -113,77 +113,46 @@ public Integer getReceiveMaximum() { return receiveMaximum; } - public void setReceiveMaximum(@Nullable final Integer receiveMaximum) { - this.receiveMaximum = receiveMaximum; - } - @Nullable @Override public Integer getSendMaximum() { return sendMaximum; } - public void setSendMaximum(@Nullable final Integer sendMaximum) { - this.sendMaximum = sendMaximum; - } - @Nullable @Override public Integer getMaximumPacketSize() { return maximumPacketSize; } - public void setMaximumPacketSize(@Nullable final Integer maximumPacketSize) { - this.maximumPacketSize = maximumPacketSize; - } - @Nullable @Override public Integer getSendMaximumPacketSize() { return sendMaximumPacketSize; } - public void setSendMaximumPacketSize(@Nullable final Integer sendMaximumPacketSize) { - this.sendMaximumPacketSize = sendMaximumPacketSize; - } - @Nullable @Override public Integer getTopicAliasMaximum() { return topicAliasMaximum; } - public void setTopicAliasMaximum(@Nullable final Integer topicAliasMaximum) { - this.topicAliasMaximum = topicAliasMaximum; - } - @Nullable @Override public Integer getSendTopicAliasMaximum() { return sendTopicAliasMaximum; } - public void setSendTopicAliasMaximum(@Nullable final Integer sendTopicAliasMaximum) { - this.sendTopicAliasMaximum = sendTopicAliasMaximum; - } - @Nullable @Override public Boolean getRequestProblemInformation() { return requestProblemInformation; } - public void setRequestProblemInformation(@Nullable final Boolean requestProblemInformation) { - this.requestProblemInformation = requestProblemInformation; - } - @Nullable @Override public Boolean getRequestResponseInformation() { return requestResponseInformation; } - public void setRequestResponseInformation(@Nullable final Boolean requestResponseInformation) { - this.requestResponseInformation = requestResponseInformation; - } } diff --git a/src/main/java/com/hivemq/cli/commands/AbstractWillFlags.java b/src/main/java/com/hivemq/cli/commands/AbstractWillFlags.java index 9d76526fe..e95b96fcf 100644 --- a/src/main/java/com/hivemq/cli/commands/AbstractWillFlags.java +++ b/src/main/java/com/hivemq/cli/commands/AbstractWillFlags.java @@ -25,10 +25,11 @@ import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator; import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublish; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; +import org.tinylog.Logger; import picocli.CommandLine; import java.nio.ByteBuffer; +import java.util.Arrays; @CommandLine.Command public abstract class AbstractWillFlags extends MqttCommand implements Will { @@ -41,7 +42,7 @@ public abstract class AbstractWillFlags extends MqttCommand implements Will { @Nullable private ByteBuffer willMessage; - @CommandLine.Option(names = {"-Wq", "--willQualityOfService"}, converter = MqttQosConverter.class, description = "Quality of service level for the will message (default: 0)", order = 3) + @CommandLine.Option(names = {"-Wq", "--willQualityOfService"}, defaultValue = "0", converter = MqttQosConverter.class, description = "Quality of service level for the will message (default: 0)", order = 3) @Nullable private MqttQos willQos; @@ -79,17 +80,20 @@ public abstract class AbstractWillFlags extends MqttCommand implements Will { String getWillOptions() { - return "willTopic='" + willTopic + '\'' + - ", willQos=" + willQos + - ", willMessage='" + willMessage + '\'' + - ", willRetain=" + willRetain + - ", willMessageExpiryInterval=" + willMessageExpiryInterval + - ", willDelayInterval=" + willDelayInterval + - ", willPayloadFormatIndicator=" + willPayloadFormatIndicator + - ", willContentType='" + willContentType + '\'' + - ", willResponseTopic='" + willResponseTopic + '\'' + - ", willCorrelationData=" + willCorrelationData + - ", willUserProperties=" + willUserProperties; + if (willTopic == null) { + return ""; + } + return ", willTopic=" + willTopic + + (willQos != null ? (", willQos=" + willQos) : "") + + (willMessage != null ? (", willMessage=" + willMessage) : "") + + (willRetain != null ? (", willRetain=" + willRetain) : "") + + (willMessageExpiryInterval != null ? (", willMessageExpiryInterval=" + willMessageExpiryInterval) : "") + + (willDelayInterval != null ? (", willDelayInterval=" + willDelayInterval) : "") + + (willPayloadFormatIndicator != null ? (", willPayloadFormatIndicator=" + willPayloadFormatIndicator) : "") + + (willContentType != null ? (", willContentType=" + willContentType) : "") + + (willResponseTopic != null ? (", willResponseTopic=" + willResponseTopic) : "") + + (willCorrelationData != null ? (", willCorrelationData=" + willCorrelationData) : "") + + (willUserProperties != null ? (", willUserProperties=" + Arrays.toString(willUserProperties)) : ""); } public void logUnusedOptions() { @@ -124,107 +128,64 @@ public String getWillTopic() { return willTopic; } - public void setWillTopic(@Nullable final String willTopic) { - this.willTopic = willTopic; - } - @Nullable @Override public ByteBuffer getWillMessage() { return willMessage; } - public void setWillMessage(@Nullable final ByteBuffer willMessage) { - this.willMessage = willMessage; - } - @Nullable @Override public MqttQos getWillQos() { return willQos; } - public void setWillQos(@Nullable final MqttQos willQos) { - this.willQos = willQos; - } - @Nullable @Override public Boolean getWillRetain() { return willRetain; } - public void setWillRetain(final @Nullable Boolean willRetain) { - this.willRetain = willRetain; - } - @Nullable @Override public Long getWillMessageExpiryInterval() { return willMessageExpiryInterval; } - public void setWillMessageExpiryInterval(@Nullable final Long willMessageExpiryInterval) { - this.willMessageExpiryInterval = willMessageExpiryInterval; - } - @Nullable @Override public Long getWillDelayInterval() { return willDelayInterval; } - public void setWillDelayInterval(final long willDelayInterval) { - this.willDelayInterval = willDelayInterval; - } - @Nullable @Override public Mqtt5PayloadFormatIndicator getWillPayloadFormatIndicator() { return willPayloadFormatIndicator; } - public void setWillPayloadFormatIndicator(@Nullable final Mqtt5PayloadFormatIndicator willPayloadFormatIndicator) { - this.willPayloadFormatIndicator = willPayloadFormatIndicator; - } - @Nullable @Override public String getWillContentType() { return willContentType; } - public void setWillContentType(@Nullable final String willContentType) { - this.willContentType = willContentType; - } - @Nullable @Override public String getWillResponseTopic() { return willResponseTopic; } - public void setWillResponseTopic(@Nullable final String willResponseTopic) { - this.willResponseTopic = willResponseTopic; - } - @Nullable @Override public ByteBuffer getWillCorrelationData() { return willCorrelationData; } - public void setWillCorrelationData(@Nullable final ByteBuffer willCorrelationData) { - this.willCorrelationData = willCorrelationData; - } - @Nullable @Override public Mqtt5UserProperties getWillUserProperties() { return MqttUtils.convertToMqtt5UserProperties(willUserProperties); } - public void setWillUserProperties(@Nullable final Mqtt5UserProperty... willUserProperties) { - this.willUserProperties = willUserProperties; - } } diff --git a/src/main/java/com/hivemq/cli/commands/MqttCLICommand.java b/src/main/java/com/hivemq/cli/commands/MqttCLICommand.java index 9619f7393..394b41999 100644 --- a/src/main/java/com/hivemq/cli/commands/MqttCLICommand.java +++ b/src/main/java/com/hivemq/cli/commands/MqttCLICommand.java @@ -36,9 +36,7 @@ public class MqttCLICommand { public static final @NotNull String VERSION_STRING = "1.0"; - @Inject - MqttCLICommand() { - } + MqttCLICommand() { } } diff --git a/src/main/java/com/hivemq/cli/commands/MqttCommand.java b/src/main/java/com/hivemq/cli/commands/MqttCommand.java index 21539d246..39c27b422 100644 --- a/src/main/java/com/hivemq/cli/commands/MqttCommand.java +++ b/src/main/java/com/hivemq/cli/commands/MqttCommand.java @@ -26,7 +26,7 @@ import com.hivemq.client.mqtt.MqttVersion; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; +import org.tinylog.Logger; import picocli.CommandLine; import java.util.List; @@ -34,7 +34,6 @@ @CommandLine.Command() public abstract class MqttCommand extends AbstractCommand implements Context { - @CommandLine.Option(names = {"-V", "--mqttVersion"}, converter = MqttVersionConverter.class, description = "The mqtt version used by the client (default: 5)", order = 1) private MqttVersion version; @@ -54,24 +53,19 @@ public abstract class MqttCommand extends AbstractCommand implements Context { public void setDefaultOptions() { final DefaultCLIProperties defaultCLIProperties = MqttCLIMain.MQTTCLI.defaultCLIProperties(); if (version == null) { - if (isVerbose()) { - Logger.trace("Setting value of 'version' to default value: {}", defaultCLIProperties.getMqttVersion()); - } version = defaultCLIProperties.getMqttVersion(); + Logger.trace("Setting value of 'version' to default value: {}", version); } if (host == null) { - if (isVerbose()) { - Logger.trace("Setting value of 'host' to default value: {}", defaultCLIProperties.getHost()); - } host = defaultCLIProperties.getHost(); + Logger.trace("Setting value of 'host' to default value: {}", host); + } if (port == null) { - if (isVerbose()) { - Logger.trace("Setting value of 'port' to default value: {}", defaultCLIProperties.getPort()); - } port = defaultCLIProperties.getPort(); + Logger.trace("Setting value of 'port' to default value: {}", port); } if (identifierPrefix == null) { @@ -86,9 +80,7 @@ public void setDefaultOptions() { else { final String rndID = MqttUtils.buildRandomClientID(defaultCLIProperties.getClientLength()); identifier = identifierPrefix + rndID; - if (isVerbose()) { - Logger.trace("Created 'identifier': {}", identifier); - } + Logger.trace("Created identifier ('{}')", identifier); } } @@ -130,7 +122,7 @@ public String toString() { return "host=" + host + ", port=" + port + ", version=" + version + - ", identifier=" + identifier; + (identifier != null && !identifier.isEmpty() ? (", identifier=" + identifier) : ""); } @Override @@ -154,34 +146,14 @@ public String getHost() { return host; } - public void setHost(final String host) { - this.host = host; - } - public int getPort() { return port; } - public void setPort(final int port) { - this.port = port; - } - @NotNull @Override public String getIdentifier() { return identifier; } - public void setIdentifier(final @Nullable String identifier) { - this.identifier = identifier; - } - - @Nullable - public String getIdentifierPrefix() { - return identifierPrefix; - } - - public void setIdentifierPrefix(final String identifierPrefix) { - this.identifierPrefix = identifierPrefix; - } } diff --git a/src/main/java/com/hivemq/cli/commands/cli/AbstractConnectFlags.java b/src/main/java/com/hivemq/cli/commands/cli/AbstractConnectFlags.java index 57624dfaf..9265542e9 100644 --- a/src/main/java/com/hivemq/cli/commands/cli/AbstractConnectFlags.java +++ b/src/main/java/com/hivemq/cli/commands/cli/AbstractConnectFlags.java @@ -25,9 +25,11 @@ import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; +import org.tinylog.Logger; import picocli.CommandLine; +import java.util.Arrays; + public abstract class AbstractConnectFlags extends AbstractCommonFlags implements Connect { @CommandLine.Option(names = {"-se", "--sessionExpiryInterval"}, converter = UnsignedIntConverter.class, description = "The lifetime of the session of the connected client", order = 2) @@ -41,9 +43,9 @@ public abstract class AbstractConnectFlags extends AbstractCommonFlags implement String connectOptions() { return commonOptions() + - ", sessionExpiryInterval= " + sessionExpiryInterval + - ", userProperties=" + connectUserProperties + - ", " + connectRestrictionOptions(); + (sessionExpiryInterval != null ? (", sessionExpiryInterval=" + sessionExpiryInterval) : "") + + (connectUserProperties != null ? (", userProperties=" + Arrays.toString(connectUserProperties)) : "") + + connectRestrictionOptions(); } @@ -66,17 +68,9 @@ public Long getSessionExpiryInterval() { return sessionExpiryInterval; } - public void setSessionExpiryInterval(@Nullable final Long sessionExpiryInterval) { - this.sessionExpiryInterval = sessionExpiryInterval; - } - @Nullable public Mqtt5UserProperties getConnectUserProperties() { return MqttUtils.convertToMqtt5UserProperties(connectUserProperties); } - public void setConnectUserProperties(@Nullable final Mqtt5UserProperty... connectUserProperties) { - this.connectUserProperties = connectUserProperties; - } - } diff --git a/src/main/java/com/hivemq/cli/commands/cli/PublishCommand.java b/src/main/java/com/hivemq/cli/commands/cli/PublishCommand.java index d4f180277..9ea2d88bb 100644 --- a/src/main/java/com/hivemq/cli/commands/cli/PublishCommand.java +++ b/src/main/java/com/hivemq/cli/commands/cli/PublishCommand.java @@ -16,11 +16,13 @@ */ package com.hivemq.cli.commands.cli; +import com.google.common.base.Throwables; import com.hivemq.cli.MqttCLIMain; import com.hivemq.cli.commands.Publish; import com.hivemq.cli.converters.*; import com.hivemq.cli.impl.MqttAction; import com.hivemq.cli.mqtt.MqttClientExecutor; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.MqttClientSslConfig; import com.hivemq.client.mqtt.MqttVersion; @@ -31,13 +33,16 @@ import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; +import org.tinylog.configuration.Configuration; import picocli.CommandLine; import javax.inject.Inject; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; @CommandLine.Command(name = "pub", versionProvider = MqttCLIMain.CLIVersionProvider.class, @@ -52,14 +57,11 @@ public class PublishCommand extends AbstractConnectFlags implements MqttAction, private MqttClientSslConfig sslConfig; //needed for pico cli - reflection code generation - public PublishCommand() { - this(null); - } + public PublishCommand() { this(null); } @Inject public PublishCommand(final @NotNull MqttClientExecutor mqttClientExecutor) { this.mqttClientExecutor = mqttClientExecutor; - } @CommandLine.Option(names = {"--version"}, versionHelp = true, description = "display version info") @@ -69,78 +71,65 @@ public PublishCommand(final @NotNull MqttClientExecutor mqttClientExecutor) { boolean usageHelpRequested; @CommandLine.Option(names = {"-t", "--topic"}, required = true, description = "The topics to publish to", order = 1) - @NotNull - private String[] topics; + @NotNull private String[] topics; @CommandLine.Option(names = {"-q", "--qos"}, converter = MqttQosConverter.class, defaultValue = "0", description = "Quality of service for the corresponding topic (default for all: 0)", order = 1) - @NotNull - private MqttQos[] qos; + @NotNull private MqttQos[] qos; @CommandLine.Option(names = {"-m", "--message"}, converter = ByteBufferConverter.class, required = true, description = "The message to publish", order = 1) - @NotNull - private ByteBuffer message; + @NotNull private ByteBuffer message; @CommandLine.Option(names = {"-r", "--retain"}, negatable = true, description = "The message will be retained (default: false)", order = 1) - @Nullable - private Boolean retain; + @Nullable private Boolean retain; @CommandLine.Option(names = {"-e", "--messageExpiryInterval"}, converter = UnsignedIntConverter.class, description = "The lifetime of the publish message in seconds (default: no message expiry)", order = 1) - @Nullable - private Long messageExpiryInterval; + @Nullable private Long messageExpiryInterval; @CommandLine.Option(names = {"-pf", "--payloadFormatIndicator"}, converter = PayloadFormatIndicatorConverter.class, description = "The payload format indicator of the publish message", order = 1) - @Nullable - private Mqtt5PayloadFormatIndicator payloadFormatIndicator; + @Nullable private Mqtt5PayloadFormatIndicator payloadFormatIndicator; @CommandLine.Option(names = {"-ct", "--contentType"}, description = "A description of publish message's content", order = 1) - @Nullable - private String contentType; + @Nullable private String contentType; @CommandLine.Option(names = {"-rt", "--responseTopic"}, description = "The topic name for the publish message`s response message", order = 1) - @Nullable - private String responseTopic; + @Nullable private String responseTopic; @CommandLine.Option(names = {"-cd", "--correlationData"}, converter = ByteBufferConverter.class, description = "The correlation data of the publish message", order = 1) - @Nullable - private ByteBuffer correlationData; - + @Nullable private ByteBuffer correlationData; @CommandLine.Option(names = {"-up", "--userProperty"}, converter = Mqtt5UserPropertyConverter.class, description = "A user property of the publish message", order = 1) - @Nullable - private Mqtt5UserProperty[] userProperties; + @Nullable private Mqtt5UserProperty[] userProperties; @Override public void run() { - LoggingContext.put("identifier", "PUBLISH"); + // TinyLog configuration + Map configurationMap = new HashMap() {{ + put("writer1", "console"); + put("writer1.format", "{message-only}"); + put("writer1.level", "warn"); + if (isDebug()) put("writer1.level", "debug"); + if (isVerbose()) put("writer1.level", "trace"); + }}; - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } + LoggerUtils.useDefaultLogging(configurationMap); setDefaultOptions(); sslConfig = buildSslConfig(); + Logger.trace("Command {} ", this); + logUnusedOptions(); try { qos = MqttUtils.arrangeQosToMatchTopics(topics, qos); mqttClientExecutor.publish(this); } + catch (final ConnectionFailedException cex) { + Logger.error(cex, cex.getCause().getMessage()); + } catch (final Exception ex) { - if (ex instanceof ConnectionFailedException) { - LoggingContext.put("identifier", "CONNECT ERROR:"); - } - else { - LoggingContext.put("identifier", "PUBLISH ERROR:"); - } - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } } @@ -174,17 +163,18 @@ public void logUnusedOptions() { @Override public String toString() { - return "Publish:: {" + - "topics=" + Arrays.toString(topics) + + return getClass().getSimpleName() + "{" + + connectOptions() + + ", topics=" + Arrays.toString(topics) + ", qos=" + Arrays.toString(qos) + - ", retain=" + retain + - ", messageExpiryInterval=" + messageExpiryInterval + - ", payloadFormatIndicator=" + payloadFormatIndicator + - ", contentType=" + contentType + - ", responseTopic=" + responseTopic + - ", correlationData=" + correlationData + - ", userProperties=" + getUserProperties() + - ", Connect:: {" + connectOptions() + "}" + + ", message=" + new String(message.array(), StandardCharsets.UTF_8) + + (retain != null ? (", retain=" + retain) : "") + + (messageExpiryInterval != null ? (", messageExpiryInterval=" + messageExpiryInterval) : "") + + (payloadFormatIndicator != null ? (", payloadFormatIndicator=" + payloadFormatIndicator) : "") + + (contentType != null ? (", contentType=" + contentType) : "") + + (responseTopic != null ? (", responseTopic=" + responseTopic) : "") + + (correlationData != null ? (", correlationData=" + new String(correlationData.array(), StandardCharsets.UTF_8)) : "") + + (userProperties != null ? (", userProperties=" + getUserProperties()) : "") + '}'; } @@ -195,20 +185,12 @@ public String[] getTopics() { return topics; } - public void setTopics(final String[] topics) { - this.topics = topics; - } - @NotNull @Override public MqttQos[] getQos() { return qos; } - public void setQos(final MqttQos[] qos) { - this.qos = qos; - } - @NotNull @Override public ByteBuffer getMessage() { @@ -225,60 +207,36 @@ public Boolean getRetain() { return retain; } - public void setRetain(final @Nullable Boolean retain) { - this.retain = retain; - } - @Override @Nullable public Long getMessageExpiryInterval() { return messageExpiryInterval; } - public void setMessageExpiryInterval(@Nullable final Long messageExpiryInterval) { - this.messageExpiryInterval = messageExpiryInterval; - } - @Nullable @Override public Mqtt5PayloadFormatIndicator getPayloadFormatIndicator() { return payloadFormatIndicator; } - public void setPayloadFormatIndicator(@Nullable final Mqtt5PayloadFormatIndicator payloadFormatIndicator) { - this.payloadFormatIndicator = payloadFormatIndicator; - } - @Nullable @Override public String getContentType() { return contentType; } - public void setContentType(@Nullable final String contentType) { - this.contentType = contentType; - } - @Nullable @Override public String getResponseTopic() { return responseTopic; } - public void setResponseTopic(@Nullable final String responseTopic) { - this.responseTopic = responseTopic; - } - @Nullable @Override public ByteBuffer getCorrelationData() { return correlationData; } - public void setCorrelationData(@Nullable final ByteBuffer correlationData) { - this.correlationData = correlationData; - } - @Nullable @Override public Mqtt5UserProperties getUserProperties() { @@ -295,7 +253,4 @@ public MqttClientSslConfig getSslConfig() { return sslConfig; } - public void setSslConfig(final MqttClientSslConfig sslConfig) { - this.sslConfig = sslConfig; - } } diff --git a/src/main/java/com/hivemq/cli/commands/cli/SubscribeCommand.java b/src/main/java/com/hivemq/cli/commands/cli/SubscribeCommand.java index 8dc569df9..42bf47ca0 100644 --- a/src/main/java/com/hivemq/cli/commands/cli/SubscribeCommand.java +++ b/src/main/java/com/hivemq/cli/commands/cli/SubscribeCommand.java @@ -16,6 +16,7 @@ */ package com.hivemq.cli.commands.cli; +import com.google.common.base.Throwables; import com.hivemq.cli.DefaultCLIProperties; import com.hivemq.cli.MqttCLIMain; import com.hivemq.cli.commands.Subscribe; @@ -23,7 +24,9 @@ import com.hivemq.cli.converters.MqttQosConverter; import com.hivemq.cli.impl.MqttAction; import com.hivemq.cli.mqtt.MqttClientExecutor; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; +import com.hivemq.client.mqtt.MqttClient; import com.hivemq.client.mqtt.MqttClientSslConfig; import com.hivemq.client.mqtt.MqttVersion; import com.hivemq.client.mqtt.datatypes.MqttQos; @@ -32,13 +35,15 @@ import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; +import org.tinylog.configuration.Configuration; import picocli.CommandLine; import javax.inject.Inject; import java.io.File; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; @CommandLine.Command(name = "sub", versionProvider = MqttCLIMain.CLIVersionProvider.class, @@ -50,6 +55,7 @@ public class SubscribeCommand extends AbstractConnectFlags implements MqttAction private final MqttClientExecutor mqttClientExecutor; private final DefaultCLIProperties defaultCLIProperties; + private MqttClient subscribeClient; private MqttClientSslConfig sslConfig; @@ -57,7 +63,7 @@ public class SubscribeCommand extends AbstractConnectFlags implements MqttAction //needed for pico cli - reflection code generation public SubscribeCommand() { - this(null,null); + this(null, null); } @Inject @@ -74,19 +80,16 @@ public SubscribeCommand(final @NotNull MqttClientExecutor mqttClientExecutor, boolean usageHelpRequested; @CommandLine.Option(names = {"-t", "--topic"}, required = true, description = "The topics to subscribe to", order = 1) - @NotNull - private String[] topics; + @NotNull private String[] topics; @CommandLine.Option(names = {"-q", "--qos"}, converter = MqttQosConverter.class, defaultValue = "2", description = "Quality of service for the corresponding topics (default for all: 2)", order = 1) - @NotNull - private MqttQos[] qos; + @NotNull private MqttQos[] qos; @CommandLine.Option(names = {"-up", "--userProperty"}, converter = Mqtt5UserPropertyConverter.class, description = "A user property of the subscribe message", order = 1) - @Nullable Mqtt5UserProperty[] userProperties; + @Nullable private Mqtt5UserProperty[] userProperties; @CommandLine.Option(names = {"-of", "--outputToFile"}, description = "A file to which the received publish messages will be written", order = 1) - @Nullable - private File publishFile; + @Nullable private File publishFile; @CommandLine.Option(names = {"-oc", "--outputToConsole"}, hidden = true, defaultValue = "true", description = "The received messages will be written to the console (default: true)", order = 1) private boolean printToSTDOUT; @@ -97,50 +100,41 @@ public SubscribeCommand(final @NotNull MqttClientExecutor mqttClientExecutor, @Override public void run() { - LoggingContext.put("identifier", "SUBSCRIBE"); - + // TinyLog configuration + Map configurationMap = new HashMap() {{ + put("writer1", "console"); + put("writer1.format", "{message-only}"); + put("writer1.level", "warn"); + if (isDebug()) put("writer1.level", "debug"); + if (isVerbose()) put("writer1.level", "trace"); + }}; - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } + LoggerUtils.useDefaultLogging(configurationMap); setDefaultOptions(); - sslConfig = buildSslConfig(); + Logger.trace("Command {} ", this); + logUnusedOptions(); try { qos = MqttUtils.arrangeQosToMatchTopics(topics, qos); - mqttClientExecutor.subscribe(this); + subscribeClient = mqttClientExecutor.subscribe(this); + } + catch (final ConnectionFailedException cex) { + Logger.error(cex, cex.getCause().getMessage()); } catch (final Exception ex) { - if (ex instanceof ConnectionFailedException) { - LoggingContext.put("identifier", "CONNECT ERROR:"); - } - else { - LoggingContext.put("identifier", "SUBSCRIBE ERROR:"); - } - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); + return; } try { stay(); } catch (final InterruptedException ex) { - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } @@ -157,12 +151,9 @@ public void logUnusedOptions() { } private void stay() throws InterruptedException { - while (mqttClientExecutor.isConnected(this)) { + while (subscribeClient.getState().isConnectedOrReconnect()) { Thread.sleep(IDLE_TIME); } - if (isVerbose()) { - Logger.trace("Client disconnected."); - } } @Override @@ -170,9 +161,7 @@ public void setDefaultOptions() { super.setDefaultOptions(); if (publishFile == null && defaultCLIProperties.getClientSubscribeOutputFile() != null) { - if (isVerbose()) { - Logger.trace("Setting value of 'toFile' to {}", defaultCLIProperties.getClientSubscribeOutputFile()); - } + Logger.trace("Setting value of 'toFile' to {}", defaultCLIProperties.getClientSubscribeOutputFile()); publishFile = new File(defaultCLIProperties.getClientSubscribeOutputFile()); } @@ -180,14 +169,14 @@ public void setDefaultOptions() { @Override public String toString() { - return "Subscribe:: {" + + return getClass().getSimpleName() + "{" + + connectOptions() + "topics=" + Arrays.toString(topics) + ", qos=" + Arrays.toString(qos) + - ", userProperties=" + userProperties + - ", toFile=" + publishFile + + (userProperties != null ? (", userProperties=" + Arrays.toString(userProperties)) : "") + + (publishFile != null ? (", publishFile=" + publishFile.getAbsolutePath()) : "") + ", outputToConsole=" + printToSTDOUT + ", base64=" + base64 + - ", Connect:: {" + commonOptions() + "}" + '}'; } @@ -198,65 +187,38 @@ public String[] getTopics() { return topics; } - public void setTopics(final String[] topics) { - this.topics = topics; - } - @NotNull @Override public MqttQos[] getQos() { return qos; } - public void setQos(final MqttQos[] qos) { - this.qos = qos; - } - @Nullable @Override public File getPublishFile() { return publishFile; } - public void setPublishFile(@Nullable final File publishFile) { - this.publishFile = publishFile; - } - public boolean isPrintToSTDOUT() { return printToSTDOUT; } - public void setPrintToSTDOUT(final boolean printToSTDOUT) { - this.printToSTDOUT = printToSTDOUT; - } - public boolean isBase64() { return base64; } - public void setBase64(final boolean base64) { - this.base64 = base64; - } - @Nullable @Override - public Mqtt5UserProperties getUserProperties() { - - return MqttUtils.convertToMqtt5UserProperties(userProperties); - } + public Mqtt5UserProperties getUserProperties() { return MqttUtils.convertToMqtt5UserProperties(userProperties); } public void setUserProperties(@Nullable final Mqtt5UserProperty... userProperties) { this.userProperties = userProperties; } - @Nullable @Override public MqttClientSslConfig getSslConfig() { return sslConfig; } - public void setSslConfig(final MqttClientSslConfig sslConfig) { - this.sslConfig = sslConfig; - } } diff --git a/src/main/java/com/hivemq/cli/commands/shell/ClearScreenCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ClearScreenCommand.java index 9f88a6553..d0d49930c 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ClearScreenCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ClearScreenCommand.java @@ -18,11 +18,9 @@ import com.hivemq.cli.commands.CliCommand; -import org.pmw.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; -import java.io.IOException; import java.util.concurrent.Callable; @@ -37,25 +35,19 @@ public class ClearScreenCommand implements CliCommand, Callable { @Inject - ClearScreenCommand() { - } + ClearScreenCommand() {} @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "display this help message") boolean usageHelpRequested; - public Void call() throws IOException { - - if (isVerbose()) { - Logger.trace("Command: {}", this); - } - + public Void call() { ShellCommand.clearScreen(); return null; } @Override public String toString() { - return "ClearScreen::"; + return this.getClass().getSimpleName(); } @Override diff --git a/src/main/java/com/hivemq/cli/commands/shell/ContextDisconnectCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ContextDisconnectCommand.java index 84b48a6f4..d29a15e0a 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ContextDisconnectCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ContextDisconnectCommand.java @@ -16,21 +16,23 @@ */ package com.hivemq.cli.commands.shell; +import com.google.common.base.Throwables; import com.hivemq.cli.commands.Disconnect; import com.hivemq.cli.converters.Mqtt5UserPropertyConverter; import com.hivemq.cli.converters.UnsignedIntConverter; import com.hivemq.cli.mqtt.MqttClientExecutor; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.MqttVersion; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; +import java.util.Arrays; @CommandLine.Command(name = "dis", aliases = "disconnect", @@ -55,23 +57,18 @@ public ContextDisconnectCommand(final @NotNull MqttClientExecutor executor) { private boolean disconnectAll; @CommandLine.Option(names = {"-e", "--sessionExpiryInterval"}, converter = UnsignedIntConverter.class, description = "The session expiry of the disconnect (default: 0)") - @Nullable - private Long sessionExpiryInterval; + @Nullable private Long sessionExpiryInterval; @CommandLine.Option(names = {"-r", "--reason"}, description = "The reason of the disconnect") - @Nullable - private String reasonString; + @Nullable private String reasonString; @CommandLine.Option(names = {"-up", "--userProperty"}, converter = Mqtt5UserPropertyConverter.class, description = "A user property of the disconnect message") - @Nullable - private Mqtt5UserProperty[] userProperties; + @Nullable private Mqtt5UserProperty[] userProperties; @Override public void run() { - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } + Logger.trace("Command {} ", this); logUnusedDisconnectOptions(); @@ -84,14 +81,7 @@ public void run() { } } catch (final Exception ex) { - LoggingContext.put("identifier", "DISCONNECT"); - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } } @@ -114,8 +104,12 @@ private void logUnusedDisconnectOptions() { @Override public String toString() { - return "ContextDisconnect:: {" + + return getClass().getSimpleName() + "{" + "key=" + getKey() + + ", all=" + disconnectAll + + (sessionExpiryInterval != null ? (", sessionExpiryInterval=" + sessionExpiryInterval) : "") + + (reasonString != null ? (", reasonString=" + reasonString) : "") + + (userProperties != null ? (", userProperties=" + Arrays.toString(userProperties)) : "") + "}"; } @@ -125,20 +119,12 @@ public Long getSessionExpiryInterval() { return sessionExpiryInterval; } - public void setSessionExpiryInterval(@Nullable final Long sessionExpiryInterval) { - this.sessionExpiryInterval = sessionExpiryInterval; - } - @Nullable @Override public String getReasonString() { return reasonString; } - public void setReasonString(@Nullable final String reasonString) { - this.reasonString = reasonString; - } - @Nullable @Override public Mqtt5UserProperties getUserProperties() { diff --git a/src/main/java/com/hivemq/cli/commands/shell/ContextExitCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ContextExitCommand.java index 145e94e4f..51dc6bd6b 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ContextExitCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ContextExitCommand.java @@ -19,7 +19,6 @@ import com.hivemq.cli.mqtt.MqttClientExecutor; import org.jetbrains.annotations.NotNull; -import org.pmw.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; @@ -42,16 +41,12 @@ public ContextExitCommand(@NotNull MqttClientExecutor mqttClientExecutor) { @Override public void run() { - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } - removeContext(); } @Override public String toString() { - return "ContextExit::"; + return getClass().getSimpleName(); } } diff --git a/src/main/java/com/hivemq/cli/commands/shell/ContextPublishCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ContextPublishCommand.java index 80ad4af3c..f75ead076 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ContextPublishCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ContextPublishCommand.java @@ -16,9 +16,11 @@ */ package com.hivemq.cli.commands.shell; +import com.google.common.base.Throwables; import com.hivemq.cli.commands.Publish; import com.hivemq.cli.converters.*; import com.hivemq.cli.mqtt.MqttClientExecutor; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.MqttVersion; import com.hivemq.client.mqtt.datatypes.MqttQos; @@ -27,12 +29,12 @@ import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Arrays; @@ -57,67 +59,47 @@ public ContextPublishCommand(final @NotNull MqttClientExecutor executor) { boolean usageHelpRequested; @CommandLine.Option(names = {"-t", "--topic"}, required = true, description = "The topics to publish to") - @NotNull - private String[] topics; + @NotNull private String[] topics; @CommandLine.Option(names = {"-q", "--qos"}, converter = MqttQosConverter.class, defaultValue = "0", description = "Quality of service for the corresponding topic (default for all: 0)") - @NotNull - private MqttQos[] qos; + @NotNull private MqttQos[] qos; @CommandLine.Option(names = {"-m", "--message"}, converter = ByteBufferConverter.class, required = true, description = "The message to publish") - @NotNull - private ByteBuffer message; + @NotNull private ByteBuffer message; @CommandLine.Option(names = {"-r", "--retain"}, negatable = true, defaultValue = "false", description = "The message will be retained (default: false)") - @Nullable - private Boolean retain; + @Nullable private Boolean retain; @CommandLine.Option(names = {"-e", "--messageExpiryInterval"}, converter = UnsignedIntConverter.class, description = "The lifetime of the publish message in seconds (default: no message expiry)") - @Nullable - private Long messageExpiryInterval; + @Nullable private Long messageExpiryInterval; @CommandLine.Option(names = {"-pf", "--payloadFormatIndicator"}, converter = PayloadFormatIndicatorConverter.class, description = "The payload format indicator of the publish message") - @Nullable - private Mqtt5PayloadFormatIndicator payloadFormatIndicator; + @Nullable private Mqtt5PayloadFormatIndicator payloadFormatIndicator; @CommandLine.Option(names = {"-ct", "--contentType"}, description = "A description of publish message's content") - @Nullable - private String contentType; + @Nullable private String contentType; @CommandLine.Option(names = {"-rt", "--responseTopic"}, description = "The topic name for the publish message`s response message") - @Nullable - private String responseTopic; + @Nullable private String responseTopic; @CommandLine.Option(names = {"-cd", "--correlationData"}, converter = ByteBufferConverter.class, description = "The correlation data of the publish message") - @Nullable - private ByteBuffer correlationData; + @Nullable private ByteBuffer correlationData; @CommandLine.Option(names = {"-up", "--userProperty"}, converter = Mqtt5UserPropertyConverter.class, description = "A user property of the publish message") - @Nullable - private Mqtt5UserProperty[] userProperties; - + @Nullable private Mqtt5UserProperty[] userProperties; @Override public void run() { logUnusedOptions(); - if (isVerbose()) { - Logger.trace("Command {} ", this); - } + Logger.trace("Command {} ", this); try { qos = MqttUtils.arrangeQosToMatchTopics(topics, qos); mqttClientExecutor.publish(contextClient, this); } catch (final Exception ex) { - LoggingContext.put("identifier", "PUBLISH"); - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } } @@ -146,17 +128,18 @@ private void logUnusedOptions() { @Override public String toString() { - return "ContextPublish:: {" + + return getClass().getSimpleName() + "{" + "key=" + getKey() + ", topics=" + Arrays.toString(topics) + ", qos=" + Arrays.toString(qos) + + ", message=" + new String(message.array(), StandardCharsets.UTF_8) + ", retain=" + retain + - ", messageExpiryInterval=" + messageExpiryInterval + - ", payloadFormatIndicator=" + payloadFormatIndicator + - ", contentType=" + contentType + - ", responseTopic=" + responseTopic + - ", correlationData=" + correlationData + - ", userProperties=" + userProperties + + (messageExpiryInterval != null ? (", messageExpiryInterval=" + messageExpiryInterval) : "") + + (payloadFormatIndicator != null ? (", payloadFormatIndicator=" + payloadFormatIndicator) : "") + + (contentType != null ? (", contentType=" + contentType) : "") + + (responseTopic != null ? (", responseTopic=" + responseTopic) : "") + + (correlationData != null ? (", correlationData=" + new String(correlationData.array(), StandardCharsets.UTF_8)) : "") + + (userProperties != null ? (", userProperties=" + Arrays.toString(userProperties)) : "") + '}'; } @@ -166,20 +149,12 @@ public String[] getTopics() { return topics; } - public void setTopics(final String[] topics) { - this.topics = topics; - } - @NotNull @Override public MqttQos[] getQos() { return qos; } - public void setQos(final MqttQos[] qos) { - this.qos = qos; - } - @NotNull @Override public ByteBuffer getMessage() { @@ -196,60 +171,36 @@ public Boolean getRetain() { return retain; } - public void setRetain(final @Nullable Boolean retain) { - this.retain = retain; - } - @Nullable @Override public Long getMessageExpiryInterval() { return messageExpiryInterval; } - public void setMessageExpiryInterval(@Nullable final Long messageExpiryInterval) { - this.messageExpiryInterval = messageExpiryInterval; - } - @Nullable @Override public Mqtt5PayloadFormatIndicator getPayloadFormatIndicator() { return payloadFormatIndicator; } - public void setPayloadFormatIndicator(@Nullable final Mqtt5PayloadFormatIndicator payloadFormatIndicator) { - this.payloadFormatIndicator = payloadFormatIndicator; - } - @Nullable @Override public String getContentType() { return contentType; } - public void setContentType(@Nullable final String contentType) { - this.contentType = contentType; - } - @Nullable @Override public String getResponseTopic() { return responseTopic; } - public void setResponseTopic(@Nullable final String responseTopic) { - this.responseTopic = responseTopic; - } - @Nullable @Override public ByteBuffer getCorrelationData() { return correlationData; } - public void setCorrelationData(@Nullable final ByteBuffer correlationData) { - this.correlationData = correlationData; - } - @Nullable @Override public Mqtt5UserProperties getUserProperties() { diff --git a/src/main/java/com/hivemq/cli/commands/shell/ContextSubscribeCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ContextSubscribeCommand.java index f07f77111..9af349358 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ContextSubscribeCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ContextSubscribeCommand.java @@ -16,6 +16,7 @@ */ package com.hivemq.cli.commands.shell; +import com.google.common.base.Throwables; import com.hivemq.cli.DefaultCLIProperties; import com.hivemq.cli.commands.Subscribe; import com.hivemq.cli.commands.Unsubscribe; @@ -30,8 +31,7 @@ import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; @@ -48,7 +48,6 @@ public class ContextSubscribeCommand extends ShellContextCommand implements Runnable, Subscribe, Unsubscribe { public static final int IDLE_TIME = 1000; - private final DefaultCLIProperties defaultCLIProperties; //needed for pico cli - reflection code generation @@ -63,24 +62,20 @@ public ContextSubscribeCommand(final @NotNull MqttClientExecutor mqttClientExecu this.defaultCLIProperties = defaultCLIProperties; } - @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "display this help message") boolean usageHelpRequested; @CommandLine.Option(names = {"-t", "--topic"}, required = true, description = "The topics to subscribe to") - @NotNull - private String[] topics; + @NotNull private String[] topics; @CommandLine.Option(names = {"-q", "--qos"}, converter = MqttQosConverter.class, defaultValue = "2", description = "Quality of service for the corresponding topics (default for all: 2)") - @NotNull - private MqttQos[] qos; + @NotNull private MqttQos[] qos; @CommandLine.Option(names = {"-up", "--userProperty"}, converter = Mqtt5UserPropertyConverter.class, description = "A user property of the subscribe message") @Nullable Mqtt5UserProperty[] userProperties; @CommandLine.Option(names = {"-of", "--outputToFile"}, description = "A file to which the received publish messages will be written") - @Nullable - private File publishFile; + @Nullable private File publishFile; @CommandLine.Option(names = {"-oc", "--outputToConsole"}, defaultValue = "false", description = "The received messages will be written to the console (default: false)") private boolean printToSTDOUT; @@ -94,10 +89,7 @@ public ContextSubscribeCommand(final @NotNull MqttClientExecutor mqttClientExecu @Override public void run() { - - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } + Logger.trace("Command {} ", this); setDefaultOptions(); @@ -107,20 +99,12 @@ public void run() { printToSTDOUT = true; } - try { qos = MqttUtils.arrangeQosToMatchTopics(topics, qos); mqttClientExecutor.subscribe(contextClient, this); } catch (final Exception ex) { - LoggingContext.put("identifier", "SUBSCRIBE"); - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } if (stay) { @@ -128,13 +112,7 @@ else if (isDebug()) { stay(); } catch (final InterruptedException ex) { - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } } } @@ -143,20 +121,16 @@ private void stay() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); - final Runnable waitForDisconnectRunnable = new Runnable() { - - @Override - public void run() { - while (contextClient.getState().isConnected()) { - try { - Thread.sleep(IDLE_TIME); - } - catch (final InterruptedException e) { - return; - } + final Runnable waitForDisconnectRunnable = () -> { + while (contextClient.getState().isConnected()) { + try { + Thread.sleep(IDLE_TIME); + } + catch (final InterruptedException e) { + return; } - latch.countDown(); } + latch.countDown(); }; final Runnable waitForExitCommandRunnable = new Runnable() { @@ -165,7 +139,6 @@ public void run() { final Scanner scanner = new Scanner(System.in); scanner.nextLine(); latch.countDown(); - return; } }; @@ -179,7 +152,6 @@ public void run() { WORKER_THREADS.shutdownNow(); if (!contextClient.getState().isConnectedOrReconnect()) { - Logger.info("Client disconnected."); removeContext(); } else { @@ -190,14 +162,14 @@ public void run() { @Override public String toString() { - return "ContextSubscribe:: {" + + return getClass().getSimpleName() + "{" + "key=" + getKey() + ", topics=" + Arrays.toString(topics) + ", qos=" + Arrays.toString(qos) + - ", userProperties=" + userProperties + - ", toFile=" + publishFile + ", outputToConsole=" + printToSTDOUT + ", base64=" + base64 + + (userProperties != null ? (", userProperties=" + Arrays.toString(userProperties)) : "") + + (publishFile != null ? (", publishFile=" + publishFile.getAbsolutePath()) : "") + '}'; } @@ -225,44 +197,24 @@ public String[] getTopics() { return topics; } - public void setTopics(final String[] topics) { - this.topics = topics; - } - @NotNull public MqttQos[] getQos() { return qos; } - public void setQos(final MqttQos[] qos) { - this.qos = qos; - } - @Nullable public File getPublishFile() { return publishFile; } - public void setPublishFile(@Nullable final File publishFile) { - this.publishFile = publishFile; - } - public boolean isPrintToSTDOUT() { return printToSTDOUT; } - public void setPrintToSTDOUT(final boolean printToSTDOUT) { - this.printToSTDOUT = printToSTDOUT; - } - public boolean isBase64() { return base64; } - public void setBase64(final boolean base64) { - this.base64 = base64; - } - @Override @Nullable public Mqtt5UserProperties getUserProperties() { diff --git a/src/main/java/com/hivemq/cli/commands/shell/ContextSwitchCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ContextSwitchCommand.java index 075c9e015..5c27dc8b7 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ContextSwitchCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ContextSwitchCommand.java @@ -16,13 +16,13 @@ */ package com.hivemq.cli.commands.shell; +import com.google.common.base.Throwables; import com.hivemq.cli.commands.Context; import com.hivemq.cli.mqtt.MqttClientExecutor; -import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.MqttClient; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; +import org.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; @@ -70,29 +70,18 @@ public void run() { extractKeyFromContextName(contextName); } catch (final IllegalArgumentException ex) { - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); return; } } - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } + Logger.trace("Command {} ", this); final MqttClient client = mqttClientExecutor.getMqttClient(this); if (client != null) { updateContext(client); } else { - if (isVerbose()) { - Logger.trace("Client with key: {} not in Cache", getKey()); - } Logger.error("Context {}@{} not found", identifier, host); } } @@ -120,9 +109,9 @@ public String getKey() { @Override public String toString() { - return "ContextSwitch:: {" + - "contextName='" + contextName + '\'' + - ", key=" + getKey() + + return getClass().getSimpleName() + "{" + + "identifier=" + identifier + + ", host=" + host + '}'; } @@ -131,10 +120,6 @@ public String getHost() { return host; } - public void setHost(final String host) { - this.host = host; - } - @Override @NotNull public String getIdentifier() { diff --git a/src/main/java/com/hivemq/cli/commands/shell/ContextUnsubscribeCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ContextUnsubscribeCommand.java index 74e2b6f4b..5845e9be6 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ContextUnsubscribeCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ContextUnsubscribeCommand.java @@ -16,17 +16,18 @@ */ package com.hivemq.cli.commands.shell; +import com.google.common.base.Throwables; import com.hivemq.cli.commands.Unsubscribe; import com.hivemq.cli.converters.Mqtt5UserPropertyConverter; import com.hivemq.cli.mqtt.MqttClientExecutor; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.MqttVersion; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; @@ -52,32 +53,24 @@ public ContextUnsubscribeCommand(@NotNull MqttClientExecutor mqttClientExecutor) boolean usageHelpRequested; @CommandLine.Option(names = {"-t", "--topic"}, required = true, description = "The topics to publish to") - @NotNull - private String[] topics; + @NotNull private String[] topics; @CommandLine.Option(names = {"-up", "--userProperty"}, converter = Mqtt5UserPropertyConverter.class, description = "A user property for the unsubscribe message") @Nullable private Mqtt5UserProperty[] userProperties; - @Override public void run() { - if (isVerbose()) { - Logger.trace("Command {} ", this); - } + + Logger.trace("Command {} ", this); + + logUnusedUnsubscribeOptions(); try { mqttClientExecutor.unsubscribe(contextClient, this); } catch (final Exception ex) { - LoggingContext.put("identifier", "UNSUBSCRIBE"); - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } } @@ -91,10 +84,10 @@ private void logUnusedUnsubscribeOptions() { @Override public String toString() { - return "ContextUnsubscribe:: {" + + return getClass().getSimpleName() + "{" + "key=" + getKey() + ", topics=" + Arrays.toString(topics) + - ", userProperties=" + userProperties + + (userProperties != null ? (", userProperties=" + Arrays.toString(userProperties)) : "") + '}'; } @@ -104,10 +97,6 @@ public String[] getTopics() { return topics; } - public void setTopics(final String[] topics) { - this.topics = topics; - } - @Override @Nullable public Mqtt5UserProperties getUserProperties() { diff --git a/src/main/java/com/hivemq/cli/commands/shell/ListClientsCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ListClientsCommand.java index d5c88e629..24cc06279 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ListClientsCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ListClientsCommand.java @@ -20,12 +20,12 @@ import com.hivemq.cli.mqtt.ClientData; import com.hivemq.cli.mqtt.MqttClientExecutor; import com.hivemq.client.mqtt.MqttClient; -import com.hivemq.client.mqtt.MqttClientState; import org.jetbrains.annotations.NotNull; -import org.pmw.tinylog.Logger; +import org.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; +import java.io.PrintWriter; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -66,20 +66,17 @@ public ListClientsCommand() { @CommandLine.Option(names = {"-s", "--subscriptions"}, defaultValue = "false", description = "list subscribed topics of clients") private boolean listSubscriptions; - - - @Override public void run() { - if (isVerbose()) { - Logger.trace("Command: {}", this); - } + Logger.trace("Command {}", this); final List sortedClientData = getSortedClientData(); + final PrintWriter writer = ShellCommand.TERMINAL_WRITER; + if (longOutput) { - System.out.println("total " + sortedClientData.size()); + writer.println("total " + sortedClientData.size()); if (sortedClientData.size() == 0) { return; @@ -131,7 +128,7 @@ public void run() { final String connectionState = client.getState().toString(); - System.out.printf(format, + writer.printf(format, connectionState, dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond(), client.getConfig().getClientIdentifier().get().toString(), @@ -141,7 +138,7 @@ public void run() { client.getConfig().getSslConfig().map(ssl -> ssl.getProtocols().get().toString()).orElse("NO_SSL")); if (listSubscriptions) { - System.out.printf(" -subscribed topics: %s\n", clientData.getSubscribedTopics()); + writer.printf(" -subscribed topics: %s\n", clientData.getSubscribedTopics()); } } @@ -149,9 +146,9 @@ public void run() { } else { for (final ClientData clientData : sortedClientData) { - System.out.println(clientData.getClient().getConfig().getClientIdentifier().get() + "@" + clientData.getClient().getConfig().getServerHost()); + writer.println(clientData.getClient().getConfig().getClientIdentifier().get() + "@" + clientData.getClient().getConfig().getServerHost()); if (listSubscriptions) { - System.out.printf(" -subscribed topics: %s\n", clientData.getSubscribedTopics()); + writer.printf(" -subscribed topics: %s\n", clientData.getSubscribedTopics()); } } } @@ -190,9 +187,12 @@ public List getSortedClientData() { @Override public String toString() { - return "List:: {" + + return getClass().getSimpleName() + "{" + "sortByTime=" + sortByTime + - ", detailedOutput=" + longOutput + + ", doNotSort=" + doNotSort + + ", reverse=" + reverse + + ", listSubscriptions" + listSubscriptions + + ", longOutput=" + longOutput + '}'; } diff --git a/src/main/java/com/hivemq/cli/commands/shell/ShellCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ShellCommand.java index 32abdf0e3..e1397b1ff 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ShellCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ShellCommand.java @@ -17,9 +17,10 @@ package com.hivemq.cli.commands.shell; +import com.google.common.base.Throwables; import com.hivemq.cli.DefaultCLIProperties; import com.hivemq.cli.MqttCLIMain; -import com.hivemq.cli.utils.MqttUtils; +import com.hivemq.cli.utils.LoggerUtils; import org.jetbrains.annotations.NotNull; import org.jline.reader.*; import org.jline.reader.impl.DefaultParser; @@ -28,20 +29,15 @@ import org.jline.terminal.TerminalBuilder; import org.jline.utils.AttributedStringBuilder; import org.jline.utils.AttributedStyle; -import org.pmw.tinylog.Configurator; -import org.pmw.tinylog.Level; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; -import org.pmw.tinylog.labelers.TimestampLabeler; -import org.pmw.tinylog.policies.SizePolicy; -import org.pmw.tinylog.writers.ConsoleWriter; -import org.pmw.tinylog.writers.RollingFileWriter; +import org.tinylog.Logger; +import org.tinylog.configuration.Configuration; import picocli.CommandLine; import picocli.shell.jline3.PicocliJLineCompleter; import javax.inject.Inject; -import java.io.File; import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; @CommandLine.Command(name = "shell", aliases = "sh", versionProvider = MqttCLIMain.CLIVersionProvider.class, @@ -94,48 +90,15 @@ public class ShellCommand implements Runnable { @Override public void run() { - final Level debugLevel = defaultCLIProperties.getShellDebugLevel(); - switch (debugLevel) { - case TRACE: - VERBOSE = true; - DEBUG = false; - break; - case DEBUG: - VERBOSE = false; - DEBUG = true; - break; - case INFO: - VERBOSE = false; - DEBUG = false; - break; - } - - final String dir = defaultCLIProperties.getLogfilePath(); - - final File dirFile = new File(dir); - dirFile.mkdirs(); - - final String logfileFormatPattern = "{date:yyyy-MM-dd HH:mm:ss}: {{level}:|min-size=6} {context:identifier}: {message}"; - - final RollingFileWriter logfileWriter = new RollingFileWriter(dir + "hmq-cli.log", 30, false, new TimestampLabeler("yyyy-MM-dd"), new SizePolicy(1024 * 10)); + Map configurationMap = new HashMap() {{ + put("writer1", "console"); + put("writer1.format", "{message-only}"); + put("writer1.level", "warn"); + }}; - Configurator.defaultConfig() - .writer(logfileWriter, - debugLevel, - logfileFormatPattern) - .addWriter(new ConsoleWriter(), - Level.INFO, - "{message}") - .activate(); - - LoggingContext.put("identifier", "SHELL"); - - logfilePath = logfileWriter.getFilename(); - - if (VERBOSE) { - Logger.trace("Command: {} ", this); - } + LoggerUtils.useDefaultLogging(configurationMap); + logfilePath = Configuration.get("writer.file"); interact(); } @@ -170,13 +133,15 @@ private void interact() { TERMINAL_WRITER.println(shellCommandLine.getUsageMessage()); TERMINAL_WRITER.flush(); - Logger.info("Using default values from properties file {}:", defaultCLIProperties.getFile().getPath()); - Logger.info("Host: {}, Port: {}, Mqtt-Version {}, Shell-Debug-Level: {}", + TERMINAL_WRITER.printf("Using default values from properties file %s:\n", defaultCLIProperties.getFile().getPath()); + TERMINAL_WRITER.printf("Host: %s, Port: %d, Mqtt-Version %s, Logfile-Debug-Level: %s\n", defaultCLIProperties.getHost(), defaultCLIProperties.getPort(), defaultCLIProperties.getMqttVersion(), - defaultCLIProperties.getShellDebugLevel()); - Logger.info("Writing Logfile to {}", logfilePath); + defaultCLIProperties.getLogfileDebugLevel()); + TERMINAL_WRITER.printf("Writing Logfile to %s\n", logfilePath); + + Logger.info("--- Shell-Mode started ---"); String line; while (!exitShell) { @@ -188,38 +153,15 @@ private void interact() { currentCommandLine.execute(arguments); } } catch (final UserInterruptException e) { - if (VERBOSE) { - Logger.trace("User interrupted shell: {}", e); - } + Logger.trace("--- User interrupted shell ---"); return; - } catch (final EndOfFileException e) { - if (VERBOSE) { - Logger.trace(e); - } - else if (DEBUG) { - Logger.debug(e.getMessage()); - } - Logger.error(MqttUtils.getRootCause(e).getMessage()); - return; - } catch (final Exception all) { - if (DEBUG) { - Logger.trace(all); - } - else if (VERBOSE) { - Logger.debug(all.getMessage()); - } - Logger.error(MqttUtils.getRootCause(all).getMessage()); + } catch (final Exception ex) { + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } } - } catch (final Throwable t) { - if (VERBOSE) { - Logger.trace(t); - } - else if (DEBUG) { - Logger.debug(t.getMessage()); - } - Logger.error(MqttUtils.getRootCause(t).getMessage()); - + Logger.info("--- Shell-Mode exited ---"); + } catch (final Exception ex) { + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } } @@ -252,7 +194,6 @@ static void readFromShell() { .toAnsi(); } - static void usage(Object command) { currentCommandLine.usage(command, System.out); } @@ -275,7 +216,7 @@ static boolean isDebug() { @Override public String toString() { - return "Shell:: {" + + return getClass().getSimpleName() + "{" + "logfilePath=" + logfilePath + ", debug=" + DEBUG + ", verbose=" + VERBOSE + diff --git a/src/main/java/com/hivemq/cli/commands/shell/ShellConnectCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ShellConnectCommand.java index 345ec9fb0..12afbc80c 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ShellConnectCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ShellConnectCommand.java @@ -16,24 +16,27 @@ */ package com.hivemq.cli.commands.shell; +import com.google.common.base.Throwables; import com.hivemq.cli.commands.AbstractCommonFlags; import com.hivemq.cli.commands.Connect; import com.hivemq.cli.converters.Mqtt5UserPropertyConverter; import com.hivemq.cli.converters.UnsignedIntConverter; import com.hivemq.cli.mqtt.MqttClientExecutor; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.MqttClient; import com.hivemq.client.mqtt.MqttClientSslConfig; import com.hivemq.client.mqtt.MqttVersion; +import com.hivemq.client.mqtt.exceptions.ConnectionFailedException; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; +import java.util.Arrays; @CommandLine.Command(name = "con", aliases = "connect", @@ -43,9 +46,7 @@ public class ShellConnectCommand extends AbstractCommonFlags implements Runnable, Connect { private final MqttClientExecutor mqttClientExecutor; - - @Nullable - private MqttClientSslConfig sslConfig; + @Nullable private MqttClientSslConfig sslConfig; //needed for pico cli - reflection code generation public ShellConnectCommand() { @@ -54,7 +55,6 @@ public ShellConnectCommand() { @Inject public ShellConnectCommand(@NotNull final MqttClientExecutor mqttClientExecutor) { - this.mqttClientExecutor = mqttClientExecutor; } @@ -62,47 +62,32 @@ public ShellConnectCommand(@NotNull final MqttClientExecutor mqttClientExecutor) boolean usageHelpRequested; @CommandLine.Option(names = {"-se", "--sessionExpiryInterval"}, converter = UnsignedIntConverter.class, description = "The lifetime of the session of the connected client'") - @Nullable - private Long sessionExpiryInterval; + @Nullable private Long sessionExpiryInterval; @CommandLine.Option(names = {"-up", "--userProperty"}, converter = Mqtt5UserPropertyConverter.class, description = "A user property of the connect message") - @Nullable - private Mqtt5UserProperty[] connectUserProperties; - + @Nullable private Mqtt5UserProperty[] connectUserProperties; public void run() { - setDefaultOptions(); - sslConfig = buildSslConfig(); - logUnusedOptions(); - final MqttClient client = connect(); - sslConfig = null; - ShellContextCommand.updateContext(client); } private @Nullable MqttClient connect() { - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } + + Logger.trace("Command {} ", this); try { - MqttClient client = mqttClientExecutor.connect(this); - return client; + return mqttClientExecutor.connect(this); + } + catch (final ConnectionFailedException cex) { + Logger.error(cex, cex.getCause().getMessage()); } catch (final Exception ex) { - LoggingContext.put("identifier", "CONNECT"); - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } return null; } @@ -123,15 +108,15 @@ public void logUnusedOptions() { String connectOptions() { return commonOptions() + - ", sessionExpiryInterval= " + sessionExpiryInterval + - ", userProperties=" + connectUserProperties + - ", " + connectRestrictionOptions(); + (sessionExpiryInterval != null ? (", sessionExpiryInterval=" + sessionExpiryInterval) : "") + + (connectUserProperties != null ? (", userProperties=" + Arrays.toString(connectUserProperties)) : "") + + connectRestrictionOptions(); } @Override public String toString() { - return "ShellConnectCommand:: {" + connectOptions() + "}"; + return getClass().getSimpleName() + "{" + connectOptions() + "}"; } @Override @@ -149,26 +134,15 @@ public Long getSessionExpiryInterval() { return sessionExpiryInterval; } - public void setSessionExpiryInterval(@Nullable final Long sessionExpiryInterval) { - this.sessionExpiryInterval = sessionExpiryInterval; - } - @Nullable public Mqtt5UserProperties getConnectUserProperties() { return MqttUtils.convertToMqtt5UserProperties(connectUserProperties); } - public void setConnectUserProperties(@Nullable final Mqtt5UserProperty... connectUserProperties) { - this.connectUserProperties = connectUserProperties; - } - @Nullable @Override public MqttClientSslConfig getSslConfig() { return sslConfig; } - public void setSslConfig(final MqttClientSslConfig sslConfig) { - this.sslConfig = sslConfig; - } } diff --git a/src/main/java/com/hivemq/cli/commands/shell/ShellContextCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ShellContextCommand.java index 0360691f8..d11424fe5 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ShellContextCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ShellContextCommand.java @@ -22,8 +22,6 @@ import com.hivemq.client.mqtt.MqttClient; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; import picocli.CommandLine; import javax.inject.Inject; @@ -53,29 +51,21 @@ public ShellContextCommand(final @NotNull MqttClientExecutor mqttClientExecutor) this.mqttClientExecutor = mqttClientExecutor; } - public static void updateContext(final @Nullable MqttClient client) { + static void updateContext(final @Nullable MqttClient client) { if (client != null && client.getConfig().getState().isConnectedOrReconnect()) { - if (ShellCommand.isVerbose()) { - Logger.trace("Update context to {}@{}", client.getConfig().getClientIdentifier().get(), client.getConfig().getServerHost()); - } - LoggingContext.put("identifier", "CLIENT " + client.getConfig().getClientIdentifier().get()); contextClient = client; ShellCommand.readFromContext(); } } public static void removeContext() { - if (ShellCommand.isVerbose()) { - Logger.trace("Remove context"); - } - LoggingContext.put("identifier", "SHELL"); contextClient = null; ShellCommand.readFromShell(); } @Override public void run() { - System.out.println(ShellCommand.getUsageMessage()); + ShellCommand.TERMINAL_WRITER.println(ShellCommand.getUsageMessage()); } public String getKey() { diff --git a/src/main/java/com/hivemq/cli/commands/shell/ShellDisconnectCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ShellDisconnectCommand.java index 5defd3832..6d9216050 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ShellDisconnectCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ShellDisconnectCommand.java @@ -17,22 +17,24 @@ package com.hivemq.cli.commands.shell; +import com.google.common.base.Throwables; import com.hivemq.cli.DefaultCLIProperties; import com.hivemq.cli.commands.Disconnect; import com.hivemq.cli.converters.Mqtt5UserPropertyConverter; import com.hivemq.cli.converters.UnsignedIntConverter; import com.hivemq.cli.impl.MqttAction; import com.hivemq.cli.mqtt.MqttClientExecutor; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties; import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; +import java.util.Arrays; @CommandLine.Command(name = "dis", aliases = "disconnect", @@ -64,24 +66,19 @@ public ShellDisconnectCommand() { private boolean disconnectAll; @CommandLine.Option(names = {"-i", "--identifier"}, description = "The client identifier UTF-8 String (default randomly generated string)") - @Nullable - private String identifier; + @Nullable private String identifier; @CommandLine.Option(names = {"-h", "--host"}, description = "The hostname of the message broker (default 'localhost')") - @Nullable - private String host; + @Nullable private String host; @CommandLine.Option(names = {"-e", "--sessionExpiryInterval"}, converter = UnsignedIntConverter.class, description = "The session expiry of the disconnect (default: 0)") - @Nullable - private Long sessionExpiryInterval; + @Nullable private Long sessionExpiryInterval; @CommandLine.Option(names = {"-r", "--reason"}, description = "The reason of the disconnect") - @Nullable - private String reasonString; + @Nullable private String reasonString; @CommandLine.Option(names = {"-up", "--userProperty"}, converter = Mqtt5UserPropertyConverter.class, description = "A user property of the disconnect message") - @Nullable - private Mqtt5UserProperty[] userProperties; + @Nullable private Mqtt5UserProperty[] userProperties; @Override public void run() { @@ -90,9 +87,7 @@ public void run() { host = defaultCLIProperties.getHost(); } - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } + Logger.trace("Command {} ", this); try { if (disconnectAll) { @@ -108,14 +103,7 @@ public void run() { } } catch (final Exception ex) { - LoggingContext.put("identifier", "DISCONNECT"); - if (isVerbose()) { - Logger.trace(ex); - } - else if (isDebug()) { - Logger.debug(ex.getMessage()); - } - Logger.error(MqttUtils.getRootCause(ex).getMessage()); + Logger.error(ex, Throwables.getRootCause(ex).getMessage()); } } @@ -135,7 +123,15 @@ public String getKey() { @Override public String toString() { - return "Disconnect::" + getKey(); + return getClass().getSimpleName() + "{" + + "disconnectAll=" + disconnectAll + + (identifier != null ? (", identifier=" + identifier) : "") + + (host != null ? (", host=" + host) : "") + + (sessionExpiryInterval != null ? (", sessionExpiryInterval=" + host) : "") + + (reasonString != null ? (", reasonString=" + reasonString) : "") + + (userProperties != null ? (", userProperties=" + Arrays.toString(userProperties)) : "") + + "}"; + } @Override @@ -158,23 +154,6 @@ public String getHost() { return MqttUtils.convertToMqtt5UserProperties(userProperties); } - public void setSessionExpiryInterval(final @Nullable Long sessionExpiryInterval) { - this.sessionExpiryInterval = sessionExpiryInterval; - } - - public void setReasonString(final @Nullable String reasonString) { - this.reasonString = reasonString; - } - - public void setIdentifier(@NotNull final String identifier) { - this.identifier = identifier; - } - - - public void setHost(@NotNull final String host) { - this.host = host; - } - public void setUserProperties(final @Nullable Mqtt5UserProperty... userProperties) { this.userProperties = userProperties; } diff --git a/src/main/java/com/hivemq/cli/commands/shell/ShellExitCommand.java b/src/main/java/com/hivemq/cli/commands/shell/ShellExitCommand.java index 57faaf5bd..c5f685539 100644 --- a/src/main/java/com/hivemq/cli/commands/shell/ShellExitCommand.java +++ b/src/main/java/com/hivemq/cli/commands/shell/ShellExitCommand.java @@ -17,7 +17,6 @@ package com.hivemq.cli.commands.shell; import com.hivemq.cli.commands.CliCommand; -import org.pmw.tinylog.Logger; import picocli.CommandLine; import javax.inject.Inject; @@ -36,16 +35,12 @@ public ShellExitCommand() { @Override public void run() { - if (isVerbose()) { - Logger.trace("Command: {} ", this); - } - ShellCommand.exitShell(); } @Override public String toString() { - return "ShellExit::"; + return getClass().getSimpleName(); } @Override diff --git a/src/main/java/com/hivemq/cli/converters/FileToPrivateKeyConverter.java b/src/main/java/com/hivemq/cli/converters/FileToPrivateKeyConverter.java index 68e57b0c7..33e6e00fb 100644 --- a/src/main/java/com/hivemq/cli/converters/FileToPrivateKeyConverter.java +++ b/src/main/java/com/hivemq/cli/converters/FileToPrivateKeyConverter.java @@ -29,7 +29,6 @@ import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo; import org.bouncycastle.pkcs.PKCSException; import org.jetbrains.annotations.NotNull; -import org.pmw.tinylog.Logger; import picocli.CommandLine; import java.io.File; @@ -58,7 +57,6 @@ private PrivateKey getPrivateKeyFromFile(final @NotNull File keyFile) throws Exc try { object = pemParser.readObject(); } catch (PEMException pe) { - Logger.debug(pe); throw new Exception(MALFORMED_KEY); } diff --git a/src/main/java/com/hivemq/cli/mqtt/AbstractMqttClientExecutor.java b/src/main/java/com/hivemq/cli/mqtt/AbstractMqttClientExecutor.java index b88dccbce..ff98183bd 100644 --- a/src/main/java/com/hivemq/cli/mqtt/AbstractMqttClientExecutor.java +++ b/src/main/java/com/hivemq/cli/mqtt/AbstractMqttClientExecutor.java @@ -20,6 +20,7 @@ import com.hivemq.cli.commands.cli.PublishCommand; import com.hivemq.cli.commands.cli.SubscribeCommand; import com.hivemq.cli.utils.MqttUtils; +import com.hivemq.client.internal.mqtt.message.connect.MqttConnectRestrictions; import com.hivemq.client.mqtt.MqttClient; import com.hivemq.client.mqtt.MqttClientBuilder; import com.hivemq.client.mqtt.MqttClientState; @@ -42,12 +43,10 @@ import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5WillPublishBuilder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; @@ -78,17 +77,17 @@ abstract class AbstractMqttClientExecutor { abstract void mqtt3Disconnect(final @NotNull Mqtt3Client client, final @NotNull Disconnect disconnect); - public void subscribe(final @NotNull SubscribeCommand subscribeCommand) { + public MqttClient subscribe(final @NotNull SubscribeCommand subscribeCommand) { final MqttClient client = connect(subscribeCommand); subscribe(client, subscribeCommand); + return client; + } public void subscribe(final @NotNull MqttClient client, final @NotNull Subscribe subscribe) { - LoggingContext.put("identifier", "CLIENT " + client.getConfig().getClientIdentifier().get()); - for (int i = 0; i < subscribe.getTopics().length; i++) { final String topic = subscribe.getTopics()[i]; @@ -115,8 +114,6 @@ public void publish(final @NotNull PublishCommand publishCommand) { } public void publish(final @NotNull MqttClient client, final @NotNull Publish publish) { - LoggingContext.put("identifier", "CLIENT " + client.getConfig().getClientIdentifier().get()); - for (int i = 0; i < publish.getTopics().length; i++) { final String topic = publish.getTopics()[i]; int qosI = i < publish.getQos().length ? i: publish.getQos().length-1; @@ -135,9 +132,6 @@ public void publish(final @NotNull MqttClient client, final @NotNull Publish pub } public void disconnect(final @NotNull Disconnect disconnect) { - - LoggingContext.put("identifier", "CLIENT " + disconnect.getIdentifier()); - final String clientKey = disconnect.getKey(); if (clientKeyToClientData.containsKey(clientKey)) { @@ -152,21 +146,15 @@ public void disconnect(final @NotNull Disconnect disconnect) { break; } clientKeyToClientData.remove(clientKey); - } - else if (disconnect.isDebug()) { - Logger.debug("client to disconnect is not connected: {} ", clientKey); + else { + Logger.error("client to disconnect is not connected ({}) ", clientKey); } - } public void disconnectAllClients(final @NotNull Disconnect disconnect) { - - final String context = LoggingContext.get("identifier"); - for (Map.Entry entry: clientKeyToClientData.entrySet()) { final MqttClient client = entry.getValue().getClient(); - LoggingContext.put("identifier", "CLIENT " + client.getConfig().getClientIdentifier().get()); switch (client.getConfig().getMqttVersion()) { case MQTT_5_0: mqtt5Disconnect((Mqtt5Client) client, disconnect); @@ -176,16 +164,10 @@ public void disconnectAllClients(final @NotNull Disconnect disconnect) { break; } } - clientKeyToClientData.clear(); - - LoggingContext.put("identifier", context); } public void unsubscribe(final @NotNull MqttClient client, final @NotNull Unsubscribe unsubscribe) { - - LoggingContext.put("identifier", "CLIENT " + unsubscribe.getIdentifier()); - switch (client.getConfig().getMqttVersion()) { case MQTT_5_0: mqtt5Unsubscribe((Mqtt5Client) client, unsubscribe); @@ -199,7 +181,6 @@ public void unsubscribe(final @NotNull MqttClient client, final @NotNull Unsubsc public boolean isConnected(final @NotNull Context context) { - if (clientKeyToClientData.containsKey(context.getKey())) { final MqttClient client = clientKeyToClientData.get(context.getKey()).getClient(); final MqttClientState state = client.getState(); @@ -210,16 +191,9 @@ public boolean isConnected(final @NotNull Context context) { public @NotNull MqttClient connect(final @NotNull Connect connect) { - - LoggingContext.put("identifier", "CLIENT " + connect.getIdentifier()); - if (isConnected(connect)) { - if (connect.isVerbose()) { - Logger.trace("Client is already connected ({})", connect.getKey()); - } else if (connect.isDebug()) { - Logger.debug("Client is already connected"); - } - Logger.info("Using already connected client with key: {}", connect.getKey()); + Logger.debug("Client is already connected ({})", connect.getKey()); + Logger.info("Using already connected ({})", connect.getKey()); return clientKeyToClientData.get(connect.getKey()).getClient(); } @@ -241,28 +215,22 @@ public boolean isConnected(final @NotNull Context context) { final @NotNull Mqtt5ConnectRestrictions connectRestrictions = createMqtt5ConnectRestrictions(connect); final Mqtt5ConnectBuilder connectBuilder = Mqtt5Connect.builder() - .willPublish(willPublish) - .restrictions(connectRestrictions); + .willPublish(willPublish); - if (connect.getCleanStart() != null) { - connectBuilder.cleanStart(connect.getCleanStart()); + // Workaround : if the built connect restrictions are the default ones do not append them to the connect builder + // -> Else the connectMessage.toString() method will flood the logging output + if (!connectRestrictions.equals(Mqtt5ConnectRestrictions.builder().build())) { + connectBuilder.restrictions(connectRestrictions); } - if (connect.getKeepAlive() != null) { - connectBuilder.keepAlive(connect.getKeepAlive()); - } - - if (connect.getSessionExpiryInterval() != null) { - connectBuilder.sessionExpiryInterval(connect.getSessionExpiryInterval()); - } - - if (connect.getConnectUserProperties() != null) { - connectBuilder.userProperties(connect.getConnectUserProperties()); - } + if (connect.getCleanStart() != null) { connectBuilder.cleanStart(connect.getCleanStart()); } + if (connect.getKeepAlive() != null) { connectBuilder.keepAlive(connect.getKeepAlive()); } + if (connect.getSessionExpiryInterval() != null) { connectBuilder.sessionExpiryInterval(connect.getSessionExpiryInterval()); } + if (connect.getConnectUserProperties() != null) { connectBuilder.userProperties(connect.getConnectUserProperties()); } connectBuilder.simpleAuth(buildMqtt5Authentication(connect)); - client.toAsync().publishes(MqttGlobalPublishFilter.REMAINING, buildRemainingMqtt5PublishesCallback(connect)); + client.toAsync().publishes(MqttGlobalPublishFilter.REMAINING, buildRemainingMqtt5PublishesCallback(connect, client)); mqtt5Connect(client, connectBuilder.build(), connect); @@ -294,7 +262,7 @@ public boolean isConnected(final @NotNull Context context) { connectBuilder.simpleAuth(buildMqtt3Authentication(connect)); - client.toAsync().publishes(MqttGlobalPublishFilter.REMAINING, buildRemainingMqtt3PublishesCallback(connect)); + client.toAsync().publishes(MqttGlobalPublishFilter.REMAINING, buildRemainingMqtt3PublishesCallback(connect, client)); mqtt3Connect(client, connectBuilder.build(), connect); @@ -465,34 +433,24 @@ else if (connect.getPassword() != null) { return client; } - @NotNull private Consumer buildRemainingMqtt5PublishesCallback(final @NotNull Connect connect) { + @NotNull private Consumer buildRemainingMqtt5PublishesCallback(final @NotNull Connect connect, final @NotNull Mqtt5Client client) { if (connect instanceof Subscribe) { - return new SubscribeMqtt5PublishCallback((Subscribe) connect); + return new SubscribeMqtt5PublishCallback((Subscribe) connect, client); } else { return mqtt5Publish -> { - if (connect.isVerbose()) { - Logger.trace("received PUBLISH: {}, MESSAGE: '{}'", mqtt5Publish, new String(mqtt5Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); - } - else if (connect.isDebug()) { - Logger.debug("received PUBLISH: (Topic: '{}', MESSAGE: '{}')", mqtt5Publish.getTopic(), new String(mqtt5Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); - } + Logger.debug("received PUBLISH: {}, MESSAGE: '{}'", mqtt5Publish, new String(mqtt5Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); }; } } - @NotNull private Consumer buildRemainingMqtt3PublishesCallback(final @NotNull Connect connect) { + @NotNull private Consumer buildRemainingMqtt3PublishesCallback(final @NotNull Connect connect, final @NotNull Mqtt3Client client) { if (connect instanceof Subscribe) { - return new SubscribeMqtt3PublishCallback((Subscribe) connect); + return new SubscribeMqtt3PublishCallback((Subscribe) connect, client); } else { return mqtt3Publish -> { - if (connect.isVerbose()) { - Logger.trace("received PUBLISH: {}, MESSAGE: '{}'", mqtt3Publish, new String(mqtt3Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); - } - else if (connect.isDebug()) { - Logger.debug("received PUBLISH: (Topic: '{}', MESSAGE: '{}')", mqtt3Publish.getTopic(), new String(mqtt3Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); - } + Logger.debug("received PUBLISH: {}, MESSAGE: '{}'", mqtt3Publish, new String(mqtt3Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); }; } } diff --git a/src/main/java/com/hivemq/cli/mqtt/ContextClientDisconnectListener.java b/src/main/java/com/hivemq/cli/mqtt/ContextClientDisconnectListener.java index fd7b781ae..2359a16f4 100644 --- a/src/main/java/com/hivemq/cli/mqtt/ContextClientDisconnectListener.java +++ b/src/main/java/com/hivemq/cli/mqtt/ContextClientDisconnectListener.java @@ -16,39 +16,32 @@ */ package com.hivemq.cli.mqtt; +import com.google.common.base.Throwables; import com.hivemq.cli.commands.shell.ShellCommand; import com.hivemq.cli.commands.shell.ShellContextCommand; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.MqttClientConfig; import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedContext; import com.hivemq.client.mqtt.lifecycle.MqttClientDisconnectedListener; import com.hivemq.client.mqtt.lifecycle.MqttDisconnectSource; import org.jetbrains.annotations.NotNull; -import org.pmw.tinylog.Logger; -import org.pmw.tinylog.LoggingContext; +import org.tinylog.Logger; public class ContextClientDisconnectListener implements MqttClientDisconnectedListener { @Override public void onDisconnected(final @NotNull MqttClientDisconnectedContext context) { - final String contextBefore = LoggingContext.get("identifier"); - - LoggingContext.put("identifier", "CLIENT " + context.getClientConfig().getClientIdentifier().orElse(null)); - if (context.getSource() != MqttDisconnectSource.USER) { final Throwable cause = context.getCause(); - if (ShellCommand.VERBOSE) { - Logger.trace(cause); - } - else if (ShellCommand.DEBUG) { - Logger.debug(cause.getMessage()); - } + Logger.debug(cause, "{} DISCONNECTED {}", LoggerUtils.getClientPrefix(context.getClientConfig()), + Throwables.getRootCause(cause).getMessage()); // If the currently active shell client gets disconnected from the server prompt the user to enter if (contextEqualsShellContext(context)) { - Logger.error(MqttUtils.getRootCause(cause).getMessage()); + Logger.error(cause, Throwables.getRootCause(cause).getMessage()); ShellContextCommand.removeContext(); ShellCommand.TERMINAL_WRITER.printf("Press ENTER to resume: "); ShellCommand.TERMINAL_WRITER.flush(); @@ -59,8 +52,6 @@ else if (contextEqualsShellContext(context)){ } MqttClientExecutor.getClientDataMap().remove(getKeyFromConfig(context.getClientConfig())); - - LoggingContext.put("identifier", contextBefore); } private String getKeyFromConfig(final @NotNull MqttClientConfig clientConfig) { diff --git a/src/main/java/com/hivemq/cli/mqtt/MqttClientExecutor.java b/src/main/java/com/hivemq/cli/mqtt/MqttClientExecutor.java index 40281b441..7d777d467 100644 --- a/src/main/java/com/hivemq/cli/mqtt/MqttClientExecutor.java +++ b/src/main/java/com/hivemq/cli/mqtt/MqttClientExecutor.java @@ -16,14 +16,13 @@ */ package com.hivemq.cli.mqtt; +import com.google.common.base.Throwables; import com.hivemq.cli.commands.*; -import com.hivemq.cli.commands.cli.PublishCommand; +import com.hivemq.cli.utils.LoggerUtils; import com.hivemq.cli.utils.MqttUtils; import com.hivemq.client.mqtt.MqttVersion; import com.hivemq.client.mqtt.datatypes.MqttQos; import com.hivemq.client.mqtt.datatypes.MqttTopicFilter; -import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient; -import com.hivemq.client.mqtt.mqtt3.Mqtt3BlockingClient; import com.hivemq.client.mqtt.mqtt3.Mqtt3Client; import com.hivemq.client.mqtt.mqtt3.message.connect.Mqtt3Connect; import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck; @@ -33,90 +32,63 @@ import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3Subscribe; import com.hivemq.client.mqtt.mqtt3.message.subscribe.Mqtt3SubscribeBuilder; import com.hivemq.client.mqtt.mqtt3.message.unsubscribe.Mqtt3Unsubscribe; -import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient; -import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient; import com.hivemq.client.mqtt.mqtt5.Mqtt5Client; -import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5MessageException; -import com.hivemq.client.mqtt.mqtt5.exceptions.Mqtt5PubAckException; import com.hivemq.client.mqtt.mqtt5.message.connect.Mqtt5Connect; import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck; - import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5Disconnect; import com.hivemq.client.mqtt.mqtt5.message.disconnect.Mqtt5DisconnectBuilder; import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish; import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishBuilder; -import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PublishResult; import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe; import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5SubscribeBuilder; import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe; import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck; -import com.hivemq.client.util.TypeSwitch; import org.jetbrains.annotations.NotNull; -import org.pmw.tinylog.Logger; import javax.inject.Inject; import javax.inject.Singleton; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.concurrent.CompletableFuture; -import org.bouncycastle.util.encoders.Base64; +import org.tinylog.Logger; @Singleton public class MqttClientExecutor extends AbstractMqttClientExecutor { @Inject - MqttClientExecutor() { - } + MqttClientExecutor() {} void mqtt5Connect(final @NotNull Mqtt5Client client, final @NotNull Mqtt5Connect connectMessage, final @NotNull Connect connect) { - if (connect.isVerbose()) { - Logger.trace("sending CONNECT with Mqtt5Connect: {}", connectMessage); - } - else if (connect.isDebug()) { - Logger.debug("sending CONNECT"); - } + String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); + + Logger.debug("{} sending CONNECT {}", clientLogPrefix, connectMessage); final Mqtt5ConnAck connAck = client .toBlocking() .connect(connectMessage); - if (connect.isVerbose()) { - Logger.trace("received CONNACK: {} ", connAck); - Logger.trace("now in State: {}", client.getConfig().getState()); - } - else if (connect.isDebug()) { - Logger.debug("received CONNACK {}", connAck.getReasonCode()); - } + Logger.debug("{} received CONNACK {} ", clientLogPrefix, connAck); } void mqtt3Connect(final @NotNull Mqtt3Client client, final @NotNull Mqtt3Connect connectMessage, final @NotNull Connect connect) { - if (connect.isVerbose()) { - Logger.trace("sending CONNECT with Mqtt3Connect: {}", connectMessage); - } - else if (connect.isDebug()) { - Logger.debug("sending CONNECT"); - } + final String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); + + Logger.debug("{} sending CONNECT {}", clientLogPrefix, connectMessage); final Mqtt3ConnAck connAck = client .toBlocking() .connect(connectMessage); - if (connect.isVerbose()) { - Logger.trace("received CONNACK: {} ", connAck); - Logger.trace("now in State: {}", client.getConfig().getState()); - } - else if (connect.isDebug()) { - Logger.debug("received CONNACK {}", connAck.getReturnCode()); - } - + Logger.debug("{} received CONNACK {} ", clientLogPrefix, connAck); } void mqtt5Subscribe(final @NotNull Mqtt5Client client, final @NotNull Subscribe subscribe, final @NotNull String topic, final @NotNull MqttQos qos) { + final String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); + final Mqtt5SubscribeBuilder.Start.Complete builder = Mqtt5Subscribe.builder() .topicFilter(topic) .qos(qos); @@ -128,40 +100,27 @@ void mqtt5Subscribe(final @NotNull Mqtt5Client client, final @NotNull Subscribe final Mqtt5Subscribe subscribeMessage = builder.build(); - if (subscribe.isVerbose()) { - Logger.trace("sending SUBSCRIBE with Mqtt5Subscribe: {}", subscribeMessage); - } - else if (subscribe.isDebug()) { - Logger.debug("sending SUBSCRIBE: (Topic: {}, QoS: '{}')", topic, qos); - } - + Logger.debug("{} sending SUBSCRIBE {}", clientLogPrefix, subscribeMessage); client.toAsync() - .subscribe(subscribeMessage, new SubscribeMqtt5PublishCallback(subscribe)) + .subscribe(subscribeMessage, new SubscribeMqtt5PublishCallback(subscribe, client)) .whenComplete((subAck, throwable) -> { if (throwable != null) { - if (subscribe.isVerbose()) { - Logger.trace("SUBSCRIBE to TOPIC '{}' failed: {}", topic, throwable); - } - else if (subscribe.isDebug()) { - Logger.debug("SUBSCRIBE to TOPIC '{}' failed: {} ", topic, throwable.getMessage()); - } - - Logger.error("SUBSCRIBE to TOPIC '{}' failed with '{}'", topic, MqttUtils.getRootCause(throwable).getMessage()); + Logger.error(throwable,"{} failed SUBSCRIBE to TOPIC '{}': {}", + clientLogPrefix, + topic, + Throwables.getRootCause(throwable).getMessage()); } else { - getClientDataMap().get(subscribe.getKey()).addSubscription(MqttTopicFilter.of(topic)); + final String clientKey = MqttUtils.buildKey( + client.getConfig().getClientIdentifier().get().toString(), + client.getConfig().getServerHost()); - if (subscribe.isVerbose()) { - Logger.trace("received SUBACK: {}", subAck); - } - else if (subscribe.isDebug()) { - Logger.debug("received SUBACK: {}", subAck.getReasonCodes()); - } + getClientDataMap().get(clientKey).addSubscription(MqttTopicFilter.of(topic)); + Logger.debug("{} received SUBACK {}", clientLogPrefix, subAck); } - }) .join(); @@ -169,6 +128,8 @@ else if (subscribe.isDebug()) { void mqtt3Subscribe(final @NotNull Mqtt3Client client, final @NotNull Subscribe subscribe, final @NotNull String topic, final @NotNull MqttQos qos) { + final String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); + final Mqtt3SubscribeBuilder.Start.Complete builder = Mqtt3Subscribe.builder() .topicFilter(topic) .qos(qos); @@ -176,38 +137,24 @@ void mqtt3Subscribe(final @NotNull Mqtt3Client client, final @NotNull Subscribe final Mqtt3Subscribe subscribeMessage = builder.build(); - if (subscribe.isVerbose()) { - Logger.trace("sending SUBSCRIBE with Mqtt3Subscribe: {}", subscribeMessage); - } - else if (subscribe.isDebug()) { - Logger.debug("sending SUBSCRIBE: (Topic: {}, QoS: '{}')", topic, qos); - } - + Logger.debug("{} sending SUBSCRIBE {}", clientLogPrefix, subscribeMessage); client.toAsync() - .subscribe(subscribeMessage, new SubscribeMqtt3PublishCallback(subscribe)) + .subscribe(subscribeMessage, new SubscribeMqtt3PublishCallback(subscribe, client)) .whenComplete((subAck, throwable) -> { if (throwable != null) { - - if (subscribe.isVerbose()) { - Logger.trace("SUBSCRIBE to TOPIC '{}' failed: {}", topic, throwable); - } - else if (subscribe.isDebug()) { - Logger.debug("SUBSCRIBE to TOPIC '{}' failed: {} ", topic, throwable.getMessage()); - } - - Logger.error("SUBSCRIBE to TOPIC '{}' failed with '{}'", topic, MqttUtils.getRootCause(throwable).getMessage()); + Logger.error(throwable, "{} failed SUBSCRIBE to TOPIC '{}': {}", + clientLogPrefix, + topic, + Throwables.getRootCause(throwable).getMessage()); } else { - getClientDataMap().get(subscribe.getKey()).addSubscription(MqttTopicFilter.of(topic)); + final String clientKey = MqttUtils.buildKey(client.getConfig().getClientIdentifier().get().toString(), + client.getConfig().getServerHost()); - if (subscribe.isVerbose()) { - Logger.trace("received SUBACK: {}", subAck); - } - else if (subscribe.isDebug()) { - Logger.debug("received SUBACK: {}", subAck.getReturnCodes()); - } + getClientDataMap().get(clientKey).addSubscription(MqttTopicFilter.of(topic)); + Logger.debug("{} received SUBACK {}", clientLogPrefix, subAck); } }) .join(); @@ -215,6 +162,8 @@ else if (subscribe.isDebug()) { void mqtt5Publish(final @NotNull Mqtt5Client client, final @NotNull Publish publish, final @NotNull String topic, final @NotNull MqttQos qos) { + final String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); + final Mqtt5PublishBuilder.Complete publishBuilder = Mqtt5Publish.builder() .topic(topic) .qos(qos) @@ -236,48 +185,23 @@ void mqtt5Publish(final @NotNull Mqtt5Client client, final @NotNull Publish publ final Mqtt5Publish publishMessage = publishBuilder.build(); - if (publish.isVerbose()) { - Logger.trace("sending PUBLISH with Mqtt5Publish: {}", publishMessage); - } - else if (publish.isDebug()) { - Logger.debug("sending PUBLISH: (Topic: '{}', QoS: '{}', Message: '{}')", topic, qos, bufferToString(publish.getMessage())); - } - + Logger.debug("{} sending PUBLISH ('{}') {}", clientLogPrefix, + bufferToString(publish.getMessage()), + publishMessage); client.toAsync() .publish(publishMessage) .whenComplete((publishResult, throwable) -> { if (throwable != null) { - - if (publish.isVerbose()) { - Logger.trace("PUBLISH to TOPIC '{}' failed: {}", topic, throwable); - } - else if (publish.isDebug()) { - Logger.debug("PUBLISH to TOPIC '{}' failed: {} ", topic, throwable.getMessage()); - } - Logger.error("PUBLISH to TOPIC '{}' failed with '{}'", topic, MqttUtils.getRootCause(throwable).getMessage()); - + Logger.error(throwable,"{} failed PUBLISH to TOPIC '{}': {}", + clientLogPrefix, + topic, + Throwables.getRootCause(throwable).getMessage()); } else { - - final String p = bufferToString(publish.getMessage()); - - if (publish.isVerbose()) { - Logger.trace("acknowledged PUBLISH: '{}' for PUBLISH to TOPIC: '{}'", publishResult, topic); - } - else if (publish.isDebug()) { - - TypeSwitch.when(publishResult) - .is(Mqtt5PublishResult.Mqtt5Qos1Result.class, qos1Result -> { - Logger.debug("received PUBACK: '{}' for PUBLISH to TOPIC: '{}'", qos1Result.getPubAck(), topic); - }) - .is(Mqtt5PublishResult.Mqtt5Qos2Result.class, qos2Result -> { - Logger.debug("received PUBREC: '{}' for PUBLISH to TOPIC: '{}'", qos2Result.getPubRec(), topic); - }) - .is(Mqtt5PublishResult.Mqtt5Qos2CompleteResult.class, qos2CompleteResult -> { - Logger.debug("received PUBCOMP: '{}' for PUBLISH to TOPIC: '{}'", qos2CompleteResult.getPubComp(), topic); - }); - } + Logger.debug("{} received PUBLISH acknowledgement {}", + clientLogPrefix, + publishResult); } }) .join(); @@ -286,6 +210,7 @@ else if (publish.isDebug()) { void mqtt3Publish(final @NotNull Mqtt3Client client, final @NotNull Publish publish, final @NotNull String topic, final @NotNull MqttQos qos) { + final String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); final Mqtt3PublishBuilder.Complete publishBuilder = Mqtt3Publish.builder() .topic(topic) @@ -298,40 +223,21 @@ void mqtt3Publish(final @NotNull Mqtt3Client client, final @NotNull Publish publ final Mqtt3Publish publishMessage = publishBuilder.build(); - if (publish.isVerbose()) { - Logger.trace("sending PUBLISH with Mqtt3Publish: {}", publishMessage); - } - else if (publish.isDebug()) { - Logger.debug("sending PUBLISH: (TOPIC: '{}', QoS: '{}', Message: '{}')", topic, qos, bufferToString(publish.getMessage())); - } + Logger.debug("{} sending PUBLISH ('{}') {}", clientLogPrefix, bufferToString(publish.getMessage()), publishMessage); client.toAsync().publish(publishMessage) .whenComplete((publishResult, throwable) -> { if (throwable != null) { - if (publish.isVerbose()) { - Logger.trace("PUBLISH to TOPIC '{}' failed: {}", topic, throwable); - } - else if (publish.isDebug()) { - Logger.debug("PUBLISH to TOPIC '{}' failed: {} ", topic, throwable.getMessage()); - } - Logger.error("PUBLISH to TOPIC '{}' failed with '{}'", topic, MqttUtils.getRootCause(throwable).getMessage()); - + Logger.error(throwable, "{} failed PUBLISH to TOPIC '{}': {}", + clientLogPrefix, + topic, + Throwables.getRootCause(throwable).getMessage()); } else { - final String p = bufferToString(publish.getMessage()); - - if (publish.isVerbose()) { - Logger.trace("acknowledged PUBLISH: '{}' for PUBLISH to TOPIC: '{}'", publishResult, topic); - } - else if (publish.isDebug()) { - if (publishResult.getQos().equals(MqttQos.AT_LEAST_ONCE)) { - Logger.debug("received PUBACK for PUBLISH to TOPIC: '{}'", topic); - } - else if (publishResult.getQos().equals(MqttQos.EXACTLY_ONCE)) { - Logger.debug("received PUBREC for PUBLISH to TOPIC: '{}'", topic); - } - } + Logger.debug("{} received PUBLISH acknowledgement {}", + clientLogPrefix, + publishResult); } }) .join(); @@ -339,8 +245,7 @@ else if (publishResult.getQos().equals(MqttQos.EXACTLY_ONCE)) { @Override void mqtt5Unsubscribe(@NotNull final Mqtt5Client client, @NotNull final Unsubscribe unsubscribe) { - - + final String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); for (String topic : unsubscribe.getTopics()) { @@ -348,12 +253,9 @@ void mqtt5Unsubscribe(@NotNull final Mqtt5Client client, @NotNull final Unsubscr .topicFilter(topic) .build(); - if (unsubscribe.isVerbose()) { - Logger.trace("Sending UNSUBSCRIBE with Mqtt5Unsubscribe: {}", unsubscribeMessage); - } - else if (unsubscribe.isDebug()) { - Logger.debug("sending UNSUBSCRIBE: (TOPIC: '{}', userProperties: {})", topic, unsubscribe.getUserProperties()); - } + Logger.debug("{} sending UNSUBSCRIBE {}", + clientLogPrefix, + unsubscribeMessage); client.toAsync() .unsubscribe(unsubscribeMessage) @@ -361,25 +263,17 @@ else if (unsubscribe.isDebug()) { if (throwable != null) { - - if (unsubscribe.isVerbose()) { - Logger.trace("UNSUBSCRIBE of TOPIC '{}' failed: {}", topic, throwable); - } - else if (unsubscribe.isDebug()) { - Logger.debug("UNSUBSCRIBE of TOPIC '{}' failed: {}", topic, throwable.getMessage()); - } - Logger.error("UNSUBSCRIBE to {} failed with ()", topic, MqttUtils.getRootCause(throwable).getMessage()); + Logger.error(throwable,"{} failed UNSUBSCRIBE from TOPIC '{}': {}", + clientLogPrefix, + topic, + Throwables.getRootCause(throwable).getMessage()); } else { getClientDataMap().get(unsubscribe.getKey()).removeSubscription(MqttTopicFilter.of(topic)); - if (unsubscribe.isVerbose()) { - Logger.trace("received UNSUBACK: {}", unsubAck); - } - else if (unsubscribe.isDebug()) { - Logger.debug("received UNSUBACK: {}", unsubAck.getReasonCodes()); - } - + Logger.debug("{} received UNSUBACK {}", + clientLogPrefix, + unsubAck); } }) .join(); @@ -388,7 +282,7 @@ else if (unsubscribe.isDebug()) { @Override void mqtt3Unsubscribe(@NotNull final Mqtt3Client client, @NotNull final Unsubscribe unsubscribe) { - + final String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); for (String topic : unsubscribe.getTopics()) { @@ -396,37 +290,22 @@ void mqtt3Unsubscribe(@NotNull final Mqtt3Client client, @NotNull final Unsubscr .topicFilter(topic) .build(); - if (unsubscribe.isVerbose()) { - Logger.trace("Sending UNSUBSCRIBE with Mqtt3Unsubscribe: {}", unsubscribeMessage); - } - else if (unsubscribe.isDebug()) { - Logger.debug("Sending UNSUBSCRIBE: (TOPIC: '{}', userProperties: {})", topic, unsubscribe.getUserProperties()); - } + Logger.debug("{} Sending UNSUBSCRIBE {}", + clientLogPrefix, + unsubscribeMessage); - client.toAsync() + client.toAsync() .unsubscribe(unsubscribeMessage) .whenComplete((Void unsubAck, Throwable throwable) -> { if (throwable != null) { - if (unsubscribe.isVerbose()) { - Logger.trace("UNSUBSCRIBE of TOPIC '{}' failed: {}", topic, throwable); - } - else if (unsubscribe.isDebug()) { - Logger.debug("UNSUBSCRIBE of TOPIC '{}' failed: {}", topic, throwable.getMessage()); - } - Logger.error("UNSUBSCRIBE to {} failed with ()", topic, MqttUtils.getRootCause(throwable).getMessage()); - + Logger.error(throwable, "{} failed UNSUBSCRIBE from TOPIC '{}': {}", + clientLogPrefix, + topic, + Throwables.getRootCause(throwable).getMessage()); } else { - getClientDataMap().get(unsubscribe.getKey()).removeSubscription(MqttTopicFilter.of(topic)); - - if (unsubscribe.isVerbose()) { - Logger.trace("received UNSUBACK"); - } - else if (unsubscribe.isDebug()) { - Logger.debug("received UNSUBACK"); - } - + Logger.debug("{} received UNSUBACK", clientLogPrefix ); } }) .join(); @@ -435,6 +314,8 @@ else if (unsubscribe.isDebug()) { @Override void mqtt5Disconnect(@NotNull final Mqtt5Client client, @NotNull final Disconnect disconnect) { + final String clientLogPrefix = LoggerUtils.getClientPrefix(client.getConfig()); + final Mqtt5DisconnectBuilder disconnectBuilder = Mqtt5Disconnect.builder(); @@ -452,58 +333,18 @@ void mqtt5Disconnect(@NotNull final Mqtt5Client client, @NotNull final Disconnec final Mqtt5Disconnect disconnectMessage = disconnectBuilder.build(); - if (disconnect.isVerbose()) { - Logger.trace("Sending DISCONNECT with Mqtt5Disconnect: {}", disconnectMessage); - } - else if (disconnect.isDebug()) { - Logger.debug("Sending DISCONNECT (Reason: {}, sessionExpiryInterval: {}, userProperties: {})", disconnect.getReasonString(), disconnect.getSessionExpiryInterval(), disconnect.getUserProperties()); - } + Logger.debug("{} sending DISCONNECT {}", clientLogPrefix, disconnectMessage); - client.toBlocking() - .disconnect(disconnectMessage); + client.toBlocking().disconnect(disconnectMessage); } @Override void mqtt3Disconnect(@NotNull final Mqtt3Client client, @NotNull final Disconnect disconnect) { - if (disconnect.getSessionExpiryInterval() != null) { - Logger.warn("Session expiry interval set but is unused in Mqtt version {}", MqttVersion.MQTT_3_1_1); - } - if (disconnect.getReasonString() != null) { - Logger.warn("Reason string was set but is unused in Mqtt version {}", MqttVersion.MQTT_3_1_1); - } - if (disconnect.getUserProperties() != null) { - Logger.warn("User properties were set but are unused in Mqtt version {}", MqttVersion.MQTT_3_1_1); - } - - if (disconnect.isVerbose()) { - Logger.trace("Sending DISCONNECT with Mqtt3Disconnect: {}", Mqtt3Disconnect.class); - } - else if (disconnect.isDebug()) { - Logger.debug("Sending DISCONNECT"); - } - - client.toBlocking() - .disconnect(); - } - - - private @NotNull String applyBase64EncodingIfSet(final boolean encode, final byte[] payload) { - if (encode) { - return Base64.toBase64String(payload); - } else { - return new String(payload); - } - } - - private @NotNull String trimMessage(String p) { - if (p.length() > 10) { - return p.substring(0, 10); - } else { - return p; - } + Logger.debug("{} Sending DISCONNECT", LoggerUtils.getClientPrefix(client.getConfig())); + client.toBlocking().disconnect(); } private @NotNull String bufferToString(ByteBuffer b) { diff --git a/src/main/java/com/hivemq/cli/mqtt/SubscribeMqtt3PublishCallback.java b/src/main/java/com/hivemq/cli/mqtt/SubscribeMqtt3PublishCallback.java index 4f933c762..a79fb190c 100644 --- a/src/main/java/com/hivemq/cli/mqtt/SubscribeMqtt3PublishCallback.java +++ b/src/main/java/com/hivemq/cli/mqtt/SubscribeMqtt3PublishCallback.java @@ -18,38 +18,42 @@ import com.hivemq.cli.commands.Subscribe; import com.hivemq.cli.utils.FileUtils; +import com.hivemq.cli.utils.LoggerUtils; +import com.hivemq.client.mqtt.mqtt3.Mqtt3Client; import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish; import org.bouncycastle.util.encoders.Base64; import org.jetbrains.annotations.NotNull; -import org.pmw.tinylog.Logger; +import org.jetbrains.annotations.Nullable; +import org.tinylog.Logger; +import java.io.File; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.function.Consumer; public class SubscribeMqtt3PublishCallback implements Consumer { - @NotNull private final Subscribe subscribe; + @Nullable private final File publishFile; + private final boolean printToStdout; + private final boolean isBase64; + private final Mqtt3Client client; - public SubscribeMqtt3PublishCallback(final @NotNull Subscribe subscribe) { - this.subscribe = subscribe; + SubscribeMqtt3PublishCallback(final @NotNull Subscribe subscribe, final @NotNull Mqtt3Client client) { + printToStdout = subscribe.isPrintToSTDOUT(); + publishFile = subscribe.getPublishFile(); + isBase64 = subscribe.isBase64(); + this.client = client; } @Override public void accept(final @NotNull Mqtt3Publish mqtt3Publish) { PrintWriter fileWriter = null; - if (subscribe.getPublishFile() != null) { - fileWriter = FileUtils.createFileAppender(subscribe.getPublishFile()); - } - - byte[] payload = mqtt3Publish.getPayloadAsBytes(); String payloadMessage = new String(payload); - if (subscribe.isBase64()) { - payloadMessage = Base64.toBase64String(payload); - } + if (publishFile != null) { fileWriter = FileUtils.createFileAppender(publishFile); } + if (isBase64) { payloadMessage = Base64.toBase64String(payload); } if (fileWriter != null) { fileWriter.println(mqtt3Publish.getTopic() + ": " + payloadMessage); @@ -57,17 +61,12 @@ public void accept(final @NotNull Mqtt3Publish mqtt3Publish) { fileWriter.close(); } - if (subscribe.isPrintToSTDOUT()) { - System.out.println(payloadMessage); - } - - if (subscribe.isVerbose()) { - Logger.trace("received PUBLISH: {}, MESSAGE: '{}'", mqtt3Publish, new String(mqtt3Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); - } - else if (subscribe.isDebug()) { - Logger.debug("received PUBLISH: (Topic: '{}', MESSAGE: '{}')", mqtt3Publish.getTopic(), new String(mqtt3Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); - } + if (printToStdout) { System.out.println(payloadMessage); } + Logger.debug("{} received PUBLISH ('{}') {}", + LoggerUtils.getClientPrefix(client.getConfig()), + new String(mqtt3Publish.getPayloadAsBytes(), StandardCharsets.UTF_8), + mqtt3Publish); } } diff --git a/src/main/java/com/hivemq/cli/mqtt/SubscribeMqtt5PublishCallback.java b/src/main/java/com/hivemq/cli/mqtt/SubscribeMqtt5PublishCallback.java index 8a35195d0..a8f9bc423 100644 --- a/src/main/java/com/hivemq/cli/mqtt/SubscribeMqtt5PublishCallback.java +++ b/src/main/java/com/hivemq/cli/mqtt/SubscribeMqtt5PublishCallback.java @@ -18,38 +18,42 @@ import com.hivemq.cli.commands.Subscribe; import com.hivemq.cli.utils.FileUtils; +import com.hivemq.cli.utils.LoggerUtils; +import com.hivemq.client.mqtt.mqtt5.Mqtt5Client; import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish; import org.bouncycastle.util.encoders.Base64; import org.jetbrains.annotations.NotNull; -import org.pmw.tinylog.Logger; +import org.jetbrains.annotations.Nullable; +import org.tinylog.Logger; +import java.io.File; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.function.Consumer; public class SubscribeMqtt5PublishCallback implements Consumer { - @NotNull private final Subscribe subscribe; + @Nullable private final File publishFile; + private final boolean printToStdout; + private final boolean isBase64; + private final Mqtt5Client client; - SubscribeMqtt5PublishCallback(final @NotNull Subscribe subscribe) { - this.subscribe = subscribe; + SubscribeMqtt5PublishCallback(final @NotNull Subscribe subscribe, final @NotNull Mqtt5Client client) { + printToStdout = subscribe.isPrintToSTDOUT(); + publishFile = subscribe.getPublishFile(); + isBase64 = subscribe.isBase64(); + this.client = client; } @Override public void accept(final @NotNull Mqtt5Publish mqtt5Publish) { PrintWriter fileWriter = null; - if (subscribe.getPublishFile() != null) { - fileWriter = FileUtils.createFileAppender(subscribe.getPublishFile()); - } - - byte[] payload = mqtt5Publish.getPayloadAsBytes(); String payloadMessage = new String(payload); - if (subscribe.isBase64()) { - payloadMessage = Base64.toBase64String(payload); - } + if (publishFile != null) { fileWriter = FileUtils.createFileAppender(publishFile); } + if (isBase64) { payloadMessage = Base64.toBase64String(payload); } if (fileWriter != null) { fileWriter.println(mqtt5Publish.getTopic() + ": " + payloadMessage); @@ -57,16 +61,12 @@ public void accept(final @NotNull Mqtt5Publish mqtt5Publish) { fileWriter.close(); } - if (subscribe.isPrintToSTDOUT()) { - System.out.println(payloadMessage); - } + if (printToStdout) { System.out.println(payloadMessage); } - if (subscribe.isVerbose()) { - Logger.trace("received PUBLISH: {}, MESSAGE: '{}'", mqtt5Publish, new String(mqtt5Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); - } - else if (subscribe.isDebug()) { - Logger.debug("received PUBLISH: (Topic: '{}', MESSAGE: '{}')", mqtt5Publish.getTopic(), new String(mqtt5Publish.getPayloadAsBytes(), StandardCharsets.UTF_8)); - } + Logger.debug("{} received PUBLISH ('{}') {}", + LoggerUtils.getClientPrefix(client.getConfig()), + new String(mqtt5Publish.getPayloadAsBytes(), StandardCharsets.UTF_8), + mqtt5Publish); } diff --git a/src/main/java/com/hivemq/cli/utils/FileUtils.java b/src/main/java/com/hivemq/cli/utils/FileUtils.java index 1749306c5..fbfaeb9d5 100644 --- a/src/main/java/com/hivemq/cli/utils/FileUtils.java +++ b/src/main/java/com/hivemq/cli/utils/FileUtils.java @@ -17,7 +17,7 @@ package com.hivemq.cli.utils; import org.jetbrains.annotations.NotNull; -import org.pmw.tinylog.Logger; +import org.tinylog.Logger; import java.io.*; @@ -31,7 +31,7 @@ public static PrintWriter createFileAppender(@NotNull File file) { try { out = new FileOutputStream(file, true); } catch (final FileNotFoundException e) { - Logger.error("Could not open file: {} ", file.getName(), e.getMessage()); + Logger.error(e,"Could not open file ({}) ", file.getName(), e.getMessage()); } } else { // file has to be created @@ -39,7 +39,7 @@ public static PrintWriter createFileAppender(@NotNull File file) { try { out = new FileOutputStream(file); } catch (final FileNotFoundException e) { - Logger.error("Could not create file: {} ", file.getName(), e.getMessage()); + Logger.error(e, "Could not create file ({}) ", file.getName(), e.getMessage()); } } diff --git a/src/main/java/com/hivemq/cli/utils/LoggerUtils.java b/src/main/java/com/hivemq/cli/utils/LoggerUtils.java new file mode 100644 index 000000000..7a78257a8 --- /dev/null +++ b/src/main/java/com/hivemq/cli/utils/LoggerUtils.java @@ -0,0 +1,80 @@ +/* + * Copyright 2019 HiveMQ and the HiveMQ Community + * + * Licensed 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 com.hivemq.cli.utils; + +import com.hivemq.cli.DefaultCLIProperties; +import com.hivemq.cli.MqttCLIMain; +import com.hivemq.client.mqtt.MqttClientConfig; +import com.hivemq.client.mqtt.datatypes.MqttClientIdentifier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.tinylog.Level; +import org.tinylog.configuration.Configuration; + +import java.io.File; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +public class LoggerUtils { + + public static void useDefaultLogging(@Nullable final Map extendedProperties) { + final DefaultCLIProperties defaultCLIProperties = MqttCLIMain.MQTTCLI.defaultCLIProperties(); + final String dir = defaultCLIProperties.getLogfilePath(); + final Level logLevel = defaultCLIProperties.getLogfileDebugLevel(); + final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + final Date date = new Date(); + final String logfilePath = dir + "mqtt_cli_" + dateFormat.format(date) + ".log"; + final String logfileFormatPattern = "{date: yyyy-MM-dd HH:mm:ss} | {pid} | {{level}|min-size=5} | {message}"; + final File dirFile = new File(dir); + + dirFile.mkdirs(); + + // TinyLog configuration + // File Writer (creates logfiles under .mqtt-cli/logs folder) + Map configurationMap = new HashMap() {{ + put("writer", "file"); + put("writer.format", logfileFormatPattern); + put("writer.file", logfilePath); + put("writer.append", "true"); + put("writer.level", logLevel.name().toLowerCase()); + }}; + + if (extendedProperties != null) { + configurationMap.putAll(extendedProperties); + } + + Configuration.replace(configurationMap); + } + + public static void useDefaultLogging() { + useDefaultLogging(null); + } + + public static String getClientPrefix(final @NotNull MqttClientConfig config) { + Optional optId = config.getClientIdentifier(); + String id = optId.map(Objects::toString).orElse("UNKNOWN"); + if (id.isEmpty()) { + id = "UNKNOWN"; + } + return "Client '" + + id + + "@" + + config.getServerHost() + + "'"; + } +} diff --git a/src/test/java/com/hivemq/cli/DefaultCLIPropertiesTest.java b/src/test/java/com/hivemq/cli/DefaultCLIPropertiesTest.java index 78572ffa0..a061674a9 100644 --- a/src/test/java/com/hivemq/cli/DefaultCLIPropertiesTest.java +++ b/src/test/java/com/hivemq/cli/DefaultCLIPropertiesTest.java @@ -21,7 +21,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.pmw.tinylog.Level; +import org.tinylog.Level; import java.io.File; import java.io.IOException; @@ -68,7 +68,7 @@ void noPropertyFile() throws Exception { assertEquals(MqttVersion.MQTT_5_0, defaultCLIProperties.getMqttVersion()); assertEquals("localhost", defaultCLIProperties.getHost()); assertEquals(1883, defaultCLIProperties.getPort()); - assertEquals(Level.TRACE, defaultCLIProperties.getShellDebugLevel()); + assertEquals(Level.DEBUG, defaultCLIProperties.getLogfileDebugLevel()); assertEquals("mqtt", defaultCLIProperties.getClientPrefix()); assertEquals(pathToTmpDir + "/.mqtt-cli/logs/", defaultCLIProperties.getLogfilePath()); assertNull(defaultCLIProperties.getClientSubscribeOutputFile()); @@ -87,7 +87,7 @@ void emptyPropertyFile() throws Exception { assertEquals(MqttVersion.MQTT_5_0, defaultCLIProperties.getMqttVersion()); assertEquals("localhost", defaultCLIProperties.getHost()); assertEquals(1883, defaultCLIProperties.getPort()); - assertEquals(Level.TRACE, defaultCLIProperties.getShellDebugLevel()); + assertEquals(Level.DEBUG, defaultCLIProperties.getLogfileDebugLevel()); assertEquals("mqtt", defaultCLIProperties.getClientPrefix()); assertEquals(pathToTmpDir + "/.mqtt-cli/logs/", defaultCLIProperties.getLogfilePath()); assertNull(defaultCLIProperties.getClientSubscribeOutputFile()); @@ -106,7 +106,7 @@ void overridePropertyFile() throws Exception { assertEquals(MqttVersion.MQTT_3_1_1, defaultCLIProperties.getMqttVersion()); assertEquals("broker.hivemq.com", defaultCLIProperties.getHost()); assertEquals(1884, defaultCLIProperties.getPort()); - assertEquals(Level.DEBUG, defaultCLIProperties.getShellDebugLevel()); + assertEquals(Level.TRACE, defaultCLIProperties.getLogfileDebugLevel()); assertEquals("testprefix", defaultCLIProperties.getClientPrefix()); assertEquals("/.mqtt-cli/logs", defaultCLIProperties.getLogfilePath()); assertNull(defaultCLIProperties.getClientSubscribeOutputFile()); diff --git a/src/test/resources/PropertyFiles/override.properties b/src/test/resources/PropertyFiles/override.properties index 5d93b1e9d..b52d2a682 100644 --- a/src/test/resources/PropertyFiles/override.properties +++ b/src/test/resources/PropertyFiles/override.properties @@ -2,7 +2,7 @@ mqtt.port=1884 client.id.prefix=testprefix mqtt.host=broker.hivemq.com mqtt.version=3 -debug.level.shell=DEBUG +logfile.level=TRACE logfile.path=/.mqtt-cli/logs auth.username=mqtt auth.password=password \ No newline at end of file