Skip to content

Commit

Permalink
Merge pull request #188 from jamezp/LOGMGR-128
Browse files Browse the repository at this point in the history
[LOGMGR-128] Allow a LogContext to be closed as well as allowing a us…
  • Loading branch information
jamezp authored Jul 5, 2018
2 parents df688b4 + a3e1df6 commit 7423c6c
Show file tree
Hide file tree
Showing 4 changed files with 498 additions and 3 deletions.
76 changes: 74 additions & 2 deletions src/main/java/org/jboss/logmanager/LogContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,29 @@

import java.lang.ref.WeakReference;
import java.security.Permission;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import java.util.logging.Level;
import java.util.logging.LoggingMXBean;
import java.util.logging.LoggingPermission;

/**
* A logging context, for producing isolated logging environments.
*/
public final class LogContext implements Protectable {
@SuppressWarnings("unused")
public final class LogContext implements Protectable, AutoCloseable {
private static final LogContext SYSTEM_CONTEXT = new LogContext(false);

static final Permission CREATE_CONTEXT_PERMISSION = new RuntimePermission("createLogContext", null);
Expand Down Expand Up @@ -98,6 +101,8 @@ private static void addStrong(Map<String, LevelRef> map, Level level) {
}

private final AtomicReference<Map<String, LevelRef>> levelMapReference;
// Guarded by treeLock
private final Set<AutoCloseable> closeHandlers;

/**
* This lock is taken any time a change is made which affects multiple nodes in the hierarchy.
Expand All @@ -109,6 +114,7 @@ private static void addStrong(Map<String, LevelRef> map, Level level) {
levelMapReference = new AtomicReference<Map<String, LevelRef>>(LazyHolder.INITIAL_LEVEL_MAP);
rootLogger = new LoggerNode(this);
loggerNames = new ConcurrentSkipListMap<String, AtomicInteger>();
closeHandlers = new LinkedHashSet<>();
}

/**
Expand Down Expand Up @@ -340,6 +346,20 @@ public void disableAccess() {
granted.remove();
}

@Override
public void close() throws Exception {
synchronized (treeLock) {
// First we want to close all loggers
recursivelyClose(rootLogger);
// Next process the close handlers associated with this log context
for (AutoCloseable handler : closeHandlers) {
handler.close();
}
// Finally clear any logger names
loggerNames.clear();
}
}

/**
* Returns an enumeration of the logger names that have been created. This does not return names of loggers that
* may have been garbage collected. Logger names added after the enumeration has been retrieved may also be added to
Expand Down Expand Up @@ -383,6 +403,49 @@ public String nextElement() {
};
}

/**
* Adds a handler invoked during the {@linkplain #close() close} of this log context. The close handlers will be
* invoked in the order they are added.
* <p>
* The loggers associated with this context will always be closed.
* </p>
*
* @param closeHandler the close handler to use
*/
public void addCloseHandler(final AutoCloseable closeHandler) {
synchronized (treeLock) {
closeHandlers.add(closeHandler);
}
}

/**
* Gets the current close handlers associated with this log context.
*
* @return the current close handlers
*/
public Set<AutoCloseable> getCloseHandlers() {
synchronized (treeLock) {
return new LinkedHashSet<>(closeHandlers);
}
}

/**
* Clears any current close handlers associated with log context, then adds the handlers to be invoked during
* the {@linkplain #close() close} of this log context. The close handlers will be invoked in the order they are
* added.
* <p>
* The loggers associated with this context will always be closed.
* </p>
*
* @param closeHandlers the close handlers to use
*/
public void setCloseHandlers(final Collection<AutoCloseable> closeHandlers) {
synchronized (treeLock) {
this.closeHandlers.clear();
this.closeHandlers.addAll(closeHandlers);
}
}

protected void incrementRef(final String name) {
AtomicInteger counter = loggerNames.get(name);
if (counter == null) {
Expand Down Expand Up @@ -426,6 +489,15 @@ ConcurrentMap<String, LoggerNode> createChildMap() {
return strong ? new CopyOnWriteMap<String, LoggerNode>() : new CopyOnWriteWeakMap<String, LoggerNode>();
}

private void recursivelyClose(final LoggerNode loggerNode) {
synchronized (treeLock) {
for (LoggerNode child : loggerNode.getChildren()) {
recursivelyClose(child);
}
loggerNode.close();
}
}

private interface LevelRef {
Level get();
}
Expand Down
22 changes: 21 additions & 1 deletion src/main/java/org/jboss/logmanager/LoggerNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
/**
* A node in the tree of logger names. Maintains weak references to children and a strong reference to its parent.
*/
final class LoggerNode {
final class LoggerNode implements AutoCloseable {

/**
* The log context.
Expand Down Expand Up @@ -144,6 +144,26 @@ private LoggerNode(LogContext context, LoggerNode parent, String nodeName) {
children = context.createChildMap();
}

@Override
public void close() {
synchronized (context.treeLock) {
// Reset everything to defaults
filter = null;
if ("".equals(fullName)) {
level = Level.INFO;
effectiveLevel = Level.INFO.intValue();
} else {
level = null;
effectiveLevel = Level.INFO.intValue();
}
handlersUpdater.clear(this);
useParentFilter = false;
useParentHandlers = true;
attachmentsUpdater.get(this).clear();
children.clear();
}
}

/**
* Get or create a relative logger node. The name is relatively qualified to this node.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ final class LogContextConfigurationImpl implements LogContextConfiguration {

LogContextConfigurationImpl(final LogContext logContext) {
this.logContext = logContext;
logContext.addCloseHandler(new LogContextConfigurationCloseHandler());
}

public LogContext getLogContext() {
Expand Down Expand Up @@ -738,4 +739,43 @@ private ObjectProducer resolveFilter(String expression, final boolean immediate)
ObjectProducer resolveFilter(String expression) {
return resolveFilter(expression, false);
}

private class LogContextConfigurationCloseHandler implements AutoCloseable {

@Override
public void close() {
final LogContextConfigurationImpl configuration = LogContextConfigurationImpl.this;
// Remove all the loggers first
for (String name : configuration.getLoggerNames()) {
configuration.removeLoggerConfiguration(name);
}

// Remove all handlers next
for (String name : configuration.getHandlerNames()) {
configuration.removeHandlerConfiguration(name);
}

// Remove all filters
for (String name : configuration.getFilterNames()) {
configuration.removeFilterConfiguration(name);
}

// Remove all formatters
for (String name : configuration.getFormatterNames()) {
configuration.removeFormatterConfiguration(name);
}

// Remove all error managers
for (String name : configuration.getErrorManagerNames()) {
configuration.removeErrorManagerConfiguration(name);
}

// Finally remove all POJO's
for (String name : configuration.getPojoNames()) {
configuration.removePojoConfiguration(name);
}

configuration.commit();
}
}
}
Loading

0 comments on commit 7423c6c

Please sign in to comment.