Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tm.te.runtime.services/src/org/eclipse/tm/te/runtime/services/AbstractServiceManager.java')
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.runtime.services/src/org/eclipse/tm/te/runtime/services/AbstractServiceManager.java278
1 files changed, 278 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tm.te.runtime.services/src/org/eclipse/tm/te/runtime/services/AbstractServiceManager.java b/target_explorer/plugins/org.eclipse.tm.te.runtime.services/src/org/eclipse/tm/te/runtime/services/AbstractServiceManager.java
new file mode 100644
index 000000000..167803720
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.runtime.services/src/org/eclipse/tm/te/runtime/services/AbstractServiceManager.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.tm.te.runtime.services;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+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.tm.te.runtime.activator.CoreBundleActivator;
+import org.eclipse.tm.te.runtime.services.interfaces.IService;
+
+/**
+ * Abstract service manager implementation.
+ */
+public abstract class AbstractServiceManager<ServiceClass extends IService> {
+
+ // map for all services per id
+ private Map<String, List<ServiceProxy>> services = new HashMap<String, List<ServiceProxy>>();
+
+ /**
+ * Proxy to provide lazy loading of contributing plug-ins.
+ */
+ protected class ServiceProxy {
+
+ private IConfigurationElement configElement = null;
+ public String clazz;
+ private ServiceClass service = null;
+ private List<Class<? extends ServiceClass>> serviceTypes = new ArrayList<Class<? extends ServiceClass>>();
+
+ /**
+ * Constructor.
+ */
+ protected ServiceProxy(IConfigurationElement configElement) {
+ Assert.isNotNull(configElement);
+ this.configElement = configElement;
+
+ // Read the class attribute. If null, check for the class sub element
+ clazz = configElement.getAttribute("class"); //$NON-NLS-1$
+ if (clazz == null) {
+ IConfigurationElement[] children = configElement.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$
+ }
+ }
+ }
+
+ /**
+ * 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 ServiceClass> serviceType) {
+ assert serviceType != null;
+ if (service == null && serviceTypes != null && !serviceTypes.contains(serviceType)) {
+ serviceTypes.add(serviceType);
+ }
+ }
+
+ /**
+ * Return the real service instance for this proxy.
+ */
+ @SuppressWarnings("unchecked")
+ protected ServiceClass getService(boolean unique) {
+ if ((service == null || unique) && configElement != null) {
+ try {
+ Object service = configElement.createExecutableExtension("class"); //$NON-NLS-1$
+ if (service instanceof IService) {
+ if (unique) {
+ return (ServiceClass) service;
+ }
+ else if (service instanceof IService) {
+ this.service = (ServiceClass)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
+ * @return
+ */
+ protected boolean isMatching(Class<? extends ServiceClass> serviceType) {
+ if (service != null) {
+ return serviceType.isInstance(service);
+ }
+ else if (configElement != null) {
+ if (serviceType.getClass().getName().equals(clazz)) {
+ return true;
+ }
+ for (Class<? extends ServiceClass> type : serviceTypes) {
+ if (type.equals(serviceType)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean equals(ServiceClass service) {
+ return clazz.equals(service.getClass());
+ }
+
+ public boolean equals(ServiceProxy proxy) {
+ return clazz.equals(proxy.clazz);
+ }
+ }
+
+ /**
+ * Constructor.
+ */
+ protected AbstractServiceManager() {
+ loadServices();
+ }
+
+ /**
+ * @param element
+ * @return
+ */
+ protected ServiceProxy getServiceProxy(IConfigurationElement element) {
+ return new ServiceProxy(element);
+ }
+
+ /**
+ * Returns all id's of the registered services.
+ *
+ * @return The list of id's of the registered services.
+ */
+ public String[] getIds() {
+ return services.keySet().toArray(new String[services.keySet().size()]);
+ }
+
+ /**
+ * Get a service for the id that implements at least the needed service type. 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 id The id for which a service is needed.
+ * @param serviceType The service type the service should at least implement or extend.
+ * @return The service or <code>null</code>.
+ */
+ public ServiceClass getService(String id, Class<? extends ServiceClass> serviceType) {
+ return getService(id, serviceType, false);
+ }
+
+ /**
+ * Get a service for the id that implements at least the needed service type. 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 id The id for which a service is needed.
+ * @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>.
+ */
+ public ServiceClass getService(String id, Class<? extends ServiceClass> serviceType, boolean unique) {
+ assert serviceType != null;
+ if (id == null) {
+ id = ""; //$NON-NLS-1$
+ }
+ List<ServiceProxy> proxies = services.get(id);
+ if (proxies != null && !proxies.isEmpty()) {
+ List<ServiceProxy> candidates = new ArrayList<ServiceProxy>();
+ boolean isInterface = serviceType.isInterface();
+ for (ServiceProxy proxy : proxies) {
+ if (proxy.isMatching(serviceType)) {
+ if (!isInterface && proxy.equals(serviceType)) {
+ ServiceClass service = proxy.getService(unique);
+ service.setId(id);
+ return service;
+ }
+ candidates.add(proxy);
+ }
+ }
+ ServiceClass service = null;
+ if (!candidates.isEmpty()) {
+ service = candidates.get(0).getService(unique);
+ service.setId(id);
+ }
+
+ return service;
+ }
+ return null;
+ }
+
+ /**
+ * Get a service list for the id that implements at least the needed service type.
+ *
+ * @param id The id for which a service is needed.
+ * @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(String id, Class<? extends ServiceClass> serviceType, boolean unique) {
+ assert serviceType != null;
+ if (id == null) {
+ id = ""; //$NON-NLS-1$
+ }
+ List<ServiceProxy> proxies = services.get(id);
+ List<IService> services = new ArrayList<IService>();
+ if (proxies != null && !proxies.isEmpty()) {
+ List<ServiceProxy> candidates = new ArrayList<ServiceProxy>();
+ for (ServiceProxy proxy : proxies) {
+ if (proxy.isMatching(serviceType)) {
+ candidates.add(proxy);
+ }
+ }
+ for (ServiceProxy serviceProxy : candidates) {
+ IService service = serviceProxy.getService(unique);
+ service.setId(id);
+ services.add(service);
+ }
+ }
+ return services.toArray(new IService[services.size()]);
+ }
+
+ /*
+ * Add a service proxy to the list of available services.
+ */
+ protected boolean addService(String id, ServiceProxy proxy) {
+ assert services != null && id != null && proxy != null;
+ List<ServiceProxy> proxies = services.get(id);
+ if (proxies == null) {
+ proxies = new ArrayList<ServiceProxy>();
+ services.put(id, proxies);
+ }
+ assert proxies != null;
+ if (proxies.isEmpty() || !proxies.contains(proxy)) {
+ return proxies.add(proxy);
+ }
+ return false;
+ }
+
+ /**
+ * Loads the contributed services into proxies (lazy loading!!) and adds them to this manager;
+ */
+ protected abstract void loadServices();
+}

Back to the top