1 9 10 package org.jboss.util; 11 12 import java.io.IOException ; 13 import java.io.ByteArrayInputStream ; 14 import java.io.ByteArrayOutputStream ; 15 import java.io.PrintWriter ; 16 import java.io.PrintStream ; 17 import java.io.InputStreamReader ; 18 import java.io.BufferedReader ; 19 import java.io.Serializable ; 20 21 import java.util.List ; 22 import java.util.Iterator ; 23 import java.util.ArrayList ; 24 25 import org.jboss.util.stream.Printable; 26 27 34 public final class StackTrace 35 implements Serializable , Cloneable , Printable 36 { 37 static final long serialVersionUID = -6077429788585907990L; 38 39 public static final int UNLIMITED = 0; 40 41 42 private static final String EMPTY_PREFIX = ""; 43 44 45 protected final List stack; 46 47 60 public StackTrace(final Throwable detail, 61 final int level, 62 final int limit) 63 { 64 if (level < 0) 65 throw new IllegalArgumentException ("level < 0"); 66 if (limit < 0) 67 throw new IllegalArgumentException ("limit < 0"); 68 69 try { 70 Parser parser = Parser.getInstance(); 71 stack = parser.parse(detail, level, limit); 72 } 73 catch (InstantiationException e) { 74 throw new NestedRuntimeException(e); 75 } 76 catch (IOException e) { 77 throw new NestedRuntimeException(e); 78 } 79 } 80 81 91 public StackTrace(final Throwable detail, final int level) { 92 this(detail, level, 0); 93 } 94 95 104 public StackTrace(final Throwable detail) { 105 this(detail, 0, 0); 106 } 107 108 116 public StackTrace(final int level, final int limit) { 117 this(new Throwable (), level + 1, limit); 118 } 119 120 125 public StackTrace(final int level) { 126 this(new Throwable (), level + 1, UNLIMITED); 127 } 128 129 132 public StackTrace() { 133 this(new Throwable (), 1, UNLIMITED); 134 } 135 136 139 protected StackTrace(final List stack) { 140 this.stack = stack; 141 } 142 143 149 public boolean equals(final Object obj) { 150 if (obj == this) return true; 151 152 if (obj != null && obj.getClass() == getClass()) { 153 return ((StackTrace)obj).stack.equals(stack); 154 } 155 156 return false; 157 } 158 159 164 public Object clone() { 165 try { 166 return super.clone(); 167 } 168 catch (CloneNotSupportedException e) { 169 throw new InternalError (); 170 } 171 } 172 173 181 public Entry getEntry(final int level) { 182 return (Entry)stack.get(level); 183 } 184 185 190 public Entry getCallerEntry() { 191 return getEntry(0); 192 } 193 194 199 public Entry getRootEntry() { 200 return getEntry(stack.size() - 1); 201 } 202 203 209 public StackTrace getSubTrace(final int level) { 210 return new StackTrace(stack.subList(level, stack.size())); 211 } 212 213 221 public StackTrace getSubTrace(final int level, int limit) { 222 if (limit > 0) { 223 limit = Math.min(level + limit, stack.size()); 224 } 225 else { 226 limit = stack.size(); 227 } 228 230 return new StackTrace(stack.subList(level, limit)); 231 } 232 233 238 public StackTrace getCallerTrace() { 239 return getSubTrace(1); 240 } 241 242 248 public void print(final PrintWriter writer, final String prefix) { 249 Iterator iter = stack.iterator(); 250 while (iter.hasNext()) { 251 Entry entry = (Entry)iter.next(); 252 entry.print(writer, prefix); 253 } 254 } 255 256 261 public void print(final PrintWriter writer) { 262 print(writer, EMPTY_PREFIX); 263 } 264 265 271 public void print(final PrintStream stream, final String prefix) { 272 Iterator iter = stack.iterator(); 273 while (iter.hasNext()) { 274 Entry entry = (Entry)iter.next(); 275 entry.print(stream, prefix); 276 } 277 } 278 279 284 public void print(final PrintStream stream) { 285 print(stream, EMPTY_PREFIX); 286 } 287 288 293 public void print(final String prefix) { 294 print(System.err, prefix); 295 } 296 297 300 public void print() { 301 print(System.err); 302 } 303 304 309 public Iterator iterator() { 310 return stack.iterator(); 311 } 312 313 318 public int size() { 319 return stack.size(); 320 } 321 322 323 327 335 public static final Entry currentEntry() { 336 return new StackTrace().getCallerEntry(); 337 } 338 339 351 public static final Entry callerEntry() { 352 return new StackTrace(1).getCallerEntry(); 353 } 354 355 361 public static final Entry rootEntry() { 362 return new StackTrace().getRootEntry(); 363 } 364 365 366 370 373 public static final class Entry 374 implements Cloneable , Serializable , Printable 375 { 376 static final long serialVersionUID = 7013023772762859280L; 377 378 public static final String UNKNOWN = "<unknown>"; 379 380 381 public static final String DEFAULT = "<default>"; 382 383 384 protected String className = UNKNOWN; 385 386 387 protected String methodName = UNKNOWN; 388 389 390 protected String sourceFileName = UNKNOWN; 391 392 393 protected String lineNumber = UNKNOWN; 394 395 403 public Entry(final String className, 404 final String methodName, 405 final String sourceFileName, 406 final String lineNumber) 407 { 408 this.className = className; 409 this.methodName = methodName; 410 this.sourceFileName = sourceFileName; 411 this.lineNumber = lineNumber; 412 } 413 414 419 public Entry(final String raw) { 420 parse(raw); 422 } 423 424 429 protected void parse(final String raw) { 430 int j = raw.indexOf("at ") + 3; 432 int i = raw.indexOf("("); 433 if (j == -1 || i == -1) return; 434 435 String temp = raw.substring(j, i); 436 i = temp.lastIndexOf("."); 437 if (i == -1) return; 438 439 className = temp.substring(0, i); 440 methodName = temp.substring(i + 1); 441 442 j = raw.indexOf("(") + 1; 444 i = raw.indexOf(":"); 445 if (j == -1) return; 446 if (i == -1) { 447 i = raw.indexOf(")"); 448 if (i == -1) return; 449 sourceFileName = raw.substring(j, i); 450 } 451 else { 452 sourceFileName = raw.substring(j, i); 453 j = i + 1; 455 i = raw.lastIndexOf(")"); 456 if (i != -1) 457 lineNumber = raw.substring(j, i); 458 else 459 lineNumber = raw.substring(j); 460 } 461 } 462 463 468 public String getClassName() { 469 return className; 470 } 471 472 480 public String getShortClassName() { 481 return Classes.stripPackageName(className); 482 } 483 484 489 public String getMethodName() { 490 return methodName; 491 } 492 493 501 public String getFullMethodName() { 502 return className + "." + methodName; 503 } 504 505 510 public String getSourceFileName() { 511 return sourceFileName; 512 } 513 514 519 public String getLineNumber() { 520 return lineNumber; 521 } 522 523 532 public String toString(final String prefix) { 533 StringBuffer buff = new StringBuffer (); 534 535 if (prefix != null) 536 buff.append(prefix); 537 538 buff.append(className).append(".").append(methodName) 539 .append("(").append(sourceFileName); 540 541 if (! lineNumber.equals(UNKNOWN)) 542 buff.append(":").append(lineNumber); 543 544 buff.append(")"); 545 546 return buff.toString(); 547 } 548 549 555 public String toString() { 556 return toString(EMPTY_PREFIX); 557 } 558 559 564 public int hashCode() { 565 return HashCode.generate(new String [] { 566 className, methodName, sourceFileName, lineNumber, 567 }); 568 } 569 570 576 public boolean equals(final Object obj) { 577 if (obj == this) return true; 578 579 if (obj != null && obj.getClass() == getClass()) { 580 Entry entry = (Entry)obj; 581 return 582 entry.className.equals(className) && 583 entry.methodName.equals(methodName) && 584 entry.sourceFileName.equals(sourceFileName) && 585 entry.lineNumber.equals(lineNumber); 586 } 587 588 return false; 589 } 590 591 596 public Object clone() { 597 try { 598 return super.clone(); 599 } 600 catch (CloneNotSupportedException e) { 601 throw new InternalError (); 602 } 603 } 604 605 611 public void print(final PrintWriter writer, final String prefix) { 612 writer.println(this.toString(prefix)); 613 } 614 615 620 public void print(final PrintWriter writer) { 621 writer.println(this.toString()); 622 } 623 624 630 public void print(final PrintStream stream, final String prefix) { 631 stream.println(this.toString(prefix)); 632 } 633 634 639 public void print(final PrintStream stream) { 640 stream.println(this.toString()); 641 } 642 643 648 public void print(final String prefix) { 649 print(System.err, prefix); 650 } 651 652 655 public void print() { 656 print(System.err); 657 } 658 } 659 660 661 665 669 public static class Parser 670 { 671 678 protected void skipDescription(final BufferedReader reader) 679 throws IOException 680 { 681 reader.readLine(); 682 } 683 684 692 protected void setLevel(final BufferedReader reader, final int level) 693 throws IOException 694 { 695 for (int i=0; i<level; i++) { 696 reader.readLine(); 697 } 698 } 699 700 708 protected byte[] readBytes(final Throwable detail) throws IOException { 709 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 710 PrintStream ps = new PrintStream (baos); 711 712 try { 713 detail.printStackTrace(ps); 714 } 715 finally { 716 ps.close(); 717 } 718 719 return baos.toByteArray(); 720 } 721 722 730 protected BufferedReader createReader(final Throwable detail) 731 throws IOException 732 { 733 byte bytes[] = readBytes(detail); 734 ByteArrayInputStream bais = new ByteArrayInputStream (bytes); 735 InputStreamReader reader = new InputStreamReader (bais); 736 737 return new BufferedReader (reader); 738 } 739 740 752 public List parse(final Throwable detail, 753 final int level, 754 final int limit) 755 throws IOException 756 { 757 BufferedReader reader = createReader(detail); 759 760 skipDescription(reader); 762 763 setLevel(reader, level); 765 766 List list = new ArrayList (); 768 769 String raw; 770 int count = 0; 771 while ((raw = reader.readLine()) != null) { 772 Entry entry = createEntry(raw); 773 list.add(entry); 774 775 if (limit > UNLIMITED && ++count >= limit) break; 777 } 778 779 return list; 780 } 781 782 790 protected Entry createEntry(final String raw) throws IOException { 791 return new Entry(raw); 792 } 793 794 798 799 private static Parser instance = null; 800 801 808 public static final synchronized Parser getInstance() 809 throws InstantiationException 810 { 811 if (instance == null) { 812 instance = new Parser(); 814 } 815 816 return instance; 817 } 818 } 819 } 820 | Popular Tags |