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 }