Nice! :-)
Gary ---------- Forwarded message ---------- From: <mi...@apache.org> Date: Aug 14, 2016 12:37 PM Subject: logging-log4j2 git commit: Ported Log4j 1's XMLLayout To: <comm...@logging.apache.org> Cc: Repository: logging-log4j2 Updated Branches: refs/heads/master f511f848c -> 8e01bde35 Ported Log4j 1's XMLLayout Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/ commit/8e01bde3 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/8e01bde3 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/8e01bde3 Branch: refs/heads/master Commit: 8e01bde35dfc47e071168f8554864ce4e8258007 Parents: f511f84 Author: Mikael Ståldal <mik...@staldal.nu> Authored: Sun Aug 14 21:37:26 2016 +0200 Committer: Mikael Ståldal <mik...@staldal.nu> Committed: Sun Aug 14 21:37:26 2016 +0200 ---------------------------------------------------------------------- log4j-1.2-api/pom.xml | 4 + .../config/Log4j1ConfigurationFactory.java | 4 +- .../apache/log4j/layout/Log4j1XmlLayout.java | 104 +++++++++++++++++++ .../config/Log4j1ConfigurationFactoryTest.java | 11 +- .../log4j/layout/Log4j1XmlLayoutTest.java | 48 +++++++++ 5 files changed, 163 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ 8e01bde3/log4j-1.2-api/pom.xml ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/pom.xml b/log4j-1.2-api/pom.xml index 779f050..76b1937 100644 --- a/log4j-1.2-api/pom.xml +++ b/log4j-1.2-api/pom.xml @@ -54,6 +54,10 @@ <artifactId>log4j-api</artifactId> </dependency> <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <type>test-jar</type> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ 8e01bde3/log4j-1.2-api/src/main/java/org/apache/log4j/config/ Log4j1ConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/config/ Log4j1ConfigurationFactory.java b/log4j-1.2-api/src/main/java/ org/apache/log4j/config/Log4j1ConfigurationFactory.java index d351897..d0126bf 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/config/ Log4j1ConfigurationFactory.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/config/ Log4j1ConfigurationFactory.java @@ -57,6 +57,7 @@ import org.apache.logging.log4j.status.StatusLogger; * <li>layout = org.apache.log4j.SimpleLayout</li> * <li>layout = org.apache.log4j.TTCCLayout</li> * <li>layout = org.apache.log4j.HTMLLayout</li> + * <li>layout = org.apache.log4j.xml.XMLLayout</li> * <li>layout.ConversionPattern</li> * </ul> * </ul> @@ -143,8 +144,7 @@ public class Log4j1ConfigurationFactory extends ConfigurationFactory { break; } case "org.apache.log4j.xml.XMLLayout": { - // We cannot use the XmlLayout in Log4j 2 since it has a significantly different format - reportWarning("Log4j 1 XMLLayout is not supported"); + appenderBuilder.add(builder.newLayout("Log4j1XmlLayout")); break; } default: http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ 8e01bde3/log4j-1.2-api/src/main/java/org/apache/log4j/ layout/Log4j1XmlLayout.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/layout/Log4j1XmlLayout.java b/log4j-1.2-api/src/main/java/org/apache/log4j/layout/Log4j1XmlLayout.java new file mode 100644 index 0000000..d602b41 --- /dev/null +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/layout/ Log4j1XmlLayout.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.log4j.layout; + +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.Node; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.layout.AbstractStringLayout; +import org.apache.logging.log4j.core.layout.ByteBufferDestination; +import org.apache.logging.log4j.core.util.Transform; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +/** + * Port of XMLLayout in Log4j 1.x. Provided for compatibility with existing Log4j 1 configurations. + * + * Originally developed by Ceki Gülcü, Mathias Bogaert. + */ +@Plugin(name = "Log4j1XmlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true) +public final class Log4j1XmlLayout extends AbstractStringLayout { + + @PluginFactory + public static Log4j1XmlLayout createLayout() { + return new Log4j1XmlLayout(); + } + + private Log4j1XmlLayout() { + super(StandardCharsets.UTF_8); + } + + @Override + public void encode(final LogEvent event, final ByteBufferDestination destination) { + final StringBuilder text = getStringBuilder(); + formatTo(event, text); + getStringBuilderEncoder().encode(text, destination); + } + + @Override + public String toSerializable(final LogEvent event) { + final StringBuilder text = getStringBuilder(); + formatTo(event, text); + return text.toString(); + } + + private void formatTo(final LogEvent event, final StringBuilder buf) { + // We yield to the \r\n heresy. + + buf.append("<log4j:event logger=\""); + buf.append(Transform.escapeHtmlTags(event.getLoggerName())); + buf.append("\" timestamp=\""); + buf.append(event.getTimeMillis()); + buf.append("\" level=\""); + buf.append(Transform.escapeHtmlTags(String.valueOf( event.getLevel()))); + buf.append("\" thread=\""); + buf.append(Transform.escapeHtmlTags(event.getThreadName())); + buf.append("\">\r\n"); + + buf.append("<log4j:message><![CDATA["); + // Append the rendered message. Also make sure to escape any existing CDATA sections. + Transform.appendEscapingCData(buf, event.getMessage(). getFormattedMessage()); + buf.append("]]></log4j:message>\r\n"); + + List<String> ndc = event.getContextStack().asList(); + if (!ndc.isEmpty()) { + buf.append("<log4j:NDC><![CDATA["); + Transform.appendEscapingCData(buf, StringUtils.join(ndc, ' ')); + buf.append("]]></log4j:NDC>\r\n"); + } + + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + Throwable thrown = event.getThrown(); + if (thrown != null) { + buf.append("<log4j:throwable><![CDATA["); + buf.append(thrown.toString()); + buf.append("\r\n"); + for (StackTraceElement element : thrown.getStackTrace()) { + Transform.appendEscapingCData(buf, "\tat " + element.toString()); + buf.append("\r\n"); + } + buf.append("]]></log4j:throwable>\r\n"); + } + + buf.append("</log4j:event>\r\n\r\n"); + } + +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ 8e01bde3/log4j-1.2-api/src/test/java/org/apache/log4j/config/ Log4j1ConfigurationFactoryTest.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/ Log4j1ConfigurationFactoryTest.java b/log4j-1.2-api/src/test/java/ org/apache/log4j/config/Log4j1ConfigurationFactoryTest.java index 48a154d..35445c4 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/ Log4j1ConfigurationFactoryTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/ Log4j1ConfigurationFactoryTest.java @@ -16,8 +16,7 @@ */ package org.apache.log4j.config; -import java.net.URL; - +import org.apache.log4j.layout.Log4j1XmlLayout; import org.apache.log4j.layout.TTCCLayout; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Layout; @@ -27,11 +26,11 @@ import org.apache.logging.log4j.core. config.Configuration; import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.core.layout.HtmlLayout; import org.apache.logging.log4j.core.layout.PatternLayout; -import org.apache.logging.log4j.core.layout.XmlLayout; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; +import java.net.URL; + public class Log4j1ConfigurationFactoryTest { private Layout<?> testConsole(final String configResource) throws Exception { @@ -82,9 +81,9 @@ public class Log4j1ConfigurationFactoryTest { Assert.assertTrue(layout instanceof TTCCLayout); } - @Ignore("XmlLayout not supported") + @Test public void testConsoleXmlLayout() throws Exception { final Layout<?> layout = testConsole("config-1.2/log4j- console-XmlLayout.properties"); - Assert.assertTrue(layout instanceof XmlLayout); + Assert.assertTrue(layout instanceof Log4j1XmlLayout); } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ 8e01bde3/log4j-1.2-api/src/test/java/org/apache/log4j/ layout/Log4j1XmlLayoutTest.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/layout/Log4j1XmlLayoutTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/layout/ Log4j1XmlLayoutTest.java new file mode 100644 index 0000000..9898550 --- /dev/null +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/layout/ Log4j1XmlLayoutTest.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.log4j.layout; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.message.SimpleMessage; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class Log4j1XmlLayoutTest { + + @Test + public void testWithoutThrown() { + Log4j1XmlLayout layout = Log4j1XmlLayout.createLayout(); + + Log4jLogEvent event = Log4jLogEvent.newBuilder() + .setLoggerName("a.B") + .setLevel(Level.INFO) + .setMessage(new SimpleMessage("Hello, World")) + .setTimeMillis(System.currentTimeMillis() + 17).build(); + + String result = layout.toSerializable(event); + + String expected = + "<log4j:event logger=\"a.B\" timestamp=\"" + event.getTimeMillis() + "\" level=\"INFO\" thread=\"main\">\r\n" + + "<log4j:message><![CDATA[Hello, World]]></log4j:message>\r\n" + + "</log4j:event>\r\n\r\n"; + + assertEquals(expected, result); + } + +}