1 /*
2 * $Id: EventRecorder.java,v 1.4 2003/07/22 00:07:22 trondandersen Exp $
3 * Copyright 2003 OErjan Nygaard Austvold. All rights reserved.
4 */
5 package org.jdiseq;
6
7 import com.sun.jdi.*;
8 import com.sun.jdi.event.*;
9 import com.sun.jdi.request.EventRequestManager;
10 import com.sun.jdi.request.MethodEntryRequest;
11 import com.sun.jdi.request.MethodExitRequest;
12
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16
17 /***
18 * This class implements a recorder for selected JDI events.
19 * Listeneres interested in receiving events implements the {@link JdiEventListener} and
20 * registers with an instance of this class.
21 * <code>JdiEventListener</code>
22 * <p>Changelog:
23 * <pre>
24 * $Log: EventRecorder.java,v $
25 * Revision 1.4 2003/07/22 00:07:22 trondandersen
26 * Removed Jython test cases
27 * .
28 *
29 * Revision 1.3 2003/05/05 17:39:04 trondandersen
30 * Inserted initial configuration class and SettingUtil retriever.
31 * Added jython test for these classes. Inserted a logging class.
32 * .
33 *
34 * Revision 1.2 2003/04/02 19:48:47 austvold
35 * Minor updates. Mostly adaptation to new event and eventlistener name.
36 * General brush-up on javadoc comments.
37 * Removal of auto-added revision and date-of-commit members.
38 *
39 * Revision 1.1.1.1 2003/03/28 08:18:23 austvold
40 * Initial import.
41 *
42 * </pre>
43 *
44 * @author Ørjan Nygaard Austvold <austvold@acm.org>
45 * @version $Id: EventRecorder.java,v 1.4 2003/07/22 00:07:22 trondandersen Exp $
46 */
47 class EventRecorder implements Runnable {
48 private JdiRemoteVMConnector vmConnector;
49 private Filter filter;
50 // private Thread recorder;
51 private List eventListeners;
52
53
54 /***
55 * Sole constructor.
56 * @param vmConnector the vmConnector to record events from.
57 * @param filter a filter for events.
58 */
59 EventRecorder(JdiRemoteVMConnector vmConnector, Filter filter) {
60 this.vmConnector = vmConnector;
61 this.filter = filter;
62 eventListeners = Collections.synchronizedList(new ArrayList());
63 }
64
65
66 /***
67 * Starts a recording session.
68 * @throws JdiConnectionException if anything bad happens.
69 */
70 void startRecording() throws JdiConnectionException {
71 if (vmConnector.isConnected() == false) {
72 throw new JdiConnectionException("Not connected.");
73 }
74 // recorder = new Thread(this, "EventRecorder");
75 // recorder.start();
76 run();
77 }
78
79
80 /***
81 * Stops the recording session, if any such session exists.
82 */
83 public void stopRecording() {
84 // recorder.interrupt();
85 // recorder = null;
86 }
87
88
89 /***
90 * Adds a listener for JDI events.
91 * After registration the listner will begin to receive JDI events.
92 * @param l the listener to add
93 */
94 public void addEventListener(JdiEventListener l) {
95 eventListeners.add(l);
96 }
97
98
99 /***
100 * Removes a listener.
101 * After removal the listner will not receive anymore JDI events.
102 * @param l the listner to remove
103 */
104 public void removeEventListener(JdiEventListener l) {
105 eventListeners.remove(l);
106 }
107
108
109
110 /***
111 * Notifies JDI event listeners about a new JDI event.
112 * @param e the event that occured
113 */
114 private void notifyJdiEventListeners(JdiEvent e) {
115 // TODO: shouldn't we make a copy of the list before iteration
116 for (int i = 0; i < eventListeners.size(); i++) {
117 JdiEventListener l = (JdiEventListener) eventListeners.get(i);
118 if (e.isMethodEntry()) {
119 l.methodEntered(e);
120 } else {
121 l.methodExited(e);
122 }
123 }
124 }
125
126
127 /***
128 * Registers the filter an waits for new JDI events from the debugee.
129 * // TODO: It's a design flaw that this method is public...
130 */
131 public void run() {
132 EventRequestManager erm = vmConnector.getVm().eventRequestManager();
133
134 MethodEntryRequest mer = erm.createMethodEntryRequest();
135 MethodExitRequest mlr = erm.createMethodExitRequest();
136
137 String[] classIncludes = filter.getClassIncludes();
138 for (int i = 0; i < filter.getClassIncludes().length; i++) {
139 mer.addClassFilter(classIncludes[i]);
140 mlr.addClassFilter(classIncludes[i]);
141 }
142 String[] classExcludes = filter.getClassExcludes();
143 for (int i = 0; i < classExcludes.length; i++) {
144 mer.addClassExclusionFilter(classExcludes[i]);
145 mlr.addClassExclusionFilter(classExcludes[i]);
146 }
147
148 mer.enable();
149 mlr.enable();
150
151 EventQueue eq = vmConnector.getVm().eventQueue();
152 vmConnector.getVm().resume();
153 while (true) {
154 try {
155 EventSet eventSet = eq.remove();
156 for (EventIterator ei = eventSet.eventIterator(); ei.hasNext();) {
157 Event e = ei.nextEvent();
158 if (e instanceof LocatableEvent) {
159 Method method = null;
160 boolean methodEntry = false;
161
162 if (e instanceof MethodEntryEvent) {
163 method = ((MethodEntryEvent) e).method();
164 methodEntry = true;
165 } else if (e instanceof MethodExitEvent) {
166 method = ((MethodExitEvent) e).method();
167 methodEntry = false;
168 } else {
169 continue; // does other LocatableEvents exists?
170 }
171
172 ThreadReference threadRef = ((LocatableEvent) e).thread();
173
174 ObjectReference objectRef = null;
175 try {
176 StackFrame sf = threadRef.frame(threadRef.frameCount() - 1);
177 objectRef = sf.thisObject();
178 } catch (IncompatibleThreadStateException e1) {
179 e1.printStackTrace(); // how to handle?
180 objectRef = null;
181 }
182
183 ReferenceType declaringType =
184 ((LocatableEvent) e).location().declaringType();
185
186 JdiEvent me = new JdiEvent(methodEntry,
187 method, threadRef, objectRef, declaringType);
188 notifyJdiEventListeners(me);
189 }
190 }
191 // vm is always paused after removal of events from the event queue
192 eventSet.resume();
193 } catch (InterruptedException e) {
194 break; // we're told to stop recording
195 }
196 } // end whle
197 }
198 }
This page was automatically generated by Maven