/******************************************************************************* * Copyright (c) 2006, 2009 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.examples.dsf.pda.ui.actions; import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.cdt.examples.dsf.pda.service.PDACommandControl; import org.eclipse.cdt.examples.dsf.pda.service.PDAVirtualMachineDMContext; import org.eclipse.cdt.examples.dsf.pda.ui.PDAUIPlugin; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.commands.IDebugCommandRequest; import org.eclipse.debug.core.commands.IEnabledStateRequest; import org.eclipse.debug.core.commands.ITerminateHandler; /** * The terminate command is specialized for the PDA debugger. Currently there * is no standard interface for terminating a debug session in DSF, because the * details of initiating and shutting down a debug session vary greatly in * different debuggers. */ public class PDATerminateCommand implements ITerminateHandler { // The executor and the services tracker, both initialized from a DSF session. private final DsfSession fSession; private final DsfServicesTracker fTracker; public PDATerminateCommand(DsfSession session) { fSession = session; fTracker = new DsfServicesTracker(PDAUIPlugin.getBundleContext(), session.getId()); } public void dispose() { // DSF services tracker always has to be disposed, because the OSGi services // use reference counting. fTracker.dispose(); } // Run control may not be available after a connection is terminated and shut down. public void canExecute(final IEnabledStateRequest request) { // Terminate can only operate on a single element. if (request.getElements().length != 1 || !(request.getElements()[0] instanceof IDMVMContext) ) { request.setEnabled(false); request.done(); return; } // Find the PDA program context in the selected element. If one is not found, // the action should be disabled. IDMVMContext vmc = (IDMVMContext)request.getElements()[0]; final PDAVirtualMachineDMContext pdaProgramCtx = DMContexts.getAncestorOfType(vmc.getDMContext(), PDAVirtualMachineDMContext.class); if (pdaProgramCtx == null) { request.setEnabled(false); request.done(); return; } try { fSession.getExecutor().execute( new DsfRunnable() { public void run() { // Get the processes service and the exec context. PDACommandControl commandControl = fTracker.getService(PDACommandControl.class); if (commandControl == null || pdaProgramCtx == null) { // Context or service already invalid. request.setEnabled(false); request.done(); } else { // Check whether the control is terminated. request.setEnabled(!commandControl.isTerminated()); request.done(); } } }); } catch (RejectedExecutionException e) { // The DSF session for this context is no longer active. It's possible to check // for this condition before calling fSession.getExecutor().execute(), but // since this method is executing in a different thread than the session control, // there would still be a chance for a race condition leading to this exception. request.setEnabled(false); request.done(); } } public boolean execute(final IDebugCommandRequest request) { // Skip the checks and assume that this method is called only if the action // was enabled. try { fSession.getExecutor().submit(new DsfRunnable() { public void run() { // If the command control service is available, attempt to terminate the program. PDACommandControl commandControl = fTracker.getService(PDACommandControl.class); if (commandControl != null) { commandControl.terminate( new RequestMonitor(ImmediateExecutor.getInstance(), null) { @Override protected void handleCompleted() { request.setStatus(getStatus()); request.done(); } }); } } }); } catch (RejectedExecutionException e) { request.setStatus(new Status(IStatus.ERROR, PDAUIPlugin.PLUGIN_ID, "PDA debug session is shut down.")); request.done(); } return false; } }