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