KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > ui > actions > StepIntoSelectionHandler


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.ui.actions;
12
13
14 import com.ibm.icu.text.MessageFormat;
15
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.debug.core.DebugEvent;
18 import org.eclipse.debug.core.DebugException;
19 import org.eclipse.debug.core.DebugPlugin;
20 import org.eclipse.debug.core.IDebugEventFilter;
21 import org.eclipse.jdt.core.IMethod;
22 import org.eclipse.jdt.core.JavaModelException;
23 import org.eclipse.jdt.core.Signature;
24 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
25 import org.eclipse.jdt.debug.core.IJavaStackFrame;
26 import org.eclipse.jdt.debug.core.IJavaThread;
27 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
28 import org.eclipse.jface.dialogs.MessageDialog;
29
30 /**
31  * Handles stepping into a selected method, for a specific thread.
32  */

33 public class StepIntoSelectionHandler implements IDebugEventFilter {
34     
35     /**
36      * The method to step into
37      */

38     private IMethod fMethod;
39     
40     /**
41      * Resolved signature of the method to step into
42      */

43     private String JavaDoc fResolvedSignature;
44     
45     /**
46      * The thread in which to step
47      */

48     private IJavaThread fThread;
49
50     /**
51      * The initial stack frame
52      */

53     private String JavaDoc fOriginalName;
54     private String JavaDoc fOriginalSignature;
55     private String JavaDoc fOriginalTypeName;
56     private int fOriginalStackDepth;
57     
58     /**
59      * Whether this is the first step into.
60      */

61     private boolean fFirstStep = true;
62     
63     /**
64      * The state of step filters before the step.
65      */

66     private boolean fStepFilterEnabledState;
67     
68     /**
69      * Expected event kind
70      */

71     private int fExpectedKind = -1;
72     
73     /**
74      * Expected event detail
75      */

76     private int fExpectedDetail = -1;
77
78     /**
79      * Constructs a step handler to step into the given method in the given thread
80      * starting from the given stack frame.
81      */

82     public StepIntoSelectionHandler(IJavaThread thread, IJavaStackFrame frame, IMethod method) {
83         fMethod = method;
84         fThread = thread;
85         try {
86             fOriginalName = frame.getName();
87             fOriginalSignature = frame.getSignature();
88             fOriginalTypeName = frame.getDeclaringTypeName();
89             if (method.isBinary()) {
90                 fResolvedSignature = method.getSignature();
91             } else {
92                 fResolvedSignature = ToggleBreakpointAdapter.resolveMethodSignature(method.getDeclaringType(), method.getSignature());
93             }
94         } catch (CoreException e) {
95             JDIDebugUIPlugin.log(e);
96         }
97     }
98     
99     /**
100      * Returns the target thread for the step.
101      *
102      * @return the target thread for the step
103      */

104     protected IJavaThread getThread() {
105         return fThread;
106     }
107     
108     protected IJavaDebugTarget getDebugTarget() {
109         return (IJavaDebugTarget)getThread().getDebugTarget();
110     }
111     
112     /**
113      * Returns the method to step into
114      *
115      * @return the method to step into
116      */

117     protected IMethod getMethod() {
118         return fMethod;
119     }
120     
121     /**
122      * Returns the resolved signature of the method to step into
123      *
124      * @return the resolved signature of the method to step into
125      */

126     protected String JavaDoc getSignature() {
127         return fResolvedSignature;
128     }
129     
130     /**
131      * @see org.eclipse.debug.core.IDebugEventFilter#filterDebugEvents(org.eclipse.debug.core.DebugEvent)
132      */

133     public DebugEvent[] filterDebugEvents(DebugEvent[] events) {
134         // we only expect one event from our thread - find the event
135
DebugEvent event = null;
136         int index = -1;
137         int threadEvents = 0;
138         for (int i = 0; i < events.length; i++) {
139             DebugEvent e = events[i];
140             if (isExpectedEvent(e)) {
141                 event = e;
142                 index = i;
143                 threadEvents++;
144             } else if (e.getSource() == getThread()) {
145                 threadEvents++;
146             }
147         }
148         
149         if (event == null) {
150             // nothing to process in this event set
151
return events;
152         }
153                 
154         // create filtered event set
155
DebugEvent[] filtered = new DebugEvent[events.length - 1];
156         if (filtered.length > 0) {
157             int j = 0;
158             for (int i = 0; i < events.length; i++) {
159                 if (i != index) {
160                     filtered[j] = events[i];
161                     j++;
162                 }
163             }
164         }
165         
166         // if more than one event in our thread, abort (filtering our event)
167
if (threadEvents > 1) {
168             cleanup();
169             return filtered;
170         }
171         
172         // we have the one expected event - process it
173
switch (event.getKind()) {
174             case DebugEvent.RESUME:
175                 // next, we expect a step end
176
setExpectedEvent(DebugEvent.SUSPEND, DebugEvent.STEP_END);
177                 if (fFirstStep) {
178                     fFirstStep = false;
179                     return events; // include the first resume event
180
}
181                 // secondary step - filter the event
182
return filtered;
183             case DebugEvent.SUSPEND:
184                 // compare location to desired location
185
try {
186                     final IJavaStackFrame frame = (IJavaStackFrame)getThread().getTopStackFrame();
187                     int stackDepth = frame.getThread().getStackFrames().length;
188                     String JavaDoc name = null;
189                     if (frame.isConstructor()) {
190                         name = frame.getDeclaringTypeName();
191                         index = name.lastIndexOf('.');
192                         if (index >= 0) {
193                             name = name.substring(index + 1);
194                         }
195                     } else {
196                         name = frame.getName();
197                     }
198                     if (name.equals(getMethod().getElementName()) && frame.getSignature().equals(getSignature())) {
199                         // hit
200
cleanup();
201                         return events;
202                     }
203                     // step again
204
Runnable JavaDoc r = null;
205                     if (stackDepth > fOriginalStackDepth) {
206                         if (frame.isSynthetic()) {
207                             // step thru synthetic methods
208
r = new Runnable JavaDoc() {
209                                 public void run() {
210                                     try {
211                                         setExpectedEvent(DebugEvent.RESUME, DebugEvent.STEP_INTO);
212                                         frame.stepInto();
213                                     } catch (DebugException e) {
214                                         JDIDebugUIPlugin.log(e);
215                                         cleanup();
216                                         DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[]{new DebugEvent(getDebugTarget(), DebugEvent.CHANGE)});
217                                     }
218                                 }
219                             };
220                         } else {
221                             r = new Runnable JavaDoc() {
222                                 public void run() {
223                                     try {
224                                         setExpectedEvent(DebugEvent.RESUME, DebugEvent.STEP_RETURN);
225                                         frame.stepReturn();
226                                     } catch (DebugException e) {
227                                         JDIDebugUIPlugin.log(e);
228                                         cleanup();
229                                         DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[]{new DebugEvent(getDebugTarget(), DebugEvent.CHANGE)});
230                                     }
231                                 }
232                             };
233                         }
234                     } else if (stackDepth == fOriginalStackDepth){
235                         // we should be back in the original stack frame - if not, abort
236
if (!(frame.getSignature().equals(fOriginalSignature) && frame.getName().equals(fOriginalName) && frame.getDeclaringTypeName().equals(fOriginalTypeName))) {
237                             missed();
238                             return events;
239                         }
240                         r = new Runnable JavaDoc() {
241                             public void run() {
242                                 try {
243                                     setExpectedEvent(DebugEvent.RESUME, DebugEvent.STEP_INTO);
244                                     frame.stepInto();
245                                 } catch (DebugException e) {
246                                     JDIDebugUIPlugin.log(e);
247                                     cleanup();
248                                     DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[]{new DebugEvent(getDebugTarget(), DebugEvent.CHANGE)});
249                                 }
250                             }
251                         };
252                     } else {
253                         // we returned from the original frame - never hit the desired method
254
missed();
255                         return events;
256                     }
257                     DebugPlugin.getDefault().asyncExec(r);
258                     // filter the events
259
return filtered;
260                 } catch (CoreException e) {
261                     // abort
262
JDIDebugUIPlugin.log(e);
263                     cleanup();
264                     return events;
265                 }
266         }
267         // execution should not reach here
268
return events;
269          
270     }
271     
272     /**
273      * Called when stepping returned from the original frame without entering the desired method.
274      */

275     protected void missed() {
276         cleanup();
277         Runnable JavaDoc r = new Runnable JavaDoc() {
278             public void run() {
279                 String JavaDoc methodName = null;
280                 try {
281                     methodName = Signature.toString(getMethod().getSignature(), getMethod().getElementName(), getMethod().getParameterNames(), false, false);
282                 } catch (JavaModelException e) {
283                     methodName = getMethod().getElementName();
284                 }
285                 new MessageDialog(JDIDebugUIPlugin.getActiveWorkbenchShell(), ActionMessages.StepIntoSelectionHandler_1, null, MessageFormat.format(ActionMessages.StepIntoSelectionHandler_Execution_did_not_enter____0____before_the_current_method_returned__1, new String JavaDoc[]{methodName}), MessageDialog.INFORMATION, new String JavaDoc[] {ActionMessages.StepIntoSelectionHandler_2}, 0).open();
286             }
287         };
288         JDIDebugUIPlugin.getStandardDisplay().asyncExec(r);
289     }
290
291     /**
292      * Performs the step.
293      */

294     public void step() {
295         // add event filter and turn off step filters
296
DebugPlugin.getDefault().addDebugEventFilter(this);
297         fStepFilterEnabledState = getDebugTarget().isStepFiltersEnabled();
298         getDebugTarget().setStepFiltersEnabled(false);
299         try {
300             fOriginalStackDepth = getThread().getStackFrames().length;
301             setExpectedEvent(DebugEvent.RESUME, DebugEvent.STEP_INTO);
302             getThread().stepInto();
303         } catch (DebugException e) {
304             JDIDebugUIPlugin.log(e);
305             cleanup();
306             DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[]{new DebugEvent(getDebugTarget(), DebugEvent.CHANGE)});
307         }
308     }
309     
310     /**
311      * Cleans up when the step is complete/aborted.
312      */

313     protected void cleanup() {
314         DebugPlugin.getDefault().removeDebugEventFilter(this);
315         // restore step filter state
316
getDebugTarget().setStepFiltersEnabled(fStepFilterEnabledState);
317     }
318     
319     /**
320      * Sets the expected debug event kind and detail we are waiting for next.
321      *
322      * @param kind event kind
323      * @param detail event detail
324      */

325     private void setExpectedEvent(int kind, int detail) {
326         fExpectedKind = kind;
327         fExpectedDetail = detail;
328     }
329     
330     /**
331      * Returns whether the given event is what we expected.
332      *
333      * @param event fire event
334      * @return whether the event is what we expected
335      */

336     protected boolean isExpectedEvent(DebugEvent event) {
337         return event.getSource().equals(getThread()) &&
338             event.getKind() == fExpectedKind &&
339             event.getDetail() == fExpectedDetail;
340     }
341 }
342
Popular Tags