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 static final long serialVersionUID = 1L;
033
034    private final ThreadLocal<AppenderControl> recursive = new ThreadLocal<AppenderControl>();
035
036    private final Appender appender;
037
038    private final Level level;
039
040    private final int intLevel;
041
042    /**
043     * Constructor.
044     * @param appender The target Appender.
045     * @param level the Level to filter on.
046     * @param filter the Filter(s) to apply.
047     */
048    public AppenderControl(final Appender appender, final Level level, final Filter filter) {
049        super(filter);
050        this.appender = appender;
051        this.level = level;
052        this.intLevel = level == null ? Level.ALL.intLevel() : level.intLevel();
053        start();
054    }
055
056    /**
057     * Returns the Appender.
058     * @return the Appender.
059     */
060    public Appender getAppender() {
061        return appender;
062    }
063
064    /**
065     * Call the appender.
066     * @param event The event to process.
067     */
068    public void callAppender(final LogEvent event) {
069        if (getFilter() != null) {
070            final Filter.Result r = getFilter().filter(event);
071            if (r == Filter.Result.DENY) {
072                return;
073            }
074        }
075        if (level != null && intLevel < event.getLevel().intLevel()) {
076            return;
077        }
078        if (recursive.get() != null) {
079            appender.getHandler().error("Recursive call to appender " + appender.getName());
080            return;
081        }
082        try {
083            recursive.set(this);
084
085            if (!appender.isStarted()) {
086                appender.getHandler().error("Attempted to append to non-started appender " + appender.getName());
087
088                if (!appender.ignoreExceptions()) {
089                    throw new AppenderLoggingException(
090                        "Attempted to append to non-started appender " + appender.getName());
091                }
092            }
093
094            if (appender instanceof Filterable && ((Filterable) appender).isFiltered(event)) {
095                return;
096            }
097
098            try {
099                appender.append(event);
100            } catch (final RuntimeException ex) {
101                appender.getHandler().error("An exception occurred processing Appender " + appender.getName(), ex);
102                if (!appender.ignoreExceptions()) {
103                    throw ex;
104                }
105            } catch (final Throwable t) {
106                appender.getHandler().error("An exception occurred processing Appender " + appender.getName(), t);
107                if (!appender.ignoreExceptions()) {
108                    throw new AppenderLoggingException(t);
109                }
110            }
111        } finally {
112            recursive.set(null);
113        }
114    }
115
116}