From a329325aec915d765691c32810ff867146707de6 Mon Sep 17 00:00:00 2001 From: James Perkins Date: Thu, 9 Mar 2017 17:14:32 -0800 Subject: [PATCH] [LOGMGR-147] Add a closeChildren property to the ExtHandler. This makes the closing of child handlers when the parent handler is closed optional. --- .../java/org/jboss/logmanager/ExtHandler.java | 39 +++++++-- .../logmanager/handlers/HandlerTest.java | 83 +++++++++++++++++++ 2 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 src/test/java/org/jboss/logmanager/handlers/HandlerTest.java diff --git a/src/main/java/org/jboss/logmanager/ExtHandler.java b/src/main/java/org/jboss/logmanager/ExtHandler.java index b2a805d0..7ee53634 100644 --- a/src/main/java/org/jboss/logmanager/ExtHandler.java +++ b/src/main/java/org/jboss/logmanager/ExtHandler.java @@ -20,7 +20,6 @@ package org.jboss.logmanager; import java.io.UnsupportedEncodingException; - import java.security.Permission; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; import java.util.logging.ErrorManager; @@ -43,6 +42,7 @@ public abstract class ExtHandler extends Handler implements FlushableCloseable, private static final Permission CONTROL_PERMISSION = new LoggingPermission("control", null); private volatile boolean autoFlush = true; private volatile boolean enabled = true; + private volatile boolean closeChildren; private static final ErrorManager DEFAULT_ERROR_MANAGER = new OnlyOnceErrorManager(); private volatile Object protectKey; @@ -67,6 +67,7 @@ public abstract class ExtHandler extends Handler implements FlushableCloseable, */ protected ExtHandler() { handlersUpdater.clear(this); + closeChildren = true; super.setErrorManager(DEFAULT_ERROR_MANAGER); } @@ -230,6 +231,28 @@ public final boolean isEnabled() { return enabled; } + /** + * Indicates whether or not children handlers should be closed when this handler is {@linkplain #close() closed}. + * + * @return {@code true} if the children handlers should be closed when this handler is closed, {@code false} if + * children handlers should not be closed when this handler is closed + */ + public boolean isCloseChildren() { + return closeChildren; + } + + /** + * Sets whether or not children handlers should be closed when this handler is {@linkplain #close() closed}. + * + * @param closeChildren {@code true} if all children handlers should be closed when this handler is closed, + * {@code false} if children handlers will not be closed when this handler + * is closed + */ + public void setCloseChildren(final boolean closeChildren) { + checkAccess(this); + this.closeChildren = closeChildren; + } + @Override public final void protect(Object protectionKey) throws SecurityException { if (protectKeyUpdater.compareAndSet(this, null, protectionKey)) { @@ -313,11 +336,15 @@ public void flush() { @Override public void close() throws SecurityException { checkAccess(this); - for (Handler handler : handlers) try { - handler.close(); - } catch (Exception ex) { - reportError("Failed to close child handler", ex, ErrorManager.CLOSE_FAILURE); - } catch (Throwable ignored) {} + if (closeChildren) { + for (Handler handler : handlers) + try { + handler.close(); + } catch (Exception ex) { + reportError("Failed to close child handler", ex, ErrorManager.CLOSE_FAILURE); + } catch (Throwable ignored) { + } + } } @Override diff --git a/src/test/java/org/jboss/logmanager/handlers/HandlerTest.java b/src/test/java/org/jboss/logmanager/handlers/HandlerTest.java new file mode 100644 index 00000000..45f49be6 --- /dev/null +++ b/src/test/java/org/jboss/logmanager/handlers/HandlerTest.java @@ -0,0 +1,83 @@ +/* + * JBoss, Home of Professional Open Source. + * + * Copyright 2017 Red Hat, Inc., and individual contributors + * as indicated by the @author tags. + * + * Licensed 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.jboss.logmanager.handlers; + +import org.jboss.logmanager.ExtHandler; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author James R. Perkins + */ +public class HandlerTest { + + @Test + public void testHandlerClose() throws Exception { + final CloseHandler parent = new CloseHandler(); + final CloseHandler child1 = new CloseHandler(); + final CloseHandler child2 = new CloseHandler(); + parent.setHandlers(new CloseHandler[] {child1, child2, new CloseHandler()}); + + // Ensure all handlers are not closed + Assert.assertFalse(parent.closed); + Assert.assertFalse(child1.closed); + Assert.assertFalse(child2.closed); + + // Close the parent handler, the children should be closed + parent.close(); + Assert.assertTrue(parent.closed); + Assert.assertTrue(child1.closed); + Assert.assertTrue(child2.closed); + + // Reset and wrap + parent.reset(); + child1.reset(); + child2.reset(); + + parent.setCloseChildren(false); + + // Ensure all handlers are not closed + Assert.assertFalse(parent.closed); + Assert.assertFalse(child1.closed); + Assert.assertFalse(child2.closed); + + parent.close(); + + // The parent should be closed, the others should be open + Assert.assertTrue(parent.closed); + Assert.assertFalse(child1.closed); + Assert.assertFalse(child2.closed); + + } + + static class CloseHandler extends ExtHandler { + private boolean closed = false; + + @Override + public void close() { + closed = true; + super.close(); + } + + void reset() { + closed = false; + } + } +}