/******************************************************************************* * Copyright (c) 2012, 2015 Mentor Graphics 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: * Mentor Graphics - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.commands; import java.util.Map; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.debug.core.model.IDebugNewExecutableHandler; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; import org.eclipse.cdt.dsf.gdb.internal.ui.launching.NewExecutableDialog; import org.eclipse.cdt.dsf.gdb.internal.ui.launching.NewExecutableInfo; import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.gdb.service.SessionType; 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.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.IRequest; import org.eclipse.debug.core.commands.IEnabledStateRequest; import org.eclipse.jface.window.Window; import org.eclipse.ui.progress.UIJob; public class GdbDebugNewExecutableCommand extends RefreshableDebugCommand implements IDebugNewExecutableHandler { private class PromptJob extends UIJob { private DataRequestMonitor<NewExecutableInfo> fRequestMonitor; final private SessionType fSessionType; private PromptJob( SessionType sessionType, DataRequestMonitor<NewExecutableInfo> rm ) { super( Messages.GdbDebugNewExecutableCommand_New_Executable_Prompt_Job ); fSessionType = sessionType; fRequestMonitor = rm; } @Override public IStatus runInUIThread( IProgressMonitor monitor ) { final NewExecutableInfo info = new NewExecutableInfo(fSessionType); NewExecutableDialog dialog = new NewExecutableDialog(GdbUIPlugin.getShell(), info); final boolean canceled = dialog.open() == Window.CANCEL; fExecutor.execute( new DsfRunnable() { @Override public void run() { if ( canceled ) fRequestMonitor.cancel(); else fRequestMonitor.setData( info ); fRequestMonitor.done(); } } ); return Status.OK_STATUS; } } private final ILaunch fLaunch; private final DsfExecutor fExecutor; private final DsfServicesTracker fTracker; public GdbDebugNewExecutableCommand( DsfSession session, ILaunch launch ) { super(); fLaunch = launch; fExecutor = session.getExecutor(); fTracker = new DsfServicesTracker( GdbUIPlugin.getBundleContext(), session.getId() ); } public boolean canDebugNewExecutable() { Query<Boolean> canDebugQuery = new Query<Boolean>() { @Override public void execute( DataRequestMonitor<Boolean> rm ) { IProcesses procService = fTracker.getService( IProcesses.class ); ICommandControlService commandControl = fTracker.getService( ICommandControlService.class ); if ( procService == null || commandControl == null ) { rm.setData( false ); rm.done(); return; } procService.isDebugNewProcessSupported( commandControl.getContext(), rm ); } }; try { fExecutor.execute( canDebugQuery ); return canDebugQuery.get(); } catch( InterruptedException e ) { } catch( ExecutionException e ) { } catch( RejectedExecutionException e ) { // Can be thrown if the session is shutdown } return false; } public void debugNewExecutable( final RequestMonitor rm ) { IGDBBackend backend = fTracker.getService( IGDBBackend.class ); final IProcesses procService = fTracker.getService( IProcesses.class ); final ICommandControlService commandControl = fTracker.getService( ICommandControlService.class ); if ( backend == null || procService == null || commandControl == null ) { rm.setStatus( new Status( IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, "Service is not available" ) ); //$NON-NLS-1$ rm.done(); return; } PromptJob job = new PromptJob( backend.getSessionType(), new DataRequestMonitor<NewExecutableInfo>( fExecutor, rm ){ @Override protected void handleCancel() { rm.cancel(); rm.done(); }; @Override protected void handleSuccess() { try { Map<String, Object> attributes = getLaunchConfiguration().getAttributes(); attributes.putAll(getData().getAttributes()); procService.debugNewProcess( commandControl.getContext(), getData().getHostPath(), attributes, new ImmediateDataRequestMonitor<IDMContext>( rm ) ); } catch( CoreException e ) { rm.setStatus( e.getStatus() ); rm.done(); } }; } ); job.schedule(); } @Override protected void doExecute( Object[] targets, IProgressMonitor monitor, IRequest request ) throws CoreException { Query<Boolean> query = new Query<Boolean>() { @Override protected void execute( DataRequestMonitor<Boolean> rm ) { debugNewExecutable( rm ); } }; try { fExecutor.execute( query ); query.get(); } catch( InterruptedException e ) { } catch( ExecutionException e ) { // There was an error. Propagate it to the user String errorMessage; if (e.getCause() != null) { errorMessage = e.getCause().getMessage(); } else { errorMessage = e.getMessage(); } request.setStatus( new Status( IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, errorMessage ) ); } catch( CancellationException e ) { // Nothing to do, just ignore the command since the user // cancelled it. } catch( RejectedExecutionException e ) { // Can be thrown if the session is shutdown } finally { updateEnablement(); } } @Override protected boolean isExecutable( Object[] targets, IProgressMonitor monitor, IEnabledStateRequest request ) throws CoreException { return canDebugNewExecutable(); } @Override protected Object getTarget( Object element ) { if ( element instanceof GdbLaunch || element instanceof IDMVMContext ) return element; return null; } public void dispose() { fTracker.dispose(); } private ILaunchConfiguration getLaunchConfiguration() { return fLaunch.getLaunchConfiguration(); } }