001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.core.sift;
015
016import ch.qos.logback.core.Appender;
017import ch.qos.logback.core.Context;
018import ch.qos.logback.core.CoreConstants;
019import ch.qos.logback.core.helpers.NOPAppender;
020import ch.qos.logback.core.joran.spi.JoranException;
021import ch.qos.logback.core.spi.AbstractComponentTracker;
022import ch.qos.logback.core.spi.ContextAwareImpl;
023
024/**
025 * Track appenders by key. When an appender is not used for
026 * longer than {@link #DEFAULT_TIMEOUT} it is stopped and removed.
027 *
028 * @author Tommy Becker
029 * @author Ceki Gulcu
030 * @author David Roussel
031 */
032public class AppenderTracker<E> extends AbstractComponentTracker<Appender<E>> {
033
034    int nopaWarningCount = 0;
035
036    final Context context;
037    final AppenderFactory<E> appenderFactory;
038    final ContextAwareImpl contextAware;
039
040    public AppenderTracker(Context context, AppenderFactory<E> appenderFactory) {
041        super();
042        this.context = context;
043        this.appenderFactory = appenderFactory;
044        this.contextAware = new ContextAwareImpl(context, this);
045    }
046
047    @Override
048    protected void processPriorToRemoval(Appender<E> component) {
049        component.stop();
050    }
051
052    @Override
053    protected Appender<E> buildComponent(String key) {
054        Appender<E> appender = null;
055        try {
056            appender = appenderFactory.buildAppender(context, key);
057        } catch (JoranException je) {
058            contextAware.addError("Error while building appender with discriminating value [" + key + "]");
059        }
060        if (appender == null) {
061            appender = buildNOPAppender(key);
062        }
063
064        return appender;
065    }
066
067    private NOPAppender<E> buildNOPAppender(String key) {
068        if (nopaWarningCount < CoreConstants.MAX_ERROR_COUNT) {
069            nopaWarningCount++;
070            contextAware.addError("Building NOPAppender for discriminating value [" + key + "]");
071        }
072        NOPAppender<E> nopa = new NOPAppender<E>();
073        nopa.setContext(context);
074        nopa.start();
075        return nopa;
076    }
077
078    @Override
079    protected boolean isComponentStale(Appender<E> appender) {
080        return !appender.isStarted();
081    }
082
083}