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


The following commit(s) were added to refs/heads/master by this push:
     new 0a09ed8  [LOG4J2-3316] Log4j 1.2 bridge should ignore case in 
properties file keys. Messy cherry-pick + port from release 2.x.
0a09ed8 is described below

commit 0a09ed8026eced56c3bb70eae9ab645162905ce2
Author: Gary Gregory <[email protected]>
AuthorDate: Tue Jan 4 17:13:38 2022 -0500

    [LOG4J2-3316] Log4j 1.2 bridge should ignore case in properties file keys. 
Messy cherry-pick + port from release 2.x.
---
 log4j-1.2-api/pom.xml                              |   6 +
 .../org/apache/log4j/builders/AbstractBuilder.java |  45 +++++---
 .../log4j/config/PropertiesConfiguration.java      |   3 +-
 .../config/PropertiesConfigurationFactory.java     |   3 +-
 .../apache/log4j/xml/XmlConfigurationFactory.java  |   5 +-
 .../log4j/config/PropertiesConfigurationTest.java  | 122 +++++++++++----------
 .../org/apache/log4j/config/TestConfigurator.java  |  55 ++++++++++
 .../log4j-FileAppender-with-props.properties       |  20 ++++
 src/changes/changes.xml                            |   3 +
 9 files changed, 184 insertions(+), 78 deletions(-)

diff --git a/log4j-1.2-api/pom.xml b/log4j-1.2-api/pom.xml
index 3df0832..30914e4 100644
--- a/log4j-1.2-api/pom.xml
+++ b/log4j-1.2-api/pom.xml
@@ -44,6 +44,12 @@
       <artifactId>junit-jupiter-engine</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!-- Place Felix before Equinox because Felix is signed. -->
+    <dependency>
       <groupId>org.hamcrest</groupId>
       <artifactId>hamcrest</artifactId>
       <scope>test</scope>
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 11e4fd4..91b5e38 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
@@ -16,6 +16,13 @@
  */
 package org.apache.log4j.builders;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
 import org.apache.log4j.bridge.FilterAdapter;
 import org.apache.log4j.bridge.FilterWrapper;
 import org.apache.log4j.helpers.OptionConverter;
@@ -27,12 +34,6 @@ import org.apache.logging.log4j.core.filter.ThresholdFilter;
 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
 import org.apache.logging.log4j.status.StatusLogger;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
 /**
  * Base class for Log4j 1 component builders.
  */
@@ -48,39 +49,46 @@ public abstract class AbstractBuilder {
     protected static final String RELATIVE = "RELATIVE";
 
     private final String prefix;
-    private final Properties props;
+    private final Properties properties;
     private final StrSubstitutor strSubstitutor;
 
     public AbstractBuilder() {
         this.prefix = null;
-        this.props = new Properties();
-        strSubstitutor = new StrSubstitutor(System.getProperties());
+        this.strSubstitutor = new StrSubstitutor(System.getProperties());
+        this.properties = new Properties();
     }
 
     public AbstractBuilder(String prefix, Properties props) {
         this.prefix = prefix + ".";
-        this.props = props;
+        this.properties = (Properties) props.clone();
         Map<String, String> map = new HashMap<>();
         System.getProperties().forEach((k, v) -> map.put(k.toString(), 
v.toString()));
         props.forEach((k, v) -> map.put(k.toString(), v.toString()));
-        strSubstitutor = new StrSubstitutor(map);
+        // normalize keys to lower case for case-insensitive access.
+        props.forEach((k, v) -> map.put(toLowerCase(k.toString()), 
v.toString()));
+        props.entrySet().forEach(e -> 
this.properties.put(toLowerCase(e.getKey().toString()), e.getValue()));
+        this.strSubstitutor = new StrSubstitutor(map);
     }
 
     public String getProperty(String key) {
-        return strSubstitutor.replace(props.getProperty(prefix + key));
+        return getProperty(key, null);
     }
 
     public String getProperty(String key, String defaultValue) {
-        return strSubstitutor.replace(props.getProperty(prefix + key, 
defaultValue));
+        String fullKey = prefix + key;
+        String value = properties.getProperty(fullKey);
+        value = value != null ? value : 
properties.getProperty(toLowerCase(fullKey), defaultValue);
+        return strSubstitutor.replace(value);
     }
 
     public boolean getBooleanProperty(String key) {
-        return 
Boolean.parseBoolean(strSubstitutor.replace(props.getProperty(prefix + key, 
Boolean.FALSE.toString())));
+        return Boolean.parseBoolean(getProperty(key, 
Boolean.FALSE.toString()));
     }
 
     public int getIntegerProperty(String key, int defaultValue) {
-        String value = getProperty(key);
+        String value = null;
         try {
+            value = getProperty(key);
             if (value != null) {
                 return Integer.parseInt(value);
             }
@@ -91,7 +99,7 @@ public abstract class AbstractBuilder {
     }
 
     public Properties getProperties() {
-        return props;
+        return properties;
     }
 
 
@@ -126,4 +134,9 @@ public abstract class AbstractBuilder {
         }
         return null;
     }
+
+    String toLowerCase(final String value) {
+        return value == null ? null : value.toLowerCase(Locale.ROOT);
+    }
+
 }
diff --git 
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
 
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
index 876da0c..7a1fee4 100644
--- 
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
+++ 
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java
@@ -80,7 +80,7 @@ public class PropertiesConfiguration  extends 
Log4j1Configuration {
 
     private static final String INTERNAL_ROOT_NAME = "root";
 
-    private final Map<String, Appender> registry;
+    private final Map<String, Appender> registry = new HashMap<>();
 
     /**
      * Constructor.
@@ -91,7 +91,6 @@ public class PropertiesConfiguration  extends 
Log4j1Configuration {
     public PropertiesConfiguration(final LoggerContext loggerContext, final 
ConfigurationSource source,
             int monitorIntervalSeconds) {
         super(loggerContext, source, monitorIntervalSeconds);
-        registry = new HashMap<>();
     }
 
     @Override
diff --git 
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.java
 
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.java
index 465eaa1..f6ebd12 100644
--- 
a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.java
+++ 
b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.java
@@ -32,6 +32,7 @@ import org.apache.logging.log4j.util.PropertiesUtil;
 @Order(2)
 public class PropertiesConfigurationFactory extends ConfigurationFactory {
 
+    static final String FILE_EXTENSION = ".properties";
 
     /**
      * File name prefix for test configurations.
@@ -48,7 +49,7 @@ public class PropertiesConfigurationFactory extends 
ConfigurationFactory {
         if 
(!PropertiesUtil.getProperties().getBooleanProperty(ConfigurationFactory.LOG4J1_EXPERIMENTAL,
 Boolean.FALSE)) {
             return null;
         }
-        return new String[] {".properties"};
+        return new String[] { FILE_EXTENSION };
     }
 
     @Override
diff --git 
a/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.java 
b/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.java
index 04b596e..d0028a4 100644
--- 
a/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.java
+++ 
b/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.java
@@ -33,6 +33,9 @@ import org.apache.logging.log4j.util.PropertiesUtil;
 @Plugin(name = "Log4j1XmlConfigurationFactory", category = 
ConfigurationFactory.CATEGORY)
 @Order(2)
 public class XmlConfigurationFactory extends ConfigurationFactory {
+
+    public static final String FILE_EXTENSION = ".xml";
+
     private static final org.apache.logging.log4j.Logger LOGGER = 
StatusLogger.getLogger();
 
     /**
@@ -50,7 +53,7 @@ public class XmlConfigurationFactory extends 
ConfigurationFactory {
         if 
(!PropertiesUtil.getProperties().getBooleanProperty(ConfigurationFactory.LOG4J1_EXPERIMENTAL,
 Boolean.FALSE)) {
             return null;
         }
-        return new String[] {".xml"};
+        return new String[] { FILE_EXTENSION };
     }
 
     @Override
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 ede1b32..5ae781a 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
@@ -16,15 +16,15 @@
  */
 package org.apache.log4j.config;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.lang3.SystemUtils;
 import org.apache.log4j.ListAppender;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
@@ -33,9 +33,8 @@ import org.apache.log4j.bridge.FilterAdapter;
 import org.apache.log4j.spi.LoggingEvent;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.FileAppender;
 import org.apache.logging.log4j.core.config.Configuration;
-import org.apache.logging.log4j.core.config.ConfigurationSource;
-import org.apache.logging.log4j.core.config.Configurator;
 import org.apache.logging.log4j.core.filter.Filterable;
 import org.junit.Test;
 
@@ -45,39 +44,26 @@ import org.junit.Test;
 public class PropertiesConfigurationTest {
 
     @Test
-    public void testProperties() throws Exception {
-        configure("target/test-classes/log4j1-file.properties");
-        Logger logger = LogManager.getLogger("test");
-        logger.debug("This is a test of the root logger");
-        File file = new File("target/temp.A1");
-        assertTrue("File A1 was not created", file.exists());
-        assertTrue("File A1 is empty", file.length() > 0);
-        file = new File("target/temp.A2");
-        assertTrue("File A2 was not created", file.exists());
-        assertTrue("File A2 is empty", file.length() > 0);
-    }
-
-    @Test
     public void testConfigureNullPointerException() throws Exception {
-        try (LoggerContext loggerContext = 
configure("target/test-classes/LOG4J2-3247.properties")) {
+        try (LoggerContext loggerContext = 
TestConfigurator.configure("target/test-classes/LOG4J2-3247.properties")) {
             // [LOG4J2-3247] configure() should not throw an NPE.
-            Configuration configuration = loggerContext.getConfiguration();
+            final Configuration configuration = 
loggerContext.getConfiguration();
             assertNotNull(configuration);
-            Appender appender = configuration.getAppender("CONSOLE");
+            final Appender appender = configuration.getAppender("CONSOLE");
             assertNotNull(appender);
         }
     }
 
     @Test
     public void testConsoleAppenderFilter() throws Exception {
-        try (LoggerContext loggerContext = 
configure("target/test-classes/LOG4J2-3247.properties")) {
+        try (LoggerContext loggerContext = 
TestConfigurator.configure("target/test-classes/LOG4J2-3247.properties")) {
             // LOG4J2-3281 PropertiesConfiguration.buildAppender not adding 
filters to appender
-            Configuration configuration = loggerContext.getConfiguration();
+            final Configuration configuration = 
loggerContext.getConfiguration();
             assertNotNull(configuration);
-            Appender appender = configuration.getAppender("CONSOLE");
+            final Appender appender = configuration.getAppender("CONSOLE");
             assertNotNull(appender);
-            Filterable filterable = (Filterable) appender;
-            FilterAdapter filter = (FilterAdapter) filterable.getFilter();
+            final Filterable filterable = (Filterable) appender;
+            final FilterAdapter filter = (FilterAdapter) 
filterable.getFilter();
             assertNotNull(filter);
             assertTrue(filter.getFilter() instanceof NeutralFilterFixture);
         }
@@ -85,14 +71,14 @@ public class PropertiesConfigurationTest {
 
     @Test
     public void testCustomAppenderFilter() throws Exception {
-        try (LoggerContext loggerContext = 
configure("target/test-classes/LOG4J2-3281.properties")) {
+        try (LoggerContext loggerContext = 
TestConfigurator.configure("target/test-classes/LOG4J2-3281.properties")) {
             // LOG4J2-3281 PropertiesConfiguration.buildAppender not adding 
filters to appender
-            Configuration configuration = loggerContext.getConfiguration();
+            final Configuration configuration = 
loggerContext.getConfiguration();
             assertNotNull(configuration);
-            Appender appender = configuration.getAppender("CUSTOM");
+            final Appender appender = configuration.getAppender("CUSTOM");
             assertNotNull(appender);
-            Filterable filterable = (Filterable) appender;
-            FilterAdapter filter = (FilterAdapter) filterable.getFilter();
+            final Filterable filterable = (Filterable) appender;
+            final FilterAdapter filter = (FilterAdapter) 
filterable.getFilter();
             assertNotNull(filter);
             assertTrue(filter.getFilter() instanceof NeutralFilterFixture);
         }
@@ -100,37 +86,57 @@ public class PropertiesConfigurationTest {
 
     @Test
     public void testListAppender() throws Exception {
-        LoggerContext loggerContext = 
configure("target/test-classes/log4j1-list.properties");
-        Logger logger = LogManager.getLogger("test");
-        logger.debug("This is a test of the root logger");
-        Configuration configuration = loggerContext.getConfiguration();
-        Map<String, Appender> appenders = configuration.getAppenders();
-        ListAppender eventAppender = null;
-        ListAppender messageAppender = null;
-        for (Map.Entry<String, Appender> entry : appenders.entrySet()) {
-            if (entry.getKey().equals("list")) {
-                messageAppender = (ListAppender) ((AppenderAdapter.Adapter) 
entry.getValue()).getAppender();
-            } else if (entry.getKey().equals("events")) {
-                eventAppender = (ListAppender) ((AppenderAdapter.Adapter) 
entry.getValue()).getAppender();
+        try (LoggerContext loggerContext = 
TestConfigurator.configure("target/test-classes/log4j1-list.properties")) {
+            final Logger logger = LogManager.getLogger("test");
+            logger.debug("This is a test of the root logger");
+            final Configuration configuration = 
loggerContext.getConfiguration();
+            final Map<String, Appender> appenders = 
configuration.getAppenders();
+            ListAppender eventAppender = null;
+            ListAppender messageAppender = null;
+            for (final Map.Entry<String, Appender> entry : 
appenders.entrySet()) {
+                if (entry.getKey().equals("list")) {
+                    messageAppender = (ListAppender) 
((AppenderAdapter.Adapter) entry.getValue()).getAppender();
+                } else if (entry.getKey().equals("events")) {
+                    eventAppender = (ListAppender) ((AppenderAdapter.Adapter) 
entry.getValue()).getAppender();
+                }
             }
+            assertNotNull("No Event Appender", eventAppender);
+            assertNotNull("No Message Appender", messageAppender);
+            final List<LoggingEvent> events = eventAppender.getEvents();
+            assertTrue("No events", events != null && events.size() > 0);
+            final List<String> messages = messageAppender.getMessages();
+            assertTrue("No messages", messages != null && messages.size() > 0);
+        }
+    }
+
+    @Test
+    public void testProperties() throws Exception {
+        try (LoggerContext loggerContext = 
TestConfigurator.configure("target/test-classes/log4j1-file.properties")) {
+            final Logger logger = LogManager.getLogger("test");
+            logger.debug("This is a test of the root logger");
+            File file = new File("target/temp.A1");
+            assertTrue("File A1 was not created", file.exists());
+            assertTrue("File A1 is empty", file.length() > 0);
+            file = new File("target/temp.A2");
+            assertTrue("File A2 was not created", file.exists());
+            assertTrue("File A2 is empty", file.length() > 0);
         }
-        assertNotNull("No Event Appender", eventAppender);
-        assertNotNull("No Message Appender", messageAppender);
-        List<LoggingEvent> events = eventAppender.getEvents();
-        assertTrue("No events", events != null && events.size() > 0);
-        List<String> messages = messageAppender.getMessages();
-        assertTrue("No messages", messages != null && messages.size() > 0);
     }
 
-    private LoggerContext configure(String configLocation) throws Exception {
-        File file = new File(configLocation);
-        InputStream is = new FileInputStream(file);
-        ConfigurationSource source = new ConfigurationSource(is, file);
-        LoggerContext context = (LoggerContext) 
org.apache.logging.log4j.LogManager.getContext(false);
-        Configuration configuration = new 
PropertiesConfigurationFactory().getConfiguration(context, source);
-        assertNotNull("No configuration created", configuration);
-        Configurator.reconfigure(configuration);
-        return context;
+    @Test
+    public void testSystemProperties() throws Exception {
+        try (LoggerContext loggerContext = 
TestConfigurator.configure("target/test-classes/config-1.2/log4j-FileAppender-with-props.properties"))
 {
+            // [LOG4J2-3312] Bridge does not convert properties.
+            final Configuration configuration = 
loggerContext.getConfiguration();
+            assertNotNull(configuration);
+            final String name = "FILE_APPENDER";
+            final Appender appender = configuration.getAppender(name);
+            assertNotNull(name, appender);
+            assertTrue(appender instanceof FileAppender);
+            final FileAppender fileAppender = (FileAppender) appender;
+            // Two slashes because that's how the config file is setup.
+            assertEquals(SystemUtils.getJavaIoTmpDir() + "//hadoop.log", 
fileAppender.getFileName());
+        }
     }
 
-}
+}
\ No newline at end of file
diff --git 
a/log4j-1.2-api/src/test/java/org/apache/log4j/config/TestConfigurator.java 
b/log4j-1.2-api/src/test/java/org/apache/log4j/config/TestConfigurator.java
new file mode 100644
index 0000000..7cd39af
--- /dev/null
+++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/TestConfigurator.java
@@ -0,0 +1,55 @@
+/*
+ * 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.config;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.apache.log4j.xml.XmlConfigurationFactory;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.Configurator;
+
+public class TestConfigurator {
+
+    @SuppressWarnings("resource")
+    static LoggerContext configure(String configLocation) throws IOException {
+        File file = new File(configLocation);
+        InputStream is = Files.newInputStream(Paths.get(configLocation));
+        ConfigurationSource source = new ConfigurationSource(is, file);
+        LoggerContext context = (LoggerContext) 
org.apache.logging.log4j.LogManager.getContext(false);
+        Configuration configuration = null;
+        if 
(configLocation.endsWith(PropertiesConfigurationFactory.FILE_EXTENSION)) {
+            configuration = new 
PropertiesConfigurationFactory().getConfiguration(context, source);
+        } else if 
(configLocation.endsWith(XmlConfigurationFactory.FILE_EXTENSION)) {
+            configuration = new 
XmlConfigurationFactory().getConfiguration(context, source);
+        } else {
+            fail("Test infra does not support " + configLocation);
+        }
+        assertNotNull("No configuration created", configuration);
+        Configurator.reconfigure(configuration);
+        return context;
+    }
+
+}
diff --git 
a/log4j-1.2-api/src/test/resources/config-1.2/log4j-FileAppender-with-props.properties
 
b/log4j-1.2-api/src/test/resources/config-1.2/log4j-FileAppender-with-props.properties
new file mode 100644
index 0000000..b98c194
--- /dev/null
+++ 
b/log4j-1.2-api/src/test/resources/config-1.2/log4j-FileAppender-with-props.properties
@@ -0,0 +1,20 @@
+###############################################################################
+#
+# Log4J 1.2 Configuration.
+#
+
+hadoop.log.file=hadoop.log
+
+log4j.rootLogger=TRACE, FILE_APPENDER
+
+#
+# Rolling File Appender
+#
+hadoop.log.maxfilesize=256MB
+hadoop.log.maxbackupindex=20
+log4j.appender.FILE_APPENDER=org.apache.log4j.FileAppender
+log4j.appender.FILE_APPENDER.file=${java.io.tmpdir}/${hadoop.log.file}
+log4j.appender.FILE_APPENDER.layout=org.apache.log4j.PatternLayout
+
+# Pattern format: Date LogLevel LoggerName LogMessage
+log4j.appender.FILE_APPENDER.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8647319..bfb990b 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -221,6 +221,9 @@
       <action dev="ggregory" type="fix">
         Log4j 1.2 bridge missing class org.apache.log4j.or.RendererMap.
       </action>
+      <action dev="ggregory" type="fix" issue="LOG4J2-3316">
+       Log4j 1.2 bridge should ignore case in properties file keys.
+      </action>
     </release>
     <release version="2.17.1" date="2021-MM-DD" description="GA Release 
2.17.1">
       <action issue="LOG4J2-3292" dev="ckozak" type="fix">

Reply via email to