/*******************************************************************************
* Copyright (c) 2011, 2014 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 org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
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.activator.CoreBundleActivator;
import org.eclipse.tcf.te.runtime.services.interfaces.IService;
import org.eclipse.tcf.te.runtime.services.nls.Messages;
import org.osgi.framework.Bundle;
/**
* Common service manager implementation, handling the extension point
* <code>org.eclipse.tcf.te.runtime.services</code>.
*/
public class ServiceManager extends AbstractServiceManager {
/*
* Thread save singleton instance creation.
*/
private static class LazyInstance {
public static ServiceManager instance = new ServiceManager();
}
/**
* Constructor.
*/
ServiceManager() {
super();
}
/**
* Returns the singleton instance of the service manager.
*/
public static ServiceManager getInstance() {
return LazyInstance.instance;
}
/**
* Get a global unbound service 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 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(Class<? extends V> serviceType, boolean unique) {
return super.getService(null, serviceType, unique);
}
/**
* Get a global unbound service 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 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(Class<? extends V> serviceType) {
return super.getService(null, serviceType);
}
/* (non-Javadoc)
* @see org.eclipse.tcf.te.runtime.services.AbstractServiceManager#loadServices()
*/
@SuppressWarnings("unchecked")
@Override
protected void loadServices() {
IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint("org.eclipse.tcf.te.runtime.services.services"); //$NON-NLS-1$
if (ep != null) {
IExtension[] extensions = ep.getExtensions();
if (extensions != null) {
for (IExtension extension : extensions) {
IConfigurationElement[] configElements = extension.getConfigurationElements();
if (configElements != null) {
for (IConfigurationElement configElement : configElements) {
if ("service".equals(configElement.getName())) { //$NON-NLS-1$
ServiceProxy proxy = getServiceProxy(configElement);
IConfigurationElement[] serviceTypes = configElement.getChildren("serviceType"); //$NON-NLS-1$
if (serviceTypes != null && serviceTypes.length > 0) {
for (IConfigurationElement serviceType : serviceTypes) {
try {
String type = serviceType.getAttribute("class"); //$NON-NLS-1$
String bundleId = serviceType.getAttribute("bundleId"); //$NON-NLS-1$
// If a bundle id got specified, use the specified bundle to load the service class
Bundle bundle = bundleId != null ? bundle = Platform.getBundle(bundleId) : null;
// If we don't have a bundle to load from yet, fallback to the declaring bundle
if (bundle == null) bundle = Platform.getBundle(configElement.getDeclaringExtension().getNamespaceIdentifier());
// And finally, use our own bundle to load the class.
// This fallback is expected to never be used.
if (bundle == null) bundle = CoreBundleActivator.getContext().getBundle();
// Try to load the service type class now.
Class<?> typeClass = bundle != null ? bundle.loadClass(type) : Class.forName(type);
proxy.addType((Class<IService>)typeClass);
}
catch (Exception e) {
IStatus status = new Status(IStatus.WARNING, CoreBundleActivator.getUniqueIdentifier(),
NLS.bind(Messages.ServiceManager_warning_failedToLoadServiceType, serviceType.getAttribute("class"), configElement.getAttribute("class")), e); //$NON-NLS-1$ //$NON-NLS-2$
Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
}
}
}
addService(proxy);
}
}
}
}
}
}
}
}