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 2021/12/19 23:44:49 UTC

[logging-log4j2] branch release-2.12.x/LOG4J2-3242 created (now a70e238)

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

ggregory pushed a change to branch release-2.12.x/LOG4J2-3242
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git.


      at a70e238  [LOG4J2-3242] Rename JNDI enablement property from 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.

This branch includes the following new commits:

     new a70e238  [LOG4J2-3242] Rename JNDI enablement property from 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[logging-log4j2] 01/01: [LOG4J2-3242] Rename JNDI enablement property from 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch release-2.12.x/LOG4J2-3242
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit a70e2383caf70c2cb2fe827e6eb136109ed57c25
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Fri Dec 17 15:48:27 2021 -0500

    [LOG4J2-3242] Rename JNDI enablement property from 'log4j2.enableJndi'
    to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and
    'log4j2.enableJndiContextSelector'.
    
    Cherry-pick from branch release-2.x, resolve conflicts, and tweak.
---
 .../log4j/core/appender/AbstractManager.java       |   3 +-
 .../log4j/core/appender/mom/JmsManager.java        |  13 +-
 .../logging/log4j/core/lookup/Interpolator.java    |  13 +-
 .../logging/log4j/core/lookup/JndiLookup.java      |  52 +-
 .../apache/logging/log4j/core/net/JndiManager.java |  39 +-
 .../log4j/core/selector/JndiContextSelector.java   |   4 +-
 .../log4j/core/appender/mom/JmsAppenderTest.java   |   7 +-
 .../routing/RoutingAppenderWithJndiTest.java       | 125 ++++
 .../log4j/core/lookup/InterpolatorTest.java        |   2 +
 .../log4j/core/lookup/JndiDisabledLookupTest.java  |  38 ++
 .../logging/log4j/core/lookup/JndiLookupTest.java  |  42 +-
 .../core/lookup/JndiRestrictedLookupTest.java      |  43 ++
 .../logging/log4j/core/net/JndiManagerTest.java    |  98 +++
 .../apache/logging/log4j/test/JUnit5Bridge.java    |  35 ++
 src/changes/changes.xml                            | 693 +++++++++++++++++++++
 src/site/xdoc/manual/appenders.xml                 |   6 +
 src/site/xdoc/manual/configuration.xml.vm          |  53 ++
 17 files changed, 1235 insertions(+), 31 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
index e85871f..bf2c53a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.appender;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
@@ -110,7 +111,7 @@ public abstract class AbstractManager implements AutoCloseable {
             @SuppressWarnings("unchecked")
             M manager = (M) MAP.get(name);
             if (manager == null) {
-                manager = factory.createManager(name, data);
+                manager = Objects.requireNonNull(factory, "factory").createManager(name, data);
                 if (manager == null) {
                     throw new IllegalStateException("ManagerFactory [" + factory + "] unable to create manager for ["
                             + name + "] with data [" + data + "]");
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/JmsManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/JmsManager.java
index c9f105b..d2d397d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/JmsManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/mom/JmsManager.java
@@ -125,17 +125,16 @@ public class JmsManager extends AbstractManager {
 
         @Override
         public JmsManager createManager(final String name, final JmsManagerConfiguration data) {
-            if (JndiManager.isJndiEnabled()) {
+            if (JndiManager.isJndiJmsEnabled()) {
                 try {
                     return new JmsManager(name, data);
                 } catch (final Exception e) {
                     logger().error("Error creating JmsManager using JmsManagerConfiguration [{}]", data, e);
                     return null;
                 }
-            } else {
-                logger().error("Jndi has not been enabled. The log4j2.enableJndi property must be set to true");
-                return null;
             }
+            logger().error("JNDI must be enabled by setting log4j2.enableJndiJms=true");
+            return null;
         }
     }
 
@@ -354,7 +353,7 @@ public class JmsManager extends AbstractManager {
      * @param object
      *            The LogEvent or String message to wrap.
      * @return A new JMS message containing the provided object.
-     * @throws JMSException
+     * @throws JMSException if the JMS provider fails to create a message due to some internal error.
      */
     public Message createMessage(final Serializable object) throws JMSException {
         if (object instanceof String) {
@@ -375,7 +374,7 @@ public class JmsManager extends AbstractManager {
      * Creates a MessageConsumer on this Destination using the current Session.
      *
      * @return A MessageConsumer on this Destination.
-     * @throws JMSException
+     * @throws JMSException if the session fails to create a consumer due to some internal error.
      */
     public MessageConsumer createMessageConsumer() throws JMSException {
         return this.session.createConsumer(this.destination);
@@ -389,7 +388,7 @@ public class JmsManager extends AbstractManager {
      * @param destination
      *            The JMS Destination for the MessageProducer
      * @return A MessageProducer on this Destination.
-     * @throws JMSException
+     * @throws JMSException if the session fails to create a MessageProducer due to some internal error.
      */
     public MessageProducer createMessageProducer(final Session session, final Destination destination)
             throws JMSException {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
index c8409ab..3d8c07d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
@@ -26,6 +26,7 @@ import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.ConfigurationAware;
 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
+import org.apache.logging.log4j.core.net.JndiManager;
 import org.apache.logging.log4j.core.util.Loader;
 import org.apache.logging.log4j.core.util.ReflectionUtil;
 import org.apache.logging.log4j.status.StatusLogger;
@@ -73,7 +74,7 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
         for (final Map.Entry<String, PluginType<?>> entry : plugins.entrySet()) {
             try {
                 final Class<? extends StrLookup> clazz = entry.getValue().getPluginClass().asSubclass(StrLookup.class);
-                if (!clazz.getName().equals("org.apache.logging.log4j.core.lookup.JndiLookup")) {
+                if (!clazz.getName().equals("org.apache.logging.log4j.core.lookup.JndiLookup") || JndiManager.isJndiLookupEnabled()) {
                     strLookupMap.put(entry.getKey().toLowerCase(), ReflectionUtil.instantiate(clazz));
                 }
             } catch (final Throwable t) {
@@ -101,6 +102,16 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
         strLookupMap.put("main", MainMapLookup.MAIN_SINGLETON);
         strLookupMap.put("marker", new MarkerLookup());
         strLookupMap.put("java", new JavaLookup());
+        // JNDI
+        if (JndiManager.isJndiLookupEnabled()) {
+            try {
+                // [LOG4J2-703] We might be on Android
+                strLookupMap.put(LOOKUP_KEY_JNDI,
+                        Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JndiLookup", StrLookup.class));
+            } catch (final LinkageError | Exception e) {
+                handleError(LOOKUP_KEY_JNDI, e);
+            }
+        }
         // JMX input args
         try {
             // We might be on Android
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java
index bd19e54..a783ea4 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JndiLookup.java
@@ -16,9 +16,16 @@
  */
 package org.apache.logging.log4j.core.lookup;
 
+import java.util.Objects;
+
+import javax.naming.NamingException;
+
 import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.net.JndiManager;
 import org.apache.logging.log4j.status.StatusLogger;
 
 /**
@@ -26,17 +33,54 @@ import org.apache.logging.log4j.status.StatusLogger;
  */
 @Plugin(name = "jndi", category = StrLookup.CATEGORY)
 public class JndiLookup extends AbstractLookup {
+
     private static final Logger LOGGER = StatusLogger.getLogger();
-    private static final String RESULT = "JNDI is not supported";
+    private static final Marker LOOKUP = MarkerManager.getMarker("LOOKUP");
+
+    /** JNDI resource path prefix used in a J2EE container */
+    static final String CONTAINER_JNDI_RESOURCE_PATH_PREFIX = "java:comp/env/";
+
+    /**
+     * Constructs a new instance or throw IllegalStateException if this feature is disabled.
+     */
+    public JndiLookup() {
+        if (!JndiManager.isJndiLookupEnabled()) {
+            throw new IllegalStateException("JNDI must be enabled by setting log4j2.enableJndiLookup=true");
+        }
+    }
+
     /**
      * Looks up the value of the JNDI resource.
+     * 
      * @param event The current LogEvent (is ignored by this StrLookup).
-     * @param key  the JNDI resource name to be looked up, may be null
+     * @param key the JNDI resource name to be looked up, may be null
      * @return The String value of the JNDI resource.
      */
     @Override
     public String lookup(final LogEvent event, final String key) {
-        LOGGER.warn("Attempt to use JNDI Lookup");
-        return RESULT;
+        if (key == null) {
+            return null;
+        }
+        final String jndiName = convertJndiName(key);
+        try (final JndiManager jndiManager = JndiManager.getDefaultManager()) {
+            return Objects.toString(jndiManager.lookup(jndiName), null);
+        } catch (final NamingException e) {
+            LOGGER.warn(LOOKUP, "Error looking up JNDI resource [{}].", jndiName, e);
+            return null;
+        }
+    }
+
+    /**
+     * Convert the given JNDI name to the actual JNDI name to use. Default implementation applies the "java:comp/env/"
+     * prefix unless other scheme like "java:" is given.
+     * 
+     * @param jndiName The name of the resource.
+     * @return The fully qualified name to look up.
+     */
+    private String convertJndiName(final String jndiName) {
+        if (!jndiName.startsWith(CONTAINER_JNDI_RESOURCE_PATH_PREFIX) && jndiName.indexOf(':') == -1) {
+            return CONTAINER_JNDI_RESOURCE_PATH_PREFIX + jndiName;
+        }
+        return jndiName;
     }
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java
index 06e2793..e005c62 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/JndiManager.java
@@ -39,11 +39,29 @@ import org.apache.logging.log4j.util.PropertiesUtil;
 public class JndiManager extends AbstractManager {
 
     private static final JndiManagerFactory FACTORY = new JndiManagerFactory();
+    private static final String PREFIX = "log4j2.enableJndi";
+    private static final String JAVA_SCHEME = "java";
 
     private final Context context;
 
+    private static boolean isJndiEnabled(final String subKey) {
+        return PropertiesUtil.getProperties().getBooleanProperty(PREFIX + subKey, false);
+    }
+
     public static boolean isJndiEnabled() {
-        return PropertiesUtil.getProperties().getBooleanProperty("log4j2.enableJndi", false);
+        return isJndiContextSelectorEnabled() || isJndiJmsEnabled() || isJndiLookupEnabled();
+    }
+
+    public static boolean isJndiContextSelectorEnabled() {
+        return isJndiEnabled("ContextSelector");
+    }
+
+    public static boolean isJndiJmsEnabled() {
+        return isJndiEnabled("Jms");
+    }
+
+    public static boolean isJndiLookupEnabled() {
+        return isJndiEnabled("Lookup");
     }
 
     private JndiManager(final String name, final Context context) {
@@ -181,7 +199,7 @@ public class JndiManager extends AbstractManager {
         }
         try {
             URI uri = new URI(name);
-            if (uri.getScheme() == null || uri.getScheme().equals("java")) {
+            if (uri.getScheme() == null || uri.getScheme().equals(JAVA_SCHEME)) {
                 return (T) this.context.lookup(name);
             }
             LOGGER.warn("Unsupported JNDI URI - {}", name);
@@ -195,15 +213,14 @@ public class JndiManager extends AbstractManager {
 
         @Override
         public JndiManager createManager(final String name, final Properties data) {
-            if (isJndiEnabled()) {
-                try {
-                    return new JndiManager(name, new InitialContext(data));
-                } catch (final NamingException e) {
-                    LOGGER.error("Error creating JNDI InitialContext.", e);
-                    return null;
-                }
-            } else {
-                return new JndiManager(name, null);
+            if (!isJndiEnabled()) {
+                throw new IllegalStateException(String.format("JNDI must be enabled by setting one of the %s* properties to true", PREFIX));
+            }
+            try {
+                return new JndiManager(name, new InitialContext(data));
+            } catch (final NamingException e) {
+                LOGGER.error("Error creating JNDI InitialContext for '{}'.", name, e);
+                return null;
             }
         }
 
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/JndiContextSelector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/JndiContextSelector.java
index 81ec3f3..7da852d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/JndiContextSelector.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/selector/JndiContextSelector.java
@@ -93,8 +93,8 @@ public class JndiContextSelector implements NamedContextSelector {
     private static final StatusLogger LOGGER = StatusLogger.getLogger();
 
     public JndiContextSelector() {
-        if (!JndiManager.isJndiEnabled()) {
-            throw new IllegalStateException("JNDI must be enabled by setting log4j2.enableJndi=true");
+        if (!JndiManager.isJndiContextSelectorEnabled()) {
+            throw new IllegalStateException("JNDI must be enabled by setting log4j2.enableJndiContextSelector=true");
         }
     }
 
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/mom/JmsAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/mom/JmsAppenderTest.java
index daf2d0e..4c5b1a9 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/mom/JmsAppenderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/mom/JmsAppenderTest.java
@@ -85,8 +85,13 @@ public class JmsAppenderTest {
     public RuleChain rules = RuleChain.outerRule(jndiRule).around(ctx);
 
     @BeforeClass
+    public static void afterClass() throws Exception {
+        System.clearProperty("log4j2.enableJndiJms");
+    }
+
+    @BeforeClass
     public static void beforeClass() throws Exception {
-        System.setProperty("log4j2.enableJndi", "true");
+        System.setProperty("log4j2.enableJndiJms", "true");
     }
 
     public JmsAppenderTest() throws Exception {
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutingAppenderWithJndiTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutingAppenderWithJndiTest.java
new file mode 100644
index 0000000..899fd5e
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/routing/RoutingAppenderWithJndiTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.logging.log4j.core.appender.routing;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Map;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.apache.logging.log4j.EventLogger;
+import org.apache.logging.log4j.junit.JndiRule;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.message.StructuredDataMessage;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+
+import static org.junit.Assert.*;
+
+/**
+ * RoutingAppenderWithJndiTest
+ */
+public class RoutingAppenderWithJndiTest {
+
+    public static final String JNDI_CONTEXT_NAME = "java:comp/env/logging/context-name";
+    private ListAppender listAppender1;
+    private ListAppender listAppender2;
+
+    public static LoggerContextRule loggerContextRule = new LoggerContextRule("log4j-routing-by-jndi.xml");
+
+    @ClassRule
+    public static RuleChain rules = RuleChain.outerRule(new JndiRule(initBindings())).around(loggerContextRule);
+
+    private static Map<String, Object> initBindings() {
+        System.setProperty("log4j2.enableJndiLookup", "true");
+        //System.setProperty("log4j2.enableJndiJms", "true");
+        //System.setProperty("log4j2.enableJndiContextSelector", "true");
+        return Collections.emptyMap();
+    }
+
+    @Before
+    public void before() {
+        listAppender1 = RoutingAppenderWithJndiTest.loggerContextRule.getListAppender("List1");
+        listAppender2 = RoutingAppenderWithJndiTest.loggerContextRule.getListAppender("List2");
+    }
+
+    @After
+    public void after() {
+        if (listAppender1 != null) {
+            listAppender1.clear();
+        }
+        if (listAppender2 != null) {
+            listAppender2.clear();
+        }
+    }
+
+    @Test
+    public void routingTest() throws NamingException {
+        // default route when there's no jndi resource
+        StructuredDataMessage msg = new StructuredDataMessage("Test", "This is a message from unknown context", "Context");
+        EventLogger.logEvent(msg);
+        final File defaultLogFile = new File("target/routingbyjndi/routingbyjnditest-unknown.log");
+        assertTrue("The default log file was not created", defaultLogFile.exists());
+
+        // now set jndi resource to Application1
+        final Context context = new InitialContext();
+        context.bind(JNDI_CONTEXT_NAME, "Application1");
+
+        msg = new StructuredDataMessage("Test", "This is a message from Application1", "Context");
+        EventLogger.logEvent(msg);
+        assertNotNull("No events generated", listAppender1.getEvents());
+        assertTrue("Incorrect number of events. Expected 1, got " + listAppender1.getEvents().size(), listAppender1.getEvents().size() == 1);
+
+        // now set jndi resource to Application2
+        context.rebind(JNDI_CONTEXT_NAME, "Application2");
+
+        msg = new StructuredDataMessage("Test", "This is a message from Application2", "Context");
+        EventLogger.logEvent(msg);
+        assertNotNull("No events generated", listAppender2.getEvents());
+        assertTrue("Incorrect number of events. Expected 1, got " + listAppender2.getEvents().size(), listAppender2.getEvents().size() == 1);
+        assertTrue("Incorrect number of events. Expected 1, got " + listAppender1.getEvents().size(), listAppender1.getEvents().size() == 1);
+
+        msg = new StructuredDataMessage("Test", "This is another message from Application2", "Context");
+        EventLogger.logEvent(msg);
+        assertNotNull("No events generated", listAppender2.getEvents());
+        assertTrue("Incorrect number of events. Expected 2, got " + listAppender2.getEvents().size(), listAppender2.getEvents().size() == 2);
+        assertTrue("Incorrect number of events. Expected 1, got " + listAppender1.getEvents().size(), listAppender1.getEvents().size() == 1);
+
+        // now set jndi resource to Application3.
+        // The context name, 'Application3', will be used as log file name by the default route.
+        context.rebind("java:comp/env/logging/context-name", "Application3");
+        msg = new StructuredDataMessage("Test", "This is a message from Application3", "Context");
+        EventLogger.logEvent(msg);
+        final File application3LogFile = new File("target/routingbyjndi/routingbyjnditest-Application3.log");
+        assertTrue("The Application3 log file was not created", application3LogFile.exists());
+
+        // now set jndi resource to Application4
+        // The context name, 'Application4', will be used as log file name by the default route.
+        context.rebind("java:comp/env/logging/context-name", "Application4");
+        msg = new StructuredDataMessage("Test", "This is a message from Application4", "Context");
+        EventLogger.logEvent(msg);
+        final File application4LogFile = new File("target/routingbyjndi/routingbyjnditest-Application4.log");
+        assertTrue("The Application3 log file was not created", application4LogFile.exists());
+    }
+}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/InterpolatorTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/InterpolatorTest.java
index 0af36fd..fc6f3d8 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/InterpolatorTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/InterpolatorTest.java
@@ -44,12 +44,14 @@ public class InterpolatorTest {
         protected void before() throws Throwable {
             System.setProperty(TESTKEY, TESTVAL);
             System.setProperty(TESTKEY2, TESTVAL);
+            System.setProperty("log4j2.enableJndiLookup", "true");
         }
 
         @Override
         protected void after() {
             System.clearProperty(TESTKEY);
             System.clearProperty(TESTKEY2);
+            System.clearProperty("log4j2.enableJndiLookup");
         }
     });
 
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiDisabledLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiDisabledLookupTest.java
new file mode 100644
index 0000000..362a67d
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiDisabledLookupTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.logging.log4j.core.lookup;
+
+import org.apache.logging.log4j.test.JUnit5Bridge;
+import org.junit.Test;
+
+/**
+ * JndiDisabledLookupTest
+ *
+ * Verifies the Lookups are disabled without the log4j2.enableJndiLookup property set to true.
+ */
+public class JndiDisabledLookupTest {
+
+    @Test
+    public void testLookup() {
+        JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
+            @Override
+            public void run() {
+                new JndiLookup();
+            }
+        });
+    }
+}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java
index ba45808..d02364b 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiLookupTest.java
@@ -16,17 +16,20 @@
  */
 package org.apache.logging.log4j.core.lookup;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.logging.log4j.junit.JndiRule;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
-
 /**
  * JndiLookupTest
  */
@@ -42,8 +45,22 @@ public class JndiLookupTest {
     @Rule
     public JndiRule jndiRule = new JndiRule(createBindings());
 
+    @AfterClass
+    public static void afterClass() {
+        System.setProperty("log4j2.enableJndiLookup", "true");
+    }
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.clearProperty("log4j2.enableJndiLookup");
+    }
+
     private Map<String, Object> createBindings() {
-        return new HashMap<>();
+        final Map<String, Object> map = new HashMap<>();
+        map.put(JndiLookup.CONTAINER_JNDI_RESOURCE_PATH_PREFIX + TEST_CONTEXT_RESOURCE_NAME, TEST_CONTEXT_NAME);
+        map.put(JndiLookup.CONTAINER_JNDI_RESOURCE_PATH_PREFIX + TEST_INTEGRAL_NAME, TEST_INTEGRAL_VALUE);
+        map.put(JndiLookup.CONTAINER_JNDI_RESOURCE_PATH_PREFIX + TEST_STRINGS_NAME, TEST_STRINGS_COLLECTION);
+        return map;
     }
 
     @Test
@@ -51,6 +68,23 @@ public class JndiLookupTest {
         final StrLookup lookup = new JndiLookup();
 
         String contextName = lookup.lookup(TEST_CONTEXT_RESOURCE_NAME);
-        assertEquals("JNDI is not supported", contextName);
+        assertEquals(TEST_CONTEXT_NAME, contextName);
+
+        contextName = lookup.lookup(JndiLookup.CONTAINER_JNDI_RESOURCE_PATH_PREFIX + TEST_CONTEXT_RESOURCE_NAME);
+        assertEquals(TEST_CONTEXT_NAME, contextName);
+
+        final String nonExistingResource = lookup.lookup("logging/non-existing-resource");
+        assertNull(nonExistingResource);
+    }
+
+    @Test
+    public void testNonStringLookup() throws Exception {
+        // LOG4J2-1310
+        final StrLookup lookup = new JndiLookup();
+        final String integralValue = lookup.lookup(TEST_INTEGRAL_NAME);
+        assertEquals(String.valueOf(TEST_INTEGRAL_VALUE), integralValue);
+        final String collectionValue = lookup.lookup(TEST_STRINGS_NAME);
+        assertEquals(String.valueOf(TEST_STRINGS_COLLECTION), collectionValue);
     }
+
 }
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiRestrictedLookupTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiRestrictedLookupTest.java
new file mode 100644
index 0000000..e40cdb2
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/JndiRestrictedLookupTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.logging.log4j.core.lookup;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNull;
+
+/**
+ * JndiLookupTest
+ */
+public class JndiRestrictedLookupTest {
+
+    private static final String DOMAIN = "apache.org";
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty("log4j2.enableJndiLookup", "true");
+    }
+
+    @Test
+    public void testDnsLookup() throws Exception {
+        final StrLookup lookup = new JndiLookup();
+        String result = lookup.lookup("dns:/" + DOMAIN);
+        assertNull("DNS data returend", result);
+
+    }
+}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/JndiManagerTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/JndiManagerTest.java
new file mode 100644
index 0000000..e2fd8f7
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/JndiManagerTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.logging.log4j.core.net;
+
+import static org.junit.Assert.assertFalse;
+
+import java.util.Properties;
+
+import org.apache.logging.log4j.test.JUnit5Bridge;
+import org.junit.Test;
+
+/**
+ * Tests {@link JndiManager}.
+ */
+public class JndiManagerTest {
+
+    @Test
+    public void testIsJndiEnabled() {
+        assertFalse(JndiManager.isJndiEnabled());
+    }
+
+    @Test
+    public void testIsJndiContextSelectorEnabled() {
+        assertFalse(JndiManager.isJndiContextSelectorEnabled());
+    }
+
+    @Test
+    public void testIsJndiJmsEnabled() {
+        assertFalse(JndiManager.isJndiJmsEnabled());
+    }
+
+    @Test
+    public void testIsJndiLookupEnabled() {
+        assertFalse(JndiManager.isJndiLookupEnabled());
+    }
+
+    @Test
+    public void testNoInstanceByDefault() {
+        JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
+            @Override
+            public void run() {
+                JndiManager.getDefaultManager();
+            }
+        });
+        JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
+            @Override
+            public void run() {
+                JndiManager.getDefaultManager(null);
+            }
+        });
+        JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
+            @Override
+            public void run() {
+                JndiManager.getDefaultManager("A");
+            }
+        });
+        JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
+            @Override
+            public void run() {
+                JndiManager.getJndiManager(null);
+            }
+        });
+        JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
+            @Override
+            public void run() {
+                JndiManager.getJndiManager(new Properties());
+            }
+        });
+        JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
+            @Override
+            public void run() {
+                JndiManager.getJndiManager(null, null, null, null, null, null);
+            }
+        });
+        JUnit5Bridge.assertThrows(IllegalStateException.class, new Runnable() {
+            @Override
+            public void run() {
+                JndiManager.getJndiManager("A", "A", "A", "A", "A", new Properties());
+            }
+        });
+    }
+
+}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/test/JUnit5Bridge.java b/log4j-core/src/test/java/org/apache/logging/log4j/test/JUnit5Bridge.java
new file mode 100644
index 0000000..c331433
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/test/JUnit5Bridge.java
@@ -0,0 +1,35 @@
+/*
+ * 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.logging.log4j.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class JUnit5Bridge {
+
+    /** This branch is on Java 7 and uses JUnit 4, hence this hack. */
+    public static <T> void assertThrows(Class<T> expectedType, Runnable runnable) {
+        try {
+            runnable.run();
+            fail("Expected " + expectedType.getCanonicalName());
+        } catch (Throwable t) {
+            assertEquals(expectedType, t.getClass());
+        }
+    
+    }
+
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c060fee..e9355ce 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -29,9 +29,702 @@
          - "update" - Change
          - "remove" - Removed
     -->
+<<<<<<< log4j-2.12
     <release version="2.12.3" date="2021-12-dd" description="GA Release 2.12.3">
       <action issue="LOG4J2-3230" dev="ckozak" type="fix">
         Fix string substitution recursion.
+=======
+    <release version="2.17.0" date="2021-MM-dd" description="GA Release 2.17.0">
+      <action issue="LOG4J2-3242" dev="rgoers, ggregory" type="fix">
+        Limit JNDI to the java protocol only. JNDI will remain disabled by default. Rename JNDI enablement property from
+        'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.
+      </action>
+      <action issue="LOG4J2-3241" dev="rgoers" type="fix">
+        Do not declare log4j-api-java9 and log4j-core-java9 as dependencies as it causes problems with the
+        Maven enforcer plugin.
+      </action>
+      <action issue="LOG4J2-3247" dev="ggregory" type="fix">
+        PropertiesConfiguration.parseAppenderFilters NPE when parsing properties file filters.
+      </action>
+      <action issue="LOG4J2-3249" dev="ggregory" type="fix">
+        Log4j 1.2 bridge for Syslog Appender defaults to port 512 instead of 514.
+      </action>
+      <action issue="LOG4J2-3237" dev="ggregory" type="fix">
+        Log4j 1.2 bridge API hard codes the Syslog protocol to TCP.
+      </action>
+    </release>
+    <release version="2.16.0" date="2021-12-13" description="GA Release 2.16.0">
+      <action issue="LOG4J2-3208" dev="rgoers" type="fix">
+        Disable JNDI by default. Require log4j2.enableJndi to be set to true to allow JNDI.
+      </action>
+      <action issue="LOG4J2-3211" dev="rgoers" type="fix">
+        Completely remove support for Message Lookups.
+      </action>
+    </release>
+    <release version="2.15.0" date="2021-12-06" description="GA Release 2.15.0">
+      <!-- ADDS -->
+      <action issue="LOG4J2-3198" dev="ckozak" type="add">
+        Pattern layout no longer enables lookups within message text by default for cleaner API boundaries and reduced
+        formatting overhead. The old 'log4j2.formatMsgNoLookups' which enabled this behavior has been removed as well
+        as the 'nolookups' message pattern converter option. The old behavior can be enabled on a per-pattern basis
+        using '%m{lookups}'.
+      </action>
+      <action issue="LOG4J2-3194" dev="rgoers" type="add" due-to="markuss">
+        Allow fractional attributes for size attribute of SizeBsaedTriggeringPolicy.
+      </action>
+      <action issue="LOG4J2-2978" dev="rgoers" type="add" due-to="Michael Seele">
+        Add support for Jakarta EE 9 (Tomcat 10 / Jetty 11)
+      </action>
+      <action issue="LOG4J2-3189" dev="ckozak" type="add">
+        Improve NameAbbreviator worst-case performance.
+      </action>
+      <action issue="LOG4J2-3170" dev="vy" type="add" due-to="Gareth Smith">
+        Make CRLF/HTML encoding run in O(n) worst-case time, rather than O(n^2).
+      </action>
+      <action issue="LOG4J2-3133" dev="ckozak" type="add">
+        Add missing slf4j-api singleton accessors to log4j-slf4j-impl (1.7) StaticMarkerBinder and StaticMDCBinder.
+        This doesn't impact behavior or correctness, but avoids throwing and catching NoSuchMethodErrors when slf4j
+        is initialized and avoids linkage linting warnings.
+      </action>
+      <action issue="LOG4J2-2885" dev="vy" type="add" due-to="Markus Spann">
+        Add support for US-style date patterns and micro/nano seconds to FixedDateTime.
+      </action>
+      <action issue="LOG4J2-3116" dev="rgupta" type="add">
+        Add JsonTemplateLayout for Google Cloud Platform structured logging layout.
+      </action>
+      <action issue="LOG4J2-3067" dev="vy" type="add">
+        Add CounterResolver to JsonTemplateLayout.
+      </action>
+      <action issue="LOG4J2-3074" dev="vy" type="add">
+        Add replacement parameter to ReadOnlyStringMapResolver.
+      </action>
+      <action issue="LOG4J2-3051" dev="vy" type="add">
+        Add CaseConverterResolver to JsonTemplateLayout.
+      </action>
+      <action issue="LOG4J2-3064" dev="rgoers" type="add">
+        Add Arbiters and SpringProfile plugin.
+      </action>
+      <action issue="LOG4J2-3056" dev="vy" type="add" due-to="Marcono1234">
+        Refactor MD5 usage for sharing sensitive information.
+      </action>
+      <action issue="LOG4J2-3004" dev="vy" type="add">
+        Add plugin support to JsonTemplateLayout.
+      </action>
+      <action issue="LOG4J2-3050" dev="rgoers" type="add">
+        Allow AdditionalFields to be ignored if their value is null or a zero-length String.
+      </action>
+      <action issue="LOG4J2-3049" dev="rgoers" type="add">
+        Allow MapMessage and ThreadContext attributes to be prefixed.
+      </action>
+      <action issue="LOG4J2=3048" dev="rgoers" type="add">
+        Add improved MapMessge support to GelfLayout.
+      </action>
+      <action issue="LOG4J2-3044" dev="rgoers" type="add">
+        Add RepeatPatternConverter.
+      </action>
+      <action issue="LOG4J2-2940" dev="ckozak" type="add">
+        Context selectors are aware of their dependence upon the callers ClassLoader, allowing
+        basic context selectors to avoid the unnecessary overhead of walking the stack to
+        determine the caller's ClassLoader.
+      </action>
+      <action issue="LOG4J2-2940" dev="ckozak" type="add">
+        Add BasicAsyncLoggerContextSelector equivalent to AsyncLoggerContextSelector for
+        applications with a single LoggerContext. This selector avoids classloader lookup
+        overhead incurred by the existing AsyncLoggerContextSelector.
+      </action>
+      <action issue="LOG4J2-3041" dev="rgoers" type="add">
+        Allow a PatternSelector to be specified on GelfLayout.
+      </action>
+      <action issue="LOG4J2-3141" dev="ckozak" type="add">
+        Avoid ThreadLocal overhead in RandomAccessFileAppender, RollingRandomAccessFileManager,
+        and MemoryMappedFileManager due to the unused setEndOfBatch and isEndOfBatch methods.
+        The methods on LogEvent are preferred.
+      </action>
+      <action issue="LOG4J2-3144" dev="ckozak" type="add">
+        Prefer string.getBytes(Charset) over string.getBytes(String)
+	based on performance improvements in modern Java releases.
+      </action>
+      <action issue="LOG4J2-3171" dev="ckozak" type="add">
+        Improve PatternLayout performance by reducing unnecessary indirection and branching.
+      </action>
+      <!-- FIXES -->
+      <action issue="LOG4J2-3166" dev="rgoers">
+        Fix Log Event Level vs Logger Config Level table.
+      </action>
+      <action issue="LOG4J2-2540" dev="rgoers">
+        Minor documentation correctsion regarding log levels.
+      </action>
+      <action issue="LOG4J2-2541" dev="rgoers" due-to="Gerold Broser">
+        Minor documentation corrections in the configuration section.
+      </action>
+      <action issue="LOG4J2-2553" dev="rgoers">
+        Correct documentation for SyslogAppender when using TLS.
+      </action>
+      <action issue="LOG4J2-1798" dev="rgoers" due-to="Viacheslav Zhivaev">
+        Handle interrupted exceptions that occur during rollover.
+      </action>
+      <action issue="LOG4J2-2951" dev="rgoers">
+        Log4j 1.x properties were not being substituted.
+      </action>
+      <action issue="LOG4J2-3201" dev="rgoers" type="fix">
+        Limit the protocols JNDI can use by default. Limit the servers and classes that can be accessed via LDAP.
+      </action>
+      <action issue="LOG4J2-3114" dev="rgoers" type="fix" due-to="Barnabas Bodnar">
+        Enable immediate flush on RollingFileAppender when buffered i/o is not enabled.
+      </action>
+      <action issue="LOG4J2-3168" dev="rgoers" type="fix" due-to="Benjamin Wöster">
+       Fix bug when file names contain regex characters.
+      </action>
+      <action issue="LOG4J2-3110" dev="rgoers" type="fix" due-to="Arturo Bernal">
+        Fix the number of {}-placeholders in the string literal argument does not match the number of other arguments
+        to the logging call.
+      </action>
+      <action issue="LOG4J2-3060" dev="vy" type="fix" due-to=" Nikita Mikhailov">
+        Fix thread-safety issues in DefaultErrorHandler.
+      </action>
+      <action issue="LOG4J2-3185" dev="vy" type="fix" due-to="mzbonnt">
+        Fix thread-safety issues in DefaultErrorHandler.
+      </action>
+      <action issue="LOG4J2-3183" dev="vy" type="fix">
+        Avoid using MutableInstant of the event as a cache key in JsonTemplateLayout.
+      </action>
+      <action issue="LOG4J2-2829" dev="vy" type="fix">
+        SocketAppender should propagate failures when reconnection fails.
+      </action>
+      <action issue="LOG4J2-3172" dev="vy" type="fix" due-to="Barry Fleming">
+        Buffer immutable log events in the SmtpManager.
+      </action>
+      <action issue="LOG4J2-3175" dev="vy" type="fix" due-to="wuqian0808">
+        Avoid KafkaManager override when topics differ.
+      </action>
+      <action issue="LOG4J2-3160" dev="vy" type="fix" due-to="Lars Bohl">
+        Fix documentation on how to toggle log4j2.debug system property.
+      </action>
+      <action issue="LOG4J2-3159" dev="ckozak" type="fix">
+        Fixed an unlikely race condition in Log4jMarker.getParents() volatile access.
+      </action>
+      <action issue="LOG4J2-3153" dev="ckozak" type="fix">
+        DatePatternConverter performance is not impacted by microsecond-precision clocks when such precision isn't
+        required.
+      </action>
+      <action issue="LOG4J2-2808" dev="ckozak" type="fix" due-to="Asapha Halifa">
+        LoggerContext skips resolving localhost when hostName is configured.
+      </action>
+      <action issue="LOG4J2-3150" dev="ckozak" type="fix">
+        RandomAccessFile appender uses the correct default buffer size of 256 kB
+        rather than the default appender buffer size of 8 kB.
+      </action>
+      <action issue="LOG4J2-3142" dev="ckozak" type="fix" due-to="John Meikle">
+        log4j-1.2-api implements LogEventAdapter.getTimestamp() based on the original event timestamp
+        instead of returning zero.
+      </action>
+      <action issue="LOG4J2-3083" dev="ckozak" type="fix">
+        log4j-slf4j-impl and log4j-slf4j18-impl correctly detect the calling class using both LoggerFactory.getLogger
+        methods as well as LoggerFactory.getILoggerFactory().getLogger.
+      </action>
+      <action issue="LOG4J2-2816" dev="vy" type="fix" due-to="Jacob Shields">
+        Handle Disruptor event translation exceptions.
+      </action>
+      <action issue="LOG4J2-3121" dev="ggregory" type="fix" due-to="Markus Spann">
+          log4j2 config modified at run-time may trigger incomplete MBean re-initialization due to InstanceAlreadyExistsException.
+      </action>
+      <action issue="LOG4J2-3107" dev="vy" type="fix" due-to="Markus Spann">
+        SmtpManager.createManagerName ignores port.
+      </action>
+      <action issue="LOG4J2-3080" dev="vy" type="fix">
+        Use SimpleMessage in Log4j 1 Category whenever possible.
+      </action>
+      <action issue="LOG4J2-3102" dev="ckozak" type="fix">
+        Fix a regression in 2.14.1 which allowed the AsyncAppender background thread to keep the JVM alive because
+        the daemon flag was not set.
+      </action>
+      <action issue="LOG4J2-3103" dev="ckozak" type="fix" due-to="Mike Glazer">
+        Fix race condition which can result in ConcurrentModificationException on context.stop.
+      </action>
+      <action issue="LOG4J2-3092" dev="vy" type="fix" due-to="xmh51">
+        Fix JsonWriter memory leaks due to retained excessive buffer growth.
+      </action>
+      <action issue="LOG4J2-3089" dev="vy" type="fix" due-to="Tim Perry">
+        Fix sporadic JsonTemplateLayoutNullEventDelimiterTest failures on Windows.
+      </action>
+      <action issue="LOG4J2-3075" dev="vy" type="fix">
+        Fix formatting of nanoseconds in JsonTemplateLayout.
+      </action>
+      <action issue="LOG4J2-3087" dev="vy" type="fix" due-to="Anton Klarén">
+        Fix race in JsonTemplateLayout where a timestamp could end up unquoted.
+      </action>
+      <action issue="LOG4J2-3070" dev="vy" type="fix" due-to="Romain Manni-Bucau">
+        Ensure EncodingPatternConverter#handlesThrowable is implemented.
+      </action>
+      <action issue="LOG4J2-3054" dev="ckozak" type="fix">
+        BasicContextSelector hasContext and shutdown take the default context into account
+      </action>
+      <action issue="LOG4J2-2940" dev="ckozak" type="fix">
+        Slf4j implementations walk the stack at most once rather than twice to determine the caller's class loader.
+      </action>
+      <action issue="LOG4J2-2965" dev="ckozak" type="fix">
+        Fixed a deadlock between the AsyncLoggerContextSelector and java.util.logging.LogManager by updating Disruptor to 3.4.4.
+      </action>
+      <action issue="LOG4J2-3095" dev="ggregory" type="fix" due-to="Kenny MacLeod, Gary Gregory">
+        Category.setLevel should accept null value.
+      </action>
+      <action issue="LOG4J2-3174" dev="vy" type="fix" due-to="romainmoreau">
+        Wrong subject on mail when it depends on the LogEvent
+      </action>
+      <!-- UPDATES -->
+      <action dev="rgoers" issue="" type="update">
+        Update Spring framework to 5.3.13, Spring Boot to 2.5.7, and Spring Cloud to 2020.0.4.
+      </action>
+      <action issue="LOG4J2-2025" dev="rgoers" type="update">
+        Provide support for overriding the Tomcat Log class in Tomcat 8.5+.
+      </action>
+      <action dev="ggregory" issue="" type="update">
+        Updated dependencies.
+
+        - com.fasterxml.jackson.core:jackson-annotations ................. 2.12.2 -> 2.12.4
+        - com.fasterxml.jackson.core:jackson-core ........................ 2.12.2 -> 2.12.4
+        - com.fasterxml.jackson.core:jackson-databind .................... 2.12.2 -> 2.12.4
+        - com.fasterxml.jackson.dataformat:jackson-dataformat-xml ........ 2.12.2 -> 2.12.4
+        - com.fasterxml.jackson.dataformat:jackson-dataformat-yaml ....... 2.12.2 -> 2.12.4
+        - com.fasterxml.jackson.module:jackson-module-jaxb-annotations ... 2.12.2 -> 2.12.4
+        - com.fasterxml.woodstox:woodstox-core ........................... 6.2.4 -> 6.2.6
+        - commons-io:commons-io .......................................... 2.8.0 -> 2.11.0
+        - net.javacrumbs.json-unit:json-unit ............................. 2.24.0 -> 2.25.0
+        - net.javacrumbs.json-unit:json-unit ............................. 2.25.0 -> 2.27.0
+        - org.apache.activemq:activemq-broker ............................ 5.16.1 -> 5.16.2
+        - org.apache.activemq:activemq-broker ............................ 5.16.2 -> 5.16.3
+        - org.apache.commons:commons-compress ............................ 1.20 -> 1.21
+        - org.apache.commons:commons-csv ................................. 1.8 -> 1.9.0
+        - org.apache.commons:commons-dbcp2 ............................... 2.8.0 -> 2.9.0
+        - org.apache.commons:commons-pool2 ............................... 2.9.0 -> 2.11.1
+        - org.apache.maven.plugins:maven-failsafe-plugin ................. 2.22.2 -> 3.0.0-M5
+        - org.apache.maven.plugins:maven-surefire-plugin ................. 2.22.2 -> 3.0.0-M5
+        - org.apache.rat:apache-rat-plugin ............................... 0.12 -> 0.13
+        - org.assertj:assertj-core ....................................... 3.19.0 -> 3.20.2
+        - org.codehaus.groovy:groovy-dateutil ............................ 3.0.7 -> 3.0.8
+        - org.codehaus.groovy:groovy-jsr223 .............................. 3.0.7 -> 3.0.8
+        - org.codehaus.plexus:plexus-utils ............................... 3.3.0 -> 3.4.0
+        - org.eclipse.persistence:javax.persistence ...................... 2.1.1 -> 2.2.1
+        - org.eclipse.persistence:org.eclipse.persistence.jpa ............ 2.6.5 -> 2.6.9
+        - org.eclipse.persistence:org.eclipse.persistence.jpa ............ 2.7.8 -> 2.7.9
+        - org.fusesource.jansi ........................................... 2.3.2 -> 2.3.4
+        - org.fusesource.jansi:jansi ..................................... 2.3.1 -> 2.3.2
+        - org.hsqldb:hsqldb .............................................. 2.5.1 -> 2.5.2
+        - org.junit.jupiter:junit-jupiter-engine ......................... 5.7.1 -> 5.7.2
+        - org.junit.jupiter:junit-jupiter-migrationsupport ............... 5.7.1 -> 5.7.2
+        - org.junit.jupiter:junit-jupiter-params ......................... 5.7.1 -> 5.7.2
+        - org.junit.vintage:junit-vintage-engine ......................... 5.7.1 -> 5.7.2
+        - org.liquibase:liquibase-core ................................... 3.5.3 -> 3.5.5
+        - org.mockito:mockito-core ....................................... 3.8.0 -> 3.11.2
+        - org.mockito:mockito-junit-jupiter .............................. 3.8.0 -> 3.11.2
+        - org.springframework:spring-aop ................................. 5.3.3 -> 5.3.9
+        - org.springframework:spring-beans ............................... 5.3.3 -> 5.3.9
+        - org.springframework:spring-context ............................. 5.3.3 -> 5.3.9
+        - org.springframework:spring-context-support ..................... 5.3.3 -> 5.3.9
+        - org.springframework:spring-core ................................ 5.3.3 -> 5.3.9
+        - org.springframework:spring-expression .......................... 5.3.3 -> 5.3.9
+        - org.springframework:spring-oxm ................................. 5.3.3 -> 5.3.9
+        - org.springframework:spring-test ................................ 5.3.3 -> 5.3.9
+        - org.springframework:spring-web ................................. 5.3.3 -> 5.3.9
+        - org.springframework:spring-webmvc .............................. 5.3.3 -> 5.3.9
+        - org.tukaani:xz ................................................. 1.8 -> 1.9
+      </action>
+    </release>
+    <release version="2.14.1" date="2021-03-06" description="GA Release 2.14.1">
+      <!-- FIXES -->
+      <action issue="LOG4J2-3033" dev="rgoers" type="fix">
+        Add log method with no parameters - i.e. it has an empty message.
+      </action>
+      <action issue="LOG4J2-2947" dev="rgoers" type="fix">
+        Document that LogBuilder default methods do nothing.
+      </action>
+      <action issue="LOG4J2-2948" dev="vy" type="fix">
+        Replace HashSet with IdentityHashMap in ParameterFormatter to detect cycles.
+      </action>
+      <action issue="LOG4J2-3028" dev="ckozak" type="fix" due-to="Jakub Kozlowski">
+        OutputStreamManager.flushBuffer always resets the buffer, previously the buffer was not reset after an exception.
+      </action>
+      <action issue="LOG4J2-2981" dev="rgoers" type="fix">
+        OnStartupTriggeringPolicy would fail to cause the file to roll over with DirectWriteTriggeringPolicy
+        unless minSize was set to 0.
+      </action>
+      <action issue="LOG4J2-2990" dev="rgoers" type="fix" due-to="Diogo Monteiro">
+        Reduce garbage by using putAll when copying the ThreadContext for SLF4J.
+      </action>
+      <action issue="LOG4J2-3006" dev="rgoers" type="fix">
+        Directly create a thread instead of using the common ForkJoin pool when initializing ThreadContextDataInjector"
+      </action>
+      <action issue="LOG4J2-2624" dev="mattsicker" type="fix" due-to="Tim Perry">
+        Allow auto-shutdown of log4j in log4j-web to be turned off and provide a
+        ServletContextListener "Log4jShutdownOnContextDestroyedListener" to stop log4j.
+        Register the listener at the top of web.xml to ensure the shutdown happens last.
+      </action>
+      <action issue="LOG4J2-1606" dev="mattsicker" type="fix" due-to="Tim Perry">
+        Allow auto-shutdown of log4j in log4j-web to be turned off and provide a
+        ServletContextListener "Log4jShutdownOnContextDestroyedListener" to stop log4j.
+        Register the listener at the top of web.xml to ensure the shutdown happens last.
+      </action>
+      <action issue="LOG4J2-2998" dev="vy" type="fix">
+        Fix truncation of excessive strings ending with a high surrogate in JsonWriter.
+      </action>
+      <action issue="LOG4J2-2977" dev="vy" due-to="Ron Grabowski">
+        Replace outdated PatternLayout.createLayout() calls in docs with createDefaultLayout().
+      </action>
+      <action issue="LOG4J2-2973" dev="vy" type="fix" due-to="Fabio Ricchiuti">
+        Rename EventTemplateAdditionalField#type (conflicting with properties file parser) to "format".
+      </action>
+      <action issue="LOG4J2-2972" dev="vy" type="fix">
+        Refactor AsyncAppender and AppenderControl for handling of Throwables.
+      </action>
+      <action issue="LOG4J2-2985" dev="vy" type="fix">
+        Add eventTemplateRootObjectKey parameter to JsonTemplateLayout.
+      </action>
+      <action issue="LOG4J2-2974" dev="rgoers" type="fix">
+        Log4j would fail to initialize in Java 8 with log4j-spring-boot.
+      </action>
+      <action issue="LOG4J2-2964" dev="vy" type="fix" due-to="Valery Yatsynovich">
+        Merge packages from several Configurations in Composite Configuration.
+      </action>
+      <action issue="LOG4J2-2961" dev="vy" type="fix">
+        Fix reading of JsonTemplateLayout event additional fields from config.
+      </action>
+      <action issue="LOG4J2-2916" dev="vy" type="fix" due-to="wuqian0808">
+        Avoid redundant Kafka producer instantiation causing thread leaks.
+      </action>
+      <action issue="LOG4J2-2967" dev="ckozak" type="fix">
+        Fix JsonTemplateLayout index based parameter resolution when messages contain too few parameters.
+      </action>
+      <action issue="LOG4J2-2976" dev="ckozak" type="fix">
+        JdbcAppender composes an incorrect INSERT statement without a ColumnMapping element.
+      </action>
+      <action issue="LOG4J2-3014" dev="ggregory" type="fix" due-to="Lee Breisacher, Gary Gregory">
+        Log4j1ConfigurationConverter on Windows produces "&#xd;" at end of every line.
+      </action>
+      <action issue="LOG4J2-3131" dev="ggregory" type="fix" due-to="Adam Long, Gary Gregory">
+        Attempting to call getExtendedStackTraceAsString() after deserializing JSON LogEvent results in a NPE.
+      </action>
+      <action issue="LOG4J2-3131" dev="ggregory" type="fix" due-to="Gary Gregory">
+        NoGcLayout allocates empty bytes arrays for its header and footer.
+      </action>
+      <!-- ADDS -->
+      <action issue="LOG4J2-2962" dev="vy" type="add">
+        Enrich "map" resolver by unifying its backend with "mdc" resolver.
+      </action>
+      <action issue="LOG4J2-2999" dev="vy" type="add">
+        Replace JsonTemplateLayout resolver configurations table in docs with sections.
+      </action>
+      <action issue="LOG4J2-2993" dev="vy" type="add">
+        Support stack trace truncation in JsonTemplateLayout.
+      </action>
+      <!-- UPDATES -->
+      <action issue="LOG4J2-2923" dev="rgoers" type="update">
+        Add Rollover Listener to aid in unit test validation.
+      </action>
+      <action issue="LOG4J2-2893" dev="rgoers" type="update">
+        Allow reconfiguration when Log4j 1 configuration files are updated.
+      </action>
+      <action dev="rgoers" type="update">
+        Update Spring dependencies to 5.3.2, Spring Boot to 2.3.6, and Spring Cloud to Hoxton.SR9
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.fusesource.jansi:jansi 1.17.1 -> 2.0.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update commons-codec:commons-codec 1.14 -> 1.15.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.commons:commons-lang3 3.10 -> 3.11.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.commons:commons-pool2 2.8.1 -> 2.9.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.commons:commons-dbcp2 2.4.0 -> 2.8.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update commons-io:commons-io 2.7 -> 2.8.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.codehaus.groovy:* 3.0.5 -> 3.0.6.
+      </action>
+      <action dev="ggregory" type="update">
+        Update com.fasterxml.jackson.*:* 2.11.2 - 2.11.3.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.springframework:* 5.2.8.RELEASE -> 5.3.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update junit:junit 4.13 -> 4.13.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.xmlunit:* 2.7.0 -> 2.8.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.assertj:assertj-core 3.14.0 -> 3.18.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.awaitility:awaitility 4.0.2 -> 4.0.3.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.codehaus.plexus:plexus-utils 3.2.0 -> 3.3.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update MongoDB 3 plugin: org.mongodb:mongodb-driver 3.12.6 -> 3.12.7.
+      </action>
+      <action dev="ggregory" type="update">
+        Update MongoDB 4 plugin: org.mongodb:* 4.1.0 -> 4.1.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.eclipse.tycho:org.eclipse.osgi 3.12.1.v20170821-1548 -> 3.13.0.v20180226-1711.
+      </action>
+      <action dev="ggregory" type="update">
+        Update de.flapdoodle.embed:de.flapdoodle.embed.mongo 2.2.0 -> 3.0.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update net.javacrumbs.json-unit:json-unit 1.31.1 -> 2.22.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update Mockito 3.6.0 -> 3.7.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update XML Unit 2.8.0 -> 2.8.2.
+      </action>
+      <action dev="ggregory" type="update">
+        Update JSON Unit 2.21.0 -> 2.22.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update JaCoCo 0.8.3 -> 0.8.6.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.activemq:* 5.16.0 -> 5.16.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.mockito:mockito-* 3.7.0 -> 3.7.7.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.springframework:* 5.3.2 -> 5.3.3.
+      </action>
+      <action dev="ggregory" type="update">
+        Update mongodb4.version 4.1.1 -> 4.2.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.fusesource.jansi:jansi 1.18 -> 2.2.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.assertj:assertj-core 3.18.1 -> 3.19.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update net.javacrumbs.json-unit:json-unit 2.22.0 -> 2.23.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update Woodstox 5.0.3 -> 6.2.3 to match Jackson 2.12.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.activemq:* 5.16.0 -> 5.16.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.mockito:mockito-* 3.7.0 -> 3.7.7.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.springframework:* 5.3.2 -> 5.3.3.
+      </action>
+      <action dev="ggregory" type="update">
+        Update mongodb4.version 4.1.1 -> 4.2.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.fusesource.jansi:jansi 1.18 -> 2.3.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.assertj:assertj-core 3.18.1 -> 3.19.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update net.javacrumbs.json-unit:json-unit 2.22.0 -> 2.23.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update net.javacrumbs.json-unit:json-unit 2.22.0 -> 2.23.0.
+      </action>
+      <action dev="ggregory" type="update">
+        - com.fasterxml.jackson.core:jackson-annotations ................. 2.12.1 -> 2.12.2
+        - com.fasterxml.jackson.core:jackson-core ........................ 2.12.1 -> 2.12.2
+        - com.fasterxml.jackson.core:jackson-databind .................... 2.12.1 -> 2.12.2
+        - com.fasterxml.jackson.dataformat:jackson-dataformat-xml ........ 2.12.1 -> 2.12.2
+        - com.fasterxml.jackson.dataformat:jackson-dataformat-yaml ....... 2.12.1 -> 2.12.2
+        - com.fasterxml.jackson.module:jackson-module-jaxb-annotations ... 2.12.1 -> 2.12.2
+        - org.apache.commons:commons-lang3 ............................... 3.11   -> 3.12.0
+        - org.junit.jupiter:junit-jupiter-engine ......................... 5.7.0  -> 5.7.1
+        - org.junit.jupiter:junit-jupiter-migrationsupport ............... 5.7.0  -> 5.7.1
+        - org.junit.jupiter:junit-jupiter-params ......................... 5.7.0  -> 5.7.1
+        - org.junit.vintage:junit-vintage-engine ......................... 5.7.0  -> 5.7.1
+        - org.mockito:mockito-core ....................................... 3.7.7  -> 3.8.0
+        - org.mockito:mockito-junit-jupiter .............................. 3.7.7  -> 3.8.0
+        - org.mongodb:bson ............................................... 4.2.0  -> 4.2.2
+        - org.mongodb:mongodb-driver-sync ................................ 4.2.0  -> 4.2.2
+      </action>
+    </release>
+    <release version="2.14.0" date="2020-11-06" description="GA Release 2.14.0">
+      <action issue="LOG4J2-2925" dev="rgoers" type="fix">
+        Fix broken link in FAQ.
+      </action>
+      <action issue="LOG4J2-2957" dev="vy" type="add">
+        Add JsonTemplateLayout.
+      </action>
+      <action issue="LOG4J2-2911" dev="rgoers" type="fix">
+        Log4j2EventListener in spring.cloud.config.client listens for wrong event.
+      </action>
+      <action issue="LOG4J2-2889" dev="mattsicker" type="update" due-to="Geng Yuanzhe">
+        Add date pattern support for HTML layout.
+      </action>
+      <action issue="LOG4J2-2919" dev="mattsicker" type="fix" due-to="Geng Yuanzhe">
+        Call ReliabilityStrategy's beforeStopAppenders() method before stopping AsyncAppender.
+      </action>
+      <action issue="LOG4J2-2892" dev="rgoers" type="update" due-to="Jakub Lukes">
+        Allow GelfLayout to produce newline delimited events.
+      </action>
+      <action issue="LOG4J2-2906" dev="rgoers" type="fix" due-to="Stephen Joyner">
+        Fix UnsupportedOperationException when initializing the Log4j2CloudConfigLoggingSystem.
+      </action>
+      <action issue="LOG4J2-2908" dev="rgoers" type="fix">
+        Move Spring Lookup and Spring PropertySource to its own module.
+      </action>
+      <action issue="LOG4J2-2910" dev="rgoers" type="fix">
+        Log4j-web should now stores the servlet context as a map entry instead of in the single external context field.
+      </action>
+      <action issue="LOG4J2-2822" dev="rgoers" type="fix">
+        Javadoc link in ThreadContext description was incorrect.
+      </action>
+      <action issue="LOG4J2-2894" dev="rgoers" type="fix">
+        Fix spelling error in log message.
+      </action>
+      <action issue="LOG4J2-2901" dev="rgoers" type="fix">
+        Missing configuration files should be ignored when creating a composite configuration.
+      </action>
+      <action issue="LOG4J2-2883" dev="rgoers" type="fix">
+        When using DirectFileRolloverStrategy the file pattern was not being recalculated on
+        size based rollover after a time based rollover had occurred.
+      </action>
+      <action issue="LOG4J2-2875" dev="rgoers" type="fix">
+        Rollover was failing to create directories when using a DirectFileeRolloverStrategy.
+      </action>
+      <action issue="LOG4J2-2859" dev="rgoers" type="fix" due-to="Yanming Zhou">
+        Fixed typos where mergeFactory should be mergeStrategy.
+      </action>
+      <action issue="LOG4J2-2832" dev="rgoers" type="fix" due-to="Benjamin Asbach">
+        Correct class name printed in error message in RollingFileAppender.
+      </action>
+      <action issue="LOG4J2-2882" dev="rgoers" type="fix" due-to="Emmanuel Bourg">
+        Support java.util.logging filters when using that API.
+      </action>
+      <action issue="LOG4J2-2880" dev="rgoers" type="fix">
+        Create StackWalker benchmark. Revert back to StackWalker.walk based on benchmark results.
+      </action>
+      <action issue="LOG4J2-2867" dev="rgoers" type="fix">
+        Obtain ContextDataProviders asynchronously.
+      </action>
+      <action issue="LOG4J2-2877" dev="rgoers" type="fix">
+        Determine the container id to obtain container and image information.
+      </action>
+      <action issue="LOG4J2-2844" dev="ggregory" type="fix">
+        Null pointer exception when no network interfaces are available.
+      </action>
+      <action issue="LOG4J2-2848" dev="ggregory" type="add">
+        Create module log4j-mongodb4 to use new major version 4 MongoDB driver.
+      </action>
+      <action issue="LOG4J2-2851" dev="ggregory" type="remove">
+        Drop log4j-mongodb2 module.
+      </action>
+      <action dev="ggregory" type="update">
+        Update MongoDB tests to require Java 8 unconditionally now that Log4j requires Java 8.
+      </action>
+      <action dev="ggregory" type="update">
+		Update mongodb3.version from 3.12.1 to 3.12.6.
+      </action>
+      <action dev="ggregory" type="update">
+        Update com.fasterxml.jackson.* 2.10.2 -> 2.11.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.activemq:activemq-broker 5.15.11 -> 5.16.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.commons:commons-compress 1.19 -> 1.20.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.commons:commons-csv 1.7 -> 1.8.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.apache.commons:commons-lang3 3.9 -> 3.10.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.codehaus.groovy:* 2.5.6 -> 3.0.5.
+      </action>
+      <action dev="ggregory" type="update">
+        Update tests junit:junit 4.12 -> 4.13.
+      </action>
+      <action dev="ggregory" type="update">
+        Update tests commons-io:commons-io 2.6 -> 2.7.
+      </action>
+      <action dev="ggregory" type="update">
+        Update jackson 2.11.0 -> 2.11.2.
+      </action>
+      <action dev="ggregory" type="update">
+        Update tests hsqldb 2.5.0 -> 2.5.1.
+      </action>
+      <action issue="LOG4J2-2895" dev="ckozak" type="fix">
+        Fix potential deadlock in asynchronous logging by avoiding blocking for queue space on Log4jThreads
+      </action>
+      <action issue="LOG4J2-2837" dev="ckozak" type="fix">
+        Disruptor and JUL no longer recursively start the AsyncLoggerDisruptor
+        resulting in an extra disruptor background thread constantly waiting.
+      </action>
+      <action issue="LOG4J2-2867" dev="ckozak" type="fix">
+        RingBufferLogEventTranslator uses a static ContextDataInjector instead of initializing a new object
+        on each thread.
+      </action>
+      <action issue="LOG4J2-2858" dev="ckozak" type="add" due-to="Stepan Gorban">
+        More flexible configuration of the Disruptor WaitStrategy.
+      </action>
+      <action issue="LOG4J2-2898" dev="ckozak" type="fix" due-to="Turbanov Andrey">
+        Avoid initializing volatile fields with default values.
+      </action>
+      <action issue="LOG4J2-2899" dev="ckozak" type="fix">
+        Fix log4j-1.2-api LogEventWrapper threadId and priority accessors when called multiple times.
+      </action>
+      <action issue="LOG4J2-2939" dev="ckozak" type="fix" due-to="Constantin Hirsch">
+        Fix NPE in MDCContextMap on 'contains' and 'isEmpty' invocations.
+      </action>
+      <action issue="LOG4J2-2954" dev="ckozak" type="fix" due-to="Henry Tung">
+        Prevent premature garbage collection of shutdown hooks in DefaultShutdownCallbackRegistry.
+      </action>
+    </release>
+    <release version="2.13.3" date="2020-05-10" description="GA Release 2.13.3">
+      <action issue="LOG4J2-2838" dev="rgoers" type="fix">
+        Fix NullPointerException in ThreadContextDataInjector.
+      </action>
+    </release>
+    <release version="2.13.2" date="2020-04-23" description="GA Release 2.13.2">
+      <action issue="LOG4J2-2824" dev="rgoers" type="fix" due-to="CrazyBills">
+        Implement requiresLocation in GelfLayout to reflect whether location information is used in the message Pattern.
+      </action>
+      <action issue="LOG4J2-2588" dev="rgoers" type="fix">
+        Add option to restore printing timeMillis in the JsonLayout.
+      </action>
+      <action issue="LOG4J2-2766" dev="rgoers" type="fix">
+        Initialize pattern processor before triggering policy during reconfiguration.
+      </action>
+      <action issue="LOG4J2-2457" dev="rgoers" type="update">
+        Allow the file extension in the file pattern to be modified during reconfiguration.
+      </action>
+      <action issue="LOG4J2-2810" dev="rgoers" type="fix">
+        Add information about using a url in log4j.configurationFile.
+      </action>
+      <action issue="LOG4J2-2813" dev="rgoers" type="fix" due-to="Keith D Gregory">
+        serializeToBytes was checking wrong variable for null.
+      </action>
+      <action issue="LOG4J2-2814" dev="rgoers" type="fix">
+        Fix Javadoc for ScriptPatternSelector.
+      </action>
+      <action issue="LOG4J2-2793" dev="rgoers" type="fix" due-to="Renukaprasad C">
+        Allow trailing and leading spaces in log level.
+>>>>>>> 4a4b753 [LOG4J2-3242] Rename JNDI enablement property from 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.
       </action>
       <action issue="LOG4J2-2819" dev="mattsicker" type="update">
         Add support for specifying an SSL configuration for SmtpAppender.
diff --git a/src/site/xdoc/manual/appenders.xml b/src/site/xdoc/manual/appenders.xml
index d1c14fa..03c660e 100644
--- a/src/site/xdoc/manual/appenders.xml
+++ b/src/site/xdoc/manual/appenders.xml
@@ -1527,6 +1527,12 @@ public class ConnectionFactory {
         <a name="JMSTopicAppender"/>
         <subsection name="JMS Appender">
           <p>The JMS Appender sends the formatted log event to a JMS Destination.</p>
+<<<<<<< log4j-2.12
+=======
+          <p>The JMS Appender requires JNDI support so as of release 2.16.0 this appender will not function unless
+            <code>log4j2.enableJndiJms=true</code> is configured as a system property or environment
+            variable. See the <a href="./configuration.html#enableJndiJms">enableJndiJms</a> system property.</p>
+>>>>>>> 4a4b753 [LOG4J2-3242] Rename JNDI enablement property from 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.
           <p>
             Note that in Log4j 2.0, this appender was split into a JMSQueueAppender and a JMSTopicAppender. Starting
             in Log4j 2.1, these appenders were combined into the JMS Appender which makes no distinction between queues
diff --git a/src/site/xdoc/manual/configuration.xml.vm b/src/site/xdoc/manual/configuration.xml.vm
index 727a323..ef8280d 100644
--- a/src/site/xdoc/manual/configuration.xml.vm
+++ b/src/site/xdoc/manual/configuration.xml.vm
@@ -1938,6 +1938,59 @@ public class AwesomeTest {
     </td>
   </tr>
   <tr>
+<<<<<<< log4j-2.12
+=======
+    <td><a name="enableJndiContextSelector"/>log4j2.enableJndiContextSelector</td>
+    <td>LOG4J_ENABLE_JNDI_CONTEXT_SELECTOR</td>
+    <td>false</td>
+    <td>
+      When true, the Log4j context selector that uses the JNDI java protocol is enabled. When false, the default, they are disabled.
+    </td>
+  </tr>
+  <tr>
+    <td><a name="enableJndiJms"/>log4j2.enableJndiJms</td>
+    <td>LOG4J_ENABLE_JNDI_JMS</td>
+    <td>false</td>
+    <td>
+      When true, the Log4j JMS Appender that uses JNDI's java protocol is enabled. When false, the default, they are disabled.
+    </td>
+  </tr>
+  <tr>
+    <td><a name="enableJndiLookup"/>log4j2.enableJndiLookup</td>
+    <td>LOG4J_ENABLE_JNDI_LOOKUP</td>
+    <td>false</td>
+    <td>
+      When true, the Log4j lookup that uses JNDI's java protocol is enabled. When false, the default, they are disabled.
+    </td>
+  </tr>
+  <tr>
+    <td><a name="allowedLdapClasses"/>log4j2.allowedLdapClasses</td>
+    <td>LOG4J_ALLOWED_LDAP_CLASSES</td>
+    <td>&nbsp;</td>
+    <td>
+      System property that specifies fully qualified class names that may be accessed by LDAP. The classes
+      must implement Serializable. By default only Java primitive classes are allowed.
+    </td>
+  </tr>
+  <tr>
+    <td><a name="allowedLdapHosts"/>log4j2.allowedLdapHosts</td>
+    <td>LOG4J_ALLOWED_LDAP_HOSTS</td>
+    <td>&nbsp;</td>
+    <td>
+      System property that adds host names or ip addresses that may be access by LDAP. By default it only allows
+      the local host names and ip addresses.
+    </td>
+  </tr>
+  <tr>
+    <td><a name="allowedJndiProtocols"/>log4j2.allowedJndiProtocols</td>
+    <td>LOG4J_ALLOWED_JNDI_PROTOCOLS</td>
+    <td>&nbsp;</td>
+    <td>
+      System property that adds protocol names that JNDI will allow. By default it only allows java, ldap, and ldaps.
+    </td>
+  </tr>
+  <tr>
+>>>>>>> 4a4b753 [LOG4J2-3242] Rename JNDI enablement property from 'log4j2.enableJndi' to 'log4j2.enableJndiLookup', 'log4j2.enableJndiJms', and 'log4j2.enableJndiContextSelector'.
     <td><a name="uuidSequence"/>log4j2.uuidSequence
       <br />
       (<a name="org.apache.logging.log4j.uuidSequence"/>org.apache.logging.log4j.uuidSequence)