1 8 package org.jivesoftware.util.log.format; 9 10 import org.jivesoftware.util.log.ContextMap; 11 import org.jivesoftware.util.log.LogEvent; 12 import org.jivesoftware.util.log.Priority; 13 import java.io.StringWriter ; 14 import java.text.SimpleDateFormat ; 15 import java.util.Date ; 16 import java.util.Stack ; 17 18 77 public class PatternFormatter implements Formatter { 78 private final static int TYPE_TEXT = 1; 79 private final static int TYPE_CATEGORY = 2; 80 private final static int TYPE_CONTEXT = 3; 81 private final static int TYPE_MESSAGE = 4; 82 private final static int TYPE_TIME = 5; 83 private final static int TYPE_RELATIVE_TIME = 6; 84 private final static int TYPE_THROWABLE = 7; 85 private final static int TYPE_PRIORITY = 8; 86 87 91 protected final static int MAX_TYPE = TYPE_PRIORITY; 92 93 private final static String TYPE_CATEGORY_STR = "category"; 94 private final static String TYPE_CONTEXT_STR = "context"; 95 private final static String TYPE_MESSAGE_STR = "message"; 96 private final static String TYPE_TIME_STR = "time"; 97 private final static String TYPE_RELATIVE_TIME_STR = "rtime"; 98 private final static String TYPE_THROWABLE_STR = "throwable"; 99 private final static String TYPE_PRIORITY_STR = "priority"; 100 101 private final static String SPACE_16 = " "; 102 private final static String SPACE_8 = " "; 103 private final static String SPACE_4 = " "; 104 private final static String SPACE_2 = " "; 105 private final static String SPACE_1 = " "; 106 107 private final static String EOL = System.getProperty("line.separator", "\n"); 108 109 protected static class PatternRun { 110 public String m_data; 111 public boolean m_rightJustify; 112 public int m_minSize; 113 public int m_maxSize; 114 public int m_type; 115 public String m_format; 116 } 117 118 private PatternRun m_formatSpecification[]; 119 120 private SimpleDateFormat m_simpleDateFormat; 121 private final Date m_date = new Date (); 122 123 127 public PatternFormatter() { 128 } 129 130 public PatternFormatter(final String pattern) { 131 parse(pattern); 132 } 133 134 142 private int addPatternRun(final Stack stack, 143 final char pattern[], 144 int index) { 145 final PatternRun run = new PatternRun(); 146 final int start = index++; 147 148 if ('+' == pattern[index]) 150 index++; 151 else if ('-' == pattern[index]) { 152 run.m_rightJustify = true; 153 index++; 154 } 155 156 if (Character.isDigit(pattern[index])) { 157 int total = 0; 158 while (Character.isDigit(pattern[index])) { 159 total = total * 10 + (pattern[index] - '0'); 160 index++; 161 } 162 run.m_minSize = total; 163 } 164 165 if (index < pattern.length && '.' == pattern[index]) { 167 index++; 168 169 if (Character.isDigit(pattern[index])) { 170 int total = 0; 171 while (Character.isDigit(pattern[index])) { 172 total = total * 10 + (pattern[index] - '0'); 173 index++; 174 } 175 run.m_maxSize = total; 176 } 177 } 178 179 if (index >= pattern.length || '{' != pattern[index]) { 180 throw 181 new IllegalArgumentException ("Badly formed pattern at character " + 182 index); 183 } 184 185 int typeStart = index; 186 187 while (index < pattern.length && 188 pattern[index] != ':' && pattern[index] != '}') { 189 index++; 190 } 191 192 int typeEnd = index - 1; 193 194 final String type = 195 new String (pattern, typeStart + 1, typeEnd - typeStart); 196 197 run.m_type = getTypeIdFor(type); 198 199 if (index < pattern.length && pattern[index] == ':') { 200 index++; 201 while (index < pattern.length && pattern[index] != '}') index++; 202 203 final int length = index - typeEnd - 2; 204 205 if (0 != length) { 206 run.m_format = new String (pattern, typeEnd + 2, length); 207 } 208 } 209 210 if (index >= pattern.length || '}' != pattern[index]) { 211 throw new 212 IllegalArgumentException ("Unterminated type in pattern at character " 213 + index); 214 } 215 216 index++; 217 218 stack.push(run); 219 220 return index - start; 221 } 222 223 233 private int addTextRun(final Stack stack, 234 final char pattern[], 235 int index) { 236 final PatternRun run = new PatternRun(); 237 final int start = index; 238 boolean escapeMode = false; 239 240 if ('%' == pattern[index]) index++; 241 242 final StringBuffer sb = new StringBuffer (); 243 244 while (index < pattern.length && pattern[index] != '%') { 245 if (escapeMode) { 246 if ('n' == pattern[index]) 247 sb.append(EOL); 248 else if ('t' == pattern[index]) 249 sb.append('\t'); 250 else 251 sb.append(pattern[index]); 252 escapeMode = false; 253 } 254 else if ('\\' == pattern[index]) 255 escapeMode = true; 256 else 257 sb.append(pattern[index]); 258 index++; 259 } 260 261 run.m_data = sb.toString(); 262 run.m_type = TYPE_TEXT; 263 264 stack.push(run); 265 266 return index - start; 267 } 268 269 278 private void append(final StringBuffer sb, 279 final int minSize, 280 final int maxSize, 281 final boolean rightJustify, 282 final String output) { 283 final int size = output.length(); 284 285 if (size < minSize) { 286 if (rightJustify) { 288 appendWhiteSpace(sb, minSize - size); 289 sb.append(output); 290 } 291 else { 292 sb.append(output); 293 appendWhiteSpace(sb, minSize - size); 294 } 295 } 296 else if (maxSize > 0 && maxSize < size) { 297 if (rightJustify) { 298 sb.append(output.substring(size - maxSize)); 299 } 300 else { 301 sb.append(output.substring(0, maxSize)); 302 } 303 } 304 else { 305 sb.append(output); 306 } 307 } 308 309 315 private void appendWhiteSpace(final StringBuffer sb, int length) { 316 while (length >= 16) { 317 sb.append(SPACE_16); 318 length -= 16; 319 } 320 321 if (length >= 8) { 322 sb.append(SPACE_8); 323 length -= 8; 324 } 325 326 if (length >= 4) { 327 sb.append(SPACE_4); 328 length -= 4; 329 } 330 331 if (length >= 2) { 332 sb.append(SPACE_2); 333 length -= 2; 334 } 335 336 if (length >= 1) { 337 sb.append(SPACE_1); 338 length -= 1; 339 } 340 } 341 342 348 public String format(final LogEvent event) { 349 final StringBuffer sb = new StringBuffer (); 350 351 for (int i = 0; i < m_formatSpecification.length; i++) { 352 final PatternRun run = m_formatSpecification[i]; 353 354 if (run.m_type == TYPE_TEXT) { 356 sb.append(run.m_data); 357 } 358 else { 359 final String data = formatPatternRun(event, run); 360 361 if (null != data) { 362 append(sb, run.m_minSize, run.m_maxSize, run.m_rightJustify, data); 363 } 364 } 365 } 366 367 return sb.toString(); 368 } 369 370 376 protected String formatPatternRun(final LogEvent event, final PatternRun run) { 377 switch (run.m_type) { 378 case TYPE_RELATIVE_TIME: 379 return getRTime(event.getRelativeTime(), run.m_format); 380 case TYPE_TIME: 381 return getTime(event.getTime(), run.m_format); 382 case TYPE_THROWABLE: 383 return getStackTrace(event.getThrowable(), run.m_format); 384 case TYPE_MESSAGE: 385 return getMessage(event.getMessage(), run.m_format); 386 case TYPE_CATEGORY: 387 return getCategory(event.getCategory(), run.m_format); 388 case TYPE_PRIORITY: 389 return getPriority(event.getPriority(), run.m_format); 390 391 case TYPE_CONTEXT: 392 return getContextMap(event.getContextMap(), run.m_format); 402 404 default: 405 throw new IllegalStateException ("Unknown Pattern specification." + run.m_type); 406 } 407 } 408 409 416 protected String getCategory(final String category, final String format) { 417 return category; 418 } 419 420 423 protected String getPriority(final Priority priority, final String format) { 424 return priority.getName(); 425 } 426 427 440 453 460 protected String getContextMap(final ContextMap map, final String format) { 461 if (null == map) return ""; 462 return map.get(format, "").toString(); 463 } 464 465 472 protected String getMessage(final String message, final String format) { 473 return message; 474 } 475 476 483 protected String getStackTrace(final Throwable throwable, final String format) { 484 if (null == throwable) return ""; 485 final StringWriter sw = new StringWriter (); 486 throwable.printStackTrace(new java.io.PrintWriter (sw)); 487 return sw.toString(); 488 } 489 490 497 protected String getRTime(final long time, final String format) { 498 return getTime(time, format); 499 } 500 501 508 protected String getTime(final long time, final String format) { 509 if (null == format) { 510 return Long.toString(time); 511 } 512 else { 513 synchronized (m_date) { 514 if (null == m_simpleDateFormat) { 515 m_simpleDateFormat = new SimpleDateFormat (format); 516 } 517 m_date.setTime(time); 518 return m_simpleDateFormat.format(m_date); 519 } 520 } 521 } 522 523 529 protected int getTypeIdFor(final String type) { 530 if (type.equalsIgnoreCase(TYPE_CATEGORY_STR)) 531 return TYPE_CATEGORY; 532 else if (type.equalsIgnoreCase(TYPE_CONTEXT_STR)) 533 return TYPE_CONTEXT; 534 else if (type.equalsIgnoreCase(TYPE_MESSAGE_STR)) 535 return TYPE_MESSAGE; 536 else if (type.equalsIgnoreCase(TYPE_PRIORITY_STR)) 537 return TYPE_PRIORITY; 538 else if (type.equalsIgnoreCase(TYPE_TIME_STR)) 539 return TYPE_TIME; 540 else if (type.equalsIgnoreCase(TYPE_RELATIVE_TIME_STR)) 541 return TYPE_RELATIVE_TIME; 542 else if (type.equalsIgnoreCase(TYPE_THROWABLE_STR)) { 543 return TYPE_THROWABLE; 544 } 545 else { 546 throw new IllegalArgumentException ("Unknown Type in pattern - " + 547 type); 548 } 549 } 550 551 556 protected final void parse(final String patternString) { 557 final Stack stack = new Stack (); 558 final int size = patternString.length(); 559 final char pattern[] = new char[size]; 560 int index = 0; 561 562 patternString.getChars(0, size, pattern, 0); 563 564 while (index < size) { 565 if (pattern[index] == '%' && 566 !(index != size - 1 && pattern[index + 1] == '%')) { 567 index += addPatternRun(stack, pattern, index); 568 } 569 else { 570 index += addTextRun(stack, pattern, index); 571 } 572 } 573 574 final int elementCount = stack.size(); 575 576 m_formatSpecification = new PatternRun[elementCount]; 577 578 for (int i = 0; i < elementCount; i++) { 579 m_formatSpecification[i] = (PatternRun)stack.elementAt(i); 580 } 581 } 582 583 589 public void setFormat(final String format) { 590 parse(format); 591 } 592 } 593 | Popular Tags |