1 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 ; 29 import java.beans.PropertyChangeListener ; 30 import java.util.*; 31 import java.util.logging.Level ; 32 import java.util.logging.Logger ; 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 58 public class StepIntoActionProvider extends JPDADebuggerActionProvider 59 implements Executor, PropertyChangeListener { 60 61 public static final String SS_STEP_OUT = "SS_ACTION_STEPOUT"; 62 63 private static final Logger smartLogger = Logger.getLogger("org.netbeans.modules.debugger.jpda.smartstepping"); private static final Logger logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.jdievents"); 66 private StepRequest stepRequest; 67 private String 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 91 public Set getActions () { 92 return new HashSet<Object >(Arrays.asList (new Object [] { 93 ActionsManager.ACTION_STEP_INTO, 94 })); 95 } 96 97 public void doAction (Object action) { 98 runAction(); 99 } 100 101 public void postAction(Object action, final Runnable actionPerformedNotifier) { 102 doLazyAction(new Runnable () { 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 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 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 ev) { 156 if (ev.getPropertyName () == SmartSteppingFilter.PROP_EXCLUSION_PATTERNS) { 157 if (ev.getOldValue () != null) { 158 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 []) 171 ((Set<String >) ev.getNewValue ()).toArray ( 172 new String [((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 193 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 resumeThread = setStepRequest (StepRequest.STEP_INTO); 216 return true; 217 } 218 } catch (IncompatibleThreadStateException e) { 219 } 222 223 JPDAThread t = getDebuggerImpl ().getThread (tr); 224 boolean stop = getCompoundSmartSteppingListener ().stopHere 225 (contextProvider, t, getSmartSteppingFilterImpl ()); 226 if (stop) { 227 String stopPosition = t.getClassName () + '.' + 228 t.getMethodName () + ':' + 229 t.getLineNumber (null); 230 if (position.equals(stopPosition)) { 231 stop = false; 233 resumeThread = setStepRequest (StepRequest.STEP_INTO); 234 return true; } 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 itsex) { 252 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 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 itsex) { 319 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 [] 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 |