KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > log4j > lf5 > viewer > LogBrokerMonitor


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.log4j.lf5.viewer;
17
18 import org.apache.log4j.lf5.LogLevel;
19 import org.apache.log4j.lf5.LogRecord;
20 import org.apache.log4j.lf5.LogRecordFilter;
21 import org.apache.log4j.lf5.util.DateFormatManager;
22 import org.apache.log4j.lf5.util.LogFileParser;
23 import org.apache.log4j.lf5.util.StreamUtils;
24 import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryExplorerTree;
25 import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryPath;
26 import org.apache.log4j.lf5.viewer.configure.ConfigurationManager;
27 import org.apache.log4j.lf5.viewer.configure.MRUFileManager;
28
29 import javax.swing.*;
30 import java.awt.*;
31 import java.awt.event.ActionEvent JavaDoc;
32 import java.awt.event.ActionListener JavaDoc;
33 import java.awt.event.WindowAdapter JavaDoc;
34 import java.awt.event.WindowEvent JavaDoc;
35 import java.io.File JavaDoc;
36 import java.io.IOException JavaDoc;
37 import java.io.InputStream JavaDoc;
38 import java.net.MalformedURLException JavaDoc;
39 import java.net.URL JavaDoc;
40 import java.util.*;
41 import java.util.List JavaDoc;
42
43 /**
44  * LogBrokerMonitor
45  *.
46  * @author Michael J. Sikorsky
47  * @author Robert Shaw
48  * @author Brad Marlborough
49  * @author Richard Wan
50  * @author Brent Sprecher
51  * @author Richard Hurst
52  */

53
54 // Contributed by ThoughtWorks Inc.
55

56 public class LogBrokerMonitor {
57   //--------------------------------------------------------------------------
58
// Constants:
59
//--------------------------------------------------------------------------
60

61   public static final String JavaDoc DETAILED_VIEW = "Detailed";
62 // public static final String STANDARD_VIEW = "Standard";
63
// public static final String COMPACT_VIEW = "Compact";
64
//--------------------------------------------------------------------------
65
// Protected Variables:
66
//--------------------------------------------------------------------------
67
protected JFrame _logMonitorFrame;
68   protected int _logMonitorFrameWidth = 550;
69   protected int _logMonitorFrameHeight = 500;
70   protected LogTable _table;
71   protected CategoryExplorerTree _categoryExplorerTree;
72   protected String JavaDoc _searchText;
73   protected String JavaDoc _NDCTextFilter = "";
74   protected LogLevel _leastSevereDisplayedLogLevel = LogLevel.DEBUG;
75
76   protected JScrollPane _logTableScrollPane;
77   protected JLabel _statusLabel;
78   protected Object JavaDoc _lock = new Object JavaDoc();
79   protected JComboBox _fontSizeCombo;
80
81   protected int _fontSize = 10;
82   protected String JavaDoc _fontName = "Dialog";
83   protected String JavaDoc _currentView = DETAILED_VIEW;
84
85   protected boolean _loadSystemFonts = false;
86   protected boolean _trackTableScrollPane = true;
87   protected Dimension _lastTableViewportSize;
88   protected boolean _callSystemExitOnClose = false;
89   protected List JavaDoc _displayedLogBrokerProperties = new Vector();
90
91   protected Map _logLevelMenuItems = new HashMap();
92   protected Map _logTableColumnMenuItems = new HashMap();
93
94   protected List JavaDoc _levels = null;
95   protected List JavaDoc _columns = null;
96   protected boolean _isDisposed = false;
97
98   protected ConfigurationManager _configurationManager = null;
99   protected MRUFileManager _mruFileManager = null;
100   protected File JavaDoc _fileLocation = null;
101
102   //--------------------------------------------------------------------------
103
// Private Variables:
104
//--------------------------------------------------------------------------
105

106   //--------------------------------------------------------------------------
107
// Constructors:
108
//--------------------------------------------------------------------------
109

110   /**
111    * Construct a LogBrokerMonitor.
112    */

113   public LogBrokerMonitor(List JavaDoc logLevels) {
114
115     _levels = logLevels;
116     _columns = LogTableColumn.getLogTableColumns();
117     // This allows us to use the LogBroker in command line tools and
118
// have the option for it to shutdown.
119

120     String JavaDoc callSystemExitOnClose =
121         System.getProperty("monitor.exit");
122     if (callSystemExitOnClose == null) {
123       callSystemExitOnClose = "false";
124     }
125     callSystemExitOnClose = callSystemExitOnClose.trim().toLowerCase();
126
127     if (callSystemExitOnClose.equals("true")) {
128       _callSystemExitOnClose = true;
129     }
130
131     initComponents();
132
133
134     _logMonitorFrame.addWindowListener(
135         new LogBrokerMonitorWindowAdaptor(this));
136
137   }
138
139   //--------------------------------------------------------------------------
140
// Public Methods:
141
//--------------------------------------------------------------------------
142

143   /**
144    * Show the frame for the LogBrokerMonitor. Dispatched to the
145    * swing thread.
146    */

147   public void show(final int delay) {
148     if (_logMonitorFrame.isVisible()) {
149       return;
150     }
151     // This request is very low priority, let other threads execute first.
152
SwingUtilities.invokeLater(new Runnable JavaDoc() {
153       public void run() {
154         Thread.yield();
155         pause(delay);
156         _logMonitorFrame.setVisible(true);
157       }
158     });
159   }
160
161   public void show() {
162     show(0);
163   }
164
165   /**
166    * Dispose of the frame for the LogBrokerMonitor.
167    */

168   public void dispose() {
169     _logMonitorFrame.dispose();
170     _isDisposed = true;
171
172     if (_callSystemExitOnClose == true) {
173       System.exit(0);
174     }
175   }
176
177   /**
178    * Hide the frame for the LogBrokerMonitor.
179    */

180   public void hide() {
181     _logMonitorFrame.setVisible(false);
182   }
183
184   /**
185    * Get the DateFormatManager for formatting dates.
186    */

187   public DateFormatManager getDateFormatManager() {
188     return _table.getDateFormatManager();
189   }
190
191   /**
192    * Set the date format manager for formatting dates.
193    */

194   public void setDateFormatManager(DateFormatManager dfm) {
195     _table.setDateFormatManager(dfm);
196   }
197
198   /**
199    * Get the value of whether or not System.exit() will be called
200    * when the LogBrokerMonitor is closed.
201    */

202   public boolean getCallSystemExitOnClose() {
203     return _callSystemExitOnClose;
204   }
205
206   /**
207    * Set the value of whether or not System.exit() will be called
208    * when the LogBrokerMonitor is closed.
209    */

210   public void setCallSystemExitOnClose(boolean callSystemExitOnClose) {
211     _callSystemExitOnClose = callSystemExitOnClose;
212   }
213
214   /**
215    * Add a log record message to be displayed in the LogTable.
216    * This method is thread-safe as it posts requests to the SwingThread
217    * rather than processing directly.
218    */

219   public void addMessage(final LogRecord lr) {
220     if (_isDisposed == true) {
221       // If the frame has been disposed of, do not log any more
222
// messages.
223
return;
224     }
225
226     SwingUtilities.invokeLater(new Runnable JavaDoc() {
227       public void run() {
228         _categoryExplorerTree.getExplorerModel().addLogRecord(lr);
229         _table.getFilteredLogTableModel().addLogRecord(lr); // update table
230
updateStatusLabel(); // show updated counts
231
}
232     });
233   }
234
235   public void setMaxNumberOfLogRecords(int maxNumberOfLogRecords) {
236     _table.getFilteredLogTableModel().setMaxNumberOfLogRecords(maxNumberOfLogRecords);
237   }
238
239   public JFrame getBaseFrame() {
240     return _logMonitorFrame;
241   }
242
243   public void setTitle(String JavaDoc title) {
244     _logMonitorFrame.setTitle(title + " - LogFactor5");
245   }
246
247   public void setFrameSize(int width, int height) {
248     Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
249     if (0 < width && width < screen.width) {
250       _logMonitorFrameWidth = width;
251     }
252     if (0 < height && height < screen.height) {
253       _logMonitorFrameHeight = height;
254     }
255     updateFrameSize();
256   }
257
258   public void setFontSize(int fontSize) {
259     changeFontSizeCombo(_fontSizeCombo, fontSize);
260     // setFontSizeSilently(actualFontSize); - changeFontSizeCombo fires event
261
// refreshDetailTextArea();
262
}
263
264   public void addDisplayedProperty(Object JavaDoc messageLine) {
265     _displayedLogBrokerProperties.add(messageLine);
266   }
267
268   public Map getLogLevelMenuItems() {
269     return _logLevelMenuItems;
270   }
271
272   public Map getLogTableColumnMenuItems() {
273     return _logTableColumnMenuItems;
274   }
275
276   public JCheckBoxMenuItem getTableColumnMenuItem(LogTableColumn column) {
277     return getLogTableColumnMenuItem(column);
278   }
279
280   public CategoryExplorerTree getCategoryExplorerTree() {
281     return _categoryExplorerTree;
282   }
283
284   // Added in version 1.2 - gets the value of the NDC text filter
285
// This value is set back to null each time the Monitor is initialized.
286
public String JavaDoc getNDCTextFilter() {
287     return _NDCTextFilter;
288   }
289
290   // Added in version 1.2 - sets the NDC Filter based on
291
// a String passed in by the user. This value is persisted
292
// in the XML Configuration file.
293
public void setNDCLogRecordFilter(String JavaDoc textFilter) {
294     _table.getFilteredLogTableModel().
295         setLogRecordFilter(createNDCLogRecordFilter(textFilter));
296   }
297   //--------------------------------------------------------------------------
298
// Protected Methods:
299
//--------------------------------------------------------------------------
300

301   protected void setSearchText(String JavaDoc text) {
302     _searchText = text;
303   }
304
305   // Added in version 1.2 - Sets the text filter for the NDC
306
protected void setNDCTextFilter(String JavaDoc text) {
307     // if no value is set, set it to a blank string
308
// otherwise use the value provided
309
if (text == null) {
310       _NDCTextFilter = "";
311     } else {
312       _NDCTextFilter = text;
313     }
314   }
315
316   // Added in version 1.2 - Uses a different filter that sorts
317
// based on an NDC string passed in by the user. If the string
318
// is null or is an empty string, we do nothing.
319
protected void sortByNDC() {
320     String JavaDoc text = _NDCTextFilter;
321     if (text == null || text.length() == 0) {
322       return;
323     }
324
325     // Use new NDC filter
326
_table.getFilteredLogTableModel().
327         setLogRecordFilter(createNDCLogRecordFilter(text));
328   }
329
330   protected void findSearchText() {
331     String JavaDoc text = _searchText;
332     if (text == null || text.length() == 0) {
333       return;
334     }
335     int startRow = getFirstSelectedRow();
336     int foundRow = findRecord(
337         startRow,
338         text,
339         _table.getFilteredLogTableModel().getFilteredRecords()
340     );
341     selectRow(foundRow);
342   }
343
344   protected int getFirstSelectedRow() {
345     return _table.getSelectionModel().getMinSelectionIndex();
346   }
347
348   protected void selectRow(int foundRow) {
349     if (foundRow == -1) {
350       String JavaDoc message = _searchText + " not found.";
351       JOptionPane.showMessageDialog(
352           _logMonitorFrame,
353           message,
354           "Text not found",
355           JOptionPane.INFORMATION_MESSAGE
356       );
357       return;
358     }
359     LF5SwingUtils.selectRow(foundRow, _table, _logTableScrollPane);
360   }
361
362   protected int findRecord(
363       int startRow,
364       String JavaDoc searchText,
365       List JavaDoc records
366       ) {
367     if (startRow < 0) {
368       startRow = 0; // start at first element if no rows are selected
369
} else {
370       startRow++; // start after the first selected row
371
}
372     int len = records.size();
373
374     for (int i = startRow; i < len; i++) {
375       if (matches((LogRecord) records.get(i), searchText)) {
376         return i; // found a record
377
}
378     }
379     // wrap around to beginning if when we reach the end with no match
380
len = startRow;
381     for (int i = 0; i < len; i++) {
382       if (matches((LogRecord) records.get(i), searchText)) {
383         return i; // found a record
384
}
385     }
386     // nothing found
387
return -1;
388   }
389
390   /**
391    * Check to see if the any records contain the search string.
392    * Searching now supports NDC messages and date.
393    */

394   protected boolean matches(LogRecord record, String JavaDoc text) {
395     String JavaDoc message = record.getMessage();
396     String JavaDoc NDC = record.getNDC();
397
398     if (message == null && NDC == null || text == null) {
399       return false;
400     }
401     if (message.toLowerCase().indexOf(text.toLowerCase()) == -1 &&
402         NDC.toLowerCase().indexOf(text.toLowerCase()) == -1) {
403       return false;
404     }
405
406     return true;
407   }
408
409   /**
410    * When the fontsize of a JTextArea is changed, the word-wrapped lines
411    * may become garbled. This method clears and resets the text of the
412    * text area.
413    */

414   protected void refresh(JTextArea textArea) {
415     String JavaDoc text = textArea.getText();
416     textArea.setText("");
417     textArea.setText(text);
418   }
419
420   protected void refreshDetailTextArea() {
421     refresh(_table._detailTextArea);
422   }
423
424   protected void clearDetailTextArea() {
425     _table._detailTextArea.setText("");
426   }
427
428   /**
429    * Changes the font selection in the combo box and returns the
430    * size actually selected.
431    * @return -1 if unable to select an appropriate font
432    */

433   protected int changeFontSizeCombo(JComboBox box, int requestedSize) {
434     int len = box.getItemCount();
435     int currentValue;
436     Object JavaDoc currentObject;
437     Object JavaDoc selectedObject = box.getItemAt(0);
438     int selectedValue = Integer.parseInt(String.valueOf(selectedObject));
439     for (int i = 0; i < len; i++) {
440       currentObject = box.getItemAt(i);
441       currentValue = Integer.parseInt(String.valueOf(currentObject));
442       if (selectedValue < currentValue && currentValue <= requestedSize) {
443         selectedValue = currentValue;
444         selectedObject = currentObject;
445       }
446     }
447     box.setSelectedItem(selectedObject);
448     return selectedValue;
449   }
450
451   /**
452    * Does not update gui or cause any events to be fired.
453    */

454   protected void setFontSizeSilently(int fontSize) {
455     _fontSize = fontSize;
456     setFontSize(_table._detailTextArea, fontSize);
457     selectRow(0);
458     setFontSize(_table, fontSize);
459   }
460
461   protected void setFontSize(Component component, int fontSize) {
462     Font oldFont = component.getFont();
463     Font newFont =
464         new Font(oldFont.getFontName(), oldFont.getStyle(), fontSize);
465     component.setFont(newFont);
466   }
467
468   protected void updateFrameSize() {
469     _logMonitorFrame.setSize(_logMonitorFrameWidth, _logMonitorFrameHeight);
470     centerFrame(_logMonitorFrame);
471   }
472
473   protected void pause(int millis) {
474     try {
475       Thread.sleep(millis);
476     } catch (InterruptedException JavaDoc e) {
477
478     }
479   }
480
481   protected void initComponents() {
482     //
483
// Configure the Frame.
484
//
485
_logMonitorFrame = new JFrame("LogFactor5");
486
487     _logMonitorFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
488
489     String JavaDoc resource =
490         "/org/apache/log4j/lf5/viewer/images/lf5_small_icon.gif";
491     URL JavaDoc lf5IconURL = getClass().getResource(resource);
492
493     if (lf5IconURL != null) {
494       _logMonitorFrame.setIconImage(new ImageIcon(lf5IconURL).getImage());
495     }
496     updateFrameSize();
497
498     //
499
// Configure the LogTable.
500
//
501
JTextArea detailTA = createDetailTextArea();
502     JScrollPane detailTAScrollPane = new JScrollPane(detailTA);
503     _table = new LogTable(detailTA);
504     setView(_currentView, _table);
505     _table.setFont(new Font(_fontName, Font.PLAIN, _fontSize));
506     _logTableScrollPane = new JScrollPane(_table);
507
508     if (_trackTableScrollPane) {
509       _logTableScrollPane.getVerticalScrollBar().addAdjustmentListener(
510           new TrackingAdjustmentListener()
511       );
512     }
513
514
515     // Configure the SplitPane between the LogTable & DetailTextArea
516
//
517

518     JSplitPane tableViewerSplitPane = new JSplitPane();
519     tableViewerSplitPane.setOneTouchExpandable(true);
520     tableViewerSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
521     tableViewerSplitPane.setLeftComponent(_logTableScrollPane);
522     tableViewerSplitPane.setRightComponent(detailTAScrollPane);
523     // Make sure to do this last..
524
//tableViewerSplitPane.setDividerLocation(1.0); Doesn't work
525
//the same under 1.2.x & 1.3
526
// "350" is a magic number that provides the correct default
527
// behaviour under 1.2.x & 1.3. For example, bumping this
528
// number to 400, causes the pane to be completely open in 1.2.x
529
// and closed in 1.3
530
tableViewerSplitPane.setDividerLocation(350);
531
532     //
533
// Configure the CategoryExplorer
534
//
535

536     _categoryExplorerTree = new CategoryExplorerTree();
537
538     _table.getFilteredLogTableModel().setLogRecordFilter(createLogRecordFilter());
539
540     JScrollPane categoryExplorerTreeScrollPane =
541         new JScrollPane(_categoryExplorerTree);
542     categoryExplorerTreeScrollPane.setPreferredSize(new Dimension(130, 400));
543
544     // Load most recently used file list
545
_mruFileManager = new MRUFileManager();
546
547     //
548
// Configure the SplitPane between the CategoryExplorer & (LogTable/Detail)
549
//
550

551     JSplitPane splitPane = new JSplitPane();
552     splitPane.setOneTouchExpandable(true);
553     splitPane.setRightComponent(tableViewerSplitPane);
554     splitPane.setLeftComponent(categoryExplorerTreeScrollPane);
555     // Do this last.
556
splitPane.setDividerLocation(130);
557     //
558
// Add the MenuBar, StatusArea, CategoryExplorer|LogTable to the
559
// LogMonitorFrame.
560
//
561
_logMonitorFrame.getRootPane().setJMenuBar(createMenuBar());
562     _logMonitorFrame.getContentPane().add(splitPane, BorderLayout.CENTER);
563     _logMonitorFrame.getContentPane().add(createToolBar(),
564         BorderLayout.NORTH);
565     _logMonitorFrame.getContentPane().add(createStatusArea(),
566         BorderLayout.SOUTH);
567
568     makeLogTableListenToCategoryExplorer();
569     addTableModelProperties();
570
571     //
572
// Configure ConfigurationManager
573
//
574
_configurationManager = new ConfigurationManager(this, _table);
575
576   }
577
578   protected LogRecordFilter createLogRecordFilter() {
579     LogRecordFilter result = new LogRecordFilter() {
580       public boolean passes(LogRecord record) {
581         CategoryPath path = new CategoryPath(record.getCategory());
582         return
583             getMenuItem(record.getLevel()).isSelected() &&
584             _categoryExplorerTree.getExplorerModel().isCategoryPathActive(path);
585       }
586     };
587     return result;
588   }
589
590   // Added in version 1.2 - Creates a new filter that sorts records based on
591
// an NDC string passed in by the user.
592
protected LogRecordFilter createNDCLogRecordFilter(String JavaDoc text) {
593     _NDCTextFilter = text;
594     LogRecordFilter result = new LogRecordFilter() {
595       public boolean passes(LogRecord record) {
596         String JavaDoc NDC = record.getNDC();
597         CategoryPath path = new CategoryPath(record.getCategory());
598         if (NDC == null || _NDCTextFilter == null) {
599           return false;
600         } else if (NDC.toLowerCase().indexOf(_NDCTextFilter.toLowerCase()) == -1) {
601           return false;
602         } else {
603           return getMenuItem(record.getLevel()).isSelected() &&
604               _categoryExplorerTree.getExplorerModel().isCategoryPathActive(path);
605         }
606       }
607     };
608
609     return result;
610   }
611
612
613   protected void updateStatusLabel() {
614     _statusLabel.setText(getRecordsDisplayedMessage());
615   }
616
617   protected String JavaDoc getRecordsDisplayedMessage() {
618     FilteredLogTableModel model = _table.getFilteredLogTableModel();
619     return getStatusText(model.getRowCount(), model.getTotalRowCount());
620   }
621
622   protected void addTableModelProperties() {
623     final FilteredLogTableModel model = _table.getFilteredLogTableModel();
624
625     addDisplayedProperty(new Object JavaDoc() {
626       public String JavaDoc toString() {
627         return getRecordsDisplayedMessage();
628       }
629     });
630     addDisplayedProperty(new Object JavaDoc() {
631       public String JavaDoc toString() {
632         return "Maximum number of displayed LogRecords: "
633             + model._maxNumberOfLogRecords;
634       }
635     });
636   }
637
638   protected String JavaDoc getStatusText(int displayedRows, int totalRows) {
639     StringBuffer JavaDoc result = new StringBuffer JavaDoc();
640     result.append("Displaying: ");
641     result.append(displayedRows);
642     result.append(" records out of a total of: ");
643     result.append(totalRows);
644     result.append(" records.");
645     return result.toString();
646   }
647
648   protected void makeLogTableListenToCategoryExplorer() {
649     ActionListener JavaDoc listener = new ActionListener JavaDoc() {
650       public void actionPerformed(ActionEvent JavaDoc e) {
651         _table.getFilteredLogTableModel().refresh();
652         updateStatusLabel();
653       }
654     };
655     _categoryExplorerTree.getExplorerModel().addActionListener(listener);
656   }
657
658   protected JPanel createStatusArea() {
659     JPanel statusArea = new JPanel();
660     JLabel status =
661         new JLabel("No log records to display.");
662     _statusLabel = status;
663     status.setHorizontalAlignment(JLabel.LEFT);
664
665     statusArea.setBorder(BorderFactory.createEtchedBorder());
666     statusArea.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
667     statusArea.add(status);
668
669     return (statusArea);
670   }
671
672   protected JTextArea createDetailTextArea() {
673     JTextArea detailTA = new JTextArea();
674     detailTA.setFont(new Font("Monospaced", Font.PLAIN, 14));
675     detailTA.setTabSize(3);
676     detailTA.setLineWrap(true);
677     detailTA.setWrapStyleWord(false);
678     return (detailTA);
679   }
680
681   protected JMenuBar createMenuBar() {
682     JMenuBar menuBar = new JMenuBar();
683     menuBar.add(createFileMenu());
684     menuBar.add(createEditMenu());
685     menuBar.add(createLogLevelMenu());
686     menuBar.add(createViewMenu());
687     menuBar.add(createConfigureMenu());
688     menuBar.add(createHelpMenu());
689
690     return (menuBar);
691   }
692
693   protected JMenu createLogLevelMenu() {
694     JMenu result = new JMenu("Log Level");
695     result.setMnemonic('l');
696     Iterator levels = getLogLevels();
697     while (levels.hasNext()) {
698       result.add(getMenuItem((LogLevel) levels.next()));
699     }
700
701     result.addSeparator();
702     result.add(createAllLogLevelsMenuItem());
703     result.add(createNoLogLevelsMenuItem());
704     result.addSeparator();
705     result.add(createLogLevelColorMenu());
706     result.add(createResetLogLevelColorMenuItem());
707
708     return result;
709   }
710
711   protected JMenuItem createAllLogLevelsMenuItem() {
712     JMenuItem result = new JMenuItem("Show all LogLevels");
713     result.setMnemonic('s');
714     result.addActionListener(new ActionListener JavaDoc() {
715       public void actionPerformed(ActionEvent JavaDoc e) {
716         selectAllLogLevels(true);
717         _table.getFilteredLogTableModel().refresh();
718         updateStatusLabel();
719       }
720     });
721     return result;
722   }
723
724   protected JMenuItem createNoLogLevelsMenuItem() {
725     JMenuItem result = new JMenuItem("Hide all LogLevels");
726     result.setMnemonic('h');
727     result.addActionListener(new ActionListener JavaDoc() {
728       public void actionPerformed(ActionEvent JavaDoc e) {
729         selectAllLogLevels(false);
730         _table.getFilteredLogTableModel().refresh();
731         updateStatusLabel();
732       }
733     });
734     return result;
735   }
736
737   protected JMenu createLogLevelColorMenu() {
738     JMenu colorMenu = new JMenu("Configure LogLevel Colors");
739     colorMenu.setMnemonic('c');
740     Iterator levels = getLogLevels();
741     while (levels.hasNext()) {
742       colorMenu.add(createSubMenuItem((LogLevel) levels.next()));
743     }
744
745     return colorMenu;
746   }
747
748   protected JMenuItem createResetLogLevelColorMenuItem() {
749     JMenuItem result = new JMenuItem("Reset LogLevel Colors");
750     result.setMnemonic('r');
751     result.addActionListener(new ActionListener JavaDoc() {
752       public void actionPerformed(ActionEvent JavaDoc e) {
753         // reset the level colors in the map
754
LogLevel.resetLogLevelColorMap();
755
756         // refresh the table
757
_table.getFilteredLogTableModel().refresh();
758       }
759     });
760     return result;
761   }
762
763   protected void selectAllLogLevels(boolean selected) {
764     Iterator levels = getLogLevels();
765     while (levels.hasNext()) {
766       getMenuItem((LogLevel) levels.next()).setSelected(selected);
767     }
768   }
769
770   protected JCheckBoxMenuItem getMenuItem(LogLevel level) {
771     JCheckBoxMenuItem result = (JCheckBoxMenuItem) (_logLevelMenuItems.get(level));
772     if (result == null) {
773       result = createMenuItem(level);
774       _logLevelMenuItems.put(level, result);
775     }
776     return result;
777   }
778
779   protected JMenuItem createSubMenuItem(LogLevel level) {
780     final JMenuItem result = new JMenuItem(level.toString());
781     final LogLevel logLevel = level;
782     result.setMnemonic(level.toString().charAt(0));
783     result.addActionListener(new ActionListener JavaDoc() {
784       public void actionPerformed(ActionEvent JavaDoc e) {
785         showLogLevelColorChangeDialog(result, logLevel);
786       }
787     });
788
789     return result;
790
791   }
792
793   protected void showLogLevelColorChangeDialog(JMenuItem result, LogLevel level) {
794     JMenuItem menuItem = result;
795     Color newColor = JColorChooser.showDialog(
796         _logMonitorFrame,
797         "Choose LogLevel Color",
798         result.getForeground());
799
800     if (newColor != null) {
801       // set the color for the record
802
level.setLogLevelColorMap(level, newColor);
803       _table.getFilteredLogTableModel().refresh();
804     }
805
806   }
807
808   protected JCheckBoxMenuItem createMenuItem(LogLevel level) {
809     JCheckBoxMenuItem result = new JCheckBoxMenuItem(level.toString());
810     result.setSelected(true);
811     result.setMnemonic(level.toString().charAt(0));
812     result.addActionListener(new ActionListener JavaDoc() {
813       public void actionPerformed(ActionEvent JavaDoc e) {
814         _table.getFilteredLogTableModel().refresh();
815         updateStatusLabel();
816       }
817     });
818     return result;
819   }
820
821   // view menu
822
protected JMenu createViewMenu() {
823     JMenu result = new JMenu("View");
824     result.setMnemonic('v');
825     Iterator columns = getLogTableColumns();
826     while (columns.hasNext()) {
827       result.add(getLogTableColumnMenuItem((LogTableColumn) columns.next()));
828     }
829
830     result.addSeparator();
831     result.add(createAllLogTableColumnsMenuItem());
832     result.add(createNoLogTableColumnsMenuItem());
833     return result;
834   }
835
836   protected JCheckBoxMenuItem getLogTableColumnMenuItem(LogTableColumn column) {
837     JCheckBoxMenuItem result = (JCheckBoxMenuItem) (_logTableColumnMenuItems.get(column));
838     if (result == null) {
839       result = createLogTableColumnMenuItem(column);
840       _logTableColumnMenuItems.put(column, result);
841     }
842     return result;
843   }
844
845   protected JCheckBoxMenuItem createLogTableColumnMenuItem(LogTableColumn column) {
846     JCheckBoxMenuItem result = new JCheckBoxMenuItem(column.toString());
847
848     result.setSelected(true);
849     result.setMnemonic(column.toString().charAt(0));
850     result.addActionListener(new ActionListener JavaDoc() {
851       public void actionPerformed(ActionEvent JavaDoc e) {
852         // update list of columns and reset the view
853
List JavaDoc selectedColumns = updateView();
854         _table.setView(selectedColumns);
855       }
856     });
857     return result;
858   }
859
860   protected List JavaDoc updateView() {
861     ArrayList updatedList = new ArrayList();
862     Iterator columnIterator = _columns.iterator();
863     while (columnIterator.hasNext()) {
864       LogTableColumn column = (LogTableColumn) columnIterator.next();
865       JCheckBoxMenuItem result = getLogTableColumnMenuItem(column);
866       // check and see if the checkbox is checked
867
if (result.isSelected()) {
868         updatedList.add(column);
869       }
870     }
871
872     return updatedList;
873   }
874
875   protected JMenuItem createAllLogTableColumnsMenuItem() {
876     JMenuItem result = new JMenuItem("Show all Columns");
877     result.setMnemonic('s');
878     result.addActionListener(new ActionListener JavaDoc() {
879       public void actionPerformed(ActionEvent JavaDoc e) {
880         selectAllLogTableColumns(true);
881         // update list of columns and reset the view
882
List JavaDoc selectedColumns = updateView();
883         _table.setView(selectedColumns);
884       }
885     });
886     return result;
887   }
888
889   protected JMenuItem createNoLogTableColumnsMenuItem() {
890     JMenuItem result = new JMenuItem("Hide all Columns");
891     result.setMnemonic('h');
892     result.addActionListener(new ActionListener JavaDoc() {
893       public void actionPerformed(ActionEvent JavaDoc e) {
894         selectAllLogTableColumns(false);
895         // update list of columns and reset the view
896
List JavaDoc selectedColumns = updateView();
897         _table.setView(selectedColumns);
898       }
899     });
900     return result;
901   }
902
903   protected void selectAllLogTableColumns(boolean selected) {
904     Iterator columns = getLogTableColumns();
905     while (columns.hasNext()) {
906       getLogTableColumnMenuItem((LogTableColumn) columns.next()).setSelected(selected);
907     }
908   }
909
910   protected JMenu createFileMenu() {
911     JMenu fileMenu = new JMenu("File");
912     fileMenu.setMnemonic('f');
913     JMenuItem exitMI;
914     fileMenu.add(createOpenMI());
915     fileMenu.add(createOpenURLMI());
916     fileMenu.addSeparator();
917     fileMenu.add(createCloseMI());
918     createMRUFileListMI(fileMenu);
919     fileMenu.addSeparator();
920     fileMenu.add(createExitMI());
921     return fileMenu;
922   }
923
924   /**
925    * Menu item added to allow log files to be opened with
926    * the LF5 GUI.
927    */

928   protected JMenuItem createOpenMI() {
929     JMenuItem result = new JMenuItem("Open...");
930     result.setMnemonic('o');
931     result.addActionListener(new ActionListener JavaDoc() {
932       public void actionPerformed(ActionEvent JavaDoc e) {
933         requestOpen();
934       }
935     });
936     return result;
937   }
938
939   /**
940    * Menu item added to allow log files loaded from a URL
941    * to be opened by the LF5 GUI.
942    */

943   protected JMenuItem createOpenURLMI() {
944     JMenuItem result = new JMenuItem("Open URL...");
945     result.setMnemonic('u');
946     result.addActionListener(new ActionListener JavaDoc() {
947       public void actionPerformed(ActionEvent JavaDoc e) {
948         requestOpenURL();
949       }
950     });
951     return result;
952   }
953
954   protected JMenuItem createCloseMI() {
955     JMenuItem result = new JMenuItem("Close");
956     result.setMnemonic('c');
957     result.setAccelerator(KeyStroke.getKeyStroke("control Q"));
958     result.addActionListener(new ActionListener JavaDoc() {
959       public void actionPerformed(ActionEvent JavaDoc e) {
960         requestClose();
961       }
962     });
963     return result;
964   }
965
966   /**
967    * Creates a Most Recently Used file list to be
968    * displayed in the File menu
969    */

970   protected void createMRUFileListMI(JMenu menu) {
971
972     String JavaDoc[] files = _mruFileManager.getMRUFileList();
973
974     if (files != null) {
975       menu.addSeparator();
976       for (int i = 0; i < files.length; i++) {
977         JMenuItem result = new JMenuItem((i + 1) + " " + files[i]);
978         result.setMnemonic(i + 1);
979         result.addActionListener(new ActionListener JavaDoc() {
980           public void actionPerformed(ActionEvent JavaDoc e) {
981             requestOpenMRU(e);
982           }
983         });
984         menu.add(result);
985       }
986     }
987   }
988
989   protected JMenuItem createExitMI() {
990     JMenuItem result = new JMenuItem("Exit");
991     result.setMnemonic('x');
992   &