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