001: /*
002: * EventHandler.java
003: *
004: * Copyright (C) 2002-2003 Peter Graves
005: * $Id: EventHandler.java,v 1.8 2003/05/28 16:11:49 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j.jdb;
023:
024: import com.sun.jdi.IncompatibleThreadStateException;
025: import com.sun.jdi.Method;
026: import com.sun.jdi.ObjectReference;
027: import com.sun.jdi.ReferenceType;
028: import com.sun.jdi.StackFrame;
029: import com.sun.jdi.ThreadReference;
030: import com.sun.jdi.VMDisconnectedException;
031: import com.sun.jdi.Value;
032: import com.sun.jdi.event.BreakpointEvent;
033: import com.sun.jdi.event.ClassPrepareEvent;
034: import com.sun.jdi.event.ClassUnloadEvent;
035: import com.sun.jdi.event.Event;
036: import com.sun.jdi.event.EventIterator;
037: import com.sun.jdi.event.EventQueue;
038: import com.sun.jdi.event.EventSet;
039: import com.sun.jdi.event.ExceptionEvent;
040: import com.sun.jdi.event.LocatableEvent;
041: import com.sun.jdi.event.MethodEntryEvent;
042: import com.sun.jdi.event.MethodExitEvent;
043: import com.sun.jdi.event.StepEvent;
044: import com.sun.jdi.event.ThreadDeathEvent;
045: import com.sun.jdi.event.ThreadStartEvent;
046: import com.sun.jdi.event.VMDeathEvent;
047: import com.sun.jdi.event.VMDisconnectEvent;
048: import com.sun.jdi.event.VMStartEvent;
049: import com.sun.jdi.event.WatchpointEvent;
050: import com.sun.jdi.request.BreakpointRequest;
051: import com.sun.jdi.request.EventRequest;
052: import java.util.ArrayList;
053: import java.util.Iterator;
054: import java.util.List;
055: import javax.swing.SwingUtilities;
056: import org.armedbear.j.Buffer;
057: import org.armedbear.j.Editor;
058: import org.armedbear.j.FastStringBuffer;
059: import org.armedbear.j.File;
060: import org.armedbear.j.Log;
061: import org.armedbear.j.Platform;
062:
063: public final class EventHandler implements Runnable {
064: private final Jdb jdb;
065: private final Thread eventHandlerThread;
066: private boolean connected = true;
067: private boolean completed;
068:
069: public EventHandler(Jdb jdb) {
070: this .jdb = jdb;
071: eventHandlerThread = new Thread(this , "jdb event handler");
072: eventHandlerThread.start();
073: }
074:
075: public void run() {
076: EventQueue queue = jdb.getVM().eventQueue();
077: while (connected) {
078: try {
079: boolean resume = true;
080: EventSet eventSet = queue.remove();
081: EventIterator iter = eventSet.eventIterator();
082: while (iter.hasNext()) {
083: Event event = iter.nextEvent();
084: resume &= handleEvent(event);
085: }
086: if (resume)
087: eventSet.resume();
088: else {
089: jdb.setSuspended(true);
090: // Set current thread and stack frame.
091: if (eventSet.size() > 0) {
092: Event event = (Event) eventSet.iterator()
093: .next();
094: ThreadReference threadRef = getThreadForEvent(event);
095: if (threadRef != null) {
096: jdb.setCurrentThread(threadRef);
097: try {
098: List frames = threadRef.frames();
099: if (frames.size() > 0)
100: jdb
101: .setCurrentStackFrame((StackFrame) frames
102: .get(0));
103: } catch (IncompatibleThreadStateException e) {
104: Log.error(e);
105: }
106: } else {
107: Log.debug("threadRef is null");
108: Log.debug("event = " + event);
109: }
110: }
111: jdb.fireContextChanged();
112: jdb.prompt();
113: Runnable r = new Runnable() {
114: public void run() {
115: if (!Platform.isPlatformWindows())
116: Editor.getCurrentFrame().toFront();
117: jdb.getControlDialog().toFront();
118: }
119: };
120: SwingUtilities.invokeLater(r);
121: }
122: } catch (InterruptedException e) {
123: // Do nothing.
124: } catch (VMDisconnectedException disconnect) {
125: break;
126: }
127: }
128: synchronized (this ) {
129: completed = true;
130: notifyAll();
131: }
132: jdb.setVM(null);
133: }
134:
135: private static ThreadReference getThreadForEvent(Event event) {
136: if (event instanceof ClassPrepareEvent)
137: return ((ClassPrepareEvent) event).thread();
138: else if (event instanceof LocatableEvent)
139: return ((LocatableEvent) event).thread();
140: else if (event instanceof ThreadStartEvent)
141: return ((ThreadStartEvent) event).thread();
142: else if (event instanceof ThreadDeathEvent)
143: return ((ThreadDeathEvent) event).thread();
144: else if (event instanceof VMStartEvent)
145: return ((VMStartEvent) event).thread();
146: else
147: return null;
148: }
149:
150: // Return true to resume.
151: private boolean handleEvent(Event event) {
152: if (event instanceof ExceptionEvent)
153: return handleExceptionEvent(event);
154: else if (event instanceof BreakpointEvent)
155: return handleBreakpointEvent(event);
156: else if (event instanceof WatchpointEvent)
157: return handleFieldWatchEvent(event);
158: else if (event instanceof StepEvent)
159: return handleStepEvent(event);
160: else if (event instanceof MethodEntryEvent)
161: return handleMethodEntryEvent(event);
162: else if (event instanceof MethodExitEvent)
163: return handleMethodExitEvent(event);
164: else if (event instanceof ClassPrepareEvent)
165: return handleClassPrepareEvent(event);
166: else if (event instanceof ClassUnloadEvent)
167: return handleClassUnloadEvent(event);
168: else if (event instanceof ThreadStartEvent)
169: return handleThreadStartEvent(event);
170: else if (event instanceof ThreadDeathEvent)
171: return handleThreadDeathEvent(event);
172: else if (event instanceof VMStartEvent)
173: return handleVMStartEvent(event);
174: else if (event instanceof VMDeathEvent)
175: return handleVMDeathEvent(event);
176: else if (event instanceof VMDisconnectEvent)
177: return handleVMDisconnectEvent(event);
178: jdb.log("handleEvent " + event.toString());
179: return false;
180: }
181:
182: private boolean handleExceptionEvent(Event event) {
183: ExceptionEvent ee = (ExceptionEvent) event;
184: if (ee.catchLocation() != null)
185: jdb.log("Exception encountered: " + ee.exception());
186: else
187: jdb.log("Uncaught exception encountered " + ee.exception());
188: jdb.printCurrentLocation(ee);
189: jdb.setLocation(ee.location());
190: jdb.source();
191: // Suspend the VM.
192: return false;
193: }
194:
195: private boolean handleBreakpointEvent(Event event) {
196: jdb.log("Breakpoint hit");
197: BreakpointEvent evt = (BreakpointEvent) event;
198: jdb.printCurrentLocation(evt);
199: jdb.setLocation(evt.location());
200: jdb.source();
201: // If breakpoint is temporary, delete it.
202: EventRequest er = evt.request();
203: if (er instanceof BreakpointRequest) {
204: BreakpointRequest br = (BreakpointRequest) er;
205: for (Iterator it = jdb.getBreakpoints().iterator(); it
206: .hasNext();) {
207: ResolvableBreakpoint bp = (ResolvableBreakpoint) it
208: .next();
209: if (bp.getEventRequest() == br) {
210: if (bp.isTemporary()) {
211: jdb.deleteBreakpoint(bp);
212: File file = bp.getFile();
213: if (file != null) {
214: Buffer buffer = Editor.getBufferList()
215: .findBuffer(file);
216: if (buffer != null)
217: buffer.repaint();
218: }
219: jdb.fireBreakpointChanged();
220: }
221: break;
222: }
223: }
224: }
225: // Suspend the VM.
226: return false;
227: }
228:
229: private boolean handleFieldWatchEvent(Event event) {
230: jdb.log("handleFieldWatchEvent");
231: return true;
232: }
233:
234: private boolean handleStepEvent(Event event) {
235: StepEvent evt = (StepEvent) event;
236: jdb.printCurrentLocation(evt);
237: jdb.setLocation(evt.location());
238: jdb.source();
239: // Suspend the VM.
240: return false;
241: }
242:
243: private boolean handleMethodEntryEvent(Event event) {
244: MethodEntryEvent evt = (MethodEntryEvent) event;
245: Method method = evt.method();
246: FastStringBuffer sb = new FastStringBuffer("Method entered: ");
247: sb.append(method.declaringType().name());
248: sb.append('.');
249: sb.append(method.name());
250: jdb.log(sb.toString());
251: return true;
252: }
253:
254: private boolean handleMethodExitEvent(Event event) {
255: MethodExitEvent evt = (MethodExitEvent) event;
256: Method method = evt.method();
257: FastStringBuffer sb = new FastStringBuffer("Method exited: ");
258: sb.append(method.declaringType().name());
259: sb.append('.');
260: sb.append(method.name());
261: jdb.log(sb.toString());
262: return true;
263: }
264:
265: private boolean handleClassPrepareEvent(Event event) {
266: ClassPrepareEvent evt = (ClassPrepareEvent) event;
267: jdb.log("Class loaded: ".concat(evt.referenceType().name()));
268: jdb.resolveDeferredRequests(evt);
269: return true;
270: }
271:
272: private boolean handleClassUnloadEvent(Event event) {
273: ClassUnloadEvent evt = (ClassUnloadEvent) event;
274: jdb.log("Class unloaded: ".concat(evt.className()));
275: return true;
276: }
277:
278: private boolean handleThreadStartEvent(Event event) {
279: ThreadStartEvent evt = (ThreadStartEvent) event;
280: ThreadReference threadRef = evt.thread();
281: jdb.log("Thread started: ".concat(threadRef.name()));
282: return true;
283: }
284:
285: private boolean handleThreadDeathEvent(Event event) {
286: ThreadDeathEvent evt = (ThreadDeathEvent) event;
287: ThreadReference threadRef = evt.thread();
288: jdb.log("Thread exited: ".concat(threadRef.name()));
289: return true;
290: }
291:
292: private boolean handleVMStartEvent(Event event) {
293: jdb.log("VM loaded");
294: if (jdb.isSuspended()) {
295: jdb.log("VM suspended");
296: jdb.prompt();
297: }
298: return true;
299: }
300:
301: private boolean handleVMDeathEvent(Event event) {
302: jdb.log("VM exited");
303: return true;
304: }
305:
306: private boolean handleVMDisconnectEvent(Event event) {
307: jdb.log("VM disconnected");
308: return true;
309: }
310: }
|