blob: 19d36b8032c0747ada5574741080f97aed1b0d4b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2015 Mentor Graphics and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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<>() {
@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<>() {
@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();
}
}