1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$ 3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$ 4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$ 5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License. 8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at 9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * http://www.apache.org/licenses/LICENSE-2.0 11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software 13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS, 14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and 16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License. 17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smack.debugger; 19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.ConnectionListener; 21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.PacketListener; 22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.Connection; 23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Packet; 24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.util.*; 25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.Reader; 27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.Writer; 28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.text.SimpleDateFormat; 29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Date; 30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** 32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Very simple debugger that prints to the console (stdout) the sent and received stanzas. Use 33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * this debugger with caution since printing to the console is an expensive operation that may 34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * even block the thread since only one thread may print at a time.<p> 35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/> 36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * It is possible to not only print the raw sent and received stanzas but also the interpreted 37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * packets by Smack. By default interpreted packets won't be printed. To enable this feature 38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * just change the <tt>printInterpreted</tt> static variable to <tt>true</tt>. 39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * 40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Gaston Dombiak 41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class ConsoleDebugger implements SmackDebugger { 43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public static boolean printInterpreted = false; 45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private SimpleDateFormat dateFormatter = new SimpleDateFormat("hh:mm:ss aaa"); 46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Connection connection = null; 48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private PacketListener listener = null; 50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private ConnectionListener connListener = null; 51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Writer writer; 53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private Reader reader; 54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private ReaderListener readerListener; 55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private WriterListener writerListener; 56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public ConsoleDebugger(Connection connection, Writer writer, Reader reader) { 58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.connection = connection; 59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.writer = writer; 60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen this.reader = reader; 61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen createDebug(); 62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen /** 65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates the listeners that will print in the console when new activity is detected. 66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */ 67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen private void createDebug() { 68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create a special Reader that wraps the main Reader and logs data to the GUI. 69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ObservableReader debugReader = new ObservableReader(reader); 70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen readerListener = new ReaderListener() { 71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void read(String str) { 72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println( 73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dateFormatter.format(new Date()) + " RCV (" + connection.hashCode() + 74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "): " + 75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen str); 76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen debugReader.addReaderListener(readerListener); 79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create a special Writer that wraps the main Writer and logs data to the GUI. 81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ObservableWriter debugWriter = new ObservableWriter(writer); 82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen writerListener = new WriterListener() { 83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void write(String str) { 84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println( 85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dateFormatter.format(new Date()) + " SENT (" + connection.hashCode() + 86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "): " + 87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen str); 88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen debugWriter.addWriterListener(writerListener); 91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Assign the reader/writer objects to use the debug versions. The packet reader 93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // and writer will use the debug versions when they are created. 94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reader = debugReader; 95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen writer = debugWriter; 96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Create a thread that will listen for all incoming packets and write them to 98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // the GUI. This is what we call "interpreted" packet data, since it's the packet 99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // data as Smack sees it and not as it's coming in as raw XML. 100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen listener = new PacketListener() { 101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void processPacket(Packet packet) { 102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen if (printInterpreted) { 103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println( 104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dateFormatter.format(new Date()) + " RCV PKT (" + 105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.hashCode() + 106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "): " + 107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen packet.toXML()); 108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connListener = new ConnectionListener() { 113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void connectionClosed() { 114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println( 115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dateFormatter.format(new Date()) + " Connection closed (" + 116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.hashCode() + 117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ")"); 118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void connectionClosedOnError(Exception e) { 121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println( 122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dateFormatter.format(new Date()) + 123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen " Connection closed due to an exception (" + 124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.hashCode() + 125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ")"); 126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void reconnectionFailed(Exception e) { 129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println( 130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dateFormatter.format(new Date()) + 131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen " Reconnection failed due to an exception (" + 132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.hashCode() + 133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ")"); 134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen e.printStackTrace(); 135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void reconnectionSuccessful() { 137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println( 138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dateFormatter.format(new Date()) + " Connection reconnected (" + 139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.hashCode() + 140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ")"); 141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void reconnectingIn(int seconds) { 143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println( 144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen dateFormatter.format(new Date()) + " Connection (" + 145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.hashCode() + 146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ") will reconnect in " + seconds); 147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen }; 149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Reader newConnectionReader(Reader newReader) { 152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((ObservableReader)reader).removeReaderListener(readerListener); 153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ObservableReader debugReader = new ObservableReader(newReader); 154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen debugReader.addReaderListener(readerListener); 155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen reader = debugReader; 156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return reader; 157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Writer newConnectionWriter(Writer newWriter) { 160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ((ObservableWriter)writer).removeWriterListener(writerListener); 161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen ObservableWriter debugWriter = new ObservableWriter(newWriter); 162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen debugWriter.addWriterListener(writerListener); 163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen writer = debugWriter; 164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return writer; 165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public void userHasLogged(String user) { 168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen boolean isAnonymous = "".equals(StringUtils.parseName(user)); 169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen String title = 170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen "User logged (" + connection.hashCode() + "): " 171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen + (isAnonymous ? "" : StringUtils.parseBareAddress(user)) 172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen + "@" 173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen + connection.getServiceName() 174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen + ":" 175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen + connection.getPort(); 176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen title += "/" + StringUtils.parseResource(user); 177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen System.out.println(title); 178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // Add the connection listener to the connection so that the debugger can be notified 179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen // whenever the connection is closed. 180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen connection.addConnectionListener(connListener); 181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Reader getReader() { 184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return reader; 185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public Writer getWriter() { 188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return writer; 189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public PacketListener getReaderListener() { 192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return listener; 193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen 195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen public PacketListener getWriterListener() { 196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen return null; 197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen } 198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen} 199