blob: 056bb7aa49c96da975139eee8d7c8e88ae19b21e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.debugger.jpda.actions;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.InvalidRequestStateException;
import com.sun.jdi.request.StepRequest;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.netbeans.api.debugger.ActionsManager;
import org.netbeans.api.debugger.jpda.JPDADebugger;
import org.netbeans.api.debugger.jpda.JPDAThread;
import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl;
//import org.netbeans.modules.debugger.jpda.JPDAStepImpl.SingleThreadedStepWatch;
import org.netbeans.modules.debugger.jpda.jdi.InternalExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.InvalidRequestStateExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.VMDisconnectedExceptionWrapper;
import org.netbeans.modules.debugger.jpda.jdi.VirtualMachineWrapper;
import org.netbeans.modules.debugger.jpda.jdi.request.EventRequestManagerWrapper;
import org.netbeans.modules.debugger.jpda.jdi.request.StepRequestWrapper;
import org.netbeans.modules.debugger.jpda.models.JPDAThreadImpl;
import org.netbeans.spi.debugger.ActionsProviderSupport;
import org.openide.util.WeakSet;
/**
* Representation of a debugging session.
*
* @author Jan Jancura
* @author Marian Petras
*/
public abstract class JPDADebuggerActionProvider extends ActionsProviderSupport
implements PropertyChangeListener {
protected JPDADebuggerImpl debugger;
private static final Set<JPDADebuggerActionProvider> providersToDisableOnLazyActions = new WeakSet<JPDADebuggerActionProvider>();
private volatile boolean disabled;
protected JPDADebuggerActionProvider (JPDADebuggerImpl debugger) {
this.debugger = debugger;
debugger.addPropertyChangeListener (JPDADebugger.PROP_STATE, this);
}
@Override
public void propertyChange (PropertyChangeEvent evt) {
if ("methodInvoke".equals(evt.getPropagationId())) {
return ; // Ignore events associated with method invocations
}
checkEnabled (debugger.getState ());
}
protected abstract void checkEnabled (int debuggerState);
@Override
public boolean isEnabled (Object action) {
if (!disabled) {
checkEnabled (debugger.getState ());
}
return super.isEnabled (action);
}
protected JPDADebuggerImpl getDebuggerImpl () {
return debugger;
}
protected void removeStepRequests (ThreadReference tr) {
removeStepRequests(getDebuggerImpl(), tr);
}
static void removeStepRequests(JPDADebuggerImpl debugger, ThreadReference tr) {
//S ystem.out.println ("removeStepRequests");
try {
VirtualMachine vm = debugger.getVirtualMachine ();
if (vm == null) return;
EventRequestManager erm = VirtualMachineWrapper.eventRequestManager (vm);
List<StepRequest> l = EventRequestManagerWrapper.stepRequests (erm);
Iterator<StepRequest> it = l.iterator ();
while (it.hasNext ()) {
StepRequest stepRequest = it.next ();
if (StepRequestWrapper.thread(stepRequest).equals (tr)) {
try {
//S ystem.out.println(" remove request " + stepRequest);
EventRequestManagerWrapper.deleteEventRequest(erm, stepRequest);
} catch (InvalidRequestStateExceptionWrapper ex) {}
//SingleThreadedStepWatch.stepRequestDeleted(stepRequest);
debugger.getOperator().unregister(stepRequest);
break;
}
//S ystem.out.println(" do not remove " + stepRequest + " : " + stepRequest.thread ());
}
} catch (VMDisconnectedExceptionWrapper e) {
} catch (InternalExceptionWrapper e) {
} catch (IllegalThreadStateException e) {
} catch (InvalidRequestStateException e) {
}
}
/**
* Mark the provided action provider to be disabled when a lazy action is to be performed.
*/
final void setProviderToDisableOnLazyAction(JPDADebuggerActionProvider provider) {
synchronized (JPDADebuggerActionProvider.class) {
providersToDisableOnLazyActions.add(provider);
}
}
/**
* Do the action lazily in a RequestProcessor.
* @param run The action to perform.
*/
protected final void doLazyAction(final Object action, final Runnable run) {
//System.err.println("doLazyAction() in "+this);
//Logger.getLogger(JPDADebuggerActionProvider.class.getName()).fine("doLazyAction() in "+this);
//final long start = System.nanoTime();
final ActionsSynchronizer as = ActionsSynchronizer.get(debugger);
as.actionScheduled(action);
final JPDAThreadImpl threadWithActionsPending;
JPDAThread ct = debugger.getCurrentThread();
if (ct instanceof JPDAThreadImpl && action != ActionsManager.ACTION_PAUSE) {
threadWithActionsPending = (JPDAThreadImpl) ct;
threadWithActionsPending.setPendingAction(action);
} else {
threadWithActionsPending = null;
}
final Set<JPDADebuggerActionProvider> disabledActions;
synchronized (JPDADebuggerActionProvider.class) {
disabledActions = new HashSet<JPDADebuggerActionProvider>(providersToDisableOnLazyActions);
}
for (Iterator<JPDADebuggerActionProvider> it = disabledActions.iterator(); it.hasNext(); ) {
JPDADebuggerActionProvider ap = it.next();
Set actions = ap.getActions();
ap.disabled = true;
for (Iterator ait = actions.iterator(); ait.hasNext(); ) {
Object a = ait.next();
ap.setEnabled (a, false);
//System.out.println(ap+".setEnabled("+action+", "+false+")");
}
}
debugger.getRequestProcessor().post(new Runnable() {
@Override
public void run() {
try {
//long end = System.nanoTime();
//System.err.println(" run in RP after "+(end - start)+" ns ("+((end - start)/1000000)+" ms) in "+this);
//Logger.getLogger(JPDADebuggerActionProvider.class.getName()).fine(" run in RP after "+(end - start)+" ns ("+((end - start)/1000000)+" ms) in "+this);
as.actionStarts(action);
run.run();
if (threadWithActionsPending != null) {
threadWithActionsPending.setPendingAction(null);
}
for (Iterator<JPDADebuggerActionProvider> it = disabledActions.iterator(); it.hasNext(); ) {
JPDADebuggerActionProvider ap = it.next();
Set actions = ap.getActions();
ap.disabled = false;
ap.checkEnabled (debugger.getState ());
}
} catch (com.sun.jdi.VMDisconnectedException e) {
// Causes kill action when something is being evaluated
} finally {
as.actionEnds(action);
}
}
});
}
}