1 9 package com.vladium.logging; 10 11 import java.io.PrintWriter ; 12 import java.io.StringWriter ; 13 import java.util.HashSet ; 14 import java.util.LinkedList ; 15 import java.util.NoSuchElementException ; 16 import java.util.Properties ; 17 import java.util.Set ; 18 import java.util.StringTokenizer ; 19 20 import com.vladium.emma.AppLoggers; 21 import com.vladium.emma.IAppConstants; 22 import com.vladium.util.ClassLoaderResolver; 23 import com.vladium.util.Property; 24 import com.vladium.util.Strings; 25 26 60 public 61 final class Logger implements ILogLevels 62 { 63 65 68 public static Logger create (final int level, final PrintWriter out, final String prefix, final Set classMask) 69 { 70 if ((level < NONE) || (level > ALL)) 71 throw new IllegalArgumentException ("invalid log level: " + level); 72 73 if ((out == null) || out.checkError ()) 74 throw new IllegalArgumentException ("null or corrupt input: out"); 75 76 return new Logger (level, out, prefix, classMask); 77 } 78 79 89 public static Logger create (final int level, final PrintWriter out, final String prefix, final Set classMask, 90 final Logger base) 91 { 92 if (base == null) 93 { 94 return create (level, out, prefix, classMask); 95 } 96 else 97 { 98 final int _level = level >= NONE 99 ? level 100 : base.m_level; 101 102 final PrintWriter _out = (out != null) && ! out.checkError () 103 ? out 104 : base.m_out; 105 106 final String _prefix = prefix; 108 112 final Set _classMask = classMask != null 113 ? classMask 114 : base.m_classMask; 115 116 117 return new Logger (_level, _out, _prefix, _classMask); 118 } 119 } 120 121 122 130 public final boolean isLoggable (final int level) 131 { 132 return (level <= m_level); 133 } 134 135 138 public final boolean atINFO () 139 { 140 return (INFO <= m_level); 141 } 142 143 146 public final boolean atVERBOSE () 147 { 148 return (VERBOSE <= m_level); 149 } 150 151 154 public final boolean atTRACE1 () 155 { 156 return (TRACE1 <= m_level); 157 } 158 159 162 public final boolean atTRACE2 () 163 { 164 return (TRACE2 <= m_level); 165 } 166 167 170 public final boolean atTRACE3 () 171 { 172 return (TRACE3 <= m_level); 173 } 174 175 176 182 public final void warning (final String msg) 183 { 184 _log (WARNING, null, msg, false); 185 } 186 187 193 public final void info (final String msg) 194 { 195 _log (INFO, null, msg, false); 196 } 197 198 204 public final void verbose (final String msg) 205 { 206 _log (VERBOSE, null, msg, false); 207 } 208 209 210 216 public final void trace1 (final String method, final String msg) 217 { 218 _log (TRACE1, method, msg, true); 219 } 220 221 227 public final void trace2 (final String method, final String msg) 228 { 229 _log (TRACE2, method, msg, true); 230 } 231 232 238 public final void trace3 (final String method, final String msg) 239 { 240 _log (TRACE3, method, msg, true); 241 } 242 243 250 public final void log (final int level, final String msg, final boolean logCaller) 251 { 252 _log (level, null, msg, logCaller); 253 } 254 255 263 public final void log (final int level, final String method, final String msg, final boolean logCaller) 264 { 265 _log (level, method, msg, logCaller); 266 } 267 268 277 public final void log (final int level, final String msg, final Throwable throwable) 278 { 279 _log (level, null, msg, throwable); 280 } 281 282 292 public final void log (final int level, final String method, final String msg, final Throwable throwable) 293 { 294 _log (level, method, msg, throwable); 295 } 296 297 298 303 public PrintWriter getWriter () 304 { 305 return m_out; 306 } 307 308 309 315 public static Logger getLogger () 316 { 317 final LinkedList stack = (LinkedList ) THREAD_LOCAL_STACK.get (); 318 319 321 if (stack.isEmpty ()) 322 { 323 return STATIC_LOGGER; 324 } 325 else 326 { 327 return (Logger) stack.getLast (); 328 } 329 } 330 331 335 public static void push (final Logger ctx) 336 { 337 if (ctx == null) 338 throw new IllegalArgumentException ("null input: ctx"); 339 340 final LinkedList stack = (LinkedList ) THREAD_LOCAL_STACK.get (); 341 stack.addLast (ctx); 342 } 343 344 350 public static void pop (final Logger ctx) 351 { 352 355 final LinkedList stack = (LinkedList ) THREAD_LOCAL_STACK.get (); 356 357 try 358 { 359 final Logger current = (Logger) stack.getLast (); 360 if (current != ctx) 361 throw new IllegalStateException ("invalid context being popped: " + ctx); 362 363 stack.removeLast (); 364 current.cleanup (); 365 } 366 catch (NoSuchElementException nsee) 367 { 368 throw new IllegalStateException ("empty logger context stack on thread [" + Thread.currentThread () + "]: " + nsee); 369 } 370 } 371 372 373 public static int stringToLevel (final String level) 374 { 375 if (ILogLevels.SEVERE_STRING.equalsIgnoreCase (level) || ILogLevels.SILENT_STRING.equalsIgnoreCase (level)) 376 return ILogLevels.SEVERE; 377 else if (ILogLevels.WARNING_STRING.equalsIgnoreCase (level) || ILogLevels.QUIET_STRING.equalsIgnoreCase (level)) 378 return ILogLevels.WARNING; 379 else if (ILogLevels.INFO_STRING.equalsIgnoreCase (level)) 380 return ILogLevels.INFO; 381 else if (ILogLevels.VERBOSE_STRING.equalsIgnoreCase (level)) 382 return ILogLevels.VERBOSE; 383 else if (ILogLevels.TRACE1_STRING.equalsIgnoreCase (level)) 384 return ILogLevels.TRACE1; 385 else if (ILogLevels.TRACE2_STRING.equalsIgnoreCase (level)) 386 return ILogLevels.TRACE2; 387 else if (ILogLevels.TRACE3_STRING.equalsIgnoreCase (level)) 388 return ILogLevels.TRACE3; 389 else if (ILogLevels.NONE_STRING.equalsIgnoreCase (level)) 390 return ILogLevels.NONE; 391 else if (ILogLevels.ALL_STRING.equalsIgnoreCase (level)) 392 return ILogLevels.ALL; 393 else 394 { 395 int _level = Integer.MIN_VALUE; 396 try 397 { 398 _level = Integer.parseInt (level); 399 } 400 catch (Exception ignore) {} 401 402 if ((_level >= ILogLevels.NONE) && (_level <= ILogLevels.ALL)) 403 return _level; 404 else 405 return ILogLevels.INFO; } 407 } 408 409 411 413 415 416 private static final class ThreadLocalStack extends InheritableThreadLocal 417 { 418 protected Object initialValue () 419 { 420 return new LinkedList (); 421 } 422 423 } 425 426 private Logger (final int level, final PrintWriter out, final String prefix, final Set classMask) 427 { 428 m_level = level; 429 m_out = out; 430 m_prefix = prefix; 431 m_classMask = classMask; } 433 434 private void cleanup () 435 { 436 m_out.flush (); 437 } 438 439 private void _log (final int level, final String method, 440 final String msg, final boolean logCaller) 441 { 442 if ((level <= m_level) && (level >= SEVERE)) 443 { 444 final Class caller = logCaller ? ClassLoaderResolver.getCallerClass (2) : null; 445 final StringBuffer buf = new StringBuffer (m_prefix != null ? m_prefix + ": " : ""); 446 447 if ((caller != null) || (method != null)) 448 { 449 buf.append ("["); 450 451 if (caller != null) { 453 String callerName = caller.getName (); 454 455 if (callerName.startsWith (PREFIX_TO_STRIP)) 456 callerName = callerName.substring (PREFIX_TO_STRIP_LENGTH); 457 458 String parentName = callerName; 459 460 final int firstDollar = callerName.indexOf ('$'); 461 if (firstDollar > 0) parentName = callerName.substring (0, firstDollar); 462 463 if ((m_classMask == null) || m_classMask.contains (parentName)) 464 buf.append (callerName); 465 else 466 return; 467 } 468 469 if (method != null) 470 { 471 buf.append ("::"); 472 buf.append (method); 473 } 474 475 buf.append ("] "); 476 } 477 478 final PrintWriter out = m_out; 479 480 if (msg != null) buf.append (msg); 481 482 out.println (buf); 483 if (FLUSH_LOG) out.flush (); 484 } 485 } 486 487 private void _log (final int level, final String method, 488 final String msg, final Throwable throwable) 489 { 490 if ((level <= m_level) && (level >= SEVERE)) 491 { 492 final Class caller = ClassLoaderResolver.getCallerClass (2); 493 final StringBuffer buf = new StringBuffer (m_prefix != null ? m_prefix + ": " : ""); 494 495 if ((caller != null) || (method != null)) 496 { 497 buf.append ("["); 498 499 if (caller != null) { 501 String callerName = caller.getName (); 502 503 if (callerName.startsWith (PREFIX_TO_STRIP)) 504 callerName = callerName.substring (PREFIX_TO_STRIP_LENGTH); 505 506 String parentName = callerName; 507 508 final int firstDollar = callerName.indexOf ('$'); 509 if (firstDollar > 0) parentName = callerName.substring (0, firstDollar); 510 511 if ((m_classMask == null) || m_classMask.contains (parentName)) 512 buf.append (callerName); 513 else 514 return; 515 } 516 517 if (method != null) 518 { 519 buf.append ("::"); 520 buf.append (method); 521 } 522 523 buf.append ("] "); 524 } 525 526 final PrintWriter out = m_out; 527 528 if (msg != null) buf.append (msg); 529 530 if (throwable != null) 531 { 532 final StringWriter sw = new StringWriter (); 533 final PrintWriter pw = new PrintWriter (sw); 534 535 throwable.printStackTrace (pw); 536 pw.flush (); 537 538 buf.append (sw.toString ()); 539 } 540 541 out.println (buf); 542 if (FLUSH_LOG) out.flush (); 543 } 544 } 545 546 547 548 private final int m_level; private final PrintWriter m_out; private final String m_prefix; private final Set m_classMask; 553 private static final String PREFIX_TO_STRIP = "com.vladium."; private static final int PREFIX_TO_STRIP_LENGTH = PREFIX_TO_STRIP.length (); 555 private static final boolean FLUSH_LOG = true; 556 private static final String COMMA_DELIMITERS = "," + Strings.WHITE_SPACE; 557 558 private static final Logger STATIC_LOGGER; private static final ThreadLocalStack THREAD_LOCAL_STACK; 561 static 562 { 563 THREAD_LOCAL_STACK = new ThreadLocalStack (); 564 565 569 final Properties properties = Property.getAppProperties (IAppConstants.APP_NAME_LC, Logger.class.getClassLoader ()); 570 571 573 final int level; 574 { 575 final String _level = properties.getProperty (AppLoggers.PROPERTY_VERBOSITY_LEVEL, 576 AppLoggers.DEFAULT_VERBOSITY_LEVEL); 577 level = stringToLevel (_level); 578 } 579 580 582 final Set filter; 583 { 584 final String _filter = properties.getProperty (AppLoggers.PROPERTY_VERBOSITY_FILTER); 585 Set temp = null; 586 587 if (_filter != null) 588 { 589 final StringTokenizer tokenizer = new StringTokenizer (_filter, COMMA_DELIMITERS); 590 if (tokenizer.countTokens () > 0) 591 { 592 temp = new HashSet (tokenizer.countTokens ()); 593 while (tokenizer.hasMoreTokens ()) 594 { 595 temp.add (tokenizer.nextToken ()); 596 } 597 } 598 } 599 600 filter = temp; 601 } 602 603 604 STATIC_LOGGER = create (level, 605 new PrintWriter (System.out, false), 606 IAppConstants.APP_NAME, 607 filter); 608 } 609 610 } | Popular Tags |