Return-Path: Delivered-To: apmail-logging-general-archive@www.apache.org Received: (qmail 45207 invoked from network); 9 May 2010 08:31:09 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 9 May 2010 08:31:09 -0000 Received: (qmail 7353 invoked by uid 500); 9 May 2010 08:31:09 -0000 Delivered-To: apmail-logging-general-archive@logging.apache.org Received: (qmail 7200 invoked by uid 500); 9 May 2010 08:31:07 -0000 Mailing-List: contact general-help@logging.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Logging General" List-Id: Delivered-To: mailing list general@logging.apache.org Received: (qmail 7176 invoked by uid 99); 9 May 2010 08:31:06 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 09 May 2010 08:31:06 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 09 May 2010 08:30:59 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 3F24B23889BF; Sun, 9 May 2010 08:30:02 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r942512 - in /logging/chainsaw/trunk: ./ src/main/java/org/apache/log4j/chainsaw/ src/main/java/org/apache/log4j/chainsaw/color/ src/main/java/org/apache/log4j/chainsaw/layout/ src/main/resources/org/apache/log4j/chainsaw/help/ src/main/res... Date: Sun, 09 May 2010 08:30:01 -0000 To: general@logging.apache.org From: sdeboy@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100509083002.3F24B23889BF@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: sdeboy Date: Sun May 9 08:30:00 2010 New Revision: 942512 URL: http://svn.apache.org/viewvc?rev=942512&view=rev Log: Added ability to highlight search match text in the table (per-log panel preference, enabled by default) - modified the Rule.evaluate method to accept a Map argument. If the map argument is not null, the map will be populated with text matches resulting from the rule evaluation - the keys are the field names containing text matches discovered during rule evaluation, the values are the (possibly multiple) text matches - updated Chainsaw & receivers pom.xml to require log4j-extras 1.1 snapshot due to the change to the Rule API - renamed JEditorPaneFormatter to JTextComponentFormatter - modified the Search match color in the table from black background to grey background, from white foreground to black foreground - reworked concurrency & use of event lists in ChainsawCyclicBufferTableModel - added search matches to extendedloggingevent (used during rendering) - updated findnext/previous logic to handle no selected row, better handling of wrapping forward & back - reworked tablecellrenderer logic to support bolding of search-match text in the table (required changing multiline fields to use a jtextpane) - updated all Rules to accept a Map which is populated by String keys representing the fields providing a text match, and Set values containing the one or more text matches for that field (if the map is null, no collection of results is performed) - updated And, Or and Not rules to correctly aggregate text match results of their child rules - updated ExpressionRule to allow definition of expressions containing keywords as text (must be single-quoted) Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JTextComponentFormatter.java - copied, changed from r930795, logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JEditorPaneFormatter.java Removed: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JEditorPaneFormatter.java Modified: logging/chainsaw/trunk/pom.xml logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAbout.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAppenderHandler.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ExtendedLoggingEvent.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferencePanel.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/RuleMediator.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/WelcomePanel.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/layout/LayoutEditorPane.java logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties Modified: logging/chainsaw/trunk/pom.xml URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/pom.xml?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/pom.xml (original) +++ logging/chainsaw/trunk/pom.xml Sun May 9 08:30:00 2010 @@ -328,7 +328,7 @@ log4j apache-log4j-extras - 1.0 + 1.1-SNAPSHOT log4j Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAbout.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAbout.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAbout.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAbout.java Sun May 9 08:30:00 2010 @@ -23,7 +23,6 @@ package org.apache.log4j.chainsaw; import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Font; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -35,10 +34,8 @@ import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; -import javax.swing.UIManager; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; -import javax.swing.text.html.HTMLDocument; import org.apache.log4j.Logger; import org.apache.log4j.chainsaw.help.HelpManager; @@ -86,7 +83,7 @@ class ChainsawAbout extends JDialog { } getContentPane().add(scrollPane, BorderLayout.CENTER); getContentPane().add(closeButton, BorderLayout.SOUTH); - JEditorPaneFormatter.applySystemFontAndSize(editPane); + JTextComponentFormatter.applySystemFontAndSize(editPane); editPane.setEditable(false); editPane.addHyperlinkListener( Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAppenderHandler.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAppenderHandler.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAppenderHandler.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawAppenderHandler.java Sun May 9 08:30:00 2010 @@ -26,7 +26,6 @@ import java.util.Map; import javax.swing.event.EventListenerList; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.LogManager; -import org.apache.log4j.MDC; import org.apache.log4j.helpers.Constants; import org.apache.log4j.net.SocketReceiver; import org.apache.log4j.rule.ExpressionRule; @@ -291,7 +290,7 @@ public class ChainsawAppenderHandler ext .hasNext();) { Map.Entry entry = (Map.Entry) itery.next(); Rule rule = (Rule) entry.getValue(); - if (rule.evaluate(e)) { + if (rule.evaluate(e, null)) { eventBatch.addEvent((String) entry.getKey(), e); } } Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawConstants.java Sun May 9 08:30:00 2010 @@ -36,8 +36,8 @@ public class ChainsawConstants { public static final Color COLOR_DEFAULT_FOREGROUND = Color.BLACK; public static final int DEFAULT_ROW_HEIGHT = 20; - public static final Color FIND_LOGGER_BACKGROUND = new Color(40, 40, 40); - public static final Color FIND_LOGGER_FOREGROUND = Color.WHITE; + public static final Color FIND_LOGGER_BACKGROUND = new Color(197, 193, 170); + public static final Color FIND_LOGGER_FOREGROUND = Color.BLACK; public static final Color COLOR_ODD_ROW = new Color(215, 215, 215); public static final Color COLOR_EVEN_ROW = COLOR_DEFAULT_BACKGROUND; Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ChainsawCyclicBufferTableModel.java Sun May 9 08:30:00 2010 @@ -75,6 +75,7 @@ class ChainsawCyclicBufferTableModel ext // protected final Object syncLock = new Object(); private final LoggerNameModel loggerNameModelDelegate = new LoggerNameModelSupport(); + private final Object mutex = new Object(); //because we may be using a cyclic buffer, if an ID is not provided in the property, //use and increment this row counter as the ID for each received row @@ -103,17 +104,19 @@ class ChainsawCyclicBufferTableModel ext } public List getMatchingEvents(Rule rule) { - List list = new ArrayList(); - synchronized (unfilteredList) { - Iterator iter = unfilteredList.iterator(); + List list = new ArrayList(); + List unfilteredCopy; + synchronized (mutex) { + unfilteredCopy = new ArrayList(unfilteredList); + } + Iterator iter = unfilteredCopy.iterator(); - while (iter.hasNext()) { - LoggingEvent event = (LoggingEvent) iter.next(); + while (iter.hasNext()) { + LoggingEvent event = (LoggingEvent) iter.next(); - if (rule.evaluate(event)) { - list.add(event); - } + if (rule.evaluate(event, null)) { + list.add(event); } } @@ -121,38 +124,43 @@ class ChainsawCyclicBufferTableModel ext } public void reFilter() { - synchronized (unfilteredList) { - final int previousSize = filteredList.size(); - try { - filteredList.clear(); - - Iterator iter = unfilteredList.iterator(); + final int previousSize; + final int newSize; + synchronized (mutex) { + previousSize = filteredList.size(); + filteredList.clear(); + if (displayRule == null) { + filteredList.addAll(unfilteredList); + } else { + Iterator iter = unfilteredList.iterator(); - while (iter.hasNext()) { - LoggingEvent e = (LoggingEvent) iter.next(); + while (iter.hasNext()) { + LoggingEvent e = (LoggingEvent) iter.next(); - if ((displayRule == null) || (displayRule.evaluate(e))) { - filteredList.add(e); + if (displayRule.evaluate(e, null)) { + filteredList.add(e); + } + } + } + newSize = filteredList.size(); } - } - } finally { SwingHelper.invokeOnEDT(new Runnable() { public void run() { - if (filteredList.size() > 0) { - if (previousSize == filteredList.size()) { + if (newSize > 0) { + if (previousSize == newSize) { //same - update all - fireTableRowsUpdated(0, filteredList.size() - 1); - } else if (previousSize > filteredList.size()) { + fireTableRowsUpdated(0, newSize - 1); + } else if (previousSize > newSize) { //less now..update and delete difference - fireTableRowsUpdated(0, filteredList.size() - 1); + fireTableRowsUpdated(0, newSize - 1); //swing bug exposed by variable height rows when calling fireTableRowsDeleted..use tabledatacchanged fireTableDataChanged(); - } else if (previousSize < filteredList.size()) { + } else if (previousSize < newSize) { //more now..update and insert difference if (previousSize > 0) { fireTableRowsUpdated(0, previousSize - 1); } - fireTableRowsInserted(Math.max(0, previousSize), filteredList.size() - 1); + fireTableRowsInserted(Math.max(0, previousSize), newSize - 1); } } else { //no rows to show @@ -160,38 +168,38 @@ class ChainsawCyclicBufferTableModel ext } notifyCountListeners(); }}); - } - } } - public int find(Rule rule, int startLocation, boolean searchForward) { - synchronized (filteredList) { + public int locate(Rule rule, int startLocation, boolean searchForward) { + List filteredListCopy; + synchronized (mutex) { + filteredListCopy = new ArrayList(filteredList); + } if (searchForward) { - for (int i = startLocation; i < filteredList.size(); i++) { - if (rule.evaluate((LoggingEvent) filteredList.get(i))) { + for (int i = startLocation; i < filteredListCopy.size(); i++) { + if (rule.evaluate((LoggingEvent) filteredListCopy.get(i), null)) { return i; } } //if there was no match, start at row zero and go to startLocation for (int i = 0; i < startLocation; i++) { - if (rule.evaluate((LoggingEvent) filteredList.get(i))) { + if (rule.evaluate((LoggingEvent) filteredListCopy.get(i), null)) { return i; } } } else { for (int i = startLocation; i > -1; i--) { - if (rule.evaluate((LoggingEvent) filteredList.get(i))) { + if (rule.evaluate((LoggingEvent) filteredListCopy.get(i), null)) { return i; } } //if there was no match, start at row list.size() - 1 and go to startLocation - for (int i = filteredList.size() - 1; i > startLocation; i--) { - if (rule.evaluate((LoggingEvent) filteredList.get(i))) { + for (int i = filteredListCopy.size() - 1; i > startLocation; i--) { + if (rule.evaluate((LoggingEvent) filteredListCopy.get(i), null)) { return i; } } } - } return -1; } @@ -238,9 +246,15 @@ class ChainsawCyclicBufferTableModel ext (EventCountListener[]) eventListenerList.getListeners( EventCountListener.class); + int filteredListSize; + int unfilteredListSize; + synchronized (mutex) { + filteredListSize = filteredList.size(); + unfilteredListSize = unfilteredList.size(); + } for (int i = 0; i < listeners.length; i++) { listeners[i].eventCountChanged( - filteredList.size(), unfilteredList.size()); + filteredListSize, unfilteredListSize); } } @@ -269,21 +283,26 @@ class ChainsawCyclicBufferTableModel ext * @see org.apache.log4j.chainsaw.EventContainer#sort() */ public void sort() { - if (sortEnabled && filteredList.size() > 0) { - synchronized (filteredList) { - Collections.sort( - filteredList, - new ColumnComparator( - getColumnName(currentSortColumn), currentSortColumn, - currentSortAscending)); + boolean sort; + final int filteredListSize; + synchronized (mutex) { + filteredListSize = filteredList.size(); + sort = (sortEnabled && filteredListSize > 0); + if (sort) { + Collections.sort( + filteredList, + new ColumnComparator( + getColumnName(currentSortColumn), currentSortColumn, + currentSortAscending)); + } + } + if (sort) { + SwingHelper.invokeOnEDT(new Runnable() { + public void run() { + fireTableRowsUpdated(0, Math.max(filteredListSize - 1, 0)); + } + }); } - - SwingHelper.invokeOnEDT(new Runnable() { - public void run() { - fireTableRowsUpdated(0, Math.max(filteredList.size() - 1, 0)); - } - }); - } } public boolean isSortEnabled() { @@ -304,7 +323,7 @@ class ChainsawCyclicBufferTableModel ext public void clearModel() { reachedCapacity = false; - synchronized (unfilteredList) { + synchronized (mutex) { unfilteredList.clear(); filteredList.clear(); uniqueRow = 0; @@ -320,43 +339,42 @@ class ChainsawCyclicBufferTableModel ext } public List getAllEvents() { - List list = new ArrayList(unfilteredList.size()); - - synchronized (unfilteredList) { - list.addAll(unfilteredList); - } - - return list; + synchronized (mutex) { + return new ArrayList(unfilteredList); + } } public List getFilteredEvents() { - List list = new ArrayList(filteredList.size()); - - synchronized (filteredList) { - list.addAll(filteredList); + + synchronized (mutex) { + return new ArrayList(filteredList); } - - return list; } public int getRowIndex(LoggingEvent e) { - synchronized (filteredList) { + synchronized (mutex) { return filteredList.indexOf(e); } } public void removePropertyFromEvents(String propName) { //first remove the event from any displayed events, so we can fire row updated event - for (int i=0;i -1; i--) { - ExtendedLoggingEvent event = (ExtendedLoggingEvent)filteredList.get(i); + ExtendedLoggingEvent event = (ExtendedLoggingEvent)filteredListCopy.get(i); if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) || !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) { return i; } } //searching backward, no colorized event was found - now start at list.size() - 1 and go to startLocation - for (int i = filteredList.size() - 1; i > startLocation; i--) { - ExtendedLoggingEvent event = (ExtendedLoggingEvent)filteredList.get(i); + for (int i = filteredListCopy.size() - 1; i > startLocation; i--) { + ExtendedLoggingEvent event = (ExtendedLoggingEvent)filteredListCopy.get(i); if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) || !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) { return i; } } } - } return -1; } @@ -423,7 +447,7 @@ class ChainsawCyclicBufferTableModel ext } public ExtendedLoggingEvent getRow(int row) { - synchronized (filteredList) { + synchronized (mutex) { if (row < filteredList.size()) { return (ExtendedLoggingEvent) filteredList.get(row); } @@ -433,7 +457,7 @@ class ChainsawCyclicBufferTableModel ext } public int getRowCount() { - synchronized (filteredList) { + synchronized (mutex) { return filteredList.size(); } } @@ -441,7 +465,7 @@ class ChainsawCyclicBufferTableModel ext public Object getValueAt(int rowIndex, int columnIndex) { LoggingEvent event = null; - synchronized (filteredList) { + synchronized (mutex) { if (rowIndex < filteredList.size() && rowIndex > -1) { event = (LoggingEvent) filteredList.get(rowIndex); } @@ -457,11 +481,6 @@ class ChainsawCyclicBufferTableModel ext info = event.getLocationInformation(); } - if (event == null) { - logger.error("Invalid rowindex=" + rowIndex); - throw new NullPointerException("Invalid rowIndex=" + rowIndex); - } - switch (columnIndex + 1) { case ChainsawColumns.INDEX_ID_COL_NAME: @@ -499,25 +518,25 @@ class ChainsawCyclicBufferTableModel ext case ChainsawColumns.INDEX_CLASS_COL_NAME: return ((info == null) - || ((info != null) && "?".equals(info.getClassName()))) ? "" + || ("?".equals(info.getClassName()))) ? "" : info .getClassName(); case ChainsawColumns.INDEX_FILE_COL_NAME: return ((info == null) - || ((info != null) && "?".equals(info.getFileName()))) ? "" + || ("?".equals(info.getFileName()))) ? "" : info .getFileName(); case ChainsawColumns.INDEX_LINE_COL_NAME: return ((info == null) - || ((info != null) && "?".equals(info.getLineNumber()))) ? "" + || ("?".equals(info.getLineNumber()))) ? "" : info .getLineNumber(); case ChainsawColumns.INDEX_METHOD_COL_NAME: return ((info == null) - || ((info != null) && "?".equals(info.getMethodName()))) ? "" + || ("?".equals(info.getMethodName()))) ? "" : info .getMethodName(); @@ -553,20 +572,18 @@ class ChainsawCyclicBufferTableModel ext * Set so we are not keeping track of IDs for all events ever received (we'd run out of * memory...) */ - if (isCyclic()) { + synchronized(mutex) { + if (isCyclic()) { CyclicBufferList bufferList = (CyclicBufferList) unfilteredList; if (bufferList.size() == bufferList.getMaxSize()) { - ExtendedLoggingEvent aboutToBeDropped = (ExtendedLoggingEvent) unfilteredList.get(0); reachedCapacity = true; } - } - unfilteredList.add(e); - - if ((displayRule == null) || (displayRule.evaluate(e))) { - synchronized (filteredList) { - filteredList.add(e); - rowAdded = true; - } + } + unfilteredList.add(e); + if ((displayRule == null) || (displayRule.evaluate(e, null))) { + filteredList.add(e); + rowAdded = true; + } } checkForNewColumn(e); @@ -601,18 +618,6 @@ class ChainsawCyclicBufferTableModel ext } } - public int getLastAdded() { - int last = 0; - - if (cyclic) { - last = ((CyclicBufferList) filteredList).getLast() - 1; - } else { - last = filteredList.size() - 1; - } - - return Math.max(0, last); - } - public void fireTableEvent(final int begin, final int end, final int count) { SwingHelper.invokeOnEDT(new Runnable() { public void run() { @@ -749,7 +754,9 @@ class ChainsawCyclicBufferTableModel ext * @see org.apache.log4j.chainsaw.EventContainer#size() */ public int size() { - return unfilteredList.size(); + synchronized(mutex) { + return unfilteredList.size(); + } } private class ModelChanger implements PropertyChangeListener { @@ -766,7 +773,7 @@ class ChainsawCyclicBufferTableModel ext int index = 0; try { - synchronized (unfilteredList) { + synchronized (mutex) { monitor = new ProgressMonitor( null, "Switching models...", Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/EventContainer.java Sun May 9 08:30:00 2010 @@ -100,7 +100,7 @@ public interface EventContainer extends * @param startRow * @param searchForward */ - int find(Rule rule, int startRow, boolean searchForward); + int locate(Rule rule, int startRow, boolean searchForward); /** * Returns a copied list of all the event in the model. @@ -124,11 +124,6 @@ public interface EventContainer extends ExtendedLoggingEvent getRow(int row); /** - * Return the last added row. - */ - int getLastAdded(); - - /** * Adds a row to the model. * @param e event * @return flag representing whether or not the row is being displayed (not filtered) Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ExtendedLoggingEvent.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ExtendedLoggingEvent.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ExtendedLoggingEvent.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ExtendedLoggingEvent.java Sun May 9 08:30:00 2010 @@ -17,6 +17,8 @@ package org.apache.log4j.chainsaw; import java.awt.Color; +import java.util.HashMap; +import java.util.Map; import org.apache.log4j.rule.Rule; import org.apache.log4j.spi.LoggingEvent; @@ -27,6 +29,8 @@ public class ExtendedLoggingEvent extend private Color colorRuleForeground = ChainsawConstants.COLOR_DEFAULT_FOREGROUND; private boolean searchMatch = false; + //a Map of event fields to Sets of string matches (can be used to render matches differently) + Map eventMatches = new HashMap(); //copy constructor public ExtendedLoggingEvent(LoggingEvent e) { @@ -44,9 +48,14 @@ public class ExtendedLoggingEvent extend } public void evaluateSearchRule(Rule searchRule) { - searchMatch = searchRule != null && searchRule.evaluate(this); + eventMatches.clear(); + searchMatch = searchRule != null && searchRule.evaluate(this, eventMatches); } + public Map getSearchMatches() { + return eventMatches; + } + public Color getForeground() { return searchMatch ? ChainsawConstants.FIND_LOGGER_FOREGROUND : colorRuleForeground; } Copied: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JTextComponentFormatter.java (from r930795, logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JEditorPaneFormatter.java) URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JTextComponentFormatter.java?p2=logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JTextComponentFormatter.java&p1=logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JEditorPaneFormatter.java&r1=930795&r2=942512&rev=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JEditorPaneFormatter.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/JTextComponentFormatter.java Sun May 9 08:30:00 2010 @@ -18,17 +18,18 @@ package org.apache.log4j.chainsaw; import java.awt.Font; -import javax.swing.JEditorPane; import javax.swing.UIManager; import javax.swing.text.Document; +import javax.swing.text.JTextComponent; import javax.swing.text.html.HTMLDocument; /** * Apply system font and size (normal size + 1) rule if the JEditorPane document contains html. */ -public class JEditorPaneFormatter { - public static void applySystemFontAndSize(JEditorPane editorPane) { - Document document = editorPane.getDocument(); +public class JTextComponentFormatter +{ + public static void applySystemFontAndSize(JTextComponent textComponent) { + Document document = textComponent.getDocument(); if (document instanceof HTMLDocument) { Font font = UIManager.getFont("Label.font"); String bodyRule = "body { font-family: " + font.getFamily() + "; font-size: " + (font.getSize() + 1) + "pt; }"; Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanel.java Sun May 9 08:30:00 2010 @@ -439,6 +439,16 @@ public class LogPanel extends DockablePa } }); + preferenceModel.addPropertyChangeListener( + "highlightSearchMatchText", + new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + renderer.setHighlightSearchMatchText( + ((Boolean) evt.getNewValue()).booleanValue()); + table.tableChanged(new TableModelEvent(tableModel)); + } + }); + preferenceModel.addPropertyChangeListener( "detailPaneVisible", new PropertyChangeListener() { @@ -1972,7 +1982,7 @@ public class LogPanel extends DockablePa * @return row number or -1 if row with log4jid property with that number was not found */ int setSelectedEvent(int eventNumber) { - int row = tableModel.find(ExpressionRule.getRule("prop.log4jid == " + eventNumber), 0, true); + int row = tableModel.locate(ExpressionRule.getRule("prop.log4jid == " + eventNumber), 0, true); if (row > -1) { preferenceModel.setScrollToBottom(false); @@ -2412,7 +2422,13 @@ public class LogPanel extends DockablePa if (findRule != null) { try { - int nextRow = tableModel.find(findRule, table.getSelectedRow() + 1, true); + int filteredEventsSize = getFilteredEvents().size(); + int startRow = table.getSelectedRow() + 1; + if (startRow > filteredEventsSize - 1) { + startRow = 0; + } + //no selected row would return -1, so we'd start at row zero + int nextRow = tableModel.locate(findRule, startRow, true); if (nextRow > -1) { table.scrollToRow(nextRow); @@ -2435,8 +2451,12 @@ public class LogPanel extends DockablePa if (findRule != null) { try { - final int previousRow = - tableModel.find(findRule, table.getSelectedRow() - 1, false); + int startRow = table.getSelectedRow() - 1; + int filteredEventsSize = getFilteredEvents().size(); + if (startRow < 0) { + startRow = filteredEventsSize - 1; + } + final int previousRow = tableModel.locate(findRule, startRow, false); if (previousRow > -1) { table.scrollToRow(previousRow); @@ -2504,6 +2524,7 @@ public class LogPanel extends DockablePa } preferenceModel.setDetailPaneVisible(event.asBoolean("detailPaneVisible")); preferenceModel.setLogTreePanelVisible(event.asBoolean("logTreePanelVisible")); + preferenceModel.setHighlightSearchMatchText(event.asBoolean("highlightSearchMatchText")); //re-add columns to the table in the order provided from the list for (Iterator iter = sortedColumnList.iterator(); iter.hasNext();) { TableColumn element = (TableColumn) iter.next(); @@ -2591,7 +2612,12 @@ public class LogPanel extends DockablePa } public void findNextMarker() { - final int nextRow = tableModel.find(findMarkerRule, table.getSelectedRow() + 1, true); + int startRow = table.getSelectedRow() + 1; + int filteredEventsSize = getFilteredEvents().size(); + if (startRow > filteredEventsSize - 1) { + startRow = 0; + } + final int nextRow = tableModel.locate(findMarkerRule, startRow, true); if (nextRow > -1) { table.scrollToRow(nextRow); @@ -2599,7 +2625,12 @@ public class LogPanel extends DockablePa } public void findPreviousMarker() { - final int previousRow = tableModel.find(findMarkerRule, table.getSelectedRow() - 1, false); + int startRow = table.getSelectedRow() - 1; + int filteredEventsSize = getFilteredEvents().size(); + if (startRow < 0) { + startRow = filteredEventsSize - 1; + } + final int previousRow = tableModel.locate(findMarkerRule, startRow, false); if (previousRow > -1) { table.scrollToRow(previousRow); @@ -2669,9 +2700,15 @@ public class LogPanel extends DockablePa // they stopped typing recently, but have stopped for at least // 1 sample period. lets apply the filter // logger.debug("Typed something recently applying filter"); - if (filterText != null && (!(filterText.getText().equals(lastFilterText)))) { + if (!(filterText.getText().equals(lastFilterText))) { lastFilterText = filterText.getText(); - setFilter(); + EventQueue.invokeLater(new Runnable() + { + public void run() + { + setFilter(); + } + }); } } else { // they stopped typing a while ago, let's forget about it @@ -2929,7 +2966,7 @@ public class LogPanel extends DockablePa SwingHelper.invokeOnEDT(new Runnable() { public void run() { detail.setDocument(doc); - JEditorPaneFormatter.applySystemFontAndSize(detail); + JTextComponentFormatter.applySystemFontAndSize(detail); detail.setCaretPosition(0); lastRow = selectedRow; } @@ -2946,7 +2983,7 @@ public class LogPanel extends DockablePa SwingHelper.invokeOnEDT(new Runnable() { public void run() { detail.setDocument(doc); - JEditorPaneFormatter.applySystemFontAndSize(detail); + JTextComponentFormatter.applySystemFontAndSize(detail); detail.setCaretPosition(0); lastRow = selectedRow; } Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferenceModel.java Sun May 9 08:30:00 2010 @@ -81,6 +81,7 @@ public class LogPanelPreferenceModel imp private Collection hiddenLoggers = new HashSet(); private String timeZone; private boolean wrapMsg; + private boolean highlightSearchMatchText; /** * Returns an unmodifiable list of the columns. @@ -220,6 +221,7 @@ public class LogPanelPreferenceModel imp setDateFormatPattern(model.getDateFormatPattern()); setLevelIcons(model.isLevelIcons()); setWrapMessage(model.isWrapMessage()); + setHighlightSearchMatchText(model.isHighlightSearchMatchText()); setTimeZone(model.getTimeZone()); setToolTips(model.isToolTips()); setScrollToBottom(model.isScrollToBottom()); @@ -254,6 +256,10 @@ public class LogPanelPreferenceModel imp return wrapMsg; } + public boolean isHighlightSearchMatchText() { + return highlightSearchMatchText; + } + /** * @param levelIcons */ @@ -269,6 +275,15 @@ public class LogPanelPreferenceModel imp this.wrapMsg = wrapMsg; propertySupport.firePropertyChange("wrapMessage", !wrapMsg, wrapMsg); } + + /** + * @param highlightSearchMatchText + */ + public void setHighlightSearchMatchText(boolean highlightSearchMatchText) { + this.highlightSearchMatchText = highlightSearchMatchText; + propertySupport.firePropertyChange("highlightSearchMatchText", !highlightSearchMatchText, highlightSearchMatchText); + } + /** * @param loggerPrecision - an integer representing the number of packages to display, * or an empty string representing 'display all packages' Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferencePanel.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferencePanel.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferencePanel.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogPanelPreferencePanel.java Sun May 9 08:30:00 2010 @@ -244,6 +244,7 @@ public class LogPanelPreferencePanel ext private final JRadioButton rdLevelIcons = new JRadioButton("Icons"); private final JRadioButton rdLevelText = new JRadioButton("Text"); private final JCheckBox wrapMessage = new JCheckBox("Display entire message and marker text in the table (multi-line rows)"); + private final JCheckBox highlightSearchMatchText = new JCheckBox("Highlight search match text"); private JRadioButton rdLast; //~ Constructors ========================================================== @@ -364,6 +365,7 @@ public class LogPanelPreferencePanel ext add(levelFormatPanel); add(wrapMessage); + add(highlightSearchMatchText); JPanel loggerFormatPanel = new JPanel(); loggerFormatPanel.setLayout( @@ -512,6 +514,17 @@ public class LogPanelPreferencePanel ext }; wrapMessage.addActionListener(wrapMessageListener); + + ActionListener highlightSearchMatchTextListener = new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + preferenceModel.setHighlightSearchMatchText(highlightSearchMatchText.isSelected()); + } + }; + + highlightSearchMatchText.addActionListener(highlightSearchMatchTextListener); + rdLevelIcons.addActionListener(levelIconListener); rdLevelText.addActionListener(levelIconListener); @@ -535,6 +548,17 @@ public class LogPanelPreferencePanel ext wrapMessage.setSelected(value); } }); + + preferenceModel.addPropertyChangeListener( + "highlightSearchMatchText", new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent evt) + { + boolean value = ((Boolean) evt.getNewValue()).booleanValue(); + highlightSearchMatchText.setSelected(value); + } + }); + } } Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java Sun May 9 08:30:00 2010 @@ -1042,7 +1042,7 @@ public class LogUI extends JFrame implem try { tutorialArea.setPage(ChainsawConstants.TUTORIAL_URL); - JEditorPaneFormatter.applySystemFontAndSize(tutorialArea); + JTextComponentFormatter.applySystemFontAndSize(tutorialArea); container.add(new JScrollPane(tutorialArea), BorderLayout.CENTER); } catch (Exception e) { @@ -1751,6 +1751,7 @@ public class LogUI extends JFrame implem * The FQN of the LookANdFeel */ private static void applyLookAndFeel(String lookAndFeelClassName) { + UIManager.put("swing.boldMetal", Boolean.FALSE); if ( UIManager.getLookAndFeel().getClass().getName().equals( lookAndFeelClassName)) { Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LoggerNameTreePanel.java Sun May 9 08:30:00 2010 @@ -40,6 +40,7 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import javax.swing.AbstractAction; @@ -158,7 +159,7 @@ final class LoggerNameTreePanel extends setLayout(new BorderLayout()); ruleDelegate = new AbstractRule() { - public boolean evaluate(LoggingEvent e) + public boolean evaluate(LoggingEvent e, Map matches) { String currentlySelectedLoggerName = getCurrentlySelectedLoggerName(); boolean hidden = e.getLoggerName() != null && isHidden(e.getLoggerName()); @@ -180,7 +181,7 @@ final class LoggerNameTreePanel extends colorRuleDelegate = new AbstractRule() { - public boolean evaluate(LoggingEvent e) + public boolean evaluate(LoggingEvent e, Map matches) { boolean hidden = e.getLoggerName() != null && isHidden(e.getLoggerName()); String currentlySelectedLoggerName = getCurrentlySelectedLoggerName(); @@ -380,11 +381,13 @@ final class LoggerNameTreePanel extends * * @param e DOCUMENT ME! * + * @param matches * @return DOCUMENT ME! */ - public boolean evaluate(LoggingEvent e) + public boolean evaluate(LoggingEvent e, Map matches) { - return ruleDelegate.evaluate(e); + //no need for logger to build matches + return ruleDelegate.evaluate(e, null); } public Rule getLoggerColorRule() { Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/RuleMediator.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/RuleMediator.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/RuleMediator.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/RuleMediator.java Sun May 9 08:30:00 2010 @@ -19,6 +19,7 @@ package org.apache.log4j.chainsaw; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Map; import org.apache.log4j.rule.AbstractRule; import org.apache.log4j.rule.Rule; @@ -56,11 +57,12 @@ public class RuleMediator extends Abstra /* (non-Javadoc) * @see org.apache.log4j.chainsaw.rule.Rule#evaluate(org.apache.log4j.spi.LoggingEvent) */ - public boolean evaluate(LoggingEvent e) { + public boolean evaluate(LoggingEvent e, Map matches) { boolean accepts = true; + //no need to have rulemediator build matches if (inclusionRule != null) { - accepts = inclusionRule.evaluate(e); + accepts = inclusionRule.evaluate(e, null); } if (!accepts) { @@ -68,7 +70,7 @@ public class RuleMediator extends Abstra } if (loggerRule != null) { - accepts = loggerRule.evaluate(e); + accepts = loggerRule.evaluate(e, null); } if (!accepts) { @@ -76,7 +78,7 @@ public class RuleMediator extends Abstra } if (refinementRule != null) { - accepts = refinementRule.evaluate(e); + accepts = refinementRule.evaluate(e, null); } if (!accepts) { @@ -84,7 +86,7 @@ public class RuleMediator extends Abstra } if (exclusionRule != null) { - accepts = exclusionRule.evaluate(e); + accepts = exclusionRule.evaluate(e, null); } return accepts; Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/TableColorizingRenderer.java Sun May 9 08:30:00 2010 @@ -20,6 +20,7 @@ package org.apache.log4j.chainsaw; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.Font; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; @@ -42,17 +43,21 @@ import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTable; -import javax.swing.JTextArea; +import javax.swing.JTextPane; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.HTMLEditorKit; import org.apache.log4j.chainsaw.color.RuleColorizer; import org.apache.log4j.chainsaw.icons.LevelIconFactory; import org.apache.log4j.helpers.Constants; +import org.apache.log4j.helpers.Transform; import org.apache.log4j.rule.Rule; +import org.apache.log4j.spi.LoggingEventFieldResolver; /** @@ -70,6 +75,7 @@ public class TableColorizingRenderer ext private RuleColorizer colorizer; private boolean levelUseIcons = false; private boolean wrap = false; + private boolean highlightSearchMatchText; private DateFormat dateFormatInUse = DATE_FORMATTER; private int loggerPrecision = 0; private boolean toolTipsVisible; @@ -89,11 +95,12 @@ public class TableColorizingRenderer ext private static final Border RIGHT_EMPTY_BORDER = BorderFactory.createEmptyBorder(borderWidth, 0, borderWidth, borderWidth); private final JLabel levelLabel = new JLabel(); - private final JLabel generalLabel = new JLabel(); + private JLabel generalLabel = new JLabel(); private final JPanel multiLinePanel = new JPanel(); private final JPanel generalPanel = new JPanel(); private final JPanel levelPanel = new JPanel(); + /** * Creates a new TableColorizingRenderer object. */ @@ -128,7 +135,7 @@ public class TableColorizingRenderer ext TableColumn tableColumn = table.getColumnModel().getColumn(col); //null unless needed - JTextArea multiLineTextArea = null; + JTextPane multiLineTextPane = null; JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); //chainsawcolumns uses one-based indexing @@ -140,12 +147,19 @@ public class TableColorizingRenderer ext if (loggingEvent == null) { return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col); } + Map matches = loggingEvent.getSearchMatches(); JComponent component; switch (colIndex) { case ChainsawColumns.INDEX_THROWABLE_COL_NAME: if (value instanceof String[] && ((String[])value).length > 0){ - generalLabel.setText(((String[]) value)[0]); + //exception string is split into an array..just highlight the first line completely if anything in the exception matches if we have a match for the exception field + Set exceptionMatches = (Set)matches.get(LoggingEventFieldResolver.EXCEPTION_FIELD); + if (exceptionMatches != null && exceptionMatches.size() > 0) { + generalLabel.setText(bold(((String[])value)[0])); + } else { + generalLabel.setText(((String[])value)[0]); + } } else { generalLabel.setText(""); } @@ -161,43 +175,80 @@ public class TableColorizingRenderer ext break; } } - generalLabel.setText(logger.substring(startPos + 1)); + generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.LOGGER_FIELD), logger.substring(startPos + 1))); component = generalPanel; break; case ChainsawColumns.INDEX_ID_COL_NAME: + generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.PROP_FIELD + "LOG4JID"), value.toString())); + component = generalPanel; + break; case ChainsawColumns.INDEX_CLASS_COL_NAME: + generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.CLASS_FIELD), value.toString())); + component = generalPanel; + break; case ChainsawColumns.INDEX_FILE_COL_NAME: + generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.FILE_FIELD), value.toString())); + component = generalPanel; + break; case ChainsawColumns.INDEX_LINE_COL_NAME: + generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.LINE_FIELD), value.toString())); + component = generalPanel; + break; case ChainsawColumns.INDEX_NDC_COL_NAME: + generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.NDC_FIELD), value.toString())); + component = generalPanel; + break; case ChainsawColumns.INDEX_THREAD_COL_NAME: + generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.THREAD_FIELD), value.toString())); + component = generalPanel; + break; case ChainsawColumns.INDEX_TIMESTAMP_COL_NAME: + //timestamp matches contain the millis..not the display text..just highlight if we have a match for the timestamp field + Set timestampMatches = (Set)matches.get(LoggingEventFieldResolver.TIMESTAMP_FIELD); + if (timestampMatches != null && timestampMatches.size() > 0) { + generalLabel.setText(bold(value.toString())); + } else { + generalLabel.setText(value.toString()); + } + component = generalPanel; + break; case ChainsawColumns.INDEX_METHOD_COL_NAME: - generalLabel.setText(value.toString()); - component = generalPanel; - break; - + generalLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.METHOD_FIELD), value.toString())); + component = generalPanel; + break; case ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME: case ChainsawColumns.INDEX_MESSAGE_COL_NAME: int width = tableColumn.getWidth(); - String thisString = value.toString().trim(); + String thisString; + if (colIndex == ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME) { + //property keys are set as all uppercase + thisString = buildHighlightString(matches.get(LoggingEventFieldResolver.PROP_FIELD + ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE.toUpperCase()), value.toString().trim()); + } else { + thisString = buildHighlightString(matches.get(LoggingEventFieldResolver.MSG_FIELD), value.toString().trim()); + } int tableRowHeight = table.getRowHeight(row); - multiLineTextArea = new JTextArea(); - multiLineTextArea.setMargin(null); - multiLineTextArea.setEditable(false); - multiLineTextArea.setLineWrap(wrap); - multiLineTextArea.setWrapStyleWord(wrap); - multiLineTextArea.setFont(label.getFont()); - multiLineTextArea.setText(thisString); + multiLineTextPane = new JTextPane(); + multiLineTextPane.setEditorKit(new HTMLEditorKit()); + multiLineTextPane.setMargin(null); + multiLineTextPane.setEditable(false); + multiLineTextPane.setFont(label.getFont()); + setText(thisString); multiLinePanel.removeAll(); - multiLinePanel.add(multiLineTextArea); + multiLinePanel.add(multiLineTextPane); + HTMLDocument document = new HTMLDocument(); + multiLineTextPane.setDocument(document); + Font font = label.getFont(); + String bodyRule = "body { font-family: " + font.getFamily() + "; font-size: " + (font.getSize()) + "pt; }"; + ((HTMLDocument)multiLineTextPane.getDocument()).getStyleSheet().addRule(bodyRule); + multiLineTextPane.setText(thisString); if (wrap) { Map paramMap = new HashMap(); - paramMap.put(TextAttribute.FONT, multiLineTextArea.getFont()); + paramMap.put(TextAttribute.FONT, multiLineTextPane.getFont()); int calculatedHeight = calculateHeight(thisString, width, paramMap); //set preferred size to default height - multiLineTextArea.setSize(new Dimension(width, calculatedHeight)); + multiLineTextPane.setSize(new Dimension(width, calculatedHeight)); int multiLinePanelPrefHeight = multiLinePanel.getPreferredSize().height; if(tableRowHeight < multiLinePanelPrefHeight) { @@ -218,7 +269,7 @@ public class TableColorizingRenderer ext } } else { levelLabel.setIcon(null); - levelLabel.setText(value.toString()); + levelLabel.setText(buildHighlightString(matches.get(LoggingEventFieldResolver.LEVEL_FIELD), value.toString())); if (!toolTipsVisible) { levelLabel.setToolTipText(null); } @@ -245,7 +296,9 @@ public class TableColorizingRenderer ext } } if (thisProp != null) { - generalLabel.setText(loggingEvent.getProperty(thisProp)); + String propKey = LoggingEventFieldResolver.PROP_FIELD + thisProp.toUpperCase(); + Set propKeyMatches = (Set)matches.get(propKey); + generalLabel.setText(buildHighlightString(propKeyMatches, loggingEvent.getProperty(thisProp))); } else { generalLabel.setText(""); } @@ -257,7 +310,7 @@ public class TableColorizingRenderer ext Color foreground; Rule loggerRule = colorizer.getLoggerRule(); //use logger colors in table instead of event colors if event passes logger rule - if (loggerRule != null && loggerRule.evaluate(loggingEvent)) { + if (loggerRule != null && loggerRule.evaluate(loggingEvent, null)) { background = ChainsawConstants.FIND_LOGGER_BACKGROUND; foreground = ChainsawConstants.FIND_LOGGER_FOREGROUND; } else { @@ -280,10 +333,10 @@ public class TableColorizingRenderer ext component.setForeground(foreground); //set the colors of the components inside 'component' - if (multiLineTextArea != null) + if (multiLineTextPane != null) { - multiLineTextArea.setBackground(background); - multiLineTextArea.setForeground(foreground); + multiLineTextPane.setBackground(background); + multiLineTextPane.setForeground(foreground); } levelLabel.setBackground(background); levelLabel.setForeground(foreground); @@ -408,4 +461,78 @@ public class TableColorizingRenderer ext } return Math.max(ChainsawConstants.DEFAULT_ROW_HEIGHT, (int) height); } + + private String buildHighlightString(Object matchSet, String input) { + if (!highlightSearchMatchText) { + return Transform.escapeTags(input); + } + if (matchSet instanceof Set) { + Set thisSet = (Set)matchSet; + //start with result as input and replace each time + String result = input; + for (Iterator iter = thisSet.iterator();iter.hasNext();) { + String thisEntry = iter.next().toString(); + result = bold(result, thisEntry); + } + return "" + escapeAllButBoldTags(result) + ""; + } + return Transform.escapeTags(input); + } + + private String escapeAllButBoldTags(String input) { + if (!highlightSearchMatchText) { + return Transform.escapeTags(input); + } + String lowerInput = input.toLowerCase(); + String lowerBoldStart = ""; + String lowerBoldEnd = ""; + int boldStartLength = lowerBoldStart.length(); + int boldEndLength = lowerBoldEnd.length(); + int firstIndex = 0; + int currentIndex = 0; + StringBuffer newString = new StringBuffer(""); + while ((currentIndex = lowerInput.indexOf(lowerBoldStart, firstIndex)) > -1) { + newString.append(Transform.escapeTags(input.substring(firstIndex, currentIndex))); + newString.append(lowerBoldStart); + firstIndex = currentIndex + boldStartLength; + currentIndex = lowerInput.indexOf(lowerBoldEnd, firstIndex); + if (currentIndex > -1) { + newString.append(Transform.escapeTags(input.substring(firstIndex, currentIndex))); + newString.append(lowerBoldEnd); + firstIndex = currentIndex + boldEndLength; + } + } + newString.append(Transform.escapeTags(input.substring(firstIndex, input.length()))); + return newString.toString(); + } + + private String bold(String input) { + if (!highlightSearchMatchText) { + return Transform.escapeTags(input); + } + return "" + Transform.escapeTags(input) + ""; + } + + private String bold(String input, String textToBold) { + String lowerInput = input.toLowerCase(); + String lowerTextToBold = textToBold.toLowerCase(); + int textToBoldLength = textToBold.length(); + int firstIndex = 0; + int currentIndex = 0; + StringBuffer newString = new StringBuffer(""); + while ((currentIndex = lowerInput.indexOf(lowerTextToBold, firstIndex)) > -1) { + newString.append(input.substring(firstIndex, currentIndex)); + newString.append(""); + newString.append(input.substring(currentIndex, currentIndex + textToBoldLength)); + newString.append(""); + firstIndex = currentIndex + textToBoldLength; + } + newString.append(input.substring(firstIndex, input.length())); + return newString.toString(); + } + + public void setHighlightSearchMatchText(boolean highlightSearchMatchText) + { + this.highlightSearchMatchText = highlightSearchMatchText; + } } Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/WelcomePanel.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/WelcomePanel.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/WelcomePanel.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/WelcomePanel.java Sun May 9 08:30:00 2010 @@ -74,7 +74,7 @@ public class WelcomePanel extends JPanel textInfo.setEditable(false); textInfo.setPreferredSize(new Dimension(320, 240)); textInfo.setPage(helpURL); - JEditorPaneFormatter.applySystemFontAndSize(textInfo); + JTextComponentFormatter.applySystemFontAndSize(textInfo); textInfo.addHyperlinkListener( new HyperlinkListener() { public void hyperlinkUpdate(HyperlinkEvent e) { @@ -104,7 +104,7 @@ public class WelcomePanel extends JPanel urlStack.push(textInfo.getPage()); textInfo.setPage(url); //not all pages displayed in the Welcome Panel are html-based (example receiver config is an xml file).. - JEditorPaneFormatter.applySystemFontAndSize(textInfo); + JTextComponentFormatter.applySystemFontAndSize(textInfo); urlToolbar.updateToolbar(); } catch (IOException e) { e.printStackTrace(); Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/color/RuleColorizer.java Sun May 9 08:30:00 2010 @@ -182,7 +182,7 @@ public class RuleColorizer implements Co while (iter.hasNext()) { ColorRule rule = (ColorRule) iter.next(); - if ((rule.getBackgroundColor() != null) && (rule.evaluate(event))) { + if ((rule.getBackgroundColor() != null) && (rule.evaluate(event, null))) { return rule.getBackgroundColor(); } } @@ -199,7 +199,7 @@ public class RuleColorizer implements Co while (iter.hasNext()) { ColorRule rule = (ColorRule) iter.next(); - if ((rule.getForegroundColor() != null) && (rule.evaluate(event))) { + if ((rule.getForegroundColor() != null) && (rule.evaluate(event, null))) { return rule.getForegroundColor(); } } Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/layout/LayoutEditorPane.java URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/layout/LayoutEditorPane.java?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/layout/LayoutEditorPane.java (original) +++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/layout/LayoutEditorPane.java Sun May 9 08:30:00 2010 @@ -44,7 +44,7 @@ import javax.swing.event.DocumentListene import org.apache.log4j.Logger; import org.apache.log4j.chainsaw.ChainsawConstants; -import org.apache.log4j.chainsaw.JEditorPaneFormatter; +import org.apache.log4j.chainsaw.JTextComponentFormatter; import org.apache.log4j.chainsaw.icons.ChainsawIcons; import org.apache.log4j.spi.LocationInfo; import org.apache.log4j.spi.LoggingEvent; @@ -205,7 +205,7 @@ public final class LayoutEditorPane exte okButton.setToolTipText("Accepts the current Pattern layout and will apply it to the Log Panel"); cancelButton.setToolTipText("Closes this dialog and discards your changes"); - JEditorPaneFormatter.applySystemFontAndSize(previewer); + JTextComponentFormatter.applySystemFontAndSize(previewer); previewer.setEditable(false); patternEditor.setPreferredSize(new Dimension(240, 240)); Modified: logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html (original) +++ logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html Sun May 9 08:30:00 2010 @@ -9,7 +9,11 @@
NOTE: The mechanism and format used to persist settings in Chainsaw is subject to change. If you are experiencing problems displaying events in Chainsaw, please delete everything in the $user.dir/.chainsaw directory and restart Chainsaw.
-

1.99.99

+

2.0

+

9 May 2010

+
    +
  • Added preference to display matching search text in the table as bold (on by default)
  • +

2 May 2010

  • Added preference to line wrap the marker field in the table (multi-line rows)
  • Modified: logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties?rev=942512&r1=942511&r2=942512&view=diff ============================================================================== --- logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties (original) +++ logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/prefs/default.properties Sun May 9 08:30:00 2010 @@ -25,4 +25,5 @@ loggerPrecision= toolTips=false scrollToBottom=true logTreePanelVisible=true -detailPaneVisible=true \ No newline at end of file +detailPaneVisible=true +highlightSearchMatchText=true \ No newline at end of file