1 17 package org.apache.log.format; 18 19 import java.io.StringWriter ; 20 import java.text.SimpleDateFormat ; 21 import java.util.Date ; 22 import java.util.Stack ; 23 import org.apache.log.ContextMap; 24 import org.apache.log.LogEvent; 25 import org.apache.log.Priority; 26 27 114 public class PatternFormatter 115 implements Formatter 116 { 117 private static final int TYPE_TEXT = 1; 118 private static final int TYPE_CATEGORY = 2; 119 private static final int TYPE_CONTEXT = 3; 120 private static final int TYPE_MESSAGE = 4; 121 private static final int TYPE_TIME = 5; 122 private static final int TYPE_RELATIVE_TIME = 6; 123 private static final int TYPE_THROWABLE = 7; 124 private static final int TYPE_PRIORITY = 8; 125 private static final int TYPE_THREAD = 9; 126 127 131 protected static final int MAX_TYPE = TYPE_PRIORITY; 132 133 private static final String TYPE_CATEGORY_STR = "category"; 134 private static final String TYPE_CONTEXT_STR = "context"; 135 private static final String TYPE_MESSAGE_STR = "message"; 136 private static final String TYPE_TIME_STR = "time"; 137 private static final String TYPE_RELATIVE_TIME_STR = "rtime"; 138 private static final String TYPE_THROWABLE_STR = "throwable"; 139 private static final String TYPE_PRIORITY_STR = "priority"; 140 private static final String TYPE_THREAD_STR = "thread"; 141 142 private static final String SPACE_16 = " "; 143 private static final String SPACE_8 = " "; 144 private static final String SPACE_4 = " "; 145 private static final String SPACE_2 = " "; 146 private static final String SPACE_1 = " "; 147 148 private static final String EOL = System.getProperty( "line.separator", "\n" ); 149 150 protected static class PatternRun 151 { 152 public String m_data; 153 public boolean m_rightJustify; 154 public int m_minSize; 155 public int m_maxSize; 156 public int m_type; 157 public String m_format; 158 } 159 160 private PatternRun m_formatSpecification[]; 161 162 private SimpleDateFormat m_simpleDateFormat; 163 private final Date m_date = new Date (); 164 165 169 public PatternFormatter( final String pattern ) 170 { 171 parse( pattern ); 172 } 173 174 182 private int addPatternRun( final Stack stack, 183 final char pattern[], 184 int index ) 185 { 186 final PatternRun run = new PatternRun(); 187 final int start = index++; 188 189 if( '+' == pattern[ index ] ) 191 { 192 index++; 193 } 194 else if( '-' == pattern[ index ] ) 195 { 196 run.m_rightJustify = true; 197 index++; 198 } 199 200 if( Character.isDigit( pattern[ index ] ) ) 201 { 202 int total = 0; 203 while( Character.isDigit( pattern[ index ] ) ) 204 { 205 total = total * 10 + ( pattern[ index ] - '0' ); 206 index++; 207 } 208 run.m_minSize = total; 209 } 210 211 if( index < pattern.length && '.' == pattern[ index ] ) 213 { 214 index++; 215 216 if( Character.isDigit( pattern[ index ] ) ) 217 { 218 int total = 0; 219 while( Character.isDigit( pattern[ index ] ) ) 220 { 221 total = total * 10 + ( pattern[ index ] - '0' ); 222 index++; 223 } 224 run.m_maxSize = total; 225 } 226 } 227 228 if( index >= pattern.length || '{' != pattern[ index ] ) 229 { 230 throw new IllegalArgumentException ( 231 "Badly formed pattern at character " + index ); 232 } 233 234 int typeStart = index; 235 236 while( index < pattern.length 237 && pattern[ index ] != ':' && pattern[ index ] != '}' ) 238 { 239 index++; 240 } 241 242 int typeEnd = index - 1; 243 244 final String type = 245 new String ( pattern, typeStart + 1, typeEnd - typeStart ); 246 247 run.m_type = getTypeIdFor( type ); 248 249 if( index < pattern.length && pattern[ index ] == ':' ) 250 { 251 index++; 252 while( index < pattern.length && pattern[ index ] != '}' ) index++; 253 254 final int length = index - typeEnd - 2; 255 256 if( 0 != length ) 257 { 258 run.m_format = new String ( pattern, typeEnd + 2, length ); 259 } 260 } 261 262 if( index >= pattern.length || '}' != pattern[ index ] ) 263 { 264 throw new IllegalArgumentException ( 265 "Unterminated type in pattern at character " 266 + index ); 267 } 268 269 index++; 270 271 stack.push( run ); 272 273 return index - start; 274 } 275 276 286 private int addTextRun( final Stack stack, 287 final char pattern[], 288 int index ) 289 { 290 final PatternRun run = new PatternRun(); 291 final int start = index; 292 boolean escapeMode = false; 293 294 if( '%' == pattern[ index ] ) 295 { 296 index++; 297 } 298 299 final StringBuffer sb = new StringBuffer (); 300 301 while( index < pattern.length && pattern[ index ] != '%' ) 302 { 303 if( escapeMode ) 304 { 305 if( 'n' == pattern[ index ] ) 306 { 307 sb.append( EOL ); 308 } 309 else if( 't' == pattern[ index ] ) 310 { 311 sb.append( '\t' ); 312 } 313 else 314 { 315 sb.append( pattern[ index ] ); 316 } 317 escapeMode = false; 318 } 319 else if( '\\' == pattern[ index ] ) 320 { 321 escapeMode = true; 322 } 323 else 324 { 325 sb.append( pattern[ index ] ); 326 } 327 index++; 328 } 329 330 run.m_data = sb.toString(); 331 run.m_type = TYPE_TEXT; 332 333 stack.push( run ); 334 335 return index - start; 336 } 337 338 347 private void append( final StringBuffer sb, 348 final int minSize, 349 final int maxSize, 350 final boolean rightJustify, 351 final String output ) 352 { 353 final int size = output.length(); 354 355 if( size < minSize ) 356 { 357 if( rightJustify ) 359 { 360 appendWhiteSpace( sb, minSize - size ); 361 sb.append( output ); 362 } 363 else 364 { 365 sb.append( output ); 366 appendWhiteSpace( sb, minSize - size ); 367 } 368 } 369 else if( maxSize > 0 && maxSize < size ) 370 { 371 if( rightJustify ) 372 { 373 sb.append( output.substring( size - maxSize ) ); 374 } 375 else 376 { 377 sb.append( output.substring( 0, maxSize ) ); 378 } 379 } 380 else 381 { 382 sb.append( output ); 383 } 384 } 385 386 392 private void appendWhiteSpace( final StringBuffer sb, int length ) 393 { 394 while( length >= 16 ) 395 { 396 sb.append( SPACE_16 ); 397 length -= 16; 398 } 399 400 if( length >= 8 ) 401 { 402 sb.append( SPACE_8 ); 403 length -= 8; 404 } 405 406 if( length >= 4 ) 407 { 408 sb.append( SPACE_4 ); 409 length -= 4; 410 } 411 412 if( length >= 2 ) 413 { 414 sb.append( SPACE_2 ); 415 length -= 2; 416 } 417 418 if( length >= 1 ) 419 { 420 sb.append( SPACE_1 ); 421 length -= 1; 422 } 423 } 424 425 431 public String format( final LogEvent event ) 432 { 433 final StringBuffer sb = new StringBuffer (); 434 435 for( int i = 0; i < m_formatSpecification.length; i++ ) 436 { 437 final PatternRun run = m_formatSpecification[ i ]; 438 439 if( run.m_type == TYPE_TEXT ) 441 { 442 sb.append( run.m_data ); 443 } 444 else 445 { 446 final String data = formatPatternRun( event, run ); 447 if( null != data ) 448 { 449 append( sb, run.m_minSize, run.m_maxSize, run.m_rightJustify, data ); 450 } 451 } 452 } 453 454 return sb.toString(); 455 } 456 457 463 protected String formatPatternRun( final LogEvent event, final PatternRun run ) 464 { 465 switch( run.m_type ) 466 { 467 case TYPE_RELATIVE_TIME: 468 return getRTime( event.getRelativeTime(), run.m_format ); 469 case TYPE_TIME: 470 return getTime( event.getTime(), run.m_format ); 471 case TYPE_THROWABLE: 472 return getStackTrace( event.getThrowable(), run.m_format ); 473 case TYPE_MESSAGE: 474 return getMessage( event.getMessage(), run.m_format ); 475 case TYPE_CATEGORY: 476 return getCategory( event.getCategory(), run.m_format ); 477 case TYPE_PRIORITY: 478 return getPriority( event.getPriority(), run.m_format ); 479 480 case TYPE_CONTEXT: 481 return getContextMap( event.getContextMap(), run.m_format ); 482 483 case TYPE_THREAD: 484 return getThread( run.m_format ); 485 486 default: 487 throw new IllegalStateException ( "Unknown Pattern specification." + run.m_type ); 488 } 489 } 490 491 498 protected String getCategory( final String category, final String format ) 499 { 500 return category; 501 } 502 503 506 protected String getPriority( final Priority priority, final String format ) 507 { 508 return priority.getName(); 509 } 510 511 514 protected String getThread( final String format ) 515 { 516 return Thread.currentThread().getName(); 517 } 518 519 526 protected String getContextMap( final ContextMap map, final String format ) 527 { 528 if( null == map ) return ""; 529 return map.get( format, "" ).toString(); 530 } 531 532 539 protected String getMessage( final String message, final String format ) 540 { 541 return message; 542 } 543 544 551 protected String getStackTrace( final Throwable throwable, final String format ) 552 { 553 if( null == throwable ) return ""; 554 final StringWriter sw = new StringWriter (); 555 throwable.printStackTrace( new java.io.PrintWriter ( sw ) ); 556 return sw.toString(); 557 } 558 559 566 protected String getRTime( final long time, final String format ) 567 { 568 return getTime( time, format ); 569 } 570 571 578 protected String getTime( final long time, final String format ) 579 { 580 if( null == format ) 581 { 582 return Long.toString( time ); 583 } 584 else 585 { 586 synchronized( m_date ) 587 { 588 if( null == m_simpleDateFormat ) 589 { 590 m_simpleDateFormat = new SimpleDateFormat ( format ); 591 } 592 m_date.setTime( time ); 593 return m_simpleDateFormat.format( m_date ); 594 } 595 } 596 } 597 598 604 protected int getTypeIdFor( final String type ) 605 { 606 if( type.equalsIgnoreCase( TYPE_CATEGORY_STR ) ) 607 { 608 return TYPE_CATEGORY; 609 } 610 else if( type.equalsIgnoreCase( TYPE_CONTEXT_STR ) ) 611 { 612 return TYPE_CONTEXT; 613 } 614 else if( type.equalsIgnoreCase( TYPE_MESSAGE_STR ) ) 615 { 616 return TYPE_MESSAGE; 617 } 618 else if( type.equalsIgnoreCase( TYPE_PRIORITY_STR ) ) 619 { 620 return TYPE_PRIORITY; 621 } 622 else if( type.equalsIgnoreCase( TYPE_TIME_STR ) ) 623 { 624 return TYPE_TIME; 625 } 626 else if( type.equalsIgnoreCase( TYPE_RELATIVE_TIME_STR ) ) 627 { 628 return TYPE_RELATIVE_TIME; 629 } 630 else if( type.equalsIgnoreCase( TYPE_THREAD_STR ) ) 631 { 632 return TYPE_THREAD; 633 } 634 else if( type.equalsIgnoreCase( TYPE_THROWABLE_STR ) ) 635 { 636 return TYPE_THROWABLE; 637 } 638 else 639 { 640 throw new IllegalArgumentException ( "Unknown Type in pattern - " + 641 type ); 642 } 643 } 644 645 650 protected final void parse( final String patternString ) 651 { 652 final Stack stack = new Stack (); 653 final int size = patternString.length(); 654 final char pattern[] = new char[ size ]; 655 int index = 0; 656 657 patternString.getChars( 0, size, pattern, 0 ); 658 659 while( index < size ) 660 { 661 if( pattern[ index ] == '%' 662 && !( index != size - 1 && pattern[ index + 1 ] == '%' ) ) 663 { 664 index += addPatternRun( stack, pattern, index ); 665 } 666 else 667 { 668 index += addTextRun( stack, pattern, index ); 669 } 670 } 671 672 final int elementCount = stack.size(); 673 674 m_formatSpecification = new PatternRun[ elementCount ]; 675 676 for( int i = 0; i < elementCount; i++ ) 677 { 678 m_formatSpecification[ i ] = (PatternRun)stack.elementAt( i ); 679 } 680 } 681 682 } 683 | Popular Tags |