1 19 package org.netbeans.modules.debugger.jpda.actions; 20 21 import com.sun.jdi.Location; 22 import com.sun.jdi.ThreadReference; 23 import com.sun.jdi.VMDisconnectedException; 24 import com.sun.jdi.IncompatibleThreadStateException; 25 import com.sun.jdi.VirtualMachine; 26 import com.sun.jdi.event.Event; 27 import com.sun.jdi.event.LocatableEvent; 28 import com.sun.jdi.request.StepRequest; 29 import java.util.Arrays ; 30 import java.util.HashSet ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Set ; 34 import java.util.logging.Logger ; 35 import org.netbeans.api.debugger.ActionsManager; 36 import org.netbeans.api.debugger.DebuggerManager; 37 import org.netbeans.api.debugger.Session; 38 import org.netbeans.api.debugger.jpda.JPDABreakpoint; 39 import org.netbeans.api.debugger.jpda.MethodBreakpoint; 40 import org.netbeans.api.debugger.jpda.Variable; 41 import org.netbeans.modules.debugger.jpda.ExpressionPool; 42 import org.netbeans.modules.debugger.jpda.JPDAStepImpl.MethodExitBreakpointListener; 43 import org.netbeans.modules.debugger.jpda.JPDAStepImpl.SingleThreadedStepWatch; 44 import org.netbeans.modules.debugger.jpda.SourcePath; 45 import org.netbeans.modules.debugger.jpda.breakpoints.MethodBreakpointImpl; 46 import org.netbeans.spi.debugger.ContextProvider; 47 import org.netbeans.api.debugger.jpda.JPDADebugger; 48 import org.netbeans.api.debugger.jpda.JPDAThread; 49 import org.netbeans.api.debugger.jpda.SmartSteppingFilter; 50 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl; 51 import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl; 52 import org.netbeans.modules.debugger.jpda.util.Executor; 53 import org.netbeans.spi.debugger.ActionsProvider; 54 import org.netbeans.spi.debugger.jpda.EditorContext.Operation; 55 import org.openide.ErrorManager; 56 import org.openide.util.NbBundle; 57 58 59 66 public class StepActionProvider extends JPDADebuggerActionProvider 67 implements Executor { 68 69 private StepRequest stepRequest; 70 private ContextProvider lookupProvider; 71 private MethodExitBreakpointListener lastMethodExitBreakpointListener; 72 private SingleThreadedStepWatch stepWatch; 73 74 75 private static boolean ssverbose = 76 System.getProperty ("netbeans.debugger.smartstepping") != null; 77 private static Logger logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.jdievents"); 79 80 private static int getJDIAction (Object action) { 81 if (action == ActionsManager.ACTION_STEP_OUT) 82 return StepRequest.STEP_OUT; 83 if (action == ActionsManager.ACTION_STEP_OVER) 84 return StepRequest.STEP_OVER; 85 throw new IllegalArgumentException (); 86 } 87 88 89 public StepActionProvider (ContextProvider lookupProvider) { 90 super ( 91 (JPDADebuggerImpl) lookupProvider.lookupFirst 92 (null, JPDADebugger.class) 93 ); 94 this.lookupProvider = lookupProvider; 95 setProviderToDisableOnLazyAction(this); 96 } 97 98 99 101 public Set getActions () { 102 return new HashSet <Object >(Arrays.asList (new Object [] { 103 ActionsManager.ACTION_STEP_OUT, 104 ActionsManager.ACTION_STEP_OVER 105 })); 106 } 107 108 public void doAction (final Object action) { 109 runAction(action); 110 } 111 112 public void postAction(final Object action, 113 final Runnable actionPerformedNotifier) { 114 doLazyAction(new Runnable () { 115 public void run() { 116 try { 117 runAction(action); 118 } finally { 119 actionPerformedNotifier.run(); 120 } 121 } 122 }); 123 } 124 125 public void runAction(final Object action) { 126 synchronized (getDebuggerImpl ().LOCK) { 127 try { 129 JPDAThreadImpl resumeThread = (JPDAThreadImpl) getDebuggerImpl().getCurrentThread(); 132 ThreadReference tr = resumeThread.getThreadReference (); 133 removeStepRequests (tr); 134 135 VirtualMachine vm = getDebuggerImpl ().getVirtualMachine (); 137 if (vm == null) return ; stepRequest = vm.eventRequestManager ().createStepRequest ( 139 tr, 140 StepRequest.STEP_LINE, 141 getJDIAction (action) 142 ); 143 stepRequest.addCountFilter (1); 144 getDebuggerImpl ().getOperator ().register (stepRequest, StepActionProvider.this); 145 int suspendPolicy = getDebuggerImpl().getSuspend(); 146 stepRequest.setSuspendPolicy(suspendPolicy); 147 try { 148 stepRequest.enable (); 149 } catch (IllegalThreadStateException itsex) { 150 logger.warning(itsex.getLocalizedMessage()+"\nThread: "+tr.name()+", suspended = "+tr.isSuspended()+", suspend count = "+tr.suspendCount()+", status = "+tr.status()); 155 getDebuggerImpl ().getOperator ().unregister(stepRequest); 156 return ; 157 } 158 logger.fine("JDI Request (action "+action+"): " + stepRequest); 159 if (action == ActionsManager.ACTION_STEP_OUT) { 160 addMethodExitBP(tr); 161 } 162 163 if (suspendPolicy == JPDADebugger.SUSPEND_EVENT_THREAD) { 165 stepWatch = new SingleThreadedStepWatch(getDebuggerImpl(), stepRequest); 166 getDebuggerImpl().resumeCurrentThread(); 167 } else { 169 getDebuggerImpl ().resume (); 170 } 171 } catch (VMDisconnectedException e) { 172 ErrorManager.getDefault().notify(ErrorManager.USER, 173 ErrorManager.getDefault().annotate(e, 174 NbBundle.getMessage(StepActionProvider.class, 175 "VMDisconnected"))); 176 } 177 } 179 } 180 181 private void addMethodExitBP(ThreadReference tr) { 182 if (!MethodBreakpointImpl.canGetMethodReturnValues(tr.virtualMachine())) { 183 return ; 184 } 185 Location loc; 186 try { 187 loc = tr.frame(0).location(); 188 } catch (IncompatibleThreadStateException ex) { 189 logger.fine("Incompatible Thread State: "+ex.getLocalizedMessage()); 190 return ; 191 } 192 String classType = loc.declaringType().name(); 193 String methodName = loc.method().name(); 194 MethodBreakpoint mb = MethodBreakpoint.create(classType, methodName); 195 mb.setBreakpointType(MethodBreakpoint.TYPE_METHOD_EXIT); 197 mb.setHidden(true); 198 mb.setSuspend(JPDABreakpoint.SUSPEND_NONE); 199 lastMethodExitBreakpointListener = new MethodExitBreakpointListener(mb); 200 mb.addJPDABreakpointListener(lastMethodExitBreakpointListener); 201 DebuggerManager.getDebuggerManager().addBreakpoint(mb); 202 } 203 204 protected void checkEnabled (int debuggerState) { 205 Iterator i = getActions ().iterator (); 206 while (i.hasNext ()) 207 setEnabled ( 208 i.next (), 209 (debuggerState == getDebuggerImpl ().STATE_STOPPED) && 210 (getDebuggerImpl ().getCurrentThread () != null) 211 ); 212 } 213 214 216 221 public boolean exec (Event ev) { 222 if (stepWatch != null) { 225 stepWatch.done(); 226 stepWatch = null; 227 } 228 LocatableEvent event = (LocatableEvent) ev; 229 String className = event.location ().declaringType ().name (); 230 ThreadReference tr = event.thread (); 231 if (stepRequest.depth() == StepRequest.STEP_OUT) { 232 setLastOperation(tr); 233 } 234 synchronized (getDebuggerImpl ().LOCK) { 235 237 240 241 JPDAThreadImpl ct = (JPDAThreadImpl) getDebuggerImpl (). 243 getCurrentThread (); 244 if (ct != null && 245 !ct.getThreadReference ().equals (tr) 246 ) { 247 return true; } 250 251 int suspendPolicy = getDebuggerImpl().getSuspend(); 252 253 255 try { 257 if (ct.getThreadReference().frame(0).location().method().isSynthetic()) { 258 260 removeStepRequests (ct.getThreadReference ()); 261 int step = ((StepRequest)ev.request()).depth(); 262 VirtualMachine vm = getDebuggerImpl ().getVirtualMachine (); 263 if (vm == null) { 264 return false; } 266 stepRequest = vm.eventRequestManager ().createStepRequest ( 267 ct.getThreadReference (), 268 StepRequest.STEP_LINE, 269 step 270 ); 271 stepRequest.addCountFilter(1); 272 getDebuggerImpl ().getOperator ().register (stepRequest, this); 273 stepRequest.setSuspendPolicy (suspendPolicy); 274 try { 275 stepRequest.enable (); 276 } catch (IllegalThreadStateException itsex) { 277 getDebuggerImpl ().getOperator ().unregister(stepRequest); 279 stepRequest = null; 280 } 281 return true; 282 } 283 } catch (IncompatibleThreadStateException e) { 284 ErrorManager.getDefault().notify(e); 285 } 286 287 boolean fsh = getSmartSteppingFilterImpl ().stopHere (className); 289 if (ssverbose) 290 System.out.println("SS SmartSteppingFilter.stopHere (" + 291 className + ") ? " + fsh 292 ); 293 if (fsh) { 294 JPDAThread t = getDebuggerImpl ().getThread (tr); 295 if (getCompoundSmartSteppingListener ().stopHere 296 (lookupProvider, t, getSmartSteppingFilterImpl ()) 297 ) { 298 Session session = (Session) lookupProvider.lookupFirst(null, Session.class); 300 if (session != null) { 301 DebuggerManager.getDebuggerManager().setCurrentSession(session); 302 } 303 getDebuggerImpl ().setStoppedState (tr); 304 return false; } 307 } 308 309 if (ssverbose) 311 System.out.println("\nSS: SMART STEPPING START! ********** "); 312 boolean stepInto = ((StepRequest) ev.request ()).depth () == 313 StepRequest.STEP_INTO; 314 getStepIntoActionProvider ().doAction 315 (ActionsManager.ACTION_STEP_INTO); 316 return true; } 319 } 320 321 private void setLastOperation(ThreadReference tr) { 322 Location loc; 323 try { 324 loc = tr.frame(0).location(); 325 } catch (IncompatibleThreadStateException itsex) { 326 logger.fine("Incompatible Thread State: "+itsex.getLocalizedMessage()); 327 return ; 328 } 329 Session currentSession = DebuggerManager.getDebuggerManager().getCurrentSession(); 330 String language = currentSession == null ? null : currentSession.getCurrentLanguage(); 331 SourcePath sourcePath = getDebuggerImpl().getEngineContext(); 332 String url = sourcePath.getURL(loc, language); 333 ExpressionPool exprPool = getDebuggerImpl().getExpressionPool(); 334 ExpressionPool.Expression expr = exprPool.getExpressionAt(loc, url); 335 if (expr == null) { 336 return ; 337 } 338 Operation[] ops = expr.getOperations(); 339 int codeIndex = (int) loc.codeIndex(); 341 byte[] bytecodes = loc.method().bytecodes(); 342 if (codeIndex >= 5 && (bytecodes[codeIndex - 5] & 0xFF) == 185) { codeIndex -= 5; 344 } else { 345 codeIndex -= 3; } 347 int opIndex = expr.findNextOperationIndex(codeIndex - 1); 348 Operation lastOperation; 349 if (opIndex >= 0 && ops[opIndex].getBytecodeIndex() == codeIndex) { 350 lastOperation = ops[opIndex]; 351 } else { 352 return ; 353 } 354 if (lastMethodExitBreakpointListener != null) { 355 Variable returnValue = lastMethodExitBreakpointListener.getReturnValue(); 356 lastMethodExitBreakpointListener.destroy(); 357 lastMethodExitBreakpointListener = null; 358 lastOperation.setReturnValue(returnValue); 359 } 360 JPDAThreadImpl jtr = (JPDAThreadImpl) getDebuggerImpl().getThread(tr); 361 jtr.addLastOperation(lastOperation); 362 jtr.setCurrentOperation(lastOperation); 363 } 364 365 private StepIntoActionProvider stepIntoActionProvider; 366 367 private StepIntoActionProvider getStepIntoActionProvider () { 368 if (stepIntoActionProvider == null) { 369 List l = lookupProvider.lookup (null, ActionsProvider.class); 370 int i, k = l.size (); 371 for (i = 0; i < k; i++) 372 if (l.get (i) instanceof StepIntoActionProvider) 373 stepIntoActionProvider = (StepIntoActionProvider) l.get (i); 374 } 375 return stepIntoActionProvider; 376 } 377 378 private SmartSteppingFilterImpl smartSteppingFilterImpl; 379 380 private SmartSteppingFilterImpl getSmartSteppingFilterImpl () { 381 if (smartSteppingFilterImpl == null) 382 smartSteppingFilterImpl = (SmartSteppingFilterImpl) lookupProvider. 383 lookupFirst (null, SmartSteppingFilter.class); 384 return smartSteppingFilterImpl; 385 } 386 387 private CompoundSmartSteppingListener compoundSmartSteppingListener; 388 389 private CompoundSmartSteppingListener getCompoundSmartSteppingListener () { 390 if (compoundSmartSteppingListener == null) 391 compoundSmartSteppingListener = (CompoundSmartSteppingListener) lookupProvider. 392 lookupFirst (null, CompoundSmartSteppingListener.class); 393 return compoundSmartSteppingListener; 394 } 395 } 396 | Popular Tags |