Author: sdeboy
Date: Fri Nov 5 08:26:33 2010
New Revision: 1031469
URL: http://svn.apache.org/viewvc?rev=1031469&view=rev
Log:
Added ability to create log file receiver configurations from log4j xml configuration fileappender entries
Parses the xml configuration and the patternLayout and date specifiers and creates LogFilePatternReceiver entries
Modified:
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogUI.java
logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java
logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html
Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java?rev=1031469&r1=1031468&r2=1031469&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/LogFilePatternLayoutBuilder.java Fri Nov 5 08:26:33 2010
@@ -16,13 +16,23 @@
*/
package org.apache.log4j.chainsaw;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.log4j.FileAppender;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.pattern.ClassNamePatternConverter;
+import org.apache.log4j.pattern.DatePatternConverter;
import org.apache.log4j.pattern.FileLocationPatternConverter;
import org.apache.log4j.pattern.FullLocationPatternConverter;
import org.apache.log4j.pattern.LevelPatternConverter;
@@ -39,6 +49,14 @@ import org.apache.log4j.pattern.Properti
import org.apache.log4j.pattern.RelativeTimePatternConverter;
import org.apache.log4j.pattern.SequenceNumberPatternConverter;
import org.apache.log4j.pattern.ThreadPatternConverter;
+import org.apache.log4j.xml.Log4jEntityResolver;
+import org.apache.log4j.xml.SAXErrorHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
public class LogFilePatternLayoutBuilder
{
@@ -52,11 +70,39 @@ public class LogFilePatternLayoutBuilder
return getFormatFromConverters(converters);
}
+ public static String getTimeStampFormat(String patternLayout) {
+ int basicIndex = patternLayout.indexOf("%d");
+ if (basicIndex < 0) {
+ return null;
+ }
+
+ int index = patternLayout.indexOf("%d{");
+ //%d - default
+ if (index < 0) {
+ return "yyyy-MM-dd HH:mm:ss,SSS";
+ }
+
+ int length = patternLayout.substring(index).indexOf("}");
+ String timestampFormat = patternLayout.substring(index + "%d{".length(), index + length);
+ if (timestampFormat.equals("ABSOLUTE")) {
+ return "HH:mm:ss,SSS";
+ }
+ if (timestampFormat.equals("ISO8601")) {
+ return "yyyy-MM-dd HH:mm:ss,SSS";
+ }
+ if (timestampFormat.equals("DATE")) {
+ return "dd MMM yyyy HH:mm:ss,SSS";
+ }
+ return timestampFormat;
+ }
+
private static String getFormatFromConverters(List converters) {
StringBuffer buffer = new StringBuffer();
for (Iterator iter = converters.iterator();iter.hasNext();) {
LoggingEventPatternConverter converter = (LoggingEventPatternConverter)iter.next();
- if (converter instanceof MessagePatternConverter) {
+ if (converter instanceof DatePatternConverter) {
+ buffer.append("TIMESTAMP");
+ } else if (converter instanceof MessagePatternConverter) {
buffer.append("MESSAGE");
} else if (converter instanceof LoggerPatternConverter) {
buffer.append("LOGGER");
@@ -98,4 +144,74 @@ public class LogFilePatternLayoutBuilder
}
return buffer.toString();
}
+
+ public static Map getAppenderConfiguration(File file) throws IOException, ParserConfigurationException, SAXException {
+ InputStream stream = file.toURI().toURL().openStream();
+ Map result = new HashMap();
+ try {
+ InputSource src = new InputSource(stream);
+ src.setSystemId(file.toURI().toURL().toString());
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+
+ docBuilder.setErrorHandler(new SAXErrorHandler());
+ docBuilder.setEntityResolver(new Log4jEntityResolver());
+ Document doc = docBuilder.parse(src);
+ NodeList appenders = doc.getElementsByTagName("appender");
+ for (int i = 0; i < appenders.getLength(); i++) {
+ Node appender = appenders.item(i);
+ NamedNodeMap appenderAttributes = appender.getAttributes();
+// Class appenderClass = Class.forName(map.getNamedItem("class").getNodeValue());
+ Node appenderClass = appenderAttributes.getNamedItem("class");
+ try {
+ if (appenderAttributes.getNamedItem("name") != null && appenderClass != null && appenderClass.getNodeValue() != null) {
+ //load the class or try to support custom subclasses that we don't have available in the classpath but end in 'FileAppender'
+ if (appenderClass.getNodeValue().toLowerCase().endsWith("fileappender") || FileAppender.class.isAssignableFrom(Class.forName(appenderClass.getNodeValue()))) {
+ String appenderName = appenderAttributes.getNamedItem("name").getNodeValue();
+ //subclass of FileAppender - add it
+ Map entry = new HashMap();
+ NodeList appenderChildren = appender.getChildNodes();
+ for (int j = 0; j < appenderChildren.getLength(); j++) {
+ Node appenderChild = appenderChildren.item(j);
+ if (appenderChild.getNodeName().equals("param") && appenderChild.hasAttributes()) {
+ Node fileNameNode = appenderChild.getAttributes().getNamedItem("name");
+ if (fileNameNode != null && fileNameNode.getNodeValue().equals("file")) {
+ Node fileValueNode = appenderChild.getAttributes().getNamedItem("value");
+ if (fileValueNode != null) {
+ entry.put("file", fileValueNode.getNodeValue());
+ }
+ }
+ }
+ if (appenderChild.getNodeName().equals("layout") && appenderChild.hasAttributes()) {
+ NamedNodeMap layoutAttributes = appenderChild.getAttributes();
+ Node layoutNode = layoutAttributes.getNamedItem("class");
+ if (layoutNode != null && layoutNode.getNodeValue() != null && layoutNode.getNodeValue().equals("org.apache.log4j.PatternLayout")) {
+ NodeList layoutChildren = appenderChild.getChildNodes();
+ for (int k = 0; k < layoutChildren.getLength(); k++) {
+ Node layoutChild = layoutChildren.item(k);
+ if (layoutChild.getNodeName().equals("param") && layoutChild.hasAttributes()) {
+ Node layoutName = layoutChild.getAttributes().getNamedItem("name");
+ if (layoutName != null && layoutName.getNodeValue() != null && layoutName.getNodeValue().equals("ConversionPattern")) {
+ Node conversionValue = layoutChild.getAttributes().getNamedItem("value");
+ if (conversionValue != null) {
+ entry.put("conversion", conversionValue.getNodeValue());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result.put(appenderName, entry);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ } finally {
+ stream.close();
+ }
+ return result;
+ }
}
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=1031469&r1=1031468&r2=1031469&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 Fri Nov 5 08:26:33 2010
@@ -84,6 +84,7 @@ import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
+import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Appender;
import org.apache.log4j.AppenderSkeleton;
@@ -126,6 +127,7 @@ import org.apache.log4j.spi.LoggingEvent
import org.apache.log4j.spi.RepositorySelector;
import org.apache.log4j.xml.DOMConfigurator;
import org.apache.log4j.xml.XMLDecoder;
+import org.xml.sax.SAXException;
/**
@@ -1459,6 +1461,47 @@ public class LogUI extends JFrame implem
MessageCenter.getInstance().getLogger().info(
"An error occurred creating your Receiver");
}
+ } else if (receiverConfigurationPanel.getModel().isLog4jConfig()) {
+ File log4jConfigFile = receiverConfigurationPanel.getModel().getLog4jConfigFile();
+ if (log4jConfigFile != null) {
+ try {
+ Map entries = LogFilePatternLayoutBuilder.getAppenderConfiguration(log4jConfigFile);
+ for (Iterator iter = entries.entrySet().iterator();iter.hasNext();) {
+ try {
+ Map.Entry entry = (Map.Entry)iter.next();
+ String name = (String) entry.getKey();
+ Map values = (Map) entry.getValue();
+ //values: conversion, file
+ String conversionPattern = values.get("conversion").toString();
+ File file = new File(values.get("file").toString());
+ URL fileURL = file.toURI().toURL();
+ String timestampFormat = LogFilePatternLayoutBuilder.getTimeStampFormat(conversionPattern);
+ String receiverPattern = LogFilePatternLayoutBuilder.getLogFormatFromPatternLayout(conversionPattern);
+ VFSLogFilePatternReceiver fileReceiver = new VFSLogFilePatternReceiver();
+ fileReceiver.setName(name);
+ fileReceiver.setAutoReconnect(true);
+ fileReceiver.setContainer(LogUI.this);
+ fileReceiver.setAppendNonMatches(true);
+ fileReceiver.setFileURL(fileURL.toURI().toString());
+ fileReceiver.setTailing(true);
+ fileReceiver.setLogFormat(receiverPattern);
+ fileReceiver.setTimestampFormat(timestampFormat);
+ fileReceiver.setThreshold(Level.TRACE);
+ pluginRegistry.addPlugin(fileReceiver);
+ fileReceiver.activateOptions();
+ receiversPanel.updateReceiverTreeInDispatchThread();
+ } catch (URISyntaxException e1) {
+ e1.printStackTrace();
+ }
+ }
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ } catch (ParserConfigurationException e1) {
+ e1.printStackTrace();
+ } catch (SAXException e1) {
+ e1.printStackTrace();
+ }
+ }
} else if (receiverConfigurationPanel.getModel().isLoadConfig()) {
configURL = receiverConfigurationPanel.getModel().getConfigToLoad();
} else if (receiverConfigurationPanel.getModel().isLogFileReceiverConfig()) {
Modified: logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java?rev=1031469&r1=1031468&r2=1031469&view=diff
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java (original)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/chainsaw/ReceiverConfigurationPanel.java Fri Nov 5 08:26:33 2010
@@ -30,6 +30,7 @@ import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
import java.net.MalformedURLException;
+import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
@@ -74,6 +75,10 @@ class ReceiverConfigurationPanel extends
private DefaultComboBoxModel networkReceiverClassNameComboBoxModel;
private DefaultComboBoxModel networkReceiverPortComboBoxModel;
+ //log4j config receiver widgets
+ private JButton browseLog4jConfigButton;
+ private JTextField log4jConfigURLTextField;
+
//logfile receiver widgets
private JButton browseLogFileButton;
private JComboBox logFileFormatTypeComboBox;
@@ -97,6 +102,7 @@ class ReceiverConfigurationPanel extends
private JButton cancelButton;
//radiobutton widgets
+ private JRadioButton log4jConfigReceiverRadioButton;
private JRadioButton logFileReceiverRadioButton;
private JRadioButton networkReceiverRadioButton;
private JRadioButton useExistingConfigurationRadioButton;
@@ -106,6 +112,7 @@ class ReceiverConfigurationPanel extends
private final JPanel networkReceiverPanel = buildNetworkReceiverPanel();
private final JPanel logFileReceiverPanel = buildLogFileReceiverPanel();
+ private final JPanel log4jConfigReceiverPanel = buildLog4jConfigReceiverPanel();
private final JPanel useExistingConfigurationPanel = buildUseExistingConfigurationPanel();
private final JPanel dontWarnAndOKPanel = buildDontWarnAndOKPanel();
private final JPanel bottomDescriptionPanel = buildBottomDescriptionPanel();
@@ -140,6 +147,14 @@ class ReceiverConfigurationPanel extends
c.gridx = 0;
c.gridy = yPos++;
c.fill = GridBagConstraints.HORIZONTAL;
+ log4jConfigReceiverRadioButton = new JRadioButton(" Use log4j.xml fileappender configuration ");
+ buttonGroup.add(log4jConfigReceiverRadioButton);
+ add(log4jConfigReceiverRadioButton, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = yPos++;
+ c.fill = GridBagConstraints.HORIZONTAL;
networkReceiverRadioButton = new JRadioButton(" Receive events from the network ");
buttonGroup.add(networkReceiverRadioButton);
add(networkReceiverRadioButton, c);
@@ -185,6 +200,7 @@ class ReceiverConfigurationPanel extends
};
logFileReceiverRadioButton.addActionListener(al);
+ log4jConfigReceiverRadioButton.addActionListener(al);
networkReceiverRadioButton.addActionListener(al);
useExistingConfigurationRadioButton.addActionListener(al);
@@ -332,6 +348,52 @@ class ReceiverConfigurationPanel extends
return panel;
}
+ private JPanel buildLog4jConfigReceiverPanel() {
+ log4jConfigURLTextField = new JTextField();
+ browseLog4jConfigButton = new JButton(new AbstractAction(" Open File... ") {
+ public void actionPerformed(ActionEvent e) {
+ try {
+
+ URL url = browseConfig();
+
+ if (url != null) {
+ log4jConfigURLTextField.setText(url.toExternalForm());
+ }
+ } catch (Exception ex) {
+ logger.error(
+ "Error browsing for log4j config file", ex);
+ }
+ }
+ });
+
+ browseLog4jConfigButton.setToolTipText(
+ "Shows a File Open dialog to allow you to find a log4j configuration file");
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ c.gridwidth = 2;
+ c.anchor = GridBagConstraints.LINE_START;
+ c.insets = new Insets(0, 0, 5, 0);
+ panel.add(browseLog4jConfigButton, c);
+
+ c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 1;
+ c.insets = new Insets(0, 5, 0, 5);
+ panel.add(new JLabel(" log4j configuration file URL "), c);
+
+ c = new GridBagConstraints();
+ c.gridx = 1;
+ c.gridy = 1;
+ c.weightx = 0.5;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ panel.add(log4jConfigURLTextField, c);
+
+
+ return panel;
+ }
+
private JPanel buildLogFileReceiverPanel() {
JPanel panel = new JPanel(new GridBagLayout());
browseLogFileButton = new JButton(new AbstractAction(" Open File... ") {
@@ -566,6 +628,9 @@ class ReceiverConfigurationPanel extends
if (component == logFileReceiverRadioButton) {
lowerPanel.add(logFileReceiverPanel, BorderLayout.NORTH);
}
+ if (component == log4jConfigReceiverRadioButton) {
+ lowerPanel.add(log4jConfigReceiverPanel, BorderLayout.NORTH);
+ }
lowerPanel.revalidate();
lowerPanel.repaint();
}
@@ -683,6 +748,10 @@ class ReceiverConfigurationPanel extends
return !cancelled && logFileReceiverRadioButton.isSelected();
}
+ boolean isLog4jConfig() {
+ return !cancelled && log4jConfigReceiverRadioButton.isSelected();
+ }
+
URL getConfigToLoad() {
try
@@ -767,5 +836,17 @@ class ReceiverConfigurationPanel extends
public boolean isCancelled() {
return cancelled;
}
+
+ public File getLog4jConfigFile() {
+ try {
+ URL newConfigurationURL = new URL(log4jConfigURLTextField.getText());
+ return new File(newConfigurationURL.toURI());
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
}
}
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=1031469&r1=1031468&r2=1031469&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 Fri Nov 5 08:26:33 2010
@@ -10,6 +10,11 @@
<b>NOTE:</b> 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.
<br>
<h1>2.1</h1>
+<h2>5 Nov 2010</h2>
+<ul>
+<li>Added ability to create log file receiver configurations from log4j xml configuration fileappender entries</li>
+<li>Added ability to save the receiver configuration from the receiver modification panel</li>
+</ul>
<h2>4 Nov 2010</h2>
<ul>
<li>Added ability to save the receiver configuration defined through the initial receiver configuration panel with a user-specified file path and name</li>
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.