001 /* ========================================================================
002 * JCommon : a free general purpose class library for the Java(tm) platform
003 * ========================================================================
004 *
005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jcommon/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * --------
028 * Log.java
029 * --------
030 * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
031 *
032 * Original Author: Thomas Morgner (taquera@sherito.org);
033 * Contributor(s): David Gilbert (for Object Refinery Limited);
034 *
035 * $Id: Log.java,v 1.5 2006/06/08 17:42:20 taqua Exp $
036 *
037 * Changes
038 * -------
039 * 29-Apr-2003 : Distilled from the JFreeReport project and moved into JCommon
040 * 11-Jun-2003 : Removing LogTarget did not work.
041 *
042 */
043
044 package org.jfree.util;
045
046 import java.util.ArrayList;
047 import java.util.Arrays;
048 import java.util.HashMap;
049
050 /**
051 * A simple logging facility. Create a class implementing the {@link org.jfree.util.LogTarget}
052 * interface to use this feature.
053 *
054 * @author Thomas Morgner
055 */
056 public class Log {
057
058 /**
059 * A simple message class.
060 */
061 public static class SimpleMessage {
062
063 /**
064 * The message.
065 */
066 private String message;
067
068 /**
069 * The parameters.
070 */
071 private Object[] param;
072
073 /**
074 * Creates a new message.
075 *
076 * @param message the message text.
077 * @param param1 parameter 1.
078 */
079 public SimpleMessage(final String message, final Object param1) {
080 this.message = message;
081 this.param = new Object[]{param1};
082 }
083
084 /**
085 * Creates a new message.
086 *
087 * @param message the message text.
088 * @param param1 parameter 1.
089 * @param param2 parameter 2.
090 */
091 public SimpleMessage(final String message, final Object param1,
092 final Object param2) {
093 this.message = message;
094 this.param = new Object[]{param1, param2};
095 }
096
097 /**
098 * Creates a new message.
099 *
100 * @param message the message text.
101 * @param param1 parameter 1.
102 * @param param2 parameter 2.
103 * @param param3 parameter 3.
104 */
105 public SimpleMessage(final String message, final Object param1,
106 final Object param2, final Object param3) {
107 this.message = message;
108 this.param = new Object[]{param1, param2, param3};
109 }
110
111 /**
112 * Creates a new message.
113 *
114 * @param message the message text.
115 * @param param1 parameter 1.
116 * @param param2 parameter 2.
117 * @param param3 parameter 3.
118 * @param param4 parameter 4.
119 */
120 public SimpleMessage(final String message, final Object param1,
121 final Object param2, final Object param3,
122 final Object param4) {
123 this.message = message;
124 this.param = new Object[]{param1, param2, param3, param4};
125 }
126
127 /**
128 * Creates a new message.
129 *
130 * @param message the message text.
131 * @param param the parameters.
132 */
133 public SimpleMessage(final String message, final Object[] param) {
134 this.message = message;
135 this.param = param;
136 }
137
138 /**
139 * Returns a string representation of the message (useful for debugging).
140 *
141 * @return the string.
142 */
143 public String toString() {
144 final StringBuffer b = new StringBuffer();
145 b.append(this.message);
146 if (this.param != null) {
147 for (int i = 0; i < this.param.length; i++) {
148 b.append(this.param[i]);
149 }
150 }
151 return b.toString();
152 }
153 }
154
155
156 /**
157 * The logging threshold.
158 */
159 private int debuglevel;
160
161 /**
162 * Storage for the log targets.
163 */
164 private LogTarget[] logTargets;
165
166 /** The log contexts. */
167 private HashMap logContexts;
168
169 /**
170 * the singleton instance of the Log system.
171 */
172 private static Log singleton;
173
174 /**
175 * Creates a new Log instance. The Log is used to manage the log targets.
176 */
177 protected Log() {
178 this.logContexts = new HashMap();
179 this.logTargets = new LogTarget[0];
180 this.debuglevel = 100;
181 }
182
183 /**
184 * Returns the singleton Log instance. A new instance is created if necessary.
185 *
186 * @return the singleton instance.
187 */
188 public static synchronized Log getInstance() {
189 if (singleton == null) {
190 singleton = new Log();
191 }
192 return singleton;
193 }
194
195 /**
196 * Redefines or clears the currently used log instance.
197 *
198 * @param log the new log instance or null, to return to the default implementation.
199 */
200 protected static synchronized void defineLog(final Log log) {
201 singleton = log;
202 }
203
204 /**
205 * Returns the currently defined debug level. The higher the level, the more details
206 * are printed.
207 *
208 * @return the debug level.
209 */
210 public int getDebuglevel() {
211 return this.debuglevel;
212 }
213
214 /**
215 * Defines the debug level for the log system.
216 *
217 * @param debuglevel the new debug level
218 * @see #getDebuglevel()
219 */
220 protected void setDebuglevel(final int debuglevel) {
221 this.debuglevel = debuglevel;
222 }
223
224 /**
225 * Adds a log target to this facility. Log targets get informed, via the LogTarget interface,
226 * whenever a message is logged with this class.
227 *
228 * @param target the target.
229 */
230 public synchronized void addTarget(final LogTarget target) {
231 if (target == null) {
232 throw new NullPointerException();
233 }
234 final LogTarget[] data = new LogTarget[this.logTargets.length + 1];
235 System.arraycopy(this.logTargets, 0, data, 0, this.logTargets.length);
236 data[this.logTargets.length] = target;
237 this.logTargets = data;
238 }
239
240 /**
241 * Removes a log target from this facility.
242 *
243 * @param target the target to remove.
244 */
245 public synchronized void removeTarget(final LogTarget target) {
246 if (target == null) {
247 throw new NullPointerException();
248 }
249 final ArrayList l = new ArrayList();
250 l.addAll(Arrays.asList(this.logTargets));
251 l.remove(target);
252
253 final LogTarget[] targets = new LogTarget[l.size()];
254 this.logTargets = (LogTarget[]) l.toArray(targets);
255 }
256
257 /**
258 * Returns the registered logtargets.
259 *
260 * @return the logtargets.
261 */
262 public LogTarget[] getTargets() {
263 return (LogTarget[]) this.logTargets.clone();
264 }
265
266 /**
267 * Replaces all log targets by the given target.
268 *
269 * @param target the new and only logtarget.
270 */
271 public synchronized void replaceTargets(final LogTarget target) {
272 if (target == null) {
273 throw new NullPointerException();
274 }
275 this.logTargets = new LogTarget[]{target};
276 }
277
278 /**
279 * A convenience method for logging a 'debug' message.
280 *
281 * @param message the message.
282 */
283 public static void debug(final Object message) {
284 log(LogTarget.DEBUG, message);
285 }
286
287 /**
288 * A convenience method for logging a 'debug' message.
289 *
290 * @param message the message.
291 * @param e the exception.
292 */
293 public static void debug(final Object message, final Exception e) {
294 log(LogTarget.DEBUG, message, e);
295 }
296
297 /**
298 * A convenience method for logging an 'info' message.
299 *
300 * @param message the message.
301 */
302 public static void info(final Object message) {
303 log(LogTarget.INFO, message);
304 }
305
306 /**
307 * A convenience method for logging an 'info' message.
308 *
309 * @param message the message.
310 * @param e the exception.
311 */
312 public static void info(final Object message, final Exception e) {
313 log(LogTarget.INFO, message, e);
314 }
315
316 /**
317 * A convenience method for logging a 'warning' message.
318 *
319 * @param message the message.
320 */
321 public static void warn(final Object message) {
322 log(LogTarget.WARN, message);
323 }
324
325 /**
326 * A convenience method for logging a 'warning' message.
327 *
328 * @param message the message.
329 * @param e the exception.
330 */
331 public static void warn(final Object message, final Exception e) {
332 log(LogTarget.WARN, message, e);
333 }
334
335 /**
336 * A convenience method for logging an 'error' message.
337 *
338 * @param message the message.
339 */
340 public static void error(final Object message) {
341 log(LogTarget.ERROR, message);
342 }
343
344 /**
345 * A convenience method for logging an 'error' message.
346 *
347 * @param message the message.
348 * @param e the exception.
349 */
350 public static void error(final Object message, final Exception e) {
351 log(LogTarget.ERROR, message, e);
352 }
353
354 /**
355 * Logs a message to the main log stream. All attached log targets will also
356 * receive this message. If the given log-level is higher than the given debug-level
357 * in the main config file, no logging will be done.
358 *
359 * @param level log level of the message.
360 * @param message text to be logged.
361 */
362 protected void doLog(int level, final Object message) {
363 if (level > 3) {
364 level = 3;
365 }
366 if (level <= this.debuglevel) {
367 for (int i = 0; i < this.logTargets.length; i++) {
368 final LogTarget t = this.logTargets[i];
369 t.log(level, message);
370 }
371 }
372 }
373
374 /**
375 * Logs a message to the main log stream. All attached log targets will also
376 * receive this message. If the given log-level is higher than the given debug-level
377 * in the main config file, no logging will be done.
378 *
379 * @param level log level of the message.
380 * @param message text to be logged.
381 */
382 public static void log(final int level, final Object message) {
383 getInstance().doLog(level, message);
384 }
385
386 /**
387 * Logs a message to the main log stream. All attached logTargets will also
388 * receive this message. If the given log-level is higher than the given debug-level
389 * in the main config file, no logging will be done.
390 * <p/>
391 * The exception's stacktrace will be appended to the log-stream
392 *
393 * @param level log level of the message.
394 * @param message text to be logged.
395 * @param e the exception, which should be logged.
396 */
397 public static void log(final int level, final Object message, final Exception e) {
398 getInstance().doLog(level, message, e);
399 }
400
401 /**
402 * Logs a message to the main log stream. All attached logTargets will also
403 * receive this message. If the given log-level is higher than the given debug-level
404 * in the main config file, no logging will be done.
405 * <p/>
406 * The exception's stacktrace will be appended to the log-stream
407 *
408 * @param level log level of the message.
409 * @param message text to be logged.
410 * @param e the exception, which should be logged.
411 */
412 protected void doLog(int level, final Object message, final Exception e) {
413 if (level > 3) {
414 level = 3;
415 }
416
417 if (level <= this.debuglevel) {
418 for (int i = 0; i < this.logTargets.length; i++) {
419 final LogTarget t = this.logTargets[i];
420 t.log(level, message, e);
421 }
422 }
423 }
424
425 /**
426 * Initializes the logging system. Implementors should
427 * override this method to supply their own log configuration.
428 */
429 public void init() {
430 // this method is intentionally empty.
431 }
432
433 /**
434 * Returns true, if the log level allows debug messages to be
435 * printed.
436 *
437 * @return true, if messages with an log level of DEBUG are allowed.
438 */
439 public static boolean isDebugEnabled() {
440 return getInstance().getDebuglevel() >= LogTarget.DEBUG;
441 }
442
443 /**
444 * Returns true, if the log level allows informational
445 * messages to be printed.
446 *
447 * @return true, if messages with an log level of INFO are allowed.
448 */
449 public static boolean isInfoEnabled() {
450 return getInstance().getDebuglevel() >= LogTarget.INFO;
451 }
452
453 /**
454 * Returns true, if the log level allows warning messages to be
455 * printed.
456 *
457 * @return true, if messages with an log level of WARN are allowed.
458 */
459 public static boolean isWarningEnabled() {
460 return getInstance().getDebuglevel() >= LogTarget.WARN;
461 }
462
463 /**
464 * Returns true, if the log level allows error messages to be
465 * printed.
466 *
467 * @return true, if messages with an log level of ERROR are allowed.
468 */
469 public static boolean isErrorEnabled() {
470 return getInstance().getDebuglevel() >= LogTarget.ERROR;
471 }
472
473 /**
474 * Creates a log context.
475 *
476 * @param context the class (<code>null</code> not permitted).
477 *
478 * @return A log context.
479 */
480 public static LogContext createContext(final Class context) {
481 return createContext(context.getName());
482 }
483
484 /**
485 * Creates a log context.
486 *
487 * @param context the label for the context.
488 *
489 * @return A log context.
490 */
491 public static LogContext createContext(final String context) {
492 return getInstance().internalCreateContext(context);
493 }
494
495 /**
496 * Creates a log context.
497 *
498 * @param context the name of the logging context (a common prefix).
499 *
500 * @return A log context.
501 */
502 protected LogContext internalCreateContext(final String context) {
503 synchronized (this) {
504 LogContext ctx = (LogContext) this.logContexts.get(context);
505 if (ctx == null) {
506 ctx = new LogContext(context);
507 this.logContexts.put(context, ctx);
508 }
509 return ctx;
510 }
511 }
512
513 }