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.appender; 018 019 import java.io.Serializable; 020 021 import org.apache.logging.log4j.Logger; 022 import org.apache.logging.log4j.core.Appender; 023 import org.apache.logging.log4j.core.ErrorHandler; 024 import org.apache.logging.log4j.core.Filter; 025 import org.apache.logging.log4j.core.Layout; 026 import org.apache.logging.log4j.core.LifeCycle; 027 import org.apache.logging.log4j.core.LogEvent; 028 import org.apache.logging.log4j.core.filter.AbstractFilterable; 029 import org.apache.logging.log4j.status.StatusLogger; 030 031 /** 032 * Abstract base class for Appenders. Although Appenders do not have to extend this class, doing so 033 * will simplify their implementation. 034 * 035 * @param <T> The {@link Layout}'s {@link Serializable} type. 036 */ 037 public abstract class AbstractAppender<T extends Serializable> extends AbstractFilterable 038 implements Appender<T>, LifeCycle { 039 /** 040 * Allow subclasses access to the status logger without creating another instance. 041 */ 042 protected static final Logger LOGGER = StatusLogger.getLogger(); 043 044 /** 045 * Appenders set this by calling super.start(). 046 */ 047 private boolean started = false; 048 049 private final Layout<T> layout; 050 051 private final String name; 052 053 private final boolean handleException; 054 055 private ErrorHandler handler = new DefaultErrorHandler(this); 056 057 /** 058 * Constructor that defaults to suppressing exceptions. 059 * @param name The Appender name. 060 * @param filter The Filter to associate with the Appender. 061 * @param layout The layout to use to format the event. 062 */ 063 protected AbstractAppender(final String name, final Filter filter, final Layout<T> layout) { 064 this(name, filter, layout, true); 065 } 066 067 /** 068 * Constructor. 069 * @param name The Appender name. 070 * @param filter The Filter to associate with the Appender. 071 * @param layout The layout to use to format the event. 072 * @param handleException If true, exceptions will be logged and suppressed. If false errors will be 073 * logged and then passed to the application. 074 */ 075 protected AbstractAppender(final String name, final Filter filter, final Layout<T> layout, 076 final boolean handleException) { 077 super(filter); 078 this.name = name; 079 this.layout = layout; 080 this.handleException = handleException; 081 } 082 083 /** 084 * Returns the ErrorHandler, if any. 085 * @return The ErrorHandler. 086 */ 087 @Override 088 public ErrorHandler getHandler() { 089 return handler; 090 } 091 092 /** 093 * The handler must be set before the appender is started. 094 * @param handler The ErrorHandler to use. 095 */ 096 @Override 097 public void setHandler(final ErrorHandler handler) { 098 if (handler == null) { 099 LOGGER.error("The handler cannot be set to null"); 100 } 101 if (isStarted()) { 102 LOGGER.error("The handler cannot be changed once the appender is started"); 103 return; 104 } 105 this.handler = handler; 106 } 107 108 /** 109 * Returns the name of the Appender. 110 * @return The name of the Appender. 111 */ 112 @Override 113 public String getName() { 114 return name; 115 } 116 117 /** 118 * Returns the Layout for the appender. 119 * @return The Layout used to format the event. 120 */ 121 @Override 122 public Layout<T> getLayout() { 123 return layout; 124 } 125 126 /** 127 * Some appenders need to propagate exceptions back to the application. When suppressException is false the 128 * AppenderControl will allow the exception to percolate. 129 * @return true if exceptions will be suppressed, false otherwise. 130 */ 131 @Override 132 public boolean isExceptionSuppressed() { 133 return handleException; 134 } 135 136 /** 137 * Start the Appender. 138 */ 139 @Override 140 public void start() { 141 startFilter(); 142 this.started = true; 143 } 144 145 /** 146 * Stop the Appender. 147 */ 148 @Override 149 public void stop() { 150 this.started = false; 151 stopFilter(); 152 } 153 154 /** 155 * Returns true if the Appender is started, false otherwise. 156 * @return true if the Appender is started, false otherwise. 157 */ 158 @Override 159 public boolean isStarted() { 160 return started; 161 } 162 163 @Override 164 public String toString() { 165 return name; 166 } 167 168 /** 169 * Handle an error with a message. 170 * @param msg The message. 171 */ 172 public void error(final String msg) { 173 handler.error(msg); 174 } 175 176 /** 177 * Handle an error with a message and an exception. 178 * @param msg The message. 179 * @param t The Throwable. 180 */ 181 public void error(final String msg, final Throwable t) { 182 handler.error(msg, t); 183 } 184 185 /** 186 * Handle an error with a message, and exception and a logging event. 187 * @param msg The message. 188 * @param event The LogEvent. 189 * @param t The Throwable. 190 */ 191 public void error(final String msg, final LogEvent event, final Throwable t) { 192 handler.error(msg, event, t); 193 } 194 195 }