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.commons.discovery.log;
018
019 import java.io.PrintStream;
020 import java.text.DateFormat;
021 import java.text.SimpleDateFormat;
022 import java.util.Date;
023
024 import org.apache.commons.logging.Log;
025
026
027 /**
028 * <p>Simple implementation of Log that sends all enabled log messages,
029 * for all defined loggers, to System.err.
030 * </p>
031 *
032 * <p>Hacked from commons-logging SimpleLog for use in discovery.
033 * This is intended to be enough of a Log implementation to bootstrap
034 * Discovery.
035 * </p>
036 *
037 * <p>One property: <code>org.apache.commons.discovery.log.level</code>.
038 * valid values: all, trace, debug, info, warn, error, fatal, off.
039 * </p>
040 *
041 * @author Richard A. Sitze
042 * @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
043 * @author Rod Waldhoff
044 * @author Robert Burrell Donkin
045 *
046 * @version $Id: SimpleLog.java 480374 2006-11-29 03:33:25Z niallp $
047 */
048 public class SimpleLog implements Log {
049 // ---------------------------------------------------- Log Level Constants
050
051 /** "Trace" level logging. */
052 public static final int LOG_LEVEL_TRACE = 1;
053 /** "Debug" level logging. */
054 public static final int LOG_LEVEL_DEBUG = 2;
055 /** "Info" level logging. */
056 public static final int LOG_LEVEL_INFO = 3;
057 /** "Warn" level logging. */
058 public static final int LOG_LEVEL_WARN = 4;
059 /** "Error" level logging. */
060 public static final int LOG_LEVEL_ERROR = 5;
061 /** "Fatal" level logging. */
062 public static final int LOG_LEVEL_FATAL = 6;
063
064 /** Enable all logging levels */
065 public static final int LOG_LEVEL_ALL = (LOG_LEVEL_TRACE - 1);
066
067 /** Enable no logging levels */
068 public static final int LOG_LEVEL_OFF = (LOG_LEVEL_FATAL + 1);
069
070 // ------------------------------------------------------- Class Attributes
071
072 static protected final String PROP_LEVEL =
073 "org.apache.commons.discovery.log.level";
074
075 /** Include the instance name in the log message? */
076 static protected boolean showLogName = false;
077
078 /** Include the short name ( last component ) of the logger in the log
079 message. Default to true - otherwise we'll be lost in a flood of
080 messages without knowing who sends them.
081 */
082 static protected boolean showShortName = true;
083
084 /** Include the current time in the log message */
085 static protected boolean showDateTime = false;
086
087 /** Used to format times */
088 static protected DateFormat dateFormatter = null;
089
090 /** The current log level */
091 static protected int logLevel = LOG_LEVEL_INFO;
092
093
094 /**
095 * Use 'out' instead of 'err' for logging
096 * to keep in-sync with test messages.
097 */
098 static private PrintStream out = System.out;
099
100 // ------------------------------------------------------------ Initializer
101
102 // initialize class attributes
103 static {
104 if(showDateTime) {
105 dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS zzz");
106 }
107
108 try {
109 // set log level from properties
110 String lvl = System.getProperty(PROP_LEVEL);
111
112 if("all".equalsIgnoreCase(lvl)) {
113 setLevel(SimpleLog.LOG_LEVEL_ALL);
114 } else if("trace".equalsIgnoreCase(lvl)) {
115 setLevel(SimpleLog.LOG_LEVEL_TRACE);
116 } else if("debug".equalsIgnoreCase(lvl)) {
117 setLevel(SimpleLog.LOG_LEVEL_DEBUG);
118 } else if("info".equalsIgnoreCase(lvl)) {
119 setLevel(SimpleLog.LOG_LEVEL_INFO);
120 } else if("warn".equalsIgnoreCase(lvl)) {
121 setLevel(SimpleLog.LOG_LEVEL_WARN);
122 } else if("error".equalsIgnoreCase(lvl)) {
123 setLevel(SimpleLog.LOG_LEVEL_ERROR);
124 } else if("fatal".equalsIgnoreCase(lvl)) {
125 setLevel(SimpleLog.LOG_LEVEL_FATAL);
126 } else if("off".equalsIgnoreCase(lvl)) {
127 setLevel(SimpleLog.LOG_LEVEL_OFF);
128 }
129 } catch (SecurityException ignored) {
130 //do nothing. We get here if running discovery
131 //under a servlet with restricted security rights, and
132 //cannot read the system property.
133 //In which case, the default is what you get to keep.
134 }
135
136 }
137
138 // -------------------------------------------------------- Properties
139
140 /**
141 * <p> Set logging level. </p>
142 *
143 * @param currentLogLevel new logging level
144 */
145 public static void setLevel(int currentLogLevel) {
146 logLevel = currentLogLevel;
147 }
148
149 /**
150 * <p> Get logging level. </p>
151 */
152 public static int getLevel() {
153 return logLevel;
154 }
155
156 /**
157 * Is the given log level currently enabled?
158 *
159 * @param level is this level enabled?
160 */
161 protected static boolean isLevelEnabled(int level) {
162 // log level are numerically ordered so can use simple numeric
163 // comparison
164 return (level >= getLevel());
165 }
166
167
168
169 // ------------------------------------------------------------- Attributes
170
171 /** The name of this simple log instance */
172 protected String logName = null;
173
174 private String prefix=null;
175
176
177 // ------------------------------------------------------------ Constructor
178
179 /**
180 * Construct a simple log with given name.
181 *
182 * @param name log name
183 */
184 public SimpleLog(String name) {
185 logName = name;
186 }
187
188
189 // -------------------------------------------------------- Logging Methods
190
191
192 /**
193 * <p> Do the actual logging.
194 * This method assembles the message
195 * and then prints to <code>System.err</code>.</p>
196 */
197 protected void log(int type, Object message, Throwable t) {
198 // use a string buffer for better performance
199 StringBuffer buf = new StringBuffer();
200
201 // append date-time if so configured
202 if(showDateTime) {
203 buf.append(dateFormatter.format(new Date()));
204 buf.append(" ");
205 }
206
207 // append a readable representation of the log leve
208 switch(type) {
209 case SimpleLog.LOG_LEVEL_TRACE: buf.append("[TRACE] "); break;
210 case SimpleLog.LOG_LEVEL_DEBUG: buf.append("[DEBUG] "); break;
211 case SimpleLog.LOG_LEVEL_INFO: buf.append("[INFO ] "); break;
212 case SimpleLog.LOG_LEVEL_WARN: buf.append("[WARN ] "); break;
213 case SimpleLog.LOG_LEVEL_ERROR: buf.append("[ERROR] "); break;
214 case SimpleLog.LOG_LEVEL_FATAL: buf.append("[FATAL] "); break;
215 }
216
217 // append the name of the log instance if so configured
218 if( showShortName) {
219 if( prefix==null ) {
220 // cut all but the last component of the name for both styles
221 prefix = logName.substring( logName.lastIndexOf(".") +1) + " - ";
222 prefix = prefix.substring( prefix.lastIndexOf("/") +1) + "-";
223 }
224 buf.append( prefix );
225 } else if(showLogName) {
226 buf.append(String.valueOf(logName)).append(" - ");
227 }
228
229 // append the message
230 buf.append(String.valueOf(message));
231
232 // append stack trace if not null
233 if(t != null) {
234 buf.append(" <");
235 buf.append(t.toString());
236 buf.append(">");
237 }
238
239 // print to System.err
240 out.println(buf.toString());
241
242 if (t != null)
243 t.printStackTrace(System.err);
244 }
245
246
247 // -------------------------------------------------------- Log Implementation
248
249
250 /**
251 * <p> Log a message with debug log level.</p>
252 */
253 public final void debug(Object message) {
254 if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
255 log(SimpleLog.LOG_LEVEL_DEBUG, message, null);
256 }
257 }
258
259
260 /**
261 * <p> Log an error with debug log level.</p>
262 */
263 public final void debug(Object message, Throwable t) {
264 if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) {
265 log(SimpleLog.LOG_LEVEL_DEBUG, message, t);
266 }
267 }
268
269
270 /**
271 * <p> Log a message with debug log level.</p>
272 */
273 public final void trace(Object message) {
274 if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) {
275 log(SimpleLog.LOG_LEVEL_TRACE, message, null);
276 }
277 }
278
279
280 /**
281 * <p> Log an error with debug log level.</p>
282 */
283 public final void trace(Object message, Throwable t) {
284 if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) {
285 log(SimpleLog.LOG_LEVEL_TRACE, message, t);
286 }
287 }
288
289
290 /**
291 * <p> Log a message with info log level.</p>
292 */
293 public final void info(Object message) {
294 if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) {
295 log(SimpleLog.LOG_LEVEL_INFO,message,null);
296 }
297 }
298
299
300 /**
301 * <p> Log an error with info log level.</p>
302 */
303 public final void info(Object message, Throwable t) {
304 if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) {
305 log(SimpleLog.LOG_LEVEL_INFO, message, t);
306 }
307 }
308
309
310 /**
311 * <p> Log a message with warn log level.</p>
312 */
313 public final void warn(Object message) {
314 if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) {
315 log(SimpleLog.LOG_LEVEL_WARN, message, null);
316 }
317 }
318
319
320 /**
321 * <p> Log an error with warn log level.</p>
322 */
323 public final void warn(Object message, Throwable t) {
324 if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) {
325 log(SimpleLog.LOG_LEVEL_WARN, message, t);
326 }
327 }
328
329
330 /**
331 * <p> Log a message with error log level.</p>
332 */
333 public final void error(Object message) {
334 if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) {
335 log(SimpleLog.LOG_LEVEL_ERROR, message, null);
336 }
337 }
338
339
340 /**
341 * <p> Log an error with error log level.</p>
342 */
343 public final void error(Object message, Throwable t) {
344 if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) {
345 log(SimpleLog.LOG_LEVEL_ERROR, message, t);
346 }
347 }
348
349
350 /**
351 * <p> Log a message with fatal log level.</p>
352 */
353 public final void fatal(Object message) {
354 if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) {
355 log(SimpleLog.LOG_LEVEL_FATAL, message, null);
356 }
357 }
358
359
360 /**
361 * <p> Log an error with fatal log level.</p>
362 */
363 public final void fatal(Object message, Throwable t) {
364 if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) {
365 log(SimpleLog.LOG_LEVEL_FATAL, message, t);
366 }
367 }
368
369
370 /**
371 * <p> Are debug messages currently enabled? </p>
372 *
373 * <p> This allows expensive operations such as <code>String</code>
374 * concatenation to be avoided when the message will be ignored by the
375 * logger. </p>
376 */
377 public final boolean isDebugEnabled() {
378 return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG);
379 }
380
381
382 /**
383 * <p> Are error messages currently enabled? </p>
384 *
385 * <p> This allows expensive operations such as <code>String</code>
386 * concatenation to be avoided when the message will be ignored by the
387 * logger. </p>
388 */
389 public final boolean isErrorEnabled() {
390 return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR);
391 }
392
393
394 /**
395 * <p> Are fatal messages currently enabled? </p>
396 *
397 * <p> This allows expensive operations such as <code>String</code>
398 * concatenation to be avoided when the message will be ignored by the
399 * logger. </p>
400 */
401 public final boolean isFatalEnabled() {
402 return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL);
403 }
404
405
406 /**
407 * <p> Are info messages currently enabled? </p>
408 *
409 * <p> This allows expensive operations such as <code>String</code>
410 * concatenation to be avoided when the message will be ignored by the
411 * logger. </p>
412 */
413 public final boolean isInfoEnabled() {
414 return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO);
415 }
416
417
418 /**
419 * <p> Are trace messages currently enabled? </p>
420 *
421 * <p> This allows expensive operations such as <code>String</code>
422 * concatenation to be avoided when the message will be ignored by the
423 * logger. </p>
424 */
425 public final boolean isTraceEnabled() {
426 return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE);
427 }
428
429
430 /**
431 * <p> Are warn messages currently enabled? </p>
432 *
433 * <p> This allows expensive operations such as <code>String</code>
434 * concatenation to be avoided when the message will be ignored by the
435 * logger. </p>
436 */
437 public final boolean isWarnEnabled() {
438 return isLevelEnabled(SimpleLog.LOG_LEVEL_WARN);
439 }
440 }