Javadoc. Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/f6bb2c3a Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/f6bb2c3a Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/f6bb2c3a
Branch: refs/heads/LOG4J2-1349-gcfree-threadcontext Commit: f6bb2c3af967de70dbf8cde6498e996eaea67071 Parents: a559d5c Author: ggregory <ggreg...@us-l-gg02.rocketsoftware.com> Authored: Wed Sep 7 12:23:36 2016 -0400 Committer: ggregory <ggreg...@us-l-gg02.rocketsoftware.com> Committed: Wed Sep 7 12:23:36 2016 -0400 ---------------------------------------------------------------------- .../log4j/core/appender/AbstractManager.java | 424 +++++++++---------- 1 file changed, 212 insertions(+), 212 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f6bb2c3a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractManager.java ---------------------------------------------------------------------- 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 edd82a2..acd2759 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 @@ -1,212 +1,212 @@ -/* - * 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; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.AbstractLifeCycle; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.message.Message; -import org.apache.logging.log4j.status.StatusLogger; - -/** - * Abstract base class used to register managers. - * <p> - * This class implements {@link AutoCloseable} mostly to allow unit tests to be written safely and succinctly. While - * managers do need to allocate resources (usually on construction) and then free these resources, a manager is longer - * lived than other auto-closeable objects like streams. None the less, making a manager AutoCloseable forces readers to - * be aware of the the pattern: allocate resources on construction and call {@link #close()} at some point. - * </p> - */ -public abstract class AbstractManager implements AutoCloseable { - - /** - * Allow subclasses access to the status logger without creating another instance. - */ - protected static final Logger LOGGER = StatusLogger.getLogger(); - - // Need to lock that map instead of using a ConcurrentMap due to stop removing the - // manager from the map and closing the stream, requiring the whole stop method to be locked. - private static final Map<String, AbstractManager> MAP = new HashMap<>(); - - private static final Lock LOCK = new ReentrantLock(); - - /** - * Number of Appenders using this manager. - */ - protected int count; - - private final String name; - - private final LoggerContext loggerContext; - - protected AbstractManager(final LoggerContext loggerContext, final String name) { - this.loggerContext = loggerContext; - this.name = name; - LOGGER.debug("Starting {} {}", this.getClass().getSimpleName(), name); - } - - /** - * Called to signify that this Manager is no longer required by an Appender. - */ - @Override - public void close() { - stop(AbstractLifeCycle.DEFAULT_STOP_TIMEOUT, AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT); - } - - public void stop(final long timeout, final TimeUnit timeUnit) { - LOCK.lock(); - try { - --count; - if (count <= 0) { - MAP.remove(name); - LOGGER.debug("Shutting down {} {}", this.getClass().getSimpleName(), getName()); - releaseSub(timeout, timeUnit); - } - } finally { - LOCK.unlock(); - } - } - - /** - * Retrieves a Manager if it has been previously created or creates a new Manager. - * @param name The name of the Manager to retrieve. - * @param factory The Factory to use to create the Manager. - * @param data An Object that should be passed to the factory when creating the Manager. - * @param <M> The Type of the Manager to be created. - * @param <T> The type of the Factory data. - * @return A Manager with the specified name and type. - */ - public static <M extends AbstractManager, T> M getManager(final String name, final ManagerFactory<M, T> factory, - final T data) { - LOCK.lock(); - try { - @SuppressWarnings("unchecked") - M manager = (M) MAP.get(name); - if (manager == null) { - manager = factory.createManager(name, data); - if (manager == null) { - throw new IllegalStateException("ManagerFactory [" + factory + "] unable to create manager for [" - + name + "] with data [" + data + "]"); - } - MAP.put(name, manager); - } else { - manager.updateData(data); - } - manager.count++; - return manager; - } finally { - LOCK.unlock(); - } - } - - public void updateData(final Object data) { - // This default implementation does nothing. - } - - /** - * Determines if a Manager with the specified name exists. - * @param name The name of the Manager. - * @return True if the Manager exists, false otherwise. - */ - public static boolean hasManager(final String name) { - LOCK.lock(); - try { - return MAP.containsKey(name); - } finally { - LOCK.unlock(); - } - } - - /** - * May be overridden by Managers to perform processing while the Manager is being released and the - * lock is held. - * @param timeout TODO - * @param timeUnit TODO - */ - protected void releaseSub(final long timeout, final TimeUnit timeUnit) { - // This default implementation does nothing. - } - - protected int getCount() { - return count; - } - - /** - * Gets the logger context used to create this instance or null. The logger context is usually set when an appender - * creates a manager and that appender is given a Configuration. Not all appenders are given a Configuration by - * their factory method or builder. - * - * @return the logger context used to create this instance or null. - */ - public LoggerContext getLoggerContext() { - return loggerContext; - } - - /** - * Called to signify that this Manager is no longer required by an Appender. - * @deprecated In 2.7, use {@link #close()}. - */ - @Deprecated - public void release() { - close(); - } - - /** - * Returns the name of the Manager. - * @return The name of the Manager. - */ - public String getName() { - return name; - } - - /** - * Provide a description of the content format supported by this Manager. Default implementation returns an empty - * (unspecified) Map. - * - * @return a Map of key/value pairs describing the Manager-specific content format, or an empty Map if no content - * format descriptors are specified. - */ - public Map<String, String> getContentFormat() { - return new HashMap<>(); - } - - protected void log(final Level level, final String message, final Throwable throwable) { - final Message m = LOGGER.getMessageFactory().newMessage("{} {} {}: {}", - getClass().getSimpleName(), getName(), message, throwable); - LOGGER.log(level, m, throwable); - } - - protected void logDebug(final String message, final Throwable throwable) { - log(Level.DEBUG, message, throwable); - } - - protected void logError(final String message, final Throwable throwable) { - log(Level.ERROR, message, throwable); - } - - protected void logWarn(final String message, final Throwable throwable) { - log(Level.WARN, message, throwable); - } - -} +/* + * 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; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.AbstractLifeCycle; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.status.StatusLogger; + +/** + * Abstract base class used to register managers. + * <p> + * This class implements {@link AutoCloseable} mostly to allow unit tests to be written safely and succinctly. While + * managers do need to allocate resources (usually on construction) and then free these resources, a manager is longer + * lived than other auto-closeable objects like streams. None the less, making a manager AutoCloseable forces readers to + * be aware of the the pattern: allocate resources on construction and call {@link #close()} at some point. + * </p> + */ +public abstract class AbstractManager implements AutoCloseable { + + /** + * Allow subclasses access to the status logger without creating another instance. + */ + protected static final Logger LOGGER = StatusLogger.getLogger(); + + // Need to lock that map instead of using a ConcurrentMap due to stop removing the + // manager from the map and closing the stream, requiring the whole stop method to be locked. + private static final Map<String, AbstractManager> MAP = new HashMap<>(); + + private static final Lock LOCK = new ReentrantLock(); + + /** + * Number of Appenders using this manager. + */ + protected int count; + + private final String name; + + private final LoggerContext loggerContext; + + protected AbstractManager(final LoggerContext loggerContext, final String name) { + this.loggerContext = loggerContext; + this.name = name; + LOGGER.debug("Starting {} {}", this.getClass().getSimpleName(), name); + } + + /** + * Called to signify that this Manager is no longer required by an Appender. + */ + @Override + public void close() { + stop(AbstractLifeCycle.DEFAULT_STOP_TIMEOUT, AbstractLifeCycle.DEFAULT_STOP_TIMEUNIT); + } + + public void stop(final long timeout, final TimeUnit timeUnit) { + LOCK.lock(); + try { + --count; + if (count <= 0) { + MAP.remove(name); + LOGGER.debug("Shutting down {} {}", this.getClass().getSimpleName(), getName()); + releaseSub(timeout, timeUnit); + } + } finally { + LOCK.unlock(); + } + } + + /** + * Retrieves a Manager if it has been previously created or creates a new Manager. + * @param name The name of the Manager to retrieve. + * @param factory The Factory to use to create the Manager. + * @param data An Object that should be passed to the factory when creating the Manager. + * @param <M> The Type of the Manager to be created. + * @param <T> The type of the Factory data. + * @return A Manager with the specified name and type. + */ + public static <M extends AbstractManager, T> M getManager(final String name, final ManagerFactory<M, T> factory, + final T data) { + LOCK.lock(); + try { + @SuppressWarnings("unchecked") + M manager = (M) MAP.get(name); + if (manager == null) { + manager = factory.createManager(name, data); + if (manager == null) { + throw new IllegalStateException("ManagerFactory [" + factory + "] unable to create manager for [" + + name + "] with data [" + data + "]"); + } + MAP.put(name, manager); + } else { + manager.updateData(data); + } + manager.count++; + return manager; + } finally { + LOCK.unlock(); + } + } + + public void updateData(final Object data) { + // This default implementation does nothing. + } + + /** + * Determines if a Manager with the specified name exists. + * @param name The name of the Manager. + * @return True if the Manager exists, false otherwise. + */ + public static boolean hasManager(final String name) { + LOCK.lock(); + try { + return MAP.containsKey(name); + } finally { + LOCK.unlock(); + } + } + + /** + * May be overridden by managers to perform processing while the manager is being released and the + * lock is held. A timeout is passed for implementors to use as they see fit. + * @param timeout timeout + * @param timeUnit timeout time unit + */ + protected void releaseSub(final long timeout, final TimeUnit timeUnit) { + // This default implementation does nothing. + } + + protected int getCount() { + return count; + } + + /** + * Gets the logger context used to create this instance or null. The logger context is usually set when an appender + * creates a manager and that appender is given a Configuration. Not all appenders are given a Configuration by + * their factory method or builder. + * + * @return the logger context used to create this instance or null. + */ + public LoggerContext getLoggerContext() { + return loggerContext; + } + + /** + * Called to signify that this Manager is no longer required by an Appender. + * @deprecated In 2.7, use {@link #close()}. + */ + @Deprecated + public void release() { + close(); + } + + /** + * Returns the name of the Manager. + * @return The name of the Manager. + */ + public String getName() { + return name; + } + + /** + * Provide a description of the content format supported by this Manager. Default implementation returns an empty + * (unspecified) Map. + * + * @return a Map of key/value pairs describing the Manager-specific content format, or an empty Map if no content + * format descriptors are specified. + */ + public Map<String, String> getContentFormat() { + return new HashMap<>(); + } + + protected void log(final Level level, final String message, final Throwable throwable) { + final Message m = LOGGER.getMessageFactory().newMessage("{} {} {}: {}", + getClass().getSimpleName(), getName(), message, throwable); + LOGGER.log(level, m, throwable); + } + + protected void logDebug(final String message, final Throwable throwable) { + log(Level.DEBUG, message, throwable); + } + + protected void logError(final String message, final Throwable throwable) { + log(Level.ERROR, message, throwable); + } + + protected void logWarn(final String message, final Throwable throwable) { + log(Level.WARN, message, throwable); + } + +}