View Javadoc

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 }