Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Schwarz2013-03-14 10:46:11 -0400
committerTobias Schwarz2013-03-14 10:46:36 -0400
commitf6e58ecf6f0ffde4d3a4abf2e262f0e9c8bc18dd (patch)
tree619394157d82910749bcbf3874560fd417b6888e /target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src
parent23244a7613bb4349c27f23e04174a95dbb18ac0b (diff)
downloadorg.eclipse.tcf-f6e58ecf6f0ffde4d3a4abf2e262f0e9c8bc18dd.tar.gz
org.eclipse.tcf-f6e58ecf6f0ffde4d3a4abf2e262f0e9c8bc18dd.tar.xz
org.eclipse.tcf-f6e58ecf6f0ffde4d3a4abf2e262f0e9c8bc18dd.zip
Target Explorer: fix NPE
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/AbstractServiceManager.java914
1 files changed, 458 insertions, 456 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/AbstractServiceManager.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/AbstractServiceManager.java
index 836e9abf9..38232e45f 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/AbstractServiceManager.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.services/src/org/eclipse/tcf/te/runtime/services/AbstractServiceManager.java
@@ -1,456 +1,458 @@
-/*******************************************************************************
- * 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.services;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-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.Assert;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IExecutableExtension;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.tcf.te.runtime.nls.Messages;
-import org.eclipse.tcf.te.runtime.services.activator.CoreBundleActivator;
-import org.eclipse.tcf.te.runtime.services.interfaces.IService;
-
-/**
- * Abstract service manager implementation.
- */
-public abstract class AbstractServiceManager {
-
- // Map for all contributed services stored by their respective unique id
- private Map<String, ServiceProxy> services = new HashMap<String, ServiceProxy>();
-
- /**
- * Proxy to provide lazy loading of contributing plug-ins.
- */
- protected class ServiceProxy implements IExecutableExtension {
- // Reference to the configuration element
- private IConfigurationElement configElement = null;
- // The id of the service contribution
- public String id;
- // The class implementing the service
- public String clazz;
- // The service instance
- private IService service = null;
- // The list of service types the service is implementing
- private List<Class<? extends IService>> serviceTypes = new ArrayList<Class<? extends IService>>();
- // The converted expression
- private Expression expression;
-
- /**
- * Constructor.
- */
- protected ServiceProxy() {
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
- */
- @Override
- public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
- Assert.isNotNull(config);
- this.configElement = config;
-
- // Initialize the id field by reading the <id> extension attribute.
- // Throws an exception if the id is empty or null.
- id = config.getAttribute("id"); //$NON-NLS-1$
- if (id == null || "".equals(id.trim())) { //$NON-NLS-1$
- throw new CoreException(new Status(IStatus.ERROR,
- CoreBundleActivator.getUniqueIdentifier(),
- NLS.bind(Messages.Extension_error_missingRequiredAttribute, "id", config.getContributor().getName()))); //$NON-NLS-1$
- }
-
- // Read the class attribute. If null, check for the class sub element
- clazz = config.getAttribute("class"); //$NON-NLS-1$
- if (clazz == null) {
- IConfigurationElement[] children = config.getChildren("class"); //$NON-NLS-1$
- // Single element definition assumed (see extension point schema)
- if (children.length > 0) {
- clazz = children[0].getAttribute("class"); //$NON-NLS-1$
- }
- }
- if (clazz == null || "".equals(clazz.trim())) { //$NON-NLS-1$
- throw new CoreException(new Status(IStatus.ERROR,
- CoreBundleActivator.getUniqueIdentifier(),
- NLS.bind(Messages.Extension_error_missingRequiredAttribute, "class", config.getContributor().getName()))); //$NON-NLS-1$
- }
-
- // Read the "enablement" sub element of the extension
- IConfigurationElement[] children = configElement.getChildren("enablement"); //$NON-NLS-1$
- // Only one "enablement" element is expected
- if (children != null && children.length > 0) {
- expression = ExpressionConverter.getDefault().perform(children[0]);
- }
- }
-
- /**
- * Add a type to the proxy. Types are used unless the proxy is instantiated to provide lazy
- * loading of services. After instantiated, a service will be identified only by its type
- * and implementing or extending interfaces or super-types.
- *
- * @param serviceType The type to add.
- */
- public void addType(Class<? extends IService> serviceType) {
- Assert.isNotNull(serviceType);
- if (service == null && serviceTypes != null && !serviceTypes.contains(serviceType)) {
- serviceTypes.add(serviceType);
- }
- }
-
- /**
- * Return the real service instance for this proxy.
- */
- protected IService getService(boolean unique) {
- if ((service == null || unique) && configElement != null) {
- try {
- // Create the service class instance via the configuration element
- Object service = configElement.createExecutableExtension("class"); //$NON-NLS-1$
- if (service instanceof IService) {
- if (unique) {
- return (IService)service;
- }
- this.service = (IService)service;
- }
- else {
- IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), "Service '" + service.getClass().getName() + "' not of type IService."); //$NON-NLS-1$ //$NON-NLS-2$
- Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
- }
- }
- catch (CoreException e) {
- IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), "Cannot create service '" + clazz + "'.", e); //$NON-NLS-1$ //$NON-NLS-2$
- Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
- }
- if (serviceTypes != null) {
- serviceTypes.clear();
- }
- serviceTypes = null;
- }
- return service;
- }
-
- /**
- * Check whether this proxy holds a service that is suitable for the given type.
- *
- * @param serviceType The service type. Must not be <code>null</code>.
- * @return <code>True</code> if the proxy holds a suitable service, <code>false</code> otherwise.
- */
- protected boolean isMatching(Class<? extends IService> serviceType) {
- Assert.isNotNull(serviceType);
-
- if (service != null) {
- return serviceType.isInstance(service);
- }
- else if (configElement != null) {
- if (serviceType.getClass().getName().equals(clazz)) {
- return true;
- }
- for (Class<? extends IService> type : serviceTypes) {
- if (type.equals(serviceType)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Check whether this proxy holds a service that is suitable for the given type.
- *
- * @param serviceTypeName The service type name. Must not be <code>null</code>.
- * @return <code>True</code> if the proxy holds a suitable service, <code>false</code> otherwise.
- */
- protected boolean isMatching(String serviceTypeName) {
- Assert.isNotNull(serviceTypeName);
-
- if (service != null) {
- Class<?> clazz = service.getClass();
- while (clazz != null) {
- Class<?>[] interfaces = clazz.getInterfaces();
- for (Class<?> interfaze : interfaces) {
- if (serviceTypeName.equals(interfaze.getName())) {
- return true;
- }
- }
- clazz = clazz.getSuperclass();
- }
- }
- else if (configElement != null) {
- if (serviceTypeName.equals(clazz)) {
- return true;
- }
- for (Class<? extends IService> type : serviceTypes) {
- if (serviceTypeName.equals(type.getName())) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns if or if not the service contribution is enabled for the given service context.
- * <p>
- * If the given service context is <code>null</code>, only globally unbound services are
- * enabled.
- *
- * @param context The service context or <code>null</code>.
- * @return <code>True</code> if the service contribution is enabled for the given service
- * context, <code>false</code> otherwise.
- */
- protected boolean isEnabled(Object context) {
- if (context == null) {
- return getEnablement() == null;
- }
-
- Expression enablement = getEnablement();
-
- // The service contribution is enabled by default if no expression is specified.
- boolean enabled = enablement == null;
-
- if (enablement != null) {
- // Set the default variable to the service context.
- EvaluationContext evalContext = new EvaluationContext(null, context);
- // Allow plugin activation
- evalContext.setAllowPluginActivation(true);
- // Evaluate the expression
- try {
- enabled = 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);
- }
- }
-
- return enabled;
- }
-
- /**
- * Returns the id of the service contribution.
- *
- * @return The service contribution id.
- */
- protected String getId() {
- return id;
- }
-
- /**
- * Returns the enablement expression.
- *
- * @return The enablement expression or <code>null</code>.
- */
- protected Expression getEnablement() {
- return expression;
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof ServiceProxy) {
- return id != null ? id.equals(((ServiceProxy)obj).id) : ((ServiceProxy)obj).id == null;
- }
- return super.equals(obj);
- }
-
- /* (non-Javadoc)
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return id != null ? id.hashCode() : super.hashCode();
- }
-
- public boolean equals(IService service) {
- Assert.isNotNull(service);
- return clazz != null ? clazz.equals(service.getClass().getCanonicalName()) : false;
- }
-
- public boolean equals(ServiceProxy proxy) {
- Assert.isNotNull(proxy);
- return clazz != null ? clazz.equals(proxy.clazz) : false;
- }
- }
-
- /**
- * Constructor.
- */
- protected AbstractServiceManager() {
- loadServices();
- }
-
- /**
- * Creates a new service proxy instance and initialize it.
- *
- * @param config The configuration element. Must not be <code>null</code>.
- * @return The new service proxy instance.
- */
- protected ServiceProxy getServiceProxy(IConfigurationElement config) {
- Assert.isNotNull(config);
- ServiceProxy proxy = new ServiceProxy();
- try {
- proxy.setInitializationData(config, null, null);
- } catch (CoreException e) {
- if (Platform.inDebugMode()) {
- Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(e.getStatus());
- }
- }
- return proxy;
- }
-
- /**
- * Get a service for the given service context that implements at least the needed service type.
- * <p>
- * If an interface type is given, the service with the highest implementation is returned. This
- * may result in a random selection depending on the extension registration order, especially
- * when a service interface is implemented two times in different hierarchy paths. If a class
- * type is given, if available, the service of exactly that class is returned. Otherwise the
- * highest implementation is returned.
- *
- * @param context The service context or <code>null</code>.
- * @param serviceType The service type the service should at least implement or extend.
- *
- * @return The service or <code>null</code>.
- */
- public <V extends IService> V getService(Object context, Class<? extends V> serviceType) {
- return getService(context, serviceType, false);
- }
-
- /**
- * Get a service for the given service context that implements at least the needed service type.
- * <p>
- * If an interface type is given, the service with the highest implementation is returned. This
- * may result in a random selection depending on the extension registration order, especially
- * when a service interface is implemented two times in different hierarchy paths. If a class
- * type is given, if available, the service of exactly that class is returned. Otherwise the
- * highest implementation is returned.
- *
- * @param context The service context or <code>null</code>.
- * @param serviceType The service type the service should at least implement or extend.
- * @param unique <code>true</code> if a new instance of the service is needed.
- *
- * @return The service or <code>null</code>.
- */
- @SuppressWarnings("unchecked")
- public <V extends IService> V getService(Object context, Class<? extends V> serviceType, boolean unique) {
- Assert.isNotNull(serviceType);
-
- Collection<ServiceProxy> proxies = services.values();
- if (!proxies.isEmpty()) {
- List<ServiceProxy> candidates = new ArrayList<ServiceProxy>();
- boolean isInterface = serviceType.isInterface();
- for (ServiceProxy proxy : proxies) {
- if (proxy.isMatching(serviceType) && proxy.isEnabled(context)) {
- if (!isInterface) {
- V service = (V)proxy.getService(unique);
- service.setId(proxy.getId());
- return service;
- }
- candidates.add(proxy);
- }
- }
-
- V service = null;
- if (!candidates.isEmpty()) {
- service = (V)candidates.get(0).getService(unique);
- service.setId(candidates.get(0).getId());
- }
-
- return service;
- }
-
- return null;
- }
-
- /**
- * Get a service list for the given service context that implements at least the needed service type.
- *
- * @param context The service context or <code>null</code>.
- * @param serviceType The service type the service should at least implement or extend.
- * @param unique <code>true</code> if a new instance of the service is needed.
- *
- * @return The service list or empty list.
- */
- public IService[] getServices(Object context, Class<? extends IService> serviceType, boolean unique) {
- Assert.isNotNull(serviceType);
-
- Collection<ServiceProxy> proxies = services.values();
- List<IService> services = new ArrayList<IService>();
- if (!proxies.isEmpty()) {
- List<ServiceProxy> candidates = new ArrayList<ServiceProxy>();
- for (ServiceProxy proxy : proxies) {
- if (proxy.isMatching(serviceType) && proxy.isEnabled(context)) {
- candidates.add(proxy);
- }
- }
- for (ServiceProxy serviceProxy : candidates) {
- IService service = serviceProxy.getService(unique);
- service.setId(serviceProxy.getId());
- services.add(service);
- }
- }
- return services.toArray(new IService[services.size()]);
- }
-
- /**
- * Adds the given service to the service proxy map.
- */
- protected void addService(ServiceProxy proxy) {
- Assert.isNotNull(services);
- Assert.isNotNull(proxy);
-
- String id = proxy.getId();
- Assert.isNotNull(id);
- services.put(id, proxy);
- }
-
- /**
- * Returns if or if not a service contribution for the given service context, implementing the
- * given service type, exist.
- *
- * @param context The service context or <code>null</code>.
- * @param serviceTypeName The name of a service type the service should at least implement or extend.
- *
- * @return <code>True</code> if a matching service contribution exist, <code>false</code> otherwise.
- */
- public boolean hasService(Object context, String serviceTypeName) {
- Assert.isNotNull(serviceTypeName);
-
- // Get all service contributions
- Collection<ServiceProxy> proxies = services.values();
- if (!proxies.isEmpty()) {
- for (ServiceProxy proxy : proxies) {
- if (proxy.isMatching(serviceTypeName) && proxy.isEnabled(context)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
-
- /**
- * Loads the contributed services into proxies (lazy loading!!) and adds them to this manager;
- */
- protected abstract void loadServices();
-}
+/*******************************************************************************
+ * 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.services;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.tcf.te.runtime.nls.Messages;
+import org.eclipse.tcf.te.runtime.services.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.services.interfaces.IService;
+
+/**
+ * Abstract service manager implementation.
+ */
+public abstract class AbstractServiceManager {
+
+ // Map for all contributed services stored by their respective unique id
+ private Map<String, ServiceProxy> services = new HashMap<String, ServiceProxy>();
+
+ /**
+ * Proxy to provide lazy loading of contributing plug-ins.
+ */
+ protected class ServiceProxy implements IExecutableExtension {
+ // Reference to the configuration element
+ private IConfigurationElement configElement = null;
+ // The id of the service contribution
+ public String id;
+ // The class implementing the service
+ public String clazz;
+ // The service instance
+ private IService service = null;
+ // The list of service types the service is implementing
+ private List<Class<? extends IService>> serviceTypes = new ArrayList<Class<? extends IService>>();
+ // The converted expression
+ private Expression expression;
+
+ /**
+ * Constructor.
+ */
+ protected ServiceProxy() {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ Assert.isNotNull(config);
+ this.configElement = config;
+
+ // Initialize the id field by reading the <id> extension attribute.
+ // Throws an exception if the id is empty or null.
+ id = config.getAttribute("id"); //$NON-NLS-1$
+ if (id == null || "".equals(id.trim())) { //$NON-NLS-1$
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ NLS.bind(Messages.Extension_error_missingRequiredAttribute, "id", config.getContributor().getName()))); //$NON-NLS-1$
+ }
+
+ // Read the class attribute. If null, check for the class sub element
+ clazz = config.getAttribute("class"); //$NON-NLS-1$
+ if (clazz == null) {
+ IConfigurationElement[] children = config.getChildren("class"); //$NON-NLS-1$
+ // Single element definition assumed (see extension point schema)
+ if (children.length > 0) {
+ clazz = children[0].getAttribute("class"); //$NON-NLS-1$
+ }
+ }
+ if (clazz == null || "".equals(clazz.trim())) { //$NON-NLS-1$
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ NLS.bind(Messages.Extension_error_missingRequiredAttribute, "class", config.getContributor().getName()))); //$NON-NLS-1$
+ }
+
+ // Read the "enablement" sub element of the extension
+ IConfigurationElement[] children = configElement.getChildren("enablement"); //$NON-NLS-1$
+ // Only one "enablement" element is expected
+ if (children != null && children.length > 0) {
+ expression = ExpressionConverter.getDefault().perform(children[0]);
+ }
+ }
+
+ /**
+ * Add a type to the proxy. Types are used unless the proxy is instantiated to provide lazy
+ * loading of services. After instantiated, a service will be identified only by its type
+ * and implementing or extending interfaces or super-types.
+ *
+ * @param serviceType The type to add.
+ */
+ public void addType(Class<? extends IService> serviceType) {
+ Assert.isNotNull(serviceType);
+ if (service == null && serviceTypes != null && !serviceTypes.contains(serviceType)) {
+ serviceTypes.add(serviceType);
+ }
+ }
+
+ /**
+ * Return the real service instance for this proxy.
+ */
+ protected IService getService(boolean unique) {
+ if ((service == null || unique) && configElement != null) {
+ try {
+ // Create the service class instance via the configuration element
+ Object service = configElement.createExecutableExtension("class"); //$NON-NLS-1$
+ if (service instanceof IService) {
+ if (unique) {
+ return (IService)service;
+ }
+ this.service = (IService)service;
+ }
+ else {
+ IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), "Service '" + service.getClass().getName() + "' not of type IService."); //$NON-NLS-1$ //$NON-NLS-2$
+ Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
+ }
+ }
+ catch (CoreException e) {
+ IStatus status = new Status(IStatus.ERROR, CoreBundleActivator.getUniqueIdentifier(), "Cannot create service '" + clazz + "'.", e); //$NON-NLS-1$ //$NON-NLS-2$
+ Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
+ }
+ if (serviceTypes != null) {
+ serviceTypes.clear();
+ }
+ serviceTypes = null;
+ }
+ return service;
+ }
+
+ /**
+ * Check whether this proxy holds a service that is suitable for the given type.
+ *
+ * @param serviceType The service type. Must not be <code>null</code>.
+ * @return <code>True</code> if the proxy holds a suitable service, <code>false</code> otherwise.
+ */
+ protected boolean isMatching(Class<? extends IService> serviceType) {
+ Assert.isNotNull(serviceType);
+
+ if (service != null) {
+ return serviceType.isInstance(service);
+ }
+ else if (configElement != null) {
+ if (serviceType.getClass().getName().equals(clazz)) {
+ return true;
+ }
+ if (serviceTypes != null) {
+ for (Class<? extends IService> type : serviceTypes) {
+ if (type.equals(serviceType)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check whether this proxy holds a service that is suitable for the given type.
+ *
+ * @param serviceTypeName The service type name. Must not be <code>null</code>.
+ * @return <code>True</code> if the proxy holds a suitable service, <code>false</code> otherwise.
+ */
+ protected boolean isMatching(String serviceTypeName) {
+ Assert.isNotNull(serviceTypeName);
+
+ if (service != null) {
+ Class<?> clazz = service.getClass();
+ while (clazz != null) {
+ Class<?>[] interfaces = clazz.getInterfaces();
+ for (Class<?> interfaze : interfaces) {
+ if (serviceTypeName.equals(interfaze.getName())) {
+ return true;
+ }
+ }
+ clazz = clazz.getSuperclass();
+ }
+ }
+ else if (configElement != null) {
+ if (serviceTypeName.equals(clazz)) {
+ return true;
+ }
+ for (Class<? extends IService> type : serviceTypes) {
+ if (serviceTypeName.equals(type.getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns if or if not the service contribution is enabled for the given service context.
+ * <p>
+ * If the given service context is <code>null</code>, only globally unbound services are
+ * enabled.
+ *
+ * @param context The service context or <code>null</code>.
+ * @return <code>True</code> if the service contribution is enabled for the given service
+ * context, <code>false</code> otherwise.
+ */
+ protected boolean isEnabled(Object context) {
+ if (context == null) {
+ return getEnablement() == null;
+ }
+
+ Expression enablement = getEnablement();
+
+ // The service contribution is enabled by default if no expression is specified.
+ boolean enabled = enablement == null;
+
+ if (enablement != null) {
+ // Set the default variable to the service context.
+ EvaluationContext evalContext = new EvaluationContext(null, context);
+ // Allow plugin activation
+ evalContext.setAllowPluginActivation(true);
+ // Evaluate the expression
+ try {
+ enabled = 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);
+ }
+ }
+
+ return enabled;
+ }
+
+ /**
+ * Returns the id of the service contribution.
+ *
+ * @return The service contribution id.
+ */
+ protected String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the enablement expression.
+ *
+ * @return The enablement expression or <code>null</code>.
+ */
+ protected Expression getEnablement() {
+ return expression;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ServiceProxy) {
+ return id != null ? id.equals(((ServiceProxy)obj).id) : ((ServiceProxy)obj).id == null;
+ }
+ return super.equals(obj);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return id != null ? id.hashCode() : super.hashCode();
+ }
+
+ public boolean equals(IService service) {
+ Assert.isNotNull(service);
+ return clazz != null ? clazz.equals(service.getClass().getCanonicalName()) : false;
+ }
+
+ public boolean equals(ServiceProxy proxy) {
+ Assert.isNotNull(proxy);
+ return clazz != null ? clazz.equals(proxy.clazz) : false;
+ }
+ }
+
+ /**
+ * Constructor.
+ */
+ protected AbstractServiceManager() {
+ loadServices();
+ }
+
+ /**
+ * Creates a new service proxy instance and initialize it.
+ *
+ * @param config The configuration element. Must not be <code>null</code>.
+ * @return The new service proxy instance.
+ */
+ protected ServiceProxy getServiceProxy(IConfigurationElement config) {
+ Assert.isNotNull(config);
+ ServiceProxy proxy = new ServiceProxy();
+ try {
+ proxy.setInitializationData(config, null, null);
+ } catch (CoreException e) {
+ if (Platform.inDebugMode()) {
+ Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(e.getStatus());
+ }
+ }
+ return proxy;
+ }
+
+ /**
+ * Get a service for the given service context that implements at least the needed service type.
+ * <p>
+ * If an interface type is given, the service with the highest implementation is returned. This
+ * may result in a random selection depending on the extension registration order, especially
+ * when a service interface is implemented two times in different hierarchy paths. If a class
+ * type is given, if available, the service of exactly that class is returned. Otherwise the
+ * highest implementation is returned.
+ *
+ * @param context The service context or <code>null</code>.
+ * @param serviceType The service type the service should at least implement or extend.
+ *
+ * @return The service or <code>null</code>.
+ */
+ public <V extends IService> V getService(Object context, Class<? extends V> serviceType) {
+ return getService(context, serviceType, false);
+ }
+
+ /**
+ * Get a service for the given service context that implements at least the needed service type.
+ * <p>
+ * If an interface type is given, the service with the highest implementation is returned. This
+ * may result in a random selection depending on the extension registration order, especially
+ * when a service interface is implemented two times in different hierarchy paths. If a class
+ * type is given, if available, the service of exactly that class is returned. Otherwise the
+ * highest implementation is returned.
+ *
+ * @param context The service context or <code>null</code>.
+ * @param serviceType The service type the service should at least implement or extend.
+ * @param unique <code>true</code> if a new instance of the service is needed.
+ *
+ * @return The service or <code>null</code>.
+ */
+ @SuppressWarnings("unchecked")
+ public <V extends IService> V getService(Object context, Class<? extends V> serviceType, boolean unique) {
+ Assert.isNotNull(serviceType);
+
+ Collection<ServiceProxy> proxies = services.values();
+ if (!proxies.isEmpty()) {
+ List<ServiceProxy> candidates = new ArrayList<ServiceProxy>();
+ boolean isInterface = serviceType.isInterface();
+ for (ServiceProxy proxy : proxies) {
+ if (proxy.isMatching(serviceType) && proxy.isEnabled(context)) {
+ if (!isInterface) {
+ V service = (V)proxy.getService(unique);
+ service.setId(proxy.getId());
+ return service;
+ }
+ candidates.add(proxy);
+ }
+ }
+
+ V service = null;
+ if (!candidates.isEmpty()) {
+ service = (V)candidates.get(0).getService(unique);
+ service.setId(candidates.get(0).getId());
+ }
+
+ return service;
+ }
+
+ return null;
+ }
+
+ /**
+ * Get a service list for the given service context that implements at least the needed service type.
+ *
+ * @param context The service context or <code>null</code>.
+ * @param serviceType The service type the service should at least implement or extend.
+ * @param unique <code>true</code> if a new instance of the service is needed.
+ *
+ * @return The service list or empty list.
+ */
+ public IService[] getServices(Object context, Class<? extends IService> serviceType, boolean unique) {
+ Assert.isNotNull(serviceType);
+
+ Collection<ServiceProxy> proxies = services.values();
+ List<IService> services = new ArrayList<IService>();
+ if (!proxies.isEmpty()) {
+ List<ServiceProxy> candidates = new ArrayList<ServiceProxy>();
+ for (ServiceProxy proxy : proxies) {
+ if (proxy.isMatching(serviceType) && proxy.isEnabled(context)) {
+ candidates.add(proxy);
+ }
+ }
+ for (ServiceProxy serviceProxy : candidates) {
+ IService service = serviceProxy.getService(unique);
+ service.setId(serviceProxy.getId());
+ services.add(service);
+ }
+ }
+ return services.toArray(new IService[services.size()]);
+ }
+
+ /**
+ * Adds the given service to the service proxy map.
+ */
+ protected void addService(ServiceProxy proxy) {
+ Assert.isNotNull(services);
+ Assert.isNotNull(proxy);
+
+ String id = proxy.getId();
+ Assert.isNotNull(id);
+ services.put(id, proxy);
+ }
+
+ /**
+ * Returns if or if not a service contribution for the given service context, implementing the
+ * given service type, exist.
+ *
+ * @param context The service context or <code>null</code>.
+ * @param serviceTypeName The name of a service type the service should at least implement or extend.
+ *
+ * @return <code>True</code> if a matching service contribution exist, <code>false</code> otherwise.
+ */
+ public boolean hasService(Object context, String serviceTypeName) {
+ Assert.isNotNull(serviceTypeName);
+
+ // Get all service contributions
+ Collection<ServiceProxy> proxies = services.values();
+ if (!proxies.isEmpty()) {
+ for (ServiceProxy proxy : proxies) {
+ if (proxy.isMatching(serviceTypeName) && proxy.isEnabled(context)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Loads the contributed services into proxies (lazy loading!!) and adds them to this manager;
+ */
+ protected abstract void loadServices();
+}

Back to the top