KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > debugger > jpda > actions > StepIntoActionProvider


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.debugger.jpda.actions;
20
21 import com.sun.jdi.ThreadReference;
22 import com.sun.jdi.VMDisconnectedException;
23 import com.sun.jdi.IncompatibleThreadStateException;
24 import com.sun.jdi.VirtualMachine;
25 import com.sun.jdi.event.Event;
26 import com.sun.jdi.event.LocatableEvent;
27 import com.sun.jdi.request.StepRequest;
28 import java.beans.PropertyChangeEvent JavaDoc;
29 import java.beans.PropertyChangeListener JavaDoc;
30 import java.util.*;
31 import java.util.logging.Level JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33 import org.netbeans.api.debugger.ActionsManager;
34 import org.netbeans.api.debugger.DebuggerManager;
35 import org.netbeans.api.debugger.Session;
36 import org.netbeans.spi.debugger.ContextProvider;
37 import org.netbeans.spi.debugger.ActionsProvider;
38 import org.netbeans.api.debugger.jpda.JPDADebugger;
39 import org.netbeans.api.debugger.jpda.JPDAThread;
40 import org.netbeans.api.debugger.jpda.SmartSteppingFilter;
41 import org.netbeans.modules.debugger.jpda.SourcePath;
42 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
43 import org.netbeans.modules.debugger.jpda.JPDAStepImpl.SingleThreadedStepWatch;
44 import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
45 import org.netbeans.modules.debugger.jpda.util.Executor;
46 import org.netbeans.spi.debugger.jpda.SourcePathProvider;
47 import org.openide.ErrorManager;
48 import org.openide.util.NbBundle;
49
50
51 /**
52  * Implements non visual part of stepping through code in JPDA debugger.
53  * It supports standart debugging actions StepInto, Over, Out, RunToCursor,
54  * and Go. And advanced "smart tracing" action.
55  *
56  * @author Jan Jancura
57  */

58 public class StepIntoActionProvider extends JPDADebuggerActionProvider
59 implements Executor, PropertyChangeListener JavaDoc {
60     
61     public static final String JavaDoc SS_STEP_OUT = "SS_ACTION_STEPOUT";
62     
63     private static final Logger JavaDoc smartLogger = Logger.getLogger("org.netbeans.modules.debugger.jpda.smartstepping"); // NOI18N
64
private static final Logger JavaDoc logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.jdievents"); // NOI18N
65

66     private StepRequest stepRequest;
67     private String JavaDoc position;
68     private ContextProvider contextProvider;
69     private boolean smartSteppingStepOut;
70     private SingleThreadedStepWatch stepWatch;
71
72     public StepIntoActionProvider (ContextProvider contextProvider) {
73         super (
74             (JPDADebuggerImpl) contextProvider.lookupFirst
75                 (null, JPDADebugger.class)
76         );
77         this.contextProvider = contextProvider;
78         getSmartSteppingFilterImpl ().addPropertyChangeListener (this);
79         SourcePath ec = (SourcePath) contextProvider.
80             lookupFirst (null, SourcePath.class);
81         ec.addPropertyChangeListener (this);
82         Map properties = (Map) contextProvider.lookupFirst (null, Map.class);
83         if (properties != null)
84             smartSteppingStepOut = properties.containsKey (SS_STEP_OUT);
85         setProviderToDisableOnLazyAction(this);
86     }
87
88
89     // ActionProviderSupport ...................................................
90

91     public Set getActions () {
92         return new HashSet<Object JavaDoc>(Arrays.asList (new Object JavaDoc[] {
93             ActionsManager.ACTION_STEP_INTO,
94         }));
95     }
96     
97     public void doAction (Object JavaDoc action) {
98         runAction();
99     }
100     
101     public void postAction(Object JavaDoc action, final Runnable JavaDoc actionPerformedNotifier) {
102         doLazyAction(new Runnable JavaDoc() {
103             public void run() {
104                 try {
105                     runAction();
106                 } finally {
107                     actionPerformedNotifier.run();
108                 }
109             }
110         });
111     }
112     
113     public void runAction() {
114         synchronized (getDebuggerImpl ().LOCK) {
115             smartLogger.finer("STEP INTO.");
116             JPDAThread t = getDebuggerImpl ().getCurrentThread ();
117             if (t == null || !t.isSuspended()) {
118                 // Can not step when it's not suspended.
119
smartLogger.finer("Can not step into! Thread "+t+" not suspended!");
120                 return ;
121             }
122             JPDAThread resumeThread = setStepRequest (StepRequest.STEP_INTO);
123             position = t.getClassName () + '.' +
124                        t.getMethodName () + ':' +
125                        t.getLineNumber (null);
126             logger.fine("JDI Request (action step into): " + stepRequest);
127             if (stepRequest == null) return ;
128             try {
129                 if (resumeThread == null) {
130                     getDebuggerImpl ().resume ();
131                 } else {
132                     //resumeThread.resume();
133
stepWatch = new SingleThreadedStepWatch(getDebuggerImpl(), stepRequest);
134                     getDebuggerImpl().resumeCurrentThread();
135                 }
136             } catch (VMDisconnectedException e) {
137                 ErrorManager.getDefault().notify(ErrorManager.USER,
138                     ErrorManager.getDefault().annotate(e,
139                         NbBundle.getMessage(StepIntoActionProvider.class,
140                             "VMDisconnected")));
141             }
142         }
143     }
144     
145     protected void checkEnabled (int debuggerState) {
146         Iterator i = getActions ().iterator ();
147         while (i.hasNext ())
148             setEnabled (
149                 i.next (),
150                 (debuggerState == JPDADebugger.STATE_STOPPED) &&
151                 (getDebuggerImpl ().getCurrentThread () != null)
152             );
153     }
154     
155     public void propertyChange (PropertyChangeEvent JavaDoc ev) {
156         if (ev.getPropertyName () == SmartSteppingFilter.PROP_EXCLUSION_PATTERNS) {
157             if (ev.getOldValue () != null) {
158                 // remove some patterns
159
smartLogger.finer("Exclusion patterns removed. Removing step requests.");
160                 ThreadReference tr = ((JPDAThreadImpl) getDebuggerImpl ().
161                     getCurrentThread ()).getThreadReference ();
162                 removeStepRequests (tr);
163             } else {
164                 if (smartLogger.isLoggable(Level.FINER)) {
165                     if (stepRequest == null)
166                         smartLogger.finer("Exclusion patterns has been added");
167                     else
168                         smartLogger.finer("Add exclusion patterns: "+ev.getNewValue());
169                 }
170                 addPatternsToRequest ((String JavaDoc[])
171                     ((Set<String JavaDoc>) ev.getNewValue ()).toArray (
172                         new String JavaDoc [((Set) ev.getNewValue ()).size()]
173                     )
174                 );
175             }
176         } else
177         if (ev.getPropertyName () == SourcePathProvider.PROP_SOURCE_ROOTS) {
178             smartLogger.finer("Source roots changed");
179             JPDAThreadImpl jtr = (JPDAThreadImpl) getDebuggerImpl ().
180                 getCurrentThread ();
181             if (jtr != null) {
182                 ThreadReference tr = jtr.getThreadReference ();
183                 removeStepRequests (tr);
184             }
185         } else {
186             super.propertyChange (ev);
187         }
188     }
189     
190     
191     // Executor ................................................................
192

193     /**
194      * Executes all step actions and smart stepping.
195      *
196      * Should be called from Operator only.
197      */

198     public boolean exec (Event event) {
199         if (stepWatch != null) {
200             stepWatch.done();
201             stepWatch = null;
202         }
203         JPDAThread resumeThread = null;
204         synchronized (getDebuggerImpl ().LOCK) {
205             if (stepRequest != null) {
206                 stepRequest.disable ();
207             }
208             LocatableEvent le = (LocatableEvent) event;
209
210             ThreadReference tr = le.thread ();
211
212             try {
213                 if (tr.frame(0).location().method().isSynthetic()) {
214                     //S ystem.out.println("In synthetic method -> STEP INTO again");
215
resumeThread = setStepRequest (StepRequest.STEP_INTO);
216                     return true;
217                 }
218             } catch (IncompatibleThreadStateException e) {
219                 //ErrorManager.getDefault().notify(e);
220
// This may happen while debugging a free form project
221
}
222
223             JPDAThread t = getDebuggerImpl ().getThread (tr);
224             boolean stop = getCompoundSmartSteppingListener ().stopHere
225                                (contextProvider, t, getSmartSteppingFilterImpl ());
226             if (stop) {
227                 String JavaDoc stopPosition = t.getClassName () + '.' +
228                                       t.getMethodName () + ':' +
229                                       t.getLineNumber (null);
230                 if (position.equals(stopPosition)) {
231                     // We are where we started!
232
stop = false;
233                     resumeThread = setStepRequest (StepRequest.STEP_INTO);
234                     return true;//resumeThread == null;
235
}
236             }
237             if (stop) {
238                 removeStepRequests (le.thread ());
239                 Session session = (Session) contextProvider.lookupFirst(null, Session.class);
240                 if (session != null) {
241                     DebuggerManager.getDebuggerManager().setCurrentSession(session);
242                 }
243                 getDebuggerImpl ().setStoppedState (tr);
244             } else {
245                 smartLogger.finer(" => do next step.");
246                 if (smartSteppingStepOut) {
247                     resumeThread = setStepRequest (StepRequest.STEP_OUT);
248                 } else if (stepRequest != null) {
249                     try {
250                         stepRequest.enable ();
251                     } catch (IllegalThreadStateException JavaDoc itsex) {
252                         // the thread named in the request has died.
253
getDebuggerImpl ().getOperator ().unregister(stepRequest);
254                         stepRequest = null;
255                         return true;
256                     }
257                 } else {
258                     resumeThread = setStepRequest (StepRequest.STEP_INTO);
259                 }
260             }
261
262             if (smartLogger.isLoggable(Level.FINER))
263                 if (stop) {
264                     smartLogger.finer("FINISH IN CLASS " +
265                         t.getClassName () + " ********"
266                     );
267                 }
268             return !stop;
269         }
270     }
271
272     
273     private StepActionProvider stepActionProvider;
274
275     private StepActionProvider getStepActionProvider () {
276         if (stepActionProvider == null) {
277             List l = contextProvider.lookup (null, ActionsProvider.class);
278             int i, k = l.size ();
279             for (i = 0; i < k; i++)
280                 if (l.get (i) instanceof StepActionProvider)
281                     stepActionProvider = (StepActionProvider) l.get (i);
282         }
283         return stepActionProvider;
284     }
285
286     // other methods ...........................................................
287

288     protected void removeStepRequests (ThreadReference tr) {
289         super.removeStepRequests (tr);
290         stepRequest = null;
291         smartLogger.finer("removing all patterns, all step requests.");
292     }
293     
294     private JPDAThreadImpl setStepRequest (int step) {
295         JPDAThreadImpl thread = (JPDAThreadImpl) getDebuggerImpl().getCurrentThread();
296         ThreadReference tr = thread.getThreadReference ();
297         removeStepRequests (tr);
298         VirtualMachine vm = getDebuggerImpl ().getVirtualMachine ();
299         if (vm == null) return null;
300         stepRequest = vm.eventRequestManager ().createStepRequest (
301             tr,
302             StepRequest.STEP_LINE,
303             step
304         );
305
306         getDebuggerImpl ().getOperator ().register (stepRequest, this);
307         int suspendPolicy = getDebuggerImpl().getSuspend();
308         stepRequest.setSuspendPolicy (suspendPolicy);
309         
310         if (smartLogger.isLoggable(Level.FINER)) {
311             smartLogger.finer("Set step request("+step+") and patterns: ");
312         }
313         addPatternsToRequest (
314             getSmartSteppingFilterImpl ().getExclusionPatterns ()
315         );
316         try {
317             stepRequest.enable ();
318         } catch (IllegalThreadStateException JavaDoc itsex) {
319             // the thread named in the request has died.
320
getDebuggerImpl ().getOperator ().unregister(stepRequest);
321             stepRequest = null;
322             return null;
323         }
324         if (suspendPolicy == JPDADebugger.SUSPEND_EVENT_THREAD) {
325             return thread;
326         } else {
327             return null;
328         }
329     }
330
331     private SmartSteppingFilter smartSteppingFilter;
332     
333     private SmartSteppingFilter getSmartSteppingFilterImpl () {
334         if (smartSteppingFilter == null)
335             smartSteppingFilter = (SmartSteppingFilter) contextProvider.
336                 lookupFirst (null, SmartSteppingFilter.class);
337         return smartSteppingFilter;
338     }
339
340     private CompoundSmartSteppingListener compoundSmartSteppingListener;
341     
342     private CompoundSmartSteppingListener getCompoundSmartSteppingListener () {
343         if (compoundSmartSteppingListener == null)
344             compoundSmartSteppingListener = (CompoundSmartSteppingListener)
345                 contextProvider.lookupFirst (null, CompoundSmartSteppingListener.class);
346         return compoundSmartSteppingListener;
347     }
348
349     private void addPatternsToRequest (String JavaDoc[] patterns) {
350         if (stepRequest == null) return;
351         int i, k = patterns.length;
352         for (i = 0; i < k; i++) {
353             stepRequest.addClassExclusionFilter (patterns [i]);
354             smartLogger.finer(" add pattern: "+patterns[i]);
355         }
356     }
357 }
358
Popular Tags