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 2022/01/21 13:41:35 UTC

[logging-log4j2] 01/02: Log4j 1.2 bridge throws `ClassCastException` when using `SimpleLayout` and others (#708)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit d3fb87571f4cd99910178c83eee40a28ec5d1367
Author: ppkarwasz <pi...@karwasz.org>
AuthorDate: Fri Jan 21 14:26:22 2022 +0100

    Log4j 1.2 bridge throws `ClassCastException` when using `SimpleLayout` and others (#708)
    
    * Adds marker interface Builder
    
    Since not all Log4j 1.x component builders extend `AbstractBuilder`, the
    tests with some layouts threw a `ClassCastException`.
    
    * Update Builder.java
    
    Remove dead space.
    
    * Ports common tests from `Log4j1ConfigurationFactoryTest`
    
    * Adds log message instead of ClassCastException
    
    If a custom builder plugin does not implement `Builder`, a message is
    logged instead of a `ClassCastException`.
    
    All standard builders do implement `Builder`.
    
    Co-authored-by: Piotr P. Karwasz <pi...@copernik.pl>
    Co-authored-by: Gary Gregory <ga...@users.noreply.github.com>
    Co-authored-by: Piotr P. Karwasz <pi...@karwasz.org>
---
 .../org/apache/log4j/builders/AbstractBuilder.java |  2 +-
 .../{layout/LayoutBuilder.java => Builder.java}    | 15 ++----
 .../org/apache/log4j/builders/BuilderManager.java  | 14 +++--
 .../log4j/builders/appender/AppenderBuilder.java   |  3 +-
 .../log4j/builders/filter/FilterBuilder.java       |  3 +-
 .../log4j/builders/layout/LayoutBuilder.java       |  3 +-
 .../builders/rewrite/RewritePolicyBuilder.java     |  3 +-
 .../config/AbstractLog4j1ConfigurationTest.java    | 61 ++++++++++++++++++++--
 .../config/Log4j1ConfigurationFactoryTest.java     | 46 +++++-----------
 .../log4j/config/PropertiesConfigurationTest.java  | 36 +++++++++++++
 .../apache/log4j/config/XmlConfigurationTest.java  | 36 +++++++++++++
 .../resources/config-1.2/log4j-NullAppender.xml    | 26 +++++++++
 .../log4j-console-EnhancedPatternLayout.xml        | 35 +++++++++++++
 .../config-1.2/log4j-console-HtmlLayout.xml        | 36 +++++++++++++
 .../config-1.2/log4j-console-PatternLayout.xml     | 35 +++++++++++++
 .../config-1.2/log4j-console-SimpleLayout.xml      | 33 ++++++++++++
 .../config-1.2/log4j-file-SimpleLayout.xml         | 33 ++++++++++++
 17 files changed, 361 insertions(+), 59 deletions(-)

diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.java
index e4037ef..c6118cf 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.java
@@ -40,7 +40,7 @@ import org.w3c.dom.Element;
 /**
  * Base class for Log4j 1 component builders.
  */
-public abstract class AbstractBuilder {
+public abstract class AbstractBuilder implements Builder {
 
     private static final Logger LOGGER = StatusLogger.getLogger();
     protected static final String FILE_PARAM = "File";
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/LayoutBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/Builder.java
similarity index 67%
copy from log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/LayoutBuilder.java
copy to log4j-1.2-api/src/main/java/org/apache/log4j/builders/Builder.java
index 4f28284..48cd982 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/LayoutBuilder.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/Builder.java
@@ -14,19 +14,10 @@
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
-package org.apache.log4j.builders.layout;
 
-import org.apache.log4j.Layout;
-import org.apache.log4j.config.PropertiesConfiguration;
-import org.apache.log4j.xml.XmlConfiguration;
-import org.w3c.dom.Element;
+package org.apache.log4j.builders;
 
 /**
- * Define a Layout Builder.
+ * A marker interface for Log4j 1.x component builders.
  */
-public interface LayoutBuilder {
-
-    Layout parseLayout(Element element, XmlConfiguration config);
-
-    Layout parseLayout(PropertiesConfiguration config);
-}
+public interface Builder {}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
index 3e275d7..ca8e7d7 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
@@ -156,18 +156,22 @@ public class BuilderManager {
         return null;
     }
 
-    private <T extends AbstractBuilder> T createBuilder(PluginType<?> plugin, String prefix, Properties props) {
+    @SuppressWarnings("unchecked")
+    private <T extends Builder> T createBuilder(PluginType<?> plugin, String prefix, Properties props) {
         try {
             Class<?> clazz = plugin.getPluginClass();
             if (AbstractBuilder.class.isAssignableFrom(clazz)) {
-                @SuppressWarnings("unchecked")
                 Constructor<T> constructor =
                         (Constructor<T>) clazz.getConstructor(CONSTRUCTOR_PARAMS);
                 return constructor.newInstance(prefix, props);
             }
-            @SuppressWarnings("unchecked")
-            T builder = (T) LoaderUtil.newInstanceOf(clazz);
-            return builder;
+            Object builder = LoaderUtil.newInstanceOf(clazz);
+            // Reasonable message instead of `ClassCastException`
+            if (!Builder.class.isAssignableFrom(clazz)) {
+                LOGGER.warn("Unable to load plugin: builder {} does not implement {}", clazz, Builder.class);
+                return null;
+            }
+            return (T) builder;
         } catch (ReflectiveOperationException ex) {
             LOGGER.warn("Unable to load plugin: {} due to: {}", plugin.getKey(), ex.getMessage());
             return null;
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
index bb7ff93..ff57bae 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/AppenderBuilder.java
@@ -17,6 +17,7 @@
 package org.apache.log4j.builders.appender;
 
 import org.apache.log4j.Appender;
+import org.apache.log4j.builders.Builder;
 import org.apache.log4j.config.PropertiesConfiguration;
 import org.apache.log4j.xml.XmlConfiguration;
 import org.w3c.dom.Element;
@@ -26,7 +27,7 @@ import java.util.Properties;
 /**
  * Define an Appender Builder.
  */
-public interface AppenderBuilder {
+public interface AppenderBuilder extends Builder {
 
     Appender parseAppender(Element element, XmlConfiguration configuration);
 
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/FilterBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/FilterBuilder.java
index f26e7cb..e331927 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/FilterBuilder.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/FilterBuilder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.log4j.builders.filter;
 
+import org.apache.log4j.builders.Builder;
 import org.apache.log4j.config.PropertiesConfiguration;
 import org.apache.log4j.spi.Filter;
 import org.apache.log4j.xml.XmlConfiguration;
@@ -24,7 +25,7 @@ import org.w3c.dom.Element;
 /**
  * Define a Filter Builder.
  */
-public interface FilterBuilder {
+public interface FilterBuilder extends Builder {
 
     Filter parseFilter(Element element, XmlConfiguration config);
 
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/LayoutBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/LayoutBuilder.java
index 4f28284..0a3ecb2 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/LayoutBuilder.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/LayoutBuilder.java
@@ -17,6 +17,7 @@
 package org.apache.log4j.builders.layout;
 
 import org.apache.log4j.Layout;
+import org.apache.log4j.builders.Builder;
 import org.apache.log4j.config.PropertiesConfiguration;
 import org.apache.log4j.xml.XmlConfiguration;
 import org.w3c.dom.Element;
@@ -24,7 +25,7 @@ import org.w3c.dom.Element;
 /**
  * Define a Layout Builder.
  */
-public interface LayoutBuilder {
+public interface LayoutBuilder extends Builder {
 
     Layout parseLayout(Element element, XmlConfiguration config);
 
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rewrite/RewritePolicyBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rewrite/RewritePolicyBuilder.java
index 5ca196a..94500ae 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rewrite/RewritePolicyBuilder.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rewrite/RewritePolicyBuilder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.log4j.builders.rewrite;
 
+import org.apache.log4j.builders.Builder;
 import org.apache.log4j.config.PropertiesConfiguration;
 import org.apache.log4j.rewrite.RewritePolicy;
 import org.apache.log4j.xml.XmlConfiguration;
@@ -24,7 +25,7 @@ import org.w3c.dom.Element;
 /**
  * Define a RewritePolicy Builder.
  */
-public interface RewritePolicyBuilder {
+public interface RewritePolicyBuilder extends Builder {
 
     RewritePolicy parseRewritePolicy(Element element, XmlConfiguration config);
 
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
index 8e27c74..98e1931 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java
@@ -33,6 +33,8 @@ import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.appender.ConsoleAppender;
 import org.apache.logging.log4j.core.appender.ConsoleAppender.Target;
+import org.apache.logging.log4j.core.appender.FileAppender;
+import org.apache.logging.log4j.core.appender.NullAppender;
 import org.apache.logging.log4j.core.appender.RollingFileAppender;
 import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
 import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
@@ -42,7 +44,9 @@ import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy;
 import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
 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.junit.Test;
 
 public abstract class AbstractLog4j1ConfigurationTest {
 
@@ -77,8 +81,7 @@ public abstract class AbstractLog4j1ConfigurationTest {
         final Configuration configuration = getConfiguration(configResource);
         final String name = "Console";
         final ConsoleAppender appender = configuration.getAppender(name);
-        assertNotNull("Missing appender '" + name + "' in configuration " + configResource + " → " + configuration,
-                appender);
+        assertNotNull("Missing appender '" + name + "' in configuration " + configResource + " → " + configuration, appender);
         assertEquals(Target.SYSTEM_ERR, appender.getTarget());
         //
         final LoggerConfig loggerConfig = configuration.getLoggerConfig("com.example.foo");
@@ -143,7 +146,8 @@ public abstract class AbstractLog4j1ConfigurationTest {
         }
     }
 
-    private void testRollingFileAppender(final String configResource, final String name, final String filePattern) throws Exception {
+    private void testRollingFileAppender(final String configResource, final String name, final String filePattern)
+            throws Exception {
         final Configuration configuration = getConfiguration(configResource);
         final Appender appender = configuration.getAppender(name);
         assertNotNull(appender);
@@ -170,7 +174,8 @@ public abstract class AbstractLog4j1ConfigurationTest {
         configuration.stop();
     }
 
-    private void testDailyRollingFileAppender(final String configResource, final String name, final String filePattern) throws Exception {
+    private void testDailyRollingFileAppender(final String configResource, final String name, final String filePattern)
+            throws Exception {
         final Configuration configuration = getConfiguration(configResource);
         final Appender appender = configuration.getAppender(name);
         assertNotNull(appender);
@@ -197,4 +202,52 @@ public abstract class AbstractLog4j1ConfigurationTest {
         configuration.stop();
     }
 
+    private Layout<?> testFile(final String configResource) throws Exception {
+        final Configuration configuration = getConfiguration(configResource);
+        final FileAppender appender = configuration.getAppender("File");
+        assertNotNull(appender);
+        assertEquals("target/mylog.txt", appender.getFileName());
+        //
+        final LoggerConfig loggerConfig = configuration.getLoggerConfig("com.example.foo");
+        assertNotNull(loggerConfig);
+        assertEquals(Level.DEBUG, loggerConfig.getLevel());
+        configuration.start();
+        configuration.stop();
+        return appender.getLayout();
+    }
+
+    public void testConsoleEnhancedPatternLayout() throws Exception {
+        final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-EnhancedPatternLayout");
+        assertEquals("%d{ISO8601} [%t][%c] %-5p %properties %ndc: %m%n", layout.getConversionPattern());
+    }
+
+    public void testConsoleHtmlLayout() throws Exception {
+        final HtmlLayout layout = (HtmlLayout) testConsole("config-1.2/log4j-console-HtmlLayout");
+        assertEquals("Headline", layout.getTitle());
+        assertTrue(layout.isLocationInfo());
+    }
+
+    public void testConsolePatternLayout() throws Exception {
+        final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-PatternLayout");
+        assertEquals("%d{ISO8601} [%t][%c] %-5p: %m%n", layout.getConversionPattern());
+    }
+
+    public void testConsoleSimpleLayout() throws Exception {
+        final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-SimpleLayout");
+        assertEquals("%level - %m%n", layout.getConversionPattern());
+    }
+
+    public void testFileSimpleLayout() throws Exception {
+        final PatternLayout layout = (PatternLayout) testFile("config-1.2/log4j-file-SimpleLayout");
+        assertEquals("%level - %m%n", layout.getConversionPattern());
+    }
+
+    public void testNullAppender() throws Exception {
+        final Configuration configuration = getConfiguration("config-1.2/log4j-NullAppender");
+        final Appender appender = configuration.getAppender("NullAppender");
+        assertNotNull(appender);
+        assertEquals("NullAppender", appender.getName());
+        assertTrue(appender.getClass().getName(), appender instanceof NullAppender);
+    }
+
 }
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 f40cf7e..a1a3bba 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
@@ -34,7 +34,6 @@ import org.apache.logging.log4j.core.appender.FileAppender;
 import org.apache.logging.log4j.core.appender.NullAppender;
 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.junit.Test;
 
@@ -66,43 +65,27 @@ public class Log4j1ConfigurationFactoryTest extends AbstractLog4j1ConfigurationT
         return appender.getLayout();
     }
 
-    private Layout<?> testFile(final String configResource) throws Exception {
-        final Configuration configuration = getConfiguration(configResource);
-        final FileAppender appender = configuration.getAppender("File");
-        assertNotNull(appender);
-        assertEquals("target/mylog.txt", appender.getFileName());
-        //
-        final LoggerConfig loggerConfig = configuration.getLoggerConfig("com.example.foo");
-        assertNotNull(loggerConfig);
-        assertEquals(Level.DEBUG, loggerConfig.getLevel());
-        configuration.start();
-        configuration.stop();
-        return appender.getLayout();
-    }
-
+    @Override
     @Test
     public void testConsoleEnhancedPatternLayout() throws Exception {
-        final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-EnhancedPatternLayout");
-        assertEquals("%d{ISO8601} [%t][%c] %-5p %properties %ndc: %m%n", layout.getConversionPattern());
+        super.testConsoleEnhancedPatternLayout();
     }
 
+    @Override
     @Test
     public void testConsoleHtmlLayout() throws Exception {
-        final HtmlLayout layout = (HtmlLayout) testConsole("config-1.2/log4j-console-HtmlLayout");
-        assertEquals("Headline", layout.getTitle());
-        assertTrue(layout.isLocationInfo());
+        super.testConsoleHtmlLayout();
     }
 
     @Test
     public void testConsolePatternLayout() throws Exception {
-        final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-PatternLayout");
-        assertEquals("%d{ISO8601} [%t][%c] %-5p: %m%n", layout.getConversionPattern());
+        super.testConsolePatternLayout();
     }
 
+    @Override
     @Test
     public void testConsoleSimpleLayout() throws Exception {
-        final PatternLayout layout = (PatternLayout) testConsole("config-1.2/log4j-console-SimpleLayout");
-        assertEquals("%level - %m%n", layout.getConversionPattern());
+        super.testConsoleSimpleLayout();
     }
 
     @Override
@@ -118,20 +101,17 @@ public class Log4j1ConfigurationFactoryTest extends AbstractLog4j1ConfigurationT
         assertFalse(layout.isProperties());
     }
 
+    @Override
     @Test
     public void testFileSimpleLayout() throws Exception {
-        final PatternLayout layout = (PatternLayout) testFile("config-1.2/log4j-file-SimpleLayout");
-        assertEquals("%level - %m%n", layout.getConversionPattern());
+        super.testFileSimpleLayout();
     }
 
+    @Override
     @Test
-    public void testNullAppender() throws Exception {
-        final Configuration configuration = getConfiguration("config-1.2/log4j-NullAppender");
-        final Appender appender = configuration.getAppender("NullAppender");
-        assertNotNull(appender);
-        assertEquals("NullAppender", appender.getName());
-        assertTrue(appender.getClass().getName(), appender instanceof NullAppender);
-    }
+	public void testNullAppender() throws Exception {
+        super.testNullAppender();
+	}
 
     @Override
     @Test
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java
index 51f04f1..18f9324 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java
@@ -184,6 +184,42 @@ public class PropertiesConfigurationTest extends AbstractLog4j1ConfigurationTest
 
     @Override
     @Test
+    public void testConsoleEnhancedPatternLayout() throws Exception {
+        super.testConsoleEnhancedPatternLayout();
+    }
+
+    @Override
+    @Test
+    public void testConsoleHtmlLayout() throws Exception {
+        super.testConsoleHtmlLayout();
+    }
+
+    @Override
+    @Test
+    public void testConsolePatternLayout() throws Exception {
+        super.testConsolePatternLayout();
+    }
+
+    @Override
+    @Test
+    public void testConsoleSimpleLayout() throws Exception {
+        super.testConsoleSimpleLayout();
+    }
+
+    @Override
+    @Test
+    public void testFileSimpleLayout() throws Exception {
+        super.testFileSimpleLayout();
+    }
+
+    @Override
+    @Test
+    public void testNullAppender() throws Exception {
+        super.testNullAppender();
+    }
+
+    @Override
+    @Test
     public void testConsoleCapitalization() throws Exception {
         super.testConsoleCapitalization();
     }
diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
index a410ca5..3d0f470 100644
--- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java
@@ -111,6 +111,42 @@ public class XmlConfigurationTest extends AbstractLog4j1ConfigurationTest {
 
     @Override
     @Test
+    public void testConsoleEnhancedPatternLayout() throws Exception {
+        super.testConsoleEnhancedPatternLayout();
+    }
+
+    @Override
+    @Test
+    public void testConsoleHtmlLayout() throws Exception {
+        super.testConsoleHtmlLayout();
+    }
+
+    @Override
+    @Test
+    public void testConsolePatternLayout() throws Exception {
+        super.testConsolePatternLayout();
+    }
+
+    @Override
+    @Test
+    public void testConsoleSimpleLayout() throws Exception {
+        super.testConsoleSimpleLayout();
+    }
+
+    @Override
+    @Test
+    public void testFileSimpleLayout() throws Exception {
+        super.testFileSimpleLayout();
+    }
+
+    @Override
+    @Test
+    public void testNullAppender() throws Exception {
+        super.testNullAppender();
+    }
+
+    @Override
+    @Test
     public void testConsoleCapitalization() throws Exception {
         super.testConsoleCapitalization();
     }
diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-NullAppender.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-NullAppender.xml
new file mode 100644
index 0000000..7153cab
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-NullAppender.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="NullAppender" class="org.apache.log4j.varia.NullAppender" />
+
+  <root>
+    <priority value="trace" />
+    <appender-ref ref="NullAppender" />
+  </root>
+</log4j:configuration>
diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-EnhancedPatternLayout.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-EnhancedPatternLayout.xml
new file mode 100644
index 0000000..aab4074
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-EnhancedPatternLayout.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="Console" class="org.apache.log4j.ConsoleAppender">
+    <param name="Target" value="System.err" />
+    <layout class="org.apache.log4j.EnhancedPatternLayout">
+      <param name="ConversionPattern" value="%d{ISO8601} [%t][%c] %-5p %X %x: %m%n" />
+    </layout>
+  </appender>
+
+  <logger name="com.example.foo">
+    <level value="DEBUG" />
+  </logger>
+
+  <root>
+    <priority value="trace" />
+    <appender-ref ref="Console" />
+  </root>
+</log4j:configuration>
diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-HtmlLayout.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-HtmlLayout.xml
new file mode 100644
index 0000000..6c2ae53
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-HtmlLayout.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="Console" class="org.apache.log4j.ConsoleAppender">
+    <param name="Target" value="System.err" />
+    <layout class="org.apache.log4j.HTMLLayout">
+      <param name="Title" value="Headline" />
+      <param name="LocationInfo" value="true" />
+    </layout>
+  </appender>
+
+  <logger name="com.example.foo">
+    <level value="DEBUG" />
+  </logger>
+
+  <root>
+    <priority value="trace" />
+    <appender-ref ref="Console" />
+  </root>
+</log4j:configuration>
diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-PatternLayout.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-PatternLayout.xml
new file mode 100644
index 0000000..cbe264a
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-PatternLayout.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="Console" class="org.apache.log4j.ConsoleAppender">
+    <param name="Target" value="System.err" />
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%d{ISO8601} [%t][%c] %-5p: %m%n" />
+    </layout>
+  </appender>
+
+  <logger name="com.example.foo">
+    <level value="DEBUG" />
+  </logger>
+
+  <root>
+    <priority value="trace" />
+    <appender-ref ref="Console" />
+  </root>
+</log4j:configuration>
diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-SimpleLayout.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-SimpleLayout.xml
new file mode 100644
index 0000000..b38d8f5
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-console-SimpleLayout.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="Console" class="org.apache.log4j.ConsoleAppender">
+    <param name="Target" value="System.err" />
+    <layout class="org.apache.log4j.SimpleLayout" />
+  </appender>
+
+  <logger name="com.example.foo">
+    <level value="DEBUG" />
+  </logger>
+
+  <root>
+    <priority value="trace" />
+    <appender-ref ref="Console" />
+  </root>
+</log4j:configuration>
diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-file-SimpleLayout.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-file-SimpleLayout.xml
new file mode 100644
index 0000000..37016f1
--- /dev/null
+++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-file-SimpleLayout.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="File" class="org.apache.log4j.FileAppender">
+    <param name="File" value="target/mylog.txt" />
+    <layout class="org.apache.log4j.SimpleLayout" />
+  </appender>
+
+  <logger name="com.example.foo">
+    <level value="DEBUG" />
+  </logger>
+
+  <root>
+    <priority value="trace" />
+    <appender-ref ref="File" />
+  </root>
+</log4j:configuration>