18f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenpackage de.measite.smack; 28f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 38f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport org.jivesoftware.smack.debugger.SmackDebugger; 48f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport org.jivesoftware.smack.ConnectionListener; 58f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport org.jivesoftware.smack.PacketListener; 68f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport org.jivesoftware.smack.Connection; 78f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport org.jivesoftware.smack.packet.Packet; 88f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport org.jivesoftware.smack.util.*; 98f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 108f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport android.util.Log; 118f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 128f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport java.io.Reader; 138f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport java.io.Writer; 148f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport java.text.SimpleDateFormat; 158f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenimport java.util.Date; 168f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 178f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen/** 188f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * Very simple debugger that prints to the android log the sent and received stanzas. Use 198f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * this debugger with caution since printing to the console is an expensive operation that may 208f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * even block the thread since only one thread may print at a time.<p> 218f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * <p/> 228f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * It is possible to not only print the raw sent and received stanzas but also the interpreted 238f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * packets by Smack. By default interpreted packets won't be printed. To enable this feature 248f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * just change the <tt>printInterpreted</tt> static variable to <tt>true</tt>. 258f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * 268f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * @author Gaston Dombiak 278f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen */ 288f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chenpublic class AndroidDebugger implements SmackDebugger { 298f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 308f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public static boolean printInterpreted = false; 318f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private SimpleDateFormat dateFormatter = new SimpleDateFormat("hh:mm:ss aaa"); 328f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 338f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private Connection connection = null; 348f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 358f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private PacketListener listener = null; 368f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private ConnectionListener connListener = null; 378f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 388f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private Writer writer; 398f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private Reader reader; 408f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private ReaderListener readerListener; 418f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private WriterListener writerListener; 428f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 438f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public AndroidDebugger(Connection connection, Writer writer, Reader reader) { 448f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen this.connection = connection; 458f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen this.writer = writer; 468f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen this.reader = reader; 478f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen createDebug(); 488f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 498f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 508f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen /** 518f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen * Creates the listeners that will print in the console when new activity is detected. 528f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen */ 538f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen private void createDebug() { 548f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // Create a special Reader that wraps the main Reader and logs data to the GUI. 558f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ObservableReader debugReader = new ObservableReader(reader); 568f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen readerListener = new ReaderListener() { 578f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void read(String str) { 588f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", 598f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen dateFormatter.format(new Date()) + " RCV (" + connection.hashCode() + 608f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen "): " + 618f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen str); 628f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 638f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen }; 648f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen debugReader.addReaderListener(readerListener); 658f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 668f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // Create a special Writer that wraps the main Writer and logs data to the GUI. 678f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ObservableWriter debugWriter = new ObservableWriter(writer); 688f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen writerListener = new WriterListener() { 698f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void write(String str) { 708f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", 718f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen dateFormatter.format(new Date()) + " SENT (" + connection.hashCode() + 728f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen "): " + 738f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen str); 748f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 758f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen }; 768f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen debugWriter.addWriterListener(writerListener); 778f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 788f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // Assign the reader/writer objects to use the debug versions. The packet reader 798f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // and writer will use the debug versions when they are created. 808f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen reader = debugReader; 818f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen writer = debugWriter; 828f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 838f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // Create a thread that will listen for all incoming packets and write them to 848f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // the GUI. This is what we call "interpreted" packet data, since it's the packet 858f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // data as Smack sees it and not as it's coming in as raw XML. 868f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen listener = new PacketListener() { 878f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void processPacket(Packet packet) { 888f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen if (printInterpreted) { 898f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", 908f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen dateFormatter.format(new Date()) + " RCV PKT (" + 918f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen connection.hashCode() + 928f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen "): " + 938f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen packet.toXML()); 948f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 958f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 968f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen }; 978f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 988f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen connListener = new ConnectionListener() { 998f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void connectionClosed() { 1008f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", 1018f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen dateFormatter.format(new Date()) + " Connection closed (" + 1028f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen connection.hashCode() + 1038f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ")"); 1048f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1058f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 1068f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void connectionClosedOnError(Exception e) { 1078f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", 1088f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen dateFormatter.format(new Date()) + 1098f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen " Connection closed due to an exception (" + 1108f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen connection.hashCode() + 1118f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ")"); 1128f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen e.printStackTrace(); 1138f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1148f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void reconnectionFailed(Exception e) { 1158f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", 1168f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen dateFormatter.format(new Date()) + 1178f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen " Reconnection failed due to an exception (" + 1188f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen connection.hashCode() + 1198f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ")"); 1208f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen e.printStackTrace(); 1218f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1228f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void reconnectionSuccessful() { 1238f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", 1248f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen dateFormatter.format(new Date()) + " Connection reconnected (" + 1258f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen connection.hashCode() + 1268f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ")"); 1278f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1288f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void reconnectingIn(int seconds) { 1298f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", 1308f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen dateFormatter.format(new Date()) + " Connection (" + 1318f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen connection.hashCode() + 1328f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ") will reconnect in " + seconds); 1338f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1348f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen }; 1358f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1368f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 1378f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public Reader newConnectionReader(Reader newReader) { 1388f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ((ObservableReader)reader).removeReaderListener(readerListener); 1398f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ObservableReader debugReader = new ObservableReader(newReader); 1408f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen debugReader.addReaderListener(readerListener); 1418f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen reader = debugReader; 1428f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen return reader; 1438f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1448f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 1458f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public Writer newConnectionWriter(Writer newWriter) { 1468f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ((ObservableWriter)writer).removeWriterListener(writerListener); 1478f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen ObservableWriter debugWriter = new ObservableWriter(newWriter); 1488f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen debugWriter.addWriterListener(writerListener); 1498f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen writer = debugWriter; 1508f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen return writer; 1518f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1528f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 1538f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public void userHasLogged(String user) { 1548f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen boolean isAnonymous = "".equals(StringUtils.parseName(user)); 1558f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen String title = 1568f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen "User logged (" + connection.hashCode() + "): " 1578f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen + (isAnonymous ? "" : StringUtils.parseBareAddress(user)) 1588f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen + "@" 1598f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen + connection.getServiceName() 1608f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen + ":" 1618f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen + connection.getPort(); 1628f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen title += "/" + StringUtils.parseResource(user); 1638f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen Log.d("SMACK", title); 1648f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // Add the connection listener to the connection so that the debugger can be notified 1658f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen // whenever the connection is closed. 1668f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen connection.addConnectionListener(connListener); 1678f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1688f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 1698f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public Reader getReader() { 1708f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen return reader; 1718f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1728f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 1738f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public Writer getWriter() { 1748f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen return writer; 1758f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1768f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 1778f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public PacketListener getReaderListener() { 1788f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen return listener; 1798f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1808f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 1818f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen public PacketListener getWriterListener() { 1828f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen return null; 1838f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen } 1848f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen} 1858f4ce9ea0de51fee918bffe19c434612d6bbb2d7Shuyi Chen 186