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>


Reply via email to