1 16 package org.jboss.logging.jdk.format; 17 18 import java.text.DateFormat ; 19 import java.text.SimpleDateFormat ; 20 import java.util.Date ; 21 import java.util.logging.LogRecord ; 22 23 27 40 public class PatternParser 41 { 42 public final static String LINE_SEP = System.getProperty("line.separator"); 43 44 private static long startTime = System.currentTimeMillis(); 45 46 private static final char ESCAPE_CHAR = '%'; 47 48 private static final int LITERAL_STATE = 0; 49 private static final int CONVERTER_STATE = 1; 50 private static final int MINUS_STATE = 2; 51 private static final int DOT_STATE = 3; 52 private static final int MIN_STATE = 4; 53 private static final int MAX_STATE = 5; 54 55 static final int FULL_LOCATION_CONVERTER = 1000; 56 static final int METHOD_LOCATION_CONVERTER = 1001; 57 static final int CLASS_LOCATION_CONVERTER = 1002; 58 static final int LINE_LOCATION_CONVERTER = 1003; 59 static final int FILE_LOCATION_CONVERTER = 1004; 60 61 static final int RELATIVE_TIME_CONVERTER = 2000; 62 static final int THREAD_CONVERTER = 2001; 63 static final int LEVEL_CONVERTER = 2002; 64 static final int NDC_CONVERTER = 2003; 65 static final int MESSAGE_CONVERTER = 2004; 66 static final int THREAD_NAME_CONVERTER = 2005; 67 68 int state; 69 protected StringBuffer currentLiteral = new StringBuffer (32); 70 protected int patternLength; 71 protected int i; 72 PatternConverter head; 73 PatternConverter tail; 74 protected FormattingInfo formattingInfo = new FormattingInfo(); 75 protected String pattern; 76 77 public PatternParser(String pattern) 78 { 79 this.pattern = pattern; 80 patternLength = pattern.length(); 81 state = LITERAL_STATE; 82 } 83 84 private void addToList(PatternConverter pc) 85 { 86 if (head == null) 87 { 88 head = tail = pc; 89 } 90 else 91 { 92 tail.next = pc; 93 tail = pc; 94 } 95 } 96 97 protected String extractOption() 98 { 99 if ((i < patternLength) && (pattern.charAt(i) == '{')) 100 { 101 int end = pattern.indexOf('}', i); 102 if (end > i) 103 { 104 String r = pattern.substring(i + 1, end); 105 i = end + 1; 106 return r; 107 } 108 } 109 return null; 110 } 111 112 113 117 protected int extractPrecisionOption() 118 { 119 String opt = extractOption(); 120 int r = 0; 121 if (opt != null) 122 { 123 try 124 { 125 r = Integer.parseInt(opt); 126 if (r <= 0) 127 { 128 System.err.println("Precision option (" + opt + ") isn't a positive integer."); 129 r = 0; 130 } 131 } 132 catch (NumberFormatException e) 133 { 134 System.err.println("Category option '" + opt + "' not a decimal integer." + e.getMessage()); 135 } 136 } 137 return r; 138 } 139 140 public PatternConverter parse() 141 { 142 char c; 143 i = 0; 144 while (i < patternLength) 145 { 146 c = pattern.charAt(i++); 147 switch (state) 148 { 149 case LITERAL_STATE: 150 if (i == patternLength) 152 { 153 currentLiteral.append(c); 154 continue; 155 } 156 if (c == ESCAPE_CHAR) 157 { 158 switch (pattern.charAt(i)) 160 { 161 case ESCAPE_CHAR: 162 currentLiteral.append(c); 163 i++; break; 165 case 'n': 166 currentLiteral.append(LINE_SEP); 167 i++; break; 169 default: 170 if (currentLiteral.length() != 0) 171 { 172 addToList(new LiteralPatternConverter( 173 currentLiteral.toString())); 174 } 177 currentLiteral.setLength(0); 178 currentLiteral.append(c); state = CONVERTER_STATE; 180 formattingInfo.reset(); 181 } 182 } 183 else 184 { 185 currentLiteral.append(c); 186 } 187 break; 188 case CONVERTER_STATE: 189 currentLiteral.append(c); 190 switch (c) 191 { 192 case '-': 193 formattingInfo.leftAlign = true; 194 break; 195 case '.': 196 state = DOT_STATE; 197 break; 198 default: 199 if (c >= '0' && c <= '9') 200 { 201 formattingInfo.min = c - '0'; 202 state = MIN_STATE; 203 } 204 else 205 finalizeConverter(c); 206 } break; 208 case MIN_STATE: 209 currentLiteral.append(c); 210 if (c >= '0' && c <= '9') 211 formattingInfo.min = formattingInfo.min * 10 + (c - '0'); 212 else if (c == '.') 213 state = DOT_STATE; 214 else 215 { 216 finalizeConverter(c); 217 } 218 break; 219 case DOT_STATE: 220 currentLiteral.append(c); 221 if (c >= '0' && c <= '9') 222 { 223 formattingInfo.max = c - '0'; 224 state = MAX_STATE; 225 } 226 else 227 { 228 System.err.println("Error occured in position " + i 229 + ".\n Was expecting digit, instead got char \"" + c + "\"."); 230 state = LITERAL_STATE; 231 } 232 break; 233 case MAX_STATE: 234 currentLiteral.append(c); 235 if (c >= '0' && c <= '9') 236 formattingInfo.max = formattingInfo.max * 10 + (c - '0'); 237 else 238 { 239 finalizeConverter(c); 240 state = LITERAL_STATE; 241 } 242 break; 243 } } if (currentLiteral.length() != 0) 246 { 247 addToList(new LiteralPatternConverter(currentLiteral.toString())); 248 } 250 return head; 251 } 252 253 protected void finalizeConverter(char c) 254 { 255 PatternConverter pc = null; 256 switch (c) 257 { 258 case 'c': 259 pc = new CategoryPatternConverter(formattingInfo, 260 extractPrecisionOption()); 261 currentLiteral.setLength(0); 264 break; 265 case 'C': 266 pc = new ClassNamePatternConverter(formattingInfo, 267 extractPrecisionOption()); 268 currentLiteral.setLength(0); 271 break; 272 case 'd': 273 String dateFormatStr = AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT; 274 DateFormat df; 275 String dOpt = extractOption(); 276 if (dOpt != null) 277 dateFormatStr = dOpt; 278 279 if (dateFormatStr.equalsIgnoreCase( 280 AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT)) 281 df = new ISO8601DateFormat(); 282 else if (dateFormatStr.equalsIgnoreCase( 283 AbsoluteTimeDateFormat.ABS_TIME_DATE_FORMAT)) 284 df = new AbsoluteTimeDateFormat(); 285 else if (dateFormatStr.equalsIgnoreCase( 286 AbsoluteTimeDateFormat.DATE_AND_TIME_DATE_FORMAT)) 287 df = new DateTimeDateFormat(); 288 else 289 { 290 try 291 { 292 df = new SimpleDateFormat (dateFormatStr); 293 } 294 catch (IllegalArgumentException e) 295 { 296 System.err.println("Could not instantiate SimpleDateFormat with " + 297 dateFormatStr + ", ex=" + e.getMessage()); 298 df = new ISO8601DateFormat(); 299 } 300 } 301 pc = new DatePatternConverter(formattingInfo, df); 302 currentLiteral.setLength(0); 305 break; 306 case 'F': 307 pc = new LocationPatternConverter(formattingInfo, 308 FILE_LOCATION_CONVERTER); 309 currentLiteral.setLength(0); 312 break; 313 case 'l': 314 pc = new LocationPatternConverter(formattingInfo, 315 FULL_LOCATION_CONVERTER); 316 currentLiteral.setLength(0); 319 break; 320 case 'L': 321 pc = new LocationPatternConverter(formattingInfo, 322 LINE_LOCATION_CONVERTER); 323 currentLiteral.setLength(0); 326 break; 327 case 'm': 328 pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER); 329 currentLiteral.setLength(0); 332 break; 333 case 'M': 334 pc = new LocationPatternConverter(formattingInfo, 335 METHOD_LOCATION_CONVERTER); 336 currentLiteral.setLength(0); 339 break; 340 case 'p': 341 pc = new BasicPatternConverter(formattingInfo, LEVEL_CONVERTER); 342 currentLiteral.setLength(0); 345 break; 346 case 'r': 347 pc = new BasicPatternConverter(formattingInfo, 348 RELATIVE_TIME_CONVERTER); 349 currentLiteral.setLength(0); 352 break; 353 case 't': 354 pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER); 355 currentLiteral.setLength(0); 358 break; 359 373 case 'x': 374 pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER); 375 currentLiteral.setLength(0); 377 break; 378 case 'X': 379 String xOpt = extractOption(); 380 pc = new MDCPatternConverter(formattingInfo, xOpt); 381 currentLiteral.setLength(0); 382 break; 383 default: 384 System.err.println("Unexpected char [" + c + "] at position " + i 385 + " in conversion patterrn."); 386 pc = new LiteralPatternConverter(currentLiteral.toString()); 387 currentLiteral.setLength(0); 388 } 389 390 addConverter(pc); 391 } 392 393 protected void addConverter(PatternConverter pc) 394 { 395 currentLiteral.setLength(0); 396 addToList(pc); 398 state = LITERAL_STATE; 400 formattingInfo.reset(); 402 } 403 404 408 private static class BasicPatternConverter extends PatternConverter 409 { 410 int type; 411 412 BasicPatternConverter(FormattingInfo formattingInfo, int type) 413 { 414 super(formattingInfo); 415 this.type = type; 416 } 417 418 public String convert(LogRecord event) 419 { 420 switch (type) 421 { 422 case RELATIVE_TIME_CONVERTER: 423 return (Long.toString(event.getMillis() - startTime)); 424 case THREAD_CONVERTER: 425 StringBuffer tmp = new StringBuffer ("tid("); 426 tmp.append(event.getThreadID()); 427 tmp.append(')'); 428 return tmp.toString(); 429 case THREAD_NAME_CONVERTER: 430 return "null"; 432 case LEVEL_CONVERTER: 433 return event.getLevel().toString(); 434 case NDC_CONVERTER: 435 return "NDC not supported"; 436 case MESSAGE_CONVERTER: 437 { 438 return event.getMessage(); 439 } 440 default: 441 return null; 442 } 443 } 444 } 445 446 private static class LiteralPatternConverter extends PatternConverter 447 { 448 private String literal; 449 450 LiteralPatternConverter(String value) 451 { 452 literal = value; 453 } 454 455 public 456 final void format(StringBuffer sbuf, LogRecord event) 457 { 458 sbuf.append(literal); 459 } 460 461 public String convert(LogRecord event) 462 { 463 return literal; 464 } 465 } 466 467 private static class DatePatternConverter extends PatternConverter 468 { 469 private DateFormat df; 470 private Date date; 471 472 DatePatternConverter(FormattingInfo formattingInfo, DateFormat df) 473 { 474 super(formattingInfo); 475 date = new Date (); 476 this.df = df; 477 } 478 479 public String convert(LogRecord event) 480 { 481 date.setTime(event.getMillis()); 482 String converted = null; 483 try 484 { 485 converted = df.format(date); 486 } 487 catch (Exception ex) 488 { 489 System.err.println("Error occured while converting date, " + ex.getMessage()); 490 } 491 return converted; 492 } 493 } 494 495 498 private static class MDCPatternConverter extends PatternConverter 499 { 500 private String key; 501 502 MDCPatternConverter(FormattingInfo formattingInfo, String key) 503 { 504 super(formattingInfo); 505 this.key = key; 506 } 507 508 public String convert(LogRecord event) 509 { 510 Object val = null; if (val == null) 512 { 513 return null; 514 } 515 else 516 { 517 return val.toString(); 518 } 519 } 520 } 521 522 523 private class LocationPatternConverter extends PatternConverter 524 { 525 int type; 526 527 LocationPatternConverter(FormattingInfo formattingInfo, int type) 528 { 529 super(formattingInfo); 530 this.type = type; 531 } 532 533 public String convert(LogRecord event) 534 { 535 switch (type) 536 { 537 case FULL_LOCATION_CONVERTER: 538 return "Class: " + event.getSourceClassName() + "." + event.getSourceMethodName(); 539 case METHOD_LOCATION_CONVERTER: 540 return event.getSourceMethodName(); 541 case LINE_LOCATION_CONVERTER: 542 return "0"; 543 case FILE_LOCATION_CONVERTER: 544 return event.getSourceClassName(); 545 default: 546 return null; 547 } 548 } 549 } 550 551 private static abstract class NamedPatternConverter extends PatternConverter 552 { 553 int precision; 554 555 NamedPatternConverter(FormattingInfo formattingInfo, int precision) 556 { 557 super(formattingInfo); 558 this.precision = precision; 559 } 560 561 abstract String getFullyQualifiedName(LogRecord event); 562 563 public String convert(LogRecord event) 564 { 565 String n = getFullyQualifiedName(event); 566 if (precision <= 0) 567 return n; 568 else 569 { 570 int len = n.length(); 571 572 int end = len - 1; 576 for (int i = precision; i > 0; i--) 577 { 578 end = n.lastIndexOf('.', end - 1); 579 if (end == -1) 580 return n; 581 } 582 return n.substring(end + 1, len); 583 } 584 } 585 } 586 587 private class ClassNamePatternConverter extends NamedPatternConverter 588 { 589 590 ClassNamePatternConverter(FormattingInfo formattingInfo, int precision) 591 { 592 super(formattingInfo, precision); 593 } 594 595 String getFullyQualifiedName(LogRecord event) 596 { 597 return event.getSourceClassName(); 598 } 599 } 600 601 private class CategoryPatternConverter extends NamedPatternConverter 602 { 603 604 CategoryPatternConverter(FormattingInfo formattingInfo, int precision) 605 { 606 super(formattingInfo, precision); 607 } 608 609 String getFullyQualifiedName(LogRecord event) 610 { 611 return event.getLoggerName(); 612 } 613 } 614 615 } 616 | Popular Tags |