diff options
18 files changed, 1778 insertions, 1434 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/plugin.xml b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/plugin.xml index 3298d7e12..00dcbfdf4 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/plugin.xml +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/plugin.xml @@ -1,125 +1,149 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<?eclipse version="3.4"?>
-<plugin>
-
-<!-- Extension points -->
- <extension-point id="launchConfigTypeBindings" name="%Extension.LaunchConfigTypeBindings.name" schema="schema/launchConfigTypeBindings.exsd"/>
- <extension-point id="launchManagerDelegates" name="%Extension.LaunchManagerDelegates.name" schema="schema/launchManagerDelegates.exsd"/>
-
-<!-- Adapter factory contributions -->
- <extension point="org.eclipse.core.runtime.adapters">
- <factory
- adaptableType="org.eclipse.tcf.te.launch.core.selection.interfaces.ISelectionContext"
- class="org.eclipse.tcf.te.launch.core.adapters.internal.AdapterFactory">
- <adapter type="org.eclipse.core.expressions.IIterable"/>
- <adapter type="org.eclipse.core.expressions.ICountable"/>
- </factory>
- </extension>
-
-<!-- Preference contributions -->
- <extension point="org.eclipse.core.runtime.preferences">
- <initializer
- class="org.eclipse.tcf.te.launch.core.preferences.PreferencesInitializer">
- </initializer>
- </extension>
-
-<!-- Property tester contributions -->
- <extension point="org.eclipse.core.expressions.propertyTesters">
- <propertyTester
- class="org.eclipse.tcf.te.launch.core.bindings.internal.PropertyTester"
- id="org.eclipse.tcf.te.launch.core.PropertyTester"
- namespace="org.eclipse.tcf.te.launch.core"
- properties="launchMode"
- type="org.eclipse.debug.core.ILaunch">
- </propertyTester>
- <propertyTester
- class="org.eclipse.tcf.te.launch.core.bindings.internal.PropertyTester"
- id="org.eclipse.tcf.te.launch.core.PropertyTester"
- namespace="org.eclipse.tcf.te.launch.core"
- properties="isValidLaunchConfigType"
- type="java.lang.Object">
- </propertyTester>
- </extension>
-
-<!-- Launch Step contributions -->
- <extension point="org.eclipse.tcf.te.runtime.stepper.steps">
- <step
- class="org.eclipse.tcf.te.launch.core.steps.RemoveLaunchStep"
- id="org.eclipse.tcf.te.launch.core.removeLaunchStep"
- label="%LaunchStep.RemoveLaunch.name">
- </step>
- </extension>
-
-<!-- Persistence delegate contributions -->
- <extension point="org.eclipse.tcf.te.runtime.persistence.delegates">
- <delegate
- id="org.eclipse.tcf.te.launch.core.persistence.gson.fileTransferItem"
- class="org.eclipse.tcf.te.launch.core.internal.GsonFileTransferItemPersistenceDelegate">
- </delegate>
- <delegate
- id="org.eclipse.tcf.te.launch.core.persistence.gson.referencedProjectItem"
- class="org.eclipse.tcf.te.launch.core.internal.GsonReferencedProjectItemPersistenceDelegate">
- </delegate>
- </extension>
-
-<!-- Persistence delegate bindings contributions -->
- <extension point="org.eclipse.tcf.te.runtime.persistence.bindings">
- <binding
- delegateId="org.eclipse.tcf.te.launch.core.persistence.gson.fileTransferItem"
- id="org.eclipse.tcf.te.launch.core.binding.gson.fileTransferItem">
- <enablement>
- <with variable="container">
- <or>
- <instanceof value="java.lang.String"/>
- <and>
- <instanceof value="java.lang.Class"/>
- <with variable="containerClass">
- <equals value="java.lang.String"/>
- </with>
- </and>
- </or>
- </with>
- <with variable="context">
- <or>
- <instanceof value="org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem"/>
- <and>
- <instanceof value="java.lang.Class"/>
- <with variable="contextClass">
- <equals value="org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem"/>
- </with>
- </and>
- </or>
- </with>
- </enablement>
- </binding>
- <binding
- delegateId="org.eclipse.tcf.te.launch.core.persistence.gson.referencedProjectItem"
- id="org.eclipse.tcf.te.launch.core.binding.gson.referencedProjectItem">
- <enablement>
- <with variable="container">
- <or>
- <instanceof value="java.lang.String"/>
- <and>
- <instanceof value="java.lang.Class"/>
- <with variable="containerClass">
- <equals value="java.lang.String"/>
- </with>
- </and>
- </or>
- </with>
- <with variable="context">
- <or>
- <instanceof value="org.eclipse.tcf.te.launch.core.interfaces.IReferencedProjectItem"/>
- <and>
- <instanceof value="java.lang.Class"/>
- <with variable="contextClass">
- <equals value="org.eclipse.tcf.te.launch.core.interfaces.IReferencedProjectItem"/>
- </with>
- </and>
- </or>
- </with>
- </enablement>
- </binding>
- </extension>
-
-</plugin>
+<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + +<!-- Extension points --> + <extension-point id="launchConfigTypeBindings" name="%Extension.LaunchConfigTypeBindings.name" schema="schema/launchConfigTypeBindings.exsd"/> + <extension-point id="launchManagerDelegates" name="%Extension.LaunchManagerDelegates.name" schema="schema/launchManagerDelegates.exsd"/> + +<!-- Adapter factory contributions --> + <extension point="org.eclipse.core.runtime.adapters"> + <factory + adaptableType="org.eclipse.tcf.te.launch.core.selection.interfaces.ISelectionContext" + class="org.eclipse.tcf.te.launch.core.adapters.internal.AdapterFactory"> + <adapter type="org.eclipse.core.expressions.IIterable"/> + <adapter type="org.eclipse.core.expressions.ICountable"/> + </factory> + </extension> + +<!-- Preference contributions --> + <extension point="org.eclipse.core.runtime.preferences"> + <initializer + class="org.eclipse.tcf.te.launch.core.preferences.PreferencesInitializer"> + </initializer> + </extension> + +<!-- Property tester contributions --> + <extension point="org.eclipse.core.expressions.propertyTesters"> + <propertyTester + class="org.eclipse.tcf.te.launch.core.bindings.internal.PropertyTester" + id="org.eclipse.tcf.te.launch.core.PropertyTester" + namespace="org.eclipse.tcf.te.launch.core" + properties="launchMode" + type="org.eclipse.debug.core.ILaunch"> + </propertyTester> + <propertyTester + class="org.eclipse.tcf.te.launch.core.bindings.internal.PropertyTester" + id="org.eclipse.tcf.te.launch.core.PropertyTester" + namespace="org.eclipse.tcf.te.launch.core" + properties="isValidLaunchConfigType" + type="java.lang.Object"> + </propertyTester> + </extension> + +<!-- Launch Step contributions --> + <extension point="org.eclipse.tcf.te.runtime.stepper.steps"> + <step + class="org.eclipse.tcf.te.launch.core.steps.RemoveLaunchStep" + id="org.eclipse.tcf.te.launch.core.removeLaunchStep" + label="%LaunchStep.RemoveLaunch.name"> + </step> + </extension> + +<!-- Persistence delegate contributions --> + <extension point="org.eclipse.tcf.te.runtime.persistence.delegates"> + <delegate + id="org.eclipse.tcf.te.launch.core.persistence.gson.referencedProjectItem" + class="org.eclipse.tcf.te.launch.core.internal.GsonReferencedProjectItemPersistenceDelegate"> + </delegate> + <delegate + id="org.eclipse.tcf.te.launch.core.persistence.gson.fileTransferItem" + class="org.eclipse.tcf.te.launch.core.internal.GsonFileTransferItemPersistenceDelegate"> + </delegate> + <delegate + id="org.eclipse.tcf.te.launch.core.persistence.gson.launchConfigAttributes" + class="org.eclipse.tcf.te.launch.core.internal.GsonLaunchConfigAttributesPersistenceDelegate"> + </delegate> + </extension> + +<!-- Persistence delegate bindings contributions --> + <extension point="org.eclipse.tcf.te.runtime.persistence.bindings"> + <binding + delegateId="org.eclipse.tcf.te.launch.core.persistence.gson.fileTransferItem" + id="org.eclipse.tcf.te.launch.core.binding.gson.fileTransferItem"> + <enablement> + <with variable="container"> + <or> + <instanceof value="java.lang.String"/> + <and> + <instanceof value="java.lang.Class"/> + <with variable="containerClass"> + <equals value="java.lang.String"/> + </with> + </and> + </or> + </with> + <with variable="context"> + <or> + <instanceof value="org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem"/> + <and> + <instanceof value="java.lang.Class"/> + <with variable="contextClass"> + <equals value="org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem"/> + </with> + </and> + </or> + </with> + </enablement> + </binding> + <binding + delegateId="org.eclipse.tcf.te.launch.core.persistence.gson.referencedProjectItem" + id="org.eclipse.tcf.te.launch.core.binding.gson.referencedProjectItem"> + <enablement> + <with variable="container"> + <or> + <instanceof value="java.lang.String"/> + <and> + <instanceof value="java.lang.Class"/> + <with variable="containerClass"> + <equals value="java.lang.String"/> + </with> + </and> + </or> + </with> + <with variable="context"> + <or> + <instanceof value="org.eclipse.tcf.te.launch.core.interfaces.IReferencedProjectItem"/> + <and> + <instanceof value="java.lang.Class"/> + <with variable="contextClass"> + <equals value="org.eclipse.tcf.te.launch.core.interfaces.IReferencedProjectItem"/> + </with> + </and> + </or> + </with> + </enablement> + </binding> + <binding + delegateId="org.eclipse.tcf.te.launch.core.persistence.gson.launchConfigAttributes" + id="org.eclipse.tcf.te.launch.core.binding.gson.launchConfigAttributes"> + <enablement> + <with variable="container"> + <or> + <instanceof value="java.lang.String"/> + <and> + <instanceof value="java.lang.Class"/> + <with variable="containerClass"> + <equals value="java.lang.String"/> + </with> + </and> + </or> + </with> + <with variable="context"> + <instanceof value="org.eclipse.debug.core.ILaunchConfiguration"/> + </with> + </enablement> + </binding> + </extension> + +</plugin> diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/internal/GsonLaunchSpecPersistenceDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/internal/GsonLaunchConfigAttributesPersistenceDelegate.java index e7f1a854c..01ac3fc7a 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/internal/GsonLaunchSpecPersistenceDelegate.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/internal/GsonLaunchConfigAttributesPersistenceDelegate.java @@ -13,19 +13,20 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.tcf.te.runtime.persistence.GsonMapPersistenceDelegate; -import org.eclipse.tcf.te.runtime.services.interfaces.filetransfer.IFileTransferItem; /** - * Launch Specification to string delegate implementation. + * Launch configuration to string delegate implementation. */ -public class GsonLaunchSpecPersistenceDelegate extends GsonMapPersistenceDelegate { +public class GsonLaunchConfigAttributesPersistenceDelegate extends GsonMapPersistenceDelegate { /** * Constructor. */ - public GsonLaunchSpecPersistenceDelegate() { + public GsonLaunchConfigAttributesPersistenceDelegate() { super(); } @@ -34,7 +35,7 @@ public class GsonLaunchSpecPersistenceDelegate extends GsonMapPersistenceDelegat */ @Override public Class<?> getPersistedClass(Object context) { - return ILaunchSpecification.class; + return ILaunchConfiguration.class; } /* (non-Javadoc) @@ -42,6 +43,13 @@ public class GsonLaunchSpecPersistenceDelegate extends GsonMapPersistenceDelegat */ @Override protected Map<String, Object> toMap(final Object context) throws IOException { + if (context instanceof ILaunchConfiguration) { + try { + return ((ILaunchConfiguration)context).getAttributes(); + } + catch (CoreException e) { + } + } return new HashMap<String, Object>(); } @@ -50,22 +58,9 @@ public class GsonLaunchSpecPersistenceDelegate extends GsonMapPersistenceDelegat */ @Override protected Object fromMap(Map<String, Object> map, Object context) throws IOException { - return null; - } - - /** - * Get a file transfer item from the given context. - * - * @param context The context. Must not be <code>null</code>. - * @return The file transfer item or <code>null</code>. - */ - protected IFileTransferItem getFileTransferItem(Object context) { - IFileTransferItem item = null; - - if (context instanceof IFileTransferItem) { - item = (IFileTransferItem)context; + if (context instanceof ILaunchConfigurationWorkingCopy) { + ((ILaunchConfigurationWorkingCopy)context).setAttributes(map); } - - return item; + return context; } } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/lm/delegates/DefaultLaunchManagerDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/lm/delegates/DefaultLaunchManagerDelegate.java index 885a96fb7..0de4061d6 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/lm/delegates/DefaultLaunchManagerDelegate.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.core/src/org/eclipse/tcf/te/launch/core/lm/delegates/DefaultLaunchManagerDelegate.java @@ -1,779 +1,806 @@ -/*******************************************************************************
- * Copyright (c) 2012 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.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();
- }
-
- /* (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 = 0;
- 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 >= 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();
- }
-}
+/******************************************************************************* + * Copyright (c) 2012 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.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()) { + Object value = attribute.getValue(); + if (value instanceof String) { + wc.setAttribute(attribute.getKey(), (String)value); + } + else if (value instanceof List) { + wc.setAttribute(attribute.getKey(), (List<?>)value); + } + else if (value instanceof Map) { + wc.setAttribute(attribute.getKey(), (Map<?,?>)value); + } + else if (value instanceof Set) { + wc.setAttribute(attribute.getKey(), (Set<?>)value); + } + else if (value instanceof Boolean) { + wc.setAttribute(attribute.getKey(), ((Boolean)value).booleanValue()); + } + else if (value instanceof Number) { + wc.setAttribute(attribute.getKey(), ((Number)value).intValue()); + } + else { + throw new IllegalArgumentException("Unknown attribute type " + value.getClass().getName() + "(" + value.toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + } + } + + /* (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 = 0; + 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 >= 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(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/plugin.properties b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/plugin.properties index 32a4fea8e..1a0bc4232 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/plugin.properties +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/plugin.properties @@ -39,8 +39,6 @@ FileTransfers.propertyTab.name=File Transfers General.propertyTab.name=General -SourceLookupEditorPage.name=Source - # ***** Menu Contributions ***** New.menu.name=New diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/plugin.xml b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/plugin.xml index 2e7063b85..d8f860b6c 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/plugin.xml +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/plugin.xml @@ -36,12 +36,6 @@ icon="icons/obj16/launches_root.gif" id="org.eclipse.tcf.te.launch.ui.LaunchEditorPage"> </editorPage> - - <editorPage - class="org.eclipse.tcf.te.launch.ui.editor.SourceLookupEditorPage" - name="%SourceLookupEditorPage.name" - id="org.eclipse.tcf.te.launch.ui.SourceLookupEditorPage"> - </editorPage> </extension> <!-- Navigator viewer contributions --> diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/editor/AbstractLaunchTabContainerEditorPage.java b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/editor/AbstractLaunchTabContainerEditorPage.java index de7194fff..0c1cc3a14 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/editor/AbstractLaunchTabContainerEditorPage.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/editor/AbstractLaunchTabContainerEditorPage.java @@ -21,6 +21,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.tcf.te.launch.ui.tabs.AbstractFormsLaunchConfigurationTab; import org.eclipse.tcf.te.ui.forms.CustomFormToolkit; import org.eclipse.tcf.te.ui.views.editor.pages.AbstractCustomFormToolkitEditorPage; +import org.eclipse.ui.forms.AbstractFormPart; /** * Abstract editor page implementation serving as container for a launch tab. @@ -29,6 +30,8 @@ public abstract class AbstractLaunchTabContainerEditorPage extends AbstractCusto // Reference to the launch configuration tab private final AbstractLaunchConfigurationTab launchTab; + boolean isDirty = false; + /** * Constructor. */ @@ -62,7 +65,7 @@ public abstract class AbstractLaunchTabContainerEditorPage extends AbstractCusto @Override public void dispose() { launchTab.dispose(); - super.dispose(); + super.dispose(); } /* (non-Javadoc) @@ -70,14 +73,14 @@ public abstract class AbstractLaunchTabContainerEditorPage extends AbstractCusto */ @Override protected String getContextHelpId() { - return launchTab.getHelpContextId(); + return launchTab.getHelpContextId(); } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.views.editor.pages.AbstractCustomFormToolkitEditorPage#getFormTitle() */ @Override - protected String getFormTitle() { + protected String getFormTitle() { return launchTab.getName(); } @@ -86,7 +89,15 @@ public abstract class AbstractLaunchTabContainerEditorPage extends AbstractCusto */ @Override protected Image getFormImage() { - return launchTab.getImage(); + return launchTab.getImage(); + } + + /** + * Set the dirty state for this editor page. + * @param dirty The dirty state. + */ + public void setDirty(boolean dirty) { + isDirty = dirty; } /* (non-Javadoc) @@ -104,6 +115,22 @@ public abstract class AbstractLaunchTabContainerEditorPage extends AbstractCusto launchTab.createControl(parent); } + getManagedForm().addPart(new AbstractFormPart() { + @Override + public boolean isDirty() { + return isDirty; + } + + @Override + public void commit(boolean onSave) { + super.commit(onSave); + + if (onSave) { + extractData(); + } + } + }); + // Fix the background color of the launch tab controls Color bg = parent.getBackground(); Control[] children = parent.getChildren(); @@ -113,6 +140,25 @@ public abstract class AbstractLaunchTabContainerEditorPage extends AbstractCusto } /** + * Set the data to the page. + * @param input The editor input. + * @return <code>true</code> if data was set. + */ + public abstract boolean setupData(Object input); + + /** + * Extract the data from the page. + * @return <code>true</code> if data was set. + */ + public abstract boolean extractData(); + + @Override + public void setActive(boolean active) { + super.setActive(active); + setupData(getEditorInput()); + } + + /** * Set the background color of the given controls and their children * to the given color. * @@ -123,12 +169,18 @@ public abstract class AbstractLaunchTabContainerEditorPage extends AbstractCusto Assert.isNotNull(controls); Assert.isNotNull(bg); for (Control c : controls) { - if (!(c instanceof Composite) && !(c instanceof Label) && !(c instanceof Button)) continue; + if (!(c instanceof Composite) && !(c instanceof Label) && !(c instanceof Button)) { + continue; + } if (c instanceof Button) { int style = ((Button)c).getStyle(); - if ((style & SWT.RADIO) == 0 && (style & SWT.CHECK) == 0) continue; + if ((style & SWT.RADIO) == 0 && (style & SWT.CHECK) == 0) { + continue; + } + } + if (!bg.equals(c.getBackground())) { + c.setBackground(bg); } - if (!bg.equals(c.getBackground())) c.setBackground(bg); if (c instanceof Composite) { Control[] children = ((Composite)c).getChildren(); if (children != null && children.length > 0) { diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/plugin.xml b/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/plugin.xml index 5172d7db4..6a6b59149 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/plugin.xml +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/plugin.xml @@ -30,25 +30,29 @@ delegateId="org.eclipse.tcf.te.runtime.persistence.gson.map" id="org.eclipse.tcf.te.runtime.persistence.binding.gson.map"> <enablement> - <or> - <with variable="container"> - <or> - <instanceof value="java.net.URI"/> - <instanceof value="java.lang.String"/> - </or> - </with> - <with variable="containerClass"> - <equals value="java.lang.String"/> - </with> - </or> - <or> - <with variable="context"> + <with variable="container"> + <or> + <instanceof value="java.net.URI"/> + <instanceof value="java.lang.String"/> + <and> + <instanceof value="java.lang.Class"/> + <with variable="containerClass"> + <equals value="java.lang.String"/> + </with> + </and> + </or> + </with> + <with variable="context"> + <or> <instanceof value="java.util.Map"/> - </with> - <with variable="contextClass"> - <equals value="java.util.Map"/> - </with> - </or> + <and> + <instanceof value="java.lang.Class"/> + <with variable="contextClass"> + <equals value="java.util.Map"/> + </with> + </and> + </or> + </with> </enablement> </binding> </extension> diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/src/org/eclipse/tcf/te/runtime/persistence/GsonMapPersistenceDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/src/org/eclipse/tcf/te/runtime/persistence/GsonMapPersistenceDelegate.java index 09e72bdf1..854c33209 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/src/org/eclipse/tcf/te/runtime/persistence/GsonMapPersistenceDelegate.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/src/org/eclipse/tcf/te/runtime/persistence/GsonMapPersistenceDelegate.java @@ -1,268 +1,268 @@ -/*******************************************************************************
- * Copyright (c) 2012 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.runtime.persistence;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.eclipse.core.runtime.Assert;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.tcf.te.runtime.extensions.ExecutableExtension;
-import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer;
-import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate;
-import org.eclipse.tcf.te.runtime.properties.PropertiesContainer;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-/**
- * GsonMapPersistenceDelegate
- */
-public class GsonMapPersistenceDelegate extends ExecutableExtension implements IPersistenceDelegate {
-
- private final String defaultFileExtension;
-
- /**
- * Constructor.
- */
- public GsonMapPersistenceDelegate() {
- this("json"); //$NON-NLS-1$
- }
-
- /**
- * Constructor.
- */
- public GsonMapPersistenceDelegate(String defaultFileExtension) {
- super();
- Assert.isNotNull(defaultFileExtension);
- this.defaultFileExtension = defaultFileExtension;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#getPersistedClass(java.lang.Object)
- */
- @Override
- public Class<?> getPersistedClass(Object context) {
- return Map.class;
- }
-
- /**
- * Return the default file extension if container is an URI.
- */
- protected String getDefaultFileExtension() {
- return defaultFileExtension;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#write(java.lang.Object, java.lang.Object, java.lang.String)
- */
- @Override
- public Object write(Object context, Object container, String key) throws IOException {
- Assert.isNotNull(context);
- Assert.isNotNull(container);
-
- if (container instanceof URI) {
- URI uri = (URI)container;
-
- // Only "file:" URIs are supported
- if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$
- throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- // Create the file object from the given URI
- File file = new File(uri.normalize());
-
- // The file must be absolute
- if (!file.isAbsolute()) {
- throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$
- }
-
- // If the file defaultFileExtension is no set, default to "properties"
- IPath path = new Path(file.getCanonicalPath());
- if (path.getFileExtension() == null) {
- file = path.addFileExtension(getDefaultFileExtension()).toFile();
- }
-
- Writer writer = null;
- try {
- writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); //$NON-NLS-1$
- Gson gson = new GsonBuilder().setPrettyPrinting().create();
- gson.toJson(toMap(context), Map.class, writer);
- } finally {
- if (writer != null) {
- writer.close();
- }
- }
- }
- else if (container instanceof String || String.class.equals(container)) {
- Gson gson = new GsonBuilder().create();
- container = gson.toJson(toMap(context));
- }
-
- return container;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#read(java.lang.Object, java.lang.Object, java.lang.String)
- */
- @Override
- public Object read(Object context, Object container, String key) throws IOException {
- Assert.isNotNull(container);
-
- Gson gson = new GsonBuilder().create();
- Map<String, Object> data = null;
-
- if (container instanceof URI) {
- URI uri = (URI)container;
-
- // Only "file:" URIs are supported
- if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$
- throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- // Create the file object from the given URI
- File file = new File(uri.normalize());
-
- // The file must be absolute
- if (!file.isAbsolute()) {
- throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$
- }
-
- Reader reader = null;
- try {
- reader = new InputStreamReader(new FileInputStream(file), "UTF-8"); //$NON-NLS-1$
- data = gson.fromJson(reader, Map.class);
- } finally {
- if (reader != null) {
- reader.close();
- }
- }
- }
- else if (container instanceof String) {
- data = gson.fromJson((String)container, Map.class);
- }
-
- return data != null ? fromMap(data, context) : context;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#delete(java.lang.Object, java.lang.Object, java.lang.String)
- */
- @Override
- public boolean delete(Object context, Object container, String key) throws IOException {
- Assert.isNotNull(container);
-
- if (container instanceof URI) {
- URI uri = (URI)container;
-
- // Only "file:" URIs are supported
- if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$
- throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- // Create the file object from the given URI
- File file = new File(uri.normalize());
-
- // The file must be absolute
- if (!file.isAbsolute()) {
- throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$
- }
-
- // If the file defaultFileExtension is no set, default to "properties"
- IPath path = new Path(file.getCanonicalPath());
- if (path.getFileExtension() == null) {
- file = path.addFileExtension(getDefaultFileExtension()).toFile();
- }
-
- return file.delete();
- }
-
- return false;
- }
-
- /**
- * Convert the given context to map.
- *
- * @param context The context. Must not be <code>null</code>.
- * @return Map representing the context.
- *
- * @throws IOException
- */
- @SuppressWarnings("unchecked")
- protected Map<String, Object> toMap(final Object context) throws IOException {
- Map<String, Object> result = new HashMap<String,Object>();
-
- Map<String,Object> attrs = null;
- if (context instanceof Map) {
- attrs = (Map<String, Object>)context;
- }
- else if (context instanceof IPropertiesContainer) {
- IPropertiesContainer container = (IPropertiesContainer)context;
- attrs = new HashMap<String,Object>(container.getProperties());
- }
-
- if (attrs != null) {
- for (Entry<String, Object> entry : attrs.entrySet()) {
- if (!entry.getKey().endsWith(".transient")) { //$NON-NLS-1$
- result.put(entry.getKey(), entry.getValue());
- }
- }
- }
-
- return result;
- }
-
- /**
- * Convert a map into the needed context object.
- *
- * @param map The map representing the context. Must not be <code>null</code>.
- * @param context The context to put the map values in or <code>null</code>.
- * @return The context object.
- *
- * @throws IOException
- */
- protected Object fromMap(Map<String,Object> map, Object context) throws IOException {
- if (context == null || Map.class.equals(context.getClass())) {
- return map;
- }
- else if (context instanceof Map) {
- @SuppressWarnings({ "rawtypes", "unchecked" })
- Map<String,Object> newMap = new HashMap<String, Object>((Map)context);
- newMap.putAll(map);
- return newMap;
- }
- else if (IPropertiesContainer.class.equals(context.getClass())) {
- IPropertiesContainer container = new PropertiesContainer();
- container.setProperties(map);
-
- return container;
- }
- else if (context instanceof IPropertiesContainer) {
- IPropertiesContainer container = (IPropertiesContainer)context;
- container.setProperties(map);
-
- return container;
- }
-
- return null;
- }
-}
+/******************************************************************************* + * Copyright (c) 2012 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.runtime.persistence; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.tcf.te.runtime.extensions.ExecutableExtension; +import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; +import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate; +import org.eclipse.tcf.te.runtime.properties.PropertiesContainer; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * GsonMapPersistenceDelegate + */ +public class GsonMapPersistenceDelegate extends ExecutableExtension implements IPersistenceDelegate { + + private final String defaultFileExtension; + + /** + * Constructor. + */ + public GsonMapPersistenceDelegate() { + this("json"); //$NON-NLS-1$ + } + + /** + * Constructor. + */ + public GsonMapPersistenceDelegate(String defaultFileExtension) { + super(); + Assert.isNotNull(defaultFileExtension); + this.defaultFileExtension = defaultFileExtension; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#getPersistedClass(java.lang.Object) + */ + @Override + public Class<?> getPersistedClass(Object context) { + return Map.class; + } + + /** + * Return the default file extension if container is an URI. + */ + protected String getDefaultFileExtension() { + return defaultFileExtension; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#write(java.lang.Object, java.lang.Object, java.lang.String) + */ + @Override + public Object write(Object context, Object container, String key) throws IOException { + Assert.isNotNull(context); + Assert.isNotNull(container); + + if (container instanceof URI) { + URI uri = (URI)container; + + // Only "file:" URIs are supported + if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$ + throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Create the file object from the given URI + File file = new File(uri.normalize()); + + // The file must be absolute + if (!file.isAbsolute()) { + throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$ + } + + // If the file defaultFileExtension is no set, default to "properties" + IPath path = new Path(file.getCanonicalPath()); + if (path.getFileExtension() == null) { + file = path.addFileExtension(getDefaultFileExtension()).toFile(); + } + + Writer writer = null; + try { + writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); //$NON-NLS-1$ + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + gson.toJson(toMap(context), Map.class, writer); + } finally { + if (writer != null) { + writer.close(); + } + } + } + else if (container instanceof String || String.class.equals(container)) { + Gson gson = new GsonBuilder().create(); + container = gson.toJson(toMap(context)); + } + + return container; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#read(java.lang.Object, java.lang.Object, java.lang.String) + */ + @Override + public Object read(Object context, Object container, String key) throws IOException { + Assert.isNotNull(container); + + Gson gson = new GsonBuilder().create(); + Map<String, Object> data = null; + + if (container instanceof URI) { + URI uri = (URI)container; + + // Only "file:" URIs are supported + if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$ + throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Create the file object from the given URI + File file = new File(uri.normalize()); + + // The file must be absolute + if (!file.isAbsolute()) { + throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$ + } + + Reader reader = null; + try { + reader = new InputStreamReader(new FileInputStream(file), "UTF-8"); //$NON-NLS-1$ + data = gson.fromJson(reader, Map.class); + } finally { + if (reader != null) { + reader.close(); + } + } + } + else if (container instanceof String) { + data = gson.fromJson((String)container, Map.class); + } + + return data != null ? fromMap(data, context) : context; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate#delete(java.lang.Object, java.lang.Object, java.lang.String) + */ + @Override + public boolean delete(Object context, Object container, String key) throws IOException { + Assert.isNotNull(container); + + if (container instanceof URI) { + URI uri = (URI)container; + + // Only "file:" URIs are supported + if (!"file".equalsIgnoreCase(uri.getScheme())) { //$NON-NLS-1$ + throw new IOException("Unsupported URI schema '" + uri.getScheme() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Create the file object from the given URI + File file = new File(uri.normalize()); + + // The file must be absolute + if (!file.isAbsolute()) { + throw new IOException("URI must denote an absolute file path."); //$NON-NLS-1$ + } + + // If the file defaultFileExtension is no set, default to "properties" + IPath path = new Path(file.getCanonicalPath()); + if (path.getFileExtension() == null) { + file = path.addFileExtension(getDefaultFileExtension()).toFile(); + } + + return file.delete(); + } + + return false; + } + + /** + * Convert the given context to map. + * + * @param context The context. Must not be <code>null</code>. + * @return Map representing the context. + * + * @throws IOException + */ + @SuppressWarnings("unchecked") + protected Map<String, Object> toMap(final Object context) throws IOException { + Map<String, Object> result = new HashMap<String,Object>(); + + Map<String,Object> attrs = null; + if (context instanceof Map) { + attrs = (Map<String, Object>)context; + } + else if (context instanceof IPropertiesContainer) { + IPropertiesContainer container = (IPropertiesContainer)context; + attrs = new HashMap<String,Object>(container.getProperties()); + } + + if (attrs != null) { + for (Entry<String, Object> entry : attrs.entrySet()) { + if (!entry.getKey().endsWith(".transient")) { //$NON-NLS-1$ + result.put(entry.getKey(), entry.getValue()); + } + } + } + + return result; + } + + /** + * Convert a map into the needed context object. + * + * @param map The map representing the context. Must not be <code>null</code>. + * @param context The context to put the map values in or <code>null</code>. + * @return The context object. + * + * @throws IOException + */ + protected Object fromMap(Map<String,Object> map, Object context) throws IOException { + if (context == null || (context instanceof Class && ((Class<?>)context).isInstance(map))) { + return map; + } + else if (context instanceof Map) { + @SuppressWarnings({ "rawtypes", "unchecked" }) + Map<String,Object> newMap = new HashMap<String, Object>((Map)context); + newMap.putAll(map); + return newMap; + } + else if (IPropertiesContainer.class.equals(context.getClass())) { + IPropertiesContainer container = new PropertiesContainer(); + container.setProperties(map); + + return container; + } + else if (context instanceof IPropertiesContainer) { + IPropertiesContainer container = (IPropertiesContainer)context; + container.setProperties(map); + + return container; + } + + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/src/org/eclipse/tcf/te/runtime/persistence/internal/PersistenceDelegateBindingExtensionPointManager.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/src/org/eclipse/tcf/te/runtime/persistence/internal/PersistenceDelegateBindingExtensionPointManager.java index 165dbbd8a..2e25b1cc1 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/src/org/eclipse/tcf/te/runtime/persistence/internal/PersistenceDelegateBindingExtensionPointManager.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.persistence/src/org/eclipse/tcf/te/runtime/persistence/internal/PersistenceDelegateBindingExtensionPointManager.java @@ -1,182 +1,188 @@ -/*******************************************************************************
- * Copyright (c) 2011, 2012 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.runtime.persistence.internal;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.eclipse.core.expressions.EvaluationContext;
-import org.eclipse.core.expressions.EvaluationResult;
-import org.eclipse.core.expressions.Expression;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager;
-import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
-import org.eclipse.tcf.te.runtime.persistence.activator.CoreBundleActivator;
-
-
-/**
- */
-public class PersistenceDelegateBindingExtensionPointManager extends AbstractExtensionPointManager<PersistenceDelegateBinding> {
-
- /*
- * Thread save singleton instance creation.
- */
- private static class LazyInstance {
- public static PersistenceDelegateBindingExtensionPointManager instance = new PersistenceDelegateBindingExtensionPointManager();
- }
-
- /**
- * Constructor.
- */
- PersistenceDelegateBindingExtensionPointManager() {
- super();
- }
-
- /**
- * Returns the singleton instance of the extension point manager.
- */
- public static PersistenceDelegateBindingExtensionPointManager getInstance() {
- return LazyInstance.instance;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getExtensionPointId()
- */
- @Override
- protected String getExtensionPointId() {
- return "org.eclipse.tcf.te.runtime.persistence.bindings"; //$NON-NLS-1$
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getConfigurationElementName()
- */
- @Override
- protected String getConfigurationElementName() {
- return "binding"; //$NON-NLS-1$
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#doCreateExtensionProxy(org.eclipse.core.runtime.IConfigurationElement)
- */
- @Override
- protected ExecutableExtensionProxy<PersistenceDelegateBinding> doCreateExtensionProxy(IConfigurationElement element) throws CoreException {
- return new ExecutableExtensionProxy<PersistenceDelegateBinding>(element) {
- /* (non-Javadoc)
- * @see org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy#newInstance()
- */
- @Override
- public PersistenceDelegateBinding newInstance() {
- PersistenceDelegateBinding instance = new PersistenceDelegateBinding();
- try {
- instance.setInitializationData(getConfigurationElement(), null, null);
- } catch (CoreException e) {
- IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
- e.getLocalizedMessage(), e);
- Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
- }
- return instance;
- }
- };
- }
-
- /**
- * Returns the applicable persistence delegate bindings for the given delegate context.
- *
- * @param context The delegate context or <code>null</code>.
- * @return The list of applicable editor page bindings or an empty array.
- */
- public PersistenceDelegateBinding[] getApplicableBindings(Object context, Object container) {
- List<PersistenceDelegateBinding> applicable = new ArrayList<PersistenceDelegateBinding>();
-
- for (PersistenceDelegateBinding binding : getBindings()) {
- Expression enablement = binding.getEnablement();
-
- // The binding is applicable by default if no expression is specified.
- boolean isApplicable = enablement == null;
-
- if (enablement != null) {
- if (context != null) {
- // Set the default variable to the delegate context.
- EvaluationContext evalContext = new EvaluationContext(null, context);
- evalContext.addVariable("context", context); //$NON-NLS-1$
- if (context instanceof Class) {
- evalContext.addVariable("contextClass", ((Class<?>)context).getName()); //$NON-NLS-1$
- }
- evalContext.addVariable("container", container); //$NON-NLS-1$
- if (container instanceof Class) {
- evalContext.addVariable("containerClass", ((Class<?>)container).getName()); //$NON-NLS-1$
- }
- // Allow plugin activation
- evalContext.setAllowPluginActivation(true);
- // Evaluate the expression
- try {
- isApplicable = enablement.evaluate(evalContext).equals(EvaluationResult.TRUE);
- } catch (CoreException e) {
- IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(),
- e.getLocalizedMessage(), e);
- Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
- }
- } else {
- // The enablement is false by definition if no delegate context is given.
- isApplicable = false;
- }
- }
-
- // Add the binding if applicable
- if (isApplicable) {
- applicable.add(binding);
- }
- }
-
- return applicable.toArray(new PersistenceDelegateBinding[applicable.size()]);
- }
-
- /**
- * Returns the list of all contributed persistence delegate bindings.
- *
- * @return The list of contributed persistence delegate bindings, or an empty array.
- */
- public PersistenceDelegateBinding[] getBindings() {
- List<PersistenceDelegateBinding> contributions = new ArrayList<PersistenceDelegateBinding>();
- Collection<ExecutableExtensionProxy<PersistenceDelegateBinding>> persistenceDelegateBindings = getExtensions().values();
- for (ExecutableExtensionProxy<PersistenceDelegateBinding> persistenceDelegateBinding : persistenceDelegateBindings) {
- PersistenceDelegateBinding instance = persistenceDelegateBinding.getInstance();
- if (instance != null && !contributions.contains(instance)) {
- contributions.add(instance);
- }
- }
-
- return contributions.toArray(new PersistenceDelegateBinding[contributions.size()]);
- }
-
- /**
- * Returns the persistence delegate binding identified by its unique id. If no persistence
- * delegate binding with the specified id is registered, <code>null</code> is returned.
- *
- * @param id The unique id of the persistence delegate binding or <code>null</code>
- *
- * @return The persistence delegate binding instance or <code>null</code>.
- */
- public PersistenceDelegateBinding getBinding(String id) {
- PersistenceDelegateBinding contribution = null;
- if (getExtensions().containsKey(id)) {
- ExecutableExtensionProxy<PersistenceDelegateBinding> proxy = getExtensions().get(id);
- // Get the extension instance
- contribution = proxy.getInstance();
- }
-
- return contribution;
- }
-}
+/******************************************************************************* + * Copyright (c) 2011, 2012 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.runtime.persistence.internal; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.core.expressions.EvaluationContext; +import org.eclipse.core.expressions.EvaluationResult; +import org.eclipse.core.expressions.Expression; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager; +import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy; +import org.eclipse.tcf.te.runtime.persistence.activator.CoreBundleActivator; + + +/** + */ +public class PersistenceDelegateBindingExtensionPointManager extends AbstractExtensionPointManager<PersistenceDelegateBinding> { + + /* + * Thread save singleton instance creation. + */ + private static class LazyInstance { + public static PersistenceDelegateBindingExtensionPointManager instance = new PersistenceDelegateBindingExtensionPointManager(); + } + + /** + * Constructor. + */ + PersistenceDelegateBindingExtensionPointManager() { + super(); + } + + /** + * Returns the singleton instance of the extension point manager. + */ + public static PersistenceDelegateBindingExtensionPointManager getInstance() { + return LazyInstance.instance; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getExtensionPointId() + */ + @Override + protected String getExtensionPointId() { + return "org.eclipse.tcf.te.runtime.persistence.bindings"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getConfigurationElementName() + */ + @Override + protected String getConfigurationElementName() { + return "binding"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#doCreateExtensionProxy(org.eclipse.core.runtime.IConfigurationElement) + */ + @Override + protected ExecutableExtensionProxy<PersistenceDelegateBinding> doCreateExtensionProxy(IConfigurationElement element) throws CoreException { + return new ExecutableExtensionProxy<PersistenceDelegateBinding>(element) { + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy#newInstance() + */ + @Override + public PersistenceDelegateBinding newInstance() { + PersistenceDelegateBinding instance = new PersistenceDelegateBinding(); + try { + instance.setInitializationData(getConfigurationElement(), null, null); + } catch (CoreException e) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + e.getLocalizedMessage(), e); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + return instance; + } + }; + } + + /** + * Returns the applicable persistence delegate bindings for the given delegate context. + * + * @param context The delegate context or <code>null</code>. + * @return The list of applicable editor page bindings or an empty array. + */ + public PersistenceDelegateBinding[] getApplicableBindings(Object context, Object container) { + List<PersistenceDelegateBinding> applicable = new ArrayList<PersistenceDelegateBinding>(); + + for (PersistenceDelegateBinding binding : getBindings()) { + Expression enablement = binding.getEnablement(); + + // The binding is applicable by default if no expression is specified. + boolean isApplicable = enablement == null; + + if (enablement != null) { + if (context != null) { + // Set the default variable to the delegate context. + EvaluationContext evalContext = new EvaluationContext(null, context); + evalContext.addVariable("context", context); //$NON-NLS-1$ + if (context instanceof Class) { + evalContext.addVariable("contextClass", ((Class<?>)context).getName()); //$NON-NLS-1$ + } + else { + evalContext.addVariable("contextClass", context.getClass().getName()); //$NON-NLS-1$ + } + evalContext.addVariable("container", container); //$NON-NLS-1$ + if (container instanceof Class) { + evalContext.addVariable("containerClass", ((Class<?>)container).getName()); //$NON-NLS-1$ + } + else { + evalContext.addVariable("containerClass", container.getClass().getName()); //$NON-NLS-1$ + } + // Allow plugin activation + evalContext.setAllowPluginActivation(true); + // Evaluate the expression + try { + isApplicable = enablement.evaluate(evalContext).equals(EvaluationResult.TRUE); + } catch (CoreException e) { + IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), + e.getLocalizedMessage(), e); + Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status); + } + } else { + // The enablement is false by definition if no delegate context is given. + isApplicable = false; + } + } + + // Add the binding if applicable + if (isApplicable) { + applicable.add(binding); + } + } + + return applicable.toArray(new PersistenceDelegateBinding[applicable.size()]); + } + + /** + * Returns the list of all contributed persistence delegate bindings. + * + * @return The list of contributed persistence delegate bindings, or an empty array. + */ + public PersistenceDelegateBinding[] getBindings() { + List<PersistenceDelegateBinding> contributions = new ArrayList<PersistenceDelegateBinding>(); + Collection<ExecutableExtensionProxy<PersistenceDelegateBinding>> persistenceDelegateBindings = getExtensions().values(); + for (ExecutableExtensionProxy<PersistenceDelegateBinding> persistenceDelegateBinding : persistenceDelegateBindings) { + PersistenceDelegateBinding instance = persistenceDelegateBinding.getInstance(); + if (instance != null && !contributions.contains(instance)) { + contributions.add(instance); + } + } + + return contributions.toArray(new PersistenceDelegateBinding[contributions.size()]); + } + + /** + * Returns the persistence delegate binding identified by its unique id. If no persistence + * delegate binding with the specified id is registered, <code>null</code> is returned. + * + * @param id The unique id of the persistence delegate binding or <code>null</code> + * + * @return The persistence delegate binding instance or <code>null</code>. + */ + public PersistenceDelegateBinding getBinding(String id) { + PersistenceDelegateBinding contribution = null; + if (getExtensions().containsKey(id)) { + ExecutableExtensionProxy<PersistenceDelegateBinding> proxy = getExtensions().get(id); + // Get the extension instance + contribution = proxy.getInstance(); + } + + return contribution; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/interfaces/IPeerModelProperties.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/interfaces/IPeerModelProperties.java new file mode 100644 index 000000000..8814fd406 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/interfaces/IPeerModelProperties.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.tcf.launch.core.interfaces; + + +/** + * Default set of custom peer properties. + */ +public interface IPeerModelProperties { + + /** + * Property: The peers launch configuration "Template" for new attach launch. + */ + public static final String PROP_LAUNCH_CONFIG_ATTRIBUTES = "LaunchConfigAttributes"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/lm/delegates/AttachLaunchManagerDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/lm/delegates/AttachLaunchManagerDelegate.java index 23e9a4c03..d2995d54a 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/lm/delegates/AttachLaunchManagerDelegate.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.core/src/org/eclipse/tcf/te/tcf/launch/core/lm/delegates/AttachLaunchManagerDelegate.java @@ -13,19 +13,25 @@ package org.eclipse.tcf.te.tcf.launch.core.lm.delegates; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.tcf.te.launch.core.lm.delegates.DefaultLaunchManagerDelegate; +import org.eclipse.tcf.te.launch.core.lm.interfaces.ICommonLaunchAttributes; import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchContextLaunchAttributes; import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification; import org.eclipse.tcf.te.launch.core.persistence.launchcontext.LaunchContextsPersistenceDelegate; import org.eclipse.tcf.te.launch.core.selection.interfaces.IRemoteSelectionContext; import org.eclipse.tcf.te.launch.core.selection.interfaces.ISelectionContext; import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode; +import org.eclipse.tcf.te.runtime.persistence.PersistenceManager; +import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate; import org.eclipse.tcf.te.runtime.services.ServiceManager; import org.eclipse.tcf.te.runtime.services.interfaces.IPropertiesAccessService; import org.eclipse.tcf.te.runtime.services.interfaces.constants.IPropertiesAccessServiceConstants; +import org.eclipse.tcf.te.tcf.launch.core.interfaces.IPeerModelProperties; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel; /** * RemoteAppLaunchManagerDelegate @@ -43,13 +49,14 @@ public class AttachLaunchManagerDelegate extends DefaultLaunchManagerDelegate { super(); } + /* (non-Javadoc) + * @see org.eclipse.tcf.te.launch.core.lm.delegates.DefaultLaunchManagerDelegate#updateLaunchConfigAttributes(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy, org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification) + */ @Override public void updateLaunchConfigAttributes(ILaunchConfigurationWorkingCopy wc, ILaunchSpecification launchSpec) { super.updateLaunchConfigAttributes(wc, launchSpec); - if (launchSpec.hasAttribute(ILaunchContextLaunchAttributes.ATTR_LAUNCH_CONTEXTS)) { - wc.setAttribute(ILaunchContextLaunchAttributes.ATTR_LAUNCH_CONTEXTS, (String)launchSpec.getAttribute(ILaunchContextLaunchAttributes.ATTR_LAUNCH_CONTEXTS).getValue()); - } + copySpecToConfig(launchSpec, wc); wc.rename(getDefaultLaunchName(wc)); } @@ -61,9 +68,7 @@ public class AttachLaunchManagerDelegate extends DefaultLaunchManagerDelegate { public void initLaunchConfigAttributes(ILaunchConfigurationWorkingCopy wc, ILaunchSpecification launchSpec) { super.initLaunchConfigAttributes(wc, launchSpec); - if (launchSpec.hasAttribute(ILaunchContextLaunchAttributes.ATTR_LAUNCH_CONTEXTS)) { - wc.setAttribute(ILaunchContextLaunchAttributes.ATTR_LAUNCH_CONTEXTS, (String)launchSpec.getAttribute(ILaunchContextLaunchAttributes.ATTR_LAUNCH_CONTEXTS).getValue()); - } + copySpecToConfig(launchSpec, wc); wc.rename(getDefaultLaunchName(wc)); } @@ -96,6 +101,24 @@ public class AttachLaunchManagerDelegate extends DefaultLaunchManagerDelegate { LaunchContextsPersistenceDelegate.setLaunchContexts(launchSpec, launchContexts.toArray(new IModelNode[launchContexts.size()])); } + if (remoteCtx instanceof IPeerModel) { + String launchConfigAttributes = ((IPeerModel)remoteCtx).getPeer().getAttributes().get(IPeerModelProperties.PROP_LAUNCH_CONFIG_ATTRIBUTES); + if (launchConfigAttributes != null) { + IPersistenceDelegate delegate = PersistenceManager.getInstance().getDelegate(Map.class, launchConfigAttributes, false); + try { + Map<String, String> attributes = (Map<String,String>)delegate.read(Map.class, launchConfigAttributes, null); + attributes.remove(ILaunchContextLaunchAttributes.ATTR_LAUNCH_CONTEXTS); + attributes.remove(ICommonLaunchAttributes.ATTR_UUID); + attributes.remove(ICommonLaunchAttributes.ATTR_LAST_LAUNCHED); + for (String key : attributes.keySet()) { + launchSpec.addAttribute(key, attributes.get(key), true); + } + } + catch (Exception e) { + } + } + } + launchSpec.setLaunchConfigName(getDefaultLaunchName(launchSpec)); } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/META-INF/MANIFEST.MF index 3b580f6c4..6ab958265 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/META-INF/MANIFEST.MF +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/META-INF/MANIFEST.MF @@ -29,7 +29,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.8.0", org.eclipse.tcf.te.ui.swt;bundle-version="1.1.0", org.eclipse.tcf.te.ui.views;bundle-version="1.1.0", org.eclipse.tcf.debug.ui;bundle-version="1.1.0", - org.eclipse.tcf.te.runtime.concurrent;bundle-version="1.1.0" + org.eclipse.tcf.te.runtime.concurrent;bundle-version="1.1.0", + org.eclipse.tcf.te.runtime.persistence;bundle-version="1.1.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy Bundle-Localization: plugin diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/plugin.properties b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/plugin.properties index 96f35d4d3..fe817d801 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/plugin.properties +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/plugin.properties @@ -15,6 +15,7 @@ providerName = Eclipse.org - TCF MemoryMapEditorPage.name=Symbol Files PathMapEditorPage.name=Path Map +SourceLookupEditorPage.name=Source # ***** Command contributions ***** diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/plugin.xml b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/plugin.xml index c9e55e800..7c8027bc7 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/plugin.xml +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/plugin.xml @@ -123,6 +123,12 @@ name="%PathMapEditorPage.name" id="org.eclipse.tcf.te.tcf.launch.ui.PathMapEditorPage"> </editorPage> + + <editorPage + class="org.eclipse.tcf.te.tcf.launch.ui.editor.SourceLookupEditorPage" + name="%SourceLookupEditorPage.name" + id="org.eclipse.tcf.te.launch.ui.SourceLookupEditorPage"> + </editorPage> </extension> <!-- Editor page binding contributions --> diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/AbstractTcfLaunchTabContainerEditorPage.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/AbstractTcfLaunchTabContainerEditorPage.java new file mode 100644 index 000000000..60a598741 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/AbstractTcfLaunchTabContainerEditorPage.java @@ -0,0 +1,179 @@ +/******************************************************************************* + * Copyright (c) 2012 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.tcf.launch.ui.editor; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.tcf.core.AbstractPeer; +import org.eclipse.tcf.core.TransientPeer; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.te.launch.core.lm.LaunchManager; +import org.eclipse.tcf.te.launch.core.lm.LaunchSpecification; +import org.eclipse.tcf.te.launch.core.lm.interfaces.ILaunchSpecification; +import org.eclipse.tcf.te.launch.core.persistence.launchcontext.LaunchContextsPersistenceDelegate; +import org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage; +import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode; +import org.eclipse.tcf.te.runtime.persistence.PersistenceManager; +import org.eclipse.tcf.te.runtime.persistence.interfaces.IPersistenceDelegate; +import org.eclipse.tcf.te.runtime.services.ServiceManager; +import org.eclipse.tcf.te.runtime.services.interfaces.IPropertiesAccessService; +import org.eclipse.tcf.te.tcf.core.peers.Peer; +import org.eclipse.tcf.te.tcf.launch.core.interfaces.ILaunchTypes; +import org.eclipse.tcf.te.tcf.launch.core.interfaces.IPeerModelProperties; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tcf.te.tcf.locator.interfaces.services.ILocatorModelUpdateService; +import org.eclipse.tcf.te.tcf.locator.model.Model; +import org.eclipse.tcf.te.tcf.locator.nodes.PeerRedirector; + +/** + * TCF launch configuration tab container page implementation. + */ +public abstract class AbstractTcfLaunchTabContainerEditorPage extends AbstractLaunchTabContainerEditorPage { + + protected static final String PROP_LAUNCH_CONFIG_WC = "launchConfigWorkingCopy.transient.silent"; //$NON-NLS-1$ + protected static final String PROP_ORIGINAL_LAUNCH_CONFIG_ATTRIBUTES = "launchConfigAttributes.transient.silent"; //$NON-NLS-1$ + + /** + * Get the peer model from the editor input. + * @param input The editor input. + * @return The peer model. + */ + IPeerModel getPeerModel(Object input) { + return (IPeerModel)((IAdaptable)input).getAdapter(IPeerModel.class); + } + + /** + * Get the launch configuration from the peer model. + * @param peerModel The peer model. + * @return The launch configuration. + */ + ILaunchConfigurationWorkingCopy getLaunchConfig(final IPeerModel peerModel) { + ILaunchConfigurationWorkingCopy wc = null; + if (peerModel != null) { + IPropertiesAccessService service = ServiceManager.getInstance().getService(peerModel, IPropertiesAccessService.class); + if (service != null && service.getProperty(peerModel, PROP_LAUNCH_CONFIG_WC) instanceof ILaunchConfigurationWorkingCopy) { + wc = (ILaunchConfigurationWorkingCopy)service.getProperty(peerModel, PROP_LAUNCH_CONFIG_WC); + } + else { + String launchConfigAttributes = peerModel.getPeer().getAttributes().get(IPeerModelProperties.PROP_LAUNCH_CONFIG_ATTRIBUTES); + ILaunchSpecification spec = new LaunchSpecification(ILaunchTypes.ATTACH, ILaunchManager.DEBUG_MODE); + LaunchContextsPersistenceDelegate.setLaunchContexts(spec, new IModelNode[]{peerModel}); + try { + wc = LaunchManager.getInstance().getLaunchConfiguration(spec, true).getWorkingCopy(); + LaunchContextsPersistenceDelegate.setLaunchContexts(wc, null); + IPersistenceDelegate delegate = PersistenceManager.getInstance().getDelegate(wc, launchConfigAttributes, false); + if (launchConfigAttributes != null && launchConfigAttributes.trim().length() > 0) { + delegate.read(wc, launchConfigAttributes, null); + } + launchConfigAttributes = (String)delegate.write(wc, String.class, null); + service.setProperty(peerModel, PROP_ORIGINAL_LAUNCH_CONFIG_ATTRIBUTES, launchConfigAttributes); + service.setProperty(peerModel, PROP_LAUNCH_CONFIG_WC, wc); + } + catch (Exception e) { + } + } + } + return wc; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage#setupData(java.lang.Object) + */ + @Override + public boolean setupData(Object input) { + ILaunchConfigurationWorkingCopy wc = getLaunchConfig(getPeerModel(input)); + if (wc != null) { + getLaunchConfigurationTab().initializeFrom(wc); + checkLaunchConfigDirty(); + return true; + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage#extractData() + */ + @Override + public boolean extractData() { + ILaunchConfigurationWorkingCopy wc = getLaunchConfig(getPeerModel(getEditorInput())); + if (wc != null && checkLaunchConfigDirty()) { + getLaunchConfigurationTab().performApply(wc); + IPersistenceDelegate delegate = PersistenceManager.getInstance().getDelegate(wc, String.class, false); + try { + final String launchConfigAttributes = (String)delegate.write(wc, String.class, null); + final IPeerModel peerModel = getPeerModel(getEditorInput()); + IPropertiesAccessService service = ServiceManager.getInstance().getService(peerModel, IPropertiesAccessService.class); + service.setProperty(peerModel, PROP_ORIGINAL_LAUNCH_CONFIG_ATTRIBUTES, launchConfigAttributes); + if (peerModel != null) { + Protocol.invokeAndWait(new Runnable() { + @Override + public void run() { + IPeer oldPeer = peerModel.getPeer(); + Map<String, String> attributes = new HashMap<String, String>(peerModel.getPeer().getAttributes()); + attributes.put(IPeerModelProperties.PROP_LAUNCH_CONFIG_ATTRIBUTES, launchConfigAttributes); + IPeer newPeer = new Peer(attributes); + if (oldPeer instanceof TransientPeer && !(oldPeer instanceof AbstractPeer || oldPeer instanceof PeerRedirector || oldPeer instanceof Peer)) { + peerModel.setProperty(org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModelProperties.PROP_INSTANCE, newPeer); + } else { + Model.getModel().getService(ILocatorModelUpdateService.class).mergeUserDefinedAttributes(peerModel, newPeer, false); + } + checkLaunchConfigDirty(); + } + }); + return true; + } + } + catch (Exception e) { + } + } + return false; + } + + /** + * Check if the launch config has changed. + * If it has changed, the page is set dirty. + * @return <code>true</code> if the launch config has changed since last save. + */ + public boolean checkLaunchConfigDirty() { + boolean dirty = false; + IPeerModel peerModel = getPeerModel(getEditorInput()); + IPropertiesAccessService service = ServiceManager.getInstance().getService(peerModel, IPropertiesAccessService.class); + String oldLaunchConfigAttributes = (String)service.getProperty(peerModel, PROP_ORIGINAL_LAUNCH_CONFIG_ATTRIBUTES); + IPersistenceDelegate delegate = PersistenceManager.getInstance().getDelegate(getLaunchConfig(peerModel), String.class, false); + String launchConfigAttributes = null; + try { + launchConfigAttributes = (String)delegate.write(getLaunchConfig(peerModel), String.class, null); + dirty = !launchConfigAttributes.equals(oldLaunchConfigAttributes); + } + catch (Exception e) { + } + + setDirty(dirty); + getManagedForm().dirtyStateChanged(); + return dirty; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage#dispose() + */ + @Override + public void dispose() { + super.dispose(); + IPeerModel peerModel = getPeerModel(getEditorInput()); + IPropertiesAccessService service = ServiceManager.getInstance().getService(peerModel, IPropertiesAccessService.class); + service.setProperty(peerModel, PROP_ORIGINAL_LAUNCH_CONFIG_ATTRIBUTES, null); + service.setProperty(peerModel, PROP_LAUNCH_CONFIG_WC, null); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/MemoryMapEditorPage.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/MemoryMapEditorPage.java index 5ccb6e454..5d782681f 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/MemoryMapEditorPage.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/MemoryMapEditorPage.java @@ -11,19 +11,24 @@ package org.eclipse.tcf.te.tcf.launch.ui.editor; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.tcf.internal.debug.ui.launch.TCFMemoryMapTab; -import org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage; /** * TCF memory map launch configuration tab container page implementation. */ -public class MemoryMapEditorPage extends AbstractLaunchTabContainerEditorPage { +public class MemoryMapEditorPage extends AbstractTcfLaunchTabContainerEditorPage { /* (non-Javadoc) * @see org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage#createLaunchConfigurationTab() */ - @Override + @Override protected AbstractLaunchConfigurationTab createLaunchConfigurationTab() { - return new TCFMemoryMapTab(); + return new TCFMemoryMapTab() { + @Override + protected void updateLaunchConfigurationDialog() { + super.updateLaunchConfigurationDialog(); + performApply(getLaunchConfig(getPeerModel(getEditorInput()))); + checkLaunchConfigDirty(); + } + }; } - } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/PathMapEditorPage.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/PathMapEditorPage.java index 79dcd9396..c277b9d5d 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/PathMapEditorPage.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/PathMapEditorPage.java @@ -11,19 +11,24 @@ package org.eclipse.tcf.te.tcf.launch.ui.editor; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.tcf.internal.debug.ui.launch.TCFPathMapTab; -import org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage; /** * TCF path map launch configuration tab container page implementation. */ -public class PathMapEditorPage extends AbstractLaunchTabContainerEditorPage { +public class PathMapEditorPage extends AbstractTcfLaunchTabContainerEditorPage { /* (non-Javadoc) * @see org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage#createLaunchConfigurationTab() */ - @Override + @Override protected AbstractLaunchConfigurationTab createLaunchConfigurationTab() { - return new TCFPathMapTab(); + return new TCFPathMapTab() { + @Override + protected void updateLaunchConfigurationDialog() { + super.updateLaunchConfigurationDialog(); + performApply(getLaunchConfig(getPeerModel(getEditorInput()))); + checkLaunchConfigDirty(); + } + }; } - } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/editor/SourceLookupEditorPage.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/SourceLookupEditorPage.java index 09cb7099f..d16a12c8e 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.launch.ui/src/org/eclipse/tcf/te/launch/ui/editor/SourceLookupEditorPage.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.launch.ui/src/org/eclipse/tcf/te/tcf/launch/ui/editor/SourceLookupEditorPage.java @@ -7,7 +7,7 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.tcf.te.launch.ui.editor; +package org.eclipse.tcf.te.tcf.launch.ui.editor; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.debug.ui.sourcelookup.SourceLookupTab; @@ -18,7 +18,7 @@ import org.eclipse.swt.widgets.Composite; /** * Source lookup launch configuration tab container page implementation. */ -public class SourceLookupEditorPage extends AbstractLaunchTabContainerEditorPage { +public class SourceLookupEditorPage extends AbstractTcfLaunchTabContainerEditorPage { /* (non-Javadoc) * @see org.eclipse.tcf.te.launch.ui.editor.AbstractLaunchTabContainerEditorPage#createLaunchConfigurationTab() @@ -26,15 +26,17 @@ public class SourceLookupEditorPage extends AbstractLaunchTabContainerEditorPage @Override protected AbstractLaunchConfigurationTab createLaunchConfigurationTab() { return new SourceLookupTab() { - /* (non-Javadoc) - * @see org.eclipse.debug.ui.sourcelookup.SourceLookupTab#createControl(org.eclipse.swt.widgets.Composite) - */ @Override public void createControl(Composite parent) { - super.createControl(parent); - ((Composite)getControl()).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + super.createControl(parent); + ((Composite)getControl()).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + } + @Override + protected void updateLaunchConfigurationDialog() { + super.updateLaunchConfigurationDialog(); + performApply(getLaunchConfig(getPeerModel(getEditorInput()))); + checkLaunchConfigDirty(); } }; } - } |