1 /*
2 * This file is part of AceLogger.
3 *
4 * AceLogger is free software: you can redistribute it and/or modify it under the terms of the GNU
5 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
6 * the License, or (at your option) any later version.
7 *
8 * AceLogger is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public License along with AceLogger.
13 * If not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
14 */
15 package net.sourceforge.acelogger.appender;
16
17 import net.sourceforge.acelogger.LogEvent;
18 import net.sourceforge.acelogger.constants.ExecutorManagerConstants;
19 import net.sourceforge.acelogger.constants.FormatterConstants;
20 import net.sourceforge.acelogger.constants.LevelFilterConstants;
21 import net.sourceforge.acelogger.execution.LogController;
22 import net.sourceforge.acelogger.execution.manager.ExecutorManager;
23 import net.sourceforge.acelogger.formatter.Formatter;
24 import net.sourceforge.acelogger.level.filter.LevelFilter;
25
26 /**
27 * Abstracts all common tasks for {@link Appender}.
28 *
29 * @author Zardi (https://sourceforge.net/users/daniel_zardi)
30 * @version 1.0.0
31 * @since 1.0.0
32 */
33 public abstract class BaseAppender implements Appender {
34
35 /**
36 * The formatter to be used within this appender.
37 */
38 private Formatter formatter;
39
40 /**
41 * The level filter used within this appender.
42 */
43 private LevelFilter threshold;
44
45 /**
46 * The identifier of this appender.
47 */
48 private String identifier;
49
50 /**
51 * The executor that will be used to format and append log calls.
52 */
53 private ExecutorManager executor;
54
55 /**
56 * Constructs a new BaseAppender using the supplied identifier, an empty formatter, and an empty
57 * executor manager.
58 *
59 * @param identifier
60 * A string that identifies this appender.
61 * @since 1.0.0
62 */
63 public BaseAppender(String identifier) {
64 this(identifier, FormatterConstants.EMPTY, ExecutorManagerConstants.EMPTY);
65 }
66
67 /**
68 * Constructs a new BaseAppender using the supplied identifier, formatter, and executor manager.
69 *
70 * @param identifier
71 * A string that identifies this appender.
72 * @param formatter
73 * The {@link Formatter} that will be used within this appender.
74 * @param executor
75 * The {@link ExecutorManager} that will be used within this appender.
76 * @since 1.0.0
77 */
78 public BaseAppender(String identifier, Formatter formatter, ExecutorManager executor) {
79 this(identifier, formatter, executor, LevelFilterConstants.ACCEPT_ALL);
80 }
81
82 /**
83 * Constructs a new BaseAppender using the supplied identifier, formatter, and executor manager.
84 *
85 * @param identifier
86 * A string that identifies this appender.
87 * @param formatter
88 * The {@link Formatter} that will be used within this appender.
89 * @param executor
90 * The {@link ExecutorManager} that will be used within this appender.
91 * @param threshold
92 * The filter used to determine if the call should be appended or not.
93 * @since 1.0.0
94 */
95 public BaseAppender(String identifier, Formatter formatter, ExecutorManager executor,
96 LevelFilter threshold) {
97 setIdentifier(identifier);
98 setFormatter(formatter);
99 setExecutor(executor);
100 setThreshold(threshold);
101 }
102
103 /**
104 * Defines the process used to append a log call.
105 *
106 * @param call
107 * The call that will be logged.
108 * @return A Runnable indicating the process used to log this call.
109 * @since 1.0.0
110 */
111 protected abstract Runnable appendLogProcess(LogEvent call);
112
113 /**
114 * Defines the process used to append a header to this appender.
115 *
116 * @return A Runnable indicating the process used to append a header.
117 * @since 1.0.0
118 */
119 protected Runnable appendHeaderProcess() { // NOPMD
120 // REMARK: This mean that no header will be present.
121 return null;
122 }
123
124 /**
125 * Defines the process used to append a footer to this appender.
126 *
127 * @return A Runnable indicating the process used to append a footer.
128 * @since 1.0.0
129 */
130 protected Runnable appendFooterProcess() { // NOPMD
131 // REMARK: This mean that no footer will be present.
132 return null;
133 }
134
135 /**
136 * Defines the process used to open this appender. This may include allocation and preparation
137 * of resources.
138 *
139 * @return A Runnable indicating the process used to open this appender.
140 * @since 1.0.0
141 */
142 protected Runnable openProcess() { // NOPMD
143 // REMARK: This means that should not be done on appender creation.
144 return null;
145 }
146
147 /**
148 * Defines the process used to close this appender. This may include termination and
149 * deallocation of resources.
150 *
151 * @return A Runnable indicating the process used to close this appender.
152 * @since 1.0.0
153 */
154 protected Runnable closeProcess() { // NOPMD
155 // REMARK: This means that should not be done on appender creation.
156 return null;
157 }
158
159 /**
160 * This method is responsible for calling the needed methods after the Appender construction,
161 * this includes opening, appending the header, and registering the call to append the footer
162 * and close the file.
163 *
164 * @since 1.0.0
165 */
166 protected final void initialize() {
167 open();
168 appendHeader();
169 /*
170 * FIXME: Hold a reference to this task, so we can cancel it before shutdown (this is needed
171 * to create rolling appenders).
172 */
173 LogController.submitShutdownTask(new Runnable() {
174 /**
175 * Appends the footer end closes the given appender.
176 */
177 public void run() {
178 /*
179 * FIXME: Create a method to append the footer, close the appender and remove the
180 * task from the shutdown process.
181 */
182 appendFooter();
183 close();
184 }
185 });
186 }
187
188 /** {@inheritDoc} */
189 public final void appendFooter() {
190 if (appendFooterProcess() != null) {
191 getExecutor().execute(appendFooterProcess());
192 }
193 }
194
195 /** {@inheritDoc} */
196 public final void appendHeader() {
197 if (appendHeaderProcess() != null) {
198 getExecutor().execute(appendHeaderProcess());
199 }
200 }
201
202 /** {@inheritDoc} */
203 public final void close() {
204 if (closeProcess() != null) {
205 getExecutor().execute(closeProcess());
206 }
207 }
208
209 /** {@inheritDoc} */
210 public final void open() {
211 if (openProcess() != null) {
212 getExecutor().execute(openProcess());
213 }
214 }
215
216 /** {@inheritDoc} */
217 public final void appendLog(LogEvent call) {
218 if (threshold.isSuitable(call.getLevel())) {
219 getExecutor().execute(appendLogProcess(call));
220 }
221 }
222
223 /**
224 * Returns the formatter used within this appender.
225 *
226 * @return The {@link Formatter} used within this appender.
227 * @since 1.0.0
228 */
229 public final Formatter getFormatter() {
230 return formatter;
231 }
232
233 /**
234 * Sets the formatter used within this appender.
235 *
236 * @param formatter
237 * The {@link Formatter} that will be used within this appender.
238 * @since 1.0.0
239 */
240 private void setFormatter(Formatter formatter) {
241 if (formatter == null) {
242 this.formatter = FormatterConstants.EMPTY;
243 } else {
244 this.formatter = formatter;
245 }
246 }
247
248 /**
249 * Gets the threshold of this appender.
250 *
251 * @return The filter used to determine if the call should be appended or not.
252 */
253 public final LevelFilter getThreshold() {
254 return threshold;
255 }
256
257 /**
258 * Sets the threshold of this appender.
259 *
260 * @param threshold
261 * The filter used to determine if the call should be appended or not.
262 */
263 public final void setThreshold(LevelFilter threshold) {
264 this.threshold = threshold;
265 }
266
267 /**
268 * Sets the executor manager used within this appender.
269 *
270 * @return The {@link ExecutorManager} used within this appender.
271 * @since 1.0.0
272 */
273 public final ExecutorManager getExecutor() {
274 return executor;
275 }
276
277 /**
278 * Sets the executor manager used within this appender.
279 *
280 * @param executor
281 * The {@link ExecutorManager} that will be used within this appender.
282 * @since 1.0.0
283 */
284 private void setExecutor(ExecutorManager executor) {
285 if (executor == null) {
286 this.executor = ExecutorManagerConstants.EMPTY;
287 } else {
288 this.executor = executor;
289 }
290 }
291
292 /** {@inheritDoc} */
293 public final String getIdentifier() {
294 return identifier;
295 }
296
297 /**
298 * Sets the string that identifies this object.
299 *
300 * @param identifier
301 * The identifier of this object.
302 * @since 1.0.0
303 */
304 private void setIdentifier(String identifier) {
305 if (identifier == null) {
306 this.identifier = "";
307 } else {
308 this.identifier = identifier;
309 }
310 }
311
312 /**
313 * Formats a log call based on the {@link Formatter} used by this appender.
314 *
315 * @param call
316 * The log call to be formatted.
317 * @return A string containing the formatted log call.
318 * @since 1.0.0
319 */
320 protected final String formatLogCall(LogEvent call) {
321 return formatter.formatLogCall(call);
322 }
323
324 }