blob: 0d643ae48f3e177a4117851107814100fc604905 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Sascha Radike - bug 56642
* Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
*******************************************************************************/
package org.eclipse.debug.internal.core;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
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.Path;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
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.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchDelegate;
import org.eclipse.debug.core.IStatusHandler;
import org.eclipse.debug.core.Launch;
import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
import org.eclipse.debug.core.model.IPersistableSourceLocator;
import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Launch configuration handle.
*
* @see ILaunchConfiguration
*/
public class LaunchConfiguration extends PlatformObject implements ILaunchConfiguration {
/**
* Launch configuration attribute that specifies the resources paths mapped to it.
* Not all launch configurations will have a mapped resource unless migrated.
* Value is a list of resource paths stored as portable strings, or <code>null</code>
* if none.
*
* @since 3.2
*/
public static final String ATTR_MAPPED_RESOURCE_PATHS = DebugPlugin.getUniqueIdentifier() + ".MAPPED_RESOURCE_PATHS"; //$NON-NLS-1$
/**
* Launch configuration attribute that specifies the resources types mapped to it.
* Not all launch configurations will have a mapped resource unless migrated.
* Value is a list of resource type integers, or <code>null</code> if none.
*
* @since 3.2
*/
public static final String ATTR_MAPPED_RESOURCE_TYPES = DebugPlugin.getUniqueIdentifier() + ".MAPPED_RESOURCE_TYPES"; //$NON-NLS-1$
/**
* The launch modes set on this configuration.
*
* @since 3.3
*/
public static final String ATTR_LAUNCH_MODES = DebugPlugin.getUniqueIdentifier() + ".LAUNCH_MODES"; //$NON-NLS-1$
/**
* Launch configuration attribute storing a list
* of preferred launchers for associated mode sets.
* This attribute is a list of launchers stored by mode set
* and relating to the id of the preferred launcher, which happens to be an <code>ILaunchDelegate</code>
*
* @since 3.3
*/
public static final String ATTR_PREFERRED_LAUNCHERS = DebugPlugin.getUniqueIdentifier() + ".preferred_launchers"; //$NON-NLS-1$
/**
* Launch configuration attribute storing a memento identifying the prototype
* this configuration was made from, possibly <code>null</code>.
*
* @since 3.12
*/
public static final String ATTR_PROTOTYPE = DebugPlugin.getUniqueIdentifier() + ".ATTR_PROTOTYPE"; //$NON-NLS-1$
/**
* Launch configuration attribute storing if this configuration is a
* prototype or not.
*
* @since 3.12
*/
public static final String IS_PROTOTYPE = DebugPlugin.getUniqueIdentifier() + ".IS_PROTOTYPE"; //$NON-NLS-1$
/**
* Status handler to prompt in the UI thread
*
* @since 3.3
*/
protected static final IStatus promptStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 200, "", null); //$NON-NLS-1$//$NON-NLS-2$
/**
* Status handler to prompt the user to resolve the missing launch delegate issue
* @since 3.3
*/
protected static final IStatus delegateNotAvailable = new Status(IStatus.INFO, "org.eclipse.debug.core", 226, "", null); //$NON-NLS-1$ //$NON-NLS-2$
/**
* Status handle to prompt the user to resolve duplicate launch delegates being detected
*
* @since 3.3
*/
protected static final IStatus duplicateDelegates = new Status(IStatus.INFO, "org.eclipse.debug.core", 227, "", null); //$NON-NLS-1$//$NON-NLS-2$
/**
* This configuration's name
* @since 3.5
*/
private String fName;
/**
* The container this configuration is stored in or <code>null</code> if stored locally
* with workspace metadata.
* @since 3.5
*/
private IContainer fContainer;
/**
* If this configuration is a prototype.
* @since 3.12
*/
private boolean fIsPrototype;
/**
* Constructs a launch configuration with the given name. The configuration
* is stored in the given container or locally with workspace metadata if
* the specified container is <code>null</code>.
*
* @param name launch configuration name
* @param container parent container or <code>null</code>
* @since 3.5
*/
protected LaunchConfiguration(String name, IContainer container) {
this(name, container, false);
}
/**
* Constructs a launch configuration with the given name. The configuration
* is stored in the given container or locally with workspace metadata if
* the specified container is <code>null</code>.
*
* @param name launch configuration name
* @param container parent container or <code>null</code>
* @param prototype if the configuration is a prototype or not
* @since 3.12
*/
protected LaunchConfiguration(String name, IContainer container, boolean prototype) {
initialize();
setName(name);
setContainer(container);
fIsPrototype = prototype;
}
/**
* Initialize any state variables - called first in the constructor.
* Subclasses must override as appropriate.
*/
protected void initialize() {
}
/**
* Constructs a launch configuration on the given workspace file.
*
* @param file workspace .launch file
* @since 3.5
*/
protected LaunchConfiguration(IFile file) {
this(getSimpleName(file.getName()), file.getParent(), isPrototype(file));
}
/**
* Given a name that ends with .launch or .prototype, return the simple name of the configuration.
*
* @param fileName the name to parse
* @return simple name
* @since 3.5
*/
protected static String getSimpleName(String fileName) {
IPath path = new Path(fileName);
if(ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION.equals(path.getFileExtension())) {
return path.removeFileExtension().toString();
} else if (ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION.equals(path.getFileExtension())) {
return path.removeFileExtension().toString();
}
return fileName;
}
/**
* Constructs a launch configuration from the given
* memento.
*
* @param memento launch configuration memento
* @exception CoreException if the memento is invalid or
* an exception occurs reading the memento
*/
protected LaunchConfiguration(String memento) throws CoreException {
Exception ex = null;
try {
Element root = null;
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
parser.setErrorHandler(new DefaultHandler());
StringReader reader = new StringReader(memento);
InputSource source = new InputSource(reader);
root = parser.parse(source).getDocumentElement();
String localString = root.getAttribute(IConfigurationElementConstants.LOCAL);
String path = root.getAttribute(IConfigurationElementConstants.PATH);
String message = null;
if (path == null || IInternalDebugCoreConstants.EMPTY_STRING.equals(path)) {
message = DebugCoreMessages.LaunchConfiguration_18;
} else if (localString == null || IInternalDebugCoreConstants.EMPTY_STRING.equals(localString)) {
message = DebugCoreMessages.LaunchConfiguration_19;
}
if (message != null) {
throw new CoreException(newStatus(message, DebugException.INTERNAL_ERROR, null));
}
boolean local = (Boolean.valueOf(localString)).booleanValue();
IPath iPath = new Path(path);
String name = getSimpleName(iPath.lastSegment());
IContainer container = null;
if (!local) {
container = ResourcesPlugin.getWorkspace().getRoot().getFile(iPath).getParent();
}
setName(name);
setContainer(container);
return;
} catch (ParserConfigurationException e) {
ex = e;
} catch (SAXException e) {
ex = e;
} catch (IOException e) {
ex = e;
}
IStatus s = newStatus(DebugCoreMessages.LaunchConfiguration_17, DebugException.INTERNAL_ERROR, ex);
throw new CoreException(s);
}
@Override
public boolean contentsEqual(ILaunchConfiguration object) {
try {
if (object instanceof LaunchConfiguration) {
LaunchConfiguration otherConfig = (LaunchConfiguration) object;
return getName().equals(otherConfig.getName())
&& getType().equals(otherConfig.getType())
&& equalOrNull(getContainer(), otherConfig.getContainer())
&& getInfo().equals(otherConfig.getInfo());
}
return false;
} catch (CoreException ce) {
return false;
}
}
@Override
public ILaunchConfigurationWorkingCopy copy(String name) throws CoreException {
ILaunchConfigurationWorkingCopy copy = new LaunchConfigurationWorkingCopy(this, name);
return copy;
}
@Override
public void delete() throws CoreException {
if (exists()) {
IFile file = getFile();
if (file == null) {
IFileStore store = getFileStore();
if (store != null) {
store.delete(EFS.NONE, null);
if ((store.fetchInfo().exists())) {
throw new DebugException(
new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
DebugException.REQUEST_FAILED, DebugCoreMessages.LaunchConfiguration_Failed_to_delete_launch_configuration__1, null)
);
}
}
} else {
// Delete the resource using IFile API such that
// resource deltas are fired.
// First do validate edit to ensure the resource is local
if (file.isReadOnly()) {
IStatus status = ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, null);
if (!status.isOK()) {
throw new CoreException(status);
}
}
file.delete(true, null);
}
// update the launch manager cache synchronously
getLaunchManager().launchConfigurationDeleted(this);
}
}
@Override
public void delete(int flag) throws CoreException {
if (flag == UPDATE_PROTOTYPE_CHILDREN && isPrototype()) {
// clear back pointers to this configuration
Collection<ILaunchConfiguration> children = getPrototypeChildren();
for (ILaunchConfiguration child : children) {
ILaunchConfigurationWorkingCopy childWC = child.getWorkingCopy();
childWC.setPrototype(null, false);
childWC.doSave();
}
}
delete();
}
/**
* Returns whether this configuration is equal to the
* given configuration. Two configurations are equal if
* they are stored in the same location (and neither one
* is a working copy).
*
* @return whether this configuration is equal to the
* given configuration
* @see Object#equals(Object)
*/
@Override
public boolean equals(Object object) {
if (object instanceof ILaunchConfiguration) {
if (isWorkingCopy()) {
return this == object;
}
LaunchConfiguration config = (LaunchConfiguration) object;
if (!config.isWorkingCopy()) {
return getName().equals(config.getName()) &&
equalOrNull(getContainer(), config.getContainer());
}
}
return false;
}
/**
* Returns whether the given objects are equal or both <code>null</code>.
*
* @param o1 the object
* @param o2 the object to be compared to o1
* @return whether the given objects are equal or both <code>null</code>
* @since 3.5
*/
protected boolean equalOrNull(Object o1, Object o2) {
if (o1 == null) {
return o2 == null;
} else if (o2 != null) {
return o1.equals(o2);
}
return false;
}
@Override
public boolean exists() {
IFile file = getFile();
if (file != null) {
return file.exists();
}
try {
IFileStore store = getFileStore();
if (store != null) {
return store.fetchInfo().exists();
}
} catch (CoreException e) {
}
return false;
}
@Override
public boolean getAttribute(String attributeName, boolean defaultValue) throws CoreException {
return getInfo().getBooleanAttribute(attributeName, defaultValue);
}
@Override
public int getAttribute(String attributeName, int defaultValue) throws CoreException {
return getInfo().getIntAttribute(attributeName, defaultValue);
}
@Override
public List<String> getAttribute(String attributeName, List<String> defaultValue) throws CoreException {
return getInfo().getListAttribute(attributeName, defaultValue);
}
@Override
public Set<String> getAttribute(String attributeName, Set<String> defaultValue) throws CoreException {
return getInfo().getSetAttribute(attributeName, defaultValue);
}
@Override
public Map<String, String> getAttribute(String attributeName, Map<String, String> defaultValue) throws CoreException {
return getInfo().getMapAttribute(attributeName, defaultValue);
}
@Override
public String getAttribute(String attributeName, String defaultValue) throws CoreException {
return getInfo().getStringAttribute(attributeName, defaultValue);
}
@Override
public Map<String, Object> getAttributes() throws CoreException {
LaunchConfigurationInfo info = getInfo();
return info.getAttributes();
}
@Override
public String getCategory() throws CoreException {
return getType().getCategory();
}
@Override
public IFile getFile() {
IContainer container = getContainer();
if (container != null) {
return container.getFile(new Path(getFileName()));
}
return null;
}
/**
* Returns the simple file name of this launch configuration.
*
* @return the simple file name of this launch configuration - for example
* "Abc.launch" or "Abc.prototype"
*/
protected String getFileName() {
StringBuilder buf = new StringBuilder(getName());
buf.append('.');
if (isPrototype()) {
buf.append(ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION);
} else {
buf.append(ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION);
}
return buf.toString();
}
/**
* Returns the info object containing the attributes
* of this configuration
*
* @return info for this handle
* @exception CoreException if unable to retrieve the
* info object
*/
protected LaunchConfigurationInfo getInfo() throws CoreException {
return getLaunchManager().getInfo(this);
}
/**
* Returns the launch manager
*
* @return launch manager
*/
protected LaunchManager getLaunchManager() {
return (LaunchManager)DebugPlugin.getDefault().getLaunchManager();
}
@Override
public IPath getLocation() {
try {
IFileStore store = getFileStore();
if (store != null) {
File localFile = store.toLocalFile(EFS.NONE, null);
if (localFile != null) {
return new Path(localFile.getAbsolutePath());
}
}
} catch (CoreException e) {
}
return null;
}
/**
* Returns the file store this configuration is persisted in or <code>null</code> if
* a file store cannot be derived. The file may or may not exist. If this configuration
* is in a project that is closed or does not exist, <code>null</code> is returned.
*
* @return file store this configuration is persisted in or <code>null</code>
* @throws CoreException if a problem is encountered
* @since 3.5
*/
public IFileStore getFileStore() throws CoreException {
if (isLocal()) {
return EFS.getLocalFileSystem().fromLocalFile(
LaunchManager.LOCAL_LAUNCH_CONFIGURATION_CONTAINER_PATH.append(getFileName()).toFile());
}
URI uri = getFile().getLocationURI();
if (uri != null) {
return EFS.getStore(uri);
}
return null;
}
@Override
public IResource[] getMappedResources() throws CoreException {
List<String> paths = getAttribute(ATTR_MAPPED_RESOURCE_PATHS, (List<String>) null);
if (paths == null || paths.isEmpty()) {
return null;
}
List<String> types = getAttribute(ATTR_MAPPED_RESOURCE_TYPES, (List<String>) null);
if (types == null || types.size() != paths.size()) {
throw new CoreException(newStatus(DebugCoreMessages.LaunchConfiguration_0, DebugPlugin.ERROR, null));
}
ArrayList<IResource> list = new ArrayList<>();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
for(int i = 0; i < paths.size(); i++) {
String pathStr = paths.get(i);
String typeStr= types.get(i);
int type = -1;
try {
type = Integer.decode(typeStr).intValue();
} catch (NumberFormatException e) {
throw new CoreException(newStatus(DebugCoreMessages.LaunchConfiguration_0, DebugPlugin.ERROR, e));
}
IPath path = Path.fromPortableString(pathStr);
IResource res = null;
switch (type) {
case IResource.FILE:
res = root.getFile(path);
break;
case IResource.PROJECT:
pathStr = path.makeRelative().toPortableString();
if(Path.ROOT.isValidSegment(pathStr)) {
res = root.getProject(pathStr);
}
break;
case IResource.FOLDER:
res = root.getFolder(path);
break;
case IResource.ROOT:
res = root;
break;
default:
throw new CoreException(newStatus(DebugCoreMessages.LaunchConfiguration_0, DebugPlugin.ERROR, null));
}
if(res != null) {
list.add(res);
}
}
if (list.isEmpty()) {
return null;
}
return list.toArray(new IResource[list.size()]);
}
@Override
public String getMemento() throws CoreException {
IPath relativePath = null;
IFile file = getFile();
boolean local = true;
if (file == null) {
relativePath = new Path(getName());
} else {
local = false;
relativePath = file.getFullPath();
}
Exception e= null;
try {
Document doc = LaunchManager.getDocument();
Element node = doc.createElement(IConfigurationElementConstants.LAUNCH_CONFIGURATION);
doc.appendChild(node);
node.setAttribute(IConfigurationElementConstants.LOCAL, (Boolean.valueOf(local)).toString());
node.setAttribute(IConfigurationElementConstants.PATH, relativePath.toString());
return LaunchManager.serializeDocument(doc);
} catch (IOException ioe) {
e= ioe;
} catch (ParserConfigurationException pce) {
e= pce;
} catch (TransformerException te) {
e= te;
}
IStatus status = newStatus(DebugCoreMessages.LaunchConfiguration_16, DebugException.INTERNAL_ERROR, e);
throw new CoreException(status);
}
@Override
public String getName() {
return fName;
}
/**
* Returns the container this configuration is stored in, or <code>null</code>
* if this configuration is local.
*
* @return the container this configuration is stored in, or <code>null</code>
* if this configuration is local
* @since 3.5
*/
protected IContainer getContainer() {
return fContainer;
}
@Override
public Set<String> getModes() throws CoreException {
Set<String> options = getAttribute(ATTR_LAUNCH_MODES, (Set<String>) null);
return (options != null ? new HashSet<>(options) : new HashSet<>(0));
}
@Override
public ILaunchConfigurationType getType() throws CoreException {
return getInfo().getType();
}
@Override
public ILaunchConfigurationWorkingCopy getWorkingCopy() throws CoreException {
return new LaunchConfigurationWorkingCopy(this);
}
@Override
public int hashCode() {
IContainer container = getContainer();
if (container == null) {
return getName().hashCode();
} else {
return getName().hashCode() + container.hashCode();
}
}
@Override
public boolean hasAttribute(String attributeName) throws CoreException {
return getInfo().hasAttribute(attributeName);
}
/**
* Set the source locator to use with the launch, if specified
* by this configuration.
*
* @param launch the launch on which to set the source locator
* @throws CoreException if a problem is encountered
*/
protected void initializeSourceLocator(ILaunch launch) throws CoreException {
if (launch.getSourceLocator() == null) {
String type = getAttribute(ATTR_SOURCE_LOCATOR_ID, (String)null);
if (type == null) {
type = getType().getSourceLocatorId();
}
if (type != null) {
IPersistableSourceLocator locator = getLaunchManager().newSourceLocator(type);
String memento = getAttribute(ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
if (memento == null) {
locator.initializeDefaults(this);
} else {
if(locator instanceof IPersistableSourceLocator2) {
((IPersistableSourceLocator2)locator).initializeFromMemento(memento, this);
} else {
locator.initializeFromMemento(memento);
}
}
launch.setSourceLocator(locator);
}
}
}
@Override
public boolean isLocal() {
return getContainer() == null;
}
@Override
public boolean isMigrationCandidate() throws CoreException {
return ((LaunchConfigurationType)getType()).isMigrationCandidate(this);
}
@Override
public boolean isWorkingCopy() {
return false;
}
@Override
public ILaunch launch(String mode, IProgressMonitor monitor) throws CoreException {
return launch(mode, monitor, false);
}
@Override
public ILaunch launch(String mode, IProgressMonitor monitor, boolean build) throws CoreException {
return launch(mode, monitor, build, true);
}
@Override
public ILaunch launch(String mode, IProgressMonitor monitor, boolean build, boolean register) throws CoreException {
/* Setup progress monitor
* - Prepare delegate (0)
* - Pre-launch check (1)
* - [Build before launch (7)] if build
* - [Incremental build before launch (3)] if build
* - Final launch validation (1)
* - Initialize source locator (1)
* - Launch delegate (10) */
SubMonitor lmonitor = SubMonitor.convert(monitor, DebugCoreMessages.LaunchConfiguration_9, 23);
try {
// bug 28245 - force the delegate to load in case it is interested in launch notifications
Set<String> modes = getModes();
modes.add(mode);
ILaunchDelegate[] delegates = getType().getDelegates(modes);
ILaunchConfigurationDelegate delegate = null;
switch (delegates.length) {
case 1:
delegate = delegates[0].getDelegate();
break;
case 0:
{
IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(promptStatus);
if (handler != null) {
handler.handleStatus(delegateNotAvailable, new Object[] {this, mode});
}
IStatus status = new Status(IStatus.CANCEL, DebugPlugin.getUniqueIdentifier(), DebugPlugin.ERROR, DebugCoreMessages.LaunchConfiguration_11, null);
throw new CoreException(status);
}
default:
{
ILaunchDelegate del = getPreferredDelegate(modes);
if(del == null) {
del = getType().getPreferredDelegate(modes);
}
if(del == null) {
IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(promptStatus);
IStatus status = null;
if (handler != null) {
status = (IStatus) handler.handleStatus(duplicateDelegates, new Object[] {this, mode});
}
if(status != null && status.isOK()) {
del = getPreferredDelegate(modes);
if(del == null) {
del = getType().getPreferredDelegate(modes);
}
if(del != null) {
delegate = del.getDelegate();
}
else {
status = new Status(IStatus.CANCEL, DebugPlugin.getUniqueIdentifier(), DebugPlugin.ERROR, DebugCoreMessages.LaunchConfiguration_13, null);
throw new CoreException(status);
}
}
else {
status = new Status(IStatus.CANCEL, DebugPlugin.getUniqueIdentifier(), DebugPlugin.ERROR, DebugCoreMessages.LaunchConfiguration_13, null);
throw new CoreException(status);
}
}
else {
delegate = del.getDelegate();
}
break;
}
}
ILaunchConfigurationDelegate2 delegate2 = null;
if (delegate instanceof ILaunchConfigurationDelegate2) {
delegate2 = (ILaunchConfigurationDelegate2) delegate;
}
// allow the delegate to provide a launch implementation
ILaunch launch = null;
if (delegate2 != null) {
launch = delegate2.getLaunch(this, mode);
}
if (launch == null) {
launch = new Launch(this, mode, null);
} else {
// ensure the launch mode is valid
if (!mode.equals(launch.getLaunchMode())) {
IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.ERROR,
MessageFormat.format(DebugCoreMessages.LaunchConfiguration_14, mode, launch.getLaunchMode()), null);
throw new CoreException(status);
}
}
launch.setAttribute(DebugPlugin.ATTR_LAUNCH_TIMESTAMP, Long.toString(System.currentTimeMillis()));
boolean captureOutput = getAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, true);
if(!captureOutput) {
launch.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, "false"); //$NON-NLS-1$
} else {
launch.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, null);
}
launch.setAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING, getLaunchManager().getEncoding(this));
if (register) {
getLaunchManager().addLaunch(launch);
}
// perform initial pre-launch sanity checks
lmonitor.subTask(DebugCoreMessages.LaunchConfiguration_8);
if (delegate2 != null) {
if (!(delegate2.preLaunchCheck(this, mode, lmonitor.split(1)))) {
getLaunchManager().removeLaunch(launch);
return launch;
}
}
lmonitor.setWorkRemaining(22);
// perform pre-launch build
if (build) {
lmonitor.subTask(DebugCoreMessages.LaunchConfiguration_7 + DebugCoreMessages.LaunchConfiguration_6);
boolean tempbuild = build;
if (delegate2 != null) {
tempbuild = delegate2.buildForLaunch(this, mode, lmonitor.split(7));
}
if (tempbuild) {
lmonitor.subTask(DebugCoreMessages.LaunchConfiguration_7 + DebugCoreMessages.LaunchConfiguration_5);
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, lmonitor.split(3));
}
}
lmonitor.setWorkRemaining(12);
// final validation
lmonitor.subTask(DebugCoreMessages.LaunchConfiguration_4);
if (delegate2 != null) {
if (!(delegate2.finalLaunchCheck(this, mode, lmonitor.split(1)))) {
getLaunchManager().removeLaunch(launch);
return launch;
}
}
lmonitor.setWorkRemaining(11);
try {
//initialize the source locator
lmonitor.subTask(DebugCoreMessages.LaunchConfiguration_3);
initializeSourceLocator(launch);
lmonitor.worked(1);
/* Launch the delegate */
lmonitor.subTask(DebugCoreMessages.LaunchConfiguration_2);
delegate.launch(this, mode, launch, lmonitor.split(10));
} catch (CoreException e) {
// if there was an exception, and the launch is empty, remove it
if (!launch.hasChildren()) {
getLaunchManager().removeLaunch(launch);
}
throw e;
} catch (RuntimeException e) {
// if there was a runtime exception, and the launch is empty, remove it
if (!launch.hasChildren()) {
getLaunchManager().removeLaunch(launch);
}
throw e;
}
if (lmonitor.isCanceled()) {
getLaunchManager().removeLaunch(launch);
}
return launch;
}
finally {
lmonitor.done();
}
}
@Override
public void migrate() throws CoreException {
((LaunchConfigurationType)getType()).migrate(this);
}
/**
* Creates and returns a new error status based on
* the given message, code, and exception.
*
* @param message error message
* @param code error code
* @param e exception or <code>null</code>
* @return status
*/
protected IStatus newStatus(String message, int code, Throwable e) {
return new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), code, message, e);
}
/**
* Sets the new name for this configuration.
*
* @param name the new name for this configuration
* @since 3.5
*/
protected void setName(String name) {
fName = name;
}
/**
* Sets this configurations container or <code>null</code> if stored in the
* local metadata.
*
* @param container or <code>null</code>
* @since 3.5
*/
protected void setContainer(IContainer container) {
fContainer = container;
}
@Override
public boolean supportsMode(String mode) throws CoreException {
return getType().supportsMode(mode);
}
@Override
public boolean isReadOnly() {
try {
IFileStore fileStore = getFileStore();
if (fileStore != null) {
return fileStore.fetchInfo().getAttribute(EFS.ATTRIBUTE_READ_ONLY);
}
} catch (CoreException e) {
}
return true;
}
@Override
public ILaunchDelegate getPreferredDelegate(Set<String> modes) throws CoreException {
Map<String, String> delegates = getAttribute(LaunchConfiguration.ATTR_PREFERRED_LAUNCHERS, (Map<String, String>) null);
if(delegates != null) {
String id = delegates.get(modes.toString());
if(id != null) {
return getLaunchManager().getLaunchDelegate(id);
}
}
return null;
}
@Override
public String toString() {
return getName();
}
@Override
public ILaunchConfiguration getPrototype() throws CoreException {
String memento = getAttribute(ATTR_PROTOTYPE, (String)null);
if (memento != null) {
LaunchConfiguration prototype = new LaunchConfiguration(memento);
prototype.setIsPrototype(true);
return prototype;
}
return null;
}
@Override
public Collection<ILaunchConfiguration> getPrototypeChildren() throws CoreException {
ILaunchConfiguration[] configurations = getLaunchManager().getLaunchConfigurations(getType());
List<ILaunchConfiguration> proteges = new ArrayList<>();
for (ILaunchConfiguration config : configurations) {
if (this.equals(config.getPrototype())) {
proteges.add(config);
}
}
return proteges;
}
@Override
public boolean isPrototype() {
return fIsPrototype;
}
/**
* Set the prototype state of this configuration.
*
* @param isPrototype the prototype state.
*
* @since 3.12
*/
protected void setIsPrototype(boolean isPrototype) {
fIsPrototype = isPrototype;
}
/**
* Check if the given file is a launch configuration prototype or not.
*
* @param file the given {@link IFile}.
* @return <code>true</code> if the given file is a launch configuration
* prototype, false otherwise.
*
* @since 3.12
*/
protected static boolean isPrototype(IFile file) {
if (ILaunchConfiguration.LAUNCH_CONFIGURATION_PROTOTYPE_FILE_EXTENSION.equals(file.getFileExtension())) {
return true;
}
return false;
}
@Override
public int getKind() throws CoreException {
if (fIsPrototype) {
return PROTOTYPE;
}
return CONFIGURATION;
}
@Override
public boolean isAttributeModified(String attribute) throws CoreException {
ILaunchConfiguration prototype = getPrototype();
if (prototype != null) {
Object prototypeValue = prototype.getAttributes().get(attribute);
Object attributeValue = getAttributes().get(attribute);
return !LaunchConfigurationInfo.compareAttribute(attribute, prototypeValue, attributeValue);
}
return false;
}
@Override
public Set<String> getPrototypeVisibleAttributes() throws CoreException {
return getInfo().getVisibleAttributes();
}
@Override
public void setPrototypeAttributeVisibility(String attribute, boolean visible) throws CoreException {
getInfo().setAttributeVisibility(attribute, visible);
}
}