blob: a2575dab9faf185a09868220ad2f301589c14271 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.service;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.scout.commons.logger.IScoutLogger;
import org.eclipse.scout.commons.logger.ScoutLogManager;
import org.eclipse.scout.service.internal.Activator;
import org.eclipse.scout.service.internal.ServicesExtensionManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
/**
* Utility class for querying registered OSGi services
* <p>
* There might be log warnings when a service returns null due to factory visiblity decisions. see bug
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=299351 (solved with eclipse 3.6)
* <p>
* see also {@link INullService}
* <p>
* Since 4.0 there is a service cache for much better performance. Set the config.ini property
* <code>org.eclipse.scout.service.cache.enabled=true</code> to use it. Call {@link #clearCache()} to clear it at
* runtime.
*/
public final class SERVICES {
private static final IScoutLogger LOG = ScoutLogManager.getLogger(SERVICES.class);
private SERVICES() {
}
/**
* @param serviceInterfaceClass
* The interface or class name with which the service was registered.
* @return the service with the highest ranking or <code>null</code>, if the service is not found.
*/
public static <T extends Object> T getService(Class<T> serviceInterfaceClass) {
return getService(serviceInterfaceClass, null);
}
/**
* @param serviceInterfaceClass
* The interface or class name with which the service was registered.
* @param filter
* The filter expression or {@code null}. Invalid filter expressions are ignored.
* @return the service with the highest ranking
*/
public static <T extends Object> T getService(Class<T> serviceInterfaceClass, String filter) {
Activator a = Activator.getDefault();
if (a == null || serviceInterfaceClass == null) {
return null;
}
// start the tracker, blocks until all service factories have been registered
ServicesExtensionManager extMgr = a.getServicesExtensionManager();
extMgr.start();
BundleContext context = a.getBundle().getBundleContext();
if (context == null) {
return null;
}
ServiceReference serviceReference = null;
if (filter == null) {
//If no filter is specified directly get the serviceReference with the highest ranking
serviceReference = context.getServiceReference(serviceInterfaceClass.getName());
if (serviceReference != null) {
T service = extMgr.fastResolveService(serviceInterfaceClass, context, serviceReference);
if (service != null) {
return service;
}
}
}
ServiceReference[] refs = null;
try {
refs = context.getAllServiceReferences(serviceInterfaceClass.getName(), filter);
}
catch (InvalidSyntaxException e) {
// nop
}
if (refs != null) {
for (ServiceReference ref : refs) {
T service = extMgr.fastResolveService(serviceInterfaceClass, context, ref);
if (service != null) {
return service;
}
}
}
return null;
}
/**
* @return the services ordered by ranking or an empty array, if no services are found.
*/
public static <T extends Object> T[] getServices(Class<T> serviceInterfaceClass) {
return getServices(serviceInterfaceClass, null);
}
/**
* @param serviceInterfaceClass
* The interface or class name with which the service was registered.
* @param filter
* The filter expression or {@code null}. Invalid filter expressions are ignored.
* @return the services ordered by ranking or an empty array, if no services are found.
*/
@SuppressWarnings("unchecked")
public static <T extends Object> T[] getServices(Class<T> serviceInterfaceClass, String filter) {
Activator a = Activator.getDefault();
if (a == null || serviceInterfaceClass == null) {
return (T[]) Array.newInstance(serviceInterfaceClass, 0);
}
// start the tracker, blocks until all service factories have been
// registered
ServicesExtensionManager extMgr = a.getServicesExtensionManager();
extMgr.start();
BundleContext context = a.getBundle().getBundleContext();
if (context == null) {
return (T[]) Array.newInstance(serviceInterfaceClass, 0);
}
ServiceReference[] refs = null;
try {
refs = context.getAllServiceReferences(serviceInterfaceClass.getName(), filter);
}
catch (InvalidSyntaxException e) {
// nop
}
if (refs != null) {
Arrays.sort(refs, new Comparator<ServiceReference>() {
@Override
public int compare(ServiceReference ref1, ServiceReference ref2) {
return ((Comparable) ref2.getProperty(Constants.SERVICE_RANKING)).compareTo(((Comparable) ref1.getProperty(Constants.SERVICE_RANKING)));
}
});
ArrayList<T> list = new ArrayList<T>(refs.length);
for (ServiceReference ref : refs) {
T s = extMgr.fastResolveService(serviceInterfaceClass, context, ref);
if (s != null) {
list.add((T) s);
}
}
return list.toArray((T[]) Array.newInstance(serviceInterfaceClass, list.size()));
}
return (T[]) Array.newInstance(serviceInterfaceClass, 0);
}
/**
* Clear the services cache that speeds up service lookup.
* <p>
* This does not affect the registered services it is only clears the lookup cache.
*
* @since 4.0
*/
public static void clearCache() {
Activator a = Activator.getDefault();
if (a == null) {
return;
}
ServicesExtensionManager extMgr = a.getServicesExtensionManager();
extMgr.clearDirectAccessorCache();
}
}