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;
+ }
+ }
+}