Bug 41353 - [launching] Launch config templates
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/core/ILaunchConfiguration.java b/org.eclipse.debug.core/core/org/eclipse/debug/core/ILaunchConfiguration.java
index 50a5395..53050c1 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/core/ILaunchConfiguration.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/core/ILaunchConfiguration.java
@@ -663,6 +663,20 @@
public ILaunchConfiguration getTemplate() throws CoreException;
/**
+ * Returns a map of attributes in this launch configuration that are
+ * different from the specified attributes. Returns an empty map if
+ * this launch configuration contains equivalent attributes. A <code>null</code>
+ * value is returned for attributes not contained in this launch configuration.
+ *
+ * @param attributes to compare to
+ * @return a map of attributes in this launch configuration that
+ * are different from the specified attributes
+ * @throws CoreException if an exception occurs while comparing
+ * @since 3.6
+ */
+ public Map findDifferences(Map attributes) throws CoreException;
+
+ /**
* Returns whether this configuration is a template.
*
* @return whether this configuration is a template
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfiguration.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfiguration.java
index acf5a9f..4e5c8a7 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfiguration.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfiguration.java
@@ -17,10 +17,13 @@
import java.io.StringReader;
import java.net.URI;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -1017,6 +1020,26 @@
}
return CONFIGURATION;
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.ILaunchConfiguration#findDifferences(java.util.Map)
+ */
+ public Map findDifferences(Map attributes) throws CoreException {
+ Map result = new HashMap();
+ Set entries = attributes.entrySet();
+ Iterator iterator = entries.iterator();
+ LaunchConfigurationInfo info = getInfo();
+ while (iterator.hasNext()) {
+ Entry entry = (Entry) iterator.next();
+ String key = (String) entry.getKey();
+ Object attr1 = entry.getValue();
+ Object attr2 = info.getObjectAttribute(key);
+ if (!LaunchConfigurationInfo.compareAttribute(key, attr1, attr2)) {
+ result.put(key, attr2);
+ }
+ }
+ return result;
+ }
}
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfigurationInfo.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfigurationInfo.java
index 6fc01f3..5bbac3f 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfigurationInfo.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfigurationInfo.java
@@ -79,6 +79,11 @@
private boolean fIsTemplate = false;
/**
+ * Static access to the launch manager.
+ */
+ private static LaunchManager fgLaunchManager = (LaunchManager)DebugPlugin.getDefault().getLaunchManager();
+
+ /**
* Whether running on Sun 1.4 VM - see bug 110215
*/
private static boolean fgIsSun14x = false;
@@ -260,6 +265,16 @@
}
/**
+ * Returns the raw object from the attribute table or <code>null</code> if none.
+ *
+ * @param key attribute key
+ * @return raw attribute value
+ */
+ protected Object getObjectAttribute(String key) {
+ return getAttributeTable().get(key);
+ }
+
+ /**
* Returns the <code>java.util.Map</code> attribute with the given key or
* the given default value if undefined.
*
@@ -736,38 +751,15 @@
* @return whether the two attribute maps are equal
*/
protected boolean compareAttributes(TreeMap map1, TreeMap map2) {
- LaunchManager manager = (LaunchManager)DebugPlugin.getDefault().getLaunchManager();
if (map1.size() == map2.size()) {
Iterator attributes = map1.keySet().iterator();
while (attributes.hasNext()) {
String key = (String)attributes.next();
Object attr1 = map1.get(key);
Object attr2 = map2.get(key);
- if (attr2 == null) {
+ if (!compareAttribute(key, attr1, attr2)) {
return false;
}
- Comparator comp = manager.getComparator(key);
- if (comp == null) {
- if (fgIsSun14x) {
- if(attr2 instanceof String & attr1 instanceof String) {
- // this is a hack for bug 110215, on SUN 1.4.x, \r
- // is stripped off when the stream is written to the
- // DOM
- // this is not the case for 1.5.x, so to be safe we
- // are stripping \r off all strings before we
- // compare for equality
- attr1 = ((String)attr1).replaceAll("\\r", ""); //$NON-NLS-1$ //$NON-NLS-2$
- attr2 = ((String)attr2).replaceAll("\\r", ""); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- if (!attr1.equals(attr2)) {
- return false;
- }
- } else {
- if (comp.compare(attr1, attr2) != 0) {
- return false;
- }
- }
}
return true;
}
@@ -775,6 +767,43 @@
}
/**
+ * Returns whether the two attributes are equal, considering comparator extensions.
+ *
+ * @param key attribute key
+ * @param attr1 attribute value
+ * @param attr2 attribute value to compare to, possibly <code>null</code>
+ * @return whether equivalent
+ */
+ protected static boolean compareAttribute(String key, Object attr1, Object attr2) {
+ if (attr2 == null) {
+ return false;
+ }
+ Comparator comp = fgLaunchManager.getComparator(key);
+ if (comp == null) {
+ if (fgIsSun14x) {
+ if(attr2 instanceof String & attr1 instanceof String) {
+ // this is a hack for bug 110215, on SUN 1.4.x, \r
+ // is stripped off when the stream is written to the
+ // DOM
+ // this is not the case for 1.5.x, so to be safe we
+ // are stripping \r off all strings before we
+ // compare for equality
+ attr1 = ((String)attr1).replaceAll("\\r", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ attr2 = ((String)attr2).replaceAll("\\r", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ if (!attr1.equals(attr2)) {
+ return false;
+ }
+ } else {
+ if (comp.compare(attr1, attr2) != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
diff --git a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/LaunchConfigurationTests.java b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/LaunchConfigurationTests.java
index 455d5bd..c9de10c 100644
--- a/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/LaunchConfigurationTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipe/debug/tests/launching/LaunchConfigurationTests.java
@@ -1250,6 +1250,55 @@
assertTrue(t2.isTemplate());
}
+ /**
+ * Tests that a template that adds an attribute is not considered to override any template
+ * values.
+ *
+ * @throws CoreException
+ */
+ public void testTemplateNoOverride() throws CoreException {
+ ILaunchConfigurationWorkingCopy t1 = newTemplate(null, "2-b-the-same");
+ ILaunchConfiguration template = t1.doSave();
+ ILaunchConfigurationWorkingCopy wc = template.getType().newInstance(null, "will-b-the-same", template);
+ wc.setAttribute("EXTEND-ATTRIBUTES", "EXTEND-ATTRIBUTES");
+ Map dif = wc.findDifferences(template.getAttributes());
+ assertTrue("Should not override any values", dif.isEmpty());
+ }
+
+ /**
+ * Tests that a template that changes an attribute is considered to override its template
+ * values.
+ *
+ * @throws CoreException
+ */
+ public void testTemplateOverride() throws CoreException {
+ ILaunchConfigurationWorkingCopy t1 = newTemplate(null, "2-b-diff");
+ ILaunchConfiguration template = t1.doSave();
+ ILaunchConfigurationWorkingCopy wc = template.getType().newInstance(null, "will-b-diff", template);
+ wc.setAttribute("String1", "String2");
+ Map dif = wc.findDifferences(template.getAttributes());
+ assertEquals("Should override String1 value", 1, dif.size());
+ assertTrue("Should override String1 value", dif.containsKey("String1"));
+ assertEquals("Should override String1 value with String2", "String2", dif.get("String1"));
+ }
+
+ /**
+ * Test that a configuration that omits a template value shows the difference with
+ * a <code>null</code> entry in the difference map.
+ *
+ * @throws CoreException
+ */
+ public void testMissingTemaplteValue() throws CoreException {
+ ILaunchConfigurationWorkingCopy t1 = newTemplate(null, "2-b-missing");
+ ILaunchConfiguration template = t1.doSave();
+ ILaunchConfigurationWorkingCopy wc = template.getType().newInstance(null, "will-b-diff", template);
+ wc.removeAttribute("String1");
+ Map dif = wc.findDifferences(template.getAttributes());
+ assertEquals("Should be missing String1 value", 1, dif.size());
+ assertTrue("Should be missing String1 value", dif.containsKey("String1"));
+ assertNull("Should be null value", dif.get("String1"));
+ }
+
}