├── .editorconfig
├── .github
└── workflows
│ ├── check.yml
│ └── releaseExtension.yml
├── .gitignore
├── .idea
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
└── inspectionProfiles
│ └── Project_Default.xml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── HEADER
├── LICENSE
├── NOTICE
├── README.adoc
├── build.gradle.kts
├── gradle.properties
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── renovate.json5
├── settings.gradle.kts
└── src
├── hivemq-extension
└── conf
│ └── examples
│ └── config.xml
├── integrationTest
├── java
│ └── com
│ │ └── hivemq
│ │ └── extensions
│ │ └── log
│ │ ├── FullConfigIT.java
│ │ ├── FullConfigNoPayloadIT.java
│ │ ├── FullConfigNoPayloadNoVerboseIT.java
│ │ ├── FullConfigNoVerboseIT.java
│ │ ├── FullConfigXmlIT.java
│ │ ├── FullConfigXmlNoPayloadIT.java
│ │ ├── FullConfigXmlNoPayloadNoVerboseIT.java
│ │ └── FullConfigXmlNoVerboseIT.java
└── resources
│ ├── fullConfig.properties
│ ├── fullConfig.xml
│ ├── fullConfigNoPayload.properties
│ ├── fullConfigNoPayload.xml
│ ├── fullConfigNoPayloadNoVerbose.properties
│ ├── fullConfigNoPayloadNoVerbose.xml
│ ├── fullConfigNoVerbose.properties
│ ├── fullConfigNoVerbose.xml
│ └── logback-test.xml
├── main
├── java
│ └── com
│ │ └── hivemq
│ │ └── extensions
│ │ └── log
│ │ └── mqtt
│ │ └── message
│ │ ├── ExtensionConstants.java
│ │ ├── MqttMessageLogExtensionMain.java
│ │ ├── config
│ │ ├── ExtensionConfig.java
│ │ ├── ExtensionConfigProperties.java
│ │ ├── ExtensionConfigReader.java
│ │ ├── ExtensionConfigXml.java
│ │ └── XmlParser.java
│ │ ├── initializer
│ │ ├── ClientInitializerImpl.java
│ │ └── ClientInitializerImpl4_2.java
│ │ ├── interceptor
│ │ ├── ConnackOutboundInterceptorImpl.java
│ │ ├── ConnectDisconnectEventListener.java
│ │ ├── ConnectInboundInterceptorImpl.java
│ │ ├── DisconnectInboundInterceptorImpl.java
│ │ ├── DisconnectOutboundInterceptorImpl.java
│ │ ├── PingreqInboundInterceptorImpl.java
│ │ ├── PingrespOutboundInterceptorImpl.java
│ │ ├── PubackInboundInterceptorImpl.java
│ │ ├── PubackOutboundInterceptorImpl.java
│ │ ├── PubcompInboundInterceptorImpl.java
│ │ ├── PubcompOutboundInterceptorImpl.java
│ │ ├── PublishInboundInterceptorImpl.java
│ │ ├── PublishOutboundInterceptorImpl.java
│ │ ├── PubrecInboundInterceptorImpl.java
│ │ ├── PubrecOutboundInterceptorImpl.java
│ │ ├── PubrelInboundInterceptorImpl.java
│ │ ├── PubrelOutboundInterceptorImpl.java
│ │ ├── SubackOutboundInterceptorImpl.java
│ │ ├── SubscribeInboundInterceptorImpl.java
│ │ ├── UnsubackOutboundInterceptorImpl.java
│ │ └── UnsubscribeInboundInterceptorImpl.java
│ │ └── util
│ │ └── MessageLogUtil.java
└── resources
│ └── config.xsd
└── test
├── java
└── com
│ └── hivemq
│ └── extensions
│ └── log
│ └── mqtt
│ └── message
│ ├── MqttMessageLogExtensionMainTest.java
│ ├── config
│ ├── ExtensionConfigPropertiesTest.java
│ └── ExtensionConfigReaderTest.java
│ └── util
│ ├── LogbackTestAppender.java
│ ├── MessageLogUtilTest.java
│ └── PacketUtil.java
└── resources
├── test-conf
└── mqttMessageLog.properties
├── test-invalid-xml-conf
└── conf
│ └── config.xml
└── test-xml-conf
└── conf
└── config.xml
/.github/workflows/check.yml:
--------------------------------------------------------------------------------
1 | name: CI Check
2 |
3 | on:
4 | push:
5 | branches: [ "**" ]
6 |
7 | jobs:
8 | check:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
13 | - name: Setup Java
14 | uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4
15 | with:
16 | distribution: temurin
17 | java-version: 11
18 | - name: Setup Gradle
19 | uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4
20 | - name: Check
21 | run: ./gradlew check
22 | env:
23 | ORG_GRADLE_PROJECT_dockerHubUsername: ${{ secrets.DOCKER_USERNAME }}
24 | ORG_GRADLE_PROJECT_dockerHubPassword: ${{ secrets.DOCKER_TOKEN }}
25 |
--------------------------------------------------------------------------------
/.github/workflows/releaseExtension.yml:
--------------------------------------------------------------------------------
1 | name: Release Extension
2 |
3 | on:
4 | release:
5 | types: [ published ]
6 |
7 | jobs:
8 | release:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
13 | - name: Setup Java
14 | uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4
15 | with:
16 | distribution: temurin
17 | java-version: 11
18 | - name: Setup Gradle
19 | uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4
20 | - name: Build Zip
21 | run: ./gradlew hivemqExtensionZip
22 | - name: Upload GitHub Release Asset
23 | run: gh release upload ${{ github.event.release.tag_name }} ./build/hivemq-extension/hivemq-mqtt-message-log-extension-${{ github.event.release.name }}.zip
24 | env:
25 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Gradle
2 | .gradle
3 | build/
4 |
5 | # IntelliJ
6 | out/
7 | *.iml
8 | .idea/*
9 | !.idea/codeStyles
10 | !.idea/inspectionProfiles
11 | !.idea/runConfigurations
12 |
13 | .java-version
14 | .DS_Store
15 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # HiveMQ Code of Conduct
2 |
3 | Please refer to our [HiveMQ Code of Conduct](https://github.com/hivemq/hivemq-community/blob/master/code-of-conduct.md).
4 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Welcome to the HiveMQ Community!
4 | Glad to see your interest in contributing to HiveMQ Mqtt Message Log Extension.
5 | Please checkout our [Contribution Guide](https://github.com/hivemq/hivemq-community/blob/master/CONTRIBUTING.adoc) to make sure your contribution will be accepted by the HiveMQ team.
6 |
7 | For information on how the HiveMQ Community is organized and how contributions will be accepted please have a look at our [HiveMQ Community Repo](https://github.com/hivemq/hivemq-community).
8 |
--------------------------------------------------------------------------------
/HEADER:
--------------------------------------------------------------------------------
1 | Copyright 2019-present HiveMQ GmbH
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright 2018-present HiveMQ GmbH
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use the contents of this repository except in
5 | compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
--------------------------------------------------------------------------------
/README.adoc:
--------------------------------------------------------------------------------
1 | :hivemq-blog-tools: http://www.hivemq.com/mqtt-toolbox
2 | :hivemq-support: http://www.hivemq.com/support/
3 | :hivemq-extension-download: https://www.hivemq.com/extension/mqtt-message-log-extension/
4 |
5 | = HiveMQ MQTT Message Log Extension
6 |
7 | image:https://img.shields.io/badge/Extension_Type-Logging-orange?style=for-the-badge[Extension Type]
8 | image:https://img.shields.io/github/v/release/hivemq/hivemq-mqtt-message-log-extension?style=for-the-badge[GitHub release (latest by date),link=https://github.com/hivemq/hivemq-mqtt-message-log-extension/releases/latest]
9 | image:https://img.shields.io/github/license/hivemq/hivemq-mqtt-message-log-extension?style=for-the-badge&color=brightgreen[GitHub,link=LICENSE]
10 | image:https://img.shields.io/github/actions/workflow/status/hivemq/hivemq-mqtt-message-log-extension/check.yml?branch=master&style=for-the-badge[GitHub Workflow Status,link=https://github.com/hivemq/hivemq-mqtt-message-log-extension/actions/workflows/check.yml?query=branch%3Amaster]
11 |
12 | == Prerequisites
13 |
14 | * HiveMQ Enterprise Edition (EE) 4.2.0 or later
15 | * HiveMQ Community Edition (CE) 2020.1 or later
16 |
17 | == Purpose
18 |
19 | The HiveMQ MQTT Message Log Extension provides custom logging events on clients communicating with the broker.
20 | This is useful for debugging and development purposes.
21 |
22 | *The extension logs the following events:*
23 |
24 | [cols="6,2,2"]
25 | |===
26 | |Event | Config Property | Minimum Version
27 |
28 | |A client connects to HiveMQ | client-connect | 4.2 EE or 2020.1 CE
29 | |A client disconnects from HiveMQ | client-disconnect | 4.2 EE or 2020.1 CE
30 | |A client sends a PUBLISH message | publish-received | 4.2 EE or 2020.1 CE
31 | |A client sends a SUBSCRIBE message | subscribe-received |4.2 EE or 2020.1 CE
32 | |HiveMQ sends a PUBLISH message to a client | publish-send |4.2 EE or 2020.1 CE
33 | |A client sends an UNSUBSCRIBE message | unsubscribe-received | 4.3 EE or 2020.1 CE
34 | |A client send a PING request | ping-request-received | 4.3 EE or 2020.1 CE
35 | |A client completes a received QoS 1 PUBLISH with a PUBACK message | puback-received | 4.3 EE or 2020.1 CE
36 | |A client acknowledges the reception of a QoS 2 PUBLISH with a PUBREC message | pubrec-received | 4.3 EE or 2020.1 CE
37 | |A client completes a sent QoS 2 PUBLISH with a PUBREL message | pubrel-received | 4.3 EE or 2020.1 CE
38 | |A client completes a received QoS 2 PUBLISH with a PUBCOMP message | pubcomp-received | 4.3 EE or 2020.1 CE
39 | |HiveMQ sends a CONNACK message to a client | connack-send | 4.3 EE or 2020.1 CE
40 | |HiveMQ disconnects a client with a DISCONNECT message | client-disconnect | 4.3 EE or 2020.1 CE
41 | |HiveMQ sends a SUBACK message to a client | suback-send | 4.3 EE or 2020.1 CE
42 | |HiveMQ sends an UNSUBACK message to a client | unsuback-send | 4.3 EE or 2020.1 CE
43 | |HiveMQ sends a PING response to a client | ping-response-send | 4.3 EE or 2020.1 CE
44 | |HiveMQ completes a received QoS 1 PUBLISH with a PUBACK message | puback-send | 4.3 EE or 2020.1 CE
45 | |HiveMQ acknowledges the reception of a QoS 2 PUBLISH with a PUBREC message | pubrec-send | 4.3 EE or 2020.1 CE
46 | |HiveMQ completes a sent QoS 2 PUBLISH with a PUBREL message | pubrel-send | 4.3 EE or 2020.1 CE
47 | |HiveMQ completes a received QoS 2 PUBLISH with a PUBCOMP message | pubcomp-send | 4.3 EE or 2020.1 CE
48 | |===
49 |
50 | == Installation
51 |
52 | * Download the extension from the {hivemq-extension-download}[HiveMQ Marketplace^].
53 | * Copy the content of the zip file to the `extensions` folder of your HiveMQ nodes.
54 | * Configure the extension by adding a `config.xml` file in the extension's `conf` folder.
55 | ** For your convenience, we provide an example configuration `conf/examples/config.xml` that you can copy and modify as desired.
56 | ** The file must be located in `HIVEMQ_HOME/extensions/hivemq-mqtt-message-log-extension/conf/config.xml`.
57 |
58 | NOTE: Starting with release 1.2.0 of the extension, the legacy configuration file `mqttMessageLog.properties` is deprecated.
59 | Support for the legacy configuration will be removed in a future release.
60 |
61 | == Configuration
62 |
63 | === Event Configuration
64 |
65 | By default, all MQTT events are logged.
66 | It is possible to opt out of specific log event types by adding a `config.xml` file to your `hivemq-mqtt-message-log-extension/conf` folder.
67 | An example configuration file is available in `conf/examples/`, which removes the logging of PUBLISH messages.
68 |
69 | === General Configuration
70 |
71 | |===
72 | |Config Property | Description | Default
73 |
74 | |verbose |Log detailed information about an MQTT event | false
75 | |payload |Log the payload of a message | true
76 | |===
77 |
78 | Normally, events only log important information.
79 | Set the `verbose` property to `true` to log all available information.
80 | You can see the difference between normal logging and verbose logging in the <> section.
81 |
82 | CAUTION: use `verbose=true` very carefully as it will flood your log immediately.
83 |
84 | Set the `payload` property to `false` if you want to suppress logging payloads (i.e. for publish-received, publish-send, and will messages).
85 |
86 | == First Steps
87 |
88 | Connect with an {hivemq-blog-tools}[MQTT client] of your choice.
89 | You should see a log message with its client identifier, MQTT version, clean start flag and session expiry interval.
90 |
91 | [[example]]
92 | == Examples
93 |
94 | === Verbose CONNECT message with payload
95 |
96 | [source,bash]
97 | ----
98 | "17:26:23.602 INFO - Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false',
99 | Session Expiry Interval: '10000', Keep Alive: '20000', Maximum Packet Size: '40000',
100 | Receive Maximum: '30000', Topic Alias Maximum: '50000', Request Problem Information: 'true',
101 | Request Response Information: 'false', Username: 'the username', Password: 'the password',
102 | Auth Method: 'auth method', Auth Data (Base64): 'YXV0aCBkYXRh',
103 | User Properties: [Name: 'name0', Value: 'value0'], [Name: 'name1', Value: 'value1'],
104 | Will: { Topic: 'willtopic', Payload: 'payload', QoS: '1', Retained: 'false', Message Expiry Interval: '1234',
105 | Duplicate Delivery: 'false', Correlation Data: 'data', Response Topic: 'response topic',
106 | Content Type: 'content type', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1, 2, 3, 4]',
107 | User Properties: [Name: 'name0', Value: 'value0'], [Name: 'name1', Value: 'value1'],
108 | [Name: 'name2', Value: 'value2'], Will Delay: '100' }"
109 | ----
110 |
111 | === Basic CONNECT message
112 |
113 | [source,bash]
114 | ----
115 | "17:26:23.602 INFO - Received CONNECT from client 'clientid': Protocol version: 'V_5', Clean Start: 'false', Session Expiry Interval: '10000'"
116 | ----
117 |
118 | == Need Help?
119 |
120 | If you encounter any problems, we are happy to help.
121 | The best place to get in contact is our {hivemq-support}[support^].
122 |
123 | == Contributing
124 |
125 | If you want to contribute to HiveMQ MQTT Message Log Extension, see the link:CONTRIBUTING.md[contribution guidelines].
126 |
127 | == License
128 |
129 | HiveMQ MQTT Message Log Extension is licensed under the `APACHE LICENSE, VERSION 2.0`.
130 | A copy of the license can be found link:LICENSE[here].
131 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.hivemq.extension)
3 | alias(libs.plugins.defaults)
4 | alias(libs.plugins.oci)
5 | alias(libs.plugins.license)
6 | }
7 |
8 | group = "com.hivemq.extensions"
9 | description = "HiveMQ Mqtt Message Log Extension"
10 |
11 | hivemqExtension {
12 | name = "HiveMQ Mqtt Message Log Extension"
13 | author = "HiveMQ"
14 | priority = 1000
15 | startPriority = 1000
16 | sdkVersion = libs.versions.hivemq.extensionSdk
17 |
18 | resources {
19 | from("LICENSE")
20 | from("src/main/resources/config.xsd") { into("conf") }
21 | }
22 | }
23 |
24 | java {
25 | toolchain {
26 | languageVersion = JavaLanguageVersion.of(11)
27 | }
28 | }
29 |
30 | dependencies {
31 | compileOnly(libs.jetbrains.annotations)
32 | implementation(libs.commonsLang)
33 | implementation(libs.jaxb.api)
34 | runtimeOnly(libs.jaxb.impl)
35 | }
36 |
37 | oci {
38 | registries {
39 | dockerHub {
40 | optionalCredentials()
41 | }
42 | }
43 | imageMapping {
44 | mapModule("com.hivemq", "hivemq-enterprise") {
45 | toImage("hivemq/hivemq4")
46 | }
47 | }
48 | imageDefinitions.register("main") {
49 | allPlatforms {
50 | dependencies {
51 | runtime("com.hivemq:hivemq-enterprise:latest") { isChanging = true }
52 | }
53 | layer("main") {
54 | contents {
55 | permissions("opt/hivemq/", 0b111_111_101)
56 | permissions("opt/hivemq/extensions/", 0b111_111_101)
57 | into("opt/hivemq/extensions") {
58 | from(zipTree(tasks.hivemqExtensionZip.flatMap { it.archiveFile }))
59 | }
60 | }
61 | }
62 | }
63 | }
64 | }
65 |
66 | @Suppress("UnstableApiUsage")
67 | testing {
68 | suites {
69 | withType {
70 | useJUnitJupiter(libs.versions.junit.jupiter)
71 | }
72 | "test"(JvmTestSuite::class) {
73 | dependencies {
74 | compileOnly(libs.jetbrains.annotations)
75 | implementation(libs.mockito)
76 | implementation(libs.logback.classic)
77 | }
78 | }
79 | "integrationTest"(JvmTestSuite::class) {
80 | dependencies {
81 | compileOnly(libs.jetbrains.annotations)
82 | implementation(libs.awaitility)
83 | implementation(libs.hivemq.mqttClient)
84 | implementation(libs.testcontainers.junitJupiter)
85 | implementation(libs.testcontainers.hivemq)
86 | implementation(libs.gradleOci.junitJupiter)
87 | runtimeOnly(libs.logback.classic)
88 | }
89 | oci.of(this) {
90 | imageDependencies {
91 | runtime(project).tag("latest")
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
98 | license {
99 | header = rootDir.resolve("HEADER")
100 | mapping("java", "SLASHSTAR_STYLE")
101 | exclude("**/test-conf/mqttMessageLog.properties")
102 | }
103 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | version=1.2.1
2 |
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | awaitility = "4.3.0"
3 | commonsLang = "3.17.0"
4 | gradleOci-junitJupiter = "0.7.0"
5 | hivemq-extensionSdk = "4.3.0"
6 | hivemq-mqttClient = "1.3.6"
7 | jaxb-api = "4.0.2"
8 | jaxb-impl = "4.0.5"
9 | jetbrains-annotations = "26.0.2"
10 | junit-jupiter = "5.10.3"
11 | logback = "1.5.18"
12 | mockito = "5.18.0"
13 | okhttp = "4.12.0"
14 | testcontainers = "1.21.1"
15 |
16 | [libraries]
17 | awaitility = { module = "org.awaitility:awaitility", version.ref = "awaitility" }
18 | commonsLang = { module = "org.apache.commons:commons-lang3", version.ref = "commonsLang" }
19 | gradleOci-junitJupiter = { module = "io.github.sgtsilvio:gradle-oci-junit-jupiter", version.ref = "gradleOci-junitJupiter" }
20 | hivemq-mqttClient = { module = "com.hivemq:hivemq-mqtt-client", version.ref = "hivemq-mqttClient" }
21 | jaxb-api = { module = "jakarta.xml.bind:jakarta.xml.bind-api", version.ref = "jaxb-api" }
22 | jaxb-impl = { module = "org.glassfish.jaxb:jaxb-runtime", version.ref = "jaxb-impl" }
23 | jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "jetbrains-annotations" }
24 | logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
25 | mockito = { module = "org.mockito:mockito-core", version.ref = "mockito" }
26 | okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
27 | testcontainers-hivemq = { module = "org.testcontainers:hivemq", version.ref = "testcontainers" }
28 | testcontainers-junitJupiter = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" }
29 |
30 | [plugins]
31 | defaults = { id = "io.github.sgtsilvio.gradle.defaults", version = "0.2.0" }
32 | hivemq-extension = { id = "com.hivemq.extension", version = "4.0.0" }
33 | license = { id = "com.github.hierynomus.license", version = "0.16.1" }
34 | oci = { id = "io.github.sgtsilvio.gradle.oci", version = "0.23.0" }
35 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hivemq/hivemq-mqtt-message-log-extension/ee23728b2925a06c784371e187732b0a1c9af890/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
90 | ' "$PWD" ) || exit
91 |
92 | # Use the maximum available, or set MAX_FD != -1 to use that value.
93 | MAX_FD=maximum
94 |
95 | warn () {
96 | echo "$*"
97 | } >&2
98 |
99 | die () {
100 | echo
101 | echo "$*"
102 | echo
103 | exit 1
104 | } >&2
105 |
106 | # OS specific support (must be 'true' or 'false').
107 | cygwin=false
108 | msys=false
109 | darwin=false
110 | nonstop=false
111 | case "$( uname )" in #(
112 | CYGWIN* ) cygwin=true ;; #(
113 | Darwin* ) darwin=true ;; #(
114 | MSYS* | MINGW* ) msys=true ;; #(
115 | NONSTOP* ) nonstop=true ;;
116 | esac
117 |
118 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
119 |
120 |
121 | # Determine the Java command to use to start the JVM.
122 | if [ -n "$JAVA_HOME" ] ; then
123 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
124 | # IBM's JDK on AIX uses strange locations for the executables
125 | JAVACMD=$JAVA_HOME/jre/sh/java
126 | else
127 | JAVACMD=$JAVA_HOME/bin/java
128 | fi
129 | if [ ! -x "$JAVACMD" ] ; then
130 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
131 |
132 | Please set the JAVA_HOME variable in your environment to match the
133 | location of your Java installation."
134 | fi
135 | else
136 | JAVACMD=java
137 | if ! command -v java >/dev/null 2>&1
138 | then
139 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
140 |
141 | Please set the JAVA_HOME variable in your environment to match the
142 | location of your Java installation."
143 | fi
144 | fi
145 |
146 | # Increase the maximum file descriptors if we can.
147 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
148 | case $MAX_FD in #(
149 | max*)
150 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
151 | # shellcheck disable=SC2039,SC3045
152 | MAX_FD=$( ulimit -H -n ) ||
153 | warn "Could not query maximum file descriptor limit"
154 | esac
155 | case $MAX_FD in #(
156 | '' | soft) :;; #(
157 | *)
158 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
159 | # shellcheck disable=SC2039,SC3045
160 | ulimit -n "$MAX_FD" ||
161 | warn "Could not set maximum file descriptor limit to $MAX_FD"
162 | esac
163 | fi
164 |
165 | # Collect all arguments for the java command, stacking in reverse order:
166 | # * args from the command line
167 | # * the main class name
168 | # * -classpath
169 | # * -D...appname settings
170 | # * --module-path (only if needed)
171 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
172 |
173 | # For Cygwin or MSYS, switch paths to Windows format before running java
174 | if "$cygwin" || "$msys" ; then
175 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
176 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
177 |
178 | JAVACMD=$( cygpath --unix "$JAVACMD" )
179 |
180 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
181 | for arg do
182 | if
183 | case $arg in #(
184 | -*) false ;; # don't mess with options #(
185 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
186 | [ -e "$t" ] ;; #(
187 | *) false ;;
188 | esac
189 | then
190 | arg=$( cygpath --path --ignore --mixed "$arg" )
191 | fi
192 | # Roll the args list around exactly as many times as the number of
193 | # args, so each arg winds up back in the position where it started, but
194 | # possibly modified.
195 | #
196 | # NB: a `for` loop captures its iteration list before it begins, so
197 | # changing the positional parameters here affects neither the number of
198 | # iterations, nor the values presented in `arg`.
199 | shift # remove old arg
200 | set -- "$@" "$arg" # push replacement arg
201 | done
202 | fi
203 |
204 |
205 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
206 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
207 |
208 | # Collect all arguments for the java command:
209 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
210 | # and any embedded shellness will be escaped.
211 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
212 | # treated as '${Hostname}' itself on the command line.
213 |
214 | set -- \
215 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
216 | -classpath "$CLASSPATH" \
217 | org.gradle.wrapper.GradleWrapperMain \
218 | "$@"
219 |
220 | # Stop when "xargs" is not available.
221 | if ! command -v xargs >/dev/null 2>&1
222 | then
223 | die "xargs is not available"
224 | fi
225 |
226 | # Use "xargs" to parse quoted args.
227 | #
228 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
229 | #
230 | # In Bash we could simply go:
231 | #
232 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
233 | # set -- "${ARGS[@]}" "$@"
234 | #
235 | # but POSIX shell has neither arrays nor command substitution, so instead we
236 | # post-process each arg (as a line of input to sed) to backslash-escape any
237 | # character that might be a shell metacharacter, then use eval to reverse
238 | # that process (while maintaining the separation between arguments), and wrap
239 | # the whole thing up as a single "set" statement.
240 | #
241 | # This will of course break if any of these variables contains a newline or
242 | # an unmatched quote.
243 | #
244 |
245 | eval "set -- $(
246 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
247 | xargs -n1 |
248 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
249 | tr '\n' ' '
250 | )" '"$@"'
251 |
252 | exec "$JAVACMD" "$@"
253 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/renovate.json5:
--------------------------------------------------------------------------------
1 | {
2 | $schema: "https://docs.renovatebot.com/renovate-schema.json",
3 | extends: [
4 | "local>hivemq/renovate-config:default.json5",
5 | ],
6 | addLabels: [
7 | "tooling-and-extensions-coordination",
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "hivemq-mqtt-message-log-extension"
2 |
--------------------------------------------------------------------------------
/src/hivemq-extension/conf/examples/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
10 | false
11 | true
12 |
13 |
14 | false
15 | false
16 |
17 | true
18 | true
19 | true
20 | true
21 | true
22 | true
23 | true
24 | true
25 | true
26 | true
27 | true
28 | true
29 | true
30 | true
31 | true
32 | true
33 | true
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/integrationTest/java/com/hivemq/extensions/log/FullConfigIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log;
17 |
18 | import com.hivemq.client.mqtt.datatypes.MqttQos;
19 | import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
20 | import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
21 | import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
22 | import io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages;
23 | import org.jetbrains.annotations.NotNull;
24 | import org.junit.jupiter.api.Test;
25 | import org.testcontainers.hivemq.HiveMQContainer;
26 | import org.testcontainers.junit.jupiter.Container;
27 | import org.testcontainers.junit.jupiter.Testcontainers;
28 | import org.testcontainers.utility.MountableFile;
29 |
30 | import java.nio.charset.StandardCharsets;
31 |
32 | import static org.awaitility.Awaitility.await;
33 |
34 | /**
35 | * @since 1.1.3
36 | */
37 | @Testcontainers
38 | public class FullConfigIT {
39 |
40 | @Container
41 | final @NotNull HiveMQContainer hivemq =
42 | new HiveMQContainer(OciImages.getImageName("hivemq/extensions/hivemq-mqtt-message-log-extension")
43 | .asCompatibleSubstituteFor("hivemq/hivemq4")) //
44 | .withCopyToContainer(MountableFile.forClasspathResource("fullConfig.properties"),
45 | "/opt/hivemq/extensions/hivemq-mqtt-message-log-extension/mqttMessageLog.properties")
46 | .withLogConsumer(outputFrame -> System.out.print("HiveMQ: " + outputFrame.getUtf8String()));
47 |
48 | @Test
49 | void test() {
50 | final Mqtt5BlockingClient client = Mqtt5Client.builder()
51 | .identifier("test-client")
52 | .serverHost(hivemq.getHost())
53 | .serverPort(hivemq.getMqttPort())
54 | .buildBlocking();
55 |
56 | client.connectWith()
57 | .willPublish()
58 | .topic("will")
59 | .qos(MqttQos.EXACTLY_ONCE)
60 | .payload("willPayload".getBytes(StandardCharsets.UTF_8))
61 | .contentType("text/plain")
62 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
63 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
64 | .responseTopic("willResponse")
65 | .retain(false)
66 | .messageExpiryInterval(10_000)
67 | .userProperties()
68 | .add("willProperty", "willValue")
69 | .applyUserProperties()
70 | .delayInterval(50_000)
71 | .applyWillPublish()
72 | .send();
73 | await().until(() -> hivemq.getLogs()
74 | .contains(
75 | "Received CONNECT from client 'test-client': Protocol version: 'V_5', Clean Start: 'true', Session Expiry Interval: '0', Keep Alive: '60', Maximum Packet Size: '268435460', Receive Maximum: '65535', Topic Alias Maximum: '0', Request Problem Information: 'true', Request Response Information: 'false', Username: 'null', Password: 'null', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null', Will: { Topic: 'will', Payload: 'willPayload', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'willResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'willProperty', Value: 'willValue'], Will Delay: '50000' }"));
76 | await().until(() -> hivemq.getLogs()
77 | .contains(
78 | "Sent CONNACK to client 'test-client': Reason Code: 'SUCCESS', Session Present: 'false', Session Expiry Interval: 'null', Assigned ClientId 'null', Maximum QoS: 'EXACTLY_ONCE', Maximum Packet Size: '268435460', Receive Maximum: '10', Topic Alias Maximum: '5', Reason String: 'null', Response Information: 'null', Server Keep Alive: 'null', Server Reference: 'null', Shared Subscription Available: 'true', Wildcards Available: 'true', Retain Available: 'true', Subscription Identifiers Available: 'true', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null'"));
79 |
80 | client.subscribeWith().topicFilter("#").send();
81 | await().until(() -> hivemq.getLogs()
82 | .contains(
83 | "Received SUBSCRIBE from client 'test-client': Topics: { [Topic: '#', QoS: '2', Retain As Published: 'false', No Local: 'false', Retain Handling: 'SEND'] }, Subscription Identifier: '1', User Properties: 'null'"));
84 | await().until(() -> hivemq.getLogs()
85 | .contains(
86 | "Sent SUBACK to client 'test-client': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_2'] }, Reason String: 'null', User Properties: 'null'"));
87 |
88 | client.publishWith()
89 | .topic("publish")
90 | .qos(MqttQos.EXACTLY_ONCE)
91 | .payload("payload1".getBytes(StandardCharsets.UTF_8))
92 | .contentType("text/plain")
93 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
94 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
95 | .responseTopic("publishResponse")
96 | .retain(false)
97 | .messageExpiryInterval(10_000)
98 | .userProperties()
99 | .add("publishProperty", "publishValue")
100 | .applyUserProperties()
101 | .send();
102 | await().until(() -> hivemq.getLogs()
103 | .contains(
104 | "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'publishProperty', Value: 'publishValue']"));
105 | await().until(() -> hivemq.getLogs()
106 | .contains(
107 | "Sent PUBREC to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
108 | await().until(() -> hivemq.getLogs()
109 | .contains(
110 | "Received PUBREL from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
111 | await().until(() -> hivemq.getLogs()
112 | .contains(
113 | "Sent PUBCOMP to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
114 |
115 | await().until(() -> hivemq.getLogs()
116 | .contains(
117 | "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1]', User Properties: [Name: 'publishProperty', Value: 'publishValue']"));
118 | await().until(() -> hivemq.getLogs()
119 | .contains(
120 | "Received PUBREC from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
121 | await().until(() -> hivemq.getLogs()
122 | .contains(
123 | "Sent PUBREL to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
124 | await().until(() -> hivemq.getLogs()
125 | .contains(
126 | "Received PUBCOMP from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
127 |
128 | client.publishWith()
129 | .topic("publish")
130 | .qos(MqttQos.AT_LEAST_ONCE)
131 | .payload("payload2".getBytes(StandardCharsets.UTF_8))
132 | .contentType("text/plain")
133 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
134 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
135 | .responseTopic("publishResponse")
136 | .retain(false)
137 | .messageExpiryInterval(10_000)
138 | .userProperties()
139 | .add("publishProperty", "publishValue")
140 | .applyUserProperties()
141 | .send();
142 | await().until(() -> hivemq.getLogs()
143 | .contains(
144 | "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'publishProperty', Value: 'publishValue']"));
145 | await().until(() -> hivemq.getLogs()
146 | .contains(
147 | "Sent PUBACK to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
148 | await().until(() -> hivemq.getLogs()
149 | .contains(
150 | "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1]', User Properties: [Name: 'publishProperty', Value: 'publishValue']"));
151 | await().until(() -> hivemq.getLogs()
152 | .contains(
153 | "Received PUBACK from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
154 |
155 | client.unsubscribeWith().topicFilter("#").send();
156 | await().until(() -> hivemq.getLogs()
157 | .contains(
158 | "Received UNSUBSCRIBE from client 'test-client': Topics: { [Topic: '#'] }, User Properties: 'null'"));
159 | await().until(() -> hivemq.getLogs()
160 | .contains(
161 | "Sent UNSUBACK to client 'test-client': Unsuback Reason Codes: { [Reason Code: 'SUCCESS'] }, Reason String: 'null', User Properties: 'null'"));
162 |
163 | client.disconnect();
164 | await().until(() -> hivemq.getLogs()
165 | .contains(
166 | "Received DISCONNECT from client 'test-client': Reason Code: 'NORMAL_DISCONNECTION', Reason String: 'null', Server Reference: 'null', Session Expiry: 'null', User Properties: 'null'"));
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/integrationTest/java/com/hivemq/extensions/log/FullConfigNoPayloadNoVerboseIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log;
17 |
18 | import com.hivemq.client.mqtt.datatypes.MqttQos;
19 | import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
20 | import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
21 | import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
22 | import io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages;
23 | import org.jetbrains.annotations.NotNull;
24 | import org.junit.jupiter.api.Test;
25 | import org.testcontainers.hivemq.HiveMQContainer;
26 | import org.testcontainers.junit.jupiter.Container;
27 | import org.testcontainers.junit.jupiter.Testcontainers;
28 | import org.testcontainers.utility.MountableFile;
29 |
30 | import java.nio.charset.StandardCharsets;
31 |
32 | import static org.awaitility.Awaitility.await;
33 | import static org.junit.jupiter.api.Assertions.assertFalse;
34 |
35 | /**
36 | * @since 1.1.6
37 | */
38 | @Testcontainers
39 | public class FullConfigNoPayloadNoVerboseIT {
40 |
41 | @Container
42 | final @NotNull HiveMQContainer hivemq =
43 | new HiveMQContainer(OciImages.getImageName("hivemq/extensions/hivemq-mqtt-message-log-extension")
44 | .asCompatibleSubstituteFor("hivemq/hivemq4")) //
45 | .withCopyToContainer(MountableFile.forClasspathResource("fullConfigNoPayloadNoVerbose.properties"),
46 | "/opt/hivemq/extensions/hivemq-mqtt-message-log-extension/mqttMessageLog.properties")
47 | .withLogConsumer(outputFrame -> System.out.print("HiveMQ: " + outputFrame.getUtf8String()));
48 |
49 | @Test
50 | void test() {
51 | final Mqtt5BlockingClient client = Mqtt5Client.builder()
52 | .identifier("test-client")
53 | .serverHost(hivemq.getHost())
54 | .serverPort(hivemq.getMqttPort())
55 | .buildBlocking();
56 |
57 | client.connectWith()
58 | .willPublish()
59 | .topic("will")
60 | .qos(MqttQos.EXACTLY_ONCE)
61 | .payload("willPayload".getBytes(StandardCharsets.UTF_8))
62 | .contentType("text/plain")
63 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
64 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
65 | .responseTopic("willResponse")
66 | .retain(false)
67 | .messageExpiryInterval(10_000)
68 | .userProperties()
69 | .add("willProperty", "willValue")
70 | .applyUserProperties()
71 | .delayInterval(50_000)
72 | .applyWillPublish()
73 | .send();
74 | await().until(() -> hivemq.getLogs()
75 | .contains(
76 | "Received CONNECT from client 'test-client': Protocol version: 'V_5', Clean Start: 'true', Session Expiry Interval: '0'"));
77 | await().until(() -> hivemq.getLogs()
78 | .contains("Sent CONNACK to client 'test-client': Reason Code: 'SUCCESS', Session Present: 'false'"));
79 |
80 | client.subscribeWith().topicFilter("#").send();
81 | await().until(() -> hivemq.getLogs()
82 | .contains("Received SUBSCRIBE from client 'test-client': Topics: { [Topic: '#', QoS: '2'] }"));
83 | await().until(() -> hivemq.getLogs()
84 | .contains("Sent SUBACK to client 'test-client': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_2'] }"));
85 |
86 | client.publishWith()
87 | .topic("publish")
88 | .qos(MqttQos.EXACTLY_ONCE)
89 | .payload("payload1".getBytes(StandardCharsets.UTF_8))
90 | .contentType("text/plain")
91 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
92 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
93 | .responseTopic("publishResponse")
94 | .retain(false)
95 | .messageExpiryInterval(10_000)
96 | .userProperties()
97 | .add("publishProperty", "publishValue")
98 | .applyUserProperties()
99 | .send();
100 | await().until(() -> hivemq.getLogs()
101 | .contains("Received PUBLISH from client 'test-client' for topic 'publish': QoS: '2', Retained: 'false'"));
102 | await().until(() -> hivemq.getLogs().contains("Sent PUBREC to client 'test-client': Reason Code: 'SUCCESS'"));
103 | await().until(() -> hivemq.getLogs()
104 | .contains("Received PUBREL from client 'test-client': Reason Code: 'SUCCESS'"));
105 | await().until(() -> hivemq.getLogs().contains("Sent PUBCOMP to client 'test-client': Reason Code: 'SUCCESS'"));
106 |
107 | await().until(() -> hivemq.getLogs()
108 | .contains("Sent PUBLISH to client 'test-client' on topic 'publish': QoS: '2', Retained: 'false'"));
109 | await().until(() -> hivemq.getLogs()
110 | .contains("Received PUBREC from client 'test-client': Reason Code: 'SUCCESS'"));
111 | await().until(() -> hivemq.getLogs().contains("Sent PUBREL to client 'test-client': Reason Code: 'SUCCESS'"));
112 | await().until(() -> hivemq.getLogs()
113 | .contains("Received PUBCOMP from client 'test-client': Reason Code: 'SUCCESS'"));
114 |
115 | client.publishWith()
116 | .topic("publish")
117 | .qos(MqttQos.AT_LEAST_ONCE)
118 | .payload("payload2".getBytes(StandardCharsets.UTF_8))
119 | .contentType("text/plain")
120 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
121 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
122 | .responseTopic("publishResponse")
123 | .retain(false)
124 | .messageExpiryInterval(10_000)
125 | .userProperties()
126 | .add("publishProperty", "publishValue")
127 | .applyUserProperties()
128 | .send();
129 | await().until(() -> hivemq.getLogs()
130 | .contains("Received PUBLISH from client 'test-client' for topic 'publish': QoS: '1', Retained: 'false'"));
131 | await().until(() -> hivemq.getLogs().contains("Sent PUBACK to client 'test-client': Reason Code: 'SUCCESS'"));
132 | await().until(() -> hivemq.getLogs()
133 | .contains("Sent PUBLISH to client 'test-client' on topic 'publish': QoS: '1', Retained: 'false'"));
134 | await().until(() -> hivemq.getLogs()
135 | .contains("Received PUBACK from client 'test-client': Reason Code: 'SUCCESS'"));
136 |
137 | client.unsubscribeWith().topicFilter("#").send();
138 | await().until(() -> hivemq.getLogs()
139 | .contains("Received UNSUBSCRIBE from client 'test-client': Topics: { [Topic: '#'] }"));
140 | await().until(() -> hivemq.getLogs()
141 | .contains("Sent UNSUBACK to client 'test-client': Unsuback Reason Codes: { [Reason Code: 'SUCCESS'] }"));
142 |
143 | client.disconnect();
144 | await().until(() -> hivemq.getLogs()
145 | .contains("Received DISCONNECT from client 'test-client': Reason Code: 'NORMAL_DISCONNECTION'"));
146 |
147 | assertFalse(hivemq.getLogs().contains("Payload: 'payload1'"));
148 | assertFalse(hivemq.getLogs().contains("Payload: 'payload2'"));
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/integrationTest/java/com/hivemq/extensions/log/FullConfigNoVerboseIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log;
17 |
18 | import com.hivemq.client.mqtt.datatypes.MqttQos;
19 | import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
20 | import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
21 | import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
22 | import io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages;
23 | import org.jetbrains.annotations.NotNull;
24 | import org.junit.jupiter.api.Test;
25 | import org.testcontainers.hivemq.HiveMQContainer;
26 | import org.testcontainers.junit.jupiter.Container;
27 | import org.testcontainers.junit.jupiter.Testcontainers;
28 | import org.testcontainers.utility.MountableFile;
29 |
30 | import java.nio.charset.StandardCharsets;
31 |
32 | import static org.awaitility.Awaitility.await;
33 | import static org.junit.jupiter.api.Assertions.assertTrue;
34 |
35 | /**
36 | * @since 1.1.6
37 | */
38 | @Testcontainers
39 | public class FullConfigNoVerboseIT {
40 |
41 | @Container
42 | final @NotNull HiveMQContainer hivemq =
43 | new HiveMQContainer(OciImages.getImageName("hivemq/extensions/hivemq-mqtt-message-log-extension")
44 | .asCompatibleSubstituteFor("hivemq/hivemq4")) //
45 | .withCopyToContainer(MountableFile.forClasspathResource("fullConfigNoVerbose.properties"),
46 | "/opt/hivemq/extensions/hivemq-mqtt-message-log-extension/mqttMessageLog.properties")
47 | .withLogConsumer(outputFrame -> System.out.print("HiveMQ: " + outputFrame.getUtf8String()));
48 |
49 | @Test
50 | void test() {
51 | final Mqtt5BlockingClient client = Mqtt5Client.builder()
52 | .identifier("test-client")
53 | .serverHost(hivemq.getHost())
54 | .serverPort(hivemq.getMqttPort())
55 | .buildBlocking();
56 |
57 | client.connectWith()
58 | .willPublish()
59 | .topic("will")
60 | .qos(MqttQos.EXACTLY_ONCE)
61 | .payload("willPayload".getBytes(StandardCharsets.UTF_8))
62 | .contentType("text/plain")
63 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
64 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
65 | .responseTopic("willResponse")
66 | .retain(false)
67 | .messageExpiryInterval(10_000)
68 | .userProperties()
69 | .add("willProperty", "willValue")
70 | .applyUserProperties()
71 | .delayInterval(50_000)
72 | .applyWillPublish()
73 | .send();
74 | await().until(() -> hivemq.getLogs()
75 | .contains(
76 | "Received CONNECT from client 'test-client': Protocol version: 'V_5', Clean Start: 'true', Session Expiry Interval: '0'"));
77 | await().until(() -> hivemq.getLogs()
78 | .contains("Sent CONNACK to client 'test-client': Reason Code: 'SUCCESS', Session Present: 'false'"));
79 |
80 | client.subscribeWith().topicFilter("#").send();
81 | await().until(() -> hivemq.getLogs()
82 | .contains("Received SUBSCRIBE from client 'test-client': Topics: { [Topic: '#', QoS: '2'] }"));
83 | await().until(() -> hivemq.getLogs()
84 | .contains("Sent SUBACK to client 'test-client': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_2'] }"));
85 |
86 | client.publishWith()
87 | .topic("publish")
88 | .qos(MqttQos.EXACTLY_ONCE)
89 | .payload("payload1".getBytes(StandardCharsets.UTF_8))
90 | .contentType("text/plain")
91 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
92 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
93 | .responseTopic("publishResponse")
94 | .retain(false)
95 | .messageExpiryInterval(10_000)
96 | .userProperties()
97 | .add("publishProperty", "publishValue")
98 | .applyUserProperties()
99 | .send();
100 | await().until(() -> hivemq.getLogs()
101 | .contains(
102 | "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false'"));
103 | await().until(() -> hivemq.getLogs().contains("Sent PUBREC to client 'test-client': Reason Code: 'SUCCESS'"));
104 | await().until(() -> hivemq.getLogs()
105 | .contains("Received PUBREL from client 'test-client': Reason Code: 'SUCCESS'"));
106 | await().until(() -> hivemq.getLogs().contains("Sent PUBCOMP to client 'test-client': Reason Code: 'SUCCESS'"));
107 |
108 | await().until(() -> hivemq.getLogs()
109 | .contains(
110 | "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false'"));
111 | await().until(() -> hivemq.getLogs()
112 | .contains("Received PUBREC from client 'test-client': Reason Code: 'SUCCESS'"));
113 | await().until(() -> hivemq.getLogs().contains("Sent PUBREL to client 'test-client': Reason Code: 'SUCCESS'"));
114 | await().until(() -> hivemq.getLogs()
115 | .contains("Received PUBCOMP from client 'test-client': Reason Code: 'SUCCESS'"));
116 |
117 | client.publishWith()
118 | .topic("publish")
119 | .qos(MqttQos.AT_LEAST_ONCE)
120 | .payload("payload2".getBytes(StandardCharsets.UTF_8))
121 | .contentType("text/plain")
122 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
123 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
124 | .responseTopic("publishResponse")
125 | .retain(false)
126 | .messageExpiryInterval(10_000)
127 | .userProperties()
128 | .add("publishProperty", "publishValue")
129 | .applyUserProperties()
130 | .send();
131 | await().until(() -> hivemq.getLogs()
132 | .contains(
133 | "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false'"));
134 | await().until(() -> hivemq.getLogs().contains("Sent PUBACK to client 'test-client': Reason Code: 'SUCCESS'"));
135 | await().until(() -> hivemq.getLogs()
136 | .contains(
137 | "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false'"));
138 | await().until(() -> hivemq.getLogs()
139 | .contains("Received PUBACK from client 'test-client': Reason Code: 'SUCCESS'"));
140 |
141 | client.unsubscribeWith().topicFilter("#").send();
142 | await().until(() -> hivemq.getLogs()
143 | .contains("Received UNSUBSCRIBE from client 'test-client': Topics: { [Topic: '#'] }"));
144 | await().until(() -> hivemq.getLogs()
145 | .contains("Sent UNSUBACK to client 'test-client': Unsuback Reason Codes: { [Reason Code: 'SUCCESS'] }"));
146 |
147 | client.disconnect();
148 | await().until(() -> hivemq.getLogs()
149 | .contains("Received DISCONNECT from client 'test-client': Reason Code: 'NORMAL_DISCONNECTION'"));
150 |
151 | assertTrue(hivemq.getLogs().contains("Payload: 'payload1'"));
152 | assertTrue(hivemq.getLogs().contains("Payload: 'payload2'"));
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/src/integrationTest/java/com/hivemq/extensions/log/FullConfigXmlIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log;
17 |
18 | import com.hivemq.client.mqtt.datatypes.MqttQos;
19 | import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
20 | import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
21 | import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
22 | import io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages;
23 | import org.jetbrains.annotations.NotNull;
24 | import org.junit.jupiter.api.Test;
25 | import org.testcontainers.hivemq.HiveMQContainer;
26 | import org.testcontainers.junit.jupiter.Container;
27 | import org.testcontainers.junit.jupiter.Testcontainers;
28 | import org.testcontainers.utility.MountableFile;
29 |
30 | import java.nio.charset.StandardCharsets;
31 |
32 | import static org.awaitility.Awaitility.await;
33 |
34 | /**
35 | * @since 1.2.0
36 | */
37 | @Testcontainers
38 | public class FullConfigXmlIT {
39 |
40 | @Container
41 | final @NotNull HiveMQContainer hivemq =
42 | new HiveMQContainer(OciImages.getImageName("hivemq/extensions/hivemq-mqtt-message-log-extension")
43 | .asCompatibleSubstituteFor("hivemq/hivemq4")) //
44 | .withCopyToContainer(MountableFile.forClasspathResource("fullConfig.xml"),
45 | "/opt/hivemq/extensions/hivemq-mqtt-message-log-extension/conf/config.xml")
46 | .withLogConsumer(outputFrame -> System.out.print("HiveMQ: " + outputFrame.getUtf8String()));
47 |
48 | @Test
49 | void test() {
50 | final Mqtt5BlockingClient client = Mqtt5Client.builder()
51 | .identifier("test-client")
52 | .serverHost(hivemq.getHost())
53 | .serverPort(hivemq.getMqttPort())
54 | .buildBlocking();
55 |
56 | client.connectWith()
57 | .willPublish()
58 | .topic("will")
59 | .qos(MqttQos.EXACTLY_ONCE)
60 | .payload("willPayload".getBytes(StandardCharsets.UTF_8))
61 | .contentType("text/plain")
62 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
63 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
64 | .responseTopic("willResponse")
65 | .retain(false)
66 | .messageExpiryInterval(10_000)
67 | .userProperties()
68 | .add("willProperty", "willValue")
69 | .applyUserProperties()
70 | .delayInterval(50_000)
71 | .applyWillPublish()
72 | .send();
73 | await().until(() -> hivemq.getLogs()
74 | .contains(
75 | "Received CONNECT from client 'test-client': Protocol version: 'V_5', Clean Start: 'true', Session Expiry Interval: '0', Keep Alive: '60', Maximum Packet Size: '268435460', Receive Maximum: '65535', Topic Alias Maximum: '0', Request Problem Information: 'true', Request Response Information: 'false', Username: 'null', Password: 'null', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null', Will: { Topic: 'will', Payload: 'willPayload', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'willResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'willProperty', Value: 'willValue'], Will Delay: '50000' }"));
76 | await().until(() -> hivemq.getLogs()
77 | .contains(
78 | "Sent CONNACK to client 'test-client': Reason Code: 'SUCCESS', Session Present: 'false', Session Expiry Interval: 'null', Assigned ClientId 'null', Maximum QoS: 'EXACTLY_ONCE', Maximum Packet Size: '268435460', Receive Maximum: '10', Topic Alias Maximum: '5', Reason String: 'null', Response Information: 'null', Server Keep Alive: 'null', Server Reference: 'null', Shared Subscription Available: 'true', Wildcards Available: 'true', Retain Available: 'true', Subscription Identifiers Available: 'true', Auth Method: 'null', Auth Data (Base64): 'null', User Properties: 'null'"));
79 |
80 | client.subscribeWith().topicFilter("#").send();
81 | await().until(() -> hivemq.getLogs()
82 | .contains(
83 | "Received SUBSCRIBE from client 'test-client': Topics: { [Topic: '#', QoS: '2', Retain As Published: 'false', No Local: 'false', Retain Handling: 'SEND'] }, Subscription Identifier: '1', User Properties: 'null'"));
84 | await().until(() -> hivemq.getLogs()
85 | .contains(
86 | "Sent SUBACK to client 'test-client': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_2'] }, Reason String: 'null', User Properties: 'null'"));
87 |
88 | client.publishWith()
89 | .topic("publish")
90 | .qos(MqttQos.EXACTLY_ONCE)
91 | .payload("payload1".getBytes(StandardCharsets.UTF_8))
92 | .contentType("text/plain")
93 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
94 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
95 | .responseTopic("publishResponse")
96 | .retain(false)
97 | .messageExpiryInterval(10_000)
98 | .userProperties()
99 | .add("publishProperty", "publishValue")
100 | .applyUserProperties()
101 | .send();
102 | await().until(() -> hivemq.getLogs()
103 | .contains(
104 | "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'publishProperty', Value: 'publishValue']"));
105 | await().until(() -> hivemq.getLogs()
106 | .contains(
107 | "Sent PUBREC to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
108 | await().until(() -> hivemq.getLogs()
109 | .contains(
110 | "Received PUBREL from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
111 | await().until(() -> hivemq.getLogs()
112 | .contains(
113 | "Sent PUBCOMP to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
114 |
115 | await().until(() -> hivemq.getLogs()
116 | .contains(
117 | "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1]', User Properties: [Name: 'publishProperty', Value: 'publishValue']"));
118 | await().until(() -> hivemq.getLogs()
119 | .contains(
120 | "Received PUBREC from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
121 | await().until(() -> hivemq.getLogs()
122 | .contains(
123 | "Sent PUBREL to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
124 | await().until(() -> hivemq.getLogs()
125 | .contains(
126 | "Received PUBCOMP from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
127 |
128 | client.publishWith()
129 | .topic("publish")
130 | .qos(MqttQos.AT_LEAST_ONCE)
131 | .payload("payload2".getBytes(StandardCharsets.UTF_8))
132 | .contentType("text/plain")
133 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
134 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
135 | .responseTopic("publishResponse")
136 | .retain(false)
137 | .messageExpiryInterval(10_000)
138 | .userProperties()
139 | .add("publishProperty", "publishValue")
140 | .applyUserProperties()
141 | .send();
142 | await().until(() -> hivemq.getLogs()
143 | .contains(
144 | "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[]', User Properties: [Name: 'publishProperty', Value: 'publishValue']"));
145 | await().until(() -> hivemq.getLogs()
146 | .contains(
147 | "Sent PUBACK to client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
148 | await().until(() -> hivemq.getLogs()
149 | .contains(
150 | "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false', Message Expiry Interval: '10000', Duplicate Delivery: 'false', Correlation Data: 'willCorrelationData', Response Topic: 'publishResponse', Content Type: 'text/plain', Payload Format Indicator: 'UTF_8', Subscription Identifiers: '[1]', User Properties: [Name: 'publishProperty', Value: 'publishValue']"));
151 | await().until(() -> hivemq.getLogs()
152 | .contains(
153 | "Received PUBACK from client 'test-client': Reason Code: 'SUCCESS', Reason String: 'null', User Properties: 'null'"));
154 |
155 | client.unsubscribeWith().topicFilter("#").send();
156 | await().until(() -> hivemq.getLogs()
157 | .contains(
158 | "Received UNSUBSCRIBE from client 'test-client': Topics: { [Topic: '#'] }, User Properties: 'null'"));
159 | await().until(() -> hivemq.getLogs()
160 | .contains(
161 | "Sent UNSUBACK to client 'test-client': Unsuback Reason Codes: { [Reason Code: 'SUCCESS'] }, Reason String: 'null', User Properties: 'null'"));
162 |
163 | client.disconnect();
164 | await().until(() -> hivemq.getLogs()
165 | .contains(
166 | "Received DISCONNECT from client 'test-client': Reason Code: 'NORMAL_DISCONNECTION', Reason String: 'null', Server Reference: 'null', Session Expiry: 'null', User Properties: 'null'"));
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/integrationTest/java/com/hivemq/extensions/log/FullConfigXmlNoPayloadNoVerboseIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log;
17 |
18 | import com.hivemq.client.mqtt.datatypes.MqttQos;
19 | import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
20 | import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
21 | import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
22 | import io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages;
23 | import org.jetbrains.annotations.NotNull;
24 | import org.junit.jupiter.api.Test;
25 | import org.testcontainers.hivemq.HiveMQContainer;
26 | import org.testcontainers.junit.jupiter.Container;
27 | import org.testcontainers.junit.jupiter.Testcontainers;
28 | import org.testcontainers.utility.MountableFile;
29 |
30 | import java.nio.charset.StandardCharsets;
31 |
32 | import static org.awaitility.Awaitility.await;
33 | import static org.junit.jupiter.api.Assertions.assertFalse;
34 |
35 | /**
36 | * @since 1.2.0
37 | */
38 | @Testcontainers
39 | public class FullConfigXmlNoPayloadNoVerboseIT {
40 |
41 | @Container
42 | final @NotNull HiveMQContainer hivemq =
43 | new HiveMQContainer(OciImages.getImageName("hivemq/extensions/hivemq-mqtt-message-log-extension")
44 | .asCompatibleSubstituteFor("hivemq/hivemq4")) //
45 | .withCopyToContainer(MountableFile.forClasspathResource("fullConfigNoPayloadNoVerbose.xml"),
46 | "/opt/hivemq/extensions/hivemq-mqtt-message-log-extension/conf/config.xml")
47 | .withLogConsumer(outputFrame -> System.out.print("HiveMQ: " + outputFrame.getUtf8String()));
48 |
49 | @Test
50 | void test() {
51 | final Mqtt5BlockingClient client = Mqtt5Client.builder()
52 | .identifier("test-client")
53 | .serverHost(hivemq.getHost())
54 | .serverPort(hivemq.getMqttPort())
55 | .buildBlocking();
56 |
57 | client.connectWith()
58 | .willPublish()
59 | .topic("will")
60 | .qos(MqttQos.EXACTLY_ONCE)
61 | .payload("willPayload".getBytes(StandardCharsets.UTF_8))
62 | .contentType("text/plain")
63 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
64 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
65 | .responseTopic("willResponse")
66 | .retain(false)
67 | .messageExpiryInterval(10_000)
68 | .userProperties()
69 | .add("willProperty", "willValue")
70 | .applyUserProperties()
71 | .delayInterval(50_000)
72 | .applyWillPublish()
73 | .send();
74 | await().until(() -> hivemq.getLogs()
75 | .contains(
76 | "Received CONNECT from client 'test-client': Protocol version: 'V_5', Clean Start: 'true', Session Expiry Interval: '0'"));
77 | await().until(() -> hivemq.getLogs()
78 | .contains("Sent CONNACK to client 'test-client': Reason Code: 'SUCCESS', Session Present: 'false'"));
79 |
80 | client.subscribeWith().topicFilter("#").send();
81 | await().until(() -> hivemq.getLogs()
82 | .contains("Received SUBSCRIBE from client 'test-client': Topics: { [Topic: '#', QoS: '2'] }"));
83 | await().until(() -> hivemq.getLogs()
84 | .contains("Sent SUBACK to client 'test-client': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_2'] }"));
85 |
86 | client.publishWith()
87 | .topic("publish")
88 | .qos(MqttQos.EXACTLY_ONCE)
89 | .payload("payload1".getBytes(StandardCharsets.UTF_8))
90 | .contentType("text/plain")
91 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
92 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
93 | .responseTopic("publishResponse")
94 | .retain(false)
95 | .messageExpiryInterval(10_000)
96 | .userProperties()
97 | .add("publishProperty", "publishValue")
98 | .applyUserProperties()
99 | .send();
100 | await().until(() -> hivemq.getLogs()
101 | .contains("Received PUBLISH from client 'test-client' for topic 'publish': QoS: '2', Retained: 'false'"));
102 | await().until(() -> hivemq.getLogs().contains("Sent PUBREC to client 'test-client': Reason Code: 'SUCCESS'"));
103 | await().until(() -> hivemq.getLogs()
104 | .contains("Received PUBREL from client 'test-client': Reason Code: 'SUCCESS'"));
105 | await().until(() -> hivemq.getLogs().contains("Sent PUBCOMP to client 'test-client': Reason Code: 'SUCCESS'"));
106 |
107 | await().until(() -> hivemq.getLogs()
108 | .contains("Sent PUBLISH to client 'test-client' on topic 'publish': QoS: '2', Retained: 'false'"));
109 | await().until(() -> hivemq.getLogs()
110 | .contains("Received PUBREC from client 'test-client': Reason Code: 'SUCCESS'"));
111 | await().until(() -> hivemq.getLogs().contains("Sent PUBREL to client 'test-client': Reason Code: 'SUCCESS'"));
112 | await().until(() -> hivemq.getLogs()
113 | .contains("Received PUBCOMP from client 'test-client': Reason Code: 'SUCCESS'"));
114 |
115 | client.publishWith()
116 | .topic("publish")
117 | .qos(MqttQos.AT_LEAST_ONCE)
118 | .payload("payload2".getBytes(StandardCharsets.UTF_8))
119 | .contentType("text/plain")
120 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
121 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
122 | .responseTopic("publishResponse")
123 | .retain(false)
124 | .messageExpiryInterval(10_000)
125 | .userProperties()
126 | .add("publishProperty", "publishValue")
127 | .applyUserProperties()
128 | .send();
129 | await().until(() -> hivemq.getLogs()
130 | .contains("Received PUBLISH from client 'test-client' for topic 'publish': QoS: '1', Retained: 'false'"));
131 | await().until(() -> hivemq.getLogs().contains("Sent PUBACK to client 'test-client': Reason Code: 'SUCCESS'"));
132 | await().until(() -> hivemq.getLogs()
133 | .contains("Sent PUBLISH to client 'test-client' on topic 'publish': QoS: '1', Retained: 'false'"));
134 | await().until(() -> hivemq.getLogs()
135 | .contains("Received PUBACK from client 'test-client': Reason Code: 'SUCCESS'"));
136 |
137 | client.unsubscribeWith().topicFilter("#").send();
138 | await().until(() -> hivemq.getLogs()
139 | .contains("Received UNSUBSCRIBE from client 'test-client': Topics: { [Topic: '#'] }"));
140 | await().until(() -> hivemq.getLogs()
141 | .contains("Sent UNSUBACK to client 'test-client': Unsuback Reason Codes: { [Reason Code: 'SUCCESS'] }"));
142 |
143 | client.disconnect();
144 | await().until(() -> hivemq.getLogs()
145 | .contains("Received DISCONNECT from client 'test-client': Reason Code: 'NORMAL_DISCONNECTION'"));
146 |
147 | assertFalse(hivemq.getLogs().contains("Payload: 'payload1'"));
148 | assertFalse(hivemq.getLogs().contains("Payload: 'payload2'"));
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/integrationTest/java/com/hivemq/extensions/log/FullConfigXmlNoVerboseIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log;
17 |
18 | import com.hivemq.client.mqtt.datatypes.MqttQos;
19 | import com.hivemq.client.mqtt.mqtt5.Mqtt5BlockingClient;
20 | import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
21 | import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
22 | import io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages;
23 | import org.jetbrains.annotations.NotNull;
24 | import org.junit.jupiter.api.Test;
25 | import org.testcontainers.hivemq.HiveMQContainer;
26 | import org.testcontainers.junit.jupiter.Container;
27 | import org.testcontainers.junit.jupiter.Testcontainers;
28 | import org.testcontainers.utility.MountableFile;
29 |
30 | import java.nio.charset.StandardCharsets;
31 |
32 | import static org.awaitility.Awaitility.await;
33 | import static org.junit.jupiter.api.Assertions.assertTrue;
34 |
35 | /**
36 | * @since 1.2.0
37 | */
38 | @Testcontainers
39 | public class FullConfigXmlNoVerboseIT {
40 |
41 | @Container
42 | final @NotNull HiveMQContainer hivemq =
43 | new HiveMQContainer(OciImages.getImageName("hivemq/extensions/hivemq-mqtt-message-log-extension")
44 | .asCompatibleSubstituteFor("hivemq/hivemq4")) //
45 | .withCopyToContainer(MountableFile.forClasspathResource("fullConfigNoVerbose.xml"),
46 | "/opt/hivemq/extensions/hivemq-mqtt-message-log-extension/conf/config.xml")
47 | .withLogConsumer(outputFrame -> System.out.print("HiveMQ: " + outputFrame.getUtf8String()));
48 |
49 | @Test
50 | void test() {
51 | final Mqtt5BlockingClient client = Mqtt5Client.builder()
52 | .identifier("test-client")
53 | .serverHost(hivemq.getHost())
54 | .serverPort(hivemq.getMqttPort())
55 | .buildBlocking();
56 |
57 | client.connectWith()
58 | .willPublish()
59 | .topic("will")
60 | .qos(MqttQos.EXACTLY_ONCE)
61 | .payload("willPayload".getBytes(StandardCharsets.UTF_8))
62 | .contentType("text/plain")
63 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
64 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
65 | .responseTopic("willResponse")
66 | .retain(false)
67 | .messageExpiryInterval(10_000)
68 | .userProperties()
69 | .add("willProperty", "willValue")
70 | .applyUserProperties()
71 | .delayInterval(50_000)
72 | .applyWillPublish()
73 | .send();
74 | await().until(() -> hivemq.getLogs()
75 | .contains(
76 | "Received CONNECT from client 'test-client': Protocol version: 'V_5', Clean Start: 'true', Session Expiry Interval: '0'"));
77 | await().until(() -> hivemq.getLogs()
78 | .contains("Sent CONNACK to client 'test-client': Reason Code: 'SUCCESS', Session Present: 'false'"));
79 |
80 | client.subscribeWith().topicFilter("#").send();
81 | await().until(() -> hivemq.getLogs()
82 | .contains("Received SUBSCRIBE from client 'test-client': Topics: { [Topic: '#', QoS: '2'] }"));
83 | await().until(() -> hivemq.getLogs()
84 | .contains("Sent SUBACK to client 'test-client': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_2'] }"));
85 |
86 | client.publishWith()
87 | .topic("publish")
88 | .qos(MqttQos.EXACTLY_ONCE)
89 | .payload("payload1".getBytes(StandardCharsets.UTF_8))
90 | .contentType("text/plain")
91 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
92 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
93 | .responseTopic("publishResponse")
94 | .retain(false)
95 | .messageExpiryInterval(10_000)
96 | .userProperties()
97 | .add("publishProperty", "publishValue")
98 | .applyUserProperties()
99 | .send();
100 | await().until(() -> hivemq.getLogs()
101 | .contains(
102 | "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false'"));
103 | await().until(() -> hivemq.getLogs().contains("Sent PUBREC to client 'test-client': Reason Code: 'SUCCESS'"));
104 | await().until(() -> hivemq.getLogs()
105 | .contains("Received PUBREL from client 'test-client': Reason Code: 'SUCCESS'"));
106 | await().until(() -> hivemq.getLogs().contains("Sent PUBCOMP to client 'test-client': Reason Code: 'SUCCESS'"));
107 |
108 | await().until(() -> hivemq.getLogs()
109 | .contains(
110 | "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload1', QoS: '2', Retained: 'false'"));
111 | await().until(() -> hivemq.getLogs()
112 | .contains("Received PUBREC from client 'test-client': Reason Code: 'SUCCESS'"));
113 | await().until(() -> hivemq.getLogs().contains("Sent PUBREL to client 'test-client': Reason Code: 'SUCCESS'"));
114 | await().until(() -> hivemq.getLogs()
115 | .contains("Received PUBCOMP from client 'test-client': Reason Code: 'SUCCESS'"));
116 |
117 | client.publishWith()
118 | .topic("publish")
119 | .qos(MqttQos.AT_LEAST_ONCE)
120 | .payload("payload2".getBytes(StandardCharsets.UTF_8))
121 | .contentType("text/plain")
122 | .correlationData("willCorrelationData".getBytes(StandardCharsets.UTF_8))
123 | .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
124 | .responseTopic("publishResponse")
125 | .retain(false)
126 | .messageExpiryInterval(10_000)
127 | .userProperties()
128 | .add("publishProperty", "publishValue")
129 | .applyUserProperties()
130 | .send();
131 | await().until(() -> hivemq.getLogs()
132 | .contains(
133 | "Received PUBLISH from client 'test-client' for topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false'"));
134 | await().until(() -> hivemq.getLogs().contains("Sent PUBACK to client 'test-client': Reason Code: 'SUCCESS'"));
135 | await().until(() -> hivemq.getLogs()
136 | .contains(
137 | "Sent PUBLISH to client 'test-client' on topic 'publish': Payload: 'payload2', QoS: '1', Retained: 'false'"));
138 | await().until(() -> hivemq.getLogs()
139 | .contains("Received PUBACK from client 'test-client': Reason Code: 'SUCCESS'"));
140 |
141 | client.unsubscribeWith().topicFilter("#").send();
142 | await().until(() -> hivemq.getLogs()
143 | .contains("Received UNSUBSCRIBE from client 'test-client': Topics: { [Topic: '#'] }"));
144 | await().until(() -> hivemq.getLogs()
145 | .contains("Sent UNSUBACK to client 'test-client': Unsuback Reason Codes: { [Reason Code: 'SUCCESS'] }"));
146 |
147 | client.disconnect();
148 | await().until(() -> hivemq.getLogs()
149 | .contains("Received DISCONNECT from client 'test-client': Reason Code: 'NORMAL_DISCONNECTION'"));
150 |
151 | assertTrue(hivemq.getLogs().contains("Payload: 'payload1'"));
152 | assertTrue(hivemq.getLogs().contains("Payload: 'payload2'"));
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/fullConfig.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2019-present HiveMQ GmbH
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | verbose=true
17 | payload=true
18 | publish-received=true
19 | publish-send=true
20 | client-connect=true
21 | connack-send=true
22 | client-disconnect=true
23 | subscribe-received=true
24 | suback-send=true
25 | unsubscribe-received=true
26 | unsuback-send=true
27 | ping-request-received=true
28 | ping-response-send=true
29 | puback-received=true
30 | puback-send=true
31 | pubrec-received=true
32 | pubrec-send=true
33 | pubrel-received=true
34 | pubrel-send=true
35 | pubcomp-received=true
36 | pubcomp-send=true
37 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/fullConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
21 | true
22 | true
23 | true
24 | true
25 | true
26 | true
27 | true
28 | true
29 | true
30 | true
31 | true
32 | true
33 | true
34 | true
35 | true
36 | true
37 | true
38 | true
39 | true
40 | true
41 | true
42 |
43 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/fullConfigNoPayload.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2019-present HiveMQ GmbH
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | verbose=true
17 | payload=false
18 | publish-received=true
19 | publish-send=true
20 | client-connect=true
21 | connack-send=true
22 | client-disconnect=true
23 | subscribe-received=true
24 | suback-send=true
25 | unsubscribe-received=true
26 | unsuback-send=true
27 | ping-request-received=true
28 | ping-response-send=true
29 | puback-received=true
30 | puback-send=true
31 | pubrec-received=true
32 | pubrec-send=true
33 | pubrel-received=true
34 | pubrel-send=true
35 | pubcomp-received=true
36 | pubcomp-send=true
37 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/fullConfigNoPayload.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
21 | true
22 | false
23 | true
24 | true
25 | true
26 | true
27 | true
28 | true
29 | true
30 | true
31 | true
32 | true
33 | true
34 | true
35 | true
36 | true
37 | true
38 | true
39 | true
40 | true
41 | true
42 |
43 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2019-present HiveMQ GmbH
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | verbose=false
17 | payload=false
18 | publish-received=true
19 | publish-send=true
20 | client-connect=true
21 | connack-send=true
22 | client-disconnect=true
23 | subscribe-received=true
24 | suback-send=true
25 | unsubscribe-received=true
26 | unsuback-send=true
27 | ping-request-received=true
28 | ping-response-send=true
29 | puback-received=true
30 | puback-send=true
31 | pubrec-received=true
32 | pubrec-send=true
33 | pubrel-received=true
34 | pubrel-send=true
35 | pubcomp-received=true
36 | pubcomp-send=true
37 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/fullConfigNoPayloadNoVerbose.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
21 | false
22 | false
23 | true
24 | true
25 | true
26 | true
27 | true
28 | true
29 | true
30 | true
31 | true
32 | true
33 | true
34 | true
35 | true
36 | true
37 | true
38 | true
39 | true
40 | true
41 | true
42 |
43 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/fullConfigNoVerbose.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2019-present HiveMQ GmbH
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | verbose=false
17 | payload=true
18 | publish-received=true
19 | publish-send=true
20 | client-connect=true
21 | connack-send=true
22 | client-disconnect=true
23 | subscribe-received=true
24 | suback-send=true
25 | unsubscribe-received=true
26 | unsuback-send=true
27 | ping-request-received=true
28 | ping-response-send=true
29 | puback-received=true
30 | puback-send=true
31 | pubrec-received=true
32 | pubrec-send=true
33 | pubrel-received=true
34 | pubrel-send=true
35 | pubcomp-received=true
36 | pubcomp-send=true
37 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/fullConfigNoVerbose.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
21 | false
22 | true
23 | true
24 | true
25 | true
26 | true
27 | true
28 | true
29 | true
30 | true
31 | true
32 | true
33 | true
34 | true
35 | true
36 | true
37 | true
38 | true
39 | true
40 | true
41 | true
42 |
43 |
--------------------------------------------------------------------------------
/src/integrationTest/resources/logback-test.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 | %-30(%d %level)- %msg%n%ex
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/ExtensionConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message;
17 |
18 | import org.jetbrains.annotations.NotNull;
19 |
20 | public class ExtensionConstants {
21 |
22 | public static final @NotNull String EXTENSION_NAME = "HiveMQ MQTT Message Log Extension";
23 |
24 | public static final @NotNull String EXTENSION_CONFIG_PROPERTIES_LOCATION = "mqttMessageLog.properties";
25 | public static final @NotNull String EXTENSION_CONFIG_XML_LOCATION = "conf/config.xml";
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/MqttMessageLogExtensionMain.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message;
17 |
18 | import com.hivemq.extension.sdk.api.ExtensionMain;
19 | import com.hivemq.extension.sdk.api.parameter.ExtensionStartInput;
20 | import com.hivemq.extension.sdk.api.parameter.ExtensionStartOutput;
21 | import com.hivemq.extension.sdk.api.parameter.ExtensionStopInput;
22 | import com.hivemq.extension.sdk.api.parameter.ExtensionStopOutput;
23 | import com.hivemq.extension.sdk.api.services.Services;
24 | import com.hivemq.extension.sdk.api.services.admin.LicenseEdition;
25 | import com.hivemq.extension.sdk.api.services.intializer.ClientInitializer;
26 | import com.hivemq.extensions.log.mqtt.message.config.ExtensionConfig;
27 | import com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigReader;
28 | import com.hivemq.extensions.log.mqtt.message.initializer.ClientInitializerImpl;
29 | import com.hivemq.extensions.log.mqtt.message.initializer.ClientInitializerImpl4_2;
30 | import org.jetbrains.annotations.NotNull;
31 | import org.jetbrains.annotations.VisibleForTesting;
32 | import org.slf4j.Logger;
33 | import org.slf4j.LoggerFactory;
34 |
35 | /**
36 | * @since 1.0.0
37 | */
38 | public class MqttMessageLogExtensionMain implements ExtensionMain {
39 |
40 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(MqttMessageLogExtensionMain.class);
41 |
42 | @Override
43 | public void extensionStart(
44 | final @NotNull ExtensionStartInput extensionStartInput,
45 | final @NotNull ExtensionStartOutput extensionStartOutput) {
46 | try {
47 | extensionStartInput.getServerInformation();
48 | } catch (final NoSuchMethodError e) {
49 | // only a version that is not supported will throw this exception
50 | extensionStartOutput.preventExtensionStartup("The HiveMQ version is not supported");
51 | return;
52 | }
53 |
54 | try {
55 | final ExtensionConfig config =
56 | ExtensionConfigReader.read(extensionStartInput.getExtensionInformation().getExtensionHomeFolder());
57 |
58 | if (config.allDisabled()) {
59 | extensionStartOutput.preventExtensionStartup(extensionStartInput.getExtensionInformation().getName() +
60 | " start prevented because all properties set to false");
61 | return;
62 | }
63 |
64 | final ClientInitializer initializer =
65 | getClientInitializerForEdition(Services.adminService().getLicenseInformation().getEdition(),
66 | extensionStartInput.getServerInformation().getVersion(),
67 | config);
68 |
69 | Services.initializerRegistry().setClientInitializer(initializer);
70 |
71 | } catch (final Exception e) {
72 | extensionStartOutput.preventExtensionStartup(extensionStartInput.getExtensionInformation().getName() +
73 | " cannot be started");
74 | LOG.error("{} could not be started. An exception was thrown!",
75 | extensionStartInput.getExtensionInformation().getName(),
76 | e);
77 | }
78 | }
79 |
80 | @Override
81 | public void extensionStop(
82 | final @NotNull ExtensionStopInput extensionStopInput,
83 | final @NotNull ExtensionStopOutput extensionStopOutput) {
84 | }
85 |
86 | @VisibleForTesting
87 | @NotNull
88 | ClientInitializer getClientInitializerForEdition(
89 | final @NotNull LicenseEdition edition,
90 | final @NotNull String version,
91 | final @NotNull ExtensionConfig config) {
92 | if (LicenseEdition.COMMUNITY.equals(edition)) {
93 | return new ClientInitializerImpl(config);
94 | } else if (version.startsWith("4.2.")) {
95 | return new ClientInitializerImpl4_2(config);
96 | } else {
97 | return new ClientInitializerImpl(config);
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.config;
17 |
18 | /**
19 | * @since 1.2.0
20 | */
21 | public interface ExtensionConfig {
22 |
23 | boolean isClientConnect();
24 |
25 | boolean isClientDisconnect();
26 |
27 | boolean isConnackSend();
28 |
29 | boolean isPublishReceived();
30 |
31 | boolean isPublishSend();
32 |
33 | boolean isSubscribeReceived();
34 |
35 | boolean isSubackSend();
36 |
37 | boolean isUnsubscribeReceived();
38 |
39 | boolean isUnsubackSend();
40 |
41 | boolean isPingRequestReceived();
42 |
43 | boolean isPingResponseSend();
44 |
45 | boolean isPubackReceived();
46 |
47 | boolean isPubackSend();
48 |
49 | boolean isPubrelReceived();
50 |
51 | boolean isPubrelSend();
52 |
53 | boolean isPubrecReceived();
54 |
55 | boolean isPubrecSend();
56 |
57 | boolean isPubcompReceived();
58 |
59 | boolean isPubcompSend();
60 |
61 | boolean isVerbose();
62 |
63 | boolean isPayload();
64 |
65 | default boolean allDisabled() {
66 | return !isClientConnect() &&
67 | !isClientDisconnect() &&
68 | !isConnackSend() &&
69 | !isPublishSend() &&
70 | !isPublishReceived() &&
71 | !isSubscribeReceived() &&
72 | !isSubackSend() &&
73 | !isUnsubscribeReceived() &&
74 | !isUnsubackSend() &&
75 | !isPingRequestReceived() &&
76 | !isPingResponseSend() &&
77 | !isPubackReceived() &&
78 | !isPubackSend() &&
79 | !isPubrecReceived() &&
80 | !isPubrecSend() &&
81 | !isPubrelReceived() &&
82 | !isPubrelSend() &&
83 | !isPubcompReceived() &&
84 | !isPubcompSend();
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigProperties.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.config;
17 |
18 | import org.jetbrains.annotations.NotNull;
19 | import org.jetbrains.annotations.VisibleForTesting;
20 |
21 | import java.util.Properties;
22 |
23 | public class ExtensionConfigProperties implements ExtensionConfig {
24 |
25 | static final @NotNull String TRUE = "true";
26 | static final @NotNull String FALSE = "false";
27 | static final @NotNull String VERBOSE = "verbose";
28 | static final @NotNull String PAYLOAD = "payload";
29 | static final @NotNull String CLIENT_CONNECT = "client-connect";
30 | static final @NotNull String CLIENT_DISCONNECT = "client-disconnect";
31 | static final @NotNull String CONNACK_SEND = "connack-send";
32 | static final @NotNull String PUBLISH_RECEIVED = "publish-received";
33 | static final @NotNull String PUBLISH_SEND = "publish-send";
34 | static final @NotNull String SUBSCRIBE_RECEIVED = "subscribe-received";
35 | static final @NotNull String SUBACK_SEND = "suback-send";
36 | static final @NotNull String UNSUBSCRIBE_RECEIVED = "unsubscribe-received";
37 | static final @NotNull String UNSUBACK_SEND = "unsuback-send";
38 | static final @NotNull String PING_REQUEST_RECEIVED = "ping-request-received";
39 | static final @NotNull String PING_RESPONSE_SEND = "ping-response-send";
40 | static final @NotNull String PUBACK_RECEIVED = "puback-received";
41 | static final @NotNull String PUBACK_SEND = "puback-send";
42 | static final @NotNull String PUBREC_RECEIVED = "pubrec-received";
43 | static final @NotNull String PUBREC_SEND = "pubrec-send";
44 | static final @NotNull String PUBREL_RECEIVED = "pubrel-received";
45 | static final @NotNull String PUBREL_SEND = "pubrel-send";
46 | static final @NotNull String PUBCOMP_RECEIVED = "pubcomp-received";
47 | static final @NotNull String PUBCOMP_SEND = "pubcomp-send";
48 |
49 | private final @NotNull Properties properties;
50 |
51 | public ExtensionConfigProperties(final @NotNull Properties properties) {
52 | this.properties = properties;
53 | }
54 |
55 | public boolean isClientConnect() {
56 | return getForKey(CLIENT_CONNECT);
57 | }
58 |
59 | public boolean isClientDisconnect() {
60 | return getForKey(CLIENT_DISCONNECT);
61 | }
62 |
63 | public boolean isConnackSend() {
64 | return getForKey(CONNACK_SEND);
65 | }
66 |
67 | public boolean isPublishReceived() {
68 | return getForKey(PUBLISH_RECEIVED);
69 | }
70 |
71 | public boolean isPublishSend() {
72 | return getForKey(PUBLISH_SEND);
73 | }
74 |
75 | public boolean isSubscribeReceived() {
76 | return getForKey(SUBSCRIBE_RECEIVED);
77 | }
78 |
79 | public boolean isSubackSend() {
80 | return getForKey(SUBACK_SEND);
81 | }
82 |
83 | public boolean isUnsubscribeReceived() {
84 | return getForKey(UNSUBSCRIBE_RECEIVED);
85 | }
86 |
87 | public boolean isUnsubackSend() {
88 | return getForKey(UNSUBACK_SEND);
89 | }
90 |
91 | public boolean isPingRequestReceived() {
92 | return getForKey(PING_REQUEST_RECEIVED);
93 | }
94 |
95 | public boolean isPingResponseSend() {
96 | return getForKey(PING_RESPONSE_SEND);
97 | }
98 |
99 | public boolean isPubackReceived() {
100 | return getForKey(PUBACK_RECEIVED);
101 | }
102 |
103 | public boolean isPubackSend() {
104 | return getForKey(PUBACK_SEND);
105 | }
106 |
107 | public boolean isPubrelReceived() {
108 | return getForKey(PUBREL_RECEIVED);
109 | }
110 |
111 | public boolean isPubrelSend() {
112 | return getForKey(PUBREL_SEND);
113 | }
114 |
115 | public boolean isPubrecReceived() {
116 | return getForKey(PUBREC_RECEIVED);
117 | }
118 |
119 | public boolean isPubrecSend() {
120 | return getForKey(PUBREC_SEND);
121 | }
122 |
123 | public boolean isPubcompReceived() {
124 | return getForKey(PUBCOMP_RECEIVED);
125 | }
126 |
127 | public boolean isPubcompSend() {
128 | return getForKey(PUBCOMP_SEND);
129 | }
130 |
131 | public boolean isVerbose() {
132 | return getForKey(VERBOSE);
133 | }
134 |
135 | public boolean isPayload() {
136 | return getForKey(PAYLOAD);
137 | }
138 |
139 | private boolean getForKey(final @NotNull String key) {
140 | return properties.getProperty(key, TRUE).equalsIgnoreCase(TRUE);
141 | }
142 |
143 | @VisibleForTesting
144 | @NotNull Properties getProperties() {
145 | return properties;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.config;
17 |
18 | import org.jetbrains.annotations.NotNull;
19 | import org.slf4j.Logger;
20 | import org.slf4j.LoggerFactory;
21 |
22 | import java.io.File;
23 | import java.io.FileInputStream;
24 | import java.io.IOException;
25 | import java.io.InputStream;
26 | import java.nio.file.Path;
27 | import java.util.Properties;
28 |
29 | import static com.hivemq.extensions.log.mqtt.message.ExtensionConstants.EXTENSION_CONFIG_PROPERTIES_LOCATION;
30 | import static com.hivemq.extensions.log.mqtt.message.ExtensionConstants.EXTENSION_CONFIG_XML_LOCATION;
31 | import static com.hivemq.extensions.log.mqtt.message.ExtensionConstants.EXTENSION_NAME;
32 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.CLIENT_CONNECT;
33 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.CLIENT_DISCONNECT;
34 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.CONNACK_SEND;
35 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.FALSE;
36 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PAYLOAD;
37 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PING_REQUEST_RECEIVED;
38 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PING_RESPONSE_SEND;
39 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBACK_RECEIVED;
40 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBACK_SEND;
41 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBCOMP_RECEIVED;
42 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBCOMP_SEND;
43 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBLISH_RECEIVED;
44 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBLISH_SEND;
45 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBREC_RECEIVED;
46 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBREC_SEND;
47 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBREL_RECEIVED;
48 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.PUBREL_SEND;
49 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.SUBACK_SEND;
50 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.SUBSCRIBE_RECEIVED;
51 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.TRUE;
52 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.UNSUBACK_SEND;
53 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.UNSUBSCRIBE_RECEIVED;
54 | import static com.hivemq.extensions.log.mqtt.message.config.ExtensionConfigProperties.VERBOSE;
55 |
56 | /**
57 | * @since 1.2.0
58 | */
59 | public class ExtensionConfigReader {
60 |
61 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(ExtensionConfigReader.class);
62 |
63 | /**
64 | * Reads config.xml from /conf directory if present, otherwise reads mqttMessageLog.properties from extension home
65 | * directory. Uses the defaults if neither is present/readable.
66 | *
67 | * @param extensionHomeFolder home folder of the extension
68 | * @return user defined extension configuration or default configuration
69 | */
70 | public static @NotNull ExtensionConfig read(final @NotNull File extensionHomeFolder) {
71 | final File configXmlFile = extensionHomeFolder.toPath().resolve(EXTENSION_CONFIG_XML_LOCATION).toFile();
72 |
73 | if (!configXmlFile.exists()) {
74 | return readPropertiesFile(extensionHomeFolder);
75 | }
76 |
77 | return readConfigXmlFile(configXmlFile);
78 | }
79 |
80 | private static ExtensionConfig readPropertiesFile(final @NotNull File extensionHomeFolder) {
81 | final Properties properties = setDefaults();
82 | final File propertiesFile = new File(extensionHomeFolder, EXTENSION_CONFIG_PROPERTIES_LOCATION);
83 |
84 | LOG.debug("{}: Will try to read config properties from {}",
85 | EXTENSION_NAME,
86 | EXTENSION_CONFIG_PROPERTIES_LOCATION);
87 |
88 | if (propertiesFile.exists()) {
89 | final Path extensionHomePath = extensionHomeFolder.toPath();
90 | final Path extensionLegacyConfigPropertiesPath =
91 | extensionHomePath.resolve(EXTENSION_CONFIG_PROPERTIES_LOCATION);
92 | final Path extensionConfigXmlPath = extensionHomePath.resolve(EXTENSION_CONFIG_XML_LOCATION);
93 | LOG.warn("{}: The configuration file is using the legacy location and format '{}'. " +
94 | "Please update the configuration file to the new location and format '{}'. " +
95 | "Support for the legacy location and format will be removed in a future release.",
96 | EXTENSION_NAME,
97 | extensionLegacyConfigPropertiesPath,
98 | extensionConfigXmlPath);
99 | }
100 |
101 | if (!propertiesFile.canRead()) {
102 | LOG.info("{}: Cannot read properties file {}", EXTENSION_NAME, propertiesFile.getAbsolutePath());
103 | } else {
104 | try (final InputStream is = new FileInputStream(propertiesFile)) {
105 | properties.load(is);
106 | } catch (final Exception e) {
107 | LOG.warn("{}: Could not load properties file, reason {}", EXTENSION_NAME, e.getMessage());
108 | }
109 | }
110 |
111 | LOG.info("{}: Properties initialized to: {}", EXTENSION_NAME, properties);
112 | return new ExtensionConfigProperties(properties);
113 | }
114 |
115 | private static @NotNull ExtensionConfigXml readConfigXmlFile(final @NotNull File configXmlFile) {
116 | ExtensionConfigXml extensionConfigXml;
117 |
118 | LOG.debug("{}: Will try to read config properties from {}", EXTENSION_NAME, EXTENSION_CONFIG_XML_LOCATION);
119 |
120 | if (!configXmlFile.canRead()) {
121 | LOG.warn("{}: Unable to read configuration file {}, using defaults",
122 | EXTENSION_NAME,
123 | configXmlFile.getAbsolutePath());
124 | extensionConfigXml = new ExtensionConfigXml();
125 | } else {
126 | try {
127 | extensionConfigXml = XmlParser.unmarshalExtensionConfig(configXmlFile);
128 | } catch (final IOException e) {
129 | extensionConfigXml = new ExtensionConfigXml();
130 | LOG.warn("{}: Could not read configuration file, reason: {}, using defaults",
131 | EXTENSION_NAME,
132 | e.getMessage());
133 | }
134 | }
135 |
136 | LOG.info("{}: Properties initialized to: {}", EXTENSION_NAME, extensionConfigXml);
137 | return extensionConfigXml;
138 | }
139 |
140 | private static @NotNull Properties setDefaults() {
141 | // these defaults must be kept in sync with those in ExtensionConfigXml
142 | final Properties properties = new Properties();
143 | properties.setProperty(CLIENT_CONNECT, TRUE);
144 | properties.setProperty(CONNACK_SEND, TRUE);
145 |
146 | properties.setProperty(CLIENT_DISCONNECT, TRUE);
147 |
148 | properties.setProperty(PUBLISH_RECEIVED, TRUE);
149 | properties.setProperty(PUBLISH_SEND, TRUE);
150 |
151 | properties.setProperty(SUBSCRIBE_RECEIVED, TRUE);
152 | properties.setProperty(SUBACK_SEND, TRUE);
153 |
154 | properties.setProperty(UNSUBSCRIBE_RECEIVED, TRUE);
155 | properties.setProperty(UNSUBACK_SEND, TRUE);
156 |
157 | properties.setProperty(PING_REQUEST_RECEIVED, TRUE);
158 | properties.setProperty(PING_RESPONSE_SEND, TRUE);
159 |
160 | properties.setProperty(PUBACK_RECEIVED, TRUE);
161 | properties.setProperty(PUBACK_SEND, TRUE);
162 |
163 | properties.setProperty(PUBREC_RECEIVED, TRUE);
164 | properties.setProperty(PUBREC_SEND, TRUE);
165 |
166 | properties.setProperty(PUBREL_RECEIVED, TRUE);
167 | properties.setProperty(PUBREL_SEND, TRUE);
168 |
169 | properties.setProperty(PUBCOMP_RECEIVED, TRUE);
170 | properties.setProperty(PUBCOMP_SEND, TRUE);
171 |
172 | properties.setProperty(VERBOSE, FALSE);
173 |
174 | properties.setProperty(PAYLOAD, TRUE);
175 | return properties;
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigXml.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.config;
17 |
18 |
19 | import jakarta.xml.bind.annotation.XmlAccessType;
20 | import jakarta.xml.bind.annotation.XmlAccessorType;
21 | import jakarta.xml.bind.annotation.XmlElement;
22 | import jakarta.xml.bind.annotation.XmlRootElement;
23 | import jakarta.xml.bind.annotation.XmlType;
24 |
25 | /**
26 | * @since 1.2.0
27 | */
28 | @SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal", "unused"})
29 | @XmlRootElement(name = "hivemq-mqtt-message-log-extension")
30 | @XmlType(propOrder = {})
31 | @XmlAccessorType(XmlAccessType.NONE)
32 | public class ExtensionConfigXml implements ExtensionConfig {
33 |
34 | // these defaults must be kept in sync with those in ExtensionConfigReader
35 | @XmlElement(name = "verbose", defaultValue = "false")
36 | private boolean verbose = false;
37 |
38 | @XmlElement(name = "payload", defaultValue = "true")
39 | private boolean payload = true;
40 |
41 | @XmlElement(name = "publish-received", defaultValue = "true")
42 | private boolean publishReceived = true;
43 |
44 | @XmlElement(name = "publish-send", defaultValue = "true")
45 | private boolean publishSend = true;
46 |
47 | @XmlElement(name = "client-connect", defaultValue = "true")
48 | private boolean clientConnect = true;
49 |
50 | @XmlElement(name = "connack-send", defaultValue = "true")
51 | private boolean connackSend = true;
52 |
53 | @XmlElement(name = "client-disconnect", defaultValue = "true")
54 | private boolean clientDisconnect = true;
55 |
56 | @XmlElement(name = "subscribe-received", defaultValue = "true")
57 | private boolean subscribeReceived = true;
58 |
59 | @XmlElement(name = "suback-send", defaultValue = "true")
60 | private boolean subackSend = true;
61 |
62 | @XmlElement(name = "unsubscribe-received", defaultValue = "true")
63 | private boolean unsubscribeReceived = true;
64 |
65 | @XmlElement(name = "unsuback-send", defaultValue = "true")
66 | private boolean unsubackSend = true;
67 |
68 | @XmlElement(name = "ping-request-received", defaultValue = "true")
69 | private boolean pingRequestReceived = true;
70 |
71 | @XmlElement(name = "ping-response-send", defaultValue = "true")
72 | private boolean pingResponseSend = true;
73 |
74 | @XmlElement(name = "puback-received", defaultValue = "true")
75 | private boolean pubackReceived = true;
76 |
77 | @XmlElement(name = "puback-send", defaultValue = "true")
78 | private boolean pubackSend = true;
79 |
80 | @XmlElement(name = "pubrec-received", defaultValue = "true")
81 | private boolean pubrecReceived = true;
82 |
83 | @XmlElement(name = "pubrec-send", defaultValue = "true")
84 | private boolean pubrecSend = true;
85 |
86 | @XmlElement(name = "pubrel-received", defaultValue = "true")
87 | private boolean pubrelReceived = true;
88 |
89 | @XmlElement(name = "pubrel-send", defaultValue = "true")
90 | private boolean pubrelSend = true;
91 |
92 | @XmlElement(name = "pubcomp-received", defaultValue = "true")
93 | private boolean pubcompReceived = true;
94 |
95 | @XmlElement(name = "pubcomp-send", defaultValue = "true")
96 | private boolean pubcompSend = true;
97 |
98 | public boolean isVerbose() {
99 | return verbose;
100 | }
101 |
102 | public boolean isPayload() {
103 | return payload;
104 | }
105 |
106 | public boolean isPublishReceived() {
107 | return publishReceived;
108 | }
109 |
110 | public boolean isPublishSend() {
111 | return publishSend;
112 | }
113 |
114 | public boolean isClientConnect() {
115 | return clientConnect;
116 | }
117 |
118 | public boolean isConnackSend() {
119 | return connackSend;
120 | }
121 |
122 | public boolean isClientDisconnect() {
123 | return clientDisconnect;
124 | }
125 |
126 | public boolean isSubscribeReceived() {
127 | return subscribeReceived;
128 | }
129 |
130 | public boolean isSubackSend() {
131 | return subackSend;
132 | }
133 |
134 | public boolean isUnsubscribeReceived() {
135 | return unsubscribeReceived;
136 | }
137 |
138 | public boolean isUnsubackSend() {
139 | return unsubackSend;
140 | }
141 |
142 | public boolean isPingRequestReceived() {
143 | return pingRequestReceived;
144 | }
145 |
146 | public boolean isPingResponseSend() {
147 | return pingResponseSend;
148 | }
149 |
150 | public boolean isPubackReceived() {
151 | return pubackReceived;
152 | }
153 |
154 | public boolean isPubackSend() {
155 | return pubackSend;
156 | }
157 |
158 | public boolean isPubrecReceived() {
159 | return pubrecReceived;
160 | }
161 |
162 | public boolean isPubrecSend() {
163 | return pubrecSend;
164 | }
165 |
166 | public boolean isPubrelReceived() {
167 | return pubrelReceived;
168 | }
169 |
170 | public boolean isPubrelSend() {
171 | return pubrelSend;
172 | }
173 |
174 | public boolean isPubcompReceived() {
175 | return pubcompReceived;
176 | }
177 |
178 | public boolean isPubcompSend() {
179 | return pubcompSend;
180 | }
181 |
182 | @Override
183 | public String toString() {
184 | return "{" +
185 | "verbose=" +
186 | verbose +
187 | ", payload=" +
188 | payload +
189 | ", publishReceived=" +
190 | publishReceived +
191 | ", publishSend=" +
192 | publishSend +
193 | ", clientConnect=" +
194 | clientConnect +
195 | ", connackSend=" +
196 | connackSend +
197 | ", clientDisconnect=" +
198 | clientDisconnect +
199 | ", subscribeReceived=" +
200 | subscribeReceived +
201 | ", subackSend=" +
202 | subackSend +
203 | ", unsubscribeReceived=" +
204 | unsubscribeReceived +
205 | ", unsubackSend=" +
206 | unsubackSend +
207 | ", pingRequestReceived=" +
208 | pingRequestReceived +
209 | ", pingResponseSend=" +
210 | pingResponseSend +
211 | ", pubackReceived=" +
212 | pubackReceived +
213 | ", pubackSend=" +
214 | pubackSend +
215 | ", pubrecReceived=" +
216 | pubrecReceived +
217 | ", pubrecSend=" +
218 | pubrecSend +
219 | ", pubrelReceived=" +
220 | pubrelReceived +
221 | ", pubrelSend=" +
222 | pubrelSend +
223 | ", pubcompReceived=" +
224 | pubcompReceived +
225 | ", pubcompSend=" +
226 | pubcompSend +
227 | '}';
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/config/XmlParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.config;
17 |
18 | import com.hivemq.extensions.log.mqtt.message.ExtensionConstants;
19 | import jakarta.xml.bind.JAXBContext;
20 | import jakarta.xml.bind.JAXBException;
21 | import jakarta.xml.bind.Unmarshaller;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | import java.io.File;
27 | import java.io.IOException;
28 |
29 | /**
30 | * @since 1.2.0
31 | */
32 | class XmlParser {
33 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(XmlParser.class);
34 |
35 | static @NotNull ExtensionConfigXml unmarshalExtensionConfig(final @NotNull File file) throws IOException {
36 | final @NotNull JAXBContext jaxb;
37 |
38 | try {
39 | jaxb = JAXBContext.newInstance(ExtensionConfigXml.class);
40 | } catch (final JAXBException e) {
41 | LOG.error("{}: Could not initialize XML parser", ExtensionConstants.EXTENSION_NAME, e);
42 | throw new RuntimeException(e);
43 | }
44 |
45 | try {
46 | final Unmarshaller unmarshaller = jaxb.createUnmarshaller();
47 | return (ExtensionConfigXml) unmarshaller.unmarshal(file);
48 | } catch (final JAXBException e) {
49 | throw new IOException(e);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.initializer;
17 |
18 | import com.hivemq.extension.sdk.api.client.ClientContext;
19 | import com.hivemq.extension.sdk.api.client.parameter.InitializerInput;
20 | import com.hivemq.extension.sdk.api.services.Services;
21 | import com.hivemq.extension.sdk.api.services.intializer.ClientInitializer;
22 | import com.hivemq.extensions.log.mqtt.message.config.ExtensionConfig;
23 | import com.hivemq.extensions.log.mqtt.message.interceptor.ConnackOutboundInterceptorImpl;
24 | import com.hivemq.extensions.log.mqtt.message.interceptor.ConnectInboundInterceptorImpl;
25 | import com.hivemq.extensions.log.mqtt.message.interceptor.DisconnectInboundInterceptorImpl;
26 | import com.hivemq.extensions.log.mqtt.message.interceptor.DisconnectOutboundInterceptorImpl;
27 | import com.hivemq.extensions.log.mqtt.message.interceptor.PingreqInboundInterceptorImpl;
28 | import com.hivemq.extensions.log.mqtt.message.interceptor.PingrespOutboundInterceptorImpl;
29 | import com.hivemq.extensions.log.mqtt.message.interceptor.PubackInboundInterceptorImpl;
30 | import com.hivemq.extensions.log.mqtt.message.interceptor.PubackOutboundInterceptorImpl;
31 | import com.hivemq.extensions.log.mqtt.message.interceptor.PubcompInboundInterceptorImpl;
32 | import com.hivemq.extensions.log.mqtt.message.interceptor.PubcompOutboundInterceptorImpl;
33 | import com.hivemq.extensions.log.mqtt.message.interceptor.PublishInboundInterceptorImpl;
34 | import com.hivemq.extensions.log.mqtt.message.interceptor.PublishOutboundInterceptorImpl;
35 | import com.hivemq.extensions.log.mqtt.message.interceptor.PubrecInboundInterceptorImpl;
36 | import com.hivemq.extensions.log.mqtt.message.interceptor.PubrecOutboundInterceptorImpl;
37 | import com.hivemq.extensions.log.mqtt.message.interceptor.PubrelInboundInterceptorImpl;
38 | import com.hivemq.extensions.log.mqtt.message.interceptor.PubrelOutboundInterceptorImpl;
39 | import com.hivemq.extensions.log.mqtt.message.interceptor.SubackOutboundInterceptorImpl;
40 | import com.hivemq.extensions.log.mqtt.message.interceptor.SubscribeInboundInterceptorImpl;
41 | import com.hivemq.extensions.log.mqtt.message.interceptor.UnsubackOutboundInterceptorImpl;
42 | import com.hivemq.extensions.log.mqtt.message.interceptor.UnsubscribeInboundInterceptorImpl;
43 | import org.jetbrains.annotations.NotNull;
44 |
45 | /**
46 | * Creates a {@link ClientInitializer} that is usable since HiveMQ 4.3 Enterprise Version or Community Version 2020.1.
47 | *
48 | * @version 1.1.0
49 | */
50 | public class ClientInitializerImpl implements ClientInitializer {
51 |
52 | private final @NotNull ExtensionConfig config;
53 |
54 | public ClientInitializerImpl(final @NotNull ExtensionConfig config) {
55 | this.config = config;
56 | init();
57 | }
58 |
59 | /**
60 | * Initialize any logging logic that can be done without a {@link ClientInitializer}.
61 | */
62 | private void init() {
63 | if (config.isClientConnect()) {
64 | Services.interceptorRegistry().setConnectInboundInterceptorProvider( //
65 | ignored -> new ConnectInboundInterceptorImpl(config.isVerbose(), config.isPayload()));
66 | }
67 |
68 | if (config.isConnackSend()) {
69 | Services.interceptorRegistry().setConnackOutboundInterceptorProvider( //
70 | ignored -> new ConnackOutboundInterceptorImpl(config.isVerbose()));
71 | }
72 | }
73 |
74 | @Override
75 | public void initialize(
76 | final @NotNull InitializerInput initializerInput, final @NotNull ClientContext clientContext) {
77 | if (config.isClientDisconnect()) {
78 | clientContext.addDisconnectInboundInterceptor(new DisconnectInboundInterceptorImpl(config.isVerbose()));
79 | clientContext.addDisconnectOutboundInterceptor(new DisconnectOutboundInterceptorImpl(config.isVerbose()));
80 | }
81 |
82 | if (config.isSubscribeReceived()) {
83 | clientContext.addSubscribeInboundInterceptor(new SubscribeInboundInterceptorImpl(config.isVerbose()));
84 | }
85 | if (config.isSubackSend()) {
86 | clientContext.addSubackOutboundInterceptor(new SubackOutboundInterceptorImpl(config.isVerbose()));
87 | }
88 |
89 | if (config.isPingRequestReceived()) {
90 | clientContext.addPingReqInboundInterceptor(new PingreqInboundInterceptorImpl());
91 | }
92 | if (config.isPingResponseSend()) {
93 | clientContext.addPingRespOutboundInterceptor(new PingrespOutboundInterceptorImpl());
94 | }
95 |
96 | if (config.isUnsubscribeReceived()) {
97 | clientContext.addUnsubscribeInboundInterceptor(new UnsubscribeInboundInterceptorImpl(config.isVerbose()));
98 | }
99 | if (config.isUnsubackSend()) {
100 | clientContext.addUnsubackOutboundInterceptor(new UnsubackOutboundInterceptorImpl(config.isVerbose()));
101 | }
102 |
103 | if (config.isPublishReceived()) {
104 | clientContext.addPublishInboundInterceptor(new PublishInboundInterceptorImpl(config.isVerbose(),
105 | config.isPayload()));
106 | }
107 | if (config.isPublishSend()) {
108 | clientContext.addPublishOutboundInterceptor(new PublishOutboundInterceptorImpl(config.isVerbose(),
109 | config.isPayload()));
110 | }
111 |
112 | if (config.isPubackReceived()) {
113 | clientContext.addPubackInboundInterceptor(new PubackInboundInterceptorImpl(config.isVerbose()));
114 | }
115 | if (config.isPubackSend()) {
116 | clientContext.addPubackOutboundInterceptor(new PubackOutboundInterceptorImpl(config.isVerbose()));
117 | }
118 |
119 | if (config.isPubrecReceived()) {
120 | clientContext.addPubrecInboundInterceptor(new PubrecInboundInterceptorImpl(config.isVerbose()));
121 | }
122 | if (config.isPubrecSend()) {
123 | clientContext.addPubrecOutboundInterceptor(new PubrecOutboundInterceptorImpl(config.isVerbose()));
124 | }
125 |
126 | if (config.isPubrelReceived()) {
127 | clientContext.addPubrelInboundInterceptor(new PubrelInboundInterceptorImpl(config.isVerbose()));
128 | }
129 | if (config.isPubrelSend()) {
130 | clientContext.addPubrelOutboundInterceptor(new PubrelOutboundInterceptorImpl(config.isVerbose()));
131 | }
132 |
133 | if (config.isPubcompReceived()) {
134 | clientContext.addPubcompInboundInterceptor(new PubcompInboundInterceptorImpl(config.isVerbose()));
135 | }
136 | if (config.isPubcompSend()) {
137 | clientContext.addPubcompOutboundInterceptor(new PubcompOutboundInterceptorImpl(config.isVerbose()));
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/initializer/ClientInitializerImpl4_2.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.initializer;
17 |
18 | import com.hivemq.extension.sdk.api.client.ClientContext;
19 | import com.hivemq.extension.sdk.api.client.parameter.InitializerInput;
20 | import com.hivemq.extension.sdk.api.services.Services;
21 | import com.hivemq.extension.sdk.api.services.intializer.ClientInitializer;
22 | import com.hivemq.extensions.log.mqtt.message.config.ExtensionConfig;
23 | import com.hivemq.extensions.log.mqtt.message.interceptor.ConnectDisconnectEventListener;
24 | import com.hivemq.extensions.log.mqtt.message.interceptor.ConnectInboundInterceptorImpl;
25 | import com.hivemq.extensions.log.mqtt.message.interceptor.PublishInboundInterceptorImpl;
26 | import com.hivemq.extensions.log.mqtt.message.interceptor.PublishOutboundInterceptorImpl;
27 | import com.hivemq.extensions.log.mqtt.message.interceptor.SubscribeInboundInterceptorImpl;
28 | import org.jetbrains.annotations.NotNull;
29 |
30 | /**
31 | * Creates a {@link ClientInitializer} that is usable for any HiveMQ 4.2 Enterprise Version.
32 | *
33 | * @version 1.1.0
34 | */
35 | public class ClientInitializerImpl4_2 implements ClientInitializer {
36 |
37 | private final @NotNull ExtensionConfig config;
38 |
39 | public ClientInitializerImpl4_2(final @NotNull ExtensionConfig config) {
40 | this.config = config;
41 | init();
42 | }
43 |
44 | /**
45 | * Initialize any logging logic that can be done without a {@link ClientInitializer}.
46 | */
47 | private void init() {
48 | if (config.isClientConnect() && config.isClientDisconnect()) {
49 | Services.eventRegistry().setClientLifecycleEventListener( //
50 | input -> new ConnectDisconnectEventListener(true, config.isVerbose(), config.isPayload()));
51 | } else if (config.isClientDisconnect()) {
52 | Services.eventRegistry().setClientLifecycleEventListener( //
53 | input -> new ConnectDisconnectEventListener(false, config.isVerbose(), config.isPayload()));
54 | } else if (config.isClientConnect()) {
55 | Services.interceptorRegistry().setConnectInboundInterceptorProvider( //
56 | input -> new ConnectInboundInterceptorImpl(config.isVerbose(), config.isPayload()));
57 | }
58 | }
59 |
60 | @Override
61 | public void initialize(
62 | final @NotNull InitializerInput initializerInput, final @NotNull ClientContext clientContext) {
63 | if (config.isSubscribeReceived()) {
64 | clientContext.addSubscribeInboundInterceptor(new SubscribeInboundInterceptorImpl(config.isVerbose()));
65 | }
66 | if (config.isPublishReceived()) {
67 | clientContext.addPublishInboundInterceptor(new PublishInboundInterceptorImpl(config.isVerbose(),
68 | config.isPayload()));
69 | }
70 | if (config.isPublishSend()) {
71 | clientContext.addPublishOutboundInterceptor(new PublishOutboundInterceptorImpl(config.isVerbose(),
72 | config.isPayload()));
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnackOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.connack.ConnackOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.connack.parameter.ConnackOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.connack.parameter.ConnackOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class ConnackOutboundInterceptorImpl implements ConnackOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(ConnackOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public ConnackOutboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onOutboundConnack(
40 | final @NotNull ConnackOutboundInput connackOutboundInput,
41 | final @NotNull ConnackOutboundOutput connackOutboundOutput) {
42 | try {
43 | MessageLogUtil.logConnack(connackOutboundInput, verbose);
44 | } catch (final Exception e) {
45 | LOG.debug("Exception thrown at outbound connack logging: ", e);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectDisconnectEventListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.events.client.ClientLifecycleEventListener;
19 | import com.hivemq.extension.sdk.api.events.client.parameters.AuthenticationFailedInput;
20 | import com.hivemq.extension.sdk.api.events.client.parameters.AuthenticationSuccessfulInput;
21 | import com.hivemq.extension.sdk.api.events.client.parameters.ClientInitiatedDisconnectInput;
22 | import com.hivemq.extension.sdk.api.events.client.parameters.ConnectionLostInput;
23 | import com.hivemq.extension.sdk.api.events.client.parameters.ConnectionStartInput;
24 | import com.hivemq.extension.sdk.api.events.client.parameters.DisconnectEventInput;
25 | import com.hivemq.extension.sdk.api.events.client.parameters.ServerInitiatedDisconnectInput;
26 | import com.hivemq.extension.sdk.api.packets.connect.ConnectPacket;
27 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
28 | import org.jetbrains.annotations.NotNull;
29 | import org.slf4j.Logger;
30 | import org.slf4j.LoggerFactory;
31 |
32 | /**
33 | * @since 1.0.0
34 | */
35 | public class ConnectDisconnectEventListener implements ClientLifecycleEventListener {
36 |
37 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(ConnectDisconnectEventListener.class);
38 |
39 | private final boolean logConnect;
40 | private final boolean verbose;
41 | private final boolean payload;
42 |
43 | public ConnectDisconnectEventListener(final boolean logConnect, final boolean verbose, final boolean payload) {
44 | this.logConnect = logConnect;
45 | this.verbose = verbose;
46 | this.payload = payload;
47 | }
48 |
49 | @Override
50 | public void onMqttConnectionStart(final @NotNull ConnectionStartInput connectionStartInput) {
51 | if (!logConnect) {
52 | return;
53 | }
54 | try {
55 | final ConnectPacket connectPacket = connectionStartInput.getConnectPacket();
56 | MessageLogUtil.logConnect(connectPacket, verbose, payload);
57 | } catch (final Exception e) {
58 | LOG.debug("Exception thrown at inbound connect logging: ", e);
59 | }
60 | }
61 |
62 | @Override
63 | public void onAuthenticationSuccessful(final @NotNull AuthenticationSuccessfulInput authenticationSuccessfulInput) {
64 | //NOOP
65 | }
66 |
67 | @Override
68 | public void onDisconnect(final @NotNull DisconnectEventInput disconnectEventInput) {
69 | //NOOP
70 | }
71 |
72 | @Override
73 | public void onAuthenticationFailedDisconnect(final @NotNull AuthenticationFailedInput authenticationFailedInput) {
74 | MessageLogUtil.logDisconnect(String.format("Sent DISCONNECT to client '%s' because authentication failed.",
75 | authenticationFailedInput.getClientInformation().getClientId()), authenticationFailedInput, verbose);
76 | }
77 |
78 | @Override
79 | public void onConnectionLost(final @NotNull ConnectionLostInput connectionLostInput) {
80 | //NOOP since no mqtt message is sent.
81 | }
82 |
83 | @Override
84 | public void onClientInitiatedDisconnect(final @NotNull ClientInitiatedDisconnectInput clientInitiatedDisconnectInput) {
85 | MessageLogUtil.logDisconnect(String.format("Received DISCONNECT from client '%s':",
86 | clientInitiatedDisconnectInput.getClientInformation().getClientId()),
87 | clientInitiatedDisconnectInput,
88 | verbose);
89 | }
90 |
91 | @Override
92 | public void onServerInitiatedDisconnect(final @NotNull ServerInitiatedDisconnectInput serverInitiatedDisconnectInput) {
93 | MessageLogUtil.logDisconnect(String.format("Sent DISCONNECT to client '%s':",
94 | serverInitiatedDisconnectInput.getClientInformation().getClientId()),
95 | serverInitiatedDisconnectInput,
96 | verbose);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/ConnectInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.connect.ConnectInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.connect.parameter.ConnectInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.connect.parameter.ConnectInboundOutput;
21 | import com.hivemq.extension.sdk.api.packets.connect.ConnectPacket;
22 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
23 | import org.jetbrains.annotations.NotNull;
24 | import org.slf4j.Logger;
25 | import org.slf4j.LoggerFactory;
26 |
27 | /**
28 | * @since 1.0.0
29 | */
30 | public class ConnectInboundInterceptorImpl implements ConnectInboundInterceptor {
31 |
32 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(ConnectInboundInterceptorImpl.class);
33 | private final boolean verbose;
34 | private final boolean payload;
35 |
36 | public ConnectInboundInterceptorImpl(final boolean verbose, final boolean payload) {
37 | this.verbose = verbose;
38 | this.payload = payload;
39 | }
40 |
41 | @Override
42 | public void onConnect(
43 | final @NotNull ConnectInboundInput connectInboundInput,
44 | final @NotNull ConnectInboundOutput connectInboundOutput) {
45 | try {
46 | final ConnectPacket connectPacket = connectInboundInput.getConnectPacket();
47 | MessageLogUtil.logConnect(connectPacket, verbose, payload);
48 | } catch (final Exception e) {
49 | LOG.debug("Exception thrown at inbound connect logging: ", e);
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/DisconnectInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.disconnect.DisconnectInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.disconnect.parameter.DisconnectInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.disconnect.parameter.DisconnectInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class DisconnectInboundInterceptorImpl implements DisconnectInboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(DisconnectInboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public DisconnectInboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onInboundDisconnect(
40 | final @NotNull DisconnectInboundInput disconnectInboundInput,
41 | final @NotNull DisconnectInboundOutput disconnectInboundOutput) {
42 | try {
43 | final String clientId = disconnectInboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logDisconnect(disconnectInboundInput.getDisconnectPacket(), clientId, true, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at inbound disconnect logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/DisconnectOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.disconnect.DisconnectOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.disconnect.parameter.DisconnectOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.disconnect.parameter.DisconnectOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class DisconnectOutboundInterceptorImpl implements DisconnectOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(DisconnectOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public DisconnectOutboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onOutboundDisconnect(
40 | final @NotNull DisconnectOutboundInput disconnectOutboundInput,
41 | final @NotNull DisconnectOutboundOutput disconnectOutboundOutput) {
42 | try {
43 | final String clientId = disconnectOutboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logDisconnect(disconnectOutboundInput.getDisconnectPacket(), clientId, false, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at outbound disconnect logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PingreqInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.pingreq.PingReqInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.pingreq.parameter.PingReqInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.pingreq.parameter.PingReqInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PingreqInboundInterceptorImpl implements PingReqInboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PingreqInboundInterceptorImpl.class);
32 |
33 | @Override
34 | public void onInboundPingReq(
35 | final @NotNull PingReqInboundInput pingReqInboundInput,
36 | final @NotNull PingReqInboundOutput pingReqInboundOutput) {
37 | try {
38 | MessageLogUtil.logPingreq(pingReqInboundInput);
39 | } catch (final Exception e) {
40 | LOG.debug("Exception thrown at inbound ping request logging: ", e);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PingrespOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.pingresp.PingRespOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.pingresp.parameter.PingRespOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.pingresp.parameter.PingRespOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PingrespOutboundInterceptorImpl implements PingRespOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PingrespOutboundInterceptorImpl.class);
32 |
33 | @Override
34 | public void onOutboundPingResp(
35 | final @NotNull PingRespOutboundInput pingRespOutboundInput,
36 | final @NotNull PingRespOutboundOutput pingRespOutboundOutput) {
37 | try {
38 | MessageLogUtil.logPingresp(pingRespOutboundInput);
39 | } catch (final Exception e) {
40 | LOG.debug("Exception thrown at outbound ping response logging: ", e);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PubackInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.puback.PubackInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.puback.parameter.PubackInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.puback.parameter.PubackInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PubackInboundInterceptorImpl implements PubackInboundInterceptor {
30 |
31 | private static final @NotNull Logger log = LoggerFactory.getLogger(PubackInboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public PubackInboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onInboundPuback(
40 | final @NotNull PubackInboundInput pubackInboundInput,
41 | final @NotNull PubackInboundOutput pubackInboundOutput) {
42 | try {
43 | @NotNull final String clientId = pubackInboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logPuback(pubackInboundInput.getPubackPacket(), clientId, true, verbose);
45 | } catch (final Exception e) {
46 | log.debug("Exception thrown at inbound puback logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PubackOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.puback.PubackOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.puback.parameter.PubackOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.puback.parameter.PubackOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PubackOutboundInterceptorImpl implements PubackOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PubackOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public PubackOutboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onOutboundPuback(
40 | final @NotNull PubackOutboundInput pubackOutboundInput,
41 | final @NotNull PubackOutboundOutput pubackOutboundOutput) {
42 | try {
43 | final String clientId = pubackOutboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logPuback(pubackOutboundInput.getPubackPacket(), clientId, false, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at outbound puback logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PubcompInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.pubcomp.PubcompInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.pubcomp.parameter.PubcompInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.pubcomp.parameter.PubcompInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PubcompInboundInterceptorImpl implements PubcompInboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PubcompInboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public PubcompInboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onInboundPubcomp(
40 | final @NotNull PubcompInboundInput pubcompInboundInput,
41 | final @NotNull PubcompInboundOutput pubcompInboundOutput) {
42 | try {
43 | final String clientId = pubcompInboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logPubcomp(pubcompInboundInput.getPubcompPacket(), clientId, true, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at inbound pubcomp logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PubcompOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.pubcomp.PubcompOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.pubcomp.parameter.PubcompOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.pubcomp.parameter.PubcompOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PubcompOutboundInterceptorImpl implements PubcompOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PubcompOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public PubcompOutboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onOutboundPubcomp(
40 | final @NotNull PubcompOutboundInput pubcompOutboundInput,
41 | final @NotNull PubcompOutboundOutput pubcompOutboundOutput) {
42 | try {
43 | final String clientId = pubcompOutboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logPubcomp(pubcompOutboundInput.getPubcompPacket(), clientId, false, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at outbound pubcomp logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PublishInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.publish.PublishInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.publish.parameter.PublishInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.publish.parameter.PublishInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.0.0
28 | */
29 | public class PublishInboundInterceptorImpl implements PublishInboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PublishInboundInterceptorImpl.class);
32 | private final boolean verbose;
33 | private final boolean payload;
34 |
35 | public PublishInboundInterceptorImpl(final boolean verbose, final boolean payload) {
36 | this.verbose = verbose;
37 | this.payload = payload;
38 | }
39 |
40 | @Override
41 | public void onInboundPublish(
42 | final @NotNull PublishInboundInput publishInboundInput,
43 | final @NotNull PublishInboundOutput publishInboundOutput) {
44 | try {
45 | final String clientID = publishInboundInput.getClientInformation().getClientId();
46 | MessageLogUtil.logPublish(String.format("Received PUBLISH from client '%s' for topic", clientID),
47 | publishInboundInput.getPublishPacket(),
48 | verbose,
49 | payload);
50 | } catch (final Exception e) {
51 | LOG.debug("Exception thrown at inbound publish logging: ", e);
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PublishOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.publish.PublishOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.publish.parameter.PublishOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.publish.parameter.PublishOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.0.0
28 | */
29 | public class PublishOutboundInterceptorImpl implements PublishOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PublishOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 | private final boolean payload;
34 |
35 | public PublishOutboundInterceptorImpl(final boolean verbose, final boolean payload) {
36 | this.verbose = verbose;
37 | this.payload = payload;
38 | }
39 |
40 | @Override
41 | public void onOutboundPublish(
42 | final @NotNull PublishOutboundInput publishOutboundInput,
43 | final @NotNull PublishOutboundOutput publishOutboundOutput) {
44 | try {
45 | final String clientID = publishOutboundInput.getClientInformation().getClientId();
46 | MessageLogUtil.logPublish(String.format("Sent PUBLISH to client '%s' on topic", clientID),
47 | publishOutboundInput.getPublishPacket(),
48 | verbose,
49 | payload);
50 | } catch (final Exception e) {
51 | LOG.debug("Exception thrown at outbound publish logging: ", e);
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PubrecInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.pubrec.PubrecInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.pubrec.parameter.PubrecInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.pubrec.parameter.PubrecInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PubrecInboundInterceptorImpl implements PubrecInboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PubrecInboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public PubrecInboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onInboundPubrec(
40 | final @NotNull PubrecInboundInput pubrecInboundInput,
41 | final @NotNull PubrecInboundOutput pubrecInboundOutput) {
42 | try {
43 | final String clientId = pubrecInboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logPubrec(pubrecInboundInput.getPubrecPacket(), clientId, true, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at inbound pubrec logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PubrecOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.pubrec.PubrecOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.pubrec.parameter.PubrecOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.pubrec.parameter.PubrecOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PubrecOutboundInterceptorImpl implements PubrecOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PubrecOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public PubrecOutboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onOutboundPubrec(
40 | final @NotNull PubrecOutboundInput pubrecOutboundInput,
41 | final @NotNull PubrecOutboundOutput pubrecOutboundOutput) {
42 | try {
43 | final String clientId = pubrecOutboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logPubrec(pubrecOutboundInput.getPubrecPacket(), clientId, false, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at outbound pubrec logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PubrelInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.pubrel.PubrelInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.pubrel.parameter.PubrelInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.pubrel.parameter.PubrelInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PubrelInboundInterceptorImpl implements PubrelInboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PubrelInboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public PubrelInboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onInboundPubrel(
40 | final @NotNull PubrelInboundInput pubrelInboundInput,
41 | final @NotNull PubrelInboundOutput pubrelInboundOutput) {
42 | try {
43 | final String clientId = pubrelInboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logPubrel(pubrelInboundInput.getPubrelPacket(), clientId, true, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at inbound pubrel logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/PubrelOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.pubrel.PubrelOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.pubrel.parameter.PubrelOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.pubrel.parameter.PubrelOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class PubrelOutboundInterceptorImpl implements PubrelOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(PubrelOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public PubrelOutboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onOutboundPubrel(
40 | final @NotNull PubrelOutboundInput pubrelOutboundInput,
41 | final @NotNull PubrelOutboundOutput pubrelOutboundOutput) {
42 | try {
43 | final String clientId = pubrelOutboundInput.getClientInformation().getClientId();
44 | MessageLogUtil.logPubrel(pubrelOutboundInput.getPubrelPacket(), clientId, false, verbose);
45 | } catch (final Exception e) {
46 | LOG.debug("Exception thrown at outbound pubrel logging: ", e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/SubackOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.suback.SubackOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.suback.parameter.SubackOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.suback.parameter.SubackOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class SubackOutboundInterceptorImpl implements SubackOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(SubackOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public SubackOutboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onOutboundSuback(
40 | final @NotNull SubackOutboundInput subackOutboundInput,
41 | final @NotNull SubackOutboundOutput subackOutboundOutput) {
42 | try {
43 | MessageLogUtil.logSuback(subackOutboundInput, verbose);
44 | } catch (final Exception e) {
45 | LOG.debug("Exception thrown at outbound suback logging: ", e);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/SubscribeInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.subscribe.SubscribeInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.subscribe.parameter.SubscribeInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.subscribe.parameter.SubscribeInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.0.0
28 | */
29 | public class SubscribeInboundInterceptorImpl implements SubscribeInboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(SubscribeInboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public SubscribeInboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onInboundSubscribe(
40 | final @NotNull SubscribeInboundInput subscribeInboundInput,
41 | final @NotNull SubscribeInboundOutput subscribeInboundOutput) {
42 | try {
43 | MessageLogUtil.logSubscribe(subscribeInboundInput, verbose);
44 | } catch (final Exception e) {
45 | LOG.debug("Exception thrown at inbound subscribe logging: ", e);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/UnsubackOutboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.unsuback.UnsubackOutboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.unsuback.parameter.UnsubackOutboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.unsuback.parameter.UnsubackOutboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class UnsubackOutboundInterceptorImpl implements UnsubackOutboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(UnsubackOutboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public UnsubackOutboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onOutboundUnsuback(
40 | final @NotNull UnsubackOutboundInput unsubackOutboundInput,
41 | final @NotNull UnsubackOutboundOutput unsubackOutboundOutput) {
42 | try {
43 | MessageLogUtil.logUnsuback(unsubackOutboundInput, verbose);
44 | } catch (final Exception e) {
45 | LOG.debug("Exception thrown at outbound unsuback logging: ", e);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/hivemq/extensions/log/mqtt/message/interceptor/UnsubscribeInboundInterceptorImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.interceptor;
17 |
18 | import com.hivemq.extension.sdk.api.interceptor.unsubscribe.UnsubscribeInboundInterceptor;
19 | import com.hivemq.extension.sdk.api.interceptor.unsubscribe.parameter.UnsubscribeInboundInput;
20 | import com.hivemq.extension.sdk.api.interceptor.unsubscribe.parameter.UnsubscribeInboundOutput;
21 | import com.hivemq.extensions.log.mqtt.message.util.MessageLogUtil;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * @since 1.1.0
28 | */
29 | public class UnsubscribeInboundInterceptorImpl implements UnsubscribeInboundInterceptor {
30 |
31 | private static final @NotNull Logger LOG = LoggerFactory.getLogger(UnsubscribeInboundInterceptorImpl.class);
32 | private final boolean verbose;
33 |
34 | public UnsubscribeInboundInterceptorImpl(final boolean verbose) {
35 | this.verbose = verbose;
36 | }
37 |
38 | @Override
39 | public void onInboundUnsubscribe(
40 | final @NotNull UnsubscribeInboundInput unsubscribeInboundInput,
41 | final @NotNull UnsubscribeInboundOutput unsubscribeInboundOutput) {
42 | try {
43 | MessageLogUtil.logUnsubscribe(unsubscribeInboundInput, verbose);
44 | } catch (final Exception e) {
45 | LOG.debug("Exception thrown at inbound unsubscribe logging: ", e);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/resources/config.xsd:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/test/java/com/hivemq/extensions/log/mqtt/message/MqttMessageLogExtensionMainTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message;
17 |
18 | import com.hivemq.extension.sdk.api.client.parameter.ServerInformation;
19 | import com.hivemq.extension.sdk.api.parameter.ExtensionInformation;
20 | import com.hivemq.extension.sdk.api.parameter.ExtensionStartInput;
21 | import com.hivemq.extension.sdk.api.parameter.ExtensionStartOutput;
22 | import com.hivemq.extension.sdk.api.services.admin.LicenseEdition;
23 | import com.hivemq.extension.sdk.api.services.intializer.ClientInitializer;
24 | import com.hivemq.extensions.log.mqtt.message.initializer.ClientInitializerImpl;
25 | import com.hivemq.extensions.log.mqtt.message.initializer.ClientInitializerImpl4_2;
26 | import org.jetbrains.annotations.NotNull;
27 | import org.junit.jupiter.api.BeforeEach;
28 | import org.junit.jupiter.api.Test;
29 |
30 | import java.io.File;
31 |
32 | import static org.junit.jupiter.api.Assertions.assertInstanceOf;
33 | import static org.mockito.Mockito.mock;
34 | import static org.mockito.Mockito.verify;
35 | import static org.mockito.Mockito.when;
36 |
37 | /**
38 | * @since 1.0.0
39 | */
40 | class MqttMessageLogExtensionMainTest {
41 |
42 | private @NotNull ExtensionStartInput extensionStartInput;
43 | private @NotNull ExtensionStartOutput extensionStartOutput;
44 | private @NotNull MqttMessageLogExtensionMain extensionMain;
45 |
46 | @BeforeEach
47 | void setUp() {
48 | extensionStartInput = mock(ExtensionStartInput.class);
49 | extensionStartOutput = mock(ExtensionStartOutput.class);
50 | extensionMain = new MqttMessageLogExtensionMain();
51 | }
52 |
53 | @Test
54 | void test_extension_start_prevented_no_access_to_static_components() {
55 | final ExtensionInformation information = mock(ExtensionInformation.class);
56 | final ServerInformation serverInformation = mock(ServerInformation.class);
57 |
58 | when(extensionStartInput.getExtensionInformation()).thenReturn(information);
59 | when(extensionStartInput.getServerInformation()).thenReturn(serverInformation);
60 | when(serverInformation.getVersion()).thenReturn("4");
61 | when(information.getExtensionHomeFolder()).thenReturn(new File("some/not/existing/folder"));
62 | when(information.getName()).thenReturn("My Extension");
63 |
64 | extensionMain.extensionStart(extensionStartInput, extensionStartOutput);
65 | verify(extensionStartOutput).preventExtensionStartup("My Extension cannot be started");
66 |
67 | }
68 |
69 | @Test
70 | void test_extension_start_prevented_because_of_old_version() {
71 | when(extensionStartInput.getServerInformation()).thenThrow(NoSuchMethodError.class);
72 |
73 | extensionMain.extensionStart(extensionStartInput, extensionStartOutput);
74 | verify(extensionStartOutput).preventExtensionStartup("The HiveMQ version is not supported");
75 | }
76 |
77 | @Test
78 | void getClientInitializerForEdition_4_2_0_oldImplReturned() {
79 | final ClientInitializer clientInitializerForEdition =
80 | extensionMain.getClientInitializerForEdition(LicenseEdition.ENTERPRISE, "4.2.0", mock());
81 | assertInstanceOf(ClientInitializerImpl4_2.class, clientInitializerForEdition);
82 | }
83 |
84 | @Test
85 | void getClientInitializerForEdition_4_3_0_newImplReturned() {
86 | final ClientInitializer clientInitializerForEdition =
87 | extensionMain.getClientInitializerForEdition(LicenseEdition.ENTERPRISE, "4.3.0", mock());
88 | assertInstanceOf(ClientInitializerImpl.class, clientInitializerForEdition);
89 | }
90 |
91 | @Test
92 | void getClientInitializerForEdition_4_20_0_newImplReturned() {
93 | final ClientInitializer clientInitializerForEdition =
94 | extensionMain.getClientInitializerForEdition(LicenseEdition.ENTERPRISE, "4.20.0", mock());
95 | assertInstanceOf(ClientInitializerImpl.class, clientInitializerForEdition);
96 | }
97 |
98 | @Test
99 | void getClientInitializerForEdition_COMMUNITY_newImplReturned() {
100 | final ClientInitializer clientInitializerForEdition =
101 | extensionMain.getClientInitializerForEdition(LicenseEdition.COMMUNITY, "2024.1", mock());
102 | assertInstanceOf(ClientInitializerImpl.class, clientInitializerForEdition);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/test/java/com/hivemq/extensions/log/mqtt/message/config/ExtensionConfigReaderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.config;
17 |
18 | import org.jetbrains.annotations.NotNull;
19 | import org.junit.jupiter.api.Test;
20 | import org.junit.jupiter.api.io.TempDir;
21 |
22 | import java.io.File;
23 | import java.nio.file.Path;
24 | import java.util.List;
25 | import java.util.Objects;
26 | import java.util.Properties;
27 |
28 | import static org.junit.jupiter.api.Assertions.assertEquals;
29 | import static org.junit.jupiter.api.Assertions.assertFalse;
30 | import static org.junit.jupiter.api.Assertions.assertInstanceOf;
31 | import static org.junit.jupiter.api.Assertions.assertTrue;
32 |
33 | /**
34 | * @since 1.0.0
35 | */
36 | class ExtensionConfigReaderTest {
37 |
38 | private final int totalAvailableFlags = 21;
39 |
40 | private final @NotNull List defaultProperties = List.of(ExtensionConfigProperties.CLIENT_CONNECT,
41 | ExtensionConfigProperties.CONNACK_SEND,
42 | ExtensionConfigProperties.CLIENT_DISCONNECT,
43 | ExtensionConfigProperties.PUBLISH_RECEIVED,
44 | ExtensionConfigProperties.PUBLISH_SEND,
45 | ExtensionConfigProperties.SUBSCRIBE_RECEIVED,
46 | ExtensionConfigProperties.SUBACK_SEND,
47 | ExtensionConfigProperties.UNSUBSCRIBE_RECEIVED,
48 | ExtensionConfigProperties.UNSUBACK_SEND,
49 | ExtensionConfigProperties.PING_REQUEST_RECEIVED,
50 | ExtensionConfigProperties.PING_RESPONSE_SEND,
51 | ExtensionConfigProperties.PUBACK_RECEIVED,
52 | ExtensionConfigProperties.PUBACK_SEND,
53 | ExtensionConfigProperties.PUBREC_RECEIVED,
54 | ExtensionConfigProperties.PUBREC_SEND,
55 | ExtensionConfigProperties.PUBREL_RECEIVED,
56 | ExtensionConfigProperties.PUBREL_SEND,
57 | ExtensionConfigProperties.PUBCOMP_RECEIVED,
58 | ExtensionConfigProperties.PUBCOMP_SEND,
59 | ExtensionConfigProperties.VERBOSE,
60 | ExtensionConfigProperties.PAYLOAD);
61 |
62 | @Test
63 | void defaultPropertiesWhenNoPropertyFileInConfigFolder(@TempDir final @NotNull Path tempDir) {
64 | final ExtensionConfig extensionConfig = ExtensionConfigReader.read(tempDir.toFile());
65 | assertInstanceOf(ExtensionConfigProperties.class, extensionConfig);
66 |
67 | final ExtensionConfigProperties extensionConfigProperties = ((ExtensionConfigProperties) extensionConfig);
68 | final Properties properties = extensionConfigProperties.getProperties();
69 |
70 | assertEquals(properties.size(), totalAvailableFlags);
71 | assertTrue(properties.stringPropertyNames().containsAll(defaultProperties));
72 | assertTrue(defaultProperties.containsAll(properties.stringPropertyNames()));
73 |
74 | assertTrue(extensionConfigProperties.isClientConnect());
75 | assertTrue(extensionConfigProperties.isClientDisconnect());
76 | assertTrue(extensionConfigProperties.isConnackSend());
77 | assertTrue(extensionConfigProperties.isPublishReceived());
78 | assertTrue(extensionConfigProperties.isPublishSend());
79 | assertTrue(extensionConfigProperties.isSubscribeReceived());
80 | assertTrue(extensionConfigProperties.isSubackSend());
81 | assertTrue(extensionConfigProperties.isUnsubscribeReceived());
82 | assertTrue(extensionConfigProperties.isUnsubackSend());
83 | assertTrue(extensionConfigProperties.isPingRequestReceived());
84 | assertTrue(extensionConfigProperties.isPingResponseSend());
85 | assertTrue(extensionConfigProperties.isPubackReceived());
86 | assertTrue(extensionConfigProperties.isPubackSend());
87 | assertTrue(extensionConfigProperties.isPubrelReceived());
88 | assertTrue(extensionConfigProperties.isPubrelSend());
89 | assertTrue(extensionConfigProperties.isPubrecReceived());
90 | assertTrue(extensionConfigProperties.isPubrecSend());
91 | assertTrue(extensionConfigProperties.isPubcompReceived());
92 | assertTrue(extensionConfigProperties.isPubcompSend());
93 | assertFalse(extensionConfigProperties.isVerbose());
94 | assertTrue(extensionConfigProperties.isPayload());
95 | }
96 |
97 | @Test
98 | void nonEmptyPropertiesWhenPropertyFileInConfigFolder() {
99 | final String path = Objects.requireNonNull(getClass().getResource("/test-conf")).getPath();
100 | final ExtensionConfig extensionConfig = ExtensionConfigReader.read(new File(path));
101 | assertInstanceOf(ExtensionConfigProperties.class, extensionConfig);
102 |
103 | final ExtensionConfigProperties extensionConfigProperties = ((ExtensionConfigProperties) extensionConfig);
104 | final Properties properties = extensionConfigProperties.getProperties();
105 |
106 | assertEquals(properties.size(), totalAvailableFlags);
107 | assertTrue(properties.stringPropertyNames().containsAll(defaultProperties));
108 | assertTrue(defaultProperties.containsAll(properties.stringPropertyNames()));
109 |
110 | assertFalse(extensionConfigProperties.isVerbose());
111 | assertTrue(extensionConfigProperties.isPayload());
112 | assertFalse(extensionConfigProperties.isPublishReceived());
113 | assertFalse(extensionConfigProperties.isPublishSend());
114 | }
115 |
116 | @Test
117 | void nonEmptyPropertiesWhenConfigFileInConfFolder() {
118 | final String path = Objects.requireNonNull(getClass().getResource("/test-xml-conf")).getPath();
119 | final ExtensionConfig extensionConfig = ExtensionConfigReader.read(new File(path));
120 | assertInstanceOf(ExtensionConfigXml.class, extensionConfig);
121 |
122 | final ExtensionConfigXml extensionConfigXml = (ExtensionConfigXml) extensionConfig;
123 |
124 | assertFalse(extensionConfigXml.isVerbose());
125 | assertTrue(extensionConfigXml.isPayload());
126 | assertFalse(extensionConfigXml.isPublishReceived());
127 | assertFalse(extensionConfigXml.isPublishSend());
128 | }
129 |
130 | @Test
131 | void defaultPropertiesWhenInvalidConfigFileInConfFolder() {
132 | final String path = Objects.requireNonNull(getClass().getResource("/test-invalid-xml-conf")).getPath();
133 | final ExtensionConfig extensionConfig = ExtensionConfigReader.read(new File(path));
134 | assertInstanceOf(ExtensionConfigXml.class, extensionConfig);
135 |
136 | final ExtensionConfigXml extensionConfigXml = (ExtensionConfigXml) extensionConfig;
137 |
138 | assertTrue(extensionConfigXml.isClientConnect());
139 | assertTrue(extensionConfigXml.isClientDisconnect());
140 | assertTrue(extensionConfigXml.isConnackSend());
141 | assertTrue(extensionConfigXml.isPublishReceived());
142 | assertTrue(extensionConfigXml.isPublishSend());
143 | assertTrue(extensionConfigXml.isSubscribeReceived());
144 | assertTrue(extensionConfigXml.isSubackSend());
145 | assertTrue(extensionConfigXml.isUnsubscribeReceived());
146 | assertTrue(extensionConfigXml.isUnsubackSend());
147 | assertTrue(extensionConfigXml.isPingRequestReceived());
148 | assertTrue(extensionConfigXml.isPingResponseSend());
149 | assertTrue(extensionConfigXml.isPubackReceived());
150 | assertTrue(extensionConfigXml.isPubackSend());
151 | assertTrue(extensionConfigXml.isPubrelReceived());
152 | assertTrue(extensionConfigXml.isPubrelSend());
153 | assertTrue(extensionConfigXml.isPubrecReceived());
154 | assertTrue(extensionConfigXml.isPubrecSend());
155 | assertTrue(extensionConfigXml.isPubcompReceived());
156 | assertTrue(extensionConfigXml.isPubcompSend());
157 | assertFalse(extensionConfigXml.isVerbose());
158 | assertTrue(extensionConfigXml.isPayload());
159 | }
160 |
161 | }
162 |
--------------------------------------------------------------------------------
/src/test/java/com/hivemq/extensions/log/mqtt/message/util/LogbackTestAppender.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019-present HiveMQ GmbH
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.hivemq.extensions.log.mqtt.message.util;
17 |
18 | import ch.qos.logback.classic.Level;
19 | import ch.qos.logback.classic.Logger;
20 | import ch.qos.logback.classic.spi.ILoggingEvent;
21 | import ch.qos.logback.core.AppenderBase;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.junit.jupiter.api.extension.AfterEachCallback;
24 | import org.junit.jupiter.api.extension.BeforeEachCallback;
25 | import org.junit.jupiter.api.extension.ExtensionContext;
26 |
27 | import java.util.LinkedList;
28 | import java.util.List;
29 |
30 | public class LogbackTestAppender extends AppenderBase implements BeforeEachCallback, AfterEachCallback {
31 |
32 | public static @NotNull LogbackTestAppender createFor(final @NotNull org.slf4j.Logger logger) {
33 | return new LogbackTestAppender((Logger) logger);
34 | }
35 |
36 | private final @NotNull Logger logger;
37 | private final @NotNull Level initialLevel;
38 | private final @NotNull List events = new LinkedList<>();
39 |
40 | private LogbackTestAppender(final @NotNull Logger logger) {
41 | this.logger = logger;
42 | initialLevel = logger.getLevel();
43 | }
44 |
45 | public void attach() {
46 | logger.setLevel(Level.ALL);
47 | logger.addAppender(this);
48 | start();
49 | }
50 |
51 | public void detach() {
52 | logger.setLevel(initialLevel);
53 | logger.detachAppender(this);
54 | stop();
55 | }
56 |
57 | @Override
58 | public void beforeEach(final @NotNull ExtensionContext ignored) {
59 | attach();
60 | }
61 |
62 | @Override
63 | public void afterEach(final @NotNull ExtensionContext ignored) {
64 | detach();
65 | }
66 |
67 | @Override
68 | protected void append(final @NotNull ILoggingEvent e) {
69 | events.add(e);
70 | }
71 |
72 | public @NotNull List getEvents() {
73 | return events;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/test/resources/test-conf/mqttMessageLog.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2019-present HiveMQ GmbH
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | # Example properties file that will prevent the logging of
17 | # both incomming and outgoing messages, but all other
18 | # events, such as connection and subscription events, will
19 | # be logged.
20 | publish-received=false
21 | publish-send=false
22 |
--------------------------------------------------------------------------------
/src/test/resources/test-invalid-xml-conf/conf/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 | false
21 | false
22 |
23 |
--------------------------------------------------------------------------------
/src/test/resources/test-xml-conf/conf/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
21 | false
22 | false
23 |
24 |
--------------------------------------------------------------------------------