You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2016/08/31 16:23:51 UTC

[09/33] logging-log4j2 git commit: Fix XML configuration formatting

Fix XML configuration formatting


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/87235980
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/87235980
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/87235980

Branch: refs/heads/LOG4J2-1553
Commit: 8723598057dd938be060961988f6d460f82dfe90
Parents: b1e8f6f
Author: Mikael St�ldal <mi...@staldal.nu>
Authored: Sun Aug 21 15:44:28 2016 +0200
Committer: Mikael St�ldal <mi...@staldal.nu>
Committed: Sun Aug 21 15:44:28 2016 +0200

----------------------------------------------------------------------
 .../core/config/AbstractConfiguration.java      | 189 +++++++++++++++++--
 .../impl/DefaultConfigurationBuilder.java       |  27 ++-
 .../builder/ConfigurationBuilderTest.java       |  58 +++++-
 3 files changed, 245 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/87235980/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index a152ea7..f123991 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -16,24 +16,6 @@
  */
 package org.apache.logging.log4j.core.config;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
@@ -65,6 +47,29 @@ import org.apache.logging.log4j.core.util.NanoClock;
 import org.apache.logging.log4j.core.util.WatchManager;
 import org.apache.logging.log4j.util.PropertiesUtil;
 
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
 /**
  * The base Configuration. Many configuration implementations will extend this class.
  */
@@ -181,6 +186,154 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
         return rootNode;
     }
 
+    private static final List<String> SECTION_NAMES =
+            Arrays.asList("Properties", "Scripts", "CustomLevels", "Filters", "Appenders", "Loggers");
+
+    public void writeXmlConfiguration(final OutputStream output) throws IOException {
+        try {
+            XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(output);
+            writeXmlConfiguration(xmlWriter);
+            xmlWriter.close();
+        } catch (XMLStreamException e) {
+            if (e.getNestedException() instanceof IOException) {
+                throw (IOException)e.getNestedException();
+            } else {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public String toXmlConfiguration() {
+        StringWriter sw = new StringWriter();
+        try {
+            XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(sw);
+            writeXmlConfiguration(xmlWriter);
+            xmlWriter.close();
+        } catch (XMLStreamException e) {
+            throw new RuntimeException(e);
+        }
+        return sw.toString();
+    }
+
+    private void writeXmlConfiguration(XMLStreamWriter xmlWriter) throws XMLStreamException {
+        xmlWriter.writeStartDocument();
+        xmlWriter.writeCharacters(System.lineSeparator());
+
+        xmlWriter.writeStartElement("Configuration");
+
+        if (name != null) {
+            xmlWriter.writeAttribute("name", getName());
+        }
+        /* TODO status logger config
+        if (level != null) {
+            xmlWriter.writeAttribute("status", level.name());
+        }
+        if (verbosity != null) {
+            xmlWriter.writeAttribute("verbose", verbosity);
+        }
+        if (destination != null) {
+            xmlWriter.writeAttribute("dest", destination);
+        }
+        */
+        if (!getPluginPackages().isEmpty()) {
+            xmlWriter.writeAttribute("packages", getPluginPackages().toString()); // TODO comma-separated string
+        }
+        if (!isShutdownHookEnabled()) {
+            xmlWriter.writeAttribute("shutdownHook", "disable");
+        }
+        if (advertiserNode != null) {
+            xmlWriter.writeAttribute("advertiser", advertiserNode.getName());
+        }
+        if (getWatchManager().getIntervalSeconds() > 0) {
+            xmlWriter.writeAttribute("monitorInterval", String.valueOf(getWatchManager().getIntervalSeconds()));
+        }
+
+        xmlWriter.writeCharacters(System.lineSeparator());
+
+        writeXmlSection(xmlWriter, lookupSection("Properties"));
+        writeXmlSection(xmlWriter, lookupSection("Scripts"));
+        writeXmlSection(xmlWriter, lookupSection("CustomLevels"));   // TODO customLevel level vs intLevel
+        Node filters = lookupSection("Filters");
+        if (filters != null) {
+            writeXmlSection(xmlWriter, filters);
+        } else {
+            Node filter = lookupFilter();
+            if (filter != null) {
+                writeXmlNode(xmlWriter, filter, 1);
+            }
+        }
+
+        writeXmlSection(xmlWriter, lookupSection("Appenders"));
+        writeXmlSection(xmlWriter, lookupSection("Loggers"));
+
+        xmlWriter.writeEndElement(); // "Configuration"
+        xmlWriter.writeCharacters(System.lineSeparator());
+
+        xmlWriter.writeEndDocument();
+    }
+
+    private Node lookupSection(String name) {
+        for (final Node child : rootNode.getChildren()) {
+            if (child.getName().equalsIgnoreCase(name)) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    private Node lookupFilter() {
+        for (final Node child : rootNode.getChildren()) {
+            if (!SECTION_NAMES.contains(child.getName())) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    private void writeXmlSection(XMLStreamWriter xmlWriter, Node node) throws XMLStreamException {
+        if (node != null && (!node.getAttributes().isEmpty() || !node.getChildren().isEmpty() || node.getValue() != null)) {
+            writeXmlNode(xmlWriter, node, 1);
+        }
+    }
+
+    private void writeXmlNode(XMLStreamWriter xmlWriter, Node node, int nesting) throws XMLStreamException {
+        if (!node.getChildren().isEmpty() || node.getValue() != null) {
+            writeXmlIndent(xmlWriter, nesting);
+            xmlWriter.writeStartElement(node.getName());
+            writeXmlAttributes(xmlWriter, node);
+            if (!node.getChildren().isEmpty()) {
+                xmlWriter.writeCharacters(System.lineSeparator());
+            }
+            for (Node childNode : node.getChildren()) {
+                writeXmlNode(xmlWriter, childNode, nesting + 1);
+            }
+            if (node.getValue() != null) {
+                xmlWriter.writeCharacters(node.getValue());
+            }
+            if (!node.getChildren().isEmpty()) {
+                writeXmlIndent(xmlWriter, nesting);
+            }
+            xmlWriter.writeEndElement();
+        } else {
+            writeXmlIndent(xmlWriter, nesting);
+            xmlWriter.writeEmptyElement(node.getName());
+            writeXmlAttributes(xmlWriter, node);
+        }
+        xmlWriter.writeCharacters(System.lineSeparator());
+    }
+
+    private void writeXmlIndent(XMLStreamWriter xmlWriter, int nesting) throws XMLStreamException {
+        for (int i = 0; i < nesting; i++) {
+            xmlWriter.writeCharacters("\t");
+        }
+    }
+
+    private void writeXmlAttributes(XMLStreamWriter xmlWriter, Node node) throws XMLStreamException {
+        for (Map.Entry<String, String> attribute : node.getAttributes().entrySet()) {
+            xmlWriter.writeAttribute(attribute.getKey(), attribute.getValue());
+        }
+    }
+
     @Override
 	public AsyncLoggerConfigDelegate getAsyncLoggerConfigDelegate() {
 	    // lazily instantiate only when requested by AsyncLoggers:

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/87235980/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java
index 47688f7..e3de1ae 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java
@@ -255,11 +255,16 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement
 
         xmlWriter.writeCharacters(System.lineSeparator());
 
-        for (Component component : root.getComponents()) {
-            if (!component.getAttributes().isEmpty() || !component.getComponents().isEmpty() || component.getValue() != null) {
-                writeXmlComponent(xmlWriter, component, 1);
-            }
+        writeXmlSection(xmlWriter, properties);
+        writeXmlSection(xmlWriter, scripts);
+        writeXmlSection(xmlWriter, customLevels);   // TODO customLevel level vs intLevel
+        if (filters.getComponents().size() == 1) {
+            writeXmlComponent(xmlWriter, filters.getComponents().get(0), 1);
+        } else if (filters.getComponents().size() > 1) {
+            writeXmlSection(xmlWriter, filters);
         }
+        writeXmlSection(xmlWriter, appenders);
+        writeXmlSection(xmlWriter, loggers);
 
         xmlWriter.writeEndElement(); // "Configuration"
         xmlWriter.writeCharacters(System.lineSeparator());
@@ -267,19 +272,29 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement
         xmlWriter.writeEndDocument();
     }
 
+    private void writeXmlSection(XMLStreamWriter xmlWriter, Component component) throws XMLStreamException {
+        if (!component.getAttributes().isEmpty() || !component.getComponents().isEmpty() || component.getValue() != null) {
+            writeXmlComponent(xmlWriter, component, 1);
+        }
+    }
+
     private void writeXmlComponent(XMLStreamWriter xmlWriter, Component component, int nesting) throws XMLStreamException {
         if (!component.getComponents().isEmpty() || component.getValue() != null) {
             writeXmlIndent(xmlWriter, nesting);
             xmlWriter.writeStartElement(component.getPluginType());
             writeXmlAttributes(xmlWriter, component);
-            xmlWriter.writeCharacters(System.lineSeparator());
+            if (!component.getComponents().isEmpty()) {
+                xmlWriter.writeCharacters(System.lineSeparator());
+            }
             for (Component subComponent : component.getComponents()) {
                 writeXmlComponent(xmlWriter, subComponent, nesting + 1);
             }
             if (component.getValue() != null) {
                 xmlWriter.writeCharacters(component.getValue());
             }
-            writeXmlIndent(xmlWriter, nesting);
+            if (!component.getComponents().isEmpty()) {
+                writeXmlIndent(xmlWriter, nesting);
+            }
             xmlWriter.writeEndElement();
         } else {
             writeXmlIndent(xmlWriter, nesting);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/87235980/log4j-core/src/test/java/org/apache/logging/log4j/core/config/builder/ConfigurationBuilderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/builder/ConfigurationBuilderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/builder/ConfigurationBuilderTest.java
index 3d8c4d2..b4b2bff 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/builder/ConfigurationBuilderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/builder/ConfigurationBuilderTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.config.builder;
 
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.config.AbstractConfiguration;
 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
 import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
@@ -25,15 +27,19 @@ import static org.junit.Assert.assertEquals;
 
 public class ConfigurationBuilderTest {
 
-    private final static String expectedXml =
+    private final static String expectedXml1 =
             "<?xml version='1.0' encoding='UTF-8'?>" + System.lineSeparator() +
             "<Configuration name=\"config name\" status=\"ERROR\">" + System.lineSeparator() +
+            "\t<Properties>" + System.lineSeparator() +
+            "\t\t<Property name=\"MyKey\">MyValue</Property>" + System.lineSeparator() +
+            "\t</Properties>" + System.lineSeparator() +
             "\t<Scripts>" + System.lineSeparator() +
             "\t\t<ScriptFile path=\"target/test-classes/scripts/filter.groovy\" name=\"target/test-classes/scripts/filter.groovy\" isWatched=\"true\"/>" + System.lineSeparator() +
             "\t</Scripts>" + System.lineSeparator() +
-            "\t<Filters>" + System.lineSeparator() +
-            "\t\t<ThresholdFilter onMatch=\"ACCEPT\" level=\"DEBUG\" onMisMatch=\"NEUTRAL\"/>" + System.lineSeparator() +
-            "\t</Filters>" + System.lineSeparator() +
+            "\t<CustomLevels>" + System.lineSeparator() +
+            "\t\t<CustomLevel intLevel=\"17\" name=\"Panic\"/>" + System.lineSeparator() +
+            "\t</CustomLevels>" + System.lineSeparator() +
+            "\t<ThresholdFilter onMatch=\"ACCEPT\" level=\"DEBUG\" onMisMatch=\"NEUTRAL\"/>" + System.lineSeparator() +
             "\t<Appenders>" + System.lineSeparator() +
             "\t\t<CONSOLE name=\"Stdout\" target=\"SYSTEM_OUT\">" + System.lineSeparator() +
             "\t\t\t<PatternLayout pattern=\"%d [%t] %-5level: %msg%n%throwable\"/>" + System.lineSeparator() +
@@ -54,8 +60,50 @@ public class ConfigurationBuilderTest {
     public void testXmlConstructing() throws Exception {
         final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
         CustomConfigurationFactory.addTestFixtures("config name", builder);
+        builder.addProperty("MyKey", "MyValue");
+        builder.add(builder.newCustomLevel("Panic", 17));
         final String xmlConfiguration = builder.toXmlConfiguration();
-        assertEquals(expectedXml, xmlConfiguration);
+        assertEquals(expectedXml1, xmlConfiguration);
     }
 
+    private final static String expectedXml2 =
+            "<?xml version='1.0' encoding='UTF-8'?>" + System.lineSeparator() +
+            "<Configuration name=\"config name\" status=\"ERROR\">" + System.lineSeparator() +
+            "\t<Properties>" + System.lineSeparator() +
+            "\t\t<Property name=\"MyKey\">MyValue</Property>" + System.lineSeparator() +
+            "\t</Properties>" + System.lineSeparator() +
+            "\t<Scripts>" + System.lineSeparator() +
+            "\t\t<ScriptFile name=\"target/test-classes/scripts/filter.groovy\" path=\"target/test-classes/scripts/filter.groovy\" isWatched=\"true\"/>" + System.lineSeparator() +
+            "\t</Scripts>" + System.lineSeparator() +
+            "\t<CustomLevels>" + System.lineSeparator() +
+            "\t\t<CustomLevel name=\"Panic\" intLevel=\"17\"/>" + System.lineSeparator() +
+            "\t</CustomLevels>" + System.lineSeparator() +
+            "\t<ThresholdFilter onMatch=\"ACCEPT\" level=\"DEBUG\" onMisMatch=\"NEUTRAL\"/>" + System.lineSeparator() +
+            "\t<Appenders>" + System.lineSeparator() +
+            "\t\t<CONSOLE name=\"Stdout\" target=\"SYSTEM_OUT\">" + System.lineSeparator() +
+            "\t\t\t<PatternLayout pattern=\"%d [%t] %-5level: %msg%n%throwable\"/>" + System.lineSeparator() +
+            "\t\t\t<MarkerFilter onMatch=\"DENY\" onMisMatch=\"NEUTRAL\" marker=\"FLOW\"/>" + System.lineSeparator() +
+            "\t\t</CONSOLE>" + System.lineSeparator() +
+            "\t</Appenders>" + System.lineSeparator() +
+            "\t<Loggers>" + System.lineSeparator() +
+            "\t\t<Logger name=\"org.apache.logging.log4j\" additivity=\"false\" level=\"DEBUG\" includeLocation=\"true\">" + System.lineSeparator() +
+            "\t\t\t<AppenderRef ref=\"Stdout\"/>" + System.lineSeparator() +
+            "\t\t</Logger>" + System.lineSeparator() +
+            "\t\t<Root level=\"ERROR\" includeLocation=\"true\">" + System.lineSeparator() +
+            "\t\t\t<AppenderRef ref=\"Stdout\"/>" + System.lineSeparator() +
+            "\t\t</Root>" + System.lineSeparator() +
+            "\t</Loggers>" + System.lineSeparator() +
+            "</Configuration>" + System.lineSeparator();
+
+    @Test
+    public void testXmlConstructingWithAbstractConfiguration() throws Exception {
+        final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
+        CustomConfigurationFactory.addTestFixtures("config name", builder);
+        builder.addProperty("MyKey", "MyValue");
+        builder.add(builder.newCustomLevel("Panic", 17));
+        AbstractConfiguration configuration = builder.build(false);
+        configuration.setup();
+        final String xmlConfiguration = configuration.toXmlConfiguration();
+        assertEquals(expectedXml2, xmlConfiguration);
+    }
 }