1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j.lf5.viewer;
18
19 import org.apache.log4j.lf5.LogLevel;
20 import org.apache.log4j.lf5.LogRecord;
21 import org.apache.log4j.lf5.LogRecordFilter;
22 import org.apache.log4j.lf5.util.DateFormatManager;
23 import org.apache.log4j.lf5.util.LogFileParser;
24 import org.apache.log4j.lf5.util.StreamUtils;
25 import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryExplorerTree;
26 import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryPath;
27 import org.apache.log4j.lf5.viewer.configure.ConfigurationManager;
28 import org.apache.log4j.lf5.viewer.configure.MRUFileManager;
29
30 import javax.swing.*;
31 import java.awt.*;
32 import java.awt.event.ActionEvent;
33 import java.awt.event.ActionListener;
34 import java.awt.event.WindowAdapter;
35 import java.awt.event.WindowEvent;
36 import java.io.File;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.net.MalformedURLException;
40 import java.net.URL;
41 import java.util.*;
42 import java.util.List;
43
44 /***
45 * LogBrokerMonitor
46 *.
47 * @author Michael J. Sikorsky
48 * @author Robert Shaw
49 * @author Brad Marlborough
50 * @author Richard Wan
51 * @author Brent Sprecher
52 * @author Richard Hurst
53 */
54
55
56
57 public class LogBrokerMonitor {
58
59
60
61
62 public static final String DETAILED_VIEW = "Detailed";
63
64
65
66
67
68 protected JFrame _logMonitorFrame;
69 protected int _logMonitorFrameWidth = 550;
70 protected int _logMonitorFrameHeight = 500;
71 protected LogTable _table;
72 protected CategoryExplorerTree _categoryExplorerTree;
73 protected String _searchText;
74 protected String _NDCTextFilter = "";
75 protected LogLevel _leastSevereDisplayedLogLevel = LogLevel.DEBUG;
76
77 protected JScrollPane _logTableScrollPane;
78 protected JLabel _statusLabel;
79 protected Object _lock = new Object();
80 protected JComboBox _fontSizeCombo;
81
82 protected int _fontSize = 10;
83 protected String _fontName = "Dialog";
84 protected String _currentView = DETAILED_VIEW;
85
86 protected boolean _loadSystemFonts = false;
87 protected boolean _trackTableScrollPane = true;
88 protected Dimension _lastTableViewportSize;
89 protected boolean _callSystemExitOnClose = false;
90 protected List _displayedLogBrokerProperties = new Vector();
91
92 protected Map _logLevelMenuItems = new HashMap();
93 protected Map _logTableColumnMenuItems = new HashMap();
94
95 protected List _levels = null;
96 protected List _columns = null;
97 protected boolean _isDisposed = false;
98
99 protected ConfigurationManager _configurationManager = null;
100 protected MRUFileManager _mruFileManager = null;
101 protected File _fileLocation = null;
102
103
104
105
106
107
108
109
110
111 /***
112 * Construct a LogBrokerMonitor.
113 */
114 public LogBrokerMonitor(List logLevels) {
115
116 _levels = logLevels;
117 _columns = LogTableColumn.getLogTableColumns();
118
119
120
121 String callSystemExitOnClose =
122 System.getProperty("monitor.exit");
123 if (callSystemExitOnClose == null) {
124 callSystemExitOnClose = "false";
125 }
126 callSystemExitOnClose = callSystemExitOnClose.trim().toLowerCase();
127
128 if (callSystemExitOnClose.equals("true")) {
129 _callSystemExitOnClose = true;
130 }
131
132 initComponents();
133
134
135 _logMonitorFrame.addWindowListener(
136 new LogBrokerMonitorWindowAdaptor(this));
137
138 }
139
140
141
142
143
144 /***
145 * Show the frame for the LogBrokerMonitor. Dispatched to the
146 * swing thread.
147 */
148 public void show(final int delay) {
149 if (_logMonitorFrame.isVisible()) {
150 return;
151 }
152
153 SwingUtilities.invokeLater(new Runnable() {
154 public void run() {
155 Thread.yield();
156 pause(delay);
157 _logMonitorFrame.setVisible(true);
158 }
159 });
160 }
161
162 public void show() {
163 show(0);
164 }
165
166 /***
167 * Dispose of the frame for the LogBrokerMonitor.
168 */
169 public void dispose() {
170 _logMonitorFrame.dispose();
171 _isDisposed = true;
172
173 if (_callSystemExitOnClose == true) {
174 System.exit(0);
175 }
176 }
177
178 /***
179 * Hide the frame for the LogBrokerMonitor.
180 */
181 public void hide() {
182 _logMonitorFrame.setVisible(false);
183 }
184
185 /***
186 * Get the DateFormatManager for formatting dates.
187 */
188 public DateFormatManager getDateFormatManager() {
189 return _table.getDateFormatManager();
190 }
191
192 /***
193 * Set the date format manager for formatting dates.
194 */
195 public void setDateFormatManager(DateFormatManager dfm) {
196 _table.setDateFormatManager(dfm);
197 }
198
199 /***
200 * Get the value of whether or not System.exit() will be called
201 * when the LogBrokerMonitor is closed.
202 */
203 public boolean getCallSystemExitOnClose() {
204 return _callSystemExitOnClose;
205 }
206
207 /***
208 * Set the value of whether or not System.exit() will be called
209 * when the LogBrokerMonitor is closed.
210 */
211 public void setCallSystemExitOnClose(boolean callSystemExitOnClose) {
212 _callSystemExitOnClose = callSystemExitOnClose;
213 }
214
215 /***
216 * Add a log record message to be displayed in the LogTable.
217 * This method is thread-safe as it posts requests to the SwingThread
218 * rather than processing directly.
219 */
220 public void addMessage(final LogRecord lr) {
221 if (_isDisposed == true) {
222
223
224 return;
225 }
226
227 SwingUtilities.invokeLater(new Runnable() {
228 public void run() {
229 _categoryExplorerTree.getExplorerModel().addLogRecord(lr);
230 _table.getFilteredLogTableModel().addLogRecord(lr);
231 updateStatusLabel();
232 }
233 });
234 }
235
236 public void setMaxNumberOfLogRecords(int maxNumberOfLogRecords) {
237 _table.getFilteredLogTableModel().setMaxNumberOfLogRecords(maxNumberOfLogRecords);
238 }
239
240 public JFrame getBaseFrame() {
241 return _logMonitorFrame;
242 }
243
244 public void setTitle(String title) {
245 _logMonitorFrame.setTitle(title + " - LogFactor5");
246 }
247
248 public void setFrameSize(int width, int height) {
249 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
250 if (0 < width && width < screen.width) {
251 _logMonitorFrameWidth = width;
252 }
253 if (0 < height && height < screen.height) {
254 _logMonitorFrameHeight = height;
255 }
256 updateFrameSize();
257 }
258
259 public void setFontSize(int fontSize) {
260 changeFontSizeCombo(_fontSizeCombo, fontSize);
261
262
263 }
264
265 public void addDisplayedProperty(Object messageLine) {
266 _displayedLogBrokerProperties.add(messageLine);
267 }
268
269 public Map getLogLevelMenuItems() {
270 return _logLevelMenuItems;
271 }
272
273 public Map getLogTableColumnMenuItems() {
274 return _logTableColumnMenuItems;
275 }
276
277 public JCheckBoxMenuItem getTableColumnMenuItem(LogTableColumn column) {
278 return getLogTableColumnMenuItem(column);
279 }
280
281 public CategoryExplorerTree getCategoryExplorerTree() {
282 return _categoryExplorerTree;
283 }
284
285
286
287 public String getNDCTextFilter() {
288 return _NDCTextFilter;
289 }
290
291
292
293
294 public void setNDCLogRecordFilter(String textFilter) {
295 _table.getFilteredLogTableModel().
296 setLogRecordFilter(createNDCLogRecordFilter(textFilter));
297 }
298
299
300
301
302 protected void setSearchText(String text) {
303 _searchText = text;
304 }
305
306
307 protected void setNDCTextFilter(String text) {
308
309
310 if (text == null) {
311 _NDCTextFilter = "";
312 } else {
313 _NDCTextFilter = text;
314 }
315 }
316
317
318
319
320 protected void sortByNDC() {
321 String text = _NDCTextFilter;
322 if (text == null || text.length() == 0) {
323 return;
324 }
325
326
327 _table.getFilteredLogTableModel().
328 setLogRecordFilter(createNDCLogRecordFilter(text));
329 }
330
331 protected void findSearchText() {
332 String text = _searchText;
333 if (text == null || text.length() == 0) {
334 return;
335 }
336 int startRow = getFirstSelectedRow();
337 int foundRow = findRecord(
338 startRow,
339 text,
340 _table.getFilteredLogTableModel().getFilteredRecords()
341 );
342 selectRow(foundRow);
343 }
344
345 protected int getFirstSelectedRow() {
346 return _table.getSelectionModel().getMinSelectionIndex();
347 }
348
349 protected void selectRow(int foundRow) {
350 if (foundRow == -1) {
351 String message = _searchText + " not found.";
352 JOptionPane.showMessageDialog(
353 _logMonitorFrame,
354 message,
355 "Text not found",
356 JOptionPane.INFORMATION_MESSAGE
357 );
358 return;
359 }
360 LF5SwingUtils.selectRow(foundRow, _table, _logTableScrollPane);
361 }
362
363 protected int findRecord(
364 int startRow,
365 String searchText,
366 List records
367 ) {
368 if (startRow < 0) {
369 startRow = 0;
370 } else {
371 startRow++;
372 }
373 int len = records.size();
374
375 for (int i = startRow; i < len; i++) {
376 if (matches((LogRecord) records.get(i), searchText)) {
377 return i;
378 }
379 }
380
381 len = startRow;
382 for (int i = 0; i < len; i++) {
383 if (matches((LogRecord) records.get(i), searchText)) {
384 return i;
385 }
386 }
387
388 return -1;
389 }
390
391 /***
392 * Check to see if the any records contain the search string.
393 * Searching now supports NDC messages and date.
394 */
395 protected boolean matches(LogRecord record, String text) {
396 String message = record.getMessage();
397 String NDC = record.getNDC();
398
399 if (message == null && NDC == null || text == null) {
400 return false;
401 }
402 if (message.toLowerCase().indexOf(text.toLowerCase()) == -1 &&
403 NDC.toLowerCase().indexOf(text.toLowerCase()) == -1) {
404 return false;
405 }
406
407 return true;
408 }
409
410 /***
411 * When the fontsize of a JTextArea is changed, the word-wrapped lines
412 * may become garbled. This method clears and resets the text of the
413 * text area.
414 */
415 protected void refresh(JTextArea textArea) {
416 String text = textArea.getText();
417 textArea.setText("");
418 textArea.setText(text);
419 }
420
421 protected void refreshDetailTextArea() {
422 refresh(_table._detailTextArea);
423 }
424
425 protected void clearDetailTextArea() {
426 _table._detailTextArea.setText("");
427 }
428
429 /***
430 * Changes the font selection in the combo box and returns the
431 * size actually selected.
432 * @return -1 if unable to select an appropriate font
433 */
434 protected int changeFontSizeCombo(JComboBox box, int requestedSize) {
435 int len = box.getItemCount();
436 int currentValue;
437 Object currentObject;
438 Object selectedObject = box.getItemAt(0);
439 int selectedValue = Integer.parseInt(String.valueOf(selectedObject));
440 for (int i = 0; i < len; i++) {
441 currentObject = box.getItemAt(i);
442 currentValue = Integer.parseInt(String.valueOf(currentObject));
443 if (selectedValue < currentValue && currentValue <= requestedSize) {
444 selectedValue = currentValue;
445 selectedObject = currentObject;
446 }
447 }
448 box.setSelectedItem(selectedObject);
449 return selectedValue;
450 }
451
452 /***
453 * Does not update gui or cause any events to be fired.
454 */
455 protected void setFontSizeSilently(int fontSize) {
456 _fontSize = fontSize;
457 setFontSize(_table._detailTextArea, fontSize);
458 selectRow(0);
459 setFontSize(_table, fontSize);
460 }
461
462 protected void setFontSize(Component component, int fontSize) {
463 Font oldFont = component.getFont();
464 Font newFont =
465 new Font(oldFont.getFontName(), oldFont.getStyle(), fontSize);
466 component.setFont(newFont);
467 }
468
469 protected void updateFrameSize() {
470 _logMonitorFrame.setSize(_logMonitorFrameWidth, _logMonitorFrameHeight);
471 centerFrame(_logMonitorFrame);
472 }
473
474 protected void pause(int millis) {
475 try {
476 Thread.sleep(millis);
477 } catch (InterruptedException e) {
478
479 }
480 }
481
482 protected void initComponents() {
483
484
485
486 _logMonitorFrame = new JFrame("LogFactor5");
487
488 _logMonitorFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
489
490 String resource =
491 "/org/apache/log4j/lf5/viewer/images/lf5_small_icon.gif";
492 URL lf5IconURL = getClass().getResource(resource);
493
494 if (lf5IconURL != null) {
495 _logMonitorFrame.setIconImage(new ImageIcon(lf5IconURL).getImage());
496 }
497 updateFrameSize();
498
499
500
501
502 JTextArea detailTA = createDetailTextArea();
503 JScrollPane detailTAScrollPane = new JScrollPane(detailTA);
504 _table = new LogTable(detailTA);
505 setView(_currentView, _table);
506 _table.setFont(new Font(_fontName, Font.PLAIN, _fontSize));
507 _logTableScrollPane = new JScrollPane(_table);
508
509 if (_trackTableScrollPane) {
510 _logTableScrollPane.getVerticalScrollBar().addAdjustmentListener(
511 new TrackingAdjustmentListener()
512 );
513 }
514
515
516
517
518
519 JSplitPane tableViewerSplitPane = new JSplitPane();
520 tableViewerSplitPane.setOneTouchExpandable(true);
521 tableViewerSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
522 tableViewerSplitPane.setLeftComponent(_logTableScrollPane);
523 tableViewerSplitPane.setRightComponent(detailTAScrollPane);
524
525
526
527
528
529
530
531 tableViewerSplitPane.setDividerLocation(350);
532
533
534
535
536
537 _categoryExplorerTree = new CategoryExplorerTree();
538
539 _table.getFilteredLogTableModel().setLogRecordFilter(createLogRecordFilter());
540
541 JScrollPane categoryExplorerTreeScrollPane =
542 new JScrollPane(_categoryExplorerTree);
543 categoryExplorerTreeScrollPane.setPreferredSize(new Dimension(130, 400));
544
545
546 _mruFileManager = new MRUFileManager();
547
548
549
550
551
552 JSplitPane splitPane = new JSplitPane();
553 splitPane.setOneTouchExpandable(true);
554 splitPane.setRightComponent(tableViewerSplitPane);
555 splitPane.setLeftComponent(categoryExplorerTreeScrollPane);
556
557 splitPane.setDividerLocation(130);
558
559
560
561
562 _logMonitorFrame.getRootPane().setJMenuBar(createMenuBar());
563 _logMonitorFrame.getContentPane().add(splitPane, BorderLayout.CENTER);
564 _logMonitorFrame.getContentPane().add(createToolBar(),
565 BorderLayout.NORTH);
566 _logMonitorFrame.getContentPane().add(createStatusArea(),
567 BorderLayout.SOUTH);
568
569 makeLogTableListenToCategoryExplorer();
570 addTableModelProperties();
571
572
573
574
575 _configurationManager = new ConfigurationManager(this, _table);
576
577 }
578
579 protected LogRecordFilter createLogRecordFilter() {
580 LogRecordFilter result = new LogRecordFilter() {
581 public boolean passes(LogRecord record) {
582 CategoryPath path = new CategoryPath(record.getCategory());
583 return
584 getMenuItem(record.getLevel()).isSelected() &&
585 _categoryExplorerTree.getExplorerModel().isCategoryPathActive(path);
586 }
587 };
588 return result;
589 }
590
591
592
593 protected LogRecordFilter createNDCLogRecordFilter(String text) {
594 _NDCTextFilter = text;
595 LogRecordFilter result = new LogRecordFilter() {
596 public boolean passes(LogRecord record) {
597 String NDC = record.getNDC();
598 CategoryPath path = new CategoryPath(record.getCategory());
599 if (NDC == null || _NDCTextFilter == null) {
600 return false;
601 } else if (NDC.toLowerCase().indexOf(_NDCTextFilter.toLowerCase()) == -1) {
602 return false;
603 } else {
604 return getMenuItem(record.getLevel()).isSelected() &&
605 _categoryExplorerTree.getExplorerModel().isCategoryPathActive(path);
606 }
607 }
608 };
609
610 return result;
611 }
612
613
614 protected void updateStatusLabel() {
615 _statusLabel.setText(getRecordsDisplayedMessage());
616 }
617
618 protected String getRecordsDisplayedMessage() {
619 FilteredLogTableModel model = _table.getFilteredLogTableModel();
620 return getStatusText(model.getRowCount(), model.getTotalRowCount());
621 }
622
623 protected void addTableModelProperties() {
624 final FilteredLogTableModel model = _table.getFilteredLogTableModel();
625
626 addDisplayedProperty(new Object() {
627 public String toString() {
628 return getRecordsDisplayedMessage();
629 }
630 });
631 addDisplayedProperty(new Object() {
632 public String toString() {
633 return "Maximum number of displayed LogRecords: "
634 + model._maxNumberOfLogRecords;
635 }
636 });
637 }
638
639 protected String getStatusText(int displayedRows, int totalRows) {
640 StringBuffer result = new StringBuffer();
641 result.append("Displaying: ");
642 result.append(displayedRows);
643 result.append(" records out of a total of: ");
644 result.append(totalRows);
645 result.append(" records.");
646 return result.toString();
647 }
648
649 protected void makeLogTableListenToCategoryExplorer() {
650 ActionListener listener = new ActionListener() {
651 public void actionPerformed(ActionEvent e) {
652 _table.getFilteredLogTableModel().refresh();
653 updateStatusLabel();
654 }
655 };
656 _categoryExplorerTree.getExplorerModel().addActionListener(listener);
657 }
658
659 protected JPanel createStatusArea() {
660 JPanel statusArea = new JPanel();
661 JLabel status =
662 new JLabel("No log records to display.");
663 _statusLabel = status;
664 status.setHorizontalAlignment(JLabel.LEFT);
665
666 statusArea.setBorder(BorderFactory.createEtchedBorder());
667 statusArea.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
668 statusArea.add(status);
669
670 return (statusArea);
671 }
672
673 protected JTextArea createDetailTextArea() {
674 JTextArea detailTA = new JTextArea();
675 detailTA.setFont(new Font("Monospaced", Font.PLAIN, 14));
676 detailTA.setTabSize(3);
677 detailTA.setLineWrap(true);
678 detailTA.setWrapStyleWord(false);
679 return (detailTA);
680 }
681
682 protected JMenuBar createMenuBar() {
683 JMenuBar menuBar = new JMenuBar();
684 menuBar.add(createFileMenu());
685 menuBar.add(createEditMenu());
686 menuBar.add(createLogLevelMenu());
687 menuBar.add(createViewMenu());
688 menuBar.add(createConfigureMenu());
689 menuBar.add(createHelpMenu());
690
691 return (menuBar);
692 }
693
694 protected JMenu createLogLevelMenu() {
695 JMenu result = new JMenu("Log Level");
696 result.setMnemonic('l');
697 Iterator levels = getLogLevels();
698 while (levels.hasNext()) {
699 result.add(getMenuItem((LogLevel) levels.next()));
700 }
701
702 result.addSeparator();
703 result.add(createAllLogLevelsMenuItem());
704 result.add(createNoLogLevelsMenuItem());
705 result.addSeparator();
706 result.add(createLogLevelColorMenu());
707 result.add(createResetLogLevelColorMenuItem());
708
709 return result;
710 }
711
712 protected JMenuItem createAllLogLevelsMenuItem() {
713 JMenuItem result = new JMenuItem("Show all LogLevels");
714 result.setMnemonic('s');
715 result.addActionListener(new ActionListener() {
716 public void actionPerformed(ActionEvent e) {
717 selectAllLogLevels(true);
718 _table.getFilteredLogTableModel().refresh();
719 updateStatusLabel();
720 }
721 });
722 return result;
723 }
724
725 protected JMenuItem createNoLogLevelsMenuItem() {
726 JMenuItem result = new JMenuItem("Hide all LogLevels");
727 result.setMnemonic('h');
728 result.addActionListener(new ActionListener() {
729 public void actionPerformed(ActionEvent e) {
730 selectAllLogLevels(false);
731 _table.getFilteredLogTableModel().refresh();
732 updateStatusLabel();
733 }
734 });
735 return result;
736 }
737
738 protected JMenu createLogLevelColorMenu() {
739 JMenu colorMenu = new JMenu("Configure LogLevel Colors");
740 colorMenu.setMnemonic('c');
741 Iterator levels = getLogLevels();
742 while (levels.hasNext()) {
743 colorMenu.add(createSubMenuItem((LogLevel) levels.next()));
744 }
745
746 return colorMenu;
747 }
748
749 protected JMenuItem createResetLogLevelColorMenuItem() {
750 JMenuItem result = new JMenuItem("Reset LogLevel Colors");
751 result.setMnemonic('r');
752 result.addActionListener(new ActionListener() {
753 public void actionPerformed(ActionEvent e) {
754
755 LogLevel.resetLogLevelColorMap();
756
757
758 _table.getFilteredLogTableModel().refresh();
759 }
760 });
761 return result;
762 }
763
764 protected void selectAllLogLevels(boolean selected) {
765 Iterator levels = getLogLevels();
766 while (levels.hasNext()) {
767 getMenuItem((LogLevel) levels.next()).setSelected(selected);
768 }
769 }
770
771 protected JCheckBoxMenuItem getMenuItem(LogLevel level) {
772 JCheckBoxMenuItem result = (JCheckBoxMenuItem) (_logLevelMenuItems.get(level));
773 if (result == null) {
774 result = createMenuItem(level);
775 _logLevelMenuItems.put(level, result);
776 }
777 return result;
778 }
779
780 protected JMenuItem createSubMenuItem(LogLevel level) {
781 final JMenuItem result = new JMenuItem(level.toString());
782 final LogLevel logLevel = level;
783 result.setMnemonic(level.toString().charAt(0));
784 result.addActionListener(new ActionListener() {
785 public void actionPerformed(ActionEvent e) {
786 showLogLevelColorChangeDialog(result, logLevel);
787 }
788 });
789
790 return result;
791
792 }
793
794 protected void showLogLevelColorChangeDialog(JMenuItem result, LogLevel level) {
795 JMenuItem menuItem = result;
796 Color newColor = JColorChooser.showDialog(
797 _logMonitorFrame,
798 "Choose LogLevel Color",
799 result.getForeground());
800
801 if (newColor != null) {
802
803 level.setLogLevelColorMap(level, newColor);
804 _table.getFilteredLogTableModel().refresh();
805 }
806
807 }
808
809 protected JCheckBoxMenuItem createMenuItem(LogLevel level) {
810 JCheckBoxMenuItem result = new JCheckBoxMenuItem(level.toString());
811 result.setSelected(true);
812 result.setMnemonic(level.toString().charAt(0));
813 result.addActionListener(new ActionListener() {
814 public void actionPerformed(ActionEvent e) {
815 _table.getFilteredLogTableModel().refresh();
816 updateStatusLabel();
817 }
818 });
819 return result;
820 }
821
822
823 protected JMenu createViewMenu() {
824 JMenu result = new JMenu("View");
825 result.setMnemonic('v');
826 Iterator columns = getLogTableColumns();
827 while (columns.hasNext()) {
828 result.add(getLogTableColumnMenuItem((LogTableColumn) columns.next()));
829 }
830
831 result.addSeparator();
832 result.add(createAllLogTableColumnsMenuItem());
833 result.add(createNoLogTableColumnsMenuItem());
834 return result;
835 }
836
837 protected JCheckBoxMenuItem getLogTableColumnMenuItem(LogTableColumn column) {
838 JCheckBoxMenuItem result = (JCheckBoxMenuItem) (_logTableColumnMenuItems.get(column));
839 if (result == null) {
840 result = createLogTableColumnMenuItem(column);
841 _logTableColumnMenuItems.put(column, result);
842 }
843 return result;
844 }
845
846 protected JCheckBoxMenuItem createLogTableColumnMenuItem(LogTableColumn column) {
847 JCheckBoxMenuItem result = new JCheckBoxMenuItem(column.toString());
848
849 result.setSelected(true);
850 result.setMnemonic(column.toString().charAt(0));
851 result.addActionListener(new ActionListener() {
852 public void actionPerformed(ActionEvent e) {
853
854 List selectedColumns = updateView();
855 _table.setView(selectedColumns);
856 }
857 });
858 return result;
859 }
860
861 protected List updateView() {
862 ArrayList updatedList = new ArrayList();
863 Iterator columnIterator = _columns.iterator();
864 while (columnIterator.hasNext()) {
865 LogTableColumn column = (LogTableColumn) columnIterator.next();
866 JCheckBoxMenuItem result = getLogTableColumnMenuItem(column);
867
868 if (result.isSelected()) {
869 updatedList.add(column);
870 }
871 }
872
873 return updatedList;
874 }
875
876 protected JMenuItem createAllLogTableColumnsMenuItem() {
877 JMenuItem result = new JMenuItem("Show all Columns");
878 result.setMnemonic('s');
879 result.addActionListener(new ActionListener() {
880 public void actionPerformed(ActionEvent e) {
881 selectAllLogTableColumns(true);
882
883 List selectedColumns = updateView();
884 _table.setView(selectedColumns);
885 }
886 });
887 return result;
888 }
889
890 protected JMenuItem createNoLogTableColumnsMenuItem() {
891 JMenuItem result = new JMenuItem("Hide all Columns");
892 result.setMnemonic('h');
893 result.addActionListener(new ActionListener() {
894 public void actionPerformed(ActionEvent e) {
895 selectAllLogTableColumns(false);
896
897 List selectedColumns = updateView();
898 _table.setView(selectedColumns);
899 }
900 });
901 return result;
902 }
903
904 protected void selectAllLogTableColumns(boolean selected) {
905 Iterator columns = getLogTableColumns();
906 while (columns.hasNext()) {
907 getLogTableColumnMenuItem((LogTableColumn) columns.next()).setSelected(selected);
908 }
909 }
910
911 protected JMenu createFileMenu() {
912 JMenu fileMenu = new JMenu("File");
913 fileMenu.setMnemonic('f');
914 JMenuItem exitMI;
915 fileMenu.add(createOpenMI());
916 fileMenu.add(createOpenURLMI());
917 fileMenu.addSeparator();
918 fileMenu.add(createCloseMI());
919 createMRUFileListMI(fileMenu);
920 fileMenu.addSeparator();
921 fileMenu.add(createExitMI());
922 return fileMenu;
923 }
924
925 /***
926 * Menu item added to allow log files to be opened with
927 * the LF5 GUI.
928 */
929 protected JMenuItem createOpenMI() {
930 JMenuItem result = new JMenuItem("Open...");
931 result.setMnemonic('o');
932 result.addActionListener(new ActionListener() {
933 public void actionPerformed(ActionEvent e) {
934 requestOpen();
935 }
936 });
937 return result;
938 }
939
940 /***
941 * Menu item added to allow log files loaded from a URL
942 * to be opened by the LF5 GUI.
943 */
944 protected JMenuItem createOpenURLMI() {
945 JMenuItem result = new JMenuItem("Open URL...");
946 result.setMnemonic('u');
947 result.addActionListener(new ActionListener() {
948 public void actionPerformed(ActionEvent e) {
949 requestOpenURL();
950 }
951 });
952 return result;
953 }
954
955 protected JMenuItem createCloseMI() {
956 JMenuItem result = new JMenuItem("Close");
957 result.setMnemonic('c');
958 result.setAccelerator(KeyStroke.getKeyStroke("control Q"));
959 result.addActionListener(new ActionListener() {
960 public void actionPerformed(ActionEvent e) {
961 requestClose();
962 }
963 });
964 return result;
965 }
966
967 /***
968 * Creates a Most Recently Used file list to be
969 * displayed in the File menu
970 */
971 protected void createMRUFileListMI(JMenu menu) {
972
973 String[] files = _mruFileManager.getMRUFileList();
974
975 if (files != null) {
976 menu.addSeparator();
977 for (int i = 0; i < files.length; i++) {
978 JMenuItem result = new JMenuItem((i + 1) + " " + files[i]);
979 result.setMnemonic(i + 1);
980 result.addActionListener(new ActionListener() {
981 public void actionPerformed(ActionEvent e) {
982 requestOpenMRU(e);
983 }
984 });
985 menu.add(result);
986 }
987 }
988 }
989
990 protected JMenuItem createExitMI() {
991 JMenuItem result = new JMenuItem("Exit");
992 result.setMnemonic('x');
993 result.addActionListener(new ActionListener() {
994 public void actionPerformed(ActionEvent e) {
995 requestExit();
996 }
997 });
998 return result;
999 }
1000
1001 protected JMenu createConfigureMenu() {
1002 JMenu configureMenu = new JMenu("Configure");
1003 configureMenu.setMnemonic('c');
1004 configureMenu.add(createConfigureSave());
1005 configureMenu.add(createConfigureReset());
1006 configureMenu.add(createConfigureMaxRecords());
1007
1008 return configureMenu;
1009 }
1010
1011 protected JMenuItem createConfigureSave() {
1012 JMenuItem result = new JMenuItem("Save");
1013 result.setMnemonic('s');
1014 result.addActionListener(new ActionListener() {
1015 public void actionPerformed(ActionEvent e) {
1016 saveConfiguration();
1017 }
1018 });
1019
1020 return result;
1021 }
1022
1023 protected JMenuItem createConfigureReset() {
1024 JMenuItem result = new JMenuItem("Reset");
1025 result.setMnemonic('r');
1026 result.addActionListener(new ActionListener() {
1027 public void actionPerformed(ActionEvent e) {
1028 resetConfiguration();
1029 }
1030 });
1031
1032 return result;
1033 }
1034
1035 protected JMenuItem createConfigureMaxRecords() {
1036 JMenuItem result = new JMenuItem("Set Max Number of Records");
1037 result.setMnemonic('m');
1038 result.addActionListener(new ActionListener() {
1039 public void actionPerformed(ActionEvent e) {
1040 setMaxRecordConfiguration();
1041 }
1042 });
1043
1044 return result;
1045 }
1046
1047
1048 protected void saveConfiguration() {
1049 _configurationManager.save();
1050 }
1051
1052 protected void resetConfiguration() {
1053 _configurationManager.reset();
1054 }
1055
1056 protected void setMaxRecordConfiguration() {
1057 LogFactor5InputDialog inputDialog = new LogFactor5InputDialog(
1058 getBaseFrame(), "Set Max Number of Records", "", 10);
1059
1060 String temp = inputDialog.getText();
1061
1062 if (temp != null) {
1063 try {
1064 setMaxNumberOfLogRecords(Integer.parseInt(temp));
1065 } catch (NumberFormatException e) {
1066 LogFactor5ErrorDialog error = new LogFactor5ErrorDialog(
1067 getBaseFrame(),
1068 "'" + temp + "' is an invalid parameter.\nPlease try again.");
1069 setMaxRecordConfiguration();
1070 }
1071 }
1072 }
1073
1074
1075 protected JMenu createHelpMenu() {
1076 JMenu helpMenu = new JMenu("Help");
1077 helpMenu.setMnemonic('h');
1078 helpMenu.add(createHelpProperties());
1079 return helpMenu;
1080 }
1081
1082 protected JMenuItem createHelpProperties() {
1083 final String title = "LogFactor5 Properties";
1084 final JMenuItem result = new JMenuItem(title);
1085 result.setMnemonic('l');
1086 result.addActionListener(new ActionListener() {
1087 public void actionPerformed(ActionEvent e) {
1088 showPropertiesDialog(title);
1089 }
1090 });
1091 return result;
1092 }
1093
1094 protected void showPropertiesDialog(String title) {
1095 JOptionPane.showMessageDialog(
1096 _logMonitorFrame,
1097 _displayedLogBrokerProperties.toArray(),
1098 title,
1099 JOptionPane.PLAIN_MESSAGE
1100 );
1101 }
1102
1103 protected JMenu createEditMenu() {
1104 JMenu editMenu = new JMenu("Edit");
1105 editMenu.setMnemonic('e');
1106 editMenu.add(createEditFindMI());
1107 editMenu.add(createEditFindNextMI());
1108 editMenu.addSeparator();
1109 editMenu.add(createEditSortNDCMI());
1110 editMenu.add(createEditRestoreAllNDCMI());
1111 return editMenu;
1112 }
1113
1114 protected JMenuItem createEditFindNextMI() {
1115 JMenuItem editFindNextMI = new JMenuItem("Find Next");
1116 editFindNextMI.setMnemonic('n');
1117 editFindNextMI.setAccelerator(KeyStroke.getKeyStroke("F3"));
1118 editFindNextMI.addActionListener(new ActionListener() {
1119 public void actionPerformed(ActionEvent e) {
1120 findSearchText();
1121 }
1122 });
1123 return editFindNextMI;
1124 }
1125
1126 protected JMenuItem createEditFindMI() {
1127 JMenuItem editFindMI = new JMenuItem("Find");
1128 editFindMI.setMnemonic('f');
1129 editFindMI.setAccelerator(KeyStroke.getKeyStroke("control F"));
1130
1131 editFindMI.addActionListener(
1132 new ActionListener() {
1133 public void actionPerformed(ActionEvent e) {
1134 String inputValue =
1135 JOptionPane.showInputDialog(
1136 _logMonitorFrame,
1137 "Find text: ",
1138 "Search Record Messages",
1139 JOptionPane.QUESTION_MESSAGE
1140 );
1141 setSearchText(inputValue);
1142 findSearchText();
1143 }
1144 }
1145
1146 );
1147 return editFindMI;
1148 }
1149
1150
1151
1152
1153 protected JMenuItem createEditSortNDCMI() {
1154 JMenuItem editSortNDCMI = new JMenuItem("Sort by NDC");
1155 editSortNDCMI.setMnemonic('s');
1156 editSortNDCMI.addActionListener(
1157 new ActionListener() {
1158 public void actionPerformed(ActionEvent e) {
1159 String inputValue =
1160 JOptionPane.showInputDialog(
1161 _logMonitorFrame,
1162 "Sort by this NDC: ",
1163 "Sort Log Records by NDC",
1164 JOptionPane.QUESTION_MESSAGE
1165 );
1166 setNDCTextFilter(inputValue);
1167 sortByNDC();
1168 _table.getFilteredLogTableModel().refresh();
1169 updateStatusLabel();
1170 }
1171 }
1172
1173 );
1174 return editSortNDCMI;
1175 }
1176
1177
1178
1179 protected JMenuItem createEditRestoreAllNDCMI() {
1180 JMenuItem editRestoreAllNDCMI = new JMenuItem("Restore all NDCs");
1181 editRestoreAllNDCMI.setMnemonic('r');
1182 editRestoreAllNDCMI.addActionListener(
1183 new ActionListener() {
1184 public void actionPerformed(ActionEvent e) {
1185 _table.getFilteredLogTableModel().setLogRecordFilter(createLogRecordFilter());
1186
1187 setNDCTextFilter("");
1188 _table.getFilteredLogTableModel().refresh();
1189 updateStatusLabel();
1190 }
1191 }
1192 );
1193 return editRestoreAllNDCMI;
1194 }
1195
1196 protected JToolBar createToolBar() {
1197 JToolBar tb = new JToolBar();
1198 tb.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
1199 JComboBox fontCombo = new JComboBox();
1200 JComboBox fontSizeCombo = new JComboBox();
1201 _fontSizeCombo = fontSizeCombo;
1202
1203 ClassLoader cl = this.getClass().getClassLoader();
1204 if(cl == null) {
1205 cl = ClassLoader.getSystemClassLoader();
1206 }
1207 URL newIconURL = cl.getResource("org/apache/log4j/lf5/viewer/" +
1208 "images/channelexplorer_new.gif");
1209
1210 ImageIcon newIcon = null;
1211
1212 if (newIconURL != null) {
1213 newIcon = new ImageIcon(newIconURL);
1214 }
1215
1216 JButton newButton = new JButton("Clear Log Table");
1217
1218 if (newIcon != null) {
1219 newButton.setIcon(newIcon);
1220 }
1221
1222 newButton.setToolTipText("Clear Log Table.");
1223
1224
1225 newButton.addActionListener(
1226 new ActionListener() {
1227 public void actionPerformed(ActionEvent e) {
1228 _table.clearLogRecords();
1229 _categoryExplorerTree.getExplorerModel().resetAllNodeCounts();
1230 updateStatusLabel();
1231 clearDetailTextArea();
1232 LogRecord.resetSequenceNumber();
1233 }
1234 }
1235 );
1236
1237 Toolkit tk = Toolkit.getDefaultToolkit();
1238
1239
1240 String[] fonts;
1241
1242 if (_loadSystemFonts) {
1243 fonts = GraphicsEnvironment.
1244 getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
1245 } else {
1246 fonts = tk.getFontList();
1247 }
1248
1249 for (int j = 0; j < fonts.length; j++) {
1250 fontCombo.addItem(fonts[j]);
1251 }
1252
1253 fontCombo.setSelectedItem(_fontName);
1254
1255 fontCombo.addActionListener(
1256
1257 new ActionListener() {
1258 public void actionPerformed(ActionEvent e) {
1259 JComboBox box = (JComboBox) e.getSource();
1260 String font = (String) box.getSelectedItem();
1261 _table.setFont(new Font(font, Font.PLAIN, _fontSize));
1262 _fontName = font;
1263 }
1264 }
1265 );
1266
1267 fontSizeCombo.addItem("8");
1268 fontSizeCombo.addItem("9");
1269 fontSizeCombo.addItem("10");
1270 fontSizeCombo.addItem("12");
1271 fontSizeCombo.addItem("14");
1272 fontSizeCombo.addItem("16");
1273 fontSizeCombo.addItem("18");
1274 fontSizeCombo.addItem("24");
1275
1276 fontSizeCombo.setSelectedItem(String.valueOf(_fontSize));
1277 fontSizeCombo.addActionListener(
1278 new ActionListener() {
1279 public void actionPerformed(ActionEvent e) {
1280 JComboBox box = (JComboBox) e.getSource();
1281 String size = (String) box.getSelectedItem();
1282 int s = Integer.valueOf(size).intValue();
1283
1284 setFontSizeSilently(s);
1285 refreshDetailTextArea();
1286 _fontSize = s;
1287 }
1288 }
1289 );
1290
1291 tb.add(new JLabel(" Font: "));
1292 tb.add(fontCombo);
1293 tb.add(fontSizeCombo);
1294 tb.addSeparator();
1295 tb.addSeparator();
1296 tb.add(newButton);
1297
1298 newButton.setAlignmentY(0.5f);
1299 newButton.setAlignmentX(0.5f);
1300
1301 fontCombo.setMaximumSize(fontCombo.getPreferredSize());
1302 fontSizeCombo.setMaximumSize(
1303 fontSizeCombo.getPreferredSize());
1304
1305 return (tb);
1306 }
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322 protected void setView(String viewString, LogTable table) {
1323 if (DETAILED_VIEW.equals(viewString)) {
1324 table.setDetailedView();
1325 } else {
1326 String message = viewString + "does not match a supported view.";
1327 throw new IllegalArgumentException(message);
1328 }
1329 _currentView = viewString;
1330 }
1331
1332 protected JComboBox createLogLevelCombo() {
1333 JComboBox result = new JComboBox();
1334 Iterator levels = getLogLevels();
1335 while (levels.hasNext()) {
1336 result.addItem(levels.next());
1337 }
1338 result.setSelectedItem(_leastSevereDisplayedLogLevel);
1339
1340 result.addActionListener(new ActionListener() {
1341 public void actionPerformed(ActionEvent e) {
1342 JComboBox box = (JComboBox) e.getSource();
1343 LogLevel level = (LogLevel) box.getSelectedItem();
1344 setLeastSevereDisplayedLogLevel(level);
1345 }
1346 });
1347 result.setMaximumSize(result.getPreferredSize());
1348 return result;
1349 }
1350
1351 protected void setLeastSevereDisplayedLogLevel(LogLevel level) {
1352 if (level == null || _leastSevereDisplayedLogLevel == level) {
1353 return;
1354 }
1355 _leastSevereDisplayedLogLevel = level;
1356 _table.getFilteredLogTableModel().refresh();
1357 updateStatusLabel();
1358 }
1359
1360 /***
1361 * Ensures that the Table's ScrollPane Viewport will "track" with updates
1362 * to the Table. When the vertical scroll bar is at its bottom anchor
1363 * and tracking is enabled then viewport will stay at the bottom most
1364 * point of the component. The purpose of this feature is to allow
1365 * a developer to watch the table as messages arrive and not have to
1366 * scroll after each new message arrives. When the vertical scroll bar
1367 * is at any other location, then no tracking will happen.
1368 * @deprecated tracking is now done automatically.
1369 */
1370 protected void trackTableScrollPane() {
1371
1372 }
1373
1374 protected void centerFrame(JFrame frame) {
1375 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1376 Dimension comp = frame.getSize();
1377
1378 frame.setLocation(((screen.width - comp.width) / 2),
1379 ((screen.height - comp.height) / 2));
1380
1381 }
1382
1383 /***
1384 * Uses a JFileChooser to select a file to opened with the
1385 * LF5 GUI.
1386 */
1387 protected void requestOpen() {
1388 JFileChooser chooser;
1389
1390 if (_fileLocation == null) {
1391 chooser = new JFileChooser();
1392 } else {
1393 chooser = new JFileChooser(_fileLocation);
1394 }
1395
1396 int returnVal = chooser.showOpenDialog(_logMonitorFrame);
1397 if (returnVal == JFileChooser.APPROVE_OPTION) {
1398 File f = chooser.getSelectedFile();
1399 if (loadLogFile(f)) {
1400 _fileLocation = chooser.getSelectedFile();
1401 _mruFileManager.set(f);
1402 updateMRUList();
1403 }
1404 }
1405 }
1406
1407 /***
1408 * Uses a Dialog box to accept a URL to a file to be opened
1409 * with the LF5 GUI.
1410 */
1411 protected void requestOpenURL() {
1412 LogFactor5InputDialog inputDialog = new LogFactor5InputDialog(
1413 getBaseFrame(), "Open URL", "URL:");
1414 String temp = inputDialog.getText();
1415
1416 if (temp != null) {
1417 if (temp.indexOf("://") == -1) {
1418 temp = "http://" + temp;
1419 }
1420
1421 try {
1422 URL url = new URL(temp);
1423 if (loadLogFile(url)) {
1424 _mruFileManager.set(url);
1425 updateMRUList();
1426 }
1427 } catch (MalformedURLException e) {
1428 LogFactor5ErrorDialog error = new LogFactor5ErrorDialog(
1429 getBaseFrame(), "Error reading URL.");
1430 }
1431 }
1432 }
1433
1434 /***
1435 * Removes old file list and creates a new file list
1436 * with the updated MRU list.
1437 */
1438 protected void updateMRUList() {
1439 JMenu menu = _logMonitorFrame.getJMenuBar().getMenu(0);
1440 menu.removeAll();
1441 menu.add(createOpenMI());
1442 menu.add(createOpenURLMI());
1443 menu.addSeparator();
1444 menu.add(createCloseMI());
1445 createMRUFileListMI(menu);
1446 menu.addSeparator();
1447 menu.add(createExitMI());
1448 }
1449
1450 protected void requestClose() {
1451 setCallSystemExitOnClose(false);
1452 closeAfterConfirm();
1453 }
1454
1455 /***
1456 * Opens a file in the MRU list.
1457 */
1458 protected void requestOpenMRU(ActionEvent e) {
1459 String file = e.getActionCommand();
1460 StringTokenizer st = new StringTokenizer(file);
1461 String num = st.nextToken().trim();
1462 file = st.nextToken("\n");
1463
1464 try {
1465 int index = Integer.parseInt(num) - 1;
1466
1467 InputStream in = _mruFileManager.getInputStream(index);
1468 LogFileParser lfp = new LogFileParser(in);
1469 lfp.parse(this);
1470
1471 _mruFileManager.moveToTop(index);
1472 updateMRUList();
1473
1474 } catch (Exception me) {
1475 LogFactor5ErrorDialog error = new LogFactor5ErrorDialog(
1476 getBaseFrame(), "Unable to load file " + file);
1477 }
1478
1479 }
1480
1481 protected void requestExit() {
1482 _mruFileManager.save();
1483 setCallSystemExitOnClose(true);
1484 closeAfterConfirm();
1485 }
1486
1487 protected void closeAfterConfirm() {
1488 StringBuffer message = new StringBuffer();
1489
1490 if (_callSystemExitOnClose == false) {
1491 message.append("Are you sure you want to close the logging ");
1492 message.append("console?\n");
1493 message.append("(Note: This will not shut down the Virtual Machine,\n");
1494 message.append("or the Swing event thread.)");
1495 } else {
1496 message.append("Are you sure you want to exit?\n");
1497 message.append("This will shut down the Virtual Machine.\n");
1498 }
1499
1500 String title =
1501 "Are you sure you want to dispose of the Logging Console?";
1502
1503 if (_callSystemExitOnClose == true) {
1504 title = "Are you sure you want to exit?";
1505 }
1506 int value = JOptionPane.showConfirmDialog(
1507 _logMonitorFrame,
1508 message.toString(),
1509 title,
1510 JOptionPane.OK_CANCEL_OPTION,
1511 JOptionPane.QUESTION_MESSAGE,
1512 null
1513 );
1514
1515 if (value == JOptionPane.OK_OPTION) {
1516 dispose();
1517 }
1518 }
1519
1520 protected Iterator getLogLevels() {
1521 return _levels.iterator();
1522 }
1523
1524 protected Iterator getLogTableColumns() {
1525 return _columns.iterator();
1526 }
1527
1528 /***
1529 * Loads and parses a log file.
1530 */
1531 protected boolean loadLogFile(File file) {
1532 boolean ok = false;
1533 try {
1534 LogFileParser lfp = new LogFileParser(file);
1535 lfp.parse(this);
1536 ok = true;
1537 } catch (IOException e) {
1538 LogFactor5ErrorDialog error = new LogFactor5ErrorDialog(
1539 getBaseFrame(), "Error reading " + file.getName());
1540 }
1541
1542 return ok;
1543 }
1544
1545 /***
1546 * Loads a parses a log file running on a server.
1547 */
1548 protected boolean loadLogFile(URL url) {
1549 boolean ok = false;
1550 try {
1551 LogFileParser lfp = new LogFileParser(url.openStream());
1552 lfp.parse(this);
1553 ok = true;
1554 } catch (IOException e) {
1555 LogFactor5ErrorDialog error = new LogFactor5ErrorDialog(
1556 getBaseFrame(), "Error reading URL:" + url.getFile());
1557 }
1558 return ok;
1559 }
1560
1561
1562
1563
1564
1565
1566
1567
1568 class LogBrokerMonitorWindowAdaptor extends WindowAdapter {
1569 protected LogBrokerMonitor _monitor;
1570
1571 public LogBrokerMonitorWindowAdaptor(LogBrokerMonitor monitor) {
1572 _monitor = monitor;
1573 }
1574
1575 public void windowClosing(WindowEvent ev) {
1576 _monitor.requestClose();
1577 }
1578 }
1579 }
1580
1581