/*******************************************************************************
* Copyright (c) 2012, 2014 Wind River Systems, Inc. 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.te.launch.core.lm.delegates;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.tcf.te.launch.core.activator.CoreBundleActivator;
import org.eclipse.tcf.te.launch.core.bindings.LaunchConfigTypeBindingsManager;
import org.eclipse.tcf.te.launch.core.exceptions.LaunchServiceException;
import org.eclipse.tcf.te.launch.core.interfaces.IReferencedProjectItem;
import org.eclipse.tcf.te.launch.core.interfaces.tracing.ITraceIds;
import org.eclipse.tcf.te.launch.core.lm.LaunchConfigHelper;
import org.eclipse.tcf.te.launch.core.lm.LaunchConfigSorter;
import org.eclipse.tcf.te.launch.core.lm.LaunchSpecification;
import org.eclipse.tcf.te.launch.core.lm.interfaces.ICommonLaunchAttributes;
import org.eclipse.tcf.te.launch.core.lm.interfaces.IFileTransferLaunchAttributes;
import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchAttribute;
import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchContextLaunchAttributes;
import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate;
import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification;
import org.eclipse.tcf.te.launch.core.lm.interfaces.IReferencedProjectLaunchAttributes;
import org.eclipse.tcf.te.launch.core.nls.Messages;
import org.eclipse.tcf.te.launch.core.persistence.DefaultPersistenceDelegate;
import org.eclipse.tcf.te.launch.core.persistence.filetransfer.FileTransfersPersistenceDelegate;
import org.eclipse.tcf.te.launch.core.persistence.launchcontext.LaunchContextsPersistenceDelegate;
import org.eclipse.tcf.te.launch.core.persistence.projects.ReferencedProjectsPersistenceDelegate;
import org.eclipse.tcf.te.launch.core.preferences.IPreferenceKeys;
import org.eclipse.tcf.te.launch.core.selection.interfaces.ILaunchSelection;
import org.eclipse.tcf.te.launch.core.selection.interfaces.ISelectionContext;
import org.eclipse.tcf.te.runtime.extensions.ExecutableExtension;
import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode;
import org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem;
/**
* Default launch manager delegate implementation.
*/
public class DefaultLaunchManagerDelegate extends ExecutableExtension implements ILaunchManagerDelegate {
/**
* Constructor.
*/
public DefaultLaunchManagerDelegate() {
super();
}
protected void copySpecToConfig(ILaunchSpecification launchSpec, ILaunchConfigurationWorkingCopy wc) {
for (ILaunchAttribute attribute : launchSpec.getAllAttributes()) {
LaunchConfigHelper.addLaunchConfigAttribute(wc, attribute.getKey(), attribute.getValue());
}
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#initLaunchConfigAttributes(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy, org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification)
*/
@Override
public void initLaunchConfigAttributes(ILaunchConfigurationWorkingCopy wc, ILaunchSpecification launchSpec) {
Assert.isNotNull(wc);
Assert.isNotNull(launchSpec);
if (!DefaultPersistenceDelegate.hasAttribute(wc, ICommonLaunchAttributes.ATTR_UUID)) {
DefaultPersistenceDelegate.setAttribute(wc, ICommonLaunchAttributes.ATTR_UUID, UUID.randomUUID().toString());
}
validateLaunchSpecification(launchSpec);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#updateLaunchConfigAttributes(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy, org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification)
*/
@Override
public void updateLaunchConfigAttributes(ILaunchConfigurationWorkingCopy wc, ILaunchSpecification launchSpec) {
Assert.isNotNull(wc);
Assert.isNotNull(launchSpec);
if (!DefaultPersistenceDelegate.hasAttribute(wc, ICommonLaunchAttributes.ATTR_UUID)) {
DefaultPersistenceDelegate.setAttribute(wc, ICommonLaunchAttributes.ATTR_UUID, UUID.randomUUID().toString());
}
validateLaunchSpecification(launchSpec);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#updateLaunchConfig(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy, org.eclipse.tcf.te.launch.core.selection.interfaces.ISelectionContext, boolean)
*/
@Override
public void updateLaunchConfig(ILaunchConfigurationWorkingCopy wc, ISelectionContext selContext, boolean replace) {
Assert.isNotNull(wc);
Assert.isNotNull(selContext);
}
@Override
public boolean isDefaultAttribute(String attributeKey, Object specValue, Object confValue, ILaunchSpecification launchSpec, ILaunchConfiguration launchConfig, String launchMode) {
Assert.isNotNull(attributeKey);
Assert.isNotNull(launchConfig);
Assert.isNotNull(launchSpec);
Assert.isNotNull(launchMode);
if (confValue == null && specValue != null) {
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#getMatchingLaunchConfigurations(org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification, org.eclipse.debug.core.ILaunchConfiguration[])
*/
@Override
public final ILaunchConfiguration[] getMatchingLaunchConfigurations(ILaunchSpecification launchSpec, ILaunchConfiguration[] launchConfigs) throws LaunchServiceException {
if (launchConfigs == null || launchConfigs.length == 0) {
return new ILaunchConfiguration[0];
}
else if (launchSpec != null) {
List<LaunchConfigSorter> rankedList = new ArrayList<LaunchConfigSorter>();
for (ILaunchConfiguration launchConfig : launchConfigs) {
if (CoreBundleActivator.getTraceHandler()
.isSlotEnabled(0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING)) {
System.out.println("\n***\n"); //$NON-NLS-1$
}
int ranking = 0;
try {
ranking = getLaunchConfigRanking(launchSpec, launchConfig);
}
catch (LaunchServiceException e) {
switch (e.getType()) {
case LaunchServiceException.TYPE_MISSING_LAUNCH_CONFIG_ATTR:
ranking = -1;
break;
default:
throw e;
}
}
int fullMatchRanking = getFullMatchRanking();
if (CoreBundleActivator.getTraceHandler()
.isSlotEnabled(0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING)) {
StringBuilder message = new StringBuilder("Ranking launch spec ("); //$NON-NLS-1$
message.append(launchSpec.getLaunchConfigName());
message.append(") vs launch configuration ("); //$NON-NLS-1$
message.append(launchConfig.getName());
message.append(") = "); //$NON-NLS-1$
message.append(ranking);
message.append(" ; full match ranking = "); //$NON-NLS-1$
message.append(fullMatchRanking);
CoreBundleActivator
.getTraceHandler()
.trace(message.toString(), 0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING, IStatus.INFO, this);
}
if (ranking >= 0 && ranking >= fullMatchRanking) {
rankedList.add(new LaunchConfigSorter(launchConfig, ranking));
}
}
// sort results and write back into array
Collections.sort(rankedList);
ILaunchConfiguration[] matchingConfigs = new ILaunchConfiguration[rankedList.size()];
for (int i = 0; i < rankedList.size(); i++) {
matchingConfigs[i] = rankedList.get(i).getConfig();
}
return matchingConfigs;
}
else {
return launchConfigs;
}
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#getLaunchSpecification(java.lang.String, org.eclipse.tcf.te.launch.core.selection.interfaces.ILaunchSelection)
*/
@Override
public final ILaunchSpecification getLaunchSpecification(String launchConfigTypeId, ILaunchSelection launchSelection) {
ILaunchSpecification spec = null;
if (isValidLaunchSelection(launchSelection)) {
spec = new LaunchSpecification(launchConfigTypeId, launchSelection.getLaunchMode());
for (ISelectionContext selectionContext : launchSelection.getSelectedContexts()) {
// For launch specifications, all selection contexts needs to be set as preferred
// for full validation.
// otherwise "not preferred" contexts are valid even if they are not for a give
// launch configuration type id.
boolean oldPref = selectionContext.isPreferredContext();
selectionContext.setIsPreferredContext(true);
if (LaunchConfigTypeBindingsManager
.getInstance()
.isValidLaunchConfigType(launchConfigTypeId, launchSelection.getLaunchMode(), selectionContext)) {
spec = addLaunchSpecAttributes(spec, launchConfigTypeId, selectionContext);
}
selectionContext.setIsPreferredContext(oldPref);
}
// If the number of selected contexts is 0, we have to call addLaunchSpecAttributes
// one time to add the selection independent attributes.
if (launchSelection.getSelectedContexts().length == 0) {
spec = addLaunchSpecAttributes(spec, launchConfigTypeId, null);
}
}
return spec;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#getDefaultLaunchName(org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification)
*/
@Override
public String getDefaultLaunchName(ILaunchSpecification launchSpec) {
return Messages.DefaultLaunchManagerDelegate_defaultLaunchName;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#getDefaultLaunchName(org.eclipse.debug.core.ILaunchConfiguration)
*/
@Override
public String getDefaultLaunchName(ILaunchConfiguration launchConfig) {
return Messages.DefaultLaunchManagerDelegate_defaultLaunchName;
}
/**
* Add all needed selections to the launch specification.
* <p>
* Subclasses needs to override and super-call this method!
* <p>
* <b>Note:</b> The selection context can be <code>null</code>. In this case, the method
* implementation is expected to add only selection independent attributes!
*
* @param launchSpec The launch specification to add selections to. Must not be
* <code>null</code>.
* @param launchConfigTypeId The launch configuration type id. Must not be <code>null</code>.
* @param selectionContext The validated selection context with the selection(s) or
* <code>null</code>
*
* @return The launch specification with attributes from the selection context.
*/
protected ILaunchSpecification addLaunchSpecAttributes(ILaunchSpecification launchSpec, String launchConfigTypeId, ISelectionContext selectionContext) {
Assert.isNotNull(launchSpec);
Assert.isNotNull(launchConfigTypeId);
return launchSpec;
}
/**
* Returns the ranking of the launch configuration compared to the launch specification.
* <p>
* If all attributes of the launch specification matches with the corresponding attributes of
* the launch configuration, the ranking should be at least as high as the number of attributes
* in the launch specification. The ranking should grow with every additional attribute value
* that is set to default.
* <p>
* If only a set of attributes matches, the ranking should be less than the number of attributes
* in the launch specification.
* <p>
* If no attribute matches zero should be returned.
*
* @param launchSpec The launch specification the launch configuration should be compared to.
* @param launchConfig The launch configuration to find a ranking for.
* @return The ranking of the launch configuration.
* @throws <code>LaunchServiceException</code> exception when mandatory attributes are missing
*/
private int getLaunchConfigRanking(ILaunchSpecification launchSpec, ILaunchConfiguration launchConfig) throws LaunchServiceException {
int ranking = 0;
int mandatorys = 0;
Map<?, ?> configAttributes = null;
Set<?> configKeys = null;
try {
configAttributes = launchConfig.getAttributes();
configKeys = configAttributes.keySet();
}
catch (Exception e) {
return 0;
}
// Read the launch configuration matching mode from the preferences
int mode = CoreBundleActivator.getScopedPreferences()
.getInt(IPreferenceKeys.PREF_LAUNCH_CONFIG_FIND_CREATE_MODE);
if (launchSpec.getAttribute(IPreferenceKeys.PREF_LAUNCH_CONFIG_FIND_CREATE_MODE, null) instanceof Integer) {
mode = ((Integer) launchSpec
.getAttribute(IPreferenceKeys.PREF_LAUNCH_CONFIG_FIND_CREATE_MODE, null))
.intValue();
}
if (CoreBundleActivator.getTraceHandler()
.isSlotEnabled(0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING)) {
StringBuilder message = new StringBuilder("Ranking launch spec ("); //$NON-NLS-1$
message.append(launchSpec.getLaunchConfigName());
message.append(") vs launch configuration ("); //$NON-NLS-1$
message.append(launchConfig.getName());
message.append("): Matching mode = "); //$NON-NLS-1$
if (mode == IPreferenceKeys.MODE_ALWAYS_NEW) {
message.append(" ALWAYS_NEW "); //$NON-NLS-1$
}
else if (mode == IPreferenceKeys.MODE_FIRST_MATCHING) {
message.append(" FIRST_MATCHING "); //$NON-NLS-1$
}
else if (mode == IPreferenceKeys.MODE_FULL_MATCH_TARGET) {
message.append(" FULL_MATCH_TARGET "); //$NON-NLS-1$
}
else if (mode == IPreferenceKeys.MODE_FULL_MATCH_LAUNCH_CONFIG) {
message.append(" FULL_MATCH_LAUNCH_CONFIG "); //$NON-NLS-1$
}
CoreBundleActivator
.getTraceHandler()
.trace(message.toString(), 0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING, IStatus.INFO, this);
}
for (ILaunchAttribute specAttribute : launchSpec.getAllAttributes()) {
if (!specAttribute.isCreateOnlyAttribute()) {
String key = specAttribute.getKey();
Object specValue = specAttribute.getValue();
Object configValue = configAttributes.get(key);
int match = compareAttributeValues(key, specValue, configValue, launchSpec, launchConfig);
if (CoreBundleActivator.getTraceHandler()
.isSlotEnabled(0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING)) {
StringBuilder message = new StringBuilder("Launch spec attribute '"); //$NON-NLS-1$
message.append(specAttribute.getKey());
message.append("': mandatory = "); //$NON-NLS-1$
message.append(isMandatoryAttribute(key));
message.append("; match = "); //$NON-NLS-1$
if (match == NO_MATCH) {
message.append("NO_MATCH"); //$NON-NLS-1$
}
else if (match == PARTIAL_MATCH) {
message.append("PARTIAL_MATCH"); //$NON-NLS-1$
}
else if (match == FULL_MATCH) {
message.append("FULL_MATCH"); //$NON-NLS-1$
}
if (match != FULL_MATCH) {
message.append("\n\t\tspecValue = "); //$NON-NLS-1$
message.append(specValue != null ? specValue.toString() : "null"); //$NON-NLS-1$
message.append("\n\t\tconfigValue = "); //$NON-NLS-1$
message.append(configValue != null ? configValue.toString() : "null"); //$NON-NLS-1$
}
CoreBundleActivator
.getTraceHandler()
.trace(message.toString(), 0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING, IStatus.INFO, this);
}
if (match == PARTIAL_MATCH && mode == IPreferenceKeys.MODE_FULL_MATCH_LAUNCH_CONFIG) {
return 0;
}
if (match > NO_MATCH) {
int attrRanking = getAttributeRanking(key);
ranking += attrRanking * (attrRanking > 1 ? 4 : 1);
if (match == FULL_MATCH) {
ranking += attrRanking * (attrRanking > 1 ? 2 : 1);
}
configKeys.remove(key);
if (isMandatoryAttribute(key)) {
mandatorys++;
}
}
else {
return 0;
}
}
else {
if (CoreBundleActivator.getTraceHandler()
.isSlotEnabled(0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING)) {
StringBuilder message = new StringBuilder("Skipped launch spec attribute '"); //$NON-NLS-1$
message.append(specAttribute.getKey());
message.append("': is create only attribute"); //$NON-NLS-1$
CoreBundleActivator
.getTraceHandler()
.trace(message.toString(), 0, ITraceIds.TRACE_LAUNCHCONFIGURATIONMATCHING, IStatus.INFO, this);
}
}
}
if (mandatorys < getNumMandatoryAttributes()) {
throw new LaunchServiceException("missing mandatory attribute in ILaunchSpecification", //$NON-NLS-1$
LaunchServiceException.TYPE_MISSING_LAUNCH_SPEC_ATTR);
}
Iterator<?> configIt = configKeys.iterator();
while (configIt.hasNext()) {
String key = (String) configIt.next();
Object specValue = launchSpec.getAttribute(key, null);
Object configValue = configAttributes.get(key);
int match = compareAttributeValues(key, specValue, configValue, launchSpec, launchConfig);
if (match > NO_MATCH) {
int attrRanking = getAttributeRanking(key);
ranking += attrRanking * (attrRanking > 1 ? 4 : 1);
if (match == FULL_MATCH) {
ranking += attrRanking * (attrRanking > 1 ? 2 : 1);
}
}
}
return ranking;
}
/**
* Returns the number of defined attributes for this launch manager delegate.
*
* @see #getAttributeRanking(String)
*/
protected int getNumAttributes() {
return 0;
}
/**
* Returns the list of mandatory attributes for a launch specification handled by this launch
* manager delegate.
* <p>
* The returned value must not be <code>null</code>, if no attributes are mandatory, an empty
* list should be returned.
*
* @see #getAttributeRanking(String)
*/
protected List<String> getMandatoryAttributes() {
return Collections.emptyList();
}
private boolean validateLaunchSpecification(ILaunchSpecification launchSpec) {
boolean valid = true;
if (launchSpec == null || !launchSpec.isValid()) {
return false;
}
for (String attribute : getMandatoryAttributes()) {
if (!launchSpec.hasAttribute(attribute)) {
valid = false;
break;
}
}
launchSpec.setIsValid(valid);
return valid;
}
/**
* Method for basic launch selection validations like checking the number of project or target
* contexts.
* <p>
* The default implementation returns always <code>true</code>.
*
* @param launchSelection The launch selection to check.
* @return <code>True</code> if the launch selection is valid, <code>false</code> otherwise.
*/
protected boolean isValidLaunchSelection(ILaunchSelection launchSelection) {
return true;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#validate(java.lang.String, org.eclipse.debug.core.ILaunchConfiguration)
*/
@Override
public void validate(String launchMode, ILaunchConfiguration launchConfig) throws LaunchServiceException {
StringBuilder missingAttributes = new StringBuilder();
for (String attribute : getMandatoryAttributes()) {
if (!isValidAttribute(attribute, launchConfig, launchMode)) {
if (missingAttributes.length() == 0) {
missingAttributes.append(attribute);
} else {
missingAttributes.append(", "); //$NON-NLS-1$
missingAttributes.append(attribute);
}
}
}
if (missingAttributes.length() > 0) {
throw new LaunchServiceException("Missing launch configuration attributes: " + '\n' + missingAttributes.toString(), LaunchServiceException.TYPE_MISSING_LAUNCH_CONFIG_ATTR); //$NON-NLS-1$
}
}
/**
* Validate a single attribute for a given launch configuration and a launch mode. This method
* needs to be overwritten when contributing new launch modes which does not need all attributes.
*
* @param attributeKey The attribute key.
* @param launchConfig The launch configuration.
* @param launchMode The launch mode.
*
* @return <code>True</code>, if the attribute value is valid.
*/
protected boolean isValidAttribute(String attributeKey, ILaunchConfiguration launchConfig, String launchMode) {
try {
if (launchConfig == null || !launchConfig.hasAttribute(attributeKey)) {
return false;
}
}
catch (CoreException e) {
return false;
}
return true;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#validate(org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification)
*/
@Override
public void validate(ILaunchSpecification launchSpec) throws LaunchServiceException {
StringBuilder missingAttributes = new StringBuilder();
for (String attribute : getMandatoryAttributes()) {
if (launchSpec == null || !launchSpec.hasAttribute(attribute)) {
// Remember the missing attribute for adding the list to the exception.
if (missingAttributes.length() == 0) {
missingAttributes.append(attribute);
} else {
missingAttributes.append(", "); //$NON-NLS-1$
missingAttributes.append(attribute);
}
}
}
if (missingAttributes.length() > 0) {
throw new LaunchServiceException("Missing launch specification attributes: " + '\n' + missingAttributes.toString(), LaunchServiceException.TYPE_MISSING_LAUNCH_SPEC_ATTR); //$NON-NLS-1$
}
}
/**
* Returns the number of defined mandatory attributes.
*
* @see #getMandatoryAttributes()
* @see #getAttributeRanking(String)
*/
protected final int getNumMandatoryAttributes() {
return getMandatoryAttributes().size();
}
/**
* Returns true if the attribute key is in the list of mandatory attributes.
*
* @see #getMandatoryAttributes()
* @see #getAttributeRanking(String)
*/
protected final boolean isMandatoryAttribute(String attributeKey) {
return getMandatoryAttributes().contains(attributeKey);
}
/**
* Returns the ranking for the given attribute key.
* <p>
* The default ranking is 1, ranking of mandatory and other fundamental attributes should be
* coded as <code>2^n</code>.
* <p>
* The more important an attribute is the higher <code>n</code> should be, <code>n</code> should
* never be less than the number of attributes with a lower ranking.
* <p>
* Multiple attributes can have an equal ranking when one attribute can compensate the absence
* of an other attribute with the same ranking.
*
* <pre>
* Example:
*
* Attributes a through f
* Attributes a and b are mandatory, b is more important than a.
* The attributes c and d should be higher prior than e and f, but should have equal ranking.
*
* The ranking looks like the following:
* Attribute Ranking
* b 32 (2^5)
* a 16 (2^4)
* c, d 4 (2^2)
* e, f 1 (2^0)
*
* With this rankings it is not possible to compensate a missing higher prior attribute with
* one or more lower prior attributes.
*
* Additional methods returns the following values for this example:
*
* getNumAttributes() == 6
* getMandatoryAttibutes() == {a, b}
* getNumMandatoryAttributes() == 2
* getFullMatchRanking() >= 48 (the value can be greater than 48 depending
* on the implementation of the launch manager delegate)
* </pre>
*
* @param attributeKey The attribute key for which the ranking should be returned
*/
protected int getAttributeRanking(String attributeKey) {
return 1;
}
/**
* Minimum ranking for a launch configuration to be handled as full match when comparing to a
* launch specification.
* <p>
* Should be overwritten when the method {@link #getAttributeRanking(String)} was overwritten.
*
* @see #getAttributeRanking(String)
*/
protected int getFullMatchRanking() {
return 1;
}
/**
* Compares an attribute value of launch configuration and specification.
*
* If both values are not null, calls {@link #equals(String, Object, Object, ILaunchSpecification, ILaunchConfiguration, String)}
* to compare the values. If one of the values is <code>null</code>, and the not <code>null</code> value is default, <code>true</code>
* is returned. If both values are <code>null</code>, <code>true</code> is returned.
*
* @param attributeKey The attribute key. Must not be <code>null</code>.
* @param specValue The launch specification value.
* @param confValue The launch configuration value.
* @param launchSpec The launch specification which is the source of the <code>specValue</code>. Must not be <code>null</code>.
* @param launchConfig The launch configuration which is the source of the <code>confValue</code>. Must not be <code>null</code>.
* @return NO_MATCH, PARTIAL_MATCH or FULL_MATCH
*/
protected int compareAttributeValues(String attributeKey, Object specValue, Object confValue, ILaunchSpecification launchSpec, ILaunchConfiguration launchConfig) {
Assert.isNotNull(attributeKey);
Assert.isNotNull(launchSpec);
Assert.isNotNull(launchConfig);
// values are equal if both are null
if (specValue == null && confValue == null) {
return FULL_MATCH;
}
// if a value is null, partial match if values are default
else if (specValue == null || confValue == null) {
return isDefaultAttribute(attributeKey, specValue, confValue, launchSpec, launchConfig, launchSpec.getLaunchMode()) ? PARTIAL_MATCH : NO_MATCH;
}
// full match if values are default
else if (isDefaultAttribute(attributeKey, specValue, confValue, launchSpec, launchConfig, launchSpec.getLaunchMode())) {
return FULL_MATCH;
}
// use object.equals as default
else {
Assert.isNotNull(specValue);
Assert.isNotNull(confValue);
return equals(attributeKey, specValue, confValue, launchSpec, launchConfig, launchSpec.getLaunchMode());
}
}
/**
* Compares the attribute value of launch configuration and launch specification.
* <p>
* The handling of null values is implemented in the calling private method
* {@link #compareAttributeValues(String, Object, Object, ILaunchSpecification, ILaunchConfiguration)}.
* When overwriting this method the implementor can be certain both values are not <code>null</code>.
*
* @param attributeKey The attribute key
* @param specValue The launch specification value. Must not be <code>null</code>.
* @param confValue The launch configuration value. Must not be <code>null</code>.
* @param launchSpec The launch specification.
* @param launchConfig The launch configuration which is the source of the <code>confValue</code>.
* @param launchMode The current launch mode.
*
* @return NO_MATCH, PARTIAL_MATCH or FULL_MATCH
*/
protected int equals(String attributeKey, Object specValue, Object confValue, ILaunchSpecification launchSpec, ILaunchConfiguration launchConfig, String launchMode) {
Assert.isNotNull(specValue);
Assert.isNotNull(confValue);
if (ILaunchContextLaunchAttributes.ATTR_LAUNCH_CONTEXTS.equals(attributeKey)) {
// get match of list objects
int match = specValue.equals(confValue) ? FULL_MATCH : NO_MATCH;
// compare objects in the list when they are not already equal
if (match != FULL_MATCH) {
List<IModelNode> confItems = Arrays.asList(LaunchContextsPersistenceDelegate.decodeLaunchContexts(confValue.toString()));
IModelNode[] specItems = LaunchContextsPersistenceDelegate.decodeLaunchContexts(specValue.toString());
int i = 0;
for (IModelNode item : specItems) {
if (confItems.contains(item)) {
// spec object can be found in the configuration
if (match == NO_MATCH) {
// full match on first element in the spec list,
// otherwise partial match
match = (i == 0) ? FULL_MATCH : PARTIAL_MATCH;
}
}
else if (match == FULL_MATCH) {
// reduce full to partial match when spec object wasn't found
match = PARTIAL_MATCH;
}
i++;
}
// reduce full to partial match when list size is not equal
// but all spec values where found in the configuration project list
if (match == FULL_MATCH && specItems.length != confItems.size()) {
match = PARTIAL_MATCH;
}
}
return match;
}
if (IFileTransferLaunchAttributes.ATTR_FILE_TRANSFERS.equals(attributeKey)) {
// get match of list objects
int match = specValue.equals(confValue) ? FULL_MATCH : NO_MATCH;
// compare objects in the list when they are not already equal
if (match != FULL_MATCH) {
List<IFileTransferItem> confItems = Arrays.asList(FileTransfersPersistenceDelegate.decodeFileTransferItems(confValue.toString()));
IFileTransferItem[] specItems = FileTransfersPersistenceDelegate.decodeFileTransferItems(specValue.toString());
int i = 0;
for (IFileTransferItem item : specItems) {
if (confItems.contains(item)) {
// spec object can be found in the configuration
if (match == NO_MATCH) {
// full match on first element in the spec list,
// otherwise partial match
match = (i == 0) ? FULL_MATCH : PARTIAL_MATCH;
}
}
else if (match == FULL_MATCH) {
// reduce full to partial match when spec object wasn't found
match = PARTIAL_MATCH;
}
i++;
}
// reduce full to partial match when list size is not equal
// but all spec values where found in the configuration project list
if (match == FULL_MATCH && specItems.length != confItems.size()) {
match = PARTIAL_MATCH;
}
}
return match;
}
if (IReferencedProjectLaunchAttributes.ATTR_REFERENCED_PROJECTS.equals(attributeKey)) {
// get match of list objects
int match = specValue.equals(confValue) ? FULL_MATCH : NO_MATCH;
// compare objects in the list when they are not already equal
if (match != FULL_MATCH) {
List<IReferencedProjectItem> confItems = Arrays.asList(ReferencedProjectsPersistenceDelegate.decodeReferencedProjectItems(confValue.toString()));
IReferencedProjectItem[] specItems = ReferencedProjectsPersistenceDelegate.decodeReferencedProjectItems(specValue.toString());
int i = 0;
for (IReferencedProjectItem item : specItems) {
if (confItems.contains(item)) {
// spec object can be found in the configuration
if (match == NO_MATCH) {
// full match on first element in the spec list,
// otherwise partial match
match = (i == 0) ? FULL_MATCH : PARTIAL_MATCH;
}
}
else if (match == FULL_MATCH) {
// reduce full to partial match when spec object wasn't found
match = PARTIAL_MATCH;
}
i++;
}
// reduce full to partial match when list size is not equal
// but all spec values where found in the configuration project list
if (match == FULL_MATCH && specItems.length != confItems.size()) {
match = PARTIAL_MATCH;
}
}
return match;
}
return specValue.equals(confValue) ? FULL_MATCH : NO_MATCH;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#showLaunchDialog(int)
*/
@Override
public boolean showLaunchDialog(int situation) {
return true;
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchManagerDelegate#equals(org.eclipse.tcf.te.launch.core.selection.interfaces.ISelectionContext, org.eclipse.tcf.te.launch.core.selection.interfaces.ISelectionContext)
*/
@Override
public boolean equals(ISelectionContext ctx1, ISelectionContext ctx2) {
return (ctx1 == null && ctx2 == null) || (ctx1 != null && ctx1.equals(ctx2));
}
@Override
public String getDescription(ILaunchConfiguration config) {
return config.getName();
}
}