blob: 881f8f83315d961196fd963bc06de2dbceac56a0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 The Regents of the University of California.
* This material was produced under U.S. Government contract W-7405-ENG-36
* for Los Alamos National Laboratory, which is operated by the University
* of California for the U.S. Department of Energy. The U.S. Government has
* rights to use, reproduce, and distribute this software. NEITHER THE
* GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
* ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified
* to produce derivative works, such modified software should be clearly marked,
* so as not to confuse it with the version available from LANL.
*
* Additionally, 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
*
* LA-CC 04-115
*******************************************************************************/
package org.eclipse.ptp.launch;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IPersistableSourceLocator;
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
import org.eclipse.ptp.core.IPTPLaunchConfigurationConstants;
import org.eclipse.ptp.core.PTPCorePlugin;
import org.eclipse.ptp.core.elements.IPQueue;
import org.eclipse.ptp.core.elements.IPResourceManager;
import org.eclipse.ptp.core.events.IJobChangedEvent;
import org.eclipse.ptp.core.listeners.IJobListener;
import org.eclipse.ptp.debug.core.IPDebugConfiguration;
import org.eclipse.ptp.debug.core.IPDebugger;
import org.eclipse.ptp.debug.core.PTPDebugCorePlugin;
import org.eclipse.ptp.debug.core.launch.IPLaunch;
import org.eclipse.ptp.debug.core.launch.PLaunch;
import org.eclipse.ptp.debug.ui.PTPDebugUIPlugin;
import org.eclipse.ptp.launch.messages.Messages;
import org.eclipse.ptp.launch.rulesengine.ILaunchProcessCallback;
import org.eclipse.ptp.launch.rulesengine.IRuleAction;
import org.eclipse.ptp.launch.rulesengine.ISynchronizationRule;
import org.eclipse.ptp.launch.rulesengine.RuleActionFactory;
import org.eclipse.ptp.launch.rulesengine.RuleFactory;
import org.eclipse.ptp.remote.core.IRemoteConnection;
import org.eclipse.ptp.remote.core.IRemoteConnectionManager;
import org.eclipse.ptp.remote.core.IRemoteFileManager;
import org.eclipse.ptp.remote.core.IRemoteServices;
import org.eclipse.ptp.remote.core.PTPRemoteCorePlugin;
import org.eclipse.ptp.rmsystem.IJobStatus;
import org.eclipse.ptp.rmsystem.IResourceManager;
import org.eclipse.ptp.rmsystem.IResourceManagerComponentConfiguration;
import org.eclipse.ptp.utils.core.ArgumentParser;
/**
*
*/
public abstract class AbstractParallelLaunchConfigurationDelegate extends LaunchConfigurationDelegate implements
ILaunchProcessCallback {
private final class JobListener implements IJobListener {
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.core.listeners.IJobListener#handleEvent(org.eclipse .ptp.core.events.IJobChangeEvent)
*/
public void handleEvent(IJobChangedEvent e) {
JobSubmission jobSub;
synchronized (jobSubmissions) {
jobSub = jobSubmissions.get(e.getJobId());
}
if (jobSub != null) {
jobSub.statusChanged();
}
}
}
/**
* Wait for job to begin running, then perform post launch operations. The job is guaranteed not to be in the UNDERTERMINED
* state.
*
* <pre>
* Job state transition is:
*
* SUBMITTED ----> RUNNING ----> COMPLETED
* ^ |
* |- SUSPENDED <-|
* </pre>
*
* We must call completion method when job state is RUNNING, however it is possible that the job may get to COMPLETED or
* SUSPENDED before we are started. If either of these states is reached, assume that RUNNING has also been reached.
*/
private class JobSubmission extends Job {
private final IPLaunch fLaunch;
private final IPDebugger fDebugger;
private final ReentrantLock fSubLock = new ReentrantLock();
private final Condition fSubCondition = fSubLock.newCondition();
public JobSubmission(IPLaunch launch, IPDebugger debugger) {
super(launch.getJobId());
fLaunch = launch;
fDebugger = debugger;
setSystem(true);
}
public void statusChanged() {
fSubLock.lock();
try {
fSubCondition.signalAll();
} finally {
fSubLock.unlock();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime. IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
SubMonitor subMon = SubMonitor.convert(monitor, 100);
try {
IResourceManager rm = fLaunch.getResourceManager();
String jobId = fLaunch.getJobId();
IJobStatus status;
fSubLock.lock();
try {
while ((status = rm.getJobStatus(jobId, subMon.newChild(50))).getState().equals(IJobStatus.SUBMITTED)
&& !subMon.isCanceled()) {
try {
fSubCondition.await(100, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// Expect to be interrupted if monitor is canceled
}
}
} finally {
fSubLock.unlock();
}
/*
* If job state is COMPLETED, only complete the launch if the job state detail is not FAILED or CANCELLED. This
* prevents the debugger staring if the job fails or is cancelled.
*/
if (!subMon.isCanceled()
&& (!status.getState().equals(IJobStatus.COMPLETED) || (!status.getStateDetail().equals(IJobStatus.FAILED) && !status
.getStateDetail().equals(IJobStatus.CANCELED)))) {
doCompleteJobLaunch(fLaunch, fDebugger);
fSubLock.lock();
try {
while (!rm.getJobStatus(jobId, subMon.newChild(50)).getState().equals(IJobStatus.COMPLETED)
&& !subMon.isCanceled()) {
try {
fSubCondition.await(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// Expect to be interrupted if monitor is
// canceled
}
}
} finally {
fSubLock.unlock();
}
if (!subMon.isCanceled()) {
/*
* When the job terminates, do any post launch data synchronization.
*/
// If needed, copy data back.
try {
// Get the list of paths to be copied back.
doPostLaunchSynchronization(fLaunch.getLaunchConfiguration());
} catch (CoreException e) {
PTPLaunchPlugin.log(e);
}
}
}
/*
* Clean up any launch activities.
*/
doCleanupLaunch(fLaunch);
/*
* Remove job submission
*/
synchronized (jobSubmissions) {
jobSubmissions.remove(jobId);
if (jobSubmissions.size() == 0) {
rm.removeJobListener(fJobListener);
}
}
return Status.OK_STATUS;
} finally {
if (monitor != null) {
monitor.done();
}
}
}
}
/**
* Get the program arguments specified in the Arguments tab
*
* @param configuration
* @return
* @throws CoreException
*/
protected static String getArguments(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_ARGUMENTS, (String) null);
}
/**
* Get the debugger executable path
*
* @param configuration
* @return
* @throws CoreException
*/
protected static String getDebuggerExePath(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_DEBUGGER_EXECUTABLE_PATH, (String) null);
}
/**
* Get the ID of the debugger for this launch
*
* @param configuration
* @return
* @throws CoreException
*/
protected static String getDebuggerID(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_DEBUGGER_ID, (String) null);
}
/**
* Get the debugger "stop in main" flag
*
* @param configuration
* @return "stop in main" flag
* @throws CoreException
*/
protected static boolean getDebuggerStopInMainFlag(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, false);
}
/**
* Get the working directory for this debug session
*
* @param configuration
* @return
* @throws CoreException
*/
protected static String getDebuggerWorkDirectory(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_DEBUGGER_WORKING_DIR, (String) null);
}
/**
* @param configuration
* @return
* @throws CoreException
*/
protected static String[] getEnvironmentToAppend(ILaunchConfiguration configuration) throws CoreException {
Map<?, ?> defaultEnv = null;
Map<?, ?> configEnv = configuration.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, defaultEnv);
if (configEnv == null) {
return null;
}
if (!configuration.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true)) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Parallel_launcher_does_not_support));
}
List<String> strings = new ArrayList<String>(configEnv.size());
Iterator<?> iter = configEnv.entrySet().iterator();
while (iter.hasNext()) {
Entry<?, ?> entry = (Entry<?, ?>) iter.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
strings.add(key + "=" + value); //$NON-NLS-1$
}
return strings.toArray(new String[strings.size()]);
}
/**
* Get the name of the project
*
* @param configuration
* @return
* @throws CoreException
*/
protected static String getProjectName(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null);
}
/**
* Get the name of the queue for the launch
*
* @param configuration
* @return
* @throws CoreException
*/
protected static String getQueueName(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_QUEUE_NAME, (String) null);
}
/**
* Get the resource manager to use for the launch
*
* @param configuration
* @return
* @throws CoreException
*/
protected static String getResourceManagerUniqueName(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_RESOURCE_MANAGER_UNIQUENAME, (String) null);
}
/*
* Model listeners
*/
private final IJobListener fJobListener = new JobListener();
/*
* HashMap used to keep track of job submissions
*/
protected Map<String, JobSubmission> jobSubmissions = Collections.synchronizedMap(new HashMap<String, JobSubmission>());
/*
* Data synchronization rules
*/
private List<ISynchronizationRule> extraSynchronizationRules;
/**
* Constructor
*/
public AbstractParallelLaunchConfigurationDelegate() {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.launch.rulesengine.ILaunchProcessCallback#
* addSynchronizationRule(org.eclipse.ptp.launch.data.ISynchronizationRule)
*/
/**
* @since 5.0
*/
public void addSynchronizationRule(ISynchronizationRule rule) {
extraSynchronizationRules.add(rule);
}
/**
* Get if the executable shall be copied to remote target before launch.
*
* @param configuration
* @return
* @throws CoreException
*/
public boolean getCopyExecutable(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_COPY_EXECUTABLE, false);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.model.LaunchConfigurationDelegate#getLaunch(org .eclipse.debug.core.ILaunchConfiguration,
* java.lang.String)
*/
@Override
public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
return new PLaunch(configuration, mode, null);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.launch.rulesengine.ILaunchProcessCallback#getLocalFileManager
* (org.eclipse.debug.core.ILaunchConfiguration)
*/
public IRemoteFileManager getLocalFileManager(ILaunchConfiguration configuration) throws CoreException {
IRemoteServices localServices = PTPRemoteCorePlugin.getDefault().getDefaultServices();
assert (localServices != null);
IRemoteConnectionManager lconnMgr = localServices.getConnectionManager();
assert (lconnMgr != null);
IRemoteConnection lconn = lconnMgr.getConnection(IRemoteConnectionManager.DEFAULT_CONNECTION_NAME);
assert (lconn != null);
IRemoteFileManager localFileManager = localServices.getFileManager(lconn);
assert (localFileManager != null);
return localFileManager;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ptp.launch.rulesengine.ILaunchProcessCallback#
* getRemoteFileManager(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.runtime.IProgressMonitor)
*/
/**
* @since 5.0
*/
public IRemoteFileManager getRemoteFileManager(ILaunchConfiguration configuration, IProgressMonitor monitor)
throws CoreException {
IResourceManager rm = getResourceManager(configuration);
if (rm != null) {
IResourceManagerComponentConfiguration conf = rm.getControlConfiguration();
IRemoteServices remoteServices = PTPRemoteCorePlugin.getDefault()
.getRemoteServices(conf.getRemoteServicesId(), monitor);
if (remoteServices != null) {
IRemoteConnectionManager rconnMgr = remoteServices.getConnectionManager();
if (rconnMgr != null) {
IRemoteConnection rconn = rconnMgr.getConnection(conf.getConnectionName());
if (rconn != null && rconn.isOpen()) {
return remoteServices.getFileManager(rconn);
}
}
}
}
return null;
}
/**
* Check if the copy local file is enabled. If it is, copy the executable file from the local host to the remote host.
*
* @param configuration
* launch configuration
* @throws CoreException
* if the copy fails or is cancelled
*/
protected void copyExecutable(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
boolean copyExecutable = getCopyExecutable(configuration);
if (copyExecutable) {
// Get remote and local paths
String remotePath = getExecutablePath(configuration);
String localPath = configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_LOCAL_EXECUTABLE_PATH,
(String) null);
// Check if local path is valid
if (localPath == null) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_1));
}
// Copy data
copyFileToRemoteHost(localPath, remotePath, configuration, monitor);
}
}
/**
* Copy a data from a path (can be a file or directory) from the remote host to the local host.
*
* @param remotePath
* @param localPath
* @param configuration
* @throws CoreException
*/
protected void copyFileFromRemoteHost(String remotePath, String localPath, ILaunchConfiguration configuration,
IProgressMonitor monitor) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 15);
try {
IRemoteFileManager localFileManager = getLocalFileManager(configuration);
IRemoteFileManager remoteFileManager = getRemoteFileManager(configuration, progress.newChild(5));
if (progress.isCanceled()) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Operation_cancelled_by_user, null));
}
if (remoteFileManager == null) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_0));
}
IFileStore rres = remoteFileManager.getResource(remotePath);
if (!rres.fetchInfo(EFS.NONE, progress.newChild(5)).exists()) {
// Local file not found!
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Remote_resource_does_not_exist));
}
IFileStore lres = localFileManager.getResource(localPath);
// Copy file
rres.copy(lres, EFS.OVERWRITE, progress.newChild(5));
} finally {
if (monitor != null) {
monitor.done();
}
}
}
/**
* Copy a data from a path (can be a file or directory) from the local host to the remote host.
*
* @param localPath
* @param remotePath
* @param configuration
* @throws CoreException
*/
protected void copyFileToRemoteHost(String localPath, String remotePath, ILaunchConfiguration configuration,
IProgressMonitor monitor) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 15);
try {
IRemoteFileManager localFileManager = getLocalFileManager(configuration);
IRemoteFileManager remoteFileManager = getRemoteFileManager(configuration, progress.newChild(5));
if (progress.isCanceled()) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Operation_cancelled_by_user, null));
}
if (remoteFileManager == null) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_0));
}
IFileStore lres = localFileManager.getResource(localPath);
if (!lres.fetchInfo(EFS.NONE, progress.newChild(5)).exists()) {
// Local file not found!
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Local_resource_does_not_exist));
}
IFileStore rres = remoteFileManager.getResource(remotePath);
// Copy file
lres.copy(rres, EFS.OVERWRITE, progress.newChild(5));
} finally {
if (monitor != null) {
monitor.done();
}
}
}
/**
* Called to cleanup once the job terminates
*
* @param config
* @param mode
* @param launch
* @since 5.0
*/
protected abstract void doCleanupLaunch(IPLaunch launch);
/**
* This method is called when the job state changes to RUNNING. This allows the launcher to complete the job launch.
*
* @param launch
* @param debugger
* @since 5.0
*/
protected abstract void doCompleteJobLaunch(IPLaunch launch, IPDebugger debugger);
/**
* @param configuration
* @throws CoreException
*/
protected void doPostLaunchSynchronization(ILaunchConfiguration configuration) throws CoreException {
if (configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_SYNC_AFTER, false)) {
List<?> rulesList = configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_SYNC_RULES,
new ArrayList<String>());
// This faction generate action objects which execute according to
// rules
RuleActionFactory ruleActFactory = new RuleActionFactory(configuration, this, new NullProgressMonitor());
for (Object ruleObj : rulesList) {
ISynchronizationRule syncRule = RuleFactory.createRuleFromString((String) ruleObj);
if (syncRule.isDownloadRule()) {
// Execute the action
IRuleAction action = ruleActFactory.getAction(syncRule);
action.run();
}
}
}
}
/**
* This method does the synchronization step before the job submission
*
* @param configuration
* @param monitor
*/
protected void doPreLaunchSynchronization(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
if (configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_SYNC_BEFORE, false)) {
// This faction generate action objects which execute according to
// rules
RuleActionFactory ruleActFactory = new RuleActionFactory(configuration, this, monitor);
try {
List<?> rulesList = configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_SYNC_RULES,
new ArrayList<String>());
// Iterate over rules executing them
for (Object ruleObj : rulesList) {
ISynchronizationRule syncRule = RuleFactory.createRuleFromString((String) ruleObj);
if (syncRule.isUploadRule()) {
// Execute the action
IRuleAction action = ruleActFactory.getAction(syncRule);
action.run();
}
}
} finally {
if (monitor != null) {
monitor.done();
}
}
}
}
/**
* @since 5.0
*/
protected void verifyLaunchAttributes(final ILaunchConfiguration configuration, String mode, final IProgressMonitor monitor)
throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 30);
try {
/*
* Verify executable path
*/
verifyExecutablePath(configuration, progress.newChild(10));
/*
* Verify working directory. Use the executable path if no working directory has been set.
*/
String workPath = getWorkingDirectory(configuration);
if (workPath != null) {
verifyResource(workPath, configuration, monitor);
}
if (progress.isCanceled()) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Operation_cancelled_by_user, null));
}
if (mode.equals(ILaunchManager.DEBUG_MODE)) {
verifyDebuggerPath(configuration, progress.newChild(10));
}
} finally {
if (monitor != null) {
monitor.done();
}
}
}
/**
* Get the debugger configuration
*
* @param configuration
* launch configuration
* @return debugger configuration
* @throws CoreException
*/
protected IPDebugConfiguration getDebugConfig(ILaunchConfiguration config) throws CoreException {
return PTPDebugCorePlugin.getDefault().getDebugConfiguration(getDebuggerID(config));
}
/**
* Get the absolute path of the executable to launch. If the executable is on a remote machine, this is the path to the
* executable on that machine.
*
* @param configuration
* @return
* @throws CoreException
*/
protected String getExecutablePath(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_EXECUTABLE_PATH, (String) null);
}
/**
* Convert application arguments to an array of strings.
*
* @param configuration
* launch configuration
* @return array of strings containing the program arguments
* @throws CoreException
*/
protected String[] getProgramArguments(ILaunchConfiguration configuration) throws CoreException {
String temp = getArguments(configuration);
if (temp != null && temp.length() > 0) {
ArgumentParser ap = new ArgumentParser(temp);
List<String> args = ap.getTokenList();
if (args != null) {
return args.toArray(new String[args.size()]);
}
}
return new String[0];
}
/**
* Get the name of the executable to launch
*
* @param configuration
* @return
* @throws CoreException
*/
protected String getProgramName(ILaunchConfiguration configuration) throws CoreException {
String exePath = getExecutablePath(configuration);
if (exePath != null) {
return new Path(exePath).lastSegment();
}
return null;
}
/**
* Get the path component of the executable to launch.
*
* @param configuration
* @return
* @throws CoreException
* @since 5.0
*/
protected String getProgramPath(ILaunchConfiguration configuration) throws CoreException {
String exePath = getExecutablePath(configuration);
if (exePath != null) {
return new Path(exePath).removeLastSegments(1).toString();
}
return null;
}
/**
* Get the IProject object from the project name.
*
* @param project
* name of the project
* @return IProject resource
*/
protected IProject getProject(String project) {
return getWorkspaceRoot().getProject(project);
}
/**
* Get the default queue for the given resource manager
*
* @param rm
* resource manager
* @return default queue
* @since 5.0
*/
protected IPQueue getQueueDefault(IPResourceManager rm) {
final IPQueue[] queues = rm.getQueues();
if (queues.length == 0) {
return null;
}
return queues[0];
}
/**
* Find the resource manager that corresponds to the unique name specified in the configuration
*
* @param configuration
* launch configuration
* @return resource manager
* @throws CoreException
* @since 5.0
*/
protected IResourceManager getResourceManager(ILaunchConfiguration configuration) throws CoreException {
String rmUniqueName = getResourceManagerUniqueName(configuration);
if (rmUniqueName != null) {
return PTPCorePlugin.getDefault().getModelManager().getResourceManagerFromUniqueName(rmUniqueName);
}
return null;
}
/**
* Returns the (possible empty) list of synchronization rule objects according to the rules described in the configuration.
*
* @since 5.0
*/
protected ISynchronizationRule[] getSynchronizeRules(ILaunchConfiguration configuration) throws CoreException {
List<?> ruleStrings = configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_SYNC_RULES, new ArrayList<String>());
List<ISynchronizationRule> result = new ArrayList<ISynchronizationRule>();
for (Object ruleObj : ruleStrings) {
String element = (String) ruleObj;
try {
ISynchronizationRule rule = RuleFactory.createRuleFromString(element);
result.add(rule);
} catch (RuntimeException e) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Error_converting_rules));
}
}
return result.toArray(new ISynchronizationRule[result.size()]);
}
/**
* Get the working directory for the application launch
*
* @param configuration
* @return
* @throws CoreException
* @since 5.0
*/
protected String getWorkingDirectory(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IPTPLaunchConfigurationConstants.ATTR_WORKING_DIR, (String) null);
}
/**
* Set the working directory
*
* @param configuration
* @param dir
* @throws CoreException
* @since 5.0
*/
protected void setWorkingDirectory(ILaunchConfigurationWorkingCopy configuration, String dir) throws CoreException {
configuration.setAttribute(IPTPLaunchConfigurationConstants.ATTR_WORKING_DIR, dir);
}
/**
* Get the workspace root.
*
* @return workspace root
*/
protected IWorkspaceRoot getWorkspaceRoot() {
return ResourcesPlugin.getWorkspace().getRoot();
}
/**
* Create a source locator from the ID specified in the configuration, or create a default one if it hasn't been specified.
*
* @param launch
* @param configuration
* @throws CoreException
*/
protected void setDefaultSourceLocator(ILaunch launch, ILaunchConfiguration configuration) throws CoreException {
// set default source locator if none specified
if (launch.getSourceLocator() == null) {
IPersistableSourceLocator sourceLocator;
String id = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String) null);
if (id == null) {
sourceLocator = PTPDebugUIPlugin.createDefaultSourceLocator();
sourceLocator.initializeDefaults(configuration);
} else {
sourceLocator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(id);
String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String) null);
if (memento == null) {
sourceLocator.initializeDefaults(configuration);
} else {
sourceLocator.initializeFromMemento(memento);
}
}
launch.setSourceLocator(sourceLocator);
}
}
/**
* Set the source locator for this application
*
* @param launch
* @param config
* @throws CoreException
*/
protected void setSourceLocator(ILaunch launch, ILaunchConfiguration config) throws CoreException {
setDefaultSourceLocator(launch, config);
}
/**
* Submit a job to the resource manager. Keeps track of the submission so we know when the job actually starts running. When
* this happens, the abstract method doCompleteJobLaunch() is invoked.
*
* @param configuration
* @param mode
* @param launch
* @param debugger
* @param monitor
* @throws CoreException
* @since 5.0
*/
protected void submitJob(ILaunchConfiguration configuration, String mode, IPLaunch launch, IPDebugger debugger,
IProgressMonitor monitor) throws CoreException {
SubMonitor progress = SubMonitor.convert(monitor, 10);
try {
final IResourceManager rm = getResourceManager(configuration);
if (rm == null) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_No_ResourceManager));
}
rm.addJobListener(fJobListener);
launch.setResourceManager(rm);
String jobId = rm.submitJob(configuration, mode, progress.newChild(5));
if (rm.getJobStatus(jobId, progress.newChild(50)).equals(IJobStatus.UNDETERMINED)) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_UnableToDetermineJobStatus));
}
launch.setJobId(jobId);
JobSubmission jobSub = new JobSubmission(launch, debugger);
synchronized (jobSubmissions) {
jobSubmissions.put(jobId, jobSub);
}
jobSub.schedule();
} finally {
if (monitor != null) {
monitor.done();
}
}
}
/**
* Verify the validity of the debugger path.
*
* @param configuration
* launch configuration
* @param monitor
* progress monitor
* @throws CoreException
* if the path is invalid or the monitor was canceled.
* @since 5.0
*/
protected void verifyDebuggerPath(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
String dbgPath = getDebuggerExePath(configuration);
if (dbgPath == null) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_debuggerPathNotSpecified));
}
try {
verifyResource(dbgPath, configuration, monitor);
if (monitor.isCanceled()) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Operation_cancelled_by_user, null));
}
} catch (CoreException e) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Debugger_path_not_found, new FileNotFoundException(
e.getLocalizedMessage())));
}
}
/**
* Verify the validity of executable path. If the executable is to be copied, then no additional verification is required.
* Otherwise, the path must point to an existing file.
*
* @param configuration
* launch configuration
* @param monitor
* progress monitor
* @return IPath representing path to the executable (either local or remote)
* @throws CoreException
* if the resource can't be found or the monitor was canceled.
* @since 5.0
*/
protected IPath verifyExecutablePath(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
if (getCopyExecutable(configuration)) {
return new Path(getExecutablePath(configuration));
} else {
String exePath = getExecutablePath(configuration);
try {
IPath path = verifyResource(exePath, configuration, monitor);
if (monitor.isCanceled()) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Operation_cancelled_by_user, null));
}
return path;
} catch (CoreException e) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Application_file_does_not_exist,
new FileNotFoundException(e.getLocalizedMessage())));
}
}
}
/**
* Verify that the project exists prior to the launch.
*
* @param configuration
* @return
* @throws CoreException
*/
protected IProject verifyProject(ILaunchConfiguration configuration) throws CoreException {
String proName = getProjectName(configuration);
if (proName == null) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Project_not_specified));
}
IProject project = getProject(proName);
if (project == null || !project.exists() || !project.isOpen()) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Project_does_not_exist_or_is_not_a_project));
}
return project;
}
/**
* @param path
* @param configuration
* @return
* @throws CoreException
* @since 5.0
*/
protected IPath verifyResource(String path, ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
return PTPLaunchPlugin.getDefault().verifyResource(path, configuration, monitor);
}
/**
* Verify the working directory. If no working directory is specified, the default is the location of the executable.
*
* @param configuration
* launch configuration
* @param monitor
* progress monitor
* @return path of working directory
* @throws CoreException
* if the working directory is invalid or the monitor was canceled.
* @since 5.0
*/
protected String verifyWorkDirectory(ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException {
IPath path;
String workPath = getWorkingDirectory(configuration);
if (workPath == null) {
path = verifyExecutablePath(configuration, monitor).removeLastSegments(1);
} else {
path = verifyResource(workPath, configuration, monitor);
}
if (monitor.isCanceled()) {
throw new CoreException(new Status(IStatus.ERROR, PTPLaunchPlugin.getUniqueIdentifier(),
Messages.AbstractParallelLaunchConfigurationDelegate_Operation_cancelled_by_user, null));
}
return path.toString();
}
}