SLF4J Smack Debugging Logger

This commit is contained in:
Vyacheslav Blinov 2014-08-15 15:28:07 +04:00 committed by Florian Schmaus
parent 880a348ff4
commit 52673bad3c
9 changed files with 326 additions and 0 deletions

View File

@ -3,6 +3,7 @@ include 'smack-core',
'smack-extensions',
'smack-experimental',
'smack-debug',
'smack-debug-slf4j',
'smack-resolver-dnsjava',
'smack-resolver-minidns',
'smack-resolver-javax',

View File

@ -35,6 +35,7 @@ import javax.net.ssl.HostnameVerifier;
import org.jivesoftware.smack.compression.Java7ZlibInputOutputStream;
import org.jivesoftware.smack.compression.XMPPInputOutputStream;
import org.jivesoftware.smack.debugger.SmackDebugger;
import org.jivesoftware.smack.initializer.SmackInitializer;
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
@ -256,6 +257,13 @@ public final class SmackConfiguration {
}
}
/**
* Sets smack debugger class
*/
public static <T extends SmackDebugger> void setDebugger(Class<T> debuggerClass) {
System.setProperty("smack.debuggerClass", debuggerClass.getCanonicalName());
}
/**
* Remove a SASL mechanism from the list to be used.
*

View File

@ -0,0 +1,10 @@
description = """\
Smack slf4j debugger.
Inspect the exchanged XMPP stanzas.
Connect your favourite slf4j backend of choice to get output inside of it"""
dependencies {
compile project(':smack-core')
compile 'org.slf4j:slf4j-api:1.7.7'
testCompile project(':smack-core').sourceSets.test.runtimeClasspath
}

View File

@ -0,0 +1,62 @@
/**
*
* Copyright 2014 Vyacheslav Blinov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.debugger.slf4j;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.XMPPConnection;
import org.slf4j.Logger;
class SLF4JLoggingConnectionListener implements ConnectionListener {
private final XMPPConnection connection;
private final Logger logger;
public SLF4JLoggingConnectionListener(XMPPConnection connection, Logger logger) {
this.connection = Validate.notNull(connection);
this.logger = Validate.notNull(logger);
}
@Override
public void connected(XMPPConnection connection) {
logger.debug("({}) Connection connected", connection.hashCode());
}
@Override
public void authenticated(XMPPConnection connection) {
logger.debug("({}) Connection authenticated as {}", connection.hashCode(), connection.getUser());
}
public void connectionClosed() {
logger.debug("({}) Connection closed", connection.hashCode());
}
public void connectionClosedOnError(Exception e) {
logger.debug("({}) Connection closed due to an exception: {}", connection.hashCode(), e);
}
public void reconnectionFailed(Exception e) {
logger.debug("({}) Reconnection failed due to an exception: {}", connection.hashCode(), e);
}
public void reconnectionSuccessful() {
logger.debug("({}) Connection reconnected", connection.hashCode());
}
public void reconnectingIn(int seconds) {
logger.debug("({}) Connection will reconnect in {}", connection.hashCode(), seconds);
}
}

View File

@ -0,0 +1,39 @@
/**
*
* Copyright 2014 Vyacheslav Blinov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.debugger.slf4j;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.packet.Packet;
import org.slf4j.Logger;
class SLF4JLoggingPacketListener implements PacketListener {
private final Logger logger;
private final String prefix;
public SLF4JLoggingPacketListener(Logger logger, String prefix) {
this.logger = Validate.notNull(logger);
this.prefix = Validate.notNull(prefix);
}
public void processPacket(Packet packet) {
if (SLF4JSmackDebugger.printInterpreted.get() && logger.isDebugEnabled()) {
logger.debug("{}: PKT [{}] '{}'", prefix, packet.getClass().getName(), packet.toXML());
}
}
}

View File

@ -0,0 +1,38 @@
/**
*
* Copyright 2014 Vyacheslav Blinov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.debugger.slf4j;
import org.jivesoftware.smack.util.ReaderListener;
import org.jivesoftware.smack.util.WriterListener;
import org.slf4j.Logger;
class SLF4JRawXmlListener implements ReaderListener, WriterListener {
private final Logger logger;
public SLF4JRawXmlListener(Logger logger) {
this.logger = Validate.notNull(logger);
}
public void read(String str) {
logger.debug("{}: {}", SLF4JSmackDebugger.RECEIVED_TAG, str);
}
public void write(String str) {
logger.debug("{}: {}", SLF4JSmackDebugger.SENT_TAG, str);
}
}

View File

@ -0,0 +1,130 @@
/**
*
* Copyright 2014 Vyacheslav Blinov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.debugger.slf4j;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.debugger.SmackDebugger;
import org.jivesoftware.smack.util.ObservableReader;
import org.jivesoftware.smack.util.ObservableWriter;
import org.jxmpp.util.XmppStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Reader;
import java.io.Writer;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Implementation of SmackDebugger that writes log messages using SLF4J API.
* Use in conjunction with your SLF4J bindings of choice.
* See SLF4J manual for more details about bindings usage.
*/
public class SLF4JSmackDebugger implements SmackDebugger {
public static final String LOGGER_NAME = "SMACK";
private static final Logger logger = LoggerFactory.getLogger(LOGGER_NAME);
public static final AtomicBoolean printInterpreted = new AtomicBoolean(true);
public static final String SENT_TAG = "SENT";
public static final String RECEIVED_TAG = "RECV";
private final XMPPConnection connection;
private final PacketListener receivedListener = new SLF4JLoggingPacketListener(logger, RECEIVED_TAG);
private final PacketListener sentListener = new SLF4JLoggingPacketListener(logger, SENT_TAG);
private final SLF4JRawXmlListener slf4JRawXmlListener = new SLF4JRawXmlListener(logger);
private ObservableWriter writer;
private ObservableReader reader;
/**
* Makes Smack use this Debugger
*/
public static void enable() {
SmackConfiguration.setDebugger(SLF4JSmackDebugger.class);
}
/**
* Create new SLF4J Smack Debugger instance
* @param connection Smack connection to debug
* @param writer connection data writer to observe
* @param reader connection data reader to observe
*/
public SLF4JSmackDebugger(XMPPConnection connection, Writer writer, Reader reader) {
this.connection = connection;
this.writer = new ObservableWriter(writer);
this.writer.addWriterListener(slf4JRawXmlListener);
this.reader = new ObservableReader(Validate.notNull(reader));
this.reader.addReaderListener(slf4JRawXmlListener);
this.connection.addConnectionListener(new SLF4JLoggingConnectionListener(connection, logger));
}
@Override
public Reader newConnectionReader(Reader newReader) {
reader.removeReaderListener(slf4JRawXmlListener);
reader = new ObservableReader(newReader);
reader.addReaderListener(slf4JRawXmlListener);
return reader;
}
@Override
public Writer newConnectionWriter(Writer newWriter) {
writer.removeWriterListener(slf4JRawXmlListener);
writer = new ObservableWriter(newWriter);
writer.addWriterListener(slf4JRawXmlListener);
return writer;
}
@Override
public void userHasLogged(String user) {
if (logger.isDebugEnabled()) {
String userTitle = getUserTitle(user);
logger.debug("({}) User logged in {}", connection.hashCode(), userTitle);
}
}
private String getUserTitle(String user) {
if (("@" + connection.getServiceName()).equals(XmppStringUtils.parseBareAddress(user))) {
return "<Anonymous>@" + connection.getServiceName();
} else {
return user;
}
}
@Override
public Reader getReader() {
return reader;
}
@Override
public Writer getWriter() {
return writer;
}
@Override
public PacketListener getReaderListener() {
return receivedListener;
}
@Override
public PacketListener getWriterListener() {
return sentListener;
}
}

View File

@ -0,0 +1,37 @@
/**
*
* Copyright 2014 Vyacheslav Blinov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.debugger.slf4j;
/**
* This is package-level helper class to validate dependencies while initialization is in progress
*/
final class Validate {
private Validate() { /* do not create instances */ }
public static <T> T notNull(T instance) {
return notNull(instance, null);
}
public static <T> T notNull(T instance, String message) {
if (instance == null) {
throw new NullPointerException(message);
} else {
return instance;
}
}
}

View File

@ -0,0 +1 @@
<body>Smack slf4j debugger implementation.</body>