1 22 23 package org.aspectj.debugger.base; 24 25 import org.aspectj.debugger.request.*; 26 import com.sun.jdi.*; 27 import com.sun.jdi.request.*; 28 import com.sun.jdi.event.*; 29 import org.aspectj.tools.ide.SourceLine; 30 import java.io.*; 31 import java.util.*; 32 33 import org.aspectj.util.LineNumberTableMapper; 34 35 43 44 public class AJDebugger extends Debugger { 45 46 public static AJDebugger INSTANCE = null; 47 48 private static final String workingdir = "ajworkingdir"; 49 private static final String sep = File.separator; 50 private static final char sepChar = File.separatorChar; 51 private static final int NO_LINE = -1; 52 private static final int NO_MAP = -2; 53 private HashMap noAJCHash = new HashMap(); 55 56 private File workingdirFile = null; 57 public File getWorkingdir() { 58 return workingdirFile; 59 } 60 public void setWorkingdir(String newWorkingdir) { 61 try { 62 newWorkingdir = new File(newWorkingdir).getCanonicalPath(); 63 } catch (Throwable t) {} 64 setWorkingdir(new File(newWorkingdir)); 65 } 66 private void setWorkingdir(File file) { 67 if (file == null) { 68 error("The workingdir is null: " + file); 69 return; 70 } 71 if (!file.exists()) { 72 error("The workingdir doesn't exist: " + file); 73 return; 74 } 75 if (!file.isDirectory()) { 76 String msg = "The workingdir isn't a directory: " + file; 77 File parent = file.getParentFile(); 78 msg += "\nTrying to set workingdir with " + parent; 79 error(msg); 80 setWorkingdir(parent); 81 return; 82 } 83 this.workingdirFile = file; 84 } 85 86 87 public AJDebugger(DebuggerApp app) { 88 this(app, true); 89 } 90 91 public AJDebugger(DebuggerApp app, boolean readStartupFiles) { 92 super(app); 93 if (readStartupFiles) { 94 readStartupFiles(); 95 } 96 setWorkingDirDefault(); 97 INSTANCE = this; 98 } 99 100 101 102 public ClassLineBreakpointRequestAction createClassLineEvent(String className, 103 int line, 104 boolean stop) 105 throws DebuggerException { 106 return createClassLineEvent(className, line, stop, null); 107 } 108 109 public ClassLineBreakpointRequestAction createClassLineEvent(String className, 110 int line, 111 boolean stop, 112 String text) 113 throws DebuggerException { 114 SourceLine sl = classToOutput(className, line); 115 ClassLineBreakpointRequestAction a = null; 116 if (stop) { 117 a = new StopAtRequest(this, className, sl.line); 118 a.setText(text); 119 } else { 120 a = new ClearAtRequest(this, className, sl.line); 121 a.setText(text); 122 } 123 return a; 124 } 125 126 public SourceLineBreakpointRequestAction 127 createSourceLineEvent(String sourceName, 128 int line, 129 boolean stop) 130 throws DebuggerException { 131 return createSourceLineEvent(sourceName, line, stop, null); 132 } 133 134 public SourceLineBreakpointRequestAction 135 createSourceLineEvent(String sourceName, 136 int line, 137 boolean stop, 138 String text) 139 throws DebuggerException { 140 SourceLine sl = fileToOutput(sourceName, line); 141 SourceLineBreakpointRequestAction a = null; 142 String justSource = removeFullWorkingDir(sl.filename); 143 if (stop) { 144 a = new StopOnRequest(this, justSource, sl.line); 145 a.setText(text); 146 } else { 147 a = new ClearOnRequest(this, justSource, sl.line); 148 a.setText(text); 149 } 150 return a; 151 } 152 153 154 155 private SourceLine mapToSourceLine(String fullPath, int lineNumber) { 156 return new SourceLine(fullPath, lineNumber); 158 } 169 170 public SourceLine getSourceLineFromClass(String className, int lineNumber) { 171 String fullOutputPath = getFullOutputPathFromClass(className); 172 return mapToSourceLine(fullOutputPath, lineNumber); 173 } 174 175 public SourceLine getSourceLineFromSource(String relativePath, int lineNumber) { 176 String fullOutputPath = getFullOutputPath(relativePath); 177 return mapToSourceLine(fullOutputPath, lineNumber); 178 } 179 180 public SourceLine getSourceLine(BreakpointRequestAction ba) { 181 SourceLine sl = null; 182 if (ba instanceof ClassLineBreakpointRequestAction) { 183 ClassLineBreakpointRequestAction ca = (ClassLineBreakpointRequestAction)ba; 184 return getSourceLineFromClass(ca.getClassName(), ca.getLine()); 185 } 186 if (ba instanceof BreakpointRequestAction) { 187 sl = ((BreakpointRequestAction) ba).sourceLine(); 188 } 189 if (sl == null) { 190 String sourceName = ba.getRealSourceName(); 192 String pkgWithSep = getPackagePathWithSeparator(ba.getLocation()); 193 if ("".equals(pkgWithSep)) { 194 int islash = sourceName.lastIndexOf(File.separatorChar); 196 if (islash == -1) { 197 islash = sourceName.lastIndexOf('/'); 198 } 199 if (islash == -1) { 200 islash = sourceName.lastIndexOf('\\'); 201 } 202 if (islash != -1) { 203 sourceName = sourceName.substring(islash+1); 204 } 205 } 207 String fullOutputPath = getFullOutputPath(pkgWithSep + sourceName); 208 int lineNumber = ba.getLine(); 209 sl = mapToSourceLine(fullOutputPath, lineNumber); 210 } 211 return sl; 212 } 213 214 215 216 220 public void use(String sourcePath) { 221 super.use(sourcePath); 222 setWorkingDirDefault(); 223 } 224 225 protected void setWorkingDirDefault() { 226 if (getWorkingdir() == null) { 227 String defaultWorkingdir = getSourcePath() + sep + workingdir; 228 app.outln("Using default workingdir: " + defaultWorkingdir); 229 setWorkingdir(defaultWorkingdir); 230 } 231 } 232 233 protected void go(String className, 234 String vmArgs, 235 String commandLine, 236 boolean isSuspended, 237 int debugTraceMode) { 238 if (getWorkingdir() == null) { 239 setWorkingDirDefault(); 240 } 241 super.go(className, vmArgs, commandLine, isSuspended, debugTraceMode); 242 } 243 244 245 246 private int line(SourceLine sl) { 247 return sl.line+1; 248 } 249 250 private SourceLine fileToOutput(String relativePath, int sourceLine) 251 throws NonMappingSourceLineException { 252 String fullPath = getFullSourcePath(relativePath); 253 return mapToOutputLine(fullPath, sourceLine); 254 } 255 256 private SourceLine classToOutput(String className, int sourceLine) 257 throws NonMappingSourceLineException { 258 String fullPath = getFullSourcePathFromAJCClass(className); 259 if (fullPath == null) { 260 return noSourceLine(getFullSourcePathFromClass(className), sourceLine); 261 } 262 return mapToOutputLine(fullPath, sourceLine); 263 } 264 265 public boolean isAjcFile(String fullPath) { 266 String relativePath = getRelativePath(fullPath); 267 String fullOutputPath = getFullOutputPath(relativePath); 268 File outputFile = new File(fullOutputPath); 269 if (outputFile != null && 270 outputFile.exists() && 271 !outputFile.isDirectory()) { 272 return true; 273 } 274 return false; 275 } 276 277 private SourceLine mapToOutputLine(String fullPath, int sourceLine) 278 throws NonMappingSourceLineException { 279 return new SourceLine(fullPath, sourceLine); 281 } 293 294 public SourceLine noSourceLine(String fullPath, int line) { 295 return new SourceLine(fullPath, line); 296 } 297 298 public SourceLine sourceLine(SourceLine sl) { 299 sl.filename = removeSourcePath(sl.filename); 300 return sl; 301 } 302 303 public SourceLine nonMappingSourceLine(String sourceName, int lineNumber) { 304 return new SourceLine("<non-mapping>:" + sourceName + ":" + lineNumber, -1); 305 } 306 307 public SourceLine emptySourceLine() { 308 return new SourceLine("<no-source>", -1); 309 } 310 311 private boolean outputFileExists(String fullPath) { 312 String relativePath = removeSourcePath(fullPath); 313 File file = new File(getFullOutputPath(relativePath)); 314 return file.exists(); 315 } 316 317 public String __removeSourcePath(String fullPath) { 318 fullPath = new File(fullPath).getAbsolutePath(); 319 int iroot = fullPath.toLowerCase().indexOf(getSourcePath().toLowerCase()); 320 if (iroot != -1) { 321 String relativePath = fullPath.substring(getSourcePath().length()); 322 while (relativePath.length() > 0 && 323 !Character.isJavaIdentifierPart(relativePath.charAt(0))) { 324 relativePath = relativePath.substring(1); 325 } 326 return relativePath; 327 } 328 return fullPath; 329 } 330 331 public String addSourcePath(String relativePath) { 332 if (!(relativePath.startsWith(getSourcePath()))) { 333 try { 334 return new File(getSourcePath() + sep + 335 relativePath).getCanonicalPath(); 336 } catch (Exception ioe) { 337 } 338 } 339 return relativePath; 340 } 341 342 public String removeWorkingDir(String relativePath) { 343 String target = workingdir + sep; 344 int iwd = relativePath.indexOf(target); 345 if (iwd != -1) { 346 return relativePath.substring(target.length()); 347 } 348 return relativePath; 349 } 350 351 public String removeWorkingDirFromFullPath(String fullPath) { 352 String target = workingdir + sep; 353 int iwd = fullPath.indexOf(target); 354 if (iwd == -1) return fullPath; 355 return fullPath.substring(0, iwd) + 356 fullPath.substring(iwd + target.length()); 357 } 358 359 public String removeFilePath(String fullPath, File comparison) { 360 int isep = fullPath.indexOf(sep); 361 if (isep == -1) return fullPath; 362 for (int i = 0; i < fullPath.length(); i++) { 363 char c = fullPath.charAt(i); 364 if (isSep(c)) { 365 String filePath = fullPath.substring(0,i); 366 File file = new File(fullPath.substring(0, i)); 367 if (file.equals(comparison)) { 368 return fullPath.substring(i+1); 369 } 370 } 371 } 372 return fullPath; 373 } 374 public String removeFilePath(String fullPath, String comparison) { 375 return removeFilePath(fullPath, new File(comparison)); 376 } 377 public String removeFullWorkingDir(String fullPath) { 378 return removeFilePath(fullPath, getWorkingdir()); 379 } 380 public String removeSourcePath(String fullPath) { 381 return removeCurrentPath(_removeSourcePath(fullPath)); 382 } 383 public String _removeSourcePath(String fullPath) { 384 return removeFilePath(fullPath, getSourcePath()); 385 } 386 public String removeCurrentPath(String fullPath) { 387 return removeFilePath(fullPath, "."); 388 } 389 390 private boolean isSep(char c) { 391 return c == sepChar || c == '/' || c == '\\'; 392 } 393 394 private String getFullSourcePathFromClass(String className) { 395 String relativePath = getRelativeFilePathFromClass(className); 396 return getFullSourcePath(relativePath); 397 } 398 399 public String getFullSourcePath(String relativePath) { 400 return getFullFilePath(relativePath, false); 401 } 402 403 public String getFullOutputPath(Location loc, String realSourceName) { 404 String decString = loc.declaringType().name(); 405 String pkg = ""; 406 int idot = decString.lastIndexOf("."); 407 if (idot != -1) { 408 pkg = decString.substring(0, idot).replace('.', sepChar) + sep; 409 } 410 String relativePath = pkg + realSourceName; 411 return getFullOutputPath(relativePath); 412 } 413 414 public String getPackagePathWithSeparator(Location loc) { 415 if (loc == null) return ""; 416 String decString = loc.declaringType().name(); 417 String pkg = ""; 418 int idot = decString.lastIndexOf("."); 419 if (idot != -1) { 420 pkg = decString.substring(0, idot).replace('.', sepChar) + sep; 421 } 422 return pkg; 423 } 424 425 public String getFullOutputPath(String relativePath) { 426 if (getWorkingdir() == null) { 427 return ""; } 429 String wdName = getWorkingdir().getName(); 430 int iwd = relativePath.indexOf(wdName); 431 if (iwd != -1) { 432 relativePath = relativePath.substring(iwd + wdName.length()); 433 } 434 char c = relativePath.charAt(0); 435 if (c == '/' || c == '\\' || c == sepChar) { 436 relativePath = relativePath.substring(1); 437 } 438 return getFullFilePath(relativePath, true); 439 } 440 441 public String getFullOutputPathFromClass(String className) { 442 return getFullOutputPath(getRelativeFilePathFromClass(className)); 443 } 444 445 public String getFullFilePath(String relativePath, boolean inWorkingDir) { 446 String fullName = null; 447 File file; 448 if (inWorkingDir) { 449 file = new File(getWorkingdir() + sep + relativePath); 450 } else { 451 file = new File(relativePath); 452 } 453 if (file != null && file.exists()) return file.getAbsolutePath(); 454 try { 455 relativePath = getRelativePath(relativePath); 456 if (relativePath.toLowerCase().startsWith(getSourcePath().toLowerCase())) { 457 fullName = relativePath; 458 } else { 459 boolean oldway = false; 460 if (oldway) { 461 fullName = getSourcePath() + sep; 462 if (inWorkingDir) { 463 fullName += workingdir + sep; 464 } 465 fullName += relativePath; 466 } else { 467 if (inWorkingDir) { 468 fullName = getWorkingdir() + sep + relativePath; 469 } else { 470 fullName = getSourcePath() + sep + relativePath; 471 } 472 } 473 } 474 if (false) { 475 return new File(fullName).getCanonicalPath(); 476 } else { 477 return new File(fullName).getAbsolutePath(); 478 } 479 } catch (Exception ioe) { 480 ioe.printStackTrace(System.err); 481 System.err.println("relativePath=" + relativePath); 482 System.err.println("fullName=" + fullName); 483 return new File(fullName).getAbsolutePath(); 484 } 485 } 486 487 public String getRelativePath(String fullPath) { 488 int isourcePath = fullPath.toLowerCase().indexOf(getSourcePath().toLowerCase()); 489 if (isourcePath == -1) return fullPath; 490 return fullPath.substring(isourcePath+getSourcePath().length()); 491 } 492 493 public String getRelativeFilePathFromClass(String className) { 495 String newClassName = className.replace('.', sepChar); 496 newClassName += ".java"; 497 return newClassName; 498 } 499 500 public String getFullSourcePathFromAJCClass(String className) { 501 if (noAJCHash.get(className) != null) { 503 return null; 504 } 505 String ajFile = getFullOutputPathFromClass(className); 506 return ajFile; 507 } 525 526 public String getClassNameFromFullSourcePath(String fullSourcePath, int line) { 527 return ""; 529 } 540 541 542 543 private final int limit = 10; 544 public String sourceName(ReferenceType refType) { 545 return ""; 547 } 565 566 public String sourceName(Location loc) throws AbsentInformationException { 567 return sourceLine(loc).filename; 568 } 569 570 public int lineNumber(Location loc) { 571 try { 572 return sourceLine(loc).line; 573 } catch (AbsentInformationException aie) { 574 aie.printStackTrace(); 575 } 576 return super.lineNumber(loc); 577 } 578 579 public boolean locationMaps(Location loc) { 580 String sourceName = ""; 581 try { 582 sourceName = loc.sourceName(); 583 } catch (AbsentInformationException aie) { 584 return true; 585 } 586 return isMappingRelativePath(sourceName, loc); 587 } 588 public boolean isMappingRelativePath(String sourceName, Location loc) { 589 String fullPath = getPackagePathWithSeparator(loc) + sourceName; 590 return isMappingFullPath(fullPath, loc); 591 } 592 public boolean isMappingFullPath(String fullPath, Location loc) { 593 String fullOutputPath = getFullOutputPath(fullPath); 594 if (!new File(fullOutputPath).exists()) { 595 return true; 596 } 597 int lineNumber = loc.lineNumber(); 598 SourceLine sl = null; 599 try { 600 sl = sourceLine(loc); 601 } catch (AbsentInformationException aie) { 602 return true; 603 } 604 if (sl == null || sl.line < 0) { 605 return false; 606 } 607 return true; 608 } 609 610 public SourceLine sourceLine(String sourceName, 611 String fullOutputPath, 612 int lineNumber) { 613 SourceLine sl = mapToSourceLine(fullOutputPath, lineNumber); 614 if (sl != null) { 615 return sourceLine(sl); 616 } else if (new File(fullOutputPath).exists()) { 617 return nonMappingSourceLine(sourceName, lineNumber); 618 } 619 return noSourceLine(sourceName, lineNumber); 620 } 621 622 public SourceLine sourceLine(Location loc) 623 throws AbsentInformationException { 624 String sourceName = "<not-available>"; 625 try { 626 sourceName = loc.sourceName(); 627 } catch (AbsentInformationException aie) { 628 } 629 int lineNumber = loc.lineNumber(); 630 String fullSrcPath = getFullSourcePath(getPackagePathWithSeparator(loc) + 631 sourceName); 632 SourceLine sl = sourceLineOfMethodThatShouldMap(loc, fullSrcPath); 633 if (sl != null) return sl; 634 String fullOutputPath = 635 getFullOutputPath(getPackagePathWithSeparator(loc) + 636 sourceName); 637 return sourceLine(sourceName, fullOutputPath, lineNumber); 638 } 639 640 public SourceLine sourceLineOfMethodThatShouldMap(Location loc, 641 String fullSrcPath) { 642 return new SourceLineFinder(fullSrcPath).findMethod(loc); 643 } 644 645 public SourceLine sourceLineOfMethodThatShouldMap(String className, 646 String methodName, 647 String fullSrcPath) { 648 return new SourceLineFinder(fullSrcPath). 649 findMethod(className, methodName); 650 } 651 652 public String method(Location loc) { 653 return method(loc.method()); 654 } 655 656 public void setOptions(Options options) { 657 super.setOptions(options); 658 if (options.isSet("workingdir")) { 659 setWorkingdir(options.getOpt("workingdir")); 660 } 661 } 662 663 public String method(Method method) { 664 if (getOptions().isSet("nodemangle")) return method.name(); 665 return demangleMethodName(method.name()); 666 } 667 668 public String name(Method method) { 669 if (getOptions().isSet("nodemangle")) return method.name(); 670 return demangleMethodName(method.name()); 671 } 672 673 public String name(ReferenceType refType) { 674 return refType != null ? refType.name() : "null-name"; 675 } 676 677 678 679 680 682 void handleBreakpointEvent(BreakpointEvent event) { 683 try { 684 SourceLine sl = sourceLine(event.location()); 685 if (!locationMaps(event.location())) { 686 return; 688 } 689 } catch (Exception e) { 690 } 691 super.handleBreakpointEvent(event); 692 } 693 694 void handleStepEvent(StepEvent event) { 695 try { 696 if (!locationMaps(event.location())) { 697 String name = ((StepRequest)event.request()). 698 getProperty("name")+""; 699 if (name.equals("next")) { 700 nextCommand(); 701 return; 702 } else if (name.equals("step")) { 703 stepCommand(); 704 return; 705 } else if (name.equals("step up")) { 706 stepUpCommand(); 707 return; 708 } else if (name.equals("stepi")) { 709 stepiCommand(); 710 return; 711 } else { 712 error("Bad property!"); 713 } 714 } 715 } catch (Exception e) { 716 } 717 super.handleStepEvent(event); 718 } 719 720 721 722 final static String sigToken = "$signature"; 723 final static String memberToken = "$member"; 724 final static String staticMemberToken = "$static$member"; 725 final static String adviceToken = "$reception"; 726 final static String aroundToken = "$around$reception"; 727 final static String ajcToken = "$ajc"; 728 729 public String demangleMethodName(String methodName) { 730 String translatedMethodName = ""; 731 int idollar = methodName.indexOf("$"); 732 if (idollar == -1) { 733 return methodName; 734 } 735 int iajc = methodName.indexOf(ajcToken); 736 if (iajc != -1) { 737 translatedMethodName = "<advice #"; 738 int i = iajc + ajcToken.length(); 739 while (i < methodName.length() && 740 Character.isDigit(methodName.charAt(i))) { 741 translatedMethodName += methodName.charAt(i); 742 i++; 743 } 744 translatedMethodName += ">"; 745 } else { 746 translatedMethodName = methodName.substring(0, idollar); 747 } 748 749 return translatedMethodName; 750 } 751 752 public boolean isAdvice(String methodName) { 753 return methodName.indexOf(ajcToken) != -1; 754 } 755 756 757 758 public static class NonMappingSourceLineException extends DebuggerException { 759 public NonMappingSourceLineException(String source, int line) { 760 super("The following does not map to an executable output line: " + 761 source + "::" + line); 762 } 763 } 764 765 public static class NonMappingOutputLineException extends DebuggerException { 766 public NonMappingOutputLineException(String outputFile, int line) { 767 super("The following does not map to an executable source line: " + 768 outputFile + "::" + line); 769 } 770 } 771 772 773 774 interface Formatter { 775 public String format(Object o); 776 } 777 778 public String iter(List list) { 779 return iter(list, 780 new Formatter() { 781 public String format(Object o) { 782 return " " + o; 783 }}); 784 } 785 786 public String fields(List fields) { 787 String result = ""; 788 Iterator iter = fields.iterator(); 789 while (iter.hasNext()) { 790 Field field = (Field) iter.next(); 791 try { 792 result += field.type().name() + " " + field.name() + "\n"; 793 } catch (ClassNotLoadedException cnle) { 794 } 795 } 796 return result; 797 } 798 799 public String methods(List methods) { 800 String result = ""; 801 Iterator iter = methods.iterator(); 802 while (iter.hasNext()) { 803 Method method = (Method) iter.next(); 804 String methString= method + ""; 805 int idot = method.declaringType().name().length(); 806 methString = methString.substring(0, idot) + ' ' + 807 methString.substring(idot + 1); 808 result += methString + "\n"; 809 } 810 return result; 811 } 812 813 public String classes(List classes) { 814 String result = "** classes list **"; 815 Iterator iter = classes.iterator(); 816 while (iter.hasNext()) { 817 result += "\n" + ((ReferenceType) iter.next()).name(); 818 } 819 return result; 820 } 821 822 public String clazz(ReferenceType refType) { 823 String result = ""; 824 if (refType instanceof ArrayReference) { 825 result = "Array: " + refType.name(); 826 } else { 827 String name = refType.name(); 828 result = "Class: " + name + "\n"; 829 try { 830 Class clazz = Class.forName(name); 831 result += "extends: " + clazz.getSuperclass().getName() + "\n"; 832 Class [] interfaces = clazz.getInterfaces(); 833 for (int i = 0; i < interfaces.length; i++) { 834 result += "implements: " + interfaces[i].getName() + "\n"; 835 } 836 } catch (Exception e) { 837 } 838 } 839 return result; 840 } 841 842 public String threads(List threads) { 843 String result = ""; 844 Iterator iter = threads.iterator(); 845 Hashtable threadHash = new Hashtable(); 846 String [][] cols = new String [threads.size()][3]; 847 int[] max = new int[3]; 848 int col = 0; 849 while (iter.hasNext()) { 850 ThreadReference threadRef = (ThreadReference) iter.next(); 851 ThreadGroupReference threadGroupRef = threadRef.threadGroup(); 852 cols[col] = new String [3]; 853 cols[col][0] = "(" + threadRef.type().name() + ")" + 854 toHex(threadRef.uniqueID()); 855 cols[col][1] = threadRef.name(); 856 cols[col][2] = status(threadRef); 857 for (int i = 0; i < max.length; i++) { 858 if (cols[col][i].length() > max[i]) { 859 max[i] = cols[col][i].length(); 860 } 861 } 862 Vector v = (Vector)threadHash.get(threadGroupRef); 863 if (v == null) { 864 v = new Vector(); 865 } 866 v.add(cols[col]); 867 threadHash.put(threadGroupRef, v); 868 } 869 Enumeration keys = threadHash.keys(); 870 while (keys.hasMoreElements()) { 871 ThreadGroupReference threadGroupRef = 872 (ThreadGroupReference) keys.nextElement(); 873 result += "Group " + threadGroupRef.name() + ":\n"; 874 Vector v = (Vector) threadHash.get(threadGroupRef); 875 for (int i = 0; i < v.size(); i++) { 876 String [] stringCol = (String []) v.get(i); 877 result += " "; 878 result += space(stringCol[0], max[0]) + " "; 879 result += space(stringCol[1], max[1]) + " "; 880 result += space(stringCol[2], max[2]) + "\n"; 881 } 882 } 883 return result; 884 } 885 886 public String space(String str, int length) { 887 String result = str; 888 int diff = length - str.length(); 889 for (int i = 0; i < diff; i++) { 890 result += " "; 891 } 892 return result; 893 } 894 895 public static String status(ThreadReference threadRef) { 896 switch(threadRef.status()) { 897 case ThreadReference.THREAD_STATUS_UNKNOWN: return "unknown"; 898 case ThreadReference.THREAD_STATUS_ZOMBIE: return "zombie"; 899 case ThreadReference.THREAD_STATUS_RUNNING: return "running"; 900 case ThreadReference.THREAD_STATUS_SLEEPING: return "sleeping"; 901 case ThreadReference.THREAD_STATUS_MONITOR: return "monitor"; 902 case ThreadReference.THREAD_STATUS_WAIT: return "waiting"; 903 case ThreadReference.THREAD_STATUS_NOT_STARTED: return "not started"; 904 } 905 return "?"; 906 } 907 908 public List frames(ThreadReference threadRef) 909 throws IncompatibleThreadStateException { 910 List frames = new Vector(); 911 try { 912 Iterator iter = threadRef.frames().iterator(); 913 while (iter.hasNext()) { 914 StackFrame frame = (StackFrame) iter.next(); 915 if (locationMaps(frame.location())) { 916 frames.add(frame); 917 } 918 } 919 } catch (InvalidStackFrameException isfe) { 920 } 921 return frames; 922 } 923 924 public String frames(List frames) { 925 String result = ""; 926 Iterator iter = frames.iterator(); 927 928 int i = 1; 929 String tabs = ""; 930 int size = frames.size(); 931 while ((size /= 10) != 0) tabs += " "; 932 while (iter.hasNext()) { 933 result += " [" + (i++) + "] " + tabs; 934 try { 935 Location loc = ((StackFrame) iter.next()).location(); 936 result += name(loc.declaringType()) + "." 937 + name(loc.method()) + " "; 938 try { 939 String sourceName = sourceName(loc); 940 int lineNumber = lineNumber(loc); 941 if (lineNumber == -2) { 942 result += "(" + sourceName + ")"; 943 } else if (lineNumber != -1) { 944 result += "(" + sourceName + ":" + lineNumber + ")"; 945 } else { 946 result += "[class " + loc.declaringType().name() + "]"; 947 } 948 } catch (AbsentInformationException aie) { 949 } 950 } catch (InvalidStackFrameException isfe) { 951 result += "<thread resumed>"; 952 } 953 result += "\n"; 954 } 955 return result; 956 } 957 958 public String threadGroups(List threadGroups) { 959 String result = ""; 960 Iterator iter = threadGroups.iterator(); 961 int i = 1; 962 while (iter.hasNext()) { 963 ThreadGroupReference ref = (ThreadGroupReference) iter.next(); 964 result += (i++) + ". (" + ref.type().name() + ")" + 965 toHex(ref.uniqueID()) + " " + ref.name() + "\n"; 966 } 967 return result; 968 } 969 970 public String toHex(long l) { 971 return "0x" + Long.toHexString(l); 972 } 973 974 class SourceLinesFormatter implements Formatter { 975 final int tabs = 10; 976 final boolean arrow; 977 public SourceLinesFormatter(boolean arrow) { 978 this.arrow = arrow; 979 } 980 public String format(Object o) { 981 if (!(o instanceof SourceManager.SourceLine)) { 982 return o + ""; 983 } 984 SourceManager.SourceLine sl = (SourceManager.SourceLine) o; 985 String lineString = sl.getLineString(); 986 int lineNumber = sl.getLineNumber(); 987 String result = ""; 988 if (lineNumber > 0) { 989 result += lineNumber + " "; 990 if (lineNumber < 10) result += " "; 991 else if (lineNumber < 100) result += " "; 992 else if (lineNumber < 1000) result += " "; 993 else if (lineNumber < 10000) result += " "; 994 else if (lineNumber < 100000) result += " "; 995 else result += " "; 996 result += (isStopped(sl) && arrow) ? "=>" : " "; 997 result += lineString; 998 } 999 return result; 1000 } 1001 } 1002 1003 public String sourceLines(List sourceLines) { 1004 return sourceLines(sourceLines, false); 1005 } 1006 1007 public String sourceLines(List sourceLines, boolean arrow) { 1008 return iter(sourceLines, new SourceLinesFormatter(arrow)); 1009 } 1010 1011 public String sourceLine(SourceManager.SourceLine sl) { 1012 Vector v = new Vector(1); 1013 v.add(sl); 1014 return sourceLines(v); 1015 } 1016 1017 public String locals(List locals) { 1018 if (locals == null || locals.size() == 0) { 1019 return "No local variables"; 1020 } 1021 String result = ""; 1022 Iterator iter = locals.iterator(); 1023 Vector args = new Vector(); 1024 Vector vars = new Vector(); 1025 while (iter.hasNext()) { 1026 LocalVariable local = (LocalVariable) iter.next(); 1027 if (local.isArgument()) { 1028 args.add(local); 1029 } else { 1030 vars.add(local); 1031 } 1032 } 1033 result += "Method arguments:"; 1034 for (int i = 0; i < args.size(); i++) { 1035 result += "\n" + local((LocalVariable) args.get(i)); 1036 } 1037 result += (args.size() < 1 ? "\n" : "") + "Local variables:"; 1038 for (int i = 0; i < vars.size(); i++) { 1039 result += "\n" + local((LocalVariable) vars.get(i)); 1040 } 1041 return result; 1042 } 1043 1044 public String local(LocalVariable local) { 1045 String result = " " + local.name(); 1046 try { 1047 StackFrame frame = getDefaultFrame(); 1048 result += " = " + frame.getValue(local); 1049 } catch (NoVMException nvme) { 1050 } catch (Exception e) { 1051 } 1052 return result; 1053 } 1054 1055 public String iter(List list, Formatter f) { 1056 String str = ""; 1057 boolean newline = false;; 1058 Iterator iter = list.iterator(); 1059 while (iter.hasNext()) { 1060 str += (newline ? "\n" : "") + f.format(iter.next()); 1061 newline = true; 1062 } 1063 return str; 1064 } 1065 1066 public String format(ExceptionEvent e) { 1067 String str = e.exception().referenceType().name(); 1068 Location loc = e.catchLocation(); 1069 str += " ("; 1070 str += loc == null 1071 ? "uncaught" : 1072 "to be caught at: " + format(loc, e.thread()); 1073 str += ")"; 1074 str += "\n" + format((LocatableEvent) e); 1075 ObjectReference exception = e.exception(); 1076 try { 1077 ThreadReference thread = threads.getThread(); 1078 List methods = exception.referenceType(). 1079 methodsByName("printStackTrace"); 1080 Iterator iter = methods.iterator(); 1081 while (iter.hasNext()) { 1082 Method method = (Method) iter.next(); 1083 List argumentTypeNames = method.argumentTypeNames(); 1084 if (argumentTypeNames.size() == 0) { 1085 List arguments = new Vector(); 1086 int options = ObjectReference.INVOKE_SINGLE_THREADED; 1087 exception.invokeMethod(thread, method, arguments, options); 1088 break; 1089 } 1090 } 1091 } catch (DebuggerException de) { 1092 } catch (InvalidTypeException ite) { 1093 } catch (ClassNotLoadedException cnle) { 1094 } catch (IncompatibleThreadStateException itse) { 1095 } catch (InvocationException ie) { 1096 } 1097 return str; 1098 } 1099 1100 public String format(LocatableEvent e) { 1101 return format(e.location(), e.thread()); 1102 } 1103 1104 public String format(Location loc, ThreadReference thread) { 1105 int lineNumber = lineNumber(loc); 1106 String method = method(loc); 1107 long codeIndex = loc.codeIndex(); 1108 String str = 1109 "thread=\"" + thread.name() + "\", " + 1110 loc.declaringType().name() + "." + method + "()" + 1111 (lineNumber > 0 ? ", line=" + lineNumber : "") + 1112 (codeIndex >= 0 ? ", bci=" + codeIndex : ""); 1113 try { 1114 SourceLine sl = sourceLine(loc); 1115 if (sl != null && sl.line > 0) { 1116 String smsl = 1117 sourceLine(getSourceManager().getSourceLine(sl.filename, 1118 sl.line - 1)); 1119 if (!smsl.startsWith("null")) { 1120 str += "\n" + smsl; 1121 } 1122 } 1123 } catch (AbsentInformationException aie) { 1124 } 1125 return str; 1126 } 1127 1128 public String strip(String sourceName) { 1129 int islash = sourceName.lastIndexOf(File.separator); 1130 if (islash == -1) islash = sourceName.lastIndexOf('/'); 1131 if (islash == -1) islash = sourceName.lastIndexOf('\\'); 1132 if (islash != -1) return sourceName.substring(islash+1); 1133 return sourceName; 1134 } 1135 1136 public String methodName(LocatableEvent e) { 1137 return method(e.location()); 1138 } 1139 1140 public static String d() { return "AJDebugger"; } 1141 public String toString() { return d(); } 1142 1143 public String toLongString() { 1144 Object [] objects = new Object [] { 1145 "Sourcepath", getSourcePath(), 1146 "Workingdir", getWorkingdir(), 1147 "Running class", runningClass, 1148 "Status", status, 1149 "Old class", oldClass, 1150 "Old VM args", oldVmArgs, 1151 "Old command line", oldCommandLine, 1152 }; 1153 return format(map(objects)); 1154 } 1155 1156 private Map map(Object [] objects) { 1157 Map map = new HashMap(); 1158 for (int i = 0; i < objects.length; i += 2) { 1159 map.put(objects[i], objects[i+1]); 1160 } 1161 return map; 1162 } 1163 1164 private String format(Map map) { 1165 Iterator iter; 1166 iter = map.keySet().iterator(); 1167 List keys = new Vector(); 1168 List vals = new Vector(); 1169 while (iter.hasNext()) { 1170 Object keyObj = iter.next(); 1171 String key = keyObj + ""; 1172 String val = map.get(keyObj) + "";; 1173 keys.add(key); 1174 vals.add(val); 1175 } 1176 int longest = -1; 1177 iter = keys.iterator(); 1178 while (iter.hasNext()) { 1179 int length = (iter.next() + "").length(); 1180 if (length > longest) { 1181 longest = length; 1182 } 1183 } 1184 String str = 1185 "-----------------------------------" + 1186 "-----------------------------------\n"; 1187 for (int i = 0; i < keys.size(); i++) { 1188 String key = keys.get(i)+""; 1189 String val = vals.get(i)+""; 1190 while (key.length() < longest) { 1191 key = key + " "; 1192 } 1193 str += key + " : " + val + "\n"; 1194 } 1195 str += 1196 "-----------------------------------" + 1197 "-----------------------------------\n"; 1198 return str; 1199 } 1200} 1201 | Popular Tags |