diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTarget.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTarget.java index 55ab598d645..987414558bc 100644 --- a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTarget.java +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTarget.java @@ -9,15 +9,29 @@ package org.eclipse.launchbar.core.internal.target; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.launchbar.core.target.ILaunchTarget; +import org.eclipse.launchbar.core.target.ILaunchTargetWorkingCopy; +import org.osgi.service.prefs.Preferences; public class LaunchTarget extends PlatformObject implements ILaunchTarget { private final String typeId; private final String id; + final Preferences attributes; + /** + * This should only be used to create the null target. There are no attributes supported on the + * null target. + */ public LaunchTarget(String typeId, String id) { this.typeId = typeId; this.id = id; + this.attributes = null; + } + + public LaunchTarget(String typeId, String id, Preferences attributes) { + this.typeId = typeId; + this.id = id; + this.attributes = attributes; } @Override @@ -30,6 +44,20 @@ public class LaunchTarget extends PlatformObject implements ILaunchTarget { return typeId; } + @Override + public ILaunchTargetWorkingCopy getWorkingCopy() { + return new LaunchTargetWorkingCopy(this); + } + + @Override + public String getAttribute(String key, String defValue) { + if (attributes != null) { + return attributes.get(key, defValue); + } else { + return defValue; + } + } + @Override public int hashCode() { final int prime = 31; diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTargetManager.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTargetManager.java index ddb86fe8ffc..6e313b74d1b 100644 --- a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTargetManager.java +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTargetManager.java @@ -66,6 +66,24 @@ public class LaunchTargetManager implements ILaunchTargetManager { targets = new LinkedHashMap<>(); Preferences prefs = getTargetsPref(); try { + // For backwards compat pre-attributes, load targets from type keys + for (String childName : prefs.childrenNames()) { + String[] segments = childName.split(DELIMETER1); + if (segments.length == 2) { + String typeId = segments[0]; + String name = segments[1]; + + Map type = targets.get(typeId); + if (type == null) { + type = new LinkedHashMap<>(); + targets.put(typeId, type); + } + + // Creates the node. Will flush when attributes are added + type.put(name, new LaunchTarget(typeId, name, prefs.node(childName))); + } + } + for (String typeId : prefs.keys()) { Map type = targets.get(typeId); if (type == null) { @@ -74,8 +92,13 @@ public class LaunchTargetManager implements ILaunchTargetManager { } for (String name : prefs.get(typeId, "").split(DELIMETER1)) { //$NON-NLS-1$ - type.put(name, new LaunchTarget(typeId, name)); + if (!type.containsKey(name)) { + type.put(name, new LaunchTarget(typeId, name, prefs.node(typeId + DELIMETER1 + name))); + } } + + // Use children going forward + prefs.remove(typeId); } } catch (BackingStoreException e) { Activator.log(e); @@ -166,11 +189,15 @@ public class LaunchTargetManager implements ILaunchTargetManager { targets.put(typeId, type); } - ILaunchTarget target = new LaunchTarget(typeId, id); + Preferences prefs = getTargetsPref(); + String childName = typeId + DELIMETER1 + id; + ILaunchTarget target = new LaunchTarget(typeId, id, prefs.node(childName)); type.put(id, target); - - getTargetsPref().put(typeId, - type.values().stream().map(t -> t.getId()).collect(Collectors.joining(DELIMETER1))); + try { + prefs.flush(); + } catch (BackingStoreException e) { + Activator.log(e); + } for (ILaunchTargetListener listener : listeners) { listener.launchTargetAdded(target); diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTargetWorkingCopy.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTargetWorkingCopy.java new file mode 100644 index 00000000000..380b5ce2985 --- /dev/null +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LaunchTargetWorkingCopy.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2016 QNX Software Systems 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 + *******************************************************************************/ +package org.eclipse.launchbar.core.internal.target; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.launchbar.core.internal.Activator; +import org.eclipse.launchbar.core.target.ILaunchTarget; +import org.eclipse.launchbar.core.target.ILaunchTargetWorkingCopy; +import org.osgi.service.prefs.BackingStoreException; + +public class LaunchTargetWorkingCopy extends PlatformObject implements ILaunchTargetWorkingCopy { + + private final LaunchTarget original; + private final Map changes = new HashMap<>(); + + public LaunchTargetWorkingCopy(LaunchTarget original) { + this.original = original; + } + + @Override + public ILaunchTarget getOriginal() { + return original; + } + + @Override + public String getTypeId() { + return original.getTypeId(); + } + + @Override + public String getId() { + return original.getId(); + } + + @Override + public ILaunchTargetWorkingCopy getWorkingCopy() { + return this; + } + + @Override + public String getAttribute(String key, String defValue) { + if (changes.containsKey(key)) { + return changes.get(key); + } else { + return original.getAttribute(key, defValue); + } + } + + @Override + public void setAttribute(String key, String value) { + changes.put(key, value); + } + + @Override + public ILaunchTarget save() { + try { + for (Map.Entry entry : changes.entrySet()) { + original.attributes.put(entry.getKey(), entry.getValue()); + } + original.attributes.flush(); + } catch (BackingStoreException e) { + Activator.log(e); + } + return original; + } + +} diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LocalLaunchTargetProvider.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LocalLaunchTargetProvider.java index eb7c130e6fe..2e3b600b488 100644 --- a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LocalLaunchTargetProvider.java +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/target/LocalLaunchTargetProvider.java @@ -7,10 +7,12 @@ *******************************************************************************/ package org.eclipse.launchbar.core.internal.target; +import org.eclipse.core.runtime.Platform; import org.eclipse.launchbar.core.internal.Messages; import org.eclipse.launchbar.core.target.ILaunchTarget; import org.eclipse.launchbar.core.target.ILaunchTargetManager; import org.eclipse.launchbar.core.target.ILaunchTargetProvider; +import org.eclipse.launchbar.core.target.ILaunchTargetWorkingCopy; import org.eclipse.launchbar.core.target.TargetStatus; public class LocalLaunchTargetProvider implements ILaunchTargetProvider { @@ -19,7 +21,11 @@ public class LocalLaunchTargetProvider implements ILaunchTargetProvider { public void init(ILaunchTargetManager targetManager) { if (targetManager.getLaunchTarget(ILaunchTargetManager.localLaunchTargetTypeId, Messages.LocalTarget_name) == null) { - targetManager.addLaunchTarget(ILaunchTargetManager.localLaunchTargetTypeId, Messages.LocalTarget_name); + ILaunchTarget target = targetManager.addLaunchTarget(ILaunchTargetManager.localLaunchTargetTypeId, Messages.LocalTarget_name); + ILaunchTargetWorkingCopy wc = target.getWorkingCopy(); + wc.setAttribute(ILaunchTarget.ATTR_OS, Platform.getOS()); + wc.setAttribute(ILaunchTarget.ATTR_ARCH, Platform.getOSArch()); + wc.save(); } } diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/target/ILaunchTarget.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/target/ILaunchTarget.java index 1c9ad3173fa..9aee390223c 100644 --- a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/target/ILaunchTarget.java +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/target/ILaunchTarget.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. + * Copyright (c) 2015, 2016 QNX Software Systems 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 @@ -11,13 +11,21 @@ import org.eclipse.core.runtime.IAdaptable; import org.eclipse.launchbar.core.internal.target.LaunchTarget; /** - * A launch target is a thing that a launch will run on. Launch targets are - * simple objects with the intention that the launch delegates and launches will - * adapt this object to an object that will assist in performing the launch. + * A launch target is a thing that a launch will run on. Launch targets are simple objects with the + * intention that the launch delegates and launches will adapt this object to an object that will + * assist in performing the launch. * * @noimplement not to be implemented by clients */ public interface ILaunchTarget extends IAdaptable { + + // Standard attributes + public static final String ATTR_OS = "os"; //$NON-NLS-1$ + public static final String ATTR_ARCH = "arch"; //$NON-NLS-1$ + + /** + * The null target, which is the default when no other target is available. + */ public static final ILaunchTarget NULL_TARGET = new LaunchTarget("null", "---"); //$NON-NLS-1$ //$NON-NLS-2$ /** @@ -45,4 +53,23 @@ public interface ILaunchTarget extends IAdaptable { */ String getTypeId(); + /** + * Return a string attribute of this target + * + * @param key + * key + * @param defValue + * default value + * @return value of attribute + */ + String getAttribute(String key, String defValue); + + /** + * Create a working copy of this launch target to allow setting of attributes. Note that when + * saving the attributes this target is updated. A new one is not created. + * + * @return launch target working copy + */ + ILaunchTargetWorkingCopy getWorkingCopy(); + } diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/target/ILaunchTargetWorkingCopy.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/target/ILaunchTargetWorkingCopy.java new file mode 100644 index 00000000000..f425270a7cf --- /dev/null +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/target/ILaunchTargetWorkingCopy.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2016 QNX Software Systems 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 + *******************************************************************************/ +package org.eclipse.launchbar.core.target; + +/** + * Working copy to set attributes on a target and then save them. + */ +public interface ILaunchTargetWorkingCopy extends ILaunchTarget { + + /** + * Get the original launch target. + * + * @return the original launch target + */ + ILaunchTarget getOriginal(); + + /** + * Set an attribute. + * + * @param key + * key + * @param value + * value + */ + void setAttribute(String key, String value); + + /** + * Save the changed attributes to the original working copy. + * + * @return original launch target + */ + ILaunchTarget save(); + +} diff --git a/tests/org.eclipse.launchbar.core.tests/src/org/eclipse/launchbar/core/tests/TargetAttributesTest.java b/tests/org.eclipse.launchbar.core.tests/src/org/eclipse/launchbar/core/tests/TargetAttributesTest.java new file mode 100644 index 00000000000..29eff1a2886 --- /dev/null +++ b/tests/org.eclipse.launchbar.core.tests/src/org/eclipse/launchbar/core/tests/TargetAttributesTest.java @@ -0,0 +1,36 @@ +package org.eclipse.launchbar.core.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import org.eclipse.launchbar.core.internal.Activator; +import org.eclipse.launchbar.core.target.ILaunchTarget; +import org.eclipse.launchbar.core.target.ILaunchTargetManager; +import org.eclipse.launchbar.core.target.ILaunchTargetWorkingCopy; +import org.junit.Test; + +@SuppressWarnings("nls") +public class TargetAttributesTest { + + @Test + public void testAttribute() { + ILaunchTargetManager manager = Activator.getLaunchTargetManager(); + String targetType = "testType"; + String targetId = "testTarget"; + ILaunchTarget target = manager.getLaunchTarget(targetType, targetId); + if (target != null) { + manager.removeLaunchTarget(target); + } + target = manager.addLaunchTarget(targetType, targetId); + String attributeKey = "testKey"; + String attributeValue = "testValue"; + assertEquals(target.getAttribute(attributeKey, ""), ""); + ILaunchTargetWorkingCopy wc = target.getWorkingCopy(); + assertNotEquals(target, wc); + wc.setAttribute(attributeKey, attributeValue); + assertEquals(wc.getAttribute(attributeKey, ""), attributeValue); + ILaunchTarget savedTarget = wc.save(); + assertEquals(target, savedTarget); + assertEquals(target.getAttribute(attributeKey, ""), attributeValue); + } +}