/*******************************************************************************
* Copyright (c) 2005, 2015 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Bjorn Freeman-Benson - initial API and implementation
* Wind River Systems - adopted to use with DSF
*******************************************************************************/
package org.eclipse.cdt.examples.dsf.pda.launch;
import java.util.concurrent.ExecutionException;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.examples.dsf.pda.PDAPlugin;
import org.eclipse.cdt.examples.dsf.pda.service.PDABackend;
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.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IPersistableSourceLocator;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
/**
* Launches PDA program on a PDA interpretter written in Perl
*/
public class PDALaunchDelegate extends LaunchConfigurationDelegate {
@Override
public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
// Need to configure the source locator before creating the launch
// because once the launch is created and added to launch manager,
// the adapters will be created for the whole session, including
// the source lookup adapter.
ISourceLocator locator = getSourceLocator(configuration);
return new PDALaunch(configuration, mode, locator);
}
@Override
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
// PDA programs do not require building.
return false;
}
/**
* Returns a source locator created based on the attributes in the launch configuration.
*/
private ISourceLocator getSourceLocator(ILaunchConfiguration configuration) throws CoreException {
String type = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null);
if (type == null) {
type = configuration.getType().getSourceLocatorId();
}
if (type != null) {
IPersistableSourceLocator locator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(type);
String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
if (memento == null) {
locator.initializeDefaults(configuration);
} else {
if(locator instanceof IPersistableSourceLocator2)
((IPersistableSourceLocator2)locator).initializeFromMemento(memento, configuration);
else
locator.initializeFromMemento(memento);
}
return locator;
}
return null;
}
@Override
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
String program = configuration.getAttribute(PDAPlugin.ATTR_PDA_PROGRAM, (String)null);
if (program == null) {
abort("Perl program unspecified.", null);
}
PDALaunch pdaLaunch = (PDALaunch)launch;
initServices(pdaLaunch, program);
createProcess(pdaLaunch);
}
/**
* Calls the launch to initialize DSF services for this launch.
*/
private void initServices(final PDALaunch pdaLaunch, final String program)
throws CoreException
{
// Synchronization object to use when waiting for the services initialization.
Query<Object> initQuery = new Query<Object>() {
@Override
protected void execute(DataRequestMonitor<Object> rm) {
pdaLaunch.initializeServices(program, rm);
}
};
// Submit the query to the executor.
pdaLaunch.getSession().getExecutor().execute(initQuery);
try {
// Block waiting for query results.
initQuery.get();
} catch (InterruptedException e1) {
throw new DebugException(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
} catch (ExecutionException e1) {
throw new DebugException(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in launch sequence", e1.getCause())); //$NON-NLS-1$
}
}
private void createProcess(final PDALaunch pdaLaunch) throws CoreException {
// Synchronization object to use when waiting for the services initialization.
Query<Object[]> initQuery = new Query<Object[]>() {
@Override
protected void execute(DataRequestMonitor<Object[]> rm) {
DsfServicesTracker tracker = new DsfServicesTracker(PDAPlugin.getBundleContext(), pdaLaunch.getSession().getId());
PDABackend backend = tracker.getService(PDABackend.class);
if (backend == null) {
PDAPlugin.failRequest(rm, IDsfStatusConstants.INVALID_STATE, "PDA Backend service not available");
return;
}
Object[] retVal = new Object[] { backend.getProcess(), backend.getProcessName() };
rm.setData(retVal);
rm.done();
}
};
// Submit the query to the executor.
pdaLaunch.getSession().getExecutor().execute(initQuery);
try {
// Block waiting for query results.
Object[] processData = initQuery.get();
DebugPlugin.newProcess(pdaLaunch, (Process)processData[0], (String)processData[1]);
} catch (InterruptedException e1) {
throw new DebugException(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
} catch (ExecutionException e1) {
throw new DebugException(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in launch sequence", e1.getCause())); //$NON-NLS-1$
}
}
/**
* Throws an exception with a new status containing the given
* message and optional exception.
*
* @param message error message
* @param e underlying exception
* @throws CoreException
*/
private void abort(String message, Throwable e) throws CoreException {
throw new CoreException(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, 0, message, e));
}
}