001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.core.config;
018
019import org.apache.logging.log4j.Level;
020import org.apache.logging.log4j.core.Appender;
021import org.apache.logging.log4j.core.Filter;
022import org.apache.logging.log4j.core.LogEvent;
023import org.apache.logging.log4j.core.appender.AppenderLoggingException;
024import org.apache.logging.log4j.core.filter.AbstractFilterable;
025import org.apache.logging.log4j.core.filter.Filterable;
026
027/**
028 * Wraps an {@link Appender} with details an appender implementation shouldn't need to know about.
029 */
030public class AppenderControl extends AbstractFilterable {
031
032    private final ThreadLocal<AppenderControl> recursive = new ThreadLocal<AppenderControl>();
033
034    private final Appender appender;
035
036    private final Level level;
037
038    private final int intLevel;
039
040    /**
041     * Constructor.
042     * @param appender The target Appender.
043     * @param level the Level to filter on.
044     * @param filter the Filter(s) to apply.
045     */
046    public AppenderControl(final Appender appender, final Level level, final Filter filter) {
047        super(filter);
048        this.appender = appender;
049        this.level = level;
050        this.intLevel = level == null ? Level.ALL.intLevel() : level.intLevel();
051        start();
052    }
053
054    /**
055     * Returns the Appender.
056     * @return the Appender.
057     */
058    public Appender getAppender() {
059        return appender;
060    }
061
062    /**
063     * Call the appender.
064     * @param event The event to process.
065     */
066    public void callAppender(final LogEvent event) {
067        if (getFilter() != null) {
068            final Filter.Result r = getFilter().filter(event);
069            if (r == Filter.Result.DENY) {
070                return;
071            }
072        }
073        if (level != null && intLevel < event.getLevel().intLevel()) {
074            return;
075        }
076        if (recursive.get() != null) {
077            appender.getHandler().error("Recursive call to appender " + appender.getName());
078            return;
079        }
080        try {
081            recursive.set(this);
082
083            if (!appender.isStarted()) {
084                appender.getHandler().error("Attempted to append to non-started appender " + appender.getName());
085
086                if (!appender.ignoreExceptions()) {
087                    throw new AppenderLoggingException(
088                        "Attempted to append to non-started appender " + appender.getName());
089                }
090            }
091
092            if (appender instanceof Filterable && ((Filterable) appender).isFiltered(event)) {
093                return;
094            }
095
096            try {
097                appender.append(event);
098            } catch (final RuntimeException ex) {
099                appender.getHandler().error("An exception occurred processing Appender " + appender.getName(), ex);
100                if (!appender.ignoreExceptions()) {
101                    throw ex;
102                }
103            } catch (final Exception ex) {
104                appender.getHandler().error("An exception occurred processing Appender " + appender.getName(), ex);
105                if (!appender.ignoreExceptions()) {
106                    throw new AppenderLoggingException(ex);
107                }
108            }
109        } finally {
110            recursive.set(null);
111        }
112    }
113
114}