You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2016/09/18 13:12:27 UTC

logging-log4j2 git commit: LOG4J2-1591 Introduced new interface LifeCycle2 with stop(long, TimeUnit) method to avoid breaking backwards compatibility with new Configurator.shutdown(LoggerContext, long, TimeUnit) API.

Repository: logging-log4j2
Updated Branches:
  refs/heads/master b4150daa4 -> e2c1b6637


LOG4J2-1591 Introduced new interface LifeCycle2 with stop(long,TimeUnit) method to avoid breaking backwards compatibility with new Configurator.shutdown(LoggerContext, long, TimeUnit) API.


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/e2c1b663
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/e2c1b663
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/e2c1b663

Branch: refs/heads/master
Commit: e2c1b6637475ce0c1d0335c6d947100deeaab0a7
Parents: b4150da
Author: rpopma <rp...@apache.org>
Authored: Sun Sep 18 22:12:32 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sun Sep 18 22:12:32 2016 +0900

----------------------------------------------------------------------
 .../logging/log4j/core/AbstractLifeCycle.java   |  4 +-
 .../apache/logging/log4j/core/LifeCycle.java    | 20 +++-------
 .../apache/logging/log4j/core/LifeCycle2.java   | 37 ++++++++++++++++++
 .../logging/log4j/core/LoggerContext.java       | 10 +++--
 .../rolling/CompositeTriggeringPolicy.java      | 10 +++--
 .../appender/rolling/RollingFileManager.java    | 14 ++++---
 .../core/appender/routing/RoutingAppender.java  | 41 +++++++++++---------
 .../core/config/AbstractConfiguration.java      | 17 ++++++--
 .../log4j/core/config/Configuration.java        |  8 +++-
 .../log4j/core/filter/AbstractFilterable.java   | 14 +++++--
 .../log4j/core/filter/CompositeFilter.java      |  7 +++-
 .../log4j/core/net/server/JmsServer.java        |  8 ++--
 .../util/DefaultShutdownCallbackRegistry.java   |  6 +--
 src/changes/changes.xml                         |  3 ++
 14 files changed, 136 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLifeCycle.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLifeCycle.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLifeCycle.java
index fbbe074..ffc50a9 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLifeCycle.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLifeCycle.java
@@ -27,7 +27,7 @@ import org.apache.logging.log4j.status.StatusLogger;
  * Wraps a {@link LifeCycle.State}.
  * </p>
  */
-public class AbstractLifeCycle implements LifeCycle {
+public class AbstractLifeCycle implements LifeCycle2 {
 
     public static final int DEFAULT_STOP_TIMEOUT = 0;
     public static final TimeUnit DEFAULT_STOP_TIMEUNIT = TimeUnit.MILLISECONDS;
@@ -137,7 +137,7 @@ public class AbstractLifeCycle implements LifeCycle {
         }
         return stopped;
     }
-    
+
     @Override
     public boolean stop(final long timeout, final TimeUnit timeUnit) {
         this.state = LifeCycle.State.STOPPED;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java
index 7dc1a94..3af9578 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java
@@ -28,11 +28,11 @@ import java.util.concurrent.TimeUnit;
  * stopped, this goes into the {@link State#STOPPED} state. In most circumstances, implementation classes should
  * store their {@link State} in a {@code volatile} field or inside an
  * {@link java.util.concurrent.atomic.AtomicReference} dependent on synchronization and concurrency requirements.
- * 
+ *
  * @see AbstractLifeCycle
  */
 public interface LifeCycle {
-    
+
     /**
      * Status of a life cycle like a {@link LoggerContext}.
      */
@@ -50,30 +50,20 @@ public interface LifeCycle {
         /** Has stopped. */
         STOPPED
     }
-    
+
     /**
      * Gets the life-cycle state.
-     * 
+     *
      * @return the life-cycle state
      */
     State getState();
 
     void initialize();
-    
+
     void start();
 
     void stop();
 
-    /**
-     * Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current
-     * thread is interrupted, whichever happens first.
-     * 
-     * @param timeout the maximum time to wait
-     * @param timeUnit the time unit of the timeout argument
-     * @return true if the receiver was stopped cleanly and normally, false otherwise.
-     */
-    boolean stop(long timeout, TimeUnit timeUnit);
-
     boolean isStarted();
 
     boolean isStopped();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle2.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle2.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle2.java
new file mode 100644
index 0000000..71c6fad
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle2.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Extends the LifeCycle interface.
+ * @since 2.7
+ */
+public interface LifeCycle2 extends LifeCycle {
+
+    /**
+     * Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current
+     * thread is interrupted, whichever happens first.
+     *
+     * @param timeout the maximum time to wait
+     * @param timeUnit the time unit of the timeout argument
+     * @return true if the receiver was stopped cleanly and normally, false otherwise.
+     * @since 2.7
+     */
+    boolean stop(long timeout, TimeUnit timeUnit);
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
index 1fbc855..8cf9520 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
@@ -325,7 +325,11 @@ public class LoggerContext extends AbstractLifeCycle
             final Configuration prev = configuration;
             configuration = NULL_CONFIGURATION;
             updateLoggers();
-            prev.stop(timeout, timeUnit);
+            if (prev instanceof LifeCycle2) {
+                ((LifeCycle2) prev).stop(timeout, timeUnit);
+            } else {
+                prev.stop();
+            }
             externalContext = null;
             LogManager.getFactory().removeContext(this);
             final String source = "LoggerContext \'" + getName() + "\'";
@@ -659,7 +663,7 @@ public class LoggerContext extends AbstractLifeCycle
 
     /**
      * Gets the executor service to submit normal tasks.
-     *  
+     *
      * @return the ExecutorService to submit normal tasks.
      */
     public ExecutorService getExecutorService() {
@@ -668,7 +672,7 @@ public class LoggerContext extends AbstractLifeCycle
 
     /**
      * Gets the executor service to submit daemon tasks.
-     *  
+     *
      * @return the ExecutorService to submit normal daemon tasks.
      */
     public ExecutorService getExecutorServiceDeamons() {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CompositeTriggeringPolicy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CompositeTriggeringPolicy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CompositeTriggeringPolicy.java
index 5e967a6..b7bf027 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CompositeTriggeringPolicy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/CompositeTriggeringPolicy.java
@@ -20,6 +20,7 @@ import java.util.Arrays;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.logging.log4j.core.LifeCycle;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginElement;
@@ -83,14 +84,17 @@ public final class CompositeTriggeringPolicy extends AbstractTriggeringPolicy {
         setStopping();
         boolean stopped = true;
         for (final TriggeringPolicy triggeringPolicy : triggeringPolicies) {
-            if (triggeringPolicy instanceof LifeCycle) {
-                stopped &= ((LifeCycle) triggeringPolicy).stop(timeout, timeUnit);
+            if (triggeringPolicy instanceof LifeCycle2) {
+                stopped &= ((LifeCycle2) triggeringPolicy).stop(timeout, timeUnit);
+            } else if (triggeringPolicy instanceof LifeCycle) {
+                ((LifeCycle) triggeringPolicy).stop();
+                stopped &= true;
             }
         }
         setStopped();
         return stopped;
     }
-    
+
     @Override
     public String toString() {
         return "CompositeTriggeringPolicy(policies=" + Arrays.toString(triggeringPolicies) + ")";

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
index 2ec6645..c157b18 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LifeCycle;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.appender.ConfigurationFactoryData;
@@ -178,12 +179,15 @@ public class RollingFileManager extends FileManager {
     @Override
     public boolean releaseSub(final long timeout, final TimeUnit timeUnit) {
         boolean stopped = true;
-        if (triggeringPolicy instanceof LifeCycle) {
-            stopped &= ((LifeCycle) triggeringPolicy).stop(timeout, timeUnit);
+        if (triggeringPolicy instanceof LifeCycle2) {
+            stopped &= ((LifeCycle2) triggeringPolicy).stop(timeout, timeUnit);
+        } else if (triggeringPolicy instanceof LifeCycle) {
+            ((LifeCycle) triggeringPolicy).stop();
+            stopped &= true;
         }
         return stopped && super.releaseSub(timeout, timeUnit);
     }
-    
+
     public synchronized void rollover() {
         if (rollover(rolloverStrategy)) {
             try {
@@ -377,7 +381,7 @@ public class RollingFileManager extends FileManager {
          */
         public FactoryData(final String pattern, final boolean append, final boolean bufferedIO,
                 final TriggeringPolicy policy, final RolloverStrategy strategy, final String advertiseURI,
-                final Layout<? extends Serializable> layout, final int bufferSize, final boolean immediateFlush, 
+                final Layout<? extends Serializable> layout, final int bufferSize, final boolean immediateFlush,
                 final boolean createOnDemand, final Configuration configuration) {
             super(configuration);
             this.pattern = pattern;
@@ -469,7 +473,7 @@ public class RollingFileManager extends FileManager {
                 final ByteBuffer buffer = ByteBuffer.wrap(new byte[actualSize]);
                 final OutputStream os = data.createOnDemand ? null : new FileOutputStream(name, data.append);
                 final long time = data.createOnDemand? System.currentTimeMillis() : file.lastModified(); // LOG4J2-531 create file first so time has valid value
-                
+
                 return new RollingFileManager(data.getLoggerContext(), name, data.pattern, os,
                         data.append, data.createOnDemand, size, time, data.policy, data.strategy, data.advertiseURI,
                         data.layout, writeHeader, buffer);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
index 49cc600..8183d26 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/routing/RoutingAppender.java
@@ -27,6 +27,7 @@ import javax.script.Bindings;
 
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.appender.AbstractAppender;
 import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
@@ -51,28 +52,28 @@ import org.apache.logging.log4j.core.util.Booleans;
  */
 @Plugin(name = "Routing", category = "Core", elementType = "appender", printObject = true)
 public final class RoutingAppender extends AbstractAppender {
-    
+
     public static final String STATIC_VARIABLES_KEY = "staticVariables";
 
     public static class Builder<B extends Builder<B>> extends AbstractAppender.Builder<B>
             implements org.apache.logging.log4j.core.util.Builder<RoutingAppender> {
-                
+
         // Does not work unless the element is called "Script", I wanted "DefaultRounteScript"...
         @PluginElement("Script")
         private AbstractScript defaultRouteScript;
-        
-        @PluginElement("Routes") 
+
+        @PluginElement("Routes")
         private Routes routes;
-        
-        @PluginConfiguration 
+
+        @PluginConfiguration
         private Configuration configuration;
-        
-        @PluginElement("RewritePolicy") 
+
+        @PluginElement("RewritePolicy")
         private RewritePolicy rewritePolicy;
-        
-        @PluginElement("PurgePolicy") 
+
+        @PluginElement("PurgePolicy")
         private PurgePolicy purgePolicy;
-        
+
         @Override
         public RoutingAppender build() {
             final String name = getName();
@@ -122,7 +123,7 @@ public final class RoutingAppender extends AbstractAppender {
             this.defaultRouteScript = defaultRouteScript;
             return asBuilder();
         }
-        
+
         public B withRewritePolicy(@SuppressWarnings("hiding") final RewritePolicy rewritePolicy) {
             this.rewritePolicy = rewritePolicy;
             return asBuilder();
@@ -133,14 +134,14 @@ public final class RoutingAppender extends AbstractAppender {
         }
 
     }
-    
+
     @PluginBuilderFactory
     public static <B extends Builder<B>> B newBuilder() {
         return new Builder<B>().asBuilder();
     }
 
     private static final String DEFAULT_KEY = "ROUTING_APPENDER_DEFAULT";
-    
+
     private final Routes routes;
     private Route defaultRoute;
     private final Configuration configuration;
@@ -149,7 +150,7 @@ public final class RoutingAppender extends AbstractAppender {
     private final PurgePolicy purgePolicy;
     private final AbstractScript defaultRouteScript;
     private final ConcurrentMap<Object, Object> scriptStaticVariables = new ConcurrentHashMap<>();
-    
+
     private RoutingAppender(final String name, final Filter filter, final boolean ignoreExceptions, final Routes routes,
             final RewritePolicy rewritePolicy, final Configuration configuration, final PurgePolicy purgePolicy,
             final AbstractScript defaultRouteScript) {
@@ -213,9 +214,13 @@ public final class RoutingAppender extends AbstractAppender {
         super.stop(timeout, timeUnit, false);
         final Map<String, Appender> map = configuration.getAppenders();
         for (final Map.Entry<String, AppenderControl> entry : appenders.entrySet()) {
-            final String name = entry.getValue().getAppender().getName();
-            if (!map.containsKey(name)) {
-                entry.getValue().getAppender().stop(timeout, timeUnit);
+            final Appender appender = entry.getValue().getAppender();
+            if (!map.containsKey(appender.getName())) {
+                if (appender instanceof LifeCycle2) {
+                    ((LifeCycle2) appender).stop(timeout, timeUnit);
+                } else {
+                    appender.stop();
+                }
             }
         }
         setStopped();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index 6933cdd..c740b8c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -40,6 +40,7 @@ import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.appender.AsyncAppender;
@@ -126,7 +127,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
     private AsyncLoggerConfigDisruptor asyncLoggerConfigDisruptor;
     private NanoClock nanoClock = new DummyNanoClock();
     private final WeakReference<LoggerContext> loggerContext;
-    
+
     /**
      * Constructor.
      */
@@ -326,7 +327,11 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
             // LOG4J2-511, LOG4J2-392 stop AsyncAppenders first
             LOGGER.trace("{} stopping {} AsyncAppenders.", cls, async.size());
             for (final Appender appender : async) {
-                appender.stop(timeout, timeUnit);
+                if (appender instanceof LifeCycle2) {
+                    ((LifeCycle2) appender).stop(timeout, timeUnit);
+                } else {
+                    appender.stop();
+                }
             }
         }
 
@@ -340,7 +345,11 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
         int appenderCount = 0;
         for (int i = array.length - 1; i >= 0; --i) {
             if (array[i].isStarted()) { // then stop remaining Appenders
-                array[i].stop(timeout, timeUnit);
+                if (array[i] instanceof LifeCycle2) {
+                    ((LifeCycle2) array[i]).stop(timeout, timeUnit);
+                } else {
+                    array[i].stop();
+                }
                 appenderCount++;
             }
         }
@@ -800,7 +809,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
     public LoggerContext getLoggerContext() {
         return loggerContext.get();
     }
-    
+
     /**
      * Returns the root Logger.
      *

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java
index 88be74d..1a55b48 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java
@@ -35,6 +35,12 @@ import org.apache.logging.log4j.core.util.WatchManager;
 
 /**
  * Interface that must be implemented to create a configuration.
+ * <p>
+ * Custom implementations are recommended to extend {@link AbstractConfiguration}.
+ * </p>
+ *
+ * @see AbstractConfiguration
+ * @see org.apache.logging.log4j.core.LifeCycle2
  */
 public interface Configuration extends Filterable {
 
@@ -192,7 +198,7 @@ public interface Configuration extends Filterable {
 
     /**
      * Gets the logger context.
-     * 
+     *
      * @return the logger context.
      */
     LoggerContext getLoggerContext();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/AbstractFilterable.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/AbstractFilterable.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/AbstractFilterable.java
index 278a02a..028710a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/AbstractFilterable.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/AbstractFilterable.java
@@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.logging.log4j.core.AbstractLifeCycle;
 import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.PluginElement;
 
@@ -30,8 +31,8 @@ import org.apache.logging.log4j.core.config.plugins.PluginElement;
 public abstract class AbstractFilterable extends AbstractLifeCycle implements Filterable {
 
     /**
-     * Subclasses can extend this abstract Builder. 
-     * 
+     * Subclasses can extend this abstract Builder.
+     *
      * @param <B> This builder class.
      */
     public abstract static class Builder<B extends Builder<B>> {
@@ -54,7 +55,7 @@ public abstract class AbstractFilterable extends AbstractLifeCycle implements Fi
         }
 
     }
-    
+
     /**
      * May be null.
      */
@@ -158,7 +159,12 @@ public abstract class AbstractFilterable extends AbstractLifeCycle implements Fi
         }
         boolean stopped = true;
         if (filter != null) {
-            stopped = filter.stop(timeout, timeUnit);
+            if (filter instanceof LifeCycle2) {
+                stopped = ((LifeCycle2) filter).stop(timeout, timeUnit);
+            } else {
+                filter.stop();
+                stopped = true;
+            }
         }
         if (changeLifeCycleState) {
             this.setStopped();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/CompositeFilter.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/CompositeFilter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/CompositeFilter.java
index 300fd80..976e05d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/CompositeFilter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/CompositeFilter.java
@@ -26,6 +26,7 @@ import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.core.AbstractLifeCycle;
 import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.Logger;
 import org.apache.logging.log4j.core.config.Node;
@@ -136,7 +137,11 @@ public final class CompositeFilter extends AbstractLifeCycle implements Iterable
     public boolean stop(final long timeout, final TimeUnit timeUnit) {
         this.setStopping();
         for (final Filter filter : filters) {
-            filter.stop(timeout, timeUnit);
+            if (filter instanceof LifeCycle2) {
+                ((LifeCycle2) filter).stop(timeout, timeUnit);
+            } else {
+                filter.stop();
+            }
         }
         setStopped();
         return true;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java
index 730e778..bcbba40 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/server/JmsServer.java
@@ -31,7 +31,7 @@ import javax.jms.ObjectMessage;
 
 import org.apache.logging.log4j.LoggingException;
 import org.apache.logging.log4j.core.AbstractLifeCycle;
-import org.apache.logging.log4j.core.LifeCycle;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.LogEventListener;
 import org.apache.logging.log4j.core.appender.mom.JmsManager;
@@ -42,7 +42,7 @@ import org.apache.logging.log4j.core.net.JndiManager;
  *
  * @since 2.1
  */
-public class JmsServer extends LogEventListener implements MessageListener, LifeCycle {
+public class JmsServer extends LogEventListener implements MessageListener, LifeCycle2 {
 
     private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZED);
     private final JmsManager jmsManager;
@@ -98,11 +98,11 @@ public class JmsServer extends LogEventListener implements MessageListener, Life
         }
     }
 
-    @Override    
+    @Override
     public void stop() {
         stop(AbstractLifeCycle.DEFAULT_STOP_TIMEOUT, AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT);
     }
-    
+
     @Override
     public boolean stop(final long timeout, final TimeUnit timeUnit) {
         boolean stopped = true;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/log4j-core/src/main/java/org/apache/logging/log4j/core/util/DefaultShutdownCallbackRegistry.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/DefaultShutdownCallbackRegistry.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/DefaultShutdownCallbackRegistry.java
index ac822ee..48d54b6 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/DefaultShutdownCallbackRegistry.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/DefaultShutdownCallbackRegistry.java
@@ -29,7 +29,7 @@ import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.AbstractLifeCycle;
-import org.apache.logging.log4j.core.LifeCycle;
+import org.apache.logging.log4j.core.LifeCycle2;
 import org.apache.logging.log4j.status.StatusLogger;
 
 /**
@@ -38,7 +38,7 @@ import org.apache.logging.log4j.status.StatusLogger;
  *
  * @since 2.1
  */
-public class DefaultShutdownCallbackRegistry implements ShutdownCallbackRegistry, LifeCycle, Runnable {
+public class DefaultShutdownCallbackRegistry implements ShutdownCallbackRegistry, LifeCycle2, Runnable {
     /** Status logger. */
     protected static final Logger LOGGER = StatusLogger.getLogger();
 
@@ -151,7 +151,7 @@ public class DefaultShutdownCallbackRegistry implements ShutdownCallbackRegistry
         Runtime.getRuntime().addShutdownHook(thread);
     }
 
-    @Override    
+    @Override
     public void stop() {
         stop(AbstractLifeCycle.DEFAULT_STOP_TIMEOUT, AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT);
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e2c1b663/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c109a92..1698408 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,9 @@
   </properties>
   <body>
     <release version="2.7" date="2016-MM-DD" description="GA Release 2.7">
+      <action issue="LOG4J2-1591" dev="rpopma" type="fix">
+        Introduced new interface LifeCycle2 with stop(long,TimeUnit) method to avoid breaking backwards compatibility with new Configurator.shutdown(LoggerContext, long, TimeUnit) API.
+      </action>
       <action issue="LOG4J2-1590" dev="rpopma" type="fix">
         Fixed issue with filters extending AbstractFilter that did not override methods with unrolled varargs.
       </action>