logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From grobme...@apache.org
Subject svn commit: r1345524 [13/17] - in /logging/log4j/branches/log4j12-bz53299: ./ contribs/ contribs/CekiGulcu/ contribs/EirikLygre/ contribs/JamesHouse/ contribs/Jamie Tsao/ contribs/JimMoore/ contribs/KevinSteppe/ contribs/KitchingSimon/ contribs/LeosLit...
Date Sat, 02 Jun 2012 15:36:26 GMT
Added: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/Resource.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/Resource.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/Resource.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/Resource.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,156 @@
+/*
+ * 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.util;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+/**
+ * Resource encapsulates access to Resources via the Classloader.
+ *
+ * @author Michael J. Sikorsky
+ * @author Robert Shaw
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class Resource {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+  protected String _name;
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Default, no argument constructor.
+   */
+  public Resource() {
+    super();
+  }
+
+  /**
+   * Construct a Resource given a name.
+   *
+   * @see #setName(String)
+   */
+  public Resource(String name) {
+    _name = name;
+  }
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Set the name of the resource.
+   * <p>
+   * A resource is some data (images, audio, text, etc) that can be accessed
+   * by class code in a way that is independent of the location of the code.
+   * </p>
+   * <p>
+   * The name of a resource is a "/"-separated path name that identifies
+   * the resource.
+   * </p>
+   *
+   * @see #getName()
+   */
+  public void setName(String name) {
+    _name = name;
+  }
+
+  /**
+   * Get the name of the resource.  Set setName() for a description of
+   * a resource.
+   *
+   * @see #setName
+   */
+  public String getName() {
+    return (_name);
+  }
+
+  /**
+   * Get the InputStream for this Resource.  Uses the classloader
+   * from this Resource.
+   *
+   * @see #getInputStreamReader
+   * @see ResourceUtils
+   */
+  public InputStream getInputStream() {
+    InputStream in = ResourceUtils.getResourceAsStream(this, this);
+
+    return (in);
+  }
+
+  /**
+   * Get the InputStreamReader for this Resource. Uses the classloader from
+   * this Resource.
+   *
+   * @see #getInputStream
+   * @see ResourceUtils
+   */
+  public InputStreamReader getInputStreamReader() {
+    InputStream in = ResourceUtils.getResourceAsStream(this, this);
+
+    if (in == null) {
+      return null;
+    }
+
+    InputStreamReader reader = new InputStreamReader(in);
+
+    return reader;
+  }
+
+  /**
+   * Get the URL of the Resource.  Uses the classloader from this Resource.
+   *
+   * @see ResourceUtils
+   */
+  public URL getURL() {
+    return (ResourceUtils.getResourceAsURL(this, this));
+  }
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces:
+  //--------------------------------------------------------------------------
+
+}
+
+
+
+
+
+

Propchange: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/Resource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/ResourceUtils.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/ResourceUtils.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/ResourceUtils.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/ResourceUtils.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,133 @@
+/*
+ * 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.util;
+
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * ResourceUtils.  Provide a set of convenience methods for working with
+ * Resources.
+ *
+ * @see org.apache.log4j.lf5.util.Resource
+ *
+ * @author Michael J. Sikorsky
+ * @author Robert Shaw
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class ResourceUtils {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Get the InputStream for this resource.  Note: to convert an InputStream
+   * into an InputReader, use: new InputStreamReader(InputStream).
+   *
+   * @param object   The object to grab the Classloader from.
+   *                 This parameter is quite important from a
+   *                 visibility of resources standpoint as the
+   *                 hierarchy of Classloaders plays a role.
+   *
+   * @param resource The resource to load.
+   *
+   * @return If the Resource was found, the InputStream, otherwise null.
+   *
+   * @see Resource
+   * @see #getResourceAsURL(Object,Resource)
+   * @see InputStream
+   */
+  public static InputStream getResourceAsStream(Object object, Resource resource) {
+    ClassLoader loader = object.getClass().getClassLoader();
+
+    InputStream in = null;
+
+    if (loader != null) {
+      in = loader.getResourceAsStream(resource.getName());
+    } else {
+      in = ClassLoader.getSystemResourceAsStream(resource.getName());
+    }
+
+    return in;
+  }
+
+  /**
+   * Get the URL for this resource.
+   *
+   * @param object   The object to grab the Classloader from.
+   *                 This parameter is quite important from a
+   *                 visibility of resources standpoint as the
+   *                 hierarchy of Classloaders plays a role.
+   *
+   * @param resource The resource to load.
+   *
+   * @return If the Resource was found, the URL, otherwise null.
+   *
+   * @see Resource
+   * @see #getResourceAsStream(Object,Resource)
+   */
+  public static URL getResourceAsURL(Object object, Resource resource) {
+    ClassLoader loader = object.getClass().getClassLoader();
+
+    URL url = null;
+
+    if (loader != null) {
+      url = loader.getResource(resource.getName());
+    } else {
+      url = ClassLoader.getSystemResource(resource.getName());
+    }
+
+    return (url);
+  }
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces:
+  //--------------------------------------------------------------------------
+
+}
+
+
+
+
+
+

Propchange: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/ResourceUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/StreamUtils.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/StreamUtils.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/StreamUtils.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/StreamUtils.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,124 @@
+/*
+ * 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.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Provides utility methods for input and output streams.
+ *
+ * @author Richard Wan
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public abstract class StreamUtils {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Default value is 2048.
+   */
+  public static final int DEFAULT_BUFFER_SIZE = 2048;
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Copies information from the input stream to the output stream using
+   * a default buffer size of 2048 bytes.
+   * @throws java.io.IOException
+   */
+  public static void copy(InputStream input, OutputStream output)
+      throws IOException {
+    copy(input, output, DEFAULT_BUFFER_SIZE);
+  }
+
+  /**
+   * Copies information from the input stream to the output stream using
+   * the specified buffer size
+   * @throws java.io.IOException
+   */
+  public static void copy(InputStream input,
+      OutputStream output,
+      int bufferSize)
+      throws IOException {
+    byte[] buf = new byte[bufferSize];
+    int bytesRead = input.read(buf);
+    while (bytesRead != -1) {
+      output.write(buf, 0, bytesRead);
+      bytesRead = input.read(buf);
+    }
+    output.flush();
+  }
+
+  /**
+   * Copies information between specified streams and then closes
+   * both of the streams.
+   * @throws java.io.IOException
+   */
+  public static void copyThenClose(InputStream input, OutputStream output)
+      throws IOException {
+    copy(input, output);
+    input.close();
+    output.close();
+  }
+
+  /**
+   * @return a byte[] containing the information contained in the
+   * specified InputStream.
+   * @throws java.io.IOException
+   */
+  public static byte[] getBytes(InputStream input)
+      throws IOException {
+    ByteArrayOutputStream result = new ByteArrayOutputStream();
+    copy(input, result);
+    result.close();
+    return result.toByteArray();
+  }
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces
+  //--------------------------------------------------------------------------
+
+}

Propchange: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/util/StreamUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/FilteredLogTableModel.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/FilteredLogTableModel.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/FilteredLogTableModel.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/FilteredLogTableModel.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,263 @@
+/*
+ * 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 org.apache.log4j.lf5.LogRecord;
+import org.apache.log4j.lf5.LogRecordFilter;
+import org.apache.log4j.lf5.PassingLogRecordFilter;
+
+import javax.swing.table.AbstractTableModel;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * A TableModel for LogRecords which includes filtering support.
+ *
+ * @author Richard Wan
+ * @author Brent Sprecher
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class FilteredLogTableModel
+    extends AbstractTableModel {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+
+  protected LogRecordFilter _filter = new PassingLogRecordFilter();
+  protected List _allRecords = new ArrayList();
+  protected List _filteredRecords;
+  protected int _maxNumberOfLogRecords = 5000;
+  protected String[] _colNames = {"Date",
+                                  "Thread",
+                                  "Message #",
+                                  "Level",
+                                  "NDC",
+                                  "Category",
+                                  "Message",
+                                  "Location",
+                                  "Thrown"};
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+
+  public FilteredLogTableModel() {
+    super();
+  }
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  public void setLogRecordFilter(LogRecordFilter filter) {
+    _filter = filter;
+  }
+
+  public LogRecordFilter getLogRecordFilter() {
+    return _filter;
+  }
+
+  public String getColumnName(int i) {
+    return _colNames[i];
+  }
+
+  public int getColumnCount() {
+    return _colNames.length;
+  }
+
+  public int getRowCount() {
+    return getFilteredRecords().size();
+  }
+
+  public int getTotalRowCount() {
+    return _allRecords.size();
+  }
+
+  public Object getValueAt(int row, int col) {
+    LogRecord record = getFilteredRecord(row);
+    return getColumn(col, record);
+  }
+
+  public void setMaxNumberOfLogRecords(int maxNumRecords) {
+    if (maxNumRecords > 0) {
+      _maxNumberOfLogRecords = maxNumRecords;
+    }
+
+  }
+
+  public synchronized boolean addLogRecord(LogRecord record) {
+
+    _allRecords.add(record);
+
+    if (_filter.passes(record) == false) {
+      return false;
+    }
+    getFilteredRecords().add(record);
+    fireTableRowsInserted(getRowCount(), getRowCount());
+    trimRecords();
+    return true;
+  }
+
+  /**
+   * Forces the LogTableModel to requery its filters to determine
+   * which records to display.
+   */
+  public synchronized void refresh() {
+    _filteredRecords = createFilteredRecordsList();
+    fireTableDataChanged();
+  }
+
+  public synchronized void fastRefresh() {
+    _filteredRecords.remove(0);
+    fireTableRowsDeleted(0, 0);
+  }
+
+
+  /**
+   * Clears all records from the LogTableModel
+   */
+  public synchronized void clear() {
+    _allRecords.clear();
+    _filteredRecords.clear();
+    fireTableDataChanged();
+  }
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+
+  protected List getFilteredRecords() {
+    if (_filteredRecords == null) {
+      refresh();
+    }
+    return _filteredRecords;
+  }
+
+  protected List createFilteredRecordsList() {
+    List result = new ArrayList();
+    Iterator records = _allRecords.iterator();
+    LogRecord current;
+    while (records.hasNext()) {
+      current = (LogRecord) records.next();
+      if (_filter.passes(current)) {
+        result.add(current);
+      }
+    }
+    return result;
+  }
+
+  protected LogRecord getFilteredRecord(int row) {
+    List records = getFilteredRecords();
+    int size = records.size();
+    if (row < size) {
+      return (LogRecord) records.get(row);
+    }
+    // a minor problem has happened. JTable has asked for
+    // a row outside the bounds, because the size of
+    // _filteredRecords has changed while it was looping.
+    // return the last row.
+    return (LogRecord) records.get(size - 1);
+
+  }
+
+  protected Object getColumn(int col, LogRecord lr) {
+    if (lr == null) {
+      return "NULL Column";
+    }
+    String date = new Date(lr.getMillis()).toString();
+    switch (col) {
+      case 0:
+        return date + " (" + lr.getMillis() + ")";
+      case 1:
+        return lr.getThreadDescription();
+      case 2:
+        return new Long(lr.getSequenceNumber());
+      case 3:
+        return lr.getLevel();
+      case 4:
+        return lr.getNDC();
+      case 5:
+        return lr.getCategory();
+      case 6:
+        return lr.getMessage();
+      case 7:
+        return lr.getLocation();
+      case 8:
+        return lr.getThrownStackTrace();
+      default:
+        String message = "The column number " + col + "must be between 0 and 8";
+        throw new IllegalArgumentException(message);
+    }
+  }
+
+  // We don't want the amount of rows to grow without bound,
+  // leading to a out-of-memory-exception.  Especially not good
+  // in a production environment :)
+
+  // This method & clearLogRecords() are synchronized so we don't
+  // delete rows that don't exist.
+  protected void trimRecords() {
+    if (needsTrimming()) {
+      trimOldestRecords();
+    }
+  }
+
+  protected boolean needsTrimming() {
+    return (_allRecords.size() > _maxNumberOfLogRecords);
+  }
+
+  protected void trimOldestRecords() {
+    synchronized (_allRecords) {
+      int trim = numberOfRecordsToTrim();
+      if (trim > 1) {
+        List oldRecords =
+            _allRecords.subList(0, trim);
+        oldRecords.clear();
+        refresh();
+      } else {
+        _allRecords.remove(0);
+        fastRefresh();
+      }
+    }
+
+  }
+
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+  private int numberOfRecordsToTrim() {
+    return _allRecords.size() - _maxNumberOfLogRecords;
+  }
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces
+  //--------------------------------------------------------------------------
+}
+

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

Added: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LF5SwingUtils.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LF5SwingUtils.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LF5SwingUtils.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LF5SwingUtils.java Sat Jun  2 15:35:46 2012
@@ -0,0 +1,153 @@
+/*
+ * 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.Adjustable;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.table.TableModel;
+
+/**
+ * Provides methods to accomplish common yet non-trivial tasks
+ * with Swing. Obvious implementations of these methods have been
+ * tried and failed.
+ *
+ * @author Richard Wan
+ */
+
+// Contributed by ThoughtWorks Inc.
+
+public class LF5SwingUtils {
+  //--------------------------------------------------------------------------
+  //   Constants:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Protected Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Private Variables:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Constructors:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Public Methods:
+  //--------------------------------------------------------------------------
+
+  /**
+   * Selects a the specified row in the specified JTable and scrolls
+   * the specified JScrollpane to the newly selected row. More importantly,
+   * the call to repaint() delayed long enough to have the table
+   * properly paint the newly selected row which may be offscre
+   * @param table should belong to the specified JScrollPane
+   */
+  public static void selectRow(int row, JTable table, JScrollPane pane) {
+    if (table == null || pane == null) {
+      return;
+    }
+    if (contains(row, table.getModel()) == false) {
+      return;
+    }
+    moveAdjustable(row * table.getRowHeight(), pane.getVerticalScrollBar());
+    selectRow(row, table.getSelectionModel());
+    // repaint must be done later because moveAdjustable
+    // posts requests to the swing thread which must execute before
+    // the repaint logic gets executed.
+    repaintLater(table);
+  }
+
+  /**
+   * Makes the specified Adjustable track if the view area expands and
+   * the specified Adjustable is located near the of the view.
+   */
+  public static void makeScrollBarTrack(Adjustable scrollBar) {
+    if (scrollBar == null) {
+      return;
+    }
+    scrollBar.addAdjustmentListener(new TrackingAdjustmentListener());
+  }
+
+  /**
+   * Makes the vertical scroll bar of the specified JScrollPane
+   * track if the view expands (e.g. if rows are added to an underlying
+   * table).
+   */
+  public static void makeVerticalScrollBarTrack(JScrollPane pane) {
+    if (pane == null) {
+      return;
+    }
+    makeScrollBarTrack(pane.getVerticalScrollBar());
+  }
+
+  //--------------------------------------------------------------------------
+  //   Protected Methods:
+  //--------------------------------------------------------------------------
+  protected static boolean contains(int row, TableModel model) {
+    if (model == null) {
+      return false;
+    }
+    if (row < 0) {
+      return false;
+    }
+    if (row >= model.getRowCount()) {
+      return false;
+    }
+    return true;
+  }
+
+  protected static void selectRow(int row, ListSelectionModel model) {
+    if (model == null) {
+      return;
+    }
+    model.setSelectionInterval(row, row);
+  }
+
+  protected static void moveAdjustable(int location, Adjustable scrollBar) {
+    if (scrollBar == null) {
+      return;
+    }
+    scrollBar.setValue(location);
+  }
+
+  /**
+   * Work around for JTable/viewport bug.
+   * @link http://developer.java.sun.com/developer/bugParade/bugs/4205145.html
+   */
+  protected static void repaintLater(final JComponent component) {
+    SwingUtilities.invokeLater(new Runnable() {
+      public void run() {
+        component.repaint();
+      }
+    });
+  }
+  //--------------------------------------------------------------------------
+  //   Private Methods:
+  //--------------------------------------------------------------------------
+
+  //--------------------------------------------------------------------------
+  //   Nested Top-Level Classes or Interfaces
+  //--------------------------------------------------------------------------
+}
+

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

Added: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java Sat Jun  2 15:35:46 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/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogBrokerMonitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java
URL: http://svn.apache.org/viewvc/logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java?rev=1345524&view=auto
==============================================================================
--- logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java (added)
+++ logging/log4j/branches/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java Sat Jun  2 15:35:46 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/log4j12-bz53299/modules/lf5/src/main/java/org/apache/log4j/lf5/viewer/LogFactor5Dialog.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message