0001: /*
0002: * Jdb.java
0003: *
0004: * Copyright (C) 2000-2003 Peter Graves
0005: * $Id: Jdb.java,v 1.28 2003/06/09 16:35:30 piso Exp $
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License
0009: * as published by the Free Software Foundation; either version 2
0010: * of the License, or (at your option) any later version.
0011: *
0012: * This program is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0015: * GNU General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * along with this program; if not, write to the Free Software
0019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0020: */
0021:
0022: package org.armedbear.j.jdb;
0023:
0024: import com.sun.jdi.AbsentInformationException;
0025: import com.sun.jdi.ArrayReference;
0026: import com.sun.jdi.Field;
0027: import com.sun.jdi.LocalVariable;
0028: import com.sun.jdi.Location;
0029: import com.sun.jdi.Method;
0030: import com.sun.jdi.ObjectReference;
0031: import com.sun.jdi.ReferenceType;
0032: import com.sun.jdi.StackFrame;
0033: import com.sun.jdi.StringReference;
0034: import com.sun.jdi.ThreadReference;
0035: import com.sun.jdi.VMDisconnectedException;
0036: import com.sun.jdi.Value;
0037: import com.sun.jdi.VirtualMachine;
0038: import com.sun.jdi.event.ClassPrepareEvent;
0039: import com.sun.jdi.event.LocatableEvent;
0040: import com.sun.jdi.request.ClassPrepareRequest;
0041: import com.sun.jdi.request.EventRequest;
0042: import com.sun.jdi.request.EventRequestManager;
0043: import com.sun.jdi.request.ExceptionRequest;
0044: import com.sun.jdi.request.StepRequest;
0045: import com.sun.jdi.request.ThreadDeathRequest;
0046: import com.sun.jdi.request.ThreadStartRequest;
0047: import java.io.IOException;
0048: import java.io.InputStream;
0049: import java.io.OutputStream;
0050: import java.util.ArrayList;
0051: import java.util.Iterator;
0052: import java.util.List;
0053: import java.util.Map;
0054: import java.util.Set;
0055: import java.util.StringTokenizer;
0056: import javax.swing.Icon;
0057: import javax.swing.SwingUtilities;
0058: import org.armedbear.j.Annotation;
0059: import org.armedbear.j.Buffer;
0060: import org.armedbear.j.BufferIterator;
0061: import org.armedbear.j.Debug;
0062: import org.armedbear.j.Editor;
0063: import org.armedbear.j.EditorIterator;
0064: import org.armedbear.j.EditorList;
0065: import org.armedbear.j.File;
0066: import org.armedbear.j.FastStringBuffer;
0067: import org.armedbear.j.JavaMode;
0068: import org.armedbear.j.JavaSource;
0069: import org.armedbear.j.Line;
0070: import org.armedbear.j.Log;
0071: import org.armedbear.j.Platform;
0072: import org.armedbear.j.Position;
0073: import org.armedbear.j.ReaderThread;
0074: import org.armedbear.j.SimpleEdit;
0075: import org.armedbear.j.Utilities;
0076:
0077: public final class Jdb extends Buffer implements JdbConstants {
0078: private static int catchMode = CATCH_UNCAUGHT;
0079:
0080: private JdbSession session;
0081: private VirtualMachine vm;
0082: private ThreadReference currentThread;
0083: private StackFrame currentStackFrame;
0084: private Location location;
0085: private String mainClass;
0086: private String mainClassArgs;
0087: private String classPath;
0088: private String javaHome;
0089: private String javaExecutable;
0090: private String vmArgs;
0091: private boolean startSuspended;
0092: private boolean isSuspended = true;
0093: private String sourcePath;
0094: private JdbControlDialog controlDialog;
0095: private Position posEndOfBuffer;
0096: private ArrayList breakpointListeners = new ArrayList();
0097: private ArrayList contextListeners = new ArrayList();
0098: private int lastCommand;
0099: private final List breakpoints = new ArrayList();
0100:
0101: public static synchronized void jdb() {
0102: final Editor editor = Editor.currentEditor();
0103: final Buffer buffer = editor.getBuffer();
0104: Jdb jdb = findJdb();
0105: if (jdb != null) {
0106: if (!jdb.equals(buffer)) {
0107: editor.getFrame().unsplitWindow();
0108: editor.makeNext(jdb);
0109: editor.activateInOtherWindow(jdb);
0110: editor.updateDisplay();
0111: }
0112: if (jdb.getVM() != null)
0113: return; // Debugger is running.
0114: }
0115: JdbDialog d = new JdbDialog(editor);
0116: editor.centerDialog(d);
0117: d.show();
0118: editor.getFrame().setWaitCursor();
0119: editor.repaintNow();
0120: if (!d.cancelled()) {
0121: JdbSession session = d.getSession();
0122: if (jdb != null) {
0123: jdb.setSession(session);
0124: jdb.startProcess();
0125: } else {
0126: jdb = new Jdb(session);
0127: if (jdb != null) {
0128: JavaMode.setJdb(jdb);
0129: editor.getFrame().unsplitWindow();
0130: editor.makeNext(jdb);
0131: editor.activateInOtherWindow(jdb);
0132: jdb.showControlDialog();
0133: jdb.startProcess();
0134: }
0135: }
0136: }
0137: editor.getFrame().setDefaultCursor();
0138: }
0139:
0140: private Jdb(JdbSession session) {
0141: super ();
0142: supportsUndo = false;
0143: mode = JdbMode.getMode();
0144: formatter = mode.getFormatter(this );
0145: readOnly = true;
0146: setSession(session);
0147: }
0148:
0149: public VirtualMachine getVM() {
0150: return vm;
0151: }
0152:
0153: public void setVM(VirtualMachine vm) {
0154: this .vm = vm;
0155: if (vm == null) {
0156: isSuspended = true;
0157: currentThread = null;
0158: currentStackFrame = null;
0159: }
0160: }
0161:
0162: public String getMainClass() {
0163: return mainClass;
0164: }
0165:
0166: public String getMainClassArgs() {
0167: return mainClassArgs;
0168: }
0169:
0170: public String getClassPath() {
0171: return classPath;
0172: }
0173:
0174: public String getJavaHome() {
0175: return javaHome;
0176: }
0177:
0178: public String getJavaExecutable() {
0179: return javaExecutable;
0180: }
0181:
0182: public String getVMArgs() {
0183: return vmArgs;
0184: }
0185:
0186: public boolean getStartSuspended() {
0187: return startSuspended;
0188: }
0189:
0190: public String getSourcePath() {
0191: return sourcePath;
0192: }
0193:
0194: public int getLastCommand() {
0195: return lastCommand;
0196: }
0197:
0198: public void setLocation(Location location) {
0199: this .location = location;
0200: }
0201:
0202: public void setCurrentThread(ThreadReference threadRef) {
0203: currentThread = threadRef;
0204: }
0205:
0206: public ThreadReference getCurrentThread() {
0207: return currentThread;
0208: }
0209:
0210: public boolean isSuspended() {
0211: return isSuspended;
0212: }
0213:
0214: public void setSuspended(boolean b) {
0215: isSuspended = b;
0216: }
0217:
0218: public synchronized void setCurrentStackFrame(StackFrame stackFrame) {
0219: currentStackFrame = stackFrame;
0220: }
0221:
0222: public synchronized StackFrame getCurrentStackFrame() {
0223: return currentStackFrame;
0224: }
0225:
0226: public List getBreakpoints() {
0227: return breakpoints;
0228: }
0229:
0230: public void addBreakpointListener(BreakpointListener listener) {
0231: synchronized (breakpointListeners) {
0232: breakpointListeners.add(listener);
0233: }
0234: }
0235:
0236: public void fireBreakpointChanged() {
0237: synchronized (breakpointListeners) {
0238: Iterator iter = breakpointListeners.iterator();
0239: while (iter.hasNext())
0240: ((BreakpointListener) iter.next()).breakpointChanged();
0241: }
0242: }
0243:
0244: public void addContextListener(ContextListener listener) {
0245: synchronized (contextListeners) {
0246: contextListeners.add(listener);
0247: }
0248: }
0249:
0250: private final Runnable fireContextChangedRunnable = new Runnable() {
0251: public void run() {
0252: synchronized (contextListeners) {
0253: for (Iterator it = contextListeners.iterator(); it
0254: .hasNext();)
0255: ((ContextListener) it.next()).contextChanged();
0256: }
0257: }
0258: };
0259:
0260: public void fireContextChanged() {
0261: if (SwingUtilities.isEventDispatchThread())
0262: fireContextChangedRunnable.run();
0263: else
0264: SwingUtilities.invokeLater(fireContextChangedRunnable);
0265: }
0266:
0267: public void initialize() {
0268: // Nothing to do.
0269: }
0270:
0271: public synchronized int load() {
0272: if (!isLoaded()) {
0273: try {
0274: lockWrite();
0275: } catch (InterruptedException e) {
0276: Log.debug(e);
0277: return LOAD_FAILED; // Shouldn't happen.
0278: }
0279: try {
0280: appendLine("");
0281: setLoaded(true);
0282: posEndOfBuffer = new Position(getFirstLine(), 0);
0283: } finally {
0284: unlockWrite();
0285: }
0286: }
0287: return LOAD_COMPLETED;
0288: }
0289:
0290: private void showControlDialog() {
0291: if (controlDialog == null) {
0292: controlDialog = new JdbControlDialog(this );
0293: controlDialog.show();
0294: }
0295: }
0296:
0297: public JdbControlDialog getControlDialog() {
0298: return controlDialog;
0299: }
0300:
0301: public void doCommand(String input) {
0302: String s = input.trim();
0303: String cmd, args;
0304: int index = s.indexOf(' ');
0305: if (index >= 0) {
0306: cmd = s.substring(0, index);
0307: args = s.substring(index + 1).trim();
0308: } else {
0309: cmd = s;
0310: args = null;
0311: }
0312: // Command may be abbreviated.
0313: int command = JdbCommands.findCommand(cmd);
0314: if (command < 0) {
0315: // Not found.
0316: logCommand(cmd);
0317: log("Command not found");
0318: } else {
0319: doCommand(command, args);
0320: lastCommand = command;
0321: }
0322: }
0323:
0324: public void doCommand(int command, String args) {
0325: switch (command) {
0326: case JDB_BREAK:
0327: logCommand("break", args);
0328: doBreak(args, false);
0329: break;
0330: case JDB_CATCH:
0331: logCommand("catch", args);
0332: doCatch(args);
0333: break;
0334: case JDB_CLEAR:
0335: logCommand("clear", args);
0336: doClear(args);
0337: break;
0338: case JDB_FINISH:
0339: logCommand("finish");
0340: doFinish();
0341: break;
0342: case JDB_LOCALS:
0343: logCommand("locals");
0344: doLocals();
0345: break;
0346: case JDB_NEXT:
0347: logCommand("next");
0348: doNext(args);
0349: break;
0350: case JDB_PRINT:
0351: logCommand("print", args);
0352: doPrint(args);
0353: break;
0354: case JDB_QUIT:
0355: logCommand("quit");
0356: quit();
0357: break;
0358: case JDB_RESTART:
0359: logCommand("restart");
0360: restart();
0361: break;
0362: case JDB_CONTINUE:
0363: logCommand("continue");
0364: doContinue();
0365: break;
0366: case JDB_STDIN:
0367: doStdin(args);
0368: break;
0369: case JDB_STEP:
0370: logCommand("step", args);
0371: doStep(args);
0372: break;
0373: case JDB_SUSPEND:
0374: logCommand("suspend");
0375: doSuspend();
0376: break;
0377: case JDB_TBREAK:
0378: logCommand("tbreak", args);
0379: doBreak(args, true);
0380: break;
0381: default:
0382: Log.error("Jdb.doCommand unknown command " + command);
0383: Debug.bug();
0384: break;
0385: }
0386: }
0387:
0388: private static final String prompt = "jdb> ";
0389:
0390: public static final String getPrompt() {
0391: return prompt;
0392: }
0393:
0394: public void prompt() {
0395: Runnable r = new Runnable() {
0396: public void run() {
0397: appendString(prompt, true,
0398: JdbFormatter.JDB_FORMAT_PROMPT);
0399: }
0400: };
0401: if (SwingUtilities.isEventDispatchThread())
0402: r.run();
0403: else
0404: SwingUtilities.invokeLater(r);
0405: }
0406:
0407: private void logCommand(String command) {
0408: log(prompt.concat(command));
0409: }
0410:
0411: private void logCommand(String command, String remainder) {
0412: FastStringBuffer sb = new FastStringBuffer(prompt);
0413: sb.append(command);
0414: if (remainder != null && remainder.length() > 0) {
0415: sb.append(' ');
0416: sb.append(remainder);
0417: }
0418: log(sb.toString());
0419: }
0420:
0421: public void log(String s) {
0422: log(s, true);
0423: }
0424:
0425: private void log(String s, boolean forceNewLine) {
0426: log(s, forceNewLine, JdbFormatter.JDB_FORMAT_LOG);
0427: }
0428:
0429: private void log(final String s, final boolean forceNewLine,
0430: final int flags) {
0431: Runnable r = new Runnable() {
0432: public void run() {
0433: Log.debug(s);
0434: appendString(s.concat("\n"), forceNewLine, flags);
0435: }
0436: };
0437: if (SwingUtilities.isEventDispatchThread())
0438: r.run();
0439: else
0440: SwingUtilities.invokeLater(r);
0441: }
0442:
0443: private void appendString(String s, boolean forceNewLine, int flags) {
0444: try {
0445: lockWrite();
0446: } catch (InterruptedException e) {
0447: Log.error(e);
0448: return;
0449: }
0450: try {
0451: Position posStart = posEndOfBuffer.copy();
0452: if (forceNewLine) {
0453: if (posEndOfBuffer.getOffset() > 0) {
0454: if (!posEndOfBuffer.getLine().getText().equals(
0455: prompt)) {
0456: insertLineSeparator(posEndOfBuffer);
0457: posEndOfBuffer.getLine().setFlags(flags);
0458: }
0459: }
0460: }
0461: if (posEndOfBuffer.getOffset() > 0 && s.startsWith(prompt)) {
0462: if (posEndOfBuffer.getLine().getText().equals(prompt))
0463: s = s.substring(prompt.length());
0464: }
0465: insertString(posEndOfBuffer, s);
0466: if (needsRenumbering())
0467: renumber();
0468: Line line = posStart.getLine();
0469: if (posStart.getOffset() > 0)
0470: line = line.next();
0471: while (line != null) {
0472: line.setFlags(flags);
0473: line = line.next();
0474: }
0475: } finally {
0476: unlockWrite();
0477: }
0478: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
0479: Editor ed = it.nextEditor();
0480: if (ed.getBuffer() == this ) {
0481: ed.eob();
0482: ed.getDisplay().setReframe(-2);
0483: ed.setUpdateFlag(REPAINT);
0484: ed.updateDisplay();
0485: }
0486: }
0487: }
0488:
0489: public void printCurrentLocation(LocatableEvent event) {
0490: printCurrentLocation(event.thread(), event.location());
0491: }
0492:
0493: public void printCurrentLocation(ThreadReference threadRef,
0494: Location location) {
0495: FastStringBuffer sb = new FastStringBuffer("[");
0496: sb.append(threadRef.name());
0497: sb.append("] ");
0498: sb.append(location.declaringType().name());
0499: sb.append('.');
0500: Method method = location.method();
0501: sb.append(method.name());
0502: try {
0503: sb.append(" (");
0504: if (method.isNative()) {
0505: sb.append("native method");
0506: } else {
0507: String sourceName = location.sourceName();
0508: sb.append(location.sourceName());
0509: int lineNumber = location.lineNumber();
0510: if (lineNumber > 0) {
0511: sb.append(':');
0512: sb.append(lineNumber);
0513: }
0514: }
0515: sb.append(')');
0516: } catch (AbsentInformationException e) {
0517: Log.error(e);
0518: }
0519: log(sb.toString());
0520: }
0521:
0522: public void displayRemoteOutput(InputStream inputStream) {
0523: ReaderThread readerThread = new ReaderThread(inputStream) {
0524: public void update(final String s) {
0525: Runnable runnable = new Runnable() {
0526: public void run() {
0527: appendString(s, false,
0528: JdbFormatter.JDB_FORMAT_OUTPUT);
0529: }
0530: };
0531: SwingUtilities.invokeLater(runnable);
0532: }
0533: };
0534: readerThread.setPriority(Thread.MAX_PRIORITY - 1);
0535: readerThread.start();
0536: }
0537:
0538: private void addBreakpoint(ResolvableBreakpoint bp) {
0539: breakpoints.add(bp);
0540: FastStringBuffer sb = new FastStringBuffer();
0541: if (bp.isTemporary())
0542: sb.append("Temporary b");
0543: else
0544: sb.append('B');
0545: sb.append("reakpoint added: ");
0546: sb.append(bp.getLocationString());
0547: log(sb.toString());
0548: if (isSuspended())
0549: prompt();
0550: }
0551:
0552: public void deleteBreakpoint(ResolvableBreakpoint bp) {
0553: bp.clear();
0554: breakpoints.remove(bp);
0555: FastStringBuffer sb = new FastStringBuffer();
0556: if (bp.isTemporary())
0557: sb.append("Temporary b");
0558: else
0559: sb.append('B');
0560: sb.append("reakpoint deleted: ");
0561: sb.append(bp.getLocationString());
0562: log(sb.toString());
0563: if (isSuspended())
0564: prompt();
0565: }
0566:
0567: public static void jdbToggleBreakpoint() {
0568: Jdb jdb = findJdb();
0569: if (jdb == null)
0570: return;
0571: final Editor editor = Editor.currentEditor();
0572: final Line line = editor.getDotLine();
0573: Annotation annotation = line.getAnnotation();
0574: if (annotation instanceof BreakpointAnnotation)
0575: jdbDeleteBreakpoint();
0576: else
0577: jdbSetBreakpoint();
0578: }
0579:
0580: public static void jdbSetBreakpoint() {
0581: setBreakpointAtCurrentLine(false);
0582: }
0583:
0584: public static void jdbRunToCurrentLine() {
0585: Jdb jdb = findJdb();
0586: if (jdb == null)
0587: return;
0588: setBreakpointAtCurrentLine(true);
0589: jdb.logCommand("continue");
0590: jdb.doContinue();
0591: }
0592:
0593: private static void setBreakpointAtCurrentLine(boolean temporary) {
0594: Jdb jdb = findJdb();
0595: if (jdb == null)
0596: return;
0597: final Editor editor = Editor.currentEditor();
0598: final Buffer buffer = editor.getBuffer();
0599: final File file = buffer.getFile();
0600: if (file != null
0601: && file.getName().toLowerCase().endsWith(".java")) {
0602: final Line line = editor.getDotLine();
0603: FastStringBuffer sb = new FastStringBuffer();
0604: if (temporary)
0605: sb.append('t');
0606: sb.append("break ");
0607: sb.append(file.getName());
0608: sb.append(':');
0609: sb.append(line.lineNumber() + 1);
0610: jdb.logCommand(sb.toString());
0611: LineNumberBreakpoint bp = new LineNumberBreakpoint(jdb,
0612: buffer, editor.getDotLine());
0613: if (temporary)
0614: bp.setTemporary();
0615: try {
0616: EventRequest eventRequest = bp
0617: .resolveAgainstPreparedClasses();
0618: if (eventRequest != null) {
0619: eventRequest.enable();
0620: } else {
0621: EventRequestManager mgr = jdb.getVM()
0622: .eventRequestManager();
0623: ClassPrepareRequest cpr = mgr
0624: .createClassPrepareRequest();
0625: String packageName = JavaSource
0626: .getPackageName(buffer);
0627: String classFilter;
0628: if (packageName != null) {
0629: classFilter = packageName.concat(".").concat(
0630: file.getName());
0631: } else {
0632: classFilter = file.getName();
0633: }
0634: if (classFilter.toLowerCase().endsWith(".java")) {
0635: classFilter = classFilter.substring(0,
0636: classFilter.length() - 5);
0637: }
0638: cpr.addClassFilter(classFilter);
0639: cpr.enable();
0640: }
0641: jdb.addBreakpoint(bp);
0642: jdb.saveSession();
0643: jdb.fireBreakpointChanged();
0644: } catch (AbsentInformationException absent) {
0645: jdb.log("Line number information is not available.");
0646: } catch (Exception e) {
0647: Log.error(e);
0648: }
0649: }
0650: }
0651:
0652: public static void jdbDeleteBreakpoint() {
0653: Jdb jdb = findJdb();
0654: if (jdb == null)
0655: return;
0656: final Editor editor = Editor.currentEditor();
0657: final Line line = editor.getDotLine();
0658: Annotation annotation = line.getAnnotation();
0659: if (annotation instanceof BreakpointAnnotation) {
0660: ResolvableBreakpoint bp = ((BreakpointAnnotation) annotation)
0661: .getBreakpoint();
0662: jdb.log("clear " + bp.getLocationString());
0663: jdb.deleteBreakpoint(bp);
0664: File file = bp.getFile();
0665: if (file != null) {
0666: Buffer buffer = Editor.getBufferList().findBuffer(file);
0667: if (buffer != null)
0668: buffer.repaint();
0669: }
0670: jdb.saveSession();
0671: jdb.fireBreakpointChanged();
0672: }
0673: }
0674:
0675: public synchronized void doContinue() {
0676: if (vm != null) {
0677: currentThread = null;
0678: currentStackFrame = null;
0679: vm.resume();
0680: isSuspended = false;
0681: fireContextChanged();
0682: }
0683: }
0684:
0685: public synchronized void doSuspend() {
0686: if (vm != null && !isSuspended) {
0687: vm.suspend();
0688: isSuspended = true;
0689: log("VM suspended");
0690: ThreadReference threadRef = null;
0691: List threads = vm.allThreads();
0692: for (int i = 0; i < threads.size(); i++) {
0693: ThreadReference tr = (ThreadReference) threads.get(i);
0694: if ("main".equals(tr.name()))
0695: threadRef = tr;
0696: }
0697: if (threadRef == null) {
0698: if (threads.size() > 0)
0699: threadRef = (ThreadReference) threads.get(0);
0700: }
0701: setCurrentThread(threadRef);
0702: fireContextChanged();
0703: prompt();
0704: }
0705: }
0706:
0707: public static Jdb findJdb() {
0708: return (Jdb) JavaMode.getJdb();
0709: }
0710:
0711: public void startProcess() {
0712: Runnable r = new Runnable() {
0713: public void run() {
0714: startProcessInternal();
0715: }
0716: };
0717: new Thread(r).start();
0718: }
0719:
0720: private void startProcessInternal() {
0721: VMConnection connection = VMConnection.getConnection(this );
0722: if (connection != null) {
0723: vm = connection.open(this );
0724: if (vm != null) {
0725: EventRequestManager mgr = vm.eventRequestManager();
0726: if (catchMode != CATCH_NONE) {
0727: ExceptionRequest exceptionRequest = mgr
0728: .createExceptionRequest(null,
0729: catchMode == CATCH_ALL, true);
0730: exceptionRequest.enable();
0731: }
0732: ThreadStartRequest tsr = mgr.createThreadStartRequest();
0733: tsr.enable();
0734: ThreadDeathRequest tdr = mgr.createThreadDeathRequest();
0735: tdr.enable();
0736: if (breakpoints.size() > 0) {
0737: Iterator iter = breakpoints.iterator();
0738: while (iter.hasNext()) {
0739: Object obj = iter.next();
0740: if (obj instanceof ResolvableBreakpoint) {
0741: ResolvableBreakpoint bp = (ResolvableBreakpoint) obj;
0742: String className = bp.getClassName();
0743: if (className != null) {
0744: Log
0745: .debug("adding class prepare request for |"
0746: + className + "|");
0747: ClassPrepareRequest cpr = mgr
0748: .createClassPrepareRequest();
0749: cpr.addClassFilter(className);
0750: cpr.enable();
0751: }
0752: }
0753: }
0754: } else {
0755: Log
0756: .debug("startProcessInternal adding default breakpoint");
0757: breakpoints.add(new MethodBreakpoint(this ,
0758: mainClass, "main"));
0759: fireBreakpointChanged();
0760: }
0761: ClassPrepareRequest cpr = mgr
0762: .createClassPrepareRequest();
0763: cpr.addClassFilter(mainClass);
0764: cpr.enable();
0765: if (!startSuspended) {
0766: vm.resume();
0767: isSuspended = false;
0768: fireContextChanged();
0769: }
0770: }
0771: }
0772: }
0773:
0774: public void resolveDeferredRequests(ClassPrepareEvent event) {
0775: synchronized (breakpoints) {
0776: Iterator iter = breakpoints.iterator();
0777: while (iter.hasNext()) {
0778: ResolvableBreakpoint bp = (ResolvableBreakpoint) iter
0779: .next();
0780: if (!bp.isResolved()) {
0781: try {
0782: Log.debug("bp.getClassName() = "
0783: + bp.getClassName());
0784: EventRequest eventRequest = bp
0785: .resolveAgainstPreparedClasses();
0786: if (eventRequest != null) {
0787: Log.debug("bp was resolved");
0788: eventRequest.enable();
0789: } else
0790: Log.debug("bp was NOT resolved");
0791: } catch (Exception e) {
0792: Log.error(e);
0793: }
0794: }
0795: }
0796: }
0797: }
0798:
0799: public JdbSession getSession() {
0800: return session;
0801: }
0802:
0803: private void setSession(JdbSession session) {
0804: this .session = session;
0805: mainClass = session.getMainClass();
0806: mainClassArgs = session.getMainClassArgs();
0807: classPath = session.getClassPath();
0808: javaHome = session.getJavaHome();
0809: javaExecutable = session.getJavaExecutable();
0810: vmArgs = session.getVMArgs();
0811: startSuspended = session.getStartSuspended();
0812: sourcePath = session.getSourcePath();
0813: initializeBreakpoints();
0814: }
0815:
0816: private void initializeBreakpoints() {
0817: breakpoints.clear();
0818: List breakpointSpecifications = session
0819: .getBreakpointSpecifications();
0820: if (breakpointSpecifications != null) {
0821: Iterator iter = breakpointSpecifications.iterator();
0822: while (iter.hasNext()) {
0823: BreakpointSpecification spec = (BreakpointSpecification) iter
0824: .next();
0825: Log.debug(spec.toString());
0826: int lineNumber = spec.getLineNumber();
0827: if (spec.getLineNumber() > 0) {
0828: File file = File.getInstance(spec.getFileName());
0829: if (file != null && file.isFile()) {
0830: LineNumberBreakpoint bp = new LineNumberBreakpoint(
0831: this , spec.getClassName(), file,
0832: lineNumber);
0833: breakpoints.add(bp);
0834: }
0835: } else {
0836: String className = spec.getClassName();
0837: String methodName = spec.getMethodName();
0838: if (className != null && methodName != null) {
0839: MethodBreakpoint bp = new MethodBreakpoint(
0840: this , className, methodName);
0841: breakpoints.add(bp);
0842: }
0843: }
0844: }
0845: }
0846: fireBreakpointChanged();
0847: }
0848:
0849: public void saveSession() {
0850: session.setBreakpoints(breakpoints);
0851: session.saveDefaults();
0852: }
0853:
0854: public void source() {
0855: source(Editor.currentEditor());
0856: }
0857:
0858: public void source(final Editor editor) {
0859: Runnable r = new Runnable() {
0860: public void run() {
0861: if (location == null)
0862: return;
0863: Method method = location.method();
0864: if (method != null && method.isNative())
0865: return;
0866: String className = location.declaringType().name();
0867: String sourceName = null;
0868: try {
0869: sourceName = location.sourceName();
0870: Log.debug("sourceName = |" + sourceName + "|");
0871: } catch (AbsentInformationException e) {
0872: Log.error(e);
0873: }
0874: int lineNumber = location.lineNumber();
0875: Log.debug("lineNumber = " + lineNumber);
0876: Log.debug(location.declaringType().name());
0877: if (sourceName != null)
0878: follow(editor, className, sourceName,
0879: lineNumber - 1);
0880: }
0881: };
0882: if (SwingUtilities.isEventDispatchThread())
0883: r.run();
0884: else
0885: SwingUtilities.invokeLater(r);
0886: }
0887:
0888: private boolean follow(Editor editor, String className,
0889: String fileName, int lineNumber) {
0890: int index = className.indexOf('$');
0891: if (index >= 0)
0892: className = className.substring(0, index);
0893: File file = JavaSource.findSource(className, sourcePath);
0894: if (file == null) {
0895: file = Utilities.findFileInPath(fileName, sourcePath,
0896: getCurrentDirectory());
0897: }
0898: if (file == null)
0899: return false;
0900: if (!file.exists())
0901: return false;
0902: final Buffer buf = Editor.getBuffer(file);
0903: if (buf == null)
0904: return false;
0905: Editor ed = null;
0906: final Buffer currentBuffer = editor.getBuffer();
0907: if (buf == currentBuffer) {
0908: ed = editor;
0909: } else {
0910: editor.makeNext(buf);
0911: if (currentBuffer instanceof Jdb) {
0912: ed = editor.activateInOtherWindow(buf);
0913: } else {
0914: // Re-use current editor.
0915: ed = editor;
0916: ed.activate(buf);
0917: }
0918: }
0919: Line line = buf.getLine(lineNumber);
0920: if (line == null) {
0921: ed.eob();
0922: } else {
0923: ed.addUndo(SimpleEdit.MOVE);
0924: ed.unmark();
0925: ed.update(ed.getDotLine());
0926: ed.setDot(line, 0);
0927: ed.update(ed.getDotLine());
0928: ed.moveCaretToDotCol();
0929: ed.updateDisplay();
0930: }
0931: return true;
0932: }
0933:
0934: public void dispose() {
0935: killVM();
0936: if (controlDialog != null) {
0937: controlDialog.dispose();
0938: controlDialog = null;
0939: }
0940: saveSession();
0941: removeAnnotations();
0942: synchronized (Jdb.class) {
0943: if (JavaMode.getJdb() != this )
0944: Debug.bug();
0945: JavaMode.setJdb(null);
0946: }
0947: }
0948:
0949: private void removeAnnotations() {
0950: if (breakpoints != null) {
0951: for (Iterator it = breakpoints.iterator(); it.hasNext();) {
0952: Object obj = it.next();
0953: if (obj instanceof ResolvableBreakpoint) {
0954: ResolvableBreakpoint bp = (ResolvableBreakpoint) obj;
0955: Line line = bp.getLine();
0956: if (line != null)
0957: line.setAnnotation(null);
0958: }
0959: }
0960: // Repaint editors with buffers in Java mode.
0961: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
0962: Editor ed = it.nextEditor();
0963: if (ed.getModeId() == JAVA_MODE)
0964: ed.repaint();
0965: }
0966: }
0967: }
0968:
0969: private void quit() {
0970: killVM();
0971: removeAnnotations();
0972: // Copy editor list since unsplitWindow() may close an editor.
0973: ArrayList editors = new ArrayList();
0974: for (EditorIterator it = new EditorIterator(); it.hasNext();)
0975: editors.add(it.next());
0976: EditorList editorList = Editor.getEditorList();
0977: for (Iterator it = editors.iterator(); it.hasNext();) {
0978: Editor ed = (Editor) it.next();
0979: if (editorList.contains(ed)) {
0980: if (ed.getBuffer() == this ) {
0981: Editor other = ed.getOtherEditor();
0982: if (other != null) {
0983: Editor.setCurrentEditor(other);
0984: ed.getFrame().unsplitWindow();
0985: }
0986: }
0987: }
0988: }
0989: kill();
0990: }
0991:
0992: private void restart() {
0993: killVM();
0994: saveSession();
0995: removeAnnotations();
0996: session.loadDefaults();
0997: initializeBreakpoints();
0998: startProcess();
0999: fireContextChanged();
1000: }
1001:
1002: private synchronized void killVM() {
1003: if (vm != null) {
1004: try {
1005: vm.exit(0);
1006: } catch (VMDisconnectedException e) {
1007: // Already exited.
1008: }
1009: setVM(null);
1010: }
1011: }
1012:
1013: private void doBreak(String arg, boolean temporary) {
1014: try {
1015: if (vm == null)
1016: return;
1017: if (arg == null) {
1018: log("No location specified");
1019: return;
1020: }
1021: int index = arg.indexOf(':');
1022: if (index >= 0) {
1023: String fileName = arg.substring(0, index);
1024: try {
1025: int lineNumber = Integer.parseInt(arg.substring(
1026: index + 1).trim());
1027: doBreakAtLineNumber(fileName, lineNumber, temporary);
1028: } catch (NumberFormatException e) {
1029: log("Invalid line number");
1030: }
1031: } else {
1032: index = arg.lastIndexOf('.');
1033: if (index < 0) {
1034: log("No class specified");
1035: return;
1036: }
1037: String className = arg.substring(0, index);
1038: String methodName = arg.substring(index + 1);
1039: doBreakAtMethod(className, methodName, temporary);
1040: }
1041: } finally {
1042: if (isSuspended())
1043: prompt();
1044: }
1045: }
1046:
1047: private void doBreakAtLineNumber(String fileName, int lineNumber,
1048: boolean temporary) {
1049: File file = findSourceFile(fileName);
1050: if (file == null) {
1051: log("File not found: ".concat(fileName));
1052: return;
1053: }
1054: String className = file.getName();
1055: if (className.toLowerCase().endsWith(".java"))
1056: className = className.substring(0, className.length() - 5);
1057: Buffer buffer = Editor.getBuffer(file);
1058: if (buffer != null) {
1059: if (!buffer.initialized())
1060: buffer.initialize();
1061: if (!buffer.isLoaded())
1062: buffer.load();
1063: String packageName = JavaSource.getPackageName(buffer);
1064: if (packageName != null)
1065: className = packageName.concat(".").concat(className);
1066: LineNumberBreakpoint bp = new LineNumberBreakpoint(this ,
1067: className, file, lineNumber);
1068: if (temporary)
1069: bp.setTemporary();
1070: try {
1071: EventRequest eventRequest = bp
1072: .resolveAgainstPreparedClasses();
1073: if (eventRequest != null) {
1074: eventRequest.enable();
1075: } else {
1076: EventRequestManager mgr = vm.eventRequestManager();
1077: ClassPrepareRequest cpr = mgr
1078: .createClassPrepareRequest();
1079: String classFilter = className;
1080: cpr.addClassFilter(classFilter);
1081: cpr.enable();
1082: }
1083: addBreakpoint(bp);
1084: saveSession();
1085: fireBreakpointChanged();
1086: } catch (AbsentInformationException absent) {
1087: log("Line number information is not available.");
1088: } catch (Exception e) {
1089: Log.error(e);
1090: }
1091: }
1092: }
1093:
1094: private File findSourceFile(String fileName) {
1095: String canonicalPath = null;
1096: if (Utilities.isFilenameAbsolute(fileName)) {
1097: File file = File.getInstance(fileName);
1098: if (file != null && file.isFile())
1099: return file;
1100: // File does not exist.
1101: return null;
1102: }
1103: // Filename is not absolute.
1104: File mainFile = JavaSource.findSource(mainClass, sourcePath);
1105: if (mainFile != null && mainFile.isFile()) {
1106: File dir = mainFile.getParentFile();
1107: if (dir != null) {
1108: File file = File.getInstance(dir, fileName);
1109: if (file != null && file.isFile())
1110: return file;
1111: }
1112: }
1113: // Try current directory.
1114: File dir = Editor.currentEditor().getCurrentDirectory();
1115: Log.debug("trying dir = " + dir);
1116: File file = File.getInstance(dir, fileName);
1117: if (file != null && file.isFile())
1118: return file;
1119: // Look for match in buffer list.
1120: List dirs = Utilities.getDirectoriesInPath(sourcePath);
1121: for (BufferIterator iter = new BufferIterator(); iter.hasNext();) {
1122: Buffer b = iter.nextBuffer();
1123: file = b.getFile();
1124: if (file.getName().equals(fileName)) {
1125: File rootDir = JavaSource.getPackageRootDirectory(b);
1126: for (Iterator it = dirs.iterator(); it.hasNext();) {
1127: String dirname = (String) it.next();
1128: if (dirname.equals(rootDir.canonicalPath()))
1129: return file;
1130: }
1131: }
1132: if (Platform.isPlatformWindows()) {
1133: if (file.getName().equalsIgnoreCase(fileName)) {
1134: File rootDir = JavaSource
1135: .getPackageRootDirectory(b);
1136: for (Iterator it = dirs.iterator(); it.hasNext();) {
1137: String dirname = (String) it.next();
1138: if (dirname.equalsIgnoreCase(rootDir
1139: .canonicalPath()))
1140: return file;
1141: }
1142: }
1143: }
1144: }
1145: // Not found.
1146: return null;
1147: }
1148:
1149: private void doBreakAtMethod(String className, String methodName,
1150: boolean temporary) {
1151: if (className.indexOf(".") < 0) {
1152: // No package prefix.
1153: String fileName = className.concat(".java");
1154: File file = findSourceFile(fileName);
1155: if (file != null) {
1156: Buffer buffer = Editor.getBuffer(file);
1157: if (buffer != null) {
1158: if (!buffer.initialized())
1159: buffer.initialize();
1160: if (!buffer.isLoaded())
1161: buffer.load();
1162: String packageName = JavaSource
1163: .getPackageName(buffer);
1164: if (packageName != null)
1165: className = packageName.concat(".").concat(
1166: className);
1167: }
1168: }
1169: }
1170: MethodBreakpoint bp = new MethodBreakpoint(this , className,
1171: methodName);
1172: if (temporary)
1173: bp.setTemporary();
1174: try {
1175: EventRequest eventRequest = bp
1176: .resolveAgainstPreparedClasses();
1177: if (eventRequest != null) {
1178: eventRequest.enable();
1179: } else {
1180: EventRequestManager mgr = vm.eventRequestManager();
1181: ClassPrepareRequest cpr = mgr
1182: .createClassPrepareRequest();
1183: cpr.addClassFilter(className);
1184: cpr.enable();
1185: }
1186: addBreakpoint(bp);
1187: saveSession();
1188: fireBreakpointChanged();
1189: } catch (Exception e) {
1190: Log.error(e);
1191: }
1192: }
1193:
1194: // e.g. "clear Jdb.java:877"
1195: private void doClear(String arg) {
1196: if (arg == null) {
1197: log("No breakpoint specified");
1198: return;
1199: }
1200: if (arg.equals("all"))
1201: doClearAll();
1202: else if (arg.indexOf(':') >= 0)
1203: doClearLineNumberBreakpoint(arg);
1204: else
1205: doClearMethodBreakpoint(arg);
1206: // Repaint editors with buffers in Java mode.
1207: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
1208: Editor ed = it.nextEditor();
1209: if (ed.getModeId() == JAVA_MODE)
1210: ed.repaint();
1211: }
1212: }
1213:
1214: private void doClearAll() {
1215: // Disable resolved breakpoints.
1216: for (Iterator it = breakpoints.iterator(); it.hasNext();) {
1217: Object obj = it.next();
1218: if (obj instanceof ResolvableBreakpoint)
1219: ((ResolvableBreakpoint) obj).clear();
1220: }
1221: // Clear the list.
1222: breakpoints.clear();
1223: fireBreakpointChanged();
1224: if (isSuspended())
1225: prompt();
1226: }
1227:
1228: private void doClearLineNumberBreakpoint(String arg) {
1229: int index = arg.indexOf(':');
1230: String fileName = arg.substring(0, index);
1231: if (!fileName.toLowerCase().endsWith(".java"))
1232: fileName = fileName.concat(".java");
1233: int lineNumber = -1;
1234: try {
1235: lineNumber = Integer.parseInt(arg.substring(index + 1));
1236: } catch (NumberFormatException e) {
1237: }
1238: if (lineNumber < 1) {
1239: log("Invalid breakpoint");
1240: return;
1241: }
1242: for (Iterator it = breakpoints.iterator(); it.hasNext();) {
1243: Object obj = it.next();
1244: if (obj instanceof LineNumberBreakpoint) {
1245: LineNumberBreakpoint bp = (LineNumberBreakpoint) obj;
1246: File file = bp.getFile();
1247: if (file != null) {
1248: if (fileName.equals(file.getName())) {
1249: if (lineNumber == bp.getLineNumber()) {
1250: // Found it.
1251: deleteBreakpoint(bp);
1252: fireBreakpointChanged();
1253: return;
1254: }
1255: }
1256: }
1257: }
1258: }
1259: log("No breakpoint at " + arg);
1260: }
1261:
1262: private void doClearMethodBreakpoint(String arg) {
1263: String className, methodName;
1264: int index = arg.lastIndexOf('.');
1265: if (index >= 0) {
1266: className = arg.substring(0, index);
1267: methodName = arg.substring(index + 1);
1268: } else {
1269: className = null;
1270: methodName = arg;
1271: }
1272: for (Iterator it = breakpoints.iterator(); it.hasNext();) {
1273: Object obj = it.next();
1274: if (obj instanceof MethodBreakpoint) {
1275: MethodBreakpoint bp = (MethodBreakpoint) obj;
1276: if (className != null) {
1277: if (className.equals(bp.getClassName())) {
1278: if (methodName.equals(bp.getMethodName())) {
1279: // Found it.
1280: deleteBreakpoint(bp);
1281: fireBreakpointChanged();
1282: return;
1283: }
1284: }
1285: } else {
1286: // No class name specified.
1287: if (methodName.equals(bp.getMethodName())) {
1288: // Found it.
1289: deleteBreakpoint(bp);
1290: fireBreakpointChanged();
1291: return;
1292: }
1293: }
1294: }
1295: }
1296: log("No breakpoint at " + arg);
1297: }
1298:
1299: private synchronized void doCatch(String arg) {
1300: try {
1301: if (vm == null)
1302: return;
1303: int newCatchMode = -1;
1304: if (arg.equals("none"))
1305: newCatchMode = CATCH_NONE;
1306: else if (arg.equals("uncaught"))
1307: newCatchMode = CATCH_UNCAUGHT;
1308: else if (arg.equals("all"))
1309: newCatchMode = CATCH_ALL;
1310: else {
1311: log("Invalid argument");
1312: return;
1313: }
1314: if (newCatchMode == catchMode)
1315: return; // No change.
1316: EventRequestManager mgr = vm.eventRequestManager();
1317: if (catchMode != CATCH_NONE) {
1318: List list = mgr.exceptionRequests();
1319: Log.debug("exception request count = " + list.size());
1320: mgr.deleteEventRequests(list);
1321: }
1322: if (newCatchMode != CATCH_NONE) {
1323: ExceptionRequest exceptionRequest = mgr
1324: .createExceptionRequest(null,
1325: newCatchMode == CATCH_ALL, true);
1326: exceptionRequest.enable();
1327: }
1328: catchMode = newCatchMode;
1329: } finally {
1330: if (isSuspended())
1331: prompt();
1332: }
1333: }
1334:
1335: private void doNext(String args) {
1336: if (vm == null)
1337: return;
1338: if (currentThread == null) {
1339: Log.debug("currentThread is null");
1340: return;
1341: }
1342: Log.debug("currentThread = " + currentThread.name());
1343: int count = 1;
1344: if (args != null) {
1345: try {
1346: count = Integer.parseInt(args);
1347: } catch (NumberFormatException e) {
1348: log("Invalid argument");
1349: return;
1350: }
1351: }
1352: clearStepForThread(currentThread);
1353: EventRequestManager erm = vm.eventRequestManager();
1354: StepRequest request = erm.createStepRequest(currentThread,
1355: StepRequest.STEP_LINE, StepRequest.STEP_OVER);
1356: request.addCountFilter(count);
1357: request.enable();
1358: doContinue();
1359: }
1360:
1361: private void doStep(String args) {
1362: if (vm == null)
1363: return;
1364: if (currentThread == null) {
1365: Log.debug("currentThread is null");
1366: return;
1367: }
1368: Log.debug("currentThread = " + currentThread.name());
1369: boolean out = false;
1370: int count = 1;
1371: if (args != null) {
1372: if (args.equals("out")) {
1373: out = true;
1374: } else {
1375: try {
1376: count = Integer.parseInt(args);
1377: } catch (NumberFormatException e) {
1378: log("Invalid argument");
1379: return;
1380: }
1381: }
1382: }
1383: clearStepForThread(currentThread);
1384: EventRequestManager erm = vm.eventRequestManager();
1385: StepRequest request = erm.createStepRequest(currentThread,
1386: StepRequest.STEP_LINE, out ? StepRequest.STEP_OUT
1387: : StepRequest.STEP_INTO);
1388: request.addCountFilter(count);
1389: request.enable();
1390: doContinue();
1391: }
1392:
1393: private void doFinish() {
1394: if (vm == null)
1395: return;
1396: if (currentThread == null) {
1397: Log.debug("currentThread is null");
1398: return;
1399: }
1400: clearStepForThread(currentThread);
1401: EventRequestManager erm = vm.eventRequestManager();
1402: StepRequest request = erm.createStepRequest(currentThread,
1403: StepRequest.STEP_LINE, StepRequest.STEP_OUT);
1404: request.addCountFilter(1);
1405: request.enable();
1406: doContinue();
1407: }
1408:
1409: private void doPrint(String what) {
1410: if (!isSuspended()) {
1411: log("VM is not suspended");
1412: return;
1413: }
1414: try {
1415: if (what == null || what.length() < 1) {
1416: log("Missing argument");
1417: return;
1418: }
1419: if (currentStackFrame == null) {
1420: log("No stack frame");
1421: return;
1422: }
1423: Value value = getValue(what, currentStackFrame);
1424: if (value == null) {
1425: log("null");
1426: } else if (value instanceof StringReference) {
1427: log(value.toString());
1428: } else if (value instanceof ArrayReference) {
1429: log(value.toString());
1430: log(getStringValueOfArray(what, (ArrayReference) value));
1431: } else {
1432: log(value.toString());
1433: if (value instanceof ObjectReference) {
1434: String s = getStringValueOfObject(
1435: (ObjectReference) value, currentThread);
1436: if (s != null) {
1437: Log.debug(s);
1438: log(s);
1439: }
1440: // getStringValueOfObject() resumes the current thread, so
1441: // the context has changed...
1442: Log.debug("doPrint calling fireContextChanged");
1443: fireContextChanged();
1444: }
1445: }
1446: } catch (AbsentInformationException e) {
1447: Log.debug(e);
1448: log("Local variable information is not available.");
1449: log("Compile with -g to generate local variable information.");
1450: } catch (NoSuchFieldException e) {
1451: log("No such field");
1452: } catch (Exception e) {
1453: log(e.toString());
1454: Log.error(e);
1455: } finally {
1456: if (isSuspended())
1457: prompt();
1458: }
1459: }
1460:
1461: private void doStdin(String s) {
1462: Process process = vm.process();
1463: if (process != null) {
1464: OutputStream out = process.getOutputStream();
1465: try {
1466: if (s != null) {
1467: out.write(s.getBytes());
1468: // Format stdin like stdout. JDB_FORMAT_INPUT is for
1469: // debugger commands.
1470: log(s, false, JdbFormatter.JDB_FORMAT_OUTPUT);
1471: }
1472: out.write('\n');
1473: out.flush();
1474: } catch (IOException e) {
1475: Log.error(e);
1476: }
1477: }
1478: }
1479:
1480: private void doLocals() {
1481: if (vm == null)
1482: return;
1483: if (currentThread == null) {
1484: Log.debug("currentThread is null");
1485: return;
1486: }
1487: boolean contextChanged = false;
1488: try {
1489: StackFrame stackFrame = currentStackFrame;
1490: if (stackFrame == null && currentThread.frameCount() > 0)
1491: stackFrame = currentThread.frame(0);
1492: List variables = stackFrame.visibleVariables();
1493: Map map = stackFrame.getValues(variables);
1494: Set entrySet = map.entrySet();
1495: Iterator iter = entrySet.iterator();
1496: while (iter.hasNext()) {
1497: Map.Entry entry = (Map.Entry) iter.next();
1498: LocalVariable variable = (LocalVariable) entry.getKey();
1499: Value value = (Value) entry.getValue();
1500: FastStringBuffer sb = new FastStringBuffer(variable
1501: .typeName());
1502: sb.append(' ');
1503: sb.append(variable.name());
1504: sb.append(" = ");
1505: sb.append(value);
1506: if (value instanceof StringReference) {
1507: ;
1508: } else if (value instanceof ArrayReference) {
1509: String s = getStringValueOfArray(variable.name(),
1510: (ArrayReference) value);
1511: if (s.length() > 0) {
1512: sb.append('\n');
1513: sb.append(s);
1514: }
1515: } else if (value instanceof ObjectReference) {
1516: String s = getStringValueOfObject(
1517: (ObjectReference) value, currentThread);
1518: if (s != null) {
1519: sb.append(' ');
1520: sb.append(s);
1521: }
1522: // getStringValueOfObject() resumes the current thread, so
1523: // the context has changed...
1524: contextChanged = true;
1525: }
1526: log(sb.toString());
1527: }
1528: } catch (AbsentInformationException e) {
1529: Log.debug(e);
1530: log("Local variable information is not available.");
1531: log("Compile with -g to generate local variable information.");
1532: } catch (Exception e) {
1533: Log.error(e);
1534: }
1535: if (contextChanged)
1536: fireContextChanged();
1537: if (isSuspended())
1538: prompt();
1539: }
1540:
1541: private String getStringValueOfObject(ObjectReference objRef,
1542: ThreadReference threadRef) {
1543: try {
1544: // Get index of current stack frame so we can restore it later.
1545: List frames = threadRef.frames();
1546: int index = -1;
1547: if (frames.size() > 0) {
1548: for (int i = 0; i < frames.size(); i++) {
1549: StackFrame frame = (StackFrame) frames.get(i);
1550: if (frame != null
1551: && frame.equals(currentStackFrame)) {
1552: index = i;
1553: break;
1554: }
1555: }
1556: }
1557:
1558: ReferenceType refType = objRef.referenceType();
1559: List methods = refType.methodsByName("toString",
1560: "()Ljava/lang/String;");
1561: Method method = (Method) methods.get(0);
1562: Value value = objRef.invokeMethod(threadRef, method,
1563: new ArrayList(),
1564: ObjectReference.INVOKE_SINGLE_THREADED);
1565:
1566: // Restore current stack frame if possible.
1567: frames = threadRef.frames();
1568: if (frames != null && index >= 0 && index < frames.size())
1569: currentStackFrame = (StackFrame) frames.get(index);
1570:
1571: if (value != null)
1572: return value.toString();
1573: } catch (Exception e) {
1574: Log.error(e);
1575: }
1576: return null;
1577: }
1578:
1579: private static String getStringValueOfArray(String name,
1580: ArrayReference ar) {
1581: FastStringBuffer sb = new FastStringBuffer();
1582: final int limit = ar.length();
1583: for (int i = 0; i < limit; i++) {
1584: sb.append(" ");
1585: sb.append(name);
1586: sb.append('[');
1587: sb.append(i);
1588: sb.append("]: ");
1589: Value v = ar.getValue(i);
1590: sb.append(v == null ? "null" : v.toString());
1591: if (i < limit - 1)
1592: sb.append('\n');
1593: }
1594: return sb.toString();
1595: }
1596:
1597: private void clearStepForThread(ThreadReference threadRef) {
1598: EventRequestManager erm = vm.eventRequestManager();
1599: List requests = erm.stepRequests();
1600: Iterator iter = requests.iterator();
1601: while (iter.hasNext()) {
1602: StepRequest request = (StepRequest) iter.next();
1603: if (request.thread().equals(threadRef)) {
1604: erm.deleteEventRequest(request);
1605: break; // There should be only one!
1606: }
1607: }
1608: }
1609:
1610: private static Value getValue(String expression, StackFrame frame)
1611: throws Exception {
1612: Log.debug("getValue");
1613: StringTokenizer st = new StringTokenizer(expression, "[].");
1614: if (!st.hasMoreTokens()) {
1615: Log.debug("no more tokens");
1616: throw new NoSuchFieldException();
1617: }
1618: String token = st.nextToken();
1619: Log.debug("token = |" + token + "|");
1620: Value currentValue = null;
1621: Field currentField = null;
1622: ObjectReference obj = null;
1623: LocalVariable local = null;
1624: if (token.equals("this")) {
1625: currentValue = frame.this Object();
1626: if (currentValue == null)
1627: throw new NoSuchFieldException(token);
1628: } else {
1629: Log.debug("calling visibleVariableByName");
1630: local = frame.visibleVariableByName(token);
1631: Log.debug("local = " + local);
1632: if (local != null) {
1633: currentValue = frame.getValue(local);
1634: Log.debug("currentValue = " + currentValue);
1635: } else {
1636: ReferenceType refType = frame.location()
1637: .declaringType();
1638: Log.debug("refType = " + refType);
1639: obj = frame.this Object();
1640: if (obj == null) {
1641: // Static method.
1642: Log.debug("static method");
1643: currentField = refType.fieldByName(token);
1644: if (currentField != null && currentField.isStatic())
1645: currentValue = refType.getValue(currentField);
1646: else
1647: throw new NoSuchFieldException();
1648: } else {
1649: currentField = refType.fieldByName(token);
1650: if (currentField != null)
1651: currentValue = obj.getValue(currentField);
1652: else {
1653: Log.debug("throwing NoSuchFieldException ...");
1654: throw new NoSuchFieldException();
1655: }
1656: }
1657: }
1658: }
1659: while (st.hasMoreTokens() && currentValue != null) {
1660: String prevToken = token;
1661: token = st.nextToken();
1662: Log.debug("while loop token = |" + token + "|");
1663: Object arg;
1664: try {
1665: arg = new Integer(token);
1666: } catch (NumberFormatException e) {
1667: arg = token;
1668: }
1669: if (currentValue instanceof ArrayReference) {
1670: int count = -1;
1671: if (arg instanceof Integer)
1672: count = ((Integer) arg).intValue();
1673: if (count >= 0
1674: && count < ((ArrayReference) currentValue)
1675: .length())
1676: currentValue = ((ArrayReference) currentValue)
1677: .getValue(count);
1678: else
1679: throw new ArrayIndexOutOfBoundsException();
1680: } else if (currentValue instanceof ObjectReference
1681: && arg instanceof String) {
1682: Log.debug("object reference, string");
1683: obj = (ObjectReference) currentValue;
1684: ReferenceType refType = obj.referenceType();
1685: currentField = refType.fieldByName(token);
1686: if (currentField != null)
1687: currentValue = obj.getValue(currentField);
1688: } else
1689: throw new Exception();
1690: }
1691: Log.debug("getValue returning currentValue = " + currentValue);
1692: return currentValue;
1693: }
1694:
1695: public boolean isModified() {
1696: return false;
1697: }
1698:
1699: // For the buffer list.
1700: public String toString() {
1701: return "jdb";
1702: }
1703:
1704: public String getTitle() {
1705: return "jdb";
1706: }
1707:
1708: public Icon getIcon() {
1709: return Utilities.getIconFromFile("jpty.png");
1710: }
1711: }
|