logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From grobme...@apache.org
Subject svn commit: r1345492 [14/18] - in /logging/log4j/branches/log4j12modules: ./ contribs/ contribs/CekiGulcu/ contribs/EirikLygre/ contribs/JamesHouse/ contribs/Jamie Tsao/ contribs/JimMoore/ contribs/KevinSteppe/ contribs/KitchingSimon/ contribs/LeosLite...
Date Sat, 02 Jun 2012 11:41:11 GMT
Added: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java (added)
+++ logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,1612 @@
+/*
+ * 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(130, 400));
+
+    // 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, 0, 0));
+    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();
+    }
+  }
+}
+
+

Propchange: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java (added)
+++ logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,151 @@
+/*
+ * 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.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Label;
+import java.awt.Toolkit;
+import java.awt.Window;
+
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+
+/**
+ * LogFactor5Dialog
+ *
+ * @author Richard Hurst
+ * @author Brad Marlborough
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public abstract class LogFactor5Dialog extends JDialog {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+  protected static final Font DISPLAY_FONT = new Font("Arial", Font.BOLD, 12);
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+  protected LogFactor5Dialog(JFrame jframe, String message, boolean modal) {
+    super(jframe, message, modal);
+  }
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+  public void show() {
+    pack();
+    minimumSizeDialog(this, 200, 100);
+    centerWindow(this);
+    super.show();
+  }
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+  protected void centerWindow(Window win) {
+    Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
+
+    // If larger than screen, reduce window width or height
+    if (screenDim.width < win.getSize().width) {
+      win.setSize(screenDim.width, win.getSize().height);
+    }
+
+    if (screenDim.height < win.getSize().height) {
+      win.setSize(win.getSize().width, screenDim.height);
+    }
+
+    // Center Frame, Dialogue or Window on screen
+    int x = (screenDim.width - win.getSize().width) / 2;
+    int y = (screenDim.height - win.getSize().height) / 2;
+    win.setLocation(x, y);
+  }
+
+  protected void wrapStringOnPanel(String message,
+      Container container) {
+    GridBagConstraints c = getDefaultConstraints();
+    c.gridwidth = GridBagConstraints.REMAINDER;
+    // Insets() args are top, left, bottom, right
+    c.insets = new Insets(0, 0, 0, 0);
+    GridBagLayout gbLayout = (GridBagLayout) container.getLayout();
+
+
+    while (message.length() > 0) {
+      int newLineIndex = message.indexOf('\n');
+      String line;
+      if (newLineIndex >= 0) {
+        line = message.substring(0, newLineIndex);
+        message = message.substring(newLineIndex + 1);
+      } else {
+        line = message;
+        message = "";
+      }
+      Label label = new Label(line);
+      label.setFont(DISPLAY_FONT);
+      gbLayout.setConstraints(label, c);
+      container.add(label);
+    }
+  }
+
+  protected GridBagConstraints getDefaultConstraints() {
+    GridBagConstraints constraints = new GridBagConstraints();
+    constraints.weightx = 1.0;
+    constraints.weighty = 1.0;
+    constraints.gridheight = 1; // One row high
+    // Insets() args are top, left, bottom, right
+    constraints.insets = new Insets(4, 4, 4, 4);
+    // fill of NONE means do not change size
+    constraints.fill = GridBagConstraints.NONE;
+    // WEST means align left
+    constraints.anchor = GridBagConstraints.WEST;
+
+    return constraints;
+  }
+
+  protected void minimumSizeDialog(Component component,
+      int minWidth,
+      int minHeight) {
+    // set the min width
+    if (component.getSize().width < minWidth)
+      component.setSize(minWidth, component.getSize().height);
+    // set the min height
+    if (component.getSize().height < minHeight)
+      component.setSize(component.getSize().width, minHeight);
+  }
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces
+  //--------------------------------------------------------------------------
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5ErrorDialog.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5ErrorDialog.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5ErrorDialog.java (added)
+++ logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5ErrorDialog.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,92 @@
+/*
+ * 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.FlowLayout;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+/**
+ * LogFactor5ErrorDialog
+ *
+ * @author Richard Hurst
+ * @author Brad Marlborough
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class LogFactor5ErrorDialog extends LogFactor5Dialog {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+  public LogFactor5ErrorDialog(JFrame jframe, String message) {
+    super(jframe, "Error", true);
+
+    JButton ok = new JButton("Ok");
+    ok.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        hide();
+      }
+    });
+
+    JPanel bottom = new JPanel();
+    bottom.setLayout(new FlowLayout());
+    bottom.add(ok);
+
+    JPanel main = new JPanel();
+    main.setLayout(new GridBagLayout());
+    wrapStringOnPanel(message, main);
+
+    getContentPane().add(main, BorderLayout.CENTER);
+    getContentPane().add(bottom, BorderLayout.SOUTH);
+    show();
+
+  }
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces
+  //--------------------------------------------------------------------------
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5ErrorDialog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5InputDialog.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5InputDialog.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5InputDialog.java (added)
+++ logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5InputDialog.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,145 @@
+/*
+ * 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 javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+/**
+ * LogFactor5InputDialog
+ *
+ * Creates a popup input dialog box so that users can enter
+ * a URL to open a log file from.
+ *
+ * @author Richard Hurst
+ * @author Brad Marlborough
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class LogFactor5InputDialog extends LogFactor5Dialog {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+  public static final int SIZE = 30;
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+  private JTextField _textField;
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Configures an input dialog box using a defualt size for the text field.
+   * param jframe the frame where the dialog will be loaded from.
+   * param title the title of the dialog box.
+   * param label the label to be put in the dialog box.
+   */
+  public LogFactor5InputDialog(JFrame jframe, String title, String label) {
+    this(jframe, title, label, SIZE);
+  }
+
+  /**
+   * Configures an input dialog box.
+   * param jframe the frame where the dialog will be loaded from.
+   * param title the title of the dialog box.
+   * param label the label to be put in the dialog box.
+   * param size the size of the text field.
+   */
+  public LogFactor5InputDialog(JFrame jframe, String title, String label,
+      int size) {
+    super(jframe, title, true);
+
+    JPanel bottom = new JPanel();
+    bottom.setLayout(new FlowLayout());
+
+    JPanel main = new JPanel();
+    main.setLayout(new FlowLayout());
+    main.add(new JLabel(label));
+    _textField = new JTextField(size);
+    main.add(_textField);
+
+    addKeyListener(new KeyAdapter() {
+      public void keyPressed(KeyEvent e) {
+        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+          hide();
+        }
+      }
+    });
+
+    JButton ok = new JButton("Ok");
+    ok.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        hide();
+      }
+    });
+
+    JButton cancel = new JButton("Cancel");
+    cancel.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        hide();
+        // set the text field to blank just in case
+        // a file was selected before the Cancel
+        // button was pressed.
+        _textField.setText("");
+      }
+    });
+
+    bottom.add(ok);
+    bottom.add(cancel);
+    getContentPane().add(main, BorderLayout.CENTER);
+    getContentPane().add(bottom, BorderLayout.SOUTH);
+    pack();
+    centerWindow(this);
+    show();
+  }
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+  public String getText() {
+    String s = _textField.getText();
+
+    if (s != null && s.trim().length() == 0) {
+      return null;
+    }
+
+    return s;
+
+  }
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces
+  //--------------------------------------------------------------------------
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5InputDialog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5LoadingDialog.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5LoadingDialog.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5LoadingDialog.java (added)
+++ logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5LoadingDialog.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,82 @@
+/*
+ * 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.FlowLayout;
+import java.awt.GridBagLayout;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+/**
+ * LogFactor5LoadingDialog
+ *
+ * @author Richard Hurst
+ * @author Brad Marlborough
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class LogFactor5LoadingDialog extends LogFactor5Dialog {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+
+  public LogFactor5LoadingDialog(JFrame jframe, String message) {
+    super(jframe, "LogFactor5", false);
+
+    JPanel bottom = new JPanel();
+    bottom.setLayout(new FlowLayout());
+
+    JPanel main = new JPanel();
+    main.setLayout(new GridBagLayout());
+    wrapStringOnPanel(message, main);
+
+    getContentPane().add(main, BorderLayout.CENTER);
+    getContentPane().add(bottom, BorderLayout.SOUTH);
+    show();
+
+  }
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces
+  //--------------------------------------------------------------------------
+}
\ No newline at end of file

Propchange: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5LoadingDialog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTable.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTable.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTable.java (added)
+++ logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTable.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,277 @@
+/*
+ * 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.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+
+import org.apache.log4j.lf5.util.DateFormatManager;
+
+/**
+ * LogTable.
+ *
+ * @author Michael J. Sikorsky
+ * @author Robert Shaw
+ * @author Brad Marlborough
+ * @author Brent Sprecher
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class LogTable extends JTable {
+  private static final long serialVersionUID = 4867085140195148458L;
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+  protected int _rowHeight = 30;
+  protected JTextArea _detailTextArea;
+
+  // For the columns:
+  protected int _numCols = 9;
+  protected TableColumn[] _tableColumns = new TableColumn[_numCols];
+  protected int[] _colWidths = {40, 40, 40, 70, 70, 360, 440, 200, 60};
+  protected LogTableColumn[] _colNames = LogTableColumn.getLogTableColumnArray();
+  protected int _colDate = 0;
+  protected int _colThread = 1;
+  protected int _colMessageNum = 2;
+  protected int _colLevel = 3;
+  protected int _colNDC = 4;
+  protected int _colCategory = 5;
+  protected int _colMessage = 6;
+  protected int _colLocation = 7;
+  protected int _colThrown = 8;
+
+  protected DateFormatManager _dateFormatManager = null;
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+
+  public LogTable(JTextArea detailTextArea) {
+    super();
+
+    init();
+
+    _detailTextArea = detailTextArea;
+
+    setModel(new FilteredLogTableModel());
+
+    Enumeration columns = getColumnModel().getColumns();
+    int i = 0;
+    while (columns.hasMoreElements()) {
+      TableColumn col = (TableColumn) columns.nextElement();
+      col.setCellRenderer(new LogTableRowRenderer());
+      col.setPreferredWidth(_colWidths[i]);
+
+      _tableColumns[i] = col;
+      i++;
+    }
+
+    ListSelectionModel rowSM = getSelectionModel();
+    rowSM.addListSelectionListener(new LogTableListSelectionListener(this));
+
+    //setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
+  }
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Get the DateFormatManager for formatting dates.
+   */
+  public DateFormatManager getDateFormatManager() {
+    return _dateFormatManager;
+  }
+
+  /**
+   * Set the date format manager for formatting dates.
+   */
+  public void setDateFormatManager(DateFormatManager dfm) {
+    _dateFormatManager = dfm;
+  }
+
+  public synchronized void clearLogRecords() {
+    //For JDK1.3
+    //((DefaultTableModel)getModel()).setRowCount(0);
+
+    // For JDK1.2.x
+    getFilteredLogTableModel().clear();
+  }
+
+  public FilteredLogTableModel getFilteredLogTableModel() {
+    return (FilteredLogTableModel) getModel();
+  }
+
+  // default view if a view is not set and saved
+  public void setDetailedView() {
+    //TODO: Defineable Views.
+    TableColumnModel model = getColumnModel();
+    // Remove all the columns:
+    for (int f = 0; f < _numCols; f++) {
+      model.removeColumn(_tableColumns[f]);
+    }
+    // Add them back in the correct order:
+    for (int i = 0; i < _numCols; i++) {
+      model.addColumn(_tableColumns[i]);
+    }
+    //SWING BUG:
+    sizeColumnsToFit(-1);
+  }
+
+  public void setView(List columns) {
+    TableColumnModel model = getColumnModel();
+
+    // Remove all the columns:
+    for (int f = 0; f < _numCols; f++) {
+      model.removeColumn(_tableColumns[f]);
+    }
+    Iterator selectedColumns = columns.iterator();
+    Vector columnNameAndNumber = getColumnNameAndNumber();
+    while (selectedColumns.hasNext()) {
+      // add the column to the view
+      model.addColumn(_tableColumns[columnNameAndNumber.indexOf(selectedColumns.next())]);
+    }
+
+    //SWING BUG:
+    sizeColumnsToFit(-1);
+  }
+
+  public void setFont(Font font) {
+    super.setFont(font);
+    Graphics g = this.getGraphics();
+    if (g != null) {
+      FontMetrics fm = g.getFontMetrics(font);
+      int height = fm.getHeight();
+      _rowHeight = height + height / 3;
+      setRowHeight(_rowHeight);
+    }
+
+
+  }
+
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  protected void init() {
+    setRowHeight(_rowHeight);
+    setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+  }
+
+  // assign a column number to a column name
+  protected Vector getColumnNameAndNumber() {
+    Vector columnNameAndNumber = new Vector();
+    for (int i = 0; i < _colNames.length; i++) {
+      columnNameAndNumber.add(i, _colNames[i]);
+    }
+    return columnNameAndNumber;
+  }
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces:
+  //--------------------------------------------------------------------------
+
+  class LogTableListSelectionListener implements ListSelectionListener {
+    protected JTable _table;
+
+    public LogTableListSelectionListener(JTable table) {
+      _table = table;
+    }
+
+    public void valueChanged(ListSelectionEvent e) {
+      //Ignore extra messages.
+      if (e.getValueIsAdjusting()) {
+        return;
+      }
+
+      ListSelectionModel lsm = (ListSelectionModel) e.getSource();
+      if (lsm.isSelectionEmpty()) {
+        //no rows are selected
+      } else {
+        StringBuffer buf = new StringBuffer();
+        int selectedRow = lsm.getMinSelectionIndex();
+
+        for (int i = 0; i < _numCols - 1; i++) {
+          String value = "";
+          Object obj = _table.getModel().getValueAt(selectedRow, i);
+          if (obj != null) {
+            value = obj.toString();
+          }
+
+          buf.append(_colNames[i] + ":");
+          buf.append("\t");
+
+          if (i == _colThread || i == _colMessage || i == _colLevel) {
+            buf.append("\t"); // pad out the date.
+          }
+
+          if (i == _colDate || i == _colNDC) {
+            buf.append("\t\t"); // pad out the date.
+          }
+
+//               if( i == _colSequence)
+//               {
+//                  buf.append("\t\t\t"); // pad out the Sequnce.
+//               }
+
+          buf.append(value);
+          buf.append("\n");
+        }
+        buf.append(_colNames[_numCols - 1] + ":\n");
+        Object obj = _table.getModel().getValueAt(selectedRow, _numCols - 1);
+        if (obj != null) {
+          buf.append(obj.toString());
+        }
+
+        _detailTextArea.setText(buf.toString());
+      }
+    }
+  }
+}
+
+
+
+
+
+

Propchange: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTableColumn.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTableColumn.java?rev=1345492&view=auto
==============================================================================
--- logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTableColumn.java (added)
+++ logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTableColumn.java Sat Jun  2 11:40:31 2012
@@ -0,0 +1,166 @@
+/*
+ * 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.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * LogTableColumn
+ *
+ * @author Michael J. Sikorsky
+ * @author Brad Marlborough
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class LogTableColumn implements java.io.Serializable {
+  private static final long serialVersionUID = -4275827753626456547L;
+
+  // log4j table columns.
+  public final static LogTableColumn DATE = new LogTableColumn("Date");
+  public final static LogTableColumn THREAD = new LogTableColumn("Thread");
+  public final static LogTableColumn MESSAGE_NUM = new LogTableColumn("Message #");
+  public final static LogTableColumn LEVEL = new LogTableColumn("Level");
+  public final static LogTableColumn NDC = new LogTableColumn("NDC");
+  public final static LogTableColumn CATEGORY = new LogTableColumn("Category");
+  public final static LogTableColumn MESSAGE = new LogTableColumn("Message");
+  public final static LogTableColumn LOCATION = new LogTableColumn("Location");
+  public final static LogTableColumn THROWN = new LogTableColumn("Thrown");
+
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+  protected String _label;
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+  private static LogTableColumn[] _log4JColumns;
+  private static Map _logTableColumnMap;
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+  static {
+    _log4JColumns = new LogTableColumn[]{DATE, THREAD, MESSAGE_NUM, LEVEL, NDC, CATEGORY,
+                                         MESSAGE, LOCATION, THROWN};
+
+    _logTableColumnMap = new HashMap();
+
+    for (int i = 0; i < _log4JColumns.length; i++) {
+      _logTableColumnMap.put(_log4JColumns[i].getLabel(), _log4JColumns[i]);
+    }
+  }
+
+
+  public LogTableColumn(String label) {
+    _label = label;
+  }
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Return the Label of the LogLevel.
+   */
+  public String getLabel() {
+    return _label;
+  }
+
+  /**
+   * Convert a column label into a LogTableColumn object.
+   *
+   * @param column The label of a level to be converted into a LogTableColumn.
+   * @return LogTableColumn The LogTableColumn with a label equal to column.
+   * @throws LogTableColumnFormatException Is thrown when the column can not be
+   *         converted into a LogTableColumn.
+   */
+  public static LogTableColumn valueOf(String column)
+      throws LogTableColumnFormatException {
+    LogTableColumn tableColumn = null;
+    if (column != null) {
+      column = column.trim();
+      tableColumn = (LogTableColumn) _logTableColumnMap.get(column);
+    }
+
+    if (tableColumn == null) {
+      StringBuffer buf = new StringBuffer();
+      buf.append("Error while trying to parse (" + column + ") into");
+      buf.append(" a LogTableColumn.");
+      throw new LogTableColumnFormatException(buf.toString());
+    }
+    return tableColumn;
+  }
+
+
+  public boolean equals(Object o) {
+    boolean equals = false;
+
+    if (o instanceof LogTableColumn) {
+      if (this.getLabel() ==
+          ((LogTableColumn) o).getLabel()) {
+        equals = true;
+      }
+    }
+
+    return equals;
+  }
+
+  public int hashCode() {
+    return _label.hashCode();
+  }
+
+  public String toString() {
+    return _label;
+  }
+
+  /**
+   * @return A <code>List</code> of <code>LogTableColumn/code> objects that map
+   * to log4j <code>Column</code> objects.
+   */
+  public static List getLogTableColumns() {
+    return Arrays.asList(_log4JColumns);
+  }
+
+  public static LogTableColumn[] getLogTableColumnArray() {
+    return _log4JColumns;
+  }
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces:
+  //--------------------------------------------------------------------------
+
+}
+
+
+
+
+
+

Propchange: logging/log4j/branches/log4j12modules/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogTableColumn.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message