001/** 002 * 003 * Copyright 2014 Vyacheslav Blinov 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.jivesoftware.smackx.debugger.slf4j; 019 020import org.jivesoftware.smack.StanzaListener; 021import org.jivesoftware.smack.SmackConfiguration; 022import org.jivesoftware.smack.XMPPConnection; 023import org.jivesoftware.smack.debugger.SmackDebugger; 024import org.jivesoftware.smack.util.ObservableReader; 025import org.jivesoftware.smack.util.ObservableWriter; 026import org.jxmpp.util.XmppStringUtils; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030import java.io.Reader; 031import java.io.Writer; 032import java.util.concurrent.atomic.AtomicBoolean; 033 034 035/** 036 * Implementation of SmackDebugger that writes log messages using SLF4J API. 037 * Use in conjunction with your SLF4J bindings of choice. 038 * See SLF4J manual for more details about bindings usage. 039 */ 040public class SLF4JSmackDebugger implements SmackDebugger { 041 public static final String LOGGER_NAME = "SMACK"; 042 private static final Logger logger = LoggerFactory.getLogger(LOGGER_NAME); 043 public static final AtomicBoolean printInterpreted = new AtomicBoolean(true); 044 045 public static final String SENT_TAG = "SENT"; 046 public static final String RECEIVED_TAG = "RECV"; 047 048 private final XMPPConnection connection; 049 050 private final StanzaListener receivedListener = new SLF4JLoggingPacketListener(logger, RECEIVED_TAG); 051 private final StanzaListener sentListener = new SLF4JLoggingPacketListener(logger, SENT_TAG); 052 private final SLF4JRawXmlListener slf4JRawXmlListener = new SLF4JRawXmlListener(logger); 053 054 private ObservableWriter writer; 055 private ObservableReader reader; 056 057 /** 058 * Makes Smack use this Debugger 059 */ 060 public static void enable() { 061 SmackConfiguration.setDebuggerFactory(new SLF4JDebuggerFactory()); 062 } 063 064 /** 065 * Create new SLF4J Smack Debugger instance 066 * @param connection Smack connection to debug 067 * @param writer connection data writer to observe 068 * @param reader connection data reader to observe 069 */ 070 public SLF4JSmackDebugger(XMPPConnection connection, Writer writer, Reader reader) { 071 this.connection = connection; 072 this.writer = new ObservableWriter(writer); 073 this.writer.addWriterListener(slf4JRawXmlListener); 074 this.reader = new ObservableReader(Validate.notNull(reader)); 075 this.reader.addReaderListener(slf4JRawXmlListener); 076 this.connection.addConnectionListener(new SLF4JLoggingConnectionListener(connection, logger)); 077 } 078 079 @Override 080 public Reader newConnectionReader(Reader newReader) { 081 reader.removeReaderListener(slf4JRawXmlListener); 082 reader = new ObservableReader(newReader); 083 reader.addReaderListener(slf4JRawXmlListener); 084 return reader; 085 } 086 087 @Override 088 public Writer newConnectionWriter(Writer newWriter) { 089 writer.removeWriterListener(slf4JRawXmlListener); 090 writer = new ObservableWriter(newWriter); 091 writer.addWriterListener(slf4JRawXmlListener); 092 return writer; 093 } 094 095 @Override 096 public void userHasLogged(String user) { 097 if (logger.isDebugEnabled()) { 098 String userTitle = getUserTitle(user); 099 logger.debug("({}) User logged in {}", connection.hashCode(), userTitle); 100 } 101 } 102 103 private String getUserTitle(String user) { 104 if (("@" + connection.getServiceName()).equals(XmppStringUtils.parseBareJid(user))) { 105 return "<Anonymous>@" + connection.getServiceName(); 106 } else { 107 return user; 108 } 109 } 110 111 @Override 112 public Reader getReader() { 113 return reader; 114 } 115 116 @Override 117 public Writer getWriter() { 118 return writer; 119 } 120 121 @Override 122 public StanzaListener getReaderListener() { 123 return receivedListener; 124 } 125 126 @Override 127 public StanzaListener getWriterListener() { 128 return sentListener; 129 } 130}