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 }