/******************************************************************************* * Copyright (c) 2000, 2007 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 java.io.InputStream; import java.util.Dictionary; import java.util.Vector; import org.eclipse.osgi.util.NLS; import org.osgi.framework.*; import org.osgi.service.device.DriverLocator; import org.osgi.service.log.LogService; import org.osgi.util.tracker.ServiceTracker; /** * DriverLocatorTracker class. This class tracks all DriverLocator services. * */ public class DriverLocatorTracker extends ServiceTracker { protected final static String clazz = "org.osgi.service.device.DriverLocator"; //$NON-NLS-1$ /** DeviceManager object. */ protected Activator manager; /** LogService object */ protected LogService log; /** List of bundles to be uninstalled. */ protected Vector bundles; /** * Create the DriverLocatorTracker. * * @param context Device manager bundle context. * @param log LogService object */ public DriverLocatorTracker(Activator manager) { super(manager.context, clazz, null); this.manager = manager; log = manager.log; bundles = new Vector(10, 10); if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, "DriverLocatorTracker constructor"); //$NON-NLS-1$ } open(); } /** * A service is being added to the ServiceTracker. * * <p>This method is called before a service which matched * the search parameters of the ServiceTracker is * added to the ServiceTracker. This method should return the * service object to be tracked for this ServiceReference. * The returned service object is stored in the ServiceTracker * and is available from the getService and getServices * methods. * * @param reference Reference to service being added to the ServiceTracker. * @return The service object to be tracked for the * ServiceReference or <tt>null</tt> if the ServiceReference should not * be tracked. */ public Object addingService(ServiceReference reference) { if (Activator.DEBUG) { log.log(reference, LogService.LOG_DEBUG, "DriverLocatorTracker adding service"); //$NON-NLS-1$ } return (context.getService(reference)); } /** * A service tracked by the ServiceTracker has been modified. * * <p>This method is called when a service being tracked * by the ServiceTracker has had it properties modified. * * @param reference Reference to service that has been modified. * @param service The service object for the modified service. */ public void modifiedService(ServiceReference reference, Object service) { //do nothing } /** * A service tracked by the ServiceTracker is being removed. * * <p>This method is called after a service is no longer being tracked * by the ServiceTracker. * * @param reference Reference to service that has been removed. * @param service The service object for the removed service. */ public void removedService(ServiceReference reference, Object object) { if (Activator.DEBUG) { log.log(reference, LogService.LOG_DEBUG, "DriverLocatorTracker removing service"); //$NON-NLS-1$ } context.ungetService(reference); } /** * Call the DriverLocator services in an attempt to locate and * install driver bundles to refine the device service. * * @param locators Array of DriverLocator objects * @param drivers Dictionary of drivers with key=DRIVER_ID, value=Driver object */ public void loadDrivers(Dictionary properties, DriverTracker drivers) { if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, Thread.currentThread().getName() + ": DriverLocatorTracker loadDrivers called"); //$NON-NLS-1$ } ServiceReference[] references = getServiceReferences(); if (references != null) { int size = references.length; for (int i = 0; i < size; i++) { ServiceReference locator = references[i]; DriverLocator service = (DriverLocator) getService(locator); if (service != null) { if (Activator.DEBUG) { log.log(locator, LogService.LOG_DEBUG, Thread.currentThread().getName() + ": DriverLocator findDrivers called"); //$NON-NLS-1$ } try { String[] driver_ids = service.findDrivers(properties); if (Activator.DEBUG) { int count = (driver_ids == null) ? 0 : driver_ids.length; StringBuffer sb = new StringBuffer(); sb.append('<'); for (int k = 0; k < count; k++) { if (k > 0) { sb.append(','); } sb.append(driver_ids[k]); } sb.append('>'); log.log(locator, LogService.LOG_DEBUG, Thread.currentThread().getName() + ": DriverLocator findDrivers returned: " + sb); //$NON-NLS-1$ } if (driver_ids != null) { int count = driver_ids.length; for (int j = 0; j < count; j++) { String driver_id = driver_ids[j]; if (drivers.getDriver(driver_id) == null) { if (Activator.DEBUG) { log.log(locator, LogService.LOG_DEBUG, Thread.currentThread().getName() + ": DriverLocator loadDriver called for driver: " + driver_id); //$NON-NLS-1$ } try { InputStream in = service.loadDriver(driver_id); if (Activator.DEBUG) { log.log(locator, LogService.LOG_DEBUG, Thread.currentThread().getName() + ": DriverLocator loadDriver returned: " + in); //$NON-NLS-1$ } installDriverBundle(driver_id, in); } catch (Throwable t) { log.log(locator, LogService.LOG_ERROR, NLS.bind(DeviceMsg.DriverLocator_unable_to_load_driver, driver_id), t); } } } } } catch (Throwable t) { log.log(locator, LogService.LOG_ERROR, DeviceMsg.DriverLocator_error_calling_findDrivers, t); } } } } } /** * Get an <code>InputStream</code> from which the driver bundle providing a driver with the giving ID can be installed. * * @param id the ID of the driver that needs to be installed. * bundle can be installed */ public void loadDriver(String driver_id, DriverTracker drivers) { if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, Thread.currentThread().getName() + ": DriverLocatorTracker loadDriver called for driver: " + driver_id); //$NON-NLS-1$ } if (drivers.getDriver(driver_id) == null) { ServiceReference[] references = getServiceReferences(); if (references != null) { int size = references.length; for (int i = 0; i < size; i++) { ServiceReference locator = references[i]; DriverLocator service = (DriverLocator) getService(locator); if (service != null) { if (Activator.DEBUG) { log.log(locator, LogService.LOG_DEBUG, Thread.currentThread().getName() + ": DriverLocator loadDriver called for driver: " + driver_id); //$NON-NLS-1$ } try { InputStream in = service.loadDriver(driver_id); if (Activator.DEBUG) { log.log(locator, LogService.LOG_DEBUG, Thread.currentThread().getName() + ": DriverLocator loadDriver returned: " + in); //$NON-NLS-1$ } if (in != null) { installDriverBundle(driver_id, in); break; } } catch (Throwable t) { log.log(locator, LogService.LOG_ERROR, NLS.bind(DeviceMsg.DriverLocator_unable_to_load_driver, driver_id), t); } } } } } } /** * Install a Driver bundle. * * @param driver_id DRIVER_ID for new driver bundle. * @param in InputStream to a new driver bundle. */ public void installDriverBundle(String driver_id, InputStream in) { if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, Thread.currentThread().getName() + ": installDriverBundle from InputStream: " + driver_id); //$NON-NLS-1$ } if (in != null) { Bundle bundle = null; try { bundle = context.installBundle(driver_id, in); /* installBundle will close the InputStream */ if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, Thread.currentThread().getName() + ": Driver bundle installed: " + driver_id); //$NON-NLS-1$ } synchronized (bundles) { if (!bundles.contains(bundle)) { bundles.addElement(bundle); } } bundle.start(); if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, Thread.currentThread().getName() + ": Driver bundle started: " + driver_id); //$NON-NLS-1$ } } catch (BundleException e) { log.log(LogService.LOG_ERROR, NLS.bind(DeviceMsg.Unable_to_install_or_start_driver_bundle, driver_id), e); if (bundle != null) { bundles.removeElement(bundle); try { bundle.uninstall(); if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, Thread.currentThread().getName() + ": Driver bundle uninstalled: " + driver_id); //$NON-NLS-1$ } } catch (BundleException ee) { log.log(LogService.LOG_ERROR, NLS.bind(DeviceMsg.Unable_to_uninstall_driver_bundle_number, driver_id), ee); } bundle = null; } } } } /** * Remove bundle from uninstall list. * * @param bundle bundle to remove from list. */ public void usingDriverBundle(Bundle bundle) { bundles.removeElement(bundle); } /** * Uninstall the recently installed but unused driver bundles. * */ public void uninstallDriverBundles() { int size; Bundle[] uninstall = null; synchronized (bundles) { size = bundles.size(); if (size > 0) { uninstall = new Bundle[size]; bundles.copyInto(uninstall); } } for (int i = 0; i < size; i++) { Bundle bundle = uninstall[i]; if ((bundle.getState() & Bundle.UNINSTALLED) == 0) { /* if bundle not already uninstalled */ try { bundle.uninstall(); if (Activator.DEBUG) { log.log(LogService.LOG_DEBUG, Thread.currentThread().getName() + ": Driver bundle uninstalled"); //$NON-NLS-1$ } } catch (BundleException ee) { log.log(LogService.LOG_ERROR, NLS.bind(DeviceMsg.Unable_to_uninstall_driver_bundle, ee)); } } } bundles.removeAllElements(); } public boolean isUninstallCandidate(Bundle bundle) { return bundles.contains(bundle); } }