1 package org.incava.qualog; 2 3 import java.io.*; 4 import java.util.*; 5 6 7 14 public class QlWriter 15 { 16 public static final int NO_OUTPUT = 0; 17 18 public static final int QUIET = 1; 19 20 public static final int VERBOSE = 2; 21 22 public int fileWidth = 25; 23 24 public boolean columns = true; 25 26 public int lineWidth = 5; 27 28 public int functionWidth = 25; 29 30 public int classWidth = 35; 31 32 public boolean showFiles = true; 33 34 public boolean showClasses = true; 35 36 public PrintWriter out = new PrintWriter(System.out, true); 37 38 public List packagesSkipped = new ArrayList(Arrays.asList( 39 new String [] { 40 "org.incava.qualog", 41 })); 42 43 public List classesSkipped = new ArrayList(Arrays.asList( 44 new String [] { 45 "tr.Ace" 46 })); 47 48 public List methodsSkipped = new ArrayList(Arrays.asList( 49 new String [] { 50 })); 51 52 private int outputType = NO_OUTPUT; 53 54 private Map packageColors = new HashMap(); 55 56 private Map classColors = new HashMap(); 57 58 private Map methodColors = new HashMap(); 59 60 private Map fileColors = new HashMap(); 61 62 private Map levelColors = new HashMap(); 63 64 private StackTraceElement prevStackElement = null; 65 66 private Thread prevThread = null; 67 68 private String prevDisplayedClass = null; 69 70 private String prevDisplayedMethod = null; 71 72 private QlLevel level = Qualog.LEVEL9; 73 74 private List filters = new ArrayList(); 75 76 private boolean useColor = true; 77 78 83 public void addFilter(QlFilter filter) 84 { 85 filters.add(filter); 86 } 87 88 public void setDisabled(Class cls) 89 { 90 addFilter(new QlClassFilter(cls, null)); 91 } 92 93 public void setClassColor(String className, ANSIColor color) 94 { 95 classColors.put(className, color); 96 } 97 98 public void setPackageColor(String pkg, ANSIColor color) 99 { 100 } 101 102 public void setMethodColor(String className, String methodName, ANSIColor color) 103 { 104 methodColors.put(className + "#" + methodName, color); 105 } 106 107 public void clearClassColor(String className) 108 { 109 classColors.remove(className); 110 } 111 112 public void setFileColor(String fileName, ANSIColor color) 113 { 114 fileColors.put(fileName, color); 115 } 116 117 public void set(boolean columns, int fileWidth, int lineWidth, int classWidth, int functionWidth) 118 { 119 this.columns = columns; 120 this.fileWidth = fileWidth; 121 this.lineWidth = lineWidth; 122 this.classWidth = classWidth; 123 this.functionWidth = functionWidth; 124 } 125 126 129 public void setOutput(int type, QlLevel level) 130 { 131 this.outputType = type; 132 this.level = level; 133 } 134 135 public boolean verbose() 136 { 137 return outputType == VERBOSE; 138 } 139 140 public void setColumns(boolean cols) 141 { 142 columns = cols; 143 } 144 145 public void addClassSkipped(Class cls) 146 { 147 addClassSkipped(cls.getName()); 148 } 149 150 public void addClassSkipped(String clsName) 151 { 152 classesSkipped.add(clsName); 153 } 154 155 158 public void clear() 159 { 160 packageColors = new HashMap(); 161 classColors = new HashMap(); 162 methodColors = new HashMap(); 163 fileColors = new HashMap(); 164 levelColors = new HashMap(); 165 prevStackElement = null; 166 prevThread = null; 167 prevDisplayedClass = null; 168 prevDisplayedMethod = null; 169 level = Qualog.LEVEL9; 170 filters = new ArrayList(); 171 } 172 173 public void reset() 174 { 175 prevThread = Thread.currentThread(); 176 prevStackElement = null; 177 } 178 179 public boolean stack(QlLevel level, 180 ANSIColor[] msgColors, 181 String name, 182 Object obj, 183 ANSIColor fileColor, 184 ANSIColor classColor, 185 ANSIColor methodColor, 186 int numFrames) 187 { 188 if (isLoggable(level)) { 189 String nm = name == null ? "" : name; 190 191 if (obj == null) { 192 String msg = nm + ": " + "null"; 193 return stack(level, msgColors, msg, fileColor, classColor, methodColor, numFrames); 194 } 195 else if (obj instanceof Collection) { 196 Collection c = (Collection)obj; 197 return QlCollection.stack(level, msgColors, nm, c, fileColor, classColor, methodColor, numFrames); 198 } 199 else if (obj instanceof Iterator) { 200 Iterator it = (Iterator)obj; 201 return QlIterator.stack(level, msgColors, nm, it, fileColor, classColor, methodColor, numFrames); 202 } 203 else if (obj instanceof Enumeration) { 204 Enumeration en = (Enumeration)obj; 205 return QlEnumeration.stack(level, msgColors, nm, en, fileColor, classColor, methodColor, numFrames); 206 } 207 else if (obj instanceof Object []) { 208 Object [] ary = (Object [])obj; 209 return QlObjectArray.stack(level, msgColors, nm, ary, fileColor, classColor, methodColor, numFrames); 210 } 211 else if (obj instanceof Map) { 212 Map m = (Map)obj; 213 return QlMap.stack(level, msgColors, nm, m, fileColor, classColor, methodColor, numFrames); 214 } 215 else if (obj.getClass().isArray()) { 216 String [] strs = null; 217 if (obj instanceof byte[]) { 218 byte[] ary = (byte[])obj; 219 strs = new String [ary.length]; 220 for (int ai = 0; ai < ary.length; ++ai) { 221 strs[ai] = String.valueOf(ary[ai]); 222 } 223 } 224 else if (obj instanceof char[]) { 225 char[] ary = (char[])obj; 226 strs = new String [ary.length]; 227 for (int ai = 0; ai < ary.length; ++ai) { 228 strs[ai] = String.valueOf(ary[ai]); 229 } 230 } 231 else if (obj instanceof double[]) { 232 double[] ary = (double[])obj; 233 strs = new String [ary.length]; 234 for (int ai = 0; ai < ary.length; ++ai) { 235 strs[ai] = String.valueOf(ary[ai]); 236 } 237 } 238 else if (obj instanceof float[]) { 239 float[] ary = (float[])obj; 240 strs = new String [ary.length]; 241 for (int ai = 0; ai < ary.length; ++ai) { 242 strs[ai] = String.valueOf(ary[ai]); 243 } 244 } 245 else if (obj instanceof int[]) { 246 int[] ary = (int[])obj; 247 strs = new String [ary.length]; 248 for (int ai = 0; ai < ary.length; ++ai) { 249 strs[ai] = String.valueOf(ary[ai]); 250 } 251 } 252 else if (obj instanceof long[]) { 253 long[] ary = (long[])obj; 254 strs = new String [ary.length]; 255 for (int ai = 0; ai < ary.length; ++ai) { 256 strs[ai] = String.valueOf(ary[ai]); 257 } 258 } 259 260 return QlObjectArray.stack(level, msgColors, nm, strs, fileColor, classColor, methodColor, numFrames); 261 } 262 else { 263 String msg = nm + ": " + objectToString(obj); 264 return stack(level, msgColors, msg, fileColor, classColor, methodColor, numFrames); 265 } 266 } 267 else { 268 return true; 269 } 270 } 271 272 public boolean isSkipped(StackTraceElement ste) 273 { 274 String className = ste.getClassName(); 275 if (classesSkipped.contains(className) || methodsSkipped.contains(ste.getMethodName())) { 276 return true; 277 } 278 else { 279 Iterator pit = packagesSkipped.iterator(); 280 while (pit.hasNext()) { 281 String pkgName = (String )pit.next(); 282 if (className.startsWith(pkgName)) { 283 return true; 284 } 285 } 286 } 287 return false; 288 } 289 290 public boolean isLoggable(QlLevel level) 291 { 292 return outputType != NO_OUTPUT && this.level != null && this.level.compareTo(level) >= 0; 293 } 294 295 296 301 public synchronized int findStackStart(StackTraceElement [] stack) 302 { 303 for (int fi = 0; fi < stack.length; ++fi) { 304 if (!isSkipped(stack[fi])) { 305 return fi; 306 } 307 } 308 309 return stack.length; 310 } 311 312 public synchronized boolean stack(QlLevel lvl, 313 ANSIColor[] msgColor, 314 String msg, 315 ANSIColor fileColor, 316 ANSIColor classColor, 317 ANSIColor methodColor, 318 int numFrames) 319 { 320 if (isLoggable(lvl)) { 321 if (outputType == QUIET) { 322 numFrames = 1; 323 } 324 325 StackTraceElement [] stack = getStack(numFrames); 326 327 if (!Thread.currentThread().equals(prevThread)) { 329 reset(); 330 } 331 332 int fi = findStackStart(stack); 333 334 for (int framesShown = 0; fi < stack.length && framesShown < numFrames; ++fi, ++framesShown) { 335 StackTraceElement stackElement = stack[fi]; 336 String className = stackElement.getClassName(); 337 String methodName = stackElement.getMethodName(); 338 boolean filtered = false; 339 340 if (framesShown == 0) { 341 Iterator fit = filters.iterator(); 342 while (fit.hasNext()) { 343 QlFilter filter = (QlFilter)fit.next(); 344 int lineNum = stackElement.getLineNumber(); 345 String fileName = stackElement.getFileName(); 346 347 if (filter.isMatch(fileName, lineNum, className, methodName)) { 348 QlLevel flevel = filter.getLevel(); 349 filtered = filtered || flevel != null && level.compareTo(flevel) < 0; 350 } 351 } 352 } 353 354 if (filtered) { 355 return true; 356 } 357 358 StringBuffer buf = new StringBuffer (); 359 360 if (outputType == VERBOSE) { 361 if (showFiles) { 362 outputFileName(buf, fileColor, stackElement); 363 } 364 if (showClasses) { 365 outputClassAndMethod(buf, classColor, methodColor, stackElement); 366 } 367 } 368 outputMessage(buf, framesShown, msgColor, msg, stackElement); 369 370 out.println(buf.toString()); 371 372 374 prevStackElement = stackElement; 375 } 376 } 377 return true; 378 } 379 380 void setUseColor(boolean useColor) 381 { 382 this.useColor = useColor; 383 } 384 385 protected void outputFileName(StringBuffer buf, ANSIColor fileColor, StackTraceElement stackElement) 386 { 387 String fileName = stackElement.getFileName(); 388 389 buf.append("["); 390 if (fileName == null) { 391 fileName = ""; 392 } 393 394 if (prevStackElement != null && 395 prevStackElement.getFileName() != null && 396 prevStackElement.getFileName().equals(fileName)) { 397 398 int width = columns ? Math.min(fileWidth, fileName.length()) : fileName.length(); 399 fileName = repeat(width, ' '); 400 } 401 402 String lnStr = stackElement.getLineNumber() >= 0 ? String.valueOf(stackElement.getLineNumber()) : ""; 403 404 ANSIColor col = fileColor; 405 if (col == null) { 406 col = (ANSIColor)fileColors.get(fileName); 407 } 408 409 if (columns) { 410 if (col == null) { 411 appendPadded(buf, fileName, fileWidth); 412 buf.append(' '); 413 buf.append(repeat(lineWidth - lnStr.length(), ' ')).append(lnStr); 414 } 415 else { 416 buf.append(col); 417 buf.append(fileName); 418 buf.append(Qualog.NONE); 419 repeat(buf, fileWidth - fileName.length(), ' '); 420 repeat(buf, 1 + lineWidth - lnStr.length(), ' '); 421 buf.append(col).append(lnStr).append(Qualog.NONE); 422 } 423 } 424 else if (col == null) { 425 appendPadded(buf, fileName + ":" + lnStr, fileWidth); 426 } 427 else { 428 buf.append(col); 429 buf.append(fileName); 430 buf.append(':'); 431 buf.append(lnStr); 432 buf.append(Qualog.NONE); 433 repeat(buf, fileWidth - fileName.length() - 1 - lnStr.length(), ' '); 434 } 435 436 buf.append("] "); 437 } 438 439 protected void outputClassAndMethod(StringBuffer buf, 440 ANSIColor classColor, 441 ANSIColor methodColor, 442 StackTraceElement stackElement) 443 { 444 buf.append("{"); 445 446 String className = stackElement.getClassName(); 447 448 if (classColor == null) { 449 classColor = (ANSIColor)classColors.get(className); 450 } 451 452 boolean sameClass = prevStackElement != null && prevStackElement.getClassName().equals(className); 453 if (sameClass) { 454 className = repeat(prevDisplayedClass.length(), ' '); 455 classColor = null; 456 } 457 else if (className != null && (className.startsWith("org.") || className.startsWith("com."))) { 458 className = "..." + className.substring(className.indexOf('.', 5) + 1); 459 } 460 461 int totalWidth = classWidth + 1 + functionWidth; 462 463 int classPadding = 0; 464 if (className.length() > classWidth) { 465 if (classWidth > 0) { 466 className = className.substring(0, classWidth - 1) + '-'; 467 } 468 else { 469 className = ""; 470 } 471 } 472 else { 473 classPadding = classWidth - className.length(); 474 } 475 476 if (classColor != null) { 477 buf.append(classColor); 478 } 479 buf.append(className); 480 if (classColor != null) { 481 buf.append(Qualog.NONE); 482 } 483 484 if (columns) { 485 repeat(buf, classPadding, ' '); 486 } 487 488 prevDisplayedClass = className; 489 490 buf.append('#'); 491 492 String methodName = stackElement.getMethodName(); 493 494 if (methodColor == null) { 495 methodColor = (ANSIColor)methodColors.get(methodName); 496 } 497 498 if (sameClass && prevStackElement != null && prevStackElement.getMethodName().equals(methodName)) { 499 methodName = repeat(prevDisplayedMethod.length(), ' '); 500 methodColor = null; 501 } 502 503 int methodPadding = 0; 504 if (methodName.length() > functionWidth) { 505 methodName = methodName.substring(0, functionWidth - 1) + '-'; 506 } 507 else { 508 methodPadding = functionWidth - methodName.length(); 509 } 510 511 if (methodColor != null) { 512 buf.append(methodColor); 513 } 514 buf.append(methodName); 515 if (methodColor != null) { 516 buf.append(Qualog.NONE); 517 } 518 519 if (!columns) { 520 repeat(buf, classPadding, ' '); 521 } 522 repeat(buf, methodPadding, ' '); 523 524 prevDisplayedMethod = methodName; 525 526 buf.append("} "); 527 } 528 529 protected void outputMessage(StringBuffer buf, 530 int framesShown, 531 ANSIColor[] msgColor, 532 String msg, 533 StackTraceElement stackElement) 534 { 535 if (framesShown > 0) { 537 msg = "\"\""; 538 } 539 else { 540 while (msg.length() > 0 && "\r\n".indexOf(msg.charAt(msg.length() - 1)) != -1) { 541 msg = msg.substring(0, msg.length() - 1); 542 } 543 if (useColor) { 544 boolean hasColor = false; 545 if (msgColor == null || (msgColor.length > 0 && msgColor[0] == null)) { 546 ANSIColor col = null; 547 col = (ANSIColor)methodColors.get(stackElement.getClassName() + "#" + stackElement.getMethodName()); 548 if (col == null) { 549 col = (ANSIColor)classColors.get(stackElement.getClassName()); 550 if (col == null) { 551 col = (ANSIColor)fileColors.get(stackElement.getFileName()); 552 } 553 } 554 if (col != null) { 555 msg = col + msg; 556 hasColor = true; 557 } 558 } 559 else { 560 for (int i = 0; i < msgColor.length; ++i) { 561 if (msgColor[i] != null) { 562 msg = msgColor[i] + msg; 563 hasColor = true; 564 } 565 } 566 } 567 568 if (hasColor) { 569 msg += Qualog.NONE; 570 } 571 } 572 } 573 574 buf.append(msg); 575 } 576 577 protected StackTraceElement [] getStack(int depth) 578 { 579 return (new Exception ("")).getStackTrace(); 580 } 581 582 protected String repeat(int len, char ch) 583 { 584 StringBuffer buf = new StringBuffer (); 585 for (int i = 0; i < len; ++i) { 586 buf.append(ch); 587 } 588 return buf.toString(); 589 } 590 591 protected StringBuffer repeat(StringBuffer buf, int len, char ch) 592 { 593 for (int i = 0; i < len; ++i) { 594 buf.append(ch); 595 } 596 return buf; 597 } 598 599 protected void appendPadded(StringBuffer buf, String str, int maxSize) 600 { 601 if (str.length() > maxSize) { 602 buf.append(str.substring(0, maxSize - 1)).append("-"); 603 } 604 else { 605 buf.append(str); 606 repeat(buf, maxSize - str.length(), ' '); 607 } 608 } 609 610 protected String objectToString(Object obj) 611 { 612 String str = null; 613 if (obj == null) { 614 str = "null"; 615 } 616 else { 617 Class [] undecorated = new Class [] { 618 String .class, 619 Number .class, 620 Character .class, 621 Boolean .class 622 }; 623 624 Class cls = obj.getClass(); 625 626 for (int ui = 0; ui < undecorated.length; ++ui) { 627 if (undecorated[ui].isAssignableFrom(cls)) { 628 str = obj.toString(); 629 break; 630 } 631 } 632 633 if (str == null) { 634 str = obj.toString() + " (" + obj.getClass() + ") #" + Integer.toHexString(obj.hashCode()); 635 } 636 } 637 return str; 638 } 639 640 641 } 642 | Popular Tags |