Project: des
Code Examples
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more 
 * contributor license agreements.  See the NOTICE file distributed with 
 * this work for additional information regarding copyright ownership. 
 * The ASF licenses this file to You under the Apache License, Version 2.0 
 * (the "License"); you may not use this file except in compliance with 
 * the License.  You may obtain a copy of the License at 
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0 
 *  
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */
package org.apache.log4j.lf5.viewer; 
 
import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.Font; 
import java.awt.GraphicsEnvironment; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.io.File; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.List; 
import java.util.Map; 
import java.util.StringTokenizer; 
import java.util.Vector; 
 
import javax.swing.BorderFactory; 
import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JCheckBoxMenuItem; 
import javax.swing.JColorChooser; 
import javax.swing.JComboBox; 
import javax.swing.JFileChooser; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JSplitPane; 
import javax.swing.JTextArea; 
import javax.swing.JToolBar; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 
 
import org.apache.log4j.lf5.LogLevel; 
import org.apache.log4j.lf5.LogRecord; 
import org.apache.log4j.lf5.LogRecordFilter; 
import org.apache.log4j.lf5.util.DateFormatManager; 
import org.apache.log4j.lf5.util.LogFileParser; 
import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryExplorerTree; 
import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryPath; 
import org.apache.log4j.lf5.viewer.configure.ConfigurationManager; 
import org.apache.log4j.lf5.viewer.configure.MRUFileManager; 
 
/**
 * LogBrokerMonitor 
 *. 
 * @author Michael J. Sikorsky 
 * @author Robert Shaw 
 * @author Brad Marlborough 
 * @author Richard Wan 
 * @author Brent Sprecher 
 * @author Richard Hurst 
 */
 
 
// Contributed by ThoughtWorks Inc. 
 
public class LogBrokerMonitor { 
  //-------------------------------------------------------------------------- 
  //   Constants: 
  //-------------------------------------------------------------------------- 
 
  public static final String DETAILED_VIEW = "Detailed"
//    public static final String STANDARD_VIEW = "Standard"; 
//    public static final String COMPACT_VIEW = "Compact"; 
  //-------------------------------------------------------------------------- 
  //   Protected Variables: 
  //-------------------------------------------------------------------------- 
  protected JFrame _logMonitorFrame; 
  protected int _logMonitorFrameWidth = 550
  protected int _logMonitorFrameHeight = 500
  protected LogTable _table; 
  protected CategoryExplorerTree _categoryExplorerTree; 
  protected String _searchText; 
  protected String _NDCTextFilter = ""
  protected LogLevel _leastSevereDisplayedLogLevel = LogLevel.DEBUG; 
 
  protected JScrollPane _logTableScrollPane; 
  protected JLabel _statusLabel; 
  protected Object _lock = new Object(); 
  protected JComboBox _fontSizeCombo; 
 
  protected int _fontSize = 10
  protected String _fontName = "Dialog"
  protected String _currentView = DETAILED_VIEW; 
 
  protected boolean _loadSystemFonts = false
  protected boolean _trackTableScrollPane = true
  protected Dimension _lastTableViewportSize; 
  protected boolean _callSystemExitOnClose = false
  protected List _displayedLogBrokerProperties = new Vector(); 
 
  protected Map _logLevelMenuItems = new HashMap(); 
  protected Map _logTableColumnMenuItems = new HashMap(); 
 
  protected List _levels = null
  protected List _columns = null
  protected boolean _isDisposed = false
 
  protected ConfigurationManager _configurationManager = null
  protected MRUFileManager _mruFileManager = null
  protected File _fileLocation = null
 
  //-------------------------------------------------------------------------- 
  //   Private Variables: 
  //-------------------------------------------------------------------------- 
 
  //-------------------------------------------------------------------------- 
  //   Constructors: 
  //-------------------------------------------------------------------------- 
 
  /**
   * Construct a LogBrokerMonitor. 
   */
 
  public LogBrokerMonitor(List logLevels) { 
 
    _levels = logLevels; 
    _columns = LogTableColumn.getLogTableColumns(); 
    // This allows us to use the LogBroker in command line tools and 
    // have the option for it to shutdown. 
 
    String callSystemExitOnClose = 
        System.getProperty("monitor.exit"); 
    if (callSystemExitOnClose == null) { 
      callSystemExitOnClose = "false"
    } 
    callSystemExitOnClose = callSystemExitOnClose.trim().toLowerCase(); 
 
    if (callSystemExitOnClose.equals("true")) { 
      _callSystemExitOnClose = true
    } 
 
    initComponents(); 
 
 
    _logMonitorFrame.addWindowListener( 
        new LogBrokerMonitorWindowAdaptor(this)); 
 
  } 
 
  //-------------------------------------------------------------------------- 
  //   Public Methods: 
  //-------------------------------------------------------------------------- 
 
  /**
   * Show the frame for the LogBrokerMonitor. Dispatched to the 
   * swing thread. 
   */
 
  public void show(final int delay) { 
    if (_logMonitorFrame.isVisible()) { 
      return
    } 
    // This request is very low priority, let other threads execute first. 
    SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
        Thread.yield(); 
        pause(delay); 
        _logMonitorFrame.setVisible(true); 
      } 
    }); 
  } 
 
  public void show() { 
    show(0); 
  } 
 
  /**
   * Dispose of the frame for the LogBrokerMonitor. 
   */
 
  public void dispose() { 
    _logMonitorFrame.dispose(); 
    _isDisposed = true
 
    if (_callSystemExitOnClose == true) { 
      System.exit(0); 
    } 
  } 
 
  /**
   * Hide the frame for the LogBrokerMonitor. 
   */
 
  public void hide() { 
    _logMonitorFrame.setVisible(false); 
  } 
 
  /**
   * Get the DateFormatManager for formatting dates. 
   */
 
  public DateFormatManager getDateFormatManager() { 
    return _table.getDateFormatManager(); 
  } 
 
  /**
   * Set the date format manager for formatting dates. 
   */
 
  public void setDateFormatManager(DateFormatManager dfm) { 
    _table.setDateFormatManager(dfm); 
  } 
 
  /**
   * Get the value of whether or not System.exit() will be called 
   * when the LogBrokerMonitor is closed. 
   */
 
  public boolean getCallSystemExitOnClose() { 
    return _callSystemExitOnClose; 
  } 
 
  /**
   * Set the value of whether or not System.exit() will be called 
   * when the LogBrokerMonitor is closed. 
   */
 
  public void setCallSystemExitOnClose(boolean callSystemExitOnClose) { 
    _callSystemExitOnClose = callSystemExitOnClose; 
  } 
 
  /**
   * Add a log record message to be displayed in the LogTable. 
   * This method is thread-safe as it posts requests to the SwingThread 
   * rather than processing directly. 
   */
 
  public void addMessage(final LogRecord lr) { 
    if (_isDisposed == true) { 
      // If the frame has been disposed of, do not log any more 
      // messages. 
      return
    } 
 
    SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
        _categoryExplorerTree.getExplorerModel().addLogRecord(lr); 
        _table.getFilteredLogTableModel().addLogRecord(lr); // update table 
        updateStatusLabel(); // show updated counts 
      } 
    }); 
  } 
 
  public void setMaxNumberOfLogRecords(int maxNumberOfLogRecords) { 
    _table.getFilteredLogTableModel().setMaxNumberOfLogRecords(maxNumberOfLogRecords); 
  } 
 
  public JFrame getBaseFrame() { 
    return _logMonitorFrame; 
  } 
 
  public void setTitle(String title) { 
    _logMonitorFrame.setTitle(title + " - LogFactor5"); 
  } 
 
  public void setFrameSize(int width, int height) { 
    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); 
    if (0 < width && width < screen.width) { 
      _logMonitorFrameWidth = width; 
    } 
    if (0 < height && height < screen.height) { 
      _logMonitorFrameHeight = height; 
    } 
    updateFrameSize(); 
  } 
 
  public void setFontSize(int fontSize) { 
    changeFontSizeCombo(_fontSizeCombo, fontSize); 
    // setFontSizeSilently(actualFontSize); - changeFontSizeCombo fires event 
    // refreshDetailTextArea(); 
  } 
 
  public void addDisplayedProperty(Object messageLine) { 
    _displayedLogBrokerProperties.add(messageLine); 
  } 
 
  public Map getLogLevelMenuItems() { 
    return _logLevelMenuItems; 
  } 
 
  public Map getLogTableColumnMenuItems() { 
    return _logTableColumnMenuItems; 
  } 
 
  public JCheckBoxMenuItem getTableColumnMenuItem(LogTableColumn column) { 
    return getLogTableColumnMenuItem(column); 
  } 
 
  public CategoryExplorerTree getCategoryExplorerTree() { 
    return _categoryExplorerTree; 
  } 
 
  // Added in version 1.2 - gets the value of the NDC text filter 
  // This value is set back to null each time the Monitor is initialized. 
  public String getNDCTextFilter() { 
    return _NDCTextFilter; 
  } 
 
  // Added in version 1.2 - sets the NDC Filter based on 
  // a String passed in by the user.  This value is persisted 
  // in the XML Configuration file. 
  public void setNDCLogRecordFilter(String textFilter) { 
    _table.getFilteredLogTableModel(). 
        setLogRecordFilter(createNDCLogRecordFilter(textFilter)); 
  } 
  //-------------------------------------------------------------------------- 
  //   Protected Methods: 
  //-------------------------------------------------------------------------- 
 
  protected void setSearchText(String text) { 
    _searchText = text; 
  } 
 
  // Added in version 1.2 - Sets the text filter for the NDC 
  protected void setNDCTextFilter(String text) { 
    // if no value is set, set it to a blank string 
    // otherwise use the value provided 
    if (text == null) { 
      _NDCTextFilter = ""
    } else { 
      _NDCTextFilter = text; 
    } 
  } 
 
  // Added in version 1.2 - Uses a different filter that sorts 
  // based on an NDC string passed in by the user.  If the string 
  // is null or is an empty string, we do nothing. 
  protected void sortByNDC() { 
    String text = _NDCTextFilter; 
    if (text == null || text.length() == 0) { 
      return
    } 
 
    // Use new NDC filter 
    _table.getFilteredLogTableModel(). 
        setLogRecordFilter(createNDCLogRecordFilter(text)); 
  } 
 
  protected void findSearchText() { 
    String text = _searchText; 
    if (text == null || text.length() == 0) { 
      return
    } 
    int startRow = getFirstSelectedRow(); 
    int foundRow = findRecord( 
        startRow, 
        text, 
        _table.getFilteredLogTableModel().getFilteredRecords() 
    ); 
    selectRow(foundRow); 
  } 
 
  protected int getFirstSelectedRow() { 
    return _table.getSelectionModel().getMinSelectionIndex(); 
  } 
 
  protected void selectRow(int foundRow) { 
    if (foundRow == -1) { 
      String message = _searchText + " not found."
      JOptionPane.showMessageDialog( 
          _logMonitorFrame, 
          message, 
          "Text not found"
          JOptionPane.INFORMATION_MESSAGE 
      ); 
      return
    } 
    LF5SwingUtils.selectRow(foundRow, _table, _logTableScrollPane); 
  } 
 
  protected int findRecord
      int startRow, 
      String searchText, 
      List records 
      ) { 
    if (startRow < 0) { 
      startRow = 0// start at first element if no rows are selected 
    } else { 
      startRow++; // start after the first selected row 
    } 
    int len = records.size(); 
 
    for (int i = startRow; i < len; i++) { 
      if (matches((LogRecord) records.get(i), searchText)) { 
        return i; // found a record 
      } 
    } 
    // wrap around to beginning if when we reach the end with no match 
    len = startRow; 
    for (int i = 0; i < len; i++) { 
      if (matches((LogRecord) records.get(i), searchText)) { 
        return i; // found a record 
      } 
    } 
    // nothing found 
    return -1
  } 
 
  /**
   * Check to see if the any records contain the search string. 
   * Searching now supports NDC messages and date. 
   */
 
  protected boolean matches(LogRecord record, String text) { 
    String message = record.getMessage(); 
    String NDC = record.getNDC(); 
 
    if (message == null && NDC == null || text == null) { 
      return false
    } 
    if (message.toLowerCase().indexOf(text.toLowerCase()) == -1 && 
        NDC.toLowerCase().indexOf(text.toLowerCase()) == -1) { 
      return false
    } 
 
    return true
  } 
 
  /**
   * When the fontsize of a JTextArea is changed, the word-wrapped lines 
   * may become garbled.  This method clears and resets the text of the 
   * text area. 
   */
 
  protected void refresh(JTextArea textArea) { 
    String text = textArea.getText(); 
    textArea.setText(""); 
    textArea.setText(text); 
  } 
 
  protected void refreshDetailTextArea() { 
    refresh(_table._detailTextArea); 
  } 
 
  protected void clearDetailTextArea() { 
    _table._detailTextArea.setText(""); 
  } 
 
  /**
   * Changes the font selection in the combo box and returns the 
   * size actually selected. 
   * @return -1 if unable to select an appropriate font 
   */
 
  protected int changeFontSizeCombo(JComboBox box, int requestedSize) { 
    int len = box.getItemCount(); 
    int currentValue; 
    Object currentObject; 
    Object selectedObject = box.getItemAt(0); 
    int selectedValue = Integer.parseInt(String.valueOf(selectedObject)); 
    for (int i = 0; i < len; i++) { 
      currentObject = box.getItemAt(i); 
      currentValue = Integer.parseInt(String.valueOf(currentObject)); 
      if (selectedValue < currentValue && currentValue <= requestedSize) { 
        selectedValue = currentValue; 
        selectedObject = currentObject; 
      } 
    } 
    box.setSelectedItem(selectedObject); 
    return selectedValue; 
  } 
 
  /**
   * Does not update gui or cause any events to be fired. 
   */
 
  protected void setFontSizeSilently(int fontSize) { 
    _fontSize = fontSize; 
    setFontSize(_table._detailTextArea, fontSize); 
    selectRow(0); 
    setFontSize(_table, fontSize); 
  } 
 
  protected void setFontSize(Component component, int fontSize) { 
    Font oldFont = component.getFont(); 
    Font newFont = 
        new Font(oldFont.getFontName(), oldFont.getStyle(), fontSize); 
    component.setFont(newFont); 
  } 
 
  protected void updateFrameSize() { 
    _logMonitorFrame.setSize(_logMonitorFrameWidth, _logMonitorFrameHeight); 
    centerFrame(_logMonitorFrame); 
  } 
 
  protected void pause(int millis) { 
    try { 
      Thread.sleep(millis); 
    } catch (InterruptedException e) { 
 
    } 
  } 
 
  protected void initComponents() { 
    // 
    // Configure the Frame. 
    // 
    _logMonitorFrame = new JFrame("LogFactor5"); 
 
    _logMonitorFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 
 
    String resource = 
        "/org/apache/log4j/lf5/viewer/images/lf5_small_icon.gif"
    URL lf5IconURL = getClass().getResource(resource); 
 
    if (lf5IconURL != null) { 
      _logMonitorFrame.setIconImage(new ImageIcon(lf5IconURL).getImage()); 
    } 
    updateFrameSize(); 
 
    // 
    // Configure the LogTable. 
    // 
    JTextArea detailTA = createDetailTextArea(); 
    JScrollPane detailTAScrollPane = new JScrollPane(detailTA); 
    _table = new LogTable(detailTA); 
    setView(_currentView, _table); 
    _table.setFont(new Font(_fontName, Font.PLAIN, _fontSize)); 
    _logTableScrollPane = new JScrollPane(_table); 
 
    if (_trackTableScrollPane) { 
      _logTableScrollPane.getVerticalScrollBar().addAdjustmentListener( 
          new TrackingAdjustmentListener() 
      ); 
    } 
 
 
    // Configure the SplitPane between the LogTable & DetailTextArea 
    // 
 
    JSplitPane tableViewerSplitPane = new JSplitPane(); 
    tableViewerSplitPane.setOneTouchExpandable(true); 
    tableViewerSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); 
    tableViewerSplitPane.setLeftComponent(_logTableScrollPane); 
    tableViewerSplitPane.setRightComponent(detailTAScrollPane); 
    // Make sure to do this last.. 
    //tableViewerSplitPane.setDividerLocation(1.0); Doesn't work 
    //the same under 1.2.x & 1.3 
    // "350" is a magic number that provides the correct default 
    // behaviour under 1.2.x & 1.3.  For example, bumping this 
    // number to 400, causes the pane to be completely open in 1.2.x 
    // and closed in 1.3 
    tableViewerSplitPane.setDividerLocation(350); 
 
    // 
    // Configure the CategoryExplorer 
    // 
 
    _categoryExplorerTree = new CategoryExplorerTree(); 
 
    _table.getFilteredLogTableModel().setLogRecordFilter(createLogRecordFilter()); 
 
    JScrollPane categoryExplorerTreeScrollPane = 
        new JScrollPane(_categoryExplorerTree); 
    categoryExplorerTreeScrollPane.setPreferredSize(new Dimension(130400)); 
 
    // Load most recently used file list 
    _mruFileManager = new MRUFileManager(); 
 
    // 
    // Configure the SplitPane between the CategoryExplorer & (LogTable/Detail) 
    // 
 
    JSplitPane splitPane = new JSplitPane(); 
    splitPane.setOneTouchExpandable(true); 
    splitPane.setRightComponent(tableViewerSplitPane); 
    splitPane.setLeftComponent(categoryExplorerTreeScrollPane); 
    // Do this last. 
    splitPane.setDividerLocation(130); 
    // 
    // Add the MenuBar, StatusArea, CategoryExplorer|LogTable to the 
    // LogMonitorFrame. 
    // 
    _logMonitorFrame.getRootPane().setJMenuBar(createMenuBar()); 
    _logMonitorFrame.getContentPane().add(splitPane, BorderLayout.CENTER); 
    _logMonitorFrame.getContentPane().add(createToolBar(), 
        BorderLayout.NORTH); 
    _logMonitorFrame.getContentPane().add(createStatusArea(), 
        BorderLayout.SOUTH); 
 
    makeLogTableListenToCategoryExplorer(); 
    addTableModelProperties(); 
 
    // 
    // Configure ConfigurationManager 
    // 
    _configurationManager = new ConfigurationManager(this, _table); 
 
  } 
 
  protected LogRecordFilter createLogRecordFilter() { 
    LogRecordFilter result = new LogRecordFilter() { 
      public boolean passes(LogRecord record) { 
        CategoryPath path = new CategoryPath(record.getCategory()); 
        return 
            getMenuItem(record.getLevel()).isSelected() && 
            _categoryExplorerTree.getExplorerModel().isCategoryPathActive(path); 
      } 
    }; 
    return result; 
  } 
 
  // Added in version 1.2 - Creates a new filter that sorts records based on 
  // an NDC string passed in by the user. 
  protected LogRecordFilter createNDCLogRecordFilter(String text) { 
    _NDCTextFilter = text; 
    LogRecordFilter result = new LogRecordFilter() { 
      public boolean passes(LogRecord record) { 
        String NDC = record.getNDC(); 
        CategoryPath path = new CategoryPath(record.getCategory()); 
        if (NDC == null || _NDCTextFilter == null) { 
          return false
        } else if (NDC.toLowerCase().indexOf(_NDCTextFilter.toLowerCase()) == -1) { 
          return false
        } else { 
          return getMenuItem(record.getLevel()).isSelected() && 
              _categoryExplorerTree.getExplorerModel().isCategoryPathActive(path); 
        } 
      } 
    }; 
 
    return result; 
  } 
 
 
  protected void updateStatusLabel() { 
    _statusLabel.setText(getRecordsDisplayedMessage()); 
  } 
 
  protected String getRecordsDisplayedMessage() { 
    FilteredLogTableModel model = _table.getFilteredLogTableModel(); 
    return getStatusText(model.getRowCount(), model.getTotalRowCount()); 
  } 
 
  protected void addTableModelProperties() { 
    final FilteredLogTableModel model = _table.getFilteredLogTableModel(); 
 
    addDisplayedProperty(new Object() { 
      public String toString() { 
        return getRecordsDisplayedMessage(); 
      } 
    }); 
    addDisplayedProperty(new Object() { 
      public String toString() { 
        return "Maximum number of displayed LogRecords: " 
            + model._maxNumberOfLogRecords; 
      } 
    }); 
  } 
 
  protected String getStatusText(int displayedRows, int totalRows) { 
    StringBuffer result = new StringBuffer(); 
    result.append("Displaying: "); 
    result.append(displayedRows); 
    result.append(" records out of a total of: "); 
    result.append(totalRows); 
    result.append(" records."); 
    return result.toString(); 
  } 
 
  protected void makeLogTableListenToCategoryExplorer() { 
    ActionListener listener = new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        _table.getFilteredLogTableModel().refresh(); 
        updateStatusLabel(); 
      } 
    }; 
    _categoryExplorerTree.getExplorerModel().addActionListener(listener); 
  } 
 
  protected JPanel createStatusArea() { 
    JPanel statusArea = new JPanel(); 
    JLabel status = 
        new JLabel("No log records to display."); 
    _statusLabel = status; 
    status.setHorizontalAlignment(JLabel.LEFT); 
 
    statusArea.setBorder(BorderFactory.createEtchedBorder()); 
    statusArea.setLayout(new FlowLayout(FlowLayout.LEFT, 00)); 
    statusArea.add(status); 
 
    return (statusArea); 
  } 
 
  protected JTextArea createDetailTextArea() { 
    JTextArea detailTA = new JTextArea(); 
    detailTA.setFont(new Font("Monospaced", Font.PLAIN, 14)); 
    detailTA.setTabSize(3); 
    detailTA.setLineWrap(true); 
    detailTA.setWrapStyleWord(false); 
    return (detailTA); 
  } 
 
  protected JMenuBar createMenuBar() { 
    JMenuBar menuBar = new JMenuBar(); 
    menuBar.add(createFileMenu()); 
    menuBar.add(createEditMenu()); 
    menuBar.add(createLogLevelMenu()); 
    menuBar.add(createViewMenu()); 
    menuBar.add(createConfigureMenu()); 
    menuBar.add(createHelpMenu()); 
 
    return (menuBar); 
  } 
 
  protected JMenu createLogLevelMenu() { 
    JMenu result = new JMenu("Log Level"); 
    result.setMnemonic('l'); 
    Iterator levels = getLogLevels(); 
    while (levels.hasNext()) { 
      result.add(getMenuItem((LogLevel) levels.next())); 
    } 
 
    result.addSeparator(); 
    result.add(createAllLogLevelsMenuItem()); 
    result.add(createNoLogLevelsMenuItem()); 
    result.addSeparator(); 
    result.add(createLogLevelColorMenu()); 
    result.add(createResetLogLevelColorMenuItem()); 
 
    return result; 
  } 
 
  protected JMenuItem createAllLogLevelsMenuItem() { 
    JMenuItem result = new JMenuItem("Show all LogLevels"); 
    result.setMnemonic('s'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        selectAllLogLevels(true); 
        _table.getFilteredLogTableModel().refresh(); 
        updateStatusLabel(); 
      } 
    }); 
    return result; 
  } 
 
  protected JMenuItem createNoLogLevelsMenuItem() { 
    JMenuItem result = new JMenuItem("Hide all LogLevels"); 
    result.setMnemonic('h'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        selectAllLogLevels(false); 
        _table.getFilteredLogTableModel().refresh(); 
        updateStatusLabel(); 
      } 
    }); 
    return result; 
  } 
 
  protected JMenu createLogLevelColorMenu() { 
    JMenu colorMenu = new JMenu("Configure LogLevel Colors"); 
    colorMenu.setMnemonic('c'); 
    Iterator levels = getLogLevels(); 
    while (levels.hasNext()) { 
      colorMenu.add(createSubMenuItem((LogLevel) levels.next())); 
    } 
 
    return colorMenu; 
  } 
 
  protected JMenuItem createResetLogLevelColorMenuItem() { 
    JMenuItem result = new JMenuItem("Reset LogLevel Colors"); 
    result.setMnemonic('r'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        // reset the level colors in the map 
        LogLevel.resetLogLevelColorMap(); 
 
        // refresh the table 
        _table.getFilteredLogTableModel().refresh(); 
      } 
    }); 
    return result; 
  } 
 
  protected void selectAllLogLevels(boolean selected) { 
    Iterator levels = getLogLevels(); 
    while (levels.hasNext()) { 
      getMenuItem((LogLevel) levels.next()).setSelected(selected); 
    } 
  } 
 
  protected JCheckBoxMenuItem getMenuItem(LogLevel level) { 
    JCheckBoxMenuItem result = (JCheckBoxMenuItem) (_logLevelMenuItems.get(level)); 
    if (result == null) { 
      result = createMenuItem(level); 
      _logLevelMenuItems.put(level, result); 
    } 
    return result; 
  } 
 
  protected JMenuItem createSubMenuItem(LogLevel level) { 
    final JMenuItem result = new JMenuItem(level.toString()); 
    final LogLevel logLevel = level; 
    result.setMnemonic(level.toString().charAt(0)); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        showLogLevelColorChangeDialog(result, logLevel); 
      } 
    }); 
 
    return result; 
 
  } 
 
  protected void showLogLevelColorChangeDialog(JMenuItem result, LogLevel level) { 
    JMenuItem menuItem = result; 
    Color newColor = JColorChooser.showDialog( 
        _logMonitorFrame, 
        "Choose LogLevel Color"
        result.getForeground()); 
 
    if (newColor != null) { 
      // set the color for the record 
      level.setLogLevelColorMap(level, newColor); 
      _table.getFilteredLogTableModel().refresh(); 
    } 
 
  } 
 
  protected JCheckBoxMenuItem createMenuItem(LogLevel level) { 
    JCheckBoxMenuItem result = new JCheckBoxMenuItem(level.toString()); 
    result.setSelected(true); 
    result.setMnemonic(level.toString().charAt(0)); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        _table.getFilteredLogTableModel().refresh(); 
        updateStatusLabel(); 
      } 
    }); 
    return result; 
  } 
 
  // view menu 
  protected JMenu createViewMenu() { 
    JMenu result = new JMenu("View"); 
    result.setMnemonic('v'); 
    Iterator columns = getLogTableColumns(); 
    while (columns.hasNext()) { 
      result.add(getLogTableColumnMenuItem((LogTableColumn) columns.next())); 
    } 
 
    result.addSeparator(); 
    result.add(createAllLogTableColumnsMenuItem()); 
    result.add(createNoLogTableColumnsMenuItem()); 
    return result; 
  } 
 
  protected JCheckBoxMenuItem getLogTableColumnMenuItem(LogTableColumn column) { 
    JCheckBoxMenuItem result = (JCheckBoxMenuItem) (_logTableColumnMenuItems.get(column)); 
    if (result == null) { 
      result = createLogTableColumnMenuItem(column); 
      _logTableColumnMenuItems.put(column, result); 
    } 
    return result; 
  } 
 
  protected JCheckBoxMenuItem createLogTableColumnMenuItem(LogTableColumn column) { 
    JCheckBoxMenuItem result = new JCheckBoxMenuItem(column.toString()); 
 
    result.setSelected(true); 
    result.setMnemonic(column.toString().charAt(0)); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        // update list of columns and reset the view 
        List selectedColumns = updateView(); 
        _table.setView(selectedColumns); 
      } 
    }); 
    return result; 
  } 
 
  protected List updateView() { 
    ArrayList updatedList = new ArrayList(); 
    Iterator columnIterator = _columns.iterator(); 
    while (columnIterator.hasNext()) { 
      LogTableColumn column = (LogTableColumn) columnIterator.next(); 
      JCheckBoxMenuItem result = getLogTableColumnMenuItem(column); 
      // check and see if the checkbox is checked 
      if (result.isSelected()) { 
        updatedList.add(column); 
      } 
    } 
 
    return updatedList; 
  } 
 
  protected JMenuItem createAllLogTableColumnsMenuItem() { 
    JMenuItem result = new JMenuItem("Show all Columns"); 
    result.setMnemonic('s'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        selectAllLogTableColumns(true); 
        // update list of columns and reset the view 
        List selectedColumns = updateView(); 
        _table.setView(selectedColumns); 
      } 
    }); 
    return result; 
  } 
 
  protected JMenuItem createNoLogTableColumnsMenuItem() { 
    JMenuItem result = new JMenuItem("Hide all Columns"); 
    result.setMnemonic('h'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        selectAllLogTableColumns(false); 
        // update list of columns and reset the view 
        List selectedColumns = updateView(); 
        _table.setView(selectedColumns); 
      } 
    }); 
    return result; 
  } 
 
  protected void selectAllLogTableColumns(boolean selected) { 
    Iterator columns = getLogTableColumns(); 
    while (columns.hasNext()) { 
      getLogTableColumnMenuItem((LogTableColumn) columns.next()).setSelected(selected); 
    } 
  } 
 
  protected JMenu createFileMenu() { 
    JMenu fileMenu = new JMenu("File"); 
    fileMenu.setMnemonic('f'); 
    JMenuItem exitMI; 
    fileMenu.add(createOpenMI()); 
    fileMenu.add(createOpenURLMI()); 
    fileMenu.addSeparator(); 
    fileMenu.add(createCloseMI()); 
    createMRUFileListMI(fileMenu); 
    fileMenu.addSeparator(); 
    fileMenu.add(createExitMI()); 
    return fileMenu; 
  } 
 
  /**
   * Menu item added to allow log files to be opened with 
   * the LF5 GUI. 
   */
 
  protected JMenuItem createOpenMI() { 
    JMenuItem result = new JMenuItem("Open..."); 
    result.setMnemonic('o'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        requestOpen(); 
      } 
    }); 
    return result; 
  } 
 
  /**
   * Menu item added to allow log files loaded from a URL 
   * to be opened by the LF5 GUI. 
   */
 
  protected JMenuItem createOpenURLMI() { 
    JMenuItem result = new JMenuItem("Open URL..."); 
    result.setMnemonic('u'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        requestOpenURL(); 
      } 
    }); 
    return result; 
  } 
 
  protected JMenuItem createCloseMI() { 
    JMenuItem result = new JMenuItem("Close"); 
    result.setMnemonic('c'); 
    result.setAccelerator(KeyStroke.getKeyStroke("control Q")); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        requestClose(); 
      } 
    }); 
    return result; 
  } 
 
  /**
   * Creates a Most Recently Used file list to be 
   * displayed in the File menu 
   */
 
  protected void createMRUFileListMI(JMenu menu) { 
 
    String[] files = _mruFileManager.getMRUFileList(); 
 
    if (files != null) { 
      menu.addSeparator(); 
      for (int i = 0; i < files.length; i++) { 
        JMenuItem result = new JMenuItem((i + 1) + " " + files[i]); 
        result.setMnemonic(i + 1); 
        result.addActionListener(new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            requestOpenMRU(e); 
          } 
        }); 
        menu.add(result); 
      } 
    } 
  } 
 
  protected JMenuItem createExitMI() { 
    JMenuItem result = new JMenuItem("Exit"); 
    result.setMnemonic('x'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        requestExit(); 
      } 
    }); 
    return result; 
  } 
 
  protected JMenu createConfigureMenu() { 
    JMenu configureMenu = new JMenu("Configure"); 
    configureMenu.setMnemonic('c'); 
    configureMenu.add(createConfigureSave()); 
    configureMenu.add(createConfigureReset()); 
    configureMenu.add(createConfigureMaxRecords()); 
 
    return configureMenu; 
  } 
 
  protected JMenuItem createConfigureSave() { 
    JMenuItem result = new JMenuItem("Save"); 
    result.setMnemonic('s'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        saveConfiguration(); 
      } 
    }); 
 
    return result; 
  } 
 
  protected JMenuItem createConfigureReset() { 
    JMenuItem result = new JMenuItem("Reset"); 
    result.setMnemonic('r'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        resetConfiguration(); 
      } 
    }); 
 
    return result; 
  } 
 
  protected JMenuItem createConfigureMaxRecords() { 
    JMenuItem result = new JMenuItem("Set Max Number of Records"); 
    result.setMnemonic('m'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        setMaxRecordConfiguration(); 
      } 
    }); 
 
    return result; 
  } 
 
 
  protected void saveConfiguration() { 
    _configurationManager.save(); 
  } 
 
  protected void resetConfiguration() { 
    _configurationManager.reset(); 
  } 
 
  protected void setMaxRecordConfiguration() { 
    LogFactor5InputDialog inputDialog = new LogFactor5InputDialog( 
        getBaseFrame(), "Set Max Number of Records"""10); 
 
    String temp = inputDialog.getText(); 
 
    if (temp != null) { 
      try { 
        setMaxNumberOfLogRecords(Integer.parseInt(temp)); 
      } catch (NumberFormatException e) { 
        LogFactor5ErrorDialog error = new LogFactor5ErrorDialog( 
            getBaseFrame(), 
            "'" + temp + "' is an invalid parameter.\nPlease try again."); 
        setMaxRecordConfiguration(); 
      } 
    } 
  } 
 
 
  protected JMenu createHelpMenu() { 
    JMenu helpMenu = new JMenu("Help"); 
    helpMenu.setMnemonic('h'); 
    helpMenu.add(createHelpProperties()); 
    return helpMenu; 
  } 
 
  protected JMenuItem createHelpProperties() { 
    final String title = "LogFactor5 Properties"
    final JMenuItem result = new JMenuItem(title); 
    result.setMnemonic('l'); 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        showPropertiesDialog(title); 
      } 
    }); 
    return result; 
  } 
 
  protected void showPropertiesDialog(String title) { 
    JOptionPane.showMessageDialog( 
        _logMonitorFrame, 
        _displayedLogBrokerProperties.toArray(), 
        title, 
        JOptionPane.PLAIN_MESSAGE 
    ); 
  } 
 
  protected JMenu createEditMenu() { 
    JMenu editMenu = new JMenu("Edit"); 
    editMenu.setMnemonic('e'); 
    editMenu.add(createEditFindMI()); 
    editMenu.add(createEditFindNextMI()); 
    editMenu.addSeparator(); 
    editMenu.add(createEditSortNDCMI()); 
    editMenu.add(createEditRestoreAllNDCMI()); 
    return editMenu; 
  } 
 
  protected JMenuItem createEditFindNextMI() { 
    JMenuItem editFindNextMI = new JMenuItem("Find Next"); 
    editFindNextMI.setMnemonic('n'); 
    editFindNextMI.setAccelerator(KeyStroke.getKeyStroke("F3")); 
    editFindNextMI.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        findSearchText(); 
      } 
    }); 
    return editFindNextMI; 
  } 
 
  protected JMenuItem createEditFindMI() { 
    JMenuItem editFindMI = new JMenuItem("Find"); 
    editFindMI.setMnemonic('f'); 
    editFindMI.setAccelerator(KeyStroke.getKeyStroke("control F")); 
 
    editFindMI.addActionListener( 
        new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            String inputValue = 
                JOptionPane.showInputDialog( 
                    _logMonitorFrame, 
                    "Find text: "
                    "Search Record Messages"
                    JOptionPane.QUESTION_MESSAGE 
                ); 
            setSearchText(inputValue); 
            findSearchText(); 
          } 
        } 
 
    ); 
    return editFindMI; 
  } 
 
  // Added version 1.2 - Allows users to Sort Log Records by an 
  // NDC text filter. A new LogRecordFilter was created to 
  // sort the records. 
  protected JMenuItem createEditSortNDCMI() { 
    JMenuItem editSortNDCMI = new JMenuItem("Sort by NDC"); 
    editSortNDCMI.setMnemonic('s'); 
    editSortNDCMI.addActionListener( 
        new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            String inputValue = 
                JOptionPane.showInputDialog( 
                    _logMonitorFrame, 
                    "Sort by this NDC: "
                    "Sort Log Records by NDC"
                    JOptionPane.QUESTION_MESSAGE 
                ); 
            setNDCTextFilter(inputValue); 
            sortByNDC(); 
            _table.getFilteredLogTableModel().refresh(); 
            updateStatusLabel(); 
          } 
        } 
 
    ); 
    return editSortNDCMI; 
  } 
 
  // Added in version 1.2 - Resets the LogRecordFilter back to default 
  // filter. 
  protected JMenuItem createEditRestoreAllNDCMI() { 
    JMenuItem editRestoreAllNDCMI = new JMenuItem("Restore all NDCs"); 
    editRestoreAllNDCMI.setMnemonic('r'); 
    editRestoreAllNDCMI.addActionListener( 
        new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            _table.getFilteredLogTableModel().setLogRecordFilter(createLogRecordFilter()); 
            // reset the text filter 
            setNDCTextFilter(""); 
            _table.getFilteredLogTableModel().refresh(); 
            updateStatusLabel(); 
          } 
        } 
    ); 
    return editRestoreAllNDCMI; 
  } 
 
  protected JToolBar createToolBar() { 
    JToolBar tb = new JToolBar(); 
    tb.putClientProperty("JToolBar.isRollover", Boolean.TRUE); 
    JComboBox fontCombo = new JComboBox(); 
    JComboBox fontSizeCombo = new JComboBox(); 
    _fontSizeCombo = fontSizeCombo; 
 
    ClassLoader cl = this.getClass().getClassLoader(); 
    if(cl == null) { 
        cl = ClassLoader.getSystemClassLoader(); 
    } 
    URL newIconURL = cl.getResource("org/apache/log4j/lf5/viewer/" + 
        "images/channelexplorer_new.gif"); 
 
    ImageIcon newIcon = null
 
    if (newIconURL != null) { 
      newIcon = new ImageIcon(newIconURL); 
    } 
 
    JButton newButton = new JButton("Clear Log Table"); 
 
    if (newIcon != null) { 
      newButton.setIcon(newIcon); 
    } 
 
    newButton.setToolTipText("Clear Log Table."); 
    //newButton.setBorder(BorderFactory.createEtchedBorder()); 
 
    newButton.addActionListener( 
        new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            _table.clearLogRecords(); 
            _categoryExplorerTree.getExplorerModel().resetAllNodeCounts(); 
            updateStatusLabel(); 
            clearDetailTextArea(); 
            LogRecord.resetSequenceNumber(); 
          } 
        } 
    ); 
 
    Toolkit tk = Toolkit.getDefaultToolkit(); 
    // This will actually grab all the fonts 
 
    String[] fonts; 
 
    if (_loadSystemFonts) { 
      fonts = GraphicsEnvironment. 
          getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); 
    } else { 
      fonts = tk.getFontList(); 
    } 
 
    for (int j = 0; j < fonts.length; j++) { 
      fontCombo.addItem(fonts[j]); 
    } 
 
    fontCombo.setSelectedItem(_fontName); 
 
    fontCombo.addActionListener( 
 
        new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            JComboBox box = (JComboBox) e.getSource(); 
            String font = (String) box.getSelectedItem(); 
            _table.setFont(new Font(font, Font.PLAIN, _fontSize)); 
            _fontName = font; 
          } 
        } 
    ); 
 
    fontSizeCombo.addItem("8"); 
    fontSizeCombo.addItem("9"); 
    fontSizeCombo.addItem("10"); 
    fontSizeCombo.addItem("12"); 
    fontSizeCombo.addItem("14"); 
    fontSizeCombo.addItem("16"); 
    fontSizeCombo.addItem("18"); 
    fontSizeCombo.addItem("24"); 
 
    fontSizeCombo.setSelectedItem(String.valueOf(_fontSize)); 
    fontSizeCombo.addActionListener( 
        new ActionListener() { 
          public void actionPerformed(ActionEvent e) { 
            JComboBox box = (JComboBox) e.getSource(); 
            String size = (String) box.getSelectedItem(); 
            int s = Integer.valueOf(size).intValue(); 
 
            setFontSizeSilently(s); 
            refreshDetailTextArea(); 
            _fontSize = s; 
          } 
        } 
    ); 
 
    tb.add(new JLabel(" Font: ")); 
    tb.add(fontCombo); 
    tb.add(fontSizeCombo); 
    tb.addSeparator(); 
    tb.addSeparator(); 
    tb.add(newButton); 
 
    newButton.setAlignmentY(0.5f); 
    newButton.setAlignmentX(0.5f); 
 
    fontCombo.setMaximumSize(fontCombo.getPreferredSize()); 
    fontSizeCombo.setMaximumSize( 
        fontSizeCombo.getPreferredSize()); 
 
    return (tb); 
  } 
 
//    protected void setView(String viewString, LogTable table) { 
//        if (STANDARD_VIEW.equals(viewString)) { 
//            table.setStandardView(); 
//        } else if (COMPACT_VIEW.equals(viewString)) { 
//            table.setCompactView(); 
//        } else if (DETAILED_VIEW.equals(viewString)) { 
//            table.setDetailedView(); 
//        } else { 
//            String message = viewString + "does not match a supported view."; 
//            throw new IllegalArgumentException(message); 
//        } 
//        _currentView = viewString; 
//    } 
 
  protected void setView(String viewString, LogTable table) { 
    if (DETAILED_VIEW.equals(viewString)) { 
      table.setDetailedView(); 
    } else { 
      String message = viewString + "does not match a supported view."
      throw new IllegalArgumentException(message); 
    } 
    _currentView = viewString; 
  } 
 
  protected JComboBox createLogLevelCombo() { 
    JComboBox result = new JComboBox(); 
    Iterator levels = getLogLevels(); 
    while (levels.hasNext()) { 
      result.addItem(levels.next()); 
    } 
    result.setSelectedItem(_leastSevereDisplayedLogLevel); 
 
    result.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
        JComboBox box = (JComboBox) e.getSource(); 
        LogLevel level = (LogLevel) box.getSelectedItem(); 
        setLeastSevereDisplayedLogLevel(level); 
      } 
    }); 
    result.setMaximumSize(result.getPreferredSize()); 
    return result; 
  } 
 
  protected void setLeastSevereDisplayedLogLevel(LogLevel level) { 
    if (level == null || _leastSevereDisplayedLogLevel == level) { 
      return// nothing to do 
    } 
    _leastSevereDisplayedLogLevel = level; 
    _table.getFilteredLogTableModel().refresh(); 
    updateStatusLabel(); 
  } 
 
  /**
   * Ensures that the Table's ScrollPane Viewport will "track" with updates 
   * to the Table.  When the vertical scroll bar is at its bottom anchor 
   * and tracking is enabled then viewport will stay at the bottom most 
   * point of the component.  The purpose of this feature is to allow 
   * a developer to watch the table as messages arrive and not have to 
   * scroll after each new message arrives.  When the vertical scroll bar 
   * is at any other location, then no tracking will happen. 
   * @deprecated tracking is now done automatically. 
   */
 
  protected void trackTableScrollPane() { 
    // do nothing 
  } 
 
  protected void centerFrame(JFrame frame) { 
    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); 
    Dimension comp = frame.getSize(); 
 
    frame.setLocation(((screen.width - comp.width) / 2), 
        ((screen.height - comp.height) / 2)); 
 
  } 
 
  /**
   * Uses a JFileChooser to select a file to opened with the 
   * LF5 GUI. 
   */
 
  protected void requestOpen() { 
    JFileChooser chooser; 
 
    if (_fileLocation == null) { 
      chooser = new JFileChooser(); 
    } else { 
      chooser = new JFileChooser(_fileLocation); 
    } 
 
    int returnVal = chooser.showOpenDialog(_logMonitorFrame); 
    if (returnVal == JFileChooser.APPROVE_OPTION) { 
      File f = chooser.getSelectedFile(); 
      if (loadLogFile(f)) { 
        _fileLocation = chooser.getSelectedFile(); 
        _mruFileManager.set(f); 
        updateMRUList(); 
      } 
    } 
  } 
 
  /**
   * Uses a Dialog box to accept a URL to a file to be opened 
   * with the LF5 GUI. 
   */
 
  protected void requestOpenURL() { 
    LogFactor5InputDialog inputDialog = new LogFactor5InputDialog( 
        getBaseFrame(), "Open URL""URL:"); 
    String temp = inputDialog.getText(); 
 
    if (temp != null) { 
      if (temp.indexOf("://") == -1) { 
        temp = "http://" + temp; 
      } 
 
      try { 
        URL url = new URL(temp); 
        if (loadLogFile(url)) { 
          _mruFileManager.set(url); 
          updateMRUList(); 
        } 
      } catch (MalformedURLException e) { 
        LogFactor5ErrorDialog error = new LogFactor5ErrorDialog( 
            getBaseFrame(), "Error reading URL."); 
      } 
    } 
  } 
 
  /**
   * Removes old file list and creates a new file list 
   * with the updated MRU list. 
   */
 
  protected void updateMRUList() { 
    JMenu menu = _logMonitorFrame.getJMenuBar().getMenu(0); 
    menu.removeAll(); 
    menu.add(createOpenMI()); 
    menu.add(createOpenURLMI()); 
    menu.addSeparator(); 
    menu.add(createCloseMI()); 
    createMRUFileListMI(menu); 
    menu.addSeparator(); 
    menu.add(createExitMI()); 
  } 
 
  protected void requestClose() { 
    setCallSystemExitOnClose(false); 
    closeAfterConfirm(); 
  } 
 
  /**
   * Opens a file in the MRU list. 
   */
 
  protected void requestOpenMRU(ActionEvent e) { 
    String file = e.getActionCommand(); 
    StringTokenizer st = new StringTokenizer(file); 
    String num = st.nextToken().trim(); 
    file = st.nextToken("\n"); 
 
    try { 
      int index = Integer.parseInt(num) - 1
 
      InputStream in = _mruFileManager.getInputStream(index); 
      LogFileParser lfp = new LogFileParser(in); 
      lfp.parse(this); 
 
      _mruFileManager.moveToTop(index); 
      updateMRUList(); 
 
    } catch (Exception me) { 
      LogFactor5ErrorDialog error = new LogFactor5ErrorDialog( 
          getBaseFrame(), "Unable to load file " + file); 
    } 
 
  } 
 
  protected void requestExit() { 
    _mruFileManager.save(); 
    setCallSystemExitOnClose(true); 
    closeAfterConfirm(); 
  } 
 
  protected void closeAfterConfirm() { 
    StringBuffer message = new StringBuffer(); 
 
    if (_callSystemExitOnClose == false) { 
      message.append("Are you sure you want to close the logging "); 
      message.append("console?\n"); 
      message.append("(Note: This will not shut down the Virtual Machine,\n"); 
      message.append("or the Swing event thread.)"); 
    } else { 
      message.append("Are you sure you want to exit?\n"); 
      message.append("This will shut down the Virtual Machine.\n"); 
    } 
 
    String title = 
        "Are you sure you want to dispose of the Logging Console?"
 
    if (_callSystemExitOnClose == true) { 
      title = "Are you sure you want to exit?"
    } 
    int value = JOptionPane.showConfirmDialog( 
        _logMonitorFrame, 
        message.toString(), 
        title, 
        JOptionPane.OK_CANCEL_OPTION, 
        JOptionPane.QUESTION_MESSAGE, 
        null 
    ); 
 
    if (value == JOptionPane.OK_OPTION) { 
      dispose(); 
    } 
  } 
 
  protected Iterator getLogLevels() { 
    return _levels.iterator(); 
  } 
 
  protected Iterator getLogTableColumns() { 
    return _columns.iterator(); 
  } 
 
  /**
   * Loads and parses a log file. 
   */
 
  protected boolean loadLogFile(File file) { 
    boolean ok = false
    try { 
      LogFileParser lfp = new LogFileParser(file); 
      lfp.parse(this); 
      ok = true
    } catch (IOException e) { 
      LogFactor5ErrorDialog error = new LogFactor5ErrorDialog( 
          getBaseFrame(), "Error reading " + file.getName()); 
    } 
 
    return ok; 
  } 
 
  /**
   * Loads a parses a log file running on a server. 
   */
 
  protected boolean loadLogFile(URL url) { 
    boolean ok = false
    try { 
      LogFileParser lfp = new LogFileParser(url.openStream()); 
      lfp.parse(this); 
      ok = true
    } catch (IOException e) { 
      LogFactor5ErrorDialog error = new LogFactor5ErrorDialog( 
          getBaseFrame(), "Error reading URL:" + url.getFile()); 
    } 
    return ok; 
  } 
  //-------------------------------------------------------------------------- 
  //   Private Methods: 
  //-------------------------------------------------------------------------- 
 
  //-------------------------------------------------------------------------- 
  //   Nested Top-Level Classes or Interfaces: 
  //-------------------------------------------------------------------------- 
 
  class LogBrokerMonitorWindowAdaptor extends WindowAdapter { 
    protected LogBrokerMonitor _monitor; 
 
    public LogBrokerMonitorWindowAdaptor(LogBrokerMonitor monitor) { 
      _monitor = monitor; 
    } 
 
    public void windowClosing(WindowEvent ev) { 
      _monitor.requestClose(); 
    } 
  } 
}