/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.equinox.device; import org.osgi.framework.ServiceReference; import org.osgi.service.device.Device; import org.osgi.service.device.DriverSelector; import org.osgi.service.log.LogService; import org.osgi.util.tracker.ServiceTracker; /** * DriverSelectorTracker class. This class tracks all DriverSelector services. * */ public class DriverSelectorTracker extends ServiceTracker { /** Driver service name */ protected final static String clazz = "org.osgi.service.device.DriverSelector"; //$NON-NLS-1$ /** LogService object */ protected LogService log; /** DeviceManager object. */ protected Activator manager; /** * Create the DriverTracker. * * @param manager DeviceManager object. * @param device DeviceTracker we are working for. */ public DriverSelectorTracker(Activator manager) { super(manager.context, clazz, null); this.manager = manager; log = manager.log; if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, "DriverSelectorTracker constructor"); //$NON-NLS-1$ } open(); } /** * Select the matching driver. * * @param device Device service being matched. * @param matches Array of the successful matches from Driver services. * @return ServiceReference to best matched Driver or null of their is no match. */ public ServiceReference select(ServiceReference device, Match[] matches) { if (Activator.DEBUG) { log.log(device, LogService.LOG_DEBUG, "DriverSelector select called"); //$NON-NLS-1$ } //This should give us the highest ranking DriverSelector (if available) ServiceReference selector = getServiceReference(); if (selector != null) { DriverSelector service = (DriverSelector) getService(selector); try { int index = service.select(device, matches); if (index == DriverSelector.SELECT_NONE) { return null; } return matches[index].getDriver(); } catch (Throwable t) { log.log(selector, LogService.LOG_ERROR, DeviceMsg.DriverSelector_error_during_match, t); } } return defaultSelection(matches); } /** * Default match selection algorithm from OSGi SPR2 spec. * * @param matchArray An array of the successful matches. * @return ServiceReference to the selected Driver service */ public ServiceReference defaultSelection(Match[] matches) { int size = matches.length; int max = Device.MATCH_NONE; ServiceReference reference = null; for (int i = 0; i < size; i++) { Match driver = matches[i]; int match = driver.getMatchValue(); if (match >= max) { if (match == max) /* we must break the tie */ { reference = breakTie(reference, driver.getDriver()); } else { max = match; reference = driver.getDriver(); } } } return reference; } /** * Select the service with the highest service.ranking. Break ties * buy selecting the lowest service.id. * */ public ServiceReference breakTie(ServiceReference ref1, ServiceReference ref2) { //first we check service rankings Object property = ref1.getProperty(org.osgi.framework.Constants.SERVICE_RANKING); int ref1Ranking = (property instanceof Integer) ? ((Integer) property).intValue() : 0; property = ref2.getProperty(org.osgi.framework.Constants.SERVICE_RANKING); int ref2Ranking = (property instanceof Integer) ? ((Integer) property).intValue() : 0; if (ref1Ranking > ref2Ranking) { return ref1; } else if (ref2Ranking > ref1Ranking) { return ref2; } else // The rankings must match here { //we now check service ids long ref1ID = ((Long) (ref1.getProperty(org.osgi.framework.Constants.SERVICE_ID))).longValue(); long ref2ID = ((Long) (ref2.getProperty(org.osgi.framework.Constants.SERVICE_ID))).longValue(); if (ref1ID < ref2ID) { return ref1; } return ref2; } } }