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">