001 /* 002 * JBoss, Home of Professional Open Source. 003 * Copyright 2008, Red Hat Middleware LLC, and individual contributors 004 * as indicated by the @author tags. See the copyright.txt file in the 005 * distribution for a full listing of individual contributors. 006 * 007 * This is free software; you can redistribute it and/or modify it 008 * under the terms of the GNU Lesser General Public License as 009 * published by the Free Software Foundation; either version 2.1 of 010 * the License, or (at your option) any later version. 011 * 012 * This software is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this software; if not, write to the Free 019 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 020 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 021 */ 022 package org.jboss.dna.common.util; 023 024 import java.util.Locale; 025 import java.util.concurrent.atomic.AtomicReference; 026 import net.jcip.annotations.ThreadSafe; 027 import org.jboss.dna.common.i18n.I18n; 028 import org.slf4j.ILoggerFactory; 029 import org.slf4j.LoggerFactory; 030 031 /** 032 * A simple logging interface that is fully compatible with multiple logging implementations. This interface does take advantage 033 * of the variable arguments and autoboxing features in Java 5, reducing the number of methods that are necessary and allowing 034 * callers to supply primitive values as parameters. 035 */ 036 @ThreadSafe 037 public final class Logger { 038 039 public enum Level { 040 OFF, 041 ERROR, 042 WARNING, 043 INFO, 044 DEBUG, 045 TRACE; 046 } 047 048 private static final AtomicReference<Locale> LOGGING_LOCALE = new AtomicReference<Locale>(null); 049 050 /** 051 * Get the locale used for the logs. If null, the {@link Locale#getDefault() default locale} is used. 052 * 053 * @return the current locale used for logging, or null if the system locale is used 054 * @see #setLoggingLocale(Locale) 055 */ 056 public static Locale getLoggingLocale() { 057 return LOGGING_LOCALE.get(); 058 } 059 060 /** 061 * Set the locale used for the logs. This should be used when the logs are to be written is a specific locale, independent of 062 * the {@link Locale#getDefault() default locale}. To use the default locale, call this method with a null value. 063 * 064 * @param locale the desired locale to use for the logs, or null if the system locale should be used 065 * @return the previous locale 066 * @see #getLoggingLocale() 067 */ 068 public static Locale setLoggingLocale( Locale locale ) { 069 return LOGGING_LOCALE.getAndSet(locale != null ? locale : Locale.getDefault()); 070 } 071 072 /** 073 * Return a logger named corresponding to the class passed as parameter, using the statically bound {@link ILoggerFactory} 074 * instance. 075 * 076 * @param clazz the returned logger will be named after clazz 077 * @return logger 078 */ 079 public static Logger getLogger( Class<?> clazz ) { 080 return new Logger(LoggerFactory.getLogger(clazz)); 081 } 082 083 /** 084 * Return a logger named according to the name parameter using the statically bound {@link ILoggerFactory} instance. 085 * 086 * @param name The name of the logger. 087 * @return logger 088 */ 089 public static Logger getLogger( String name ) { 090 return new Logger(LoggerFactory.getLogger(name)); 091 } 092 093 private final org.slf4j.Logger delegate; 094 095 private Logger( org.slf4j.Logger delegate ) { 096 this.delegate = delegate; 097 } 098 099 /** 100 * Return the name of this logger instance. 101 * 102 * @return the logger's name 103 */ 104 public String getName() { 105 return this.delegate.getName(); 106 } 107 108 /** 109 * Log a message at the suplied level according to the specified format and (optional) parameters. The message should contain 110 * a pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is 111 * efficient and avoids superfluous object creation when the logger is disabled for the desired level. 112 * 113 * @param level the level at which to log 114 * @param message the (localized) message string 115 * @param params the parameter values that are to replace the variables in the format string 116 */ 117 public void log( Level level, 118 I18n message, 119 Object... params ) { 120 if (message == null) return; 121 switch (level) { 122 case DEBUG: 123 debug(message.text(LOGGING_LOCALE.get(), params)); 124 break; 125 case ERROR: 126 error(message, params); 127 break; 128 case INFO: 129 info(message, params); 130 break; 131 case TRACE: 132 trace(message.text(LOGGING_LOCALE.get(), params)); 133 break; 134 case WARNING: 135 warn(message, params); 136 break; 137 case OFF: 138 break; 139 } 140 } 141 142 /** 143 * Log an exception (throwable) at the supplied level with an accompanying message. If the exception is null, then this method 144 * calls {@link #debug(String, Object...)}. 145 * 146 * @param level the level at which to log 147 * @param t the exception (throwable) to log 148 * @param message the message accompanying the exception 149 * @param params the parameter values that are to replace the variables in the format string 150 */ 151 public void log( Level level, 152 Throwable t, 153 I18n message, 154 Object... params ) { 155 if (message == null) return; 156 switch (level) { 157 case DEBUG: 158 debug(t, message.text(LOGGING_LOCALE.get(), params)); 159 break; 160 case ERROR: 161 error(t, message, params); 162 break; 163 case INFO: 164 info(t, message, params); 165 break; 166 case TRACE: 167 trace(t, message.text(LOGGING_LOCALE.get(), params)); 168 break; 169 case WARNING: 170 warn(t, message, params); 171 break; 172 case OFF: 173 break; 174 } 175 } 176 177 /** 178 * Log a message at the DEBUG level according to the specified format and (optional) parameters. The message should contain a 179 * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient 180 * and avoids superfluous object creation when the logger is disabled for the DEBUG level. 181 * 182 * @param message the message string 183 * @param params the parameter values that are to replace the variables in the format string 184 */ 185 public void debug( String message, 186 Object... params ) { 187 if (!isDebugEnabled()) return; 188 if (message == null) return; 189 this.delegate.debug(StringUtil.createString(message, params)); 190 } 191 192 /** 193 * Log an exception (throwable) at the DEBUG level with an accompanying message. If the exception is null, then this method 194 * calls {@link #debug(String, Object...)}. 195 * 196 * @param t the exception (throwable) to log 197 * @param message the message accompanying the exception 198 * @param params the parameter values that are to replace the variables in the format string 199 */ 200 public void debug( Throwable t, 201 String message, 202 Object... params ) { 203 if (!isDebugEnabled()) return; 204 if (t == null) { 205 debug(message, params); 206 return; 207 } 208 if (message == null) { 209 this.delegate.debug(null, t); 210 return; 211 } 212 this.delegate.debug(StringUtil.createString(message, params), t); 213 } 214 215 /** 216 * Log a message at the ERROR level according to the specified format and (optional) parameters. The message should contain a 217 * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient 218 * and avoids superfluous object creation when the logger is disabled for the ERROR level. 219 * 220 * @param message the message string 221 * @param params the parameter values that are to replace the variables in the format string 222 */ 223 public void error( I18n message, 224 Object... params ) { 225 if (!isErrorEnabled()) return; 226 if (message == null) return; 227 this.delegate.error(message.text(LOGGING_LOCALE.get(), params)); 228 } 229 230 /** 231 * Log an exception (throwable) at the ERROR level with an accompanying message. If the exception is null, then this method 232 * calls {@link #error(I18n, Object...)}. 233 * 234 * @param t the exception (throwable) to log 235 * @param message the message accompanying the exception 236 * @param params the parameter values that are to replace the variables in the format string 237 */ 238 public void error( Throwable t, 239 I18n message, 240 Object... params ) { 241 if (!isErrorEnabled()) return; 242 if (t == null) { 243 error(message, params); 244 return; 245 } 246 if (message == null) { 247 this.delegate.error(null, t); 248 return; 249 } 250 this.delegate.error(message.text(LOGGING_LOCALE.get(), params), t); 251 } 252 253 /** 254 * Log a message at the INFO level according to the specified format and (optional) parameters. The message should contain a 255 * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient 256 * and avoids superfluous object creation when the logger is disabled for the INFO level. 257 * 258 * @param message the message string 259 * @param params the parameter values that are to replace the variables in the format string 260 */ 261 public void info( I18n message, 262 Object... params ) { 263 if (!isInfoEnabled()) return; 264 if (message == null) return; 265 this.delegate.info(message.text(LOGGING_LOCALE.get(), params)); 266 } 267 268 /** 269 * Log an exception (throwable) at the INFO level with an accompanying message. If the exception is null, then this method 270 * calls {@link #info(I18n, Object...)}. 271 * 272 * @param t the exception (throwable) to log 273 * @param message the message accompanying the exception 274 * @param params the parameter values that are to replace the variables in the format string 275 */ 276 public void info( Throwable t, 277 I18n message, 278 Object... params ) { 279 if (!isInfoEnabled()) return; 280 if (t == null) { 281 info(message, params); 282 return; 283 } 284 if (message == null) { 285 this.delegate.info(null, t); 286 return; 287 } 288 this.delegate.info(message.text(LOGGING_LOCALE.get(), params), t); 289 } 290 291 /** 292 * Log a message at the TRACE level according to the specified format and (optional) parameters. The message should contain a 293 * pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is efficient 294 * and avoids superfluous object creation when the logger is disabled for the TRACE level. 295 * 296 * @param message the message string 297 * @param params the parameter values that are to replace the variables in the format string 298 */ 299 public void trace( String message, 300 Object... params ) { 301 if (!isTraceEnabled()) return; 302 if (message == null) return; 303 this.delegate.trace(StringUtil.createString(message, params)); 304 } 305 306 /** 307 * Log an exception (throwable) at the TRACE level with an accompanying message. If the exception is null, then this method 308 * calls {@link #trace(String, Object...)}. 309 * 310 * @param t the exception (throwable) to log 311 * @param message the message accompanying the exception 312 * @param params the parameter values that are to replace the variables in the format string 313 */ 314 public void trace( Throwable t, 315 String message, 316 Object... params ) { 317 if (!isTraceEnabled()) return; 318 if (t == null) { 319 this.trace(message, params); 320 return; 321 } 322 if (message == null) { 323 this.delegate.trace(null, t); 324 return; 325 } 326 this.delegate.trace(StringUtil.createString(message, params), t); 327 } 328 329 /** 330 * Log a message at the WARNING level according to the specified format and (optional) parameters. The message should contain 331 * a pair of empty curly braces for each of the parameter, which should be passed in the correct order. This method is 332 * efficient and avoids superfluous object creation when the logger is disabled for the WARNING level. 333 * 334 * @param message the message string 335 * @param params the parameter values that are to replace the variables in the format string 336 */ 337 public void warn( I18n message, 338 Object... params ) { 339 if (!isWarnEnabled()) return; 340 if (message == null) return; 341 this.delegate.warn(message.text(LOGGING_LOCALE.get(), params)); 342 } 343 344 /** 345 * Log an exception (throwable) at the WARNING level with an accompanying message. If the exception is null, then this method 346 * calls {@link #warn(I18n, Object...)}. 347 * 348 * @param t the exception (throwable) to log 349 * @param message the message accompanying the exception 350 * @param params the parameter values that are to replace the variables in the format string 351 */ 352 public void warn( Throwable t, 353 I18n message, 354 Object... params ) { 355 if (!isWarnEnabled()) return; 356 if (t == null) { 357 warn(message, params); 358 return; 359 } 360 if (message == null) { 361 this.delegate.warn(null, t); 362 return; 363 } 364 this.delegate.warn(message.text(LOGGING_LOCALE.get(), params), t); 365 } 366 367 /** 368 * Return whether messages at the INFORMATION level are being logged. 369 * 370 * @return true if INFORMATION log messages are currently being logged, or false otherwise. 371 */ 372 protected boolean isInfoEnabled() { 373 return this.delegate.isInfoEnabled(); 374 } 375 376 /** 377 * Return whether messages at the WARNING level are being logged. 378 * 379 * @return true if WARNING log messages are currently being logged, or false otherwise. 380 */ 381 protected boolean isWarnEnabled() { 382 return this.delegate.isWarnEnabled(); 383 } 384 385 /** 386 * Return whether messages at the ERROR level are being logged. 387 * 388 * @return true if ERROR log messages are currently being logged, or false otherwise. 389 */ 390 protected boolean isErrorEnabled() { 391 return this.delegate.isErrorEnabled(); 392 } 393 394 /** 395 * Return whether messages at the DEBUG level are being logged. 396 * 397 * @return true if DEBUG log messages are currently being logged, or false otherwise. 398 */ 399 public boolean isDebugEnabled() { 400 return this.delegate.isDebugEnabled(); 401 } 402 403 /** 404 * Return whether messages at the TRACE level are being logged. 405 * 406 * @return true if TRACE log messages are currently being logged, or false otherwise. 407 */ 408 public boolean isTraceEnabled() { 409 return this.delegate.isTraceEnabled(); 410 } 411 412 /** 413 * Get the logging level at which this logger is current set. 414 * 415 * @return the current logging level 416 */ 417 public Level getLevel() { 418 if (this.isTraceEnabled()) return Level.TRACE; 419 if (this.isDebugEnabled()) return Level.DEBUG; 420 if (this.isInfoEnabled()) return Level.INFO; 421 if (this.isWarnEnabled()) return Level.WARNING; 422 if (this.isErrorEnabled()) return Level.ERROR; 423 return Level.OFF; 424 } 425 426 }