KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > smackx > debugger > EnhancedDebugger


1 /**
2  * $RCSfile$
3  * $Revision: 2730 $
4  * $Date: 2005-08-26 23:23:36 -0300 (Fri, 26 Aug 2005) $
5  *
6  * Copyright 2003-2004 Jive Software.
7  *
8  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */

20
21 package org.jivesoftware.smackx.debugger;
22
23 import java.awt.*;
24 import java.awt.datatransfer.*;
25 import java.awt.event.*;
26 import java.io.*;
27 import java.net.*;
28 import java.text.*;
29 import java.util.Date JavaDoc;
30
31 import javax.swing.*;
32 import javax.swing.event.*;
33 import javax.swing.table.*;
34 import javax.xml.transform.*;
35 import javax.xml.transform.stream.*;
36
37 import org.jivesoftware.smack.*;
38 import org.jivesoftware.smack.debugger.*;
39 import org.jivesoftware.smack.packet.*;
40 import org.jivesoftware.smack.util.*;
41
42 /**
43  * The EnhancedDebugger is a debugger that allows to debug sent, received and interpreted messages
44  * but also provides the ability to send ad-hoc messages composed by the user.<p>
45  *
46  * A new EnhancedDebugger will be created for each connection to debug. All the EnhancedDebuggers
47  * will be shown in the same debug window provided by the class EnhancedDebuggerWindow.
48  *
49  * @author Gaston Dombiak
50  */

51 public class EnhancedDebugger implements SmackDebugger {
52
53     private static final String JavaDoc NEWLINE = "\n";
54
55     private static ImageIcon packetReceivedIcon;
56     private static ImageIcon packetSentIcon;
57     private static ImageIcon presencePacketIcon;
58     private static ImageIcon iqPacketIcon;
59     private static ImageIcon messagePacketIcon;
60     private static ImageIcon unknownPacketTypeIcon;
61
62     {
63         URL url;
64         // Load the image icons
65
url =
66             Thread.currentThread().getContextClassLoader().getResource("images/nav_left_blue.png");
67         if (url != null) {
68             packetReceivedIcon = new ImageIcon(url);
69         }
70         url =
71             Thread.currentThread().getContextClassLoader().getResource("images/nav_right_red.png");
72         if (url != null) {
73             packetSentIcon = new ImageIcon(url);
74         }
75         url =
76             Thread.currentThread().getContextClassLoader().getResource("images/photo_portrait.png");
77         if (url != null) {
78             presencePacketIcon = new ImageIcon(url);
79         }
80         url =
81             Thread.currentThread().getContextClassLoader().getResource(
82                 "images/question_and_answer.png");
83         if (url != null) {
84             iqPacketIcon = new ImageIcon(url);
85         }
86         url = Thread.currentThread().getContextClassLoader().getResource("images/message.png");
87         if (url != null) {
88             messagePacketIcon = new ImageIcon(url);
89         }
90         url = Thread.currentThread().getContextClassLoader().getResource("images/unknown.png");
91         if (url != null) {
92             unknownPacketTypeIcon = new ImageIcon(url);
93         }
94     }
95
96     private DefaultTableModel messagesTable = null;
97     private JTextArea messageTextArea = null;
98     private JFormattedTextField userField = null;
99     private JFormattedTextField statusField = null;
100
101     private XMPPConnection connection = null;
102
103     private PacketListener packetReaderListener = null;
104     private PacketListener packetWriterListener = null;
105     private ConnectionListener connListener = null;
106
107     private Writer writer;
108     private Reader reader;
109     private ReaderListener readerListener;
110     private WriterListener writerListener;
111
112     private Date JavaDoc creationTime = new Date JavaDoc();
113
114     // Statistics variables
115
private DefaultTableModel statisticsTable = null;
116     private int sentPackets = 0;
117     private int receivedPackets = 0;
118     private int sentIQPackets = 0;
119     private int receivedIQPackets = 0;
120     private int sentMessagePackets = 0;
121     private int receivedMessagePackets = 0;
122     private int sentPresencePackets = 0;
123     private int receivedPresencePackets = 0;
124     private int sentOtherPackets = 0;
125     private int receivedOtherPackets = 0;
126
127     JTabbedPane tabbedPane;
128
129     public EnhancedDebugger(XMPPConnection connection, Writer writer, Reader reader) {
130         this.connection = connection;
131         this.writer = writer;
132         this.reader = reader;
133         createDebug();
134         EnhancedDebuggerWindow.addDebugger(this);
135     }
136
137     /**
138      * Creates the debug process, which is a GUI window that displays XML traffic.
139      */

140     private void createDebug() {
141         // We'll arrange the UI into six tabs. The first tab contains all data, the second
142
// client generated XML, the third server generated XML, the fourth allows to send
143
// ad-hoc messages and the fifth contains connection information.
144
tabbedPane = new JTabbedPane();
145
146         // Add the All Packets, Sent, Received and Interpreted panels
147
addBasicPanels();
148
149         // Add the panel to send ad-hoc messages
150
addAdhocPacketPanel();
151
152         // Add the connection information panel
153
addInformationPanel();
154
155         // Create a thread that will listen for all incoming packets and write them to
156
// the GUI. This is what we call "interpreted" packet data, since it's the packet
157
// data as Smack sees it and not as it's coming in as raw XML.
158
packetReaderListener = new PacketListener() {
159             SimpleDateFormat dateFormatter = new SimpleDateFormat("hh:mm:ss aaa");
160             public void processPacket(Packet packet) {
161                 addReadPacketToTable(dateFormatter, packet);
162             }
163         };
164
165         // Create a thread that will listen for all outgoing packets and write them to
166
// the GUI.
167
packetWriterListener = new PacketListener() {
168             SimpleDateFormat dateFormatter = new SimpleDateFormat("hh:mm:ss aaa");
169             public void processPacket(Packet packet) {
170                 addSentPacketToTable(dateFormatter, packet);
171             }
172         };
173
174         // Create a thread that will listen for any connection closed event
175
connListener = new ConnectionListener() {
176             public void connectionClosed() {
177                 statusField.setValue("Closed");
178                 EnhancedDebuggerWindow.connectionClosed(EnhancedDebugger.this);
179             }
180
181             public void connectionClosedOnError(Exception JavaDoc e) {
182                 statusField.setValue("Closed due to an exception");
183                 EnhancedDebuggerWindow.connectionClosedOnError(EnhancedDebugger.this, e);
184             }
185         };
186     }
187
188     private void addBasicPanels() {
189         JPanel allPane = new JPanel();
190         allPane.setLayout(new GridLayout(2, 1));
191         tabbedPane.add("All Packets", allPane);
192         tabbedPane.setToolTipTextAt(0, "Sent and received packets processed by Smack");
193
194         messagesTable =
195             new DefaultTableModel(
196                 new Object JavaDoc[] { "Hide", "Timestamp", "", "", "Message", "Id", "Type", "To", "From" },
197                 0) {
198             public boolean isCellEditable(int rowIndex, int mColIndex) {
199                 return false;
200             }
201             public Class JavaDoc getColumnClass(int columnIndex) {
202                 if (columnIndex == 2 || columnIndex == 3) {
203                     return Icon.class;
204                 }
205                 return super.getColumnClass(columnIndex);
206             }
207
208         };
209         JTable table = new JTable(messagesTable);
210         // Allow only single a selection
211
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
212         // Hide the first column
213
table.getColumnModel().getColumn(0).setMaxWidth(0);
214         table.getColumnModel().getColumn(0).setMinWidth(0);
215         table.getTableHeader().getColumnModel().getColumn(0).setMaxWidth(0);
216         table.getTableHeader().getColumnModel().getColumn(0).setMinWidth(0);
217         // Set the column "timestamp" size
218
table.getColumnModel().getColumn(1).setMaxWidth(300);
219         table.getColumnModel().getColumn(1).setPreferredWidth(70);
220         // Set the column "direction" icon size
221
table.getColumnModel().getColumn(2).setMaxWidth(50);
222         table.getColumnModel().getColumn(2).setPreferredWidth(30);
223         // Set the column "packet type" icon size
224
table.getColumnModel().getColumn(3).setMaxWidth(50);
225         table.getColumnModel().getColumn(3).setPreferredWidth(30);
226         // Set the column "Id" size
227
table.getColumnModel().getColumn(5).setMaxWidth(100);
228         table.getColumnModel().getColumn(5).setPreferredWidth(55);
229         // Set the column "type" size
230
table.getColumnModel().getColumn(6).setMaxWidth(200);
231         table.getColumnModel().getColumn(6).setPreferredWidth(50);
232         // Set the column "to" size
233
table.getColumnModel().getColumn(7).setMaxWidth(300);
234         table.getColumnModel().getColumn(7).setPreferredWidth(90);
235         // Set the column "from" size
236
table.getColumnModel().getColumn(8).setMaxWidth(300);
237         table.getColumnModel().getColumn(8).setPreferredWidth(90);
238         // Create a table listener that listen for row selection events
239
SelectionListener selectionListener = new SelectionListener(table);
240         table.getSelectionModel().addListSelectionListener(selectionListener);
241         table.getColumnModel().getSelectionModel().addListSelectionListener(selectionListener);
242         allPane.add(new JScrollPane(table));
243         messageTextArea = new JTextArea();
244         messageTextArea.setEditable(false);
245         // Add pop-up menu.
246
JPopupMenu menu = new JPopupMenu();
247         JMenuItem menuItem1 = new JMenuItem("Copy");
248         menuItem1.addActionListener(new ActionListener() {
249             public void actionPerformed(ActionEvent e) {
250                 // Get the clipboard
251
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
252                 // Set the sent text as the new content of the clipboard
253
clipboard.setContents(new StringSelection(messageTextArea.getText()), null);
254             }
255         });
256         menu.add(menuItem1);
257         // Add listener to the text area so the popup menu can come up.
258
messageTextArea.addMouseListener(new PopupListener(menu));
259         allPane.add(new JScrollPane(messageTextArea));
260
261         // Create UI elements for client generated XML traffic.
262
final JTextArea sentText = new JTextArea();
263         sentText.setEditable(false);
264         sentText.setForeground(new Color(112, 3, 3));
265         tabbedPane.add("Raw Sent Packets", new JScrollPane(sentText));
266         tabbedPane.setToolTipTextAt(1, "Raw text of the sent packets");
267
268         // Add pop-up menu.
269
menu = new JPopupMenu();
270         menuItem1 = new JMenuItem("Copy");
271         menuItem1.addActionListener(new ActionListener() {
272             public void actionPerformed(ActionEvent e) {
273                 // Get the clipboard
274
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
275                 // Set the sent text as the new content of the clipboard
276
clipboard.setContents(new StringSelection(sentText.getText()), null);
277             }
278         });
279
280         JMenuItem menuItem2 = new JMenuItem("Clear");
281         menuItem2.addActionListener(new ActionListener() {
282             public void actionPerformed(ActionEvent e) {
283                 sentText.setText("");
284             }
285         });
286
287         // Add listener to the text area so the popup menu can come up.
288
sentText.addMouseListener(new PopupListener(menu));
289         menu.add(menuItem1);
290         menu.add(menuItem2);
291
292         // Create UI elements for server generated XML traffic.
293
final JTextArea receivedText = new JTextArea();
294         receivedText.setEditable(false);
295         receivedText.setForeground(new Color(6, 76, 133));
296         tabbedPane.add("Raw Received Packets", new JScrollPane(receivedText));
297         tabbedPane.setToolTipTextAt(
298             2,
299             "Raw text of the received packets before Smack process them");
300
301         // Add pop-up menu.
302
menu = new JPopupMenu();
303         menuItem1 = new JMenuItem("Copy");
304         menuItem1.addActionListener(new ActionListener() {
305             public void actionPerformed(ActionEvent e) {
306                 // Get the clipboard
307
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
308                 // Set the sent text as the new content of the clipboard
309
clipboard.setContents(new StringSelection(receivedText.getText()), null);
310             }
311         });
312
313         menuItem2 = new JMenuItem("Clear");
314         menuItem2.addActionListener(new ActionListener() {
315             public void actionPerformed(ActionEvent e) {
316                 receivedText.setText("");
317             }
318         });
319
320         // Add listener to the text area so the popup menu can come up.
321
receivedText.addMouseListener(new PopupListener(menu));
322         menu.add(menuItem1);
323         menu.add(menuItem2);
324
325         // Create a special Reader that wraps the main Reader and logs data to the GUI.
326
ObservableReader debugReader = new ObservableReader(reader);
327         readerListener = new ReaderListener() {
328                     public void read(String JavaDoc str) {
329                         int index = str.lastIndexOf(">");
330                         if (index != -1) {
331                             receivedText.append(str.substring(0, index + 1));
332                             receivedText.append(NEWLINE);
333                             if (str.length() > index) {
334                                 receivedText.append(str.substring(index + 1));
335                             }
336                         }
337                         else {
338                             receivedText.append(str);
339                         }
340                     }
341                 };
342         debugReader.addReaderListener(readerListener);
343
344         // Create a special Writer that wraps the main Writer and logs data to the GUI.
345
ObservableWriter debugWriter = new ObservableWriter(writer);
346         writerListener = new WriterListener() {
347                     public void write(String JavaDoc str) {
348                         sentText.append(str);
349                         if (str.endsWith(">")) {
350                             sentText.append(NEWLINE);
351                         }
352                     }
353                 };
354         debugWriter.addWriterListener(writerListener);
355
356         // Assign the reader/writer objects to use the debug versions. The packet reader
357
// and writer will use the debug versions when they are created.
358
reader = debugReader;
359         writer = debugWriter;
360
361     }
362
363     private void addAdhocPacketPanel() {
364         // Create UI elements for sending ad-hoc messages.
365
final JTextArea adhocMessages = new JTextArea();
366         adhocMessages.setEditable(true);
367         adhocMessages.setForeground(new Color(1, 94, 35));
368         tabbedPane.add("Ad-hoc message", new JScrollPane(adhocMessages));
369         tabbedPane.setToolTipTextAt(3, "Panel that allows you to send adhoc packets");
370
371         // Add pop-up menu.
372
JPopupMenu menu = new JPopupMenu();
373         JMenuItem menuItem = new JMenuItem("Message");
374         menuItem.addActionListener(new ActionListener() {
375             public void actionPerformed(ActionEvent e) {
376                 adhocMessages.setText(
377                     "<message to=\"\" id=\""
378                         + StringUtils.randomString(5)
379                         + "-X\"><body></body></message>");
380             }
381         });
382         menu.add(menuItem);
383
384         menuItem = new JMenuItem("IQ Get");
385         menuItem.addActionListener(new ActionListener() {
386             public void actionPerformed(ActionEvent e) {
387                 adhocMessages.setText(
388                     "<iq type=\"get\" to=\"\" id=\""
389                         + StringUtils.randomString(5)
390                         + "-X\"><query xmlns=\"\"></query></iq>");
391             }
392         });
393         menu.add(menuItem);
394
395         menuItem = new JMenuItem("IQ Set");
396         menuItem.addActionListener(new ActionListener() {
397             public void actionPerformed(ActionEvent e) {
398                 adhocMessages.setText(
399                     "<iq type=\"set\" to=\"\" id=\""
400                         + StringUtils.randomString(5)
401                         + "-X\"><query xmlns=\"\"></query></iq>");
402             }
403         });
404         menu.add(menuItem);
405
406         menuItem = new JMenuItem("Presence");
407         menuItem.addActionListener(new ActionListener() {
408             public void actionPerformed(ActionEvent e) {
409                 adhocMessages.setText(
410                     "<presence to=\"\" id=\"" + StringUtils.randomString(5) + "-X\"/>");
411             }
412         });
413         menu.add(menuItem);
414         menu.addSeparator();
415
416         menuItem = new JMenuItem("Send");
417         menuItem.addActionListener(new ActionListener() {
418             public void actionPerformed(ActionEvent e) {
419                 if (!"".equals(adhocMessages.getText())) {
420                     AdHocPacket packetToSend = new AdHocPacket(adhocMessages.getText());
421                     connection.sendPacket(packetToSend);
422                 }
423             }
424         });
425         menu.add(menuItem);
426
427         menuItem = new JMenuItem("Clear");
428         menuItem.addActionListener(new ActionListener() {
429             public void actionPerformed(ActionEvent e) {
430                 adhocMessages.setText(null);
431             }
432         });
433         menu.add(menuItem);
434
435         // Add listener to the text area so the popup menu can come up.
436
adhocMessages.addMouseListener(new PopupListener(menu));
437     }
438
439     private void addInformationPanel() {
440         // Create UI elements for connection information.
441
JPanel informationPanel = new JPanel();
442         informationPanel.setLayout(new BorderLayout());
443
444         // Add the Host information
445
JPanel connPanel = new JPanel();
446         connPanel.setLayout(new GridBagLayout());
447         connPanel.setBorder(BorderFactory.createTitledBorder("Connection information"));
448
449         JLabel label = new JLabel("Host: ");
450         label.setMinimumSize(new java.awt.Dimension JavaDoc(150, 14));
451         label.setMaximumSize(new java.awt.Dimension JavaDoc(150, 14));
452         connPanel.add(
453             label,
454             new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, 21, 0, new Insets(0, 0, 0, 0), 0, 0));
455         JFormattedTextField field = new JFormattedTextField(connection.getServiceName());
456         field.setMinimumSize(new java.awt.Dimension JavaDoc(150, 20));
457         field.setMaximumSize(new java.awt.Dimension JavaDoc(150, 20));
458         field.setEditable(false);
459         field.setBorder(null);
460         connPanel.add(
461             field,
462             new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, 10, 2, new Insets(0, 0, 0, 0), 0, 0));
463
464         // Add the Port information
465
label = new JLabel("Port: ");
466         label.setMinimumSize(new java.awt.Dimension JavaDoc(150, 14));
467         label.setMaximumSize(new java.awt.Dimension JavaDoc(150, 14));
468         connPanel.add(
469             label,
470             new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, 21, 0, new Insets(0, 0, 0, 0), 0, 0));
471         field = new JFormattedTextField(new Integer JavaDoc(connection.getPort()));
472         field.setMinimumSize(new java.awt.Dimension JavaDoc(150, 20));
473         field.setMaximumSize(new java.awt.Dimension JavaDoc(150, 20));
474         field.setEditable(false);
475         field.setBorder(null);
476         connPanel.add(
477             field,
478             new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, 10, 2, new Insets(0, 0, 0, 0), 0, 0));
479
480         // Add the connection's User information
481
label = new JLabel("User: ");
482         label.setMinimumSize(new java.awt.Dimension JavaDoc(150, 14));
483         label.setMaximumSize(new java.awt.Dimension JavaDoc(150, 14));
484         connPanel.add(
485             label,
486             new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, 21, 0, new Insets(0, 0, 0, 0), 0, 0));
487         userField = new JFormattedTextField();
488         userField.setMinimumSize(new java.awt.Dimension JavaDoc(150, 20));
489         userField.setMaximumSize(new java.awt.Dimension JavaDoc(150, 20));
490         userField.setEditable(false);
491         userField.setBorder(null);
492         connPanel.add(
493             userField,
494             new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, 10, 2, new Insets(0, 0, 0, 0), 0, 0));
495
496         // Add the connection's creationTime information
497
label = new JLabel("Creation time: ");
498         label.setMinimumSize(new java.awt.Dimension JavaDoc(150, 14));
499         label.setMaximumSize(new java.awt.Dimension JavaDoc(150, 14));
500         connPanel.add(
501             label,
502             new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, 21, 0, new Insets(0, 0, 0, 0), 0, 0));
503         field = new JFormattedTextField(new SimpleDateFormat("yyyy.MM.dd hh:mm:ss aaa"));
504         field.setMinimumSize(new java.awt.Dimension JavaDoc(150, 20));
505         field.setMaximumSize(new java.awt.Dimension JavaDoc(150, 20));
506         field.setValue(creationTime);
507         field.setEditable(false);
508         field.setBorder(null);
509         connPanel.add(
510             field,
511             new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, 10, 2, new Insets(0, 0, 0, 0), 0, 0));
512
513         // Add the connection's creationTime information
514
label = new JLabel("Status: ");
515         label.setMinimumSize(new java.awt.Dimension JavaDoc(150, 14));
516         label.setMaximumSize(new java.awt.Dimension JavaDoc(150, 14));
517         connPanel.add(
518             label,
519             new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, 21, 0, new Insets(0, 0, 0, 0), 0, 0));
520         statusField = new JFormattedTextField();
521         statusField.setMinimumSize(new java.awt.Dimension JavaDoc(150, 20));
522         statusField.setMaximumSize(new java.awt.Dimension JavaDoc(150, 20));
523         statusField.setValue("Active");
524         statusField.setEditable(false);
525         statusField.setBorder(null);
526         connPanel.add(
527             statusField,
528             new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, 10, 2, new Insets(0, 0, 0, 0), 0, 0));
529         // Add the connection panel to the information panel
530
informationPanel.add(connPanel, BorderLayout.NORTH);
531
532         // Add the Number of sent packets information
533
JPanel packetsPanel = new JPanel();
534         packetsPanel.setLayout(new GridLayout(1, 1));
535         packetsPanel.setBorder(BorderFactory.createTitledBorder("Transmitted Packets"));
536
537         statisticsTable =
538             new DefaultTableModel(new Object JavaDoc[][] { { "IQ", new Integer JavaDoc(0), new Integer JavaDoc(0)}, {
539                 "Message", new Integer JavaDoc(0), new Integer JavaDoc(0)
540                 }, {
541                 "Presence", new Integer JavaDoc(0), new Integer JavaDoc(0)
542                 }, {
543                 "Other", new Integer JavaDoc(0), new Integer JavaDoc(0)
544                 }, {
545                 "Total", new Integer JavaDoc(0), new Integer JavaDoc(0)
546                 }
547         }, new Object JavaDoc[] { "Type", "Received", "Sent" }) {
548             public boolean isCellEditable(int rowIndex, int mColIndex) {
549                 return false;
550             }
551         };
552         JTable table = new JTable(statisticsTable);
553         // Allow only single a selection
554
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
555         packetsPanel.add(new JScrollPane(table));
556
557         // Add the packets panel to the information panel
558
informationPanel.add(packetsPanel, BorderLayout.CENTER);
559
560         tabbedPane.add("Information", new JScrollPane(informationPanel));
561         tabbedPane.setToolTipTextAt(4, "Information and statistics about the debugged connection");
562     }
563
564     public Reader newConnectionReader(Reader newReader) {
565         ((ObservableReader)reader).removeReaderListener(readerListener);
566         ObservableReader debugReader = new ObservableReader(newReader);
567         debugReader.addReaderListener(readerListener);
568         reader = debugReader;
569         return reader;
570     }
571
572     public Writer newConnectionWriter(Writer newWriter) {
573         ((ObservableWriter)writer).removeWriterListener(writerListener);
574         ObservableWriter debugWriter = new ObservableWriter(newWriter);
575         debugWriter.addWriterListener(writerListener);
576         writer = debugWriter;
577         return writer;
578     }
579
580     public void userHasLogged(String JavaDoc user) {
581         userField.setText(user);
582         EnhancedDebuggerWindow.userHasLogged(this, user);
583         // Add the connection listener to the connection so that the debugger can be notified
584
// whenever the connection is closed.
585
connection.addConnectionListener(connListener);
586     }
587
588     public Reader getReader() {
589         return reader;
590     }
591
592     public Writer getWriter() {
593         return writer;
594     }
595
596     public PacketListener getReaderListener() {
597         return packetReaderListener;
598     }
599
600     public PacketListener getWriterListener() {
601         return packetWriterListener;
602     }
603
604     /**
605      * Updates the statistics table
606      */

607     private void updateStatistics() {
608         statisticsTable.setValueAt(new Integer JavaDoc(receivedIQPackets), 0, 1);
609         statisticsTable.setValueAt(new Integer JavaDoc(sentIQPackets), 0, 2);
610
611         statisticsTable.setValueAt(new Integer JavaDoc(receivedMessagePackets), 1, 1);
612         statisticsTable.setValueAt(new Integer JavaDoc(sentMessagePackets), 1, 2);
613
614         statisticsTable.setValueAt(new Integer JavaDoc(receivedPresencePackets), 2, 1);
615         statisticsTable.setValueAt(new Integer JavaDoc(sentPresencePackets), 2, 2);
616
617         statisticsTable.setValueAt(new Integer JavaDoc(receivedOtherPackets), 3, 1);
618         statisticsTable.setValueAt(new Integer JavaDoc(sentOtherPackets), 3, 2);
619
620         statisticsTable.setValueAt(new Integer JavaDoc(receivedPackets), 4, 1);
621         statisticsTable.setValueAt(new Integer JavaDoc(sentPackets), 4, 2);
622     }
623
624     /**
625      * Adds the received packet detail to the messages table.
626      *
627      * @param dateFormatter the SimpleDateFormat to use to format Dates
628      * @param packet the read packet to add to the table
629      */

630     private void addReadPacketToTable(SimpleDateFormat dateFormatter, Packet packet) {
631         String JavaDoc messageType = null;
632         String JavaDoc from = packet.getFrom();
633         String JavaDoc type = "";
634         Icon packetTypeIcon;
635         receivedPackets++;
636         if (packet instanceof IQ) {
637             packetTypeIcon = iqPacketIcon;
638             messageType = "IQ Received (class=" + packet.getClass().getName() + ")";
639             type = ((IQ) packet).getType().toString();
640             receivedIQPackets++;
641         }
642         else if (packet instanceof Message) {
643             packetTypeIcon = messagePacketIcon;
644             messageType = "Message Received";
645             type = ((Message) packet).getType().toString();
646             receivedMessagePackets++;
647         }
648         else if (packet instanceof Presence) {
649             packetTypeIcon = presencePacketIcon;
650             messageType = "Presence Received";
651             type = ((Presence) packet).getType().toString();
652             receivedPresencePackets++;
653         }
654         else {
655             packetTypeIcon = unknownPacketTypeIcon;
656             messageType = packet.getClass().getName() + " Received";
657             receivedOtherPackets++;
658         }
659
660         messagesTable.addRow(
661             new Object JavaDoc[] {
662                 formatXML(packet.toXML()),
663                 dateFormatter.format(new Date JavaDoc()),
664                 packetReceivedIcon,
665                 packetTypeIcon,
666                 messageType,
667                 packet.getPacketID(),
668                 type,
669                 "",
670                 from });
671         // Update the statistics table
672
updateStatistics();
673     }
674
675     /**
676      * Adds the sent packet detail to the messages table.
677      *
678      * @param dateFormatter the SimpleDateFormat to use to format Dates
679      * @param packet the sent packet to add to the table
680      */

681     private void addSentPacketToTable(SimpleDateFormat dateFormatter, Packet packet) {
682         String JavaDoc messageType = null;
683         String JavaDoc to = packet.getTo();
684         String JavaDoc type = "";
685         Icon packetTypeIcon;
686         sentPackets++;
687         if (packet instanceof IQ) {
688             packetTypeIcon = iqPacketIcon;
689             messageType = "IQ Sent (class=" + packet.getClass().getName() + ")";
690             type = ((IQ) packet).getType().toString();
691             sentIQPackets++;
692         }
693         else if (packet instanceof Message) {
694             packetTypeIcon = messagePacketIcon;
695             messageType = "Message Sent";
696             type = ((Message) packet).getType().toString();
697             sentMessagePackets++;
698         }
699         else if (packet instanceof Presence) {
700             packetTypeIcon = presencePacketIcon;
701             messageType = "Presence Sent";
702             type = ((Presence) packet).getType().toString();
703             sentPresencePackets++;
704         }
705         else {
706             packetTypeIcon = unknownPacketTypeIcon;
707             messageType = packet.getClass().getName() + " Sent";
708             sentOtherPackets++;
709         }
710
711         messagesTable.addRow(
712             new Object JavaDoc[] {
713                 formatXML(packet.toXML()),
714                 dateFormatter.format(new Date JavaDoc()),
715                 packetSentIcon,
716                 packetTypeIcon,
717                 messageType,
718                 packet.getPacketID(),
719                 type,
720                 to,
721                 "" });
722
723         // Update the statistics table
724
updateStatistics();
725     }
726
727     private String JavaDoc formatXML(String JavaDoc str) {
728         try {
729             // Use a Transformer for output
730
TransformerFactory tFactory = TransformerFactory.newInstance();
731             // Surround this setting in a try/catch for compatibility with Java 1.4. This setting is required
732
// for Java 1.5
733
try {
734                 tFactory.setAttribute("indent-number", new Integer JavaDoc(2));
735             }
736             catch (IllegalArgumentException JavaDoc e) {}
737             Transformer transformer = tFactory.newTransformer();
738             transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
739             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
740             transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
741
742             // Transform the requested string into a nice formatted XML string
743
StreamSource source = new StreamSource(new StringReader(str));
744             StringWriter sw = new StringWriter();
745             StreamResult result = new StreamResult(sw);
746             transformer.transform(source, result);
747             return sw.toString();
748
749         }
750         catch (TransformerConfigurationException tce) {
751             // Error generated by the parser
752
System.out.println("\n** Transformer Factory error");
753             System.out.println(" " + tce.getMessage());
754
755             // Use the contained exception, if any
756
Throwable JavaDoc x = tce;
757             if (tce.getException() != null)
758                 x = tce.getException();
759             x.printStackTrace();
760
761         }
762         catch (TransformerException te) {
763             // Error generated by the parser
764
System.out.println("\n** Transformation error");
765             System.out.println(" " + te.getMessage());
766
767             // Use the contained exception, if any
768
Throwable JavaDoc x = te;
769             if (te.getException() != null)
770                 x = te.getException();
771             x.printStackTrace();
772
773         }
774         return str;
775     }
776     
777     /**
778      * Returns true if the debugger's connection with the server is up and running.
779      *
780      * @return true if the connection with the server is active.
781      */

782     boolean isConnectionActive() {
783         return connection.isConnected();
784     }
785
786     /**
787      * Stops debugging the connection. Removes any listener on the connection.
788      *
789      */

790     void cancel() {
791         connection.removeConnectionListener(connListener);
792         connection.removePacketListener(packetReaderListener);
793         connection.removePacketWriterListener(packetWriterListener);
794         ((ObservableReader)reader).removeReaderListener(readerListener);
795         ((ObservableWriter)writer).removeWriterListener(writerListener);
796         messagesTable = null;
797     }
798
799     /**
800      * An ad-hoc packet is like any regular packet but with the exception that it's intention is
801      * to be used only <b>to send packets</b>.<p>
802      *
803      * The whole text to send must be passed to the constructor. This implies that the client of
804      * this class is responsible for sending a valid text to the constructor.
805      *
806      */

807     private class AdHocPacket extends Packet {
808
809         private String JavaDoc text;
810
811         /**
812          * Create a new AdHocPacket with the text to send. The passed text must be a valid text to
813          * send to the server, no validation will be done on the passed text.
814          *
815          * @param text the whole text of the packet to send
816          */

817         public AdHocPacket(String JavaDoc text) {
818             this.text = text;
819         }
820
821         public String JavaDoc toXML() {
822             return text;
823         }
824
825     }
826
827     /**
828      * Listens for debug window popup dialog events.
829      */

830     private class PopupListener extends MouseAdapter {
831         JPopupMenu popup;
832
833         PopupListener(JPopupMenu popupMenu) {
834             popup = popupMenu;
835         }
836
837         public void mousePressed(MouseEvent e) {
838             maybeShowPopup(e);
839         }
840
841         public void mouseReleased(MouseEvent e) {
842             maybeShowPopup(e);
843         }
844
845         private void maybeShowPopup(MouseEvent e) {
846             if (e.isPopupTrigger()) {
847                 popup.show(e.getComponent(), e.getX(), e.getY());
848             }
849         }
850     }
851
852     private class SelectionListener implements ListSelectionListener {
853         JTable table;
854
855         // It is necessary to keep the table since it is not possible
856
// to determine the table from the event's source
857
SelectionListener(JTable table) {
858             this.table = table;
859         }
860         public void valueChanged(ListSelectionEvent e) {
861             if (table.getSelectedRow() == -1) {
862                 // Clear the messageTextArea since there is none packet selected
863
messageTextArea.setText(null);
864             }
865             else {
866                 // Set the detail of the packet in the messageTextArea
867
messageTextArea.setText(
868                     (String JavaDoc) table.getModel().getValueAt(table.getSelectedRow(), 0));
869                 // Scroll up to the top
870
messageTextArea.setCaretPosition(0);
871             }
872         }
873     }
874 }
875
Popular Tags