1 18 39 package org.objectweb.petals.util.monolog.wrapper.javalog; 40 41 import java.io.PrintWriter ; 42 import java.io.StringWriter ; 43 import java.util.ArrayList ; 44 import java.util.Calendar ; 45 import java.util.Date ; 46 import java.util.List ; 47 import java.util.StringTokenizer ; 48 import java.util.logging.Formatter ; 49 import java.util.logging.LogRecord ; 50 import java.util.logging.SimpleFormatter ; 51 52 import org.objectweb.util.monolog.file.api.Pattern; 53 import org.objectweb.util.monolog.wrapper.common.AbstractFactory; 54 55 66 public class MonologFormatter extends Formatter { 67 68 public final static String WRAPPERS_PROPERTY = "monolog.wrappers"; 69 70 private static boolean debug = Boolean.getBoolean("monolog.pattern.debug"); 71 72 private static String [] LOGWRAPPER = {"org.objectweb.util.monolog.wrapper", 73 "org.apache.commons.logging"}; 74 75 private final static int PATTERN_ID_DATE = -300; 76 77 private final static int PATTERN_ID_INTERVAL = 100; 78 79 private final static int PATTERN_ID_LEVEL = -100; 80 81 private final static int PATTERN_ID_LINE_NUMBER = -800; 82 83 private final static int PATTERN_ID_MESSAGE = -500; 84 85 private final static int PATTERN_ID_METHOD = -600; 86 87 private final static int PATTERN_ID_NEW_LINE = -900; 88 89 private final static int PATTERN_ID_OBJECT = -700; 90 91 private final static int PATTERN_ID_THREAD = -400; 92 93 private final static int PATTERN_ID_TOPIC = -200; 94 95 private static long previousTime; 96 97 private static char[] previousTimeWithoutMillis = new char[20]; 99 102 private static final int STACK_TRACE_ITEMS = 9; 103 104 private final static String TOKENS = "{}" + Pattern.LEVEL + Pattern.TOPIC 105 + Pattern.DATE + Pattern.THREAD + Pattern.MESSAGE + Pattern.METHOD 106 + Pattern.OBJECT + Pattern.LINE_NUMBER + Pattern.PREFIX 107 + Pattern.NEW_LINE; 108 109 Calendar calendar; 110 111 114 int[] pattern; 115 116 118 121 String [] strings; 122 123 126 String strPattern; 127 128 public MonologFormatter() { 129 calendar = Calendar.getInstance(); 130 } 131 132 public MonologFormatter(String strPattern) { 133 this(); 134 setPattern(strPattern); 135 } 136 137 static { 138 String wrap = System.getProperty(WRAPPERS_PROPERTY); 139 if (wrap != null) { 140 List <String > ws = new ArrayList <String >(5); 141 StringTokenizer st = new StringTokenizer (wrap, ",;: /", false); 142 while (st.hasMoreTokens()) { 143 ws.add(st.nextToken()); 144 } 145 String [] wsa = new String [LOGWRAPPER.length + ws.size()]; 146 System.arraycopy(LOGWRAPPER, 0, wsa, 0, LOGWRAPPER.length); 147 for (int i = 0; i < ws.size(); i++) { 148 wsa[LOGWRAPPER.length + i] = (String ) ws.get(i); 149 } 150 LOGWRAPPER = wsa; 151 } 152 } 153 154 161 public static String [] getContext() { 162 163 Throwable t = new Throwable ().fillInStackTrace(); 164 StringWriter sw = new StringWriter (); 165 t.printStackTrace(new PrintWriter (sw)); 166 String m = sw.getBuffer().toString(); 167 int fin = 0; 168 int deb = 0; 169 for (int i = 0; i < STACK_TRACE_ITEMS; i++) { 171 deb = m.indexOf("\n", deb) + 1; 172 } 173 boolean isWrapper = true; 174 deb = m.indexOf("at ", deb) + 3; 175 while (isWrapper) { 176 isWrapper = false; 177 for (int i = 0; i < LOGWRAPPER.length && !isWrapper; i++) { 178 isWrapper |= m.startsWith(LOGWRAPPER[i], deb); 179 } 180 if (isWrapper) { 181 deb = m.indexOf("at ", deb) + 3; 182 } 183 } 184 fin = m.indexOf("\n", deb); 185 m = m.substring(deb, fin); 186 187 deb = m.indexOf("("); 189 fin = m.indexOf(":"); 190 if (deb == -1 || fin == -1) { 191 AbstractFactory 192 .warn("Bad stack trace. '(' and ':' expected in the string '" 193 + m + "'. The full stack trace is the following:\n" 194 + sw.getBuffer().toString()); 195 return new String [] {"", "", ""}; 196 } 197 String [] res = new String [3]; 198 res[2] = (fin == -1 ? "unknown" : m.substring(fin + 1, m.length() - 1)); 199 m = m.substring(0, deb); 200 201 fin = m.lastIndexOf('.'); 203 res[0] = m.substring(0, fin); 204 res[1] = m.substring(fin + 1); 205 return res; 206 } 207 208 private final static String patternIdToString(int id) { 209 switch (id) { 210 case PATTERN_ID_LEVEL: 211 return "" + Pattern.LEVEL; 212 case PATTERN_ID_TOPIC: 213 return "" + Pattern.TOPIC; 214 case PATTERN_ID_DATE: 215 return "" + Pattern.DATE; 216 case PATTERN_ID_THREAD: 217 return "" + Pattern.THREAD; 218 case PATTERN_ID_MESSAGE: 219 return "" + Pattern.MESSAGE; 220 case PATTERN_ID_METHOD: 221 return "" + Pattern.METHOD; 222 case PATTERN_ID_OBJECT: 223 return "" + Pattern.OBJECT; 224 case PATTERN_ID_LINE_NUMBER: 225 return "" + Pattern.LINE_NUMBER; 226 case PATTERN_ID_NEW_LINE: 227 return "" + Pattern.NEW_LINE; 228 default: 229 return null; 230 } 231 } 232 233 242 public void format(Date date, StringBuffer sbuf) { 243 long now = date.getTime(); 244 int millis = (int) (now % 1000); 245 246 if ((now - millis) != previousTime) { 247 251 calendar.setTime(date); 252 253 int start = sbuf.length(); 254 255 int year = calendar.get(Calendar.YEAR); 256 sbuf.append(year); 257 sbuf.append('-'); 258 int month = calendar.get(Calendar.MONTH); 259 month++; 260 if (month < 10) { 261 sbuf.append('0'); 262 } 263 sbuf.append(month); 264 sbuf.append('-'); 265 int day = calendar.get(Calendar.DAY_OF_MONTH); 266 if (day < 10) { 267 sbuf.append('0'); 268 } 269 sbuf.append(day); 270 271 sbuf.append(' '); 272 273 int hour = calendar.get(Calendar.HOUR_OF_DAY); 274 if (hour < 10) { 275 sbuf.append('0'); 276 } 277 sbuf.append(hour); 278 sbuf.append(':'); 279 280 int mins = calendar.get(Calendar.MINUTE); 281 if (mins < 10) { 282 sbuf.append('0'); 283 } 284 sbuf.append(mins); 285 sbuf.append(':'); 286 287 int secs = calendar.get(Calendar.SECOND); 288 if (secs < 10) { 289 sbuf.append('0'); 290 } 291 sbuf.append(secs); 292 sbuf.append(','); 293 294 sbuf.getChars(start, sbuf.length(), previousTimeWithoutMillis, 0); 296 297 previousTime = now - millis; 298 } else { 299 sbuf.append(previousTimeWithoutMillis); 300 } 301 if (millis < 100) { 302 sbuf.append('0'); 303 } 304 if (millis < 10) { 305 sbuf.append('0'); 306 } 307 sbuf.append(millis); 308 } 309 310 322 public String format(LogRecord record) { 323 StringBuffer sb = new StringBuffer (); 324 String [] ctx = null; 325 for (int i = 0; i < pattern.length; i++) { 326 int p = pattern[i]; 327 if (debug) { 328 AbstractFactory.debug("format: pattern=" + p + "=" 329 + patternIdToString(p)); 330 } 331 switch (p) { 332 case PATTERN_ID_LEVEL: 333 sb.append(record.getLevel().getName()); 334 break; 335 case PATTERN_ID_TOPIC: 336 sb.append(record.getLoggerName()); 337 break; 338 case PATTERN_ID_DATE: 339 format(new Date (record.getMillis()), sb); 340 break; 341 case PATTERN_ID_THREAD: 342 sb.append(Thread.currentThread().getName()); 343 break; 344 case PATTERN_ID_MESSAGE: 345 SimpleFormatter simpleFormatter = new SimpleFormatter (); 346 sb.append(simpleFormatter.formatMessage(record)); 347 break; 348 case PATTERN_ID_METHOD: 349 if (ctx == null) { 350 ctx = getContext(); 351 } 352 sb.append(ctx[1]); 353 break; 354 case PATTERN_ID_OBJECT: 355 if (ctx == null) { 356 ctx = getContext(); 357 } 358 sb.append(ctx[0]); 359 break; 360 case PATTERN_ID_LINE_NUMBER: 361 if (ctx == null) { 362 ctx = getContext(); 363 } 364 sb.append(ctx[2]); 365 break; 366 case PATTERN_ID_NEW_LINE: 367 sb.append("\n"); 368 break; 369 default: 370 if (p < 0) { 371 if (ctx == null) { 372 ctx = getContext(); 373 } 374 if (p > (PATTERN_ID_OBJECT - PATTERN_ID_INTERVAL) 375 && p < PATTERN_ID_OBJECT) { 376 p = PATTERN_ID_OBJECT - p; 377 String res = ctx[0]; 378 if (p == 1) { int idx = res.lastIndexOf('.'); 380 if (idx != -1) { 381 res = res.substring(idx + 1); 382 } 383 } else if (p == 0) { 384 } else { 386 int idx = res.lastIndexOf('.'); 387 for (; p > 1 && idx != -1; p--) { 388 if (idx != -1) { 389 idx = res.lastIndexOf('.', idx - 1); 390 } 391 } 392 if (idx != -1) { 393 res = res.substring(idx + 1); 394 } 395 } 396 sb.append(res); 397 } 398 } else if (p >= strings.length) { 399 System.err 400 .println("ERROR: String identifier unknown: " + p); 401 } else { 402 sb.append(strings[p]); 403 } 404 } 405 } 406 if (record.getThrown() != null) { 407 StringWriter sw = new StringWriter (); 408 record.getThrown().printStackTrace(new PrintWriter (sw)); 409 sb.append(sw.getBuffer()); 410 } 411 return sb.toString(); 412 } 413 414 public String format(String msg, String levelName, String topic, long time) { 415 StringBuffer sb = new StringBuffer (); 416 String [] ctx = null; 417 for (int i = 0; i < pattern.length; i++) { 418 int p = pattern[i]; 419 if (debug) { 420 AbstractFactory.debug("format: pattern=" + p + "=" 421 + patternIdToString(p)); 422 } 423 switch (p) { 424 case PATTERN_ID_LEVEL: 425 sb.append(levelName); 426 break; 427 case PATTERN_ID_TOPIC: 428 sb.append(topic); 429 break; 430 case PATTERN_ID_DATE: 431 format(new Date (time), sb); 432 break; 433 case PATTERN_ID_THREAD: 434 sb.append(Thread.currentThread().getName()); 435 break; 436 case PATTERN_ID_MESSAGE: 437 sb.append(msg); 438 break; 439 case PATTERN_ID_METHOD: 440 if (ctx == null) { 441 ctx = getContext(); 442 } 443 sb.append(ctx[1]); 444 break; 445 case PATTERN_ID_OBJECT: 446 if (ctx == null) { 447 ctx = getContext(); 448 } 449 sb.append(ctx[0]); 450 break; 451 case PATTERN_ID_LINE_NUMBER: 452 if (ctx == null) { 453 ctx = getContext(); 454 } 455 sb.append(ctx[2]); 456 break; 457 case PATTERN_ID_NEW_LINE: 458 sb.append("\n"); 459 break; 460 default: 461 if (p < 0) { 462 if (ctx == null) { 463 ctx = getContext(); 464 } 465 if (p > (PATTERN_ID_OBJECT - PATTERN_ID_INTERVAL) 466 && p < PATTERN_ID_OBJECT) { 467 p = PATTERN_ID_OBJECT - p; 468 String res = ctx[0]; 469 if (p == 1) { int idx = res.lastIndexOf('.'); 471 if (idx != -1) { 472 res = res.substring(idx + 1); 473 } 474 } else if (p == 0) { 475 } else { 477 int idx = res.lastIndexOf('.'); 478 for (; p > 1 && idx != -1; p--) { 479 if (idx != -1) { 480 idx = res.lastIndexOf('.', idx - 1); 481 } 482 } 483 if (idx != -1) { 484 res = res.substring(idx + 1); 485 } 486 } 487 sb.append(res); 488 } 489 } else if (p >= strings.length) { 490 System.err 491 .println("ERROR: String identifier unknown: " + p); 492 } else { 493 sb.append(strings[p]); 494 } 495 } 496 } 497 return sb.toString(); 498 } 499 500 public String getPattern() { 501 return strPattern; 502 } 503 504 public void setPattern(String p) { 505 if (debug) { 506 AbstractFactory.debug("Pattern=" + p); 507 } 508 this.strPattern = p; 509 if (strPattern == null) { 510 pattern = new int[0]; 511 } else { 512 StringTokenizer st = new StringTokenizer (p, TOKENS, true); 513 List <Object > sections = new ArrayList <Object >(); 514 boolean isPrefix = false; 515 boolean isObject = false; 516 boolean isInSubObject = false; 517 int subObjectNumber = 1; 518 while (st.hasMoreElements()) { 519 String token = st.nextToken(); 520 if (debug) { 521 AbstractFactory.debug("token=<" + token + ">"); 522 } 523 if (isObject && token.equals("{")) { 524 isInSubObject = true; 525 isObject = false; 526 } 527 if (token.length() == 1) { 528 char c = token.charAt(0); 529 switch (c) { 530 case '{': 531 if (!isInSubObject) { 532 addSection(sections, token); 533 } 534 break; 535 case '}': 536 if (isInSubObject) { 537 int old = ((Integer ) sections 538 .get(sections.size() - 1)).intValue(); 539 sections.set(sections.size() - 1, new Integer (old 540 - subObjectNumber)); 541 isInSubObject = false; 542 } else { 543 addSection(sections, token); 544 } 545 break; 546 case Pattern.PREFIX: 547 if (isPrefix) { 548 sections.add(String.valueOf(Pattern.PREFIX)); 549 } 550 isPrefix = !isPrefix; 551 break; 552 case Pattern.LEVEL: 553 isPrefix = treatPattern(sections, token, 554 PATTERN_ID_LEVEL, isPrefix); 555 break; 556 case Pattern.TOPIC: 557 isPrefix = treatPattern(sections, token, 558 PATTERN_ID_TOPIC, isPrefix); 559 break; 560 case Pattern.DATE: 561 isPrefix = treatPattern(sections, token, 562 PATTERN_ID_DATE, isPrefix); 563 break; 564 case Pattern.THREAD: 565 isPrefix = treatPattern(sections, token, 566 PATTERN_ID_THREAD, isPrefix); 567 break; 568 case Pattern.MESSAGE: 569 isPrefix = treatPattern(sections, token, 570 PATTERN_ID_MESSAGE, isPrefix); 571 break; 572 case Pattern.METHOD: 573 isPrefix = treatPattern(sections, token, 574 PATTERN_ID_METHOD, isPrefix); 575 break; 576 case Pattern.OBJECT: 577 isPrefix = treatPattern(sections, token, 578 PATTERN_ID_OBJECT, isPrefix); 579 isObject = true; 580 break; 581 case Pattern.LINE_NUMBER: 582 isPrefix = treatPattern(sections, token, 583 PATTERN_ID_LINE_NUMBER, isPrefix); 584 break; 585 case Pattern.NEW_LINE: 586 isPrefix = treatPattern(sections, token, 587 PATTERN_ID_NEW_LINE, isPrefix); 588 break; 589 default: 590 if (isInSubObject) { 591 subObjectNumber = Integer.parseInt(token); 592 } else { 593 addSection(sections, token); 594 } 595 break; 596 } 597 } else if (isObject) { 598 } else if (isInSubObject) { 600 subObjectNumber = Integer.parseInt(token); 601 } else { 602 addSection(sections, token); 603 } 604 } 605 pattern = new int[sections.size()]; 606 if (debug) { 607 AbstractFactory.debug("building pattern array..."); 608 AbstractFactory.debug("nb of pattern:" + pattern.length); 609 } 610 List <String > stringList = new ArrayList <String >(sections.size()); 611 int cpt = 0; 612 for (int i = 0; i < pattern.length; i++) { 613 Object o = sections.get(i); 614 if (o instanceof String ) { 615 if (debug) { 616 AbstractFactory 617 .debug("add current pattern into strings: [" + cpt 618 + ", " + o + "]"); 619 } 620 stringList.add((String ) o); 621 pattern[i] = cpt; 622 cpt++; 623 } else if (o instanceof Integer ) { 624 if (debug) { 625 AbstractFactory 626 .debug("add current pattern as negative number:" 627 + o); 628 } 629 pattern[i] = ((Integer ) o).intValue(); 630 } 631 } 632 strings = (String []) stringList.toArray(new String [cpt]); 633 if (debug) { 634 AbstractFactory.debug("nb of string:" + strings.length); 635 } 636 } 637 } 638 639 private void addSection(List <Object > sections, String s) { 640 int size = sections.size(); 641 if (size == 0) { 642 if (debug) { 643 AbstractFactory.debug("addSection(" + s + ", " + sections 644 + "): first elem"); 645 } 646 sections.add(s); 647 } else { 648 Object last = sections.get(size - 1); 649 if (last instanceof String ) { 650 sections.set(size - 1, last + s); 651 if (debug) { 652 AbstractFactory.debug("addSection(" + s + ", " + sections 653 + "): concat: " + sections.get(size - 1)); 654 } 655 } else { 656 if (debug) { 657 AbstractFactory.debug("addSection(" + s + ", " + sections 658 + "): new elem"); 659 } 660 sections.add(s); 661 } 662 } 663 } 664 665 private boolean treatPattern(List <Object > sections, String token, 666 int tokenId, boolean isPrefix) { 667 if (debug) { 668 AbstractFactory.debug("treatPttern(" + tokenId + "):" 669 + " isPrefix=" + isPrefix + " token=" + token + " sections=" 670 + sections); 671 } 672 if (isPrefix) { 673 sections.add(new Integer (tokenId)); 674 return false; 675 } else { 676 addSection(sections, token); 677 return isPrefix; 678 } 679 } 680 681 } | Popular Tags |