001/** 002 * 003 * Copyright the original author or authors 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 */ 017package org.jivesoftware.smack.debugger; 018 019import java.util.logging.Logger; 020 021import org.jivesoftware.smack.AbstractXMPPConnection; 022import org.jivesoftware.smack.ConnectionListener; 023import org.jivesoftware.smack.ReconnectionListener; 024import org.jivesoftware.smack.ReconnectionManager; 025import org.jivesoftware.smack.XMPPConnection; 026import org.jivesoftware.smack.packet.TopLevelStreamElement; 027import org.jivesoftware.smack.util.ObservableReader; 028import org.jivesoftware.smack.util.ObservableWriter; 029import org.jivesoftware.smack.util.ReaderListener; 030import org.jivesoftware.smack.util.WriterListener; 031 032import org.jxmpp.jid.EntityFullJid; 033 034public abstract class AbstractDebugger extends SmackDebugger { 035 036 private static final Logger LOGGER = Logger.getLogger(AbstractDebugger.class.getName()); 037 038 public static boolean printInterpreted = false; 039 040 private final ConnectionListener connListener; 041 private final ReconnectionListener reconnectionListener; 042 private final ReaderListener readerListener; 043 private final WriterListener writerListener; 044 045 private ObservableWriter writer; 046 private ObservableReader reader; 047 048 public AbstractDebugger(final XMPPConnection connection) { 049 super(connection); 050 051 // Create a special Reader that wraps the main Reader and logs data to the GUI. 052 this.reader = new ObservableReader(reader); 053 readerListener = new ReaderListener() { 054 @Override 055 public void read(String str) { 056 log("RECV (" + connection.getConnectionCounter() + "): " + str); 057 } 058 }; 059 this.reader.addReaderListener(readerListener); 060 061 // Create a special Writer that wraps the main Writer and logs data to the GUI. 062 this.writer = new ObservableWriter(writer); 063 writerListener = new WriterListener() { 064 @Override 065 public void write(String str) { 066 log("SENT (" + connection.getConnectionCounter() + "): " + str); 067 } 068 }; 069 this.writer.addWriterListener(writerListener); 070 071 connListener = new ConnectionListener() { 072 @Override 073 public void connected(XMPPConnection connection) { 074 log("XMPPConnection connected (" 075 + connection + ")"); 076 } 077 @Override 078 public void authenticated(XMPPConnection connection, boolean resumed) { 079 String logString = "XMPPConnection authenticated (" + connection + ")"; 080 if (resumed) { 081 logString += " and resumed"; 082 } 083 log(logString); 084 } 085 @Override 086 public void connectionClosed() { 087 log( 088 "XMPPConnection closed (" + 089 connection + 090 ")"); 091 } 092 093 @Override 094 public void connectionClosedOnError(Exception e) { 095 log( 096 "XMPPConnection closed due to an exception (" + 097 connection + 098 ")", e); 099 } 100 }; 101 102 reconnectionListener = new ReconnectionListener() { 103 @Override 104 public void reconnectionFailed(Exception e) { 105 log( 106 "Reconnection failed due to an exception (" + 107 connection + 108 ")", e); 109 } 110 @Override 111 public void reconnectingIn(int seconds) { 112 log( 113 "XMPPConnection (" + 114 connection + 115 ") will reconnect in " + seconds); 116 } 117 }; 118 119 if (connection instanceof AbstractXMPPConnection) { 120 AbstractXMPPConnection abstractXmppConnection = (AbstractXMPPConnection) connection; 121 ReconnectionManager.getInstanceFor(abstractXmppConnection).addReconnectionListener(reconnectionListener); 122 } else { 123 LOGGER.info("The connection instance " + connection 124 + " is not an instance of AbstractXMPPConnection, thus we can not install the ReconnectionListener"); 125 } 126 } 127 128 protected abstract void log(String logMessage); 129 130 protected abstract void log(String logMessage, Throwable throwable); 131 132 @Override 133 public final void outgoingStreamSink(CharSequence outgoingCharSequence) { 134 log("SENT (" + connection.getConnectionCounter() + "): " + outgoingCharSequence); 135 } 136 137 @Override 138 public final void incomingStreamSink(CharSequence incomingCharSequence) { 139 log("RECV (" + connection.getConnectionCounter() + "): " + incomingCharSequence); 140 } 141 142 @Override 143 public void userHasLogged(EntityFullJid user) { 144 String localpart = user.getLocalpart().toString(); 145 boolean isAnonymous = "".equals(localpart); 146 String title = 147 "User logged (" + connection.getConnectionCounter() + "): " 148 + (isAnonymous ? "" : localpart) 149 + "@" 150 + connection.getXMPPServiceDomain() 151 + ":" 152 + connection.getPort(); 153 title += "/" + user.getResourcepart(); 154 log(title); 155 // Add the connection listener to the connection so that the debugger can be notified 156 // whenever the connection is closed. 157 connection.addConnectionListener(connListener); 158 } 159 160 @Override 161 public void onIncomingStreamElement(TopLevelStreamElement streamElement) { 162 if (printInterpreted) { 163 log("RCV PKT (" + connection.getConnectionCounter() + "): " + streamElement.toXML()); 164 } 165 } 166 167 @Override 168 public void onOutgoingStreamElement(TopLevelStreamElement streamElement) { 169 // Does nothing (yet). 170 } 171 172}