    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     */
    017    package org.apache.logging.log4j.core.config;
    018
    019    import org.apache.logging.log4j.Level;
    020    import org.apache.logging.log4j.core.Appender;
    021    import org.apache.logging.log4j.core.Filter;
    022    import org.apache.logging.log4j.core.LogEvent;
    023    import org.apache.logging.log4j.core.appender.AppenderLoggingException;
    024    import org.apache.logging.log4j.core.filter.AbstractFilterable;
    025    import 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     */
    030    public 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 Exception ex) {
    106                    appender.getHandler().error("An exception occurred processing Appender " + appender.getName(), ex);
    107                    if (!appender.ignoreExceptions()) {
    108                        throw new AppenderLoggingException(ex);
    109                    }
    110                }
    111            } finally {
    112                recursive.set(null);
    113            }
    114        }
    115
    116    }