1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache license, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the license for the specific language governing permissions and
15 * limitations under the license.
16 */
17 package org.apache.logging.log4j.core.appender;
18
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.Appender;
21 import org.apache.logging.log4j.core.ErrorHandler;
22 import org.apache.logging.log4j.core.Filter;
23 import org.apache.logging.log4j.core.Layout;
24 import org.apache.logging.log4j.core.LifeCycle;
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.filter.AbstractFilterable;
27 import org.apache.logging.log4j.status.StatusLogger;
28
29 import java.io.Serializable;
30
31 /**
32 * Abstract base class for Appenders. Although Appenders do not have to extend this class, doing so
33 * will simplify their implementation.
34 *
35 * @param <T> The {@link Layout}'s {@link Serializable} type.
36 */
37 public abstract class AbstractAppender<T extends Serializable> extends AbstractFilterable
38 implements Appender<T>, LifeCycle {
39 /**
40 * Allow subclasses access to the status logger without creating another instance.
41 */
42 protected static final Logger LOGGER = StatusLogger.getLogger();
43
44 /**
45 * Appenders set this by calling super.start().
46 */
47 private boolean started = false;
48
49 private final Layout<T> layout;
50
51 private final String name;
52
53 private final boolean handleException;
54
55 private ErrorHandler handler = new DefaultErrorHandler(this);
56
57 /**
58 * Constructor that defaults to suppressing exceptions.
59 * @param name The Appender name.
60 * @param filter The Filter to associate with the Appender.
61 * @param layout The layout to use to format the event.
62 */
63 protected AbstractAppender(final String name, final Filter filter, final Layout<T> layout) {
64 this(name, filter, layout, true);
65 }
66
67 /**
68 * Constructor.
69 * @param name The Appender name.
70 * @param filter The Filter to associate with the Appender.
71 * @param layout The layout to use to format the event.
72 * @param handleException If true, exceptions will be logged and suppressed. If false errors will be
73 * logged and then passed to the application.
74 */
75 protected AbstractAppender(final String name, final Filter filter, final Layout<T> layout,
76 final boolean handleException) {
77 super(filter);
78 this.name = name;
79 this.layout = layout;
80 this.handleException = handleException;
81 }
82
83 /**
84 * Returns the ErrorHandler, if any.
85 * @return The ErrorHandler.
86 */
87 @Override
88 public ErrorHandler getHandler() {
89 return handler;
90 }
91
92 /**
93 * The handler must be set before the appender is started.
94 * @param handler The ErrorHandler to use.
95 */
96 @Override
97 public void setHandler(final ErrorHandler handler) {
98 if (handler == null) {
99 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 * Close the stream associated with the Appender.
110 */
111 public void close() {
112
113 }
114
115 /**
116 * Returns the name of the Appender.
117 * @return The name of the Appender.
118 */
119 @Override
120 public String getName() {
121 return name;
122 }
123
124 /**
125 * Returns the Layout for the appender.
126 * @return The Layout used to format the event.
127 */
128 @Override
129 public Layout<T> getLayout() {
130 return layout;
131 }
132
133 /**
134 * Some appenders need to propagate exceptions back to the application. When suppressException is false the
135 * AppenderControl will allow the exception to percolate.
136 * @return true if exceptions will be suppressed, false otherwise.
137 */
138 @Override
139 public boolean isExceptionSuppressed() {
140 return handleException;
141 }
142
143 /**
144 * Start the Appender.
145 */
146 @Override
147 public void start() {
148 startFilter();
149 this.started = true;
150 }
151
152 /**
153 * Stop the Appender.
154 */
155 @Override
156 public void stop() {
157 this.started = false;
158 stopFilter();
159 }
160
161 /**
162 * Returns true if the Appender is started, false otherwise.
163 * @return true if the Appender is started, false otherwise.
164 */
165 @Override
166 public boolean isStarted() {
167 return started;
168 }
169
170 @Override
171 public String toString() {
172 return name;
173 }
174
175 /**
176 * Handle an error with a message.
177 * @param msg The message.
178 */
179 public void error(final String msg) {
180 handler.error(msg);
181 }
182
183 /**
184 * Handle an error with a message and an exception.
185 * @param msg The message.
186 * @param t The Throwable.
187 */
188 public void error(final String msg, final Throwable t) {
189 handler.error(msg, t);
190 }
191
192 /**
193 * Handle an error with a message, and exception and a logging event.
194 * @param msg The message.
195 * @param event The LogEvent.
196 * @param t The Throwable.
197 */
198 public void error(final String msg, final LogEvent event, final Throwable t) {
199 handler.error(msg, event, t);
200 }
201
202 }