diff --git a/bundles/org.eclipse.launchbar.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.launchbar.core/META-INF/MANIFEST.MF index b84817037d6..cc050c64a05 100644 --- a/bundles/org.eclipse.launchbar.core/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.launchbar.core/META-INF/MANIFEST.MF @@ -8,7 +8,8 @@ Bundle-Vendor: Eclipse CDT Require-Bundle: org.eclipse.core.runtime, org.eclipse.debug.core, org.eclipse.core.filesystem, - org.eclipse.remote.core;bundle-version="2.0.0" + org.eclipse.remote.core;bundle-version="2.0.0", + org.eclipse.core.expressions Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.launchbar.core, diff --git a/bundles/org.eclipse.launchbar.core/plugin.xml b/bundles/org.eclipse.launchbar.core/plugin.xml index 37f566a2016..47331771ed4 100644 --- a/bundles/org.eclipse.launchbar.core/plugin.xml +++ b/bundles/org.eclipse.launchbar.core/plugin.xml @@ -10,8 +10,9 @@ + + + @@ -56,6 +58,9 @@ + + + diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/ILaunchDescriptorType.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/ILaunchDescriptorType.java index 0b3fad90502..49edd67687d 100644 --- a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/ILaunchDescriptorType.java +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/ILaunchDescriptorType.java @@ -18,11 +18,13 @@ import org.eclipse.core.runtime.CoreException; * It is strongly recommended to extend AbstarctLaunchDescriptorType instead of implementing this directly */ public interface ILaunchDescriptorType { - /** * Does this type own this launch object? * - * @deprecated this needs to be replaced by enablement to avoid plug-in loading. + * The main checking should be done in enablement expression of extension declaring the type, + * if enablement expression if defined this method can return true. + * This also can used for fine-tuning of ownership + * which is hard to declared in xml. * * @param element * @return owns element diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchBarManager.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchBarManager.java index c1bd9c35178..79c876f5f92 100644 --- a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchBarManager.java +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchBarManager.java @@ -76,7 +76,6 @@ public class LaunchBarManager implements ILaunchBarManager, ILaunchConfiguration // the extended info for loaded descriptor types private final Map descriptorTypeInfo = new HashMap<>(); - private final Map> configProviders = new HashMap<>(); // Descriptors in MRU order, key is desc type id and desc name. @@ -194,9 +193,7 @@ public class LaunchBarManager implements ILaunchBarManager, ILaunchConfiguration LaunchDescriptorTypeInfo typeInfo = new LaunchDescriptorTypeInfo(element); descriptorTypes.put(typeInfo.getId(), typeInfo); - // TODO figure out a better place to set the id so we don't load the type object - // until needed - descriptorTypeInfo.put(typeInfo.getType(), typeInfo); + if (configProviders.get(typeInfo.getId()) == null) { // Make sure we initialize the list @@ -211,8 +208,8 @@ public class LaunchBarManager implements ILaunchBarManager, ILaunchConfiguration } providers.add(info); } - } catch (CoreException e) { - Activator.log(e.getStatus()); + } catch (Exception e) { + Activator.log(e); } } } @@ -329,13 +326,14 @@ public class LaunchBarManager implements ILaunchBarManager, ILaunchConfiguration } private ILaunchDescriptorType ownsLaunchObject(Object launchObject) throws CoreException { - // TODO use enablement to find out what descriptor types to ask - // to prevent unnecessary plug-in loading for (LaunchDescriptorTypeInfo descriptorInfo : orderedDescriptorTypes) { - ILaunchDescriptorType descriptorType = descriptorInfo.getType(); try { - if (descriptorType.ownsLaunchObject(launchObject)) { - return descriptorType; + if (descriptorInfo.ownsLaunchObject(launchObject)) { + ILaunchDescriptorType type = descriptorInfo.getType(); + descriptorTypeInfo.put(type, descriptorInfo); + if (type.ownsLaunchObject(launchObject)) { + return type; + } } } catch (Throwable e) { Activator.log(e); // one of used defined launch types is misbehaving diff --git a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchDescriptorTypeInfo.java b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchDescriptorTypeInfo.java index 787b077d281..61ee75a5dbb 100644 --- a/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchDescriptorTypeInfo.java +++ b/bundles/org.eclipse.launchbar.core/src/org/eclipse/launchbar/core/internal/LaunchDescriptorTypeInfo.java @@ -1,7 +1,12 @@ package org.eclipse.launchbar.core.internal; +import org.eclipse.core.expressions.EvaluationContext; +import org.eclipse.core.expressions.EvaluationResult; +import org.eclipse.core.expressions.Expression; +import org.eclipse.core.expressions.ExpressionConverter; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.Status; import org.eclipse.launchbar.core.ILaunchDescriptorType; public class LaunchDescriptorTypeInfo { @@ -9,6 +14,7 @@ public class LaunchDescriptorTypeInfo { private int priority; private IConfigurationElement element; private ILaunchDescriptorType type; + private Expression expression; public LaunchDescriptorTypeInfo(IConfigurationElement element) { this.id = element.getAttribute("id"); //$NON-NLS-1$ @@ -23,6 +29,25 @@ public class LaunchDescriptorTypeInfo { } } this.element = element; + IConfigurationElement[] enabledExpressions = element.getChildren("enablement");//$NON-NLS-1$ + if (enabledExpressions == null || enabledExpressions.length == 0) { + Activator.log(new Status(Status.WARNING, Activator.PLUGIN_ID, + "Enablement expression is missing for descriptor type " + id));//$NON-NLS-1$ + } else if (enabledExpressions.length > 1) { + Activator.log(new Status(Status.WARNING, Activator.PLUGIN_ID, + "Multiple enablement expressions are detected for descriptor type "//$NON-NLS-1$ + + id)); + } else { + try { + expression = ExpressionConverter.getDefault().perform(enabledExpressions[0]); + } catch (CoreException e) { + Activator.log(e); + } + if (expression == null) { + Activator.log(new Status(Status.ERROR, Activator.PLUGIN_ID, + "Cannot parse enablement expression defined in descriptor type " + id)); //$NON-NLS-1$ + } + } } // Used for testing @@ -47,4 +72,11 @@ public class LaunchDescriptorTypeInfo { } return type; } + + public boolean ownsLaunchObject(Object object) throws CoreException { + if (expression == null) + return true; + EvaluationResult result = expression.evaluate(new EvaluationContext(null, object)); + return (result == EvaluationResult.TRUE); + } } \ No newline at end of file diff --git a/tests/org.eclipse.launchbar.core.tests/src/org/eclipse/launchbar/core/internal/LaunchBarManager2Test.java b/tests/org.eclipse.launchbar.core.tests/src/org/eclipse/launchbar/core/internal/LaunchBarManager2Test.java index 478d08f5c46..c9fa7fd5dbc 100644 --- a/tests/org.eclipse.launchbar.core.tests/src/org/eclipse/launchbar/core/internal/LaunchBarManager2Test.java +++ b/tests/org.eclipse.launchbar.core.tests/src/org/eclipse/launchbar/core/internal/LaunchBarManager2Test.java @@ -80,7 +80,7 @@ public class LaunchBarManager2Test { private ArrayList globalmodes = new ArrayList<>(); IExtensionPoint point; IEclipsePreferences store = new EclipsePreferences(); - private ArrayList elements; + private ArrayList elements; private IExtension extension; private static final String localTargetTypeId = "org.eclipse.remote.LocalServices"; private String descriptorTypeId; @@ -148,9 +148,23 @@ public class LaunchBarManager2Test { doReturn(descriptorTypeId).when(element).getAttribute("id"); doReturn(Integer.toString(priority)).when(element).getAttribute("priority"); doReturn(descriptorType).when(element).createExecutableExtension("class"); + mockEnablementElement(element); return element; } + private void mockSubElement(IConfigurationElement parent, IConfigurationElement... elements) { + doReturn(elements).when(parent).getChildren(); + String name = elements[0].getName(); + doReturn(elements).when(parent).getChildren(name); + } + + private IConfigurationElement mockEnablementElement(IConfigurationElement parent) { + IConfigurationElement enablement = mock(IConfigurationElement.class); + doReturn("enablement").when(enablement).getName(); + mockSubElement(parent, new IConfigurationElement[] { enablement }); + return enablement; + } + protected void init() throws CoreException { doReturn(elements.toArray(new IConfigurationElement[0])).when(extension).getConfigurationElements(); doReturn(targets).when(remoteServiceManager).getAllRemoteConnections(); @@ -331,6 +345,7 @@ public class LaunchBarManager2Test { ConfigBasedLaunchDescriptor desc2 = new ConfigBasedLaunchDescriptor(descriptorType, lc2); mockProviderElement(descriptorTypeId, 10, desc2, target, lc2, lc2); init(); + manager.launchObjectAdded(launchObject); // it return original lctype because we did not associate this dynmaically assertEquals(launchConfigType, manager.getLaunchConfigurationType(descriptor, target)); } @@ -344,6 +359,7 @@ public class LaunchBarManager2Test { ILaunchConfiguration lc2 = mockLC("lc2", lctype2); mockProviderElement(descriptorTypeId, 20, descriptor, target, lc2, launchObject); init(); + manager.launchObjectAdded(launchObject); assertEquals(lctype2, manager.getLaunchConfigurationType(descriptor, target)); } @@ -820,6 +836,7 @@ public class LaunchBarManager2Test { @Test public void testGetLaunchConfigurationType() throws CoreException { + manager.launchObjectAdded(launchObject); assertNotNull(manager.getLaunchConfigurationType(descriptor, otherTarget)); } @@ -830,12 +847,14 @@ public class LaunchBarManager2Test { @Test public void testGetLaunchConfigurationNull2() throws CoreException { + manager.launchObjectAdded(launchObject); assertNull(manager.getLaunchConfiguration(descriptor, null)); } @Test public void testGetLaunchConfiguration() throws CoreException { basicSetup(); + manager.launchObjectAdded(launchObject); assertTrue(manager.supportsTarget(descriptor, otherTarget)); assertNotNull(manager.getLaunchConfiguration(descriptor, otherTarget)); } @@ -926,4 +945,23 @@ public class LaunchBarManager2Test { manager.launchConfigurationRemoved(launchConfig); verify(provider).launchConfigurationRemoved(launchConfig); } + + @Test + public void testDescriptorEnablement() throws CoreException { + basicSetupOnly(); + elements.clear(); + + IConfigurationElement element = mockDescriptorTypeElement("type2", 10, descriptorType); + IConfigurationElement enablement = mockEnablementElement(element); + IConfigurationElement instance = mock(IConfigurationElement.class); + doReturn("instanceof").when(instance).getName(); + mockSubElement(enablement, new IConfigurationElement[] { instance }); + doReturn("java.lang.Integer").when(instance).getAttribute("value"); + init(); + assertNull(manager.launchObjectAdded(launchObject)); // this will be refused by enablement expression + assertNull(manager.launchObjectAdded(1)); // we programmatically refuse this + mockLaunchObjectOnDescriptor(1); + assertNotNull(manager.launchObjectAdded(1)); // now we both good programmatically and in expression in extension + } + }