/******************************************************************************* * Copyright (c) 2008, 2009 Bug Labs, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of Bug Labs, Inc. nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ package com.buglabs.application; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.osgi.service.log.LogService; import org.osgi.util.tracker.ServiceTrackerCustomizer; import com.buglabs.application.ServiceTrackerHelper.ManagedRunnable; import com.buglabs.util.LogServiceUtil; /** * Service tracker for the BugApplication Bundle; * * @deprecated Use {@link ManagedRunnable} and {@link ServiceTrackerHelper} instead. */ public abstract class AbstractServiceTracker implements ServiceTrackerCustomizer, IServiceProvider { protected BundleContext context; private Map servicesMap; protected List services; boolean started = false; private LogService logService; private String trackerName; private SortedMap servicePropertiesMap = null; public AbstractServiceTracker(BundleContext context) { this.context = context; servicesMap = new HashMap(); logService = getLogService(context); trackerName = getTrackerName(context); initServices(); } private String getTrackerName(BundleContext context2) { String name = (String) context2.getBundle().getHeaders().get("Bundle-SymbolicName"); if (name == null) { name = context.getBundle().getLocation(); } name = name + " [" + this.getClass().toString() + "]"; return name; } /** * Assume that a log service is always available. * * @param context * @return */ private LogService getLogService(BundleContext context) { return LogServiceUtil.getLogService(context); } /** * Invoked when all services have been registered. * */ public abstract void doStart(); /** * Invoked when a service is unregistered. * */ public abstract void doStop(); /** * Implementations should add services of interest */ public void initServices() { logService.log(LogService.LOG_DEBUG, trackerName + " A tracker in this bundle is tracking no services."); } /** * Used by OSGi to signal that a service was added. * */ public Object addingService(ServiceReference reference) { Object obj = context.getService(reference); String[] objClassName = (String[]) reference.getProperty(Constants.OBJECTCLASS); Object retval = null; logService.log(LogService.LOG_DEBUG, trackerName + " Tracker found service: " + objClassName[0]); if (!servicesMap.containsKey(objClassName[0])) { servicesMap.put(objClassName[0], obj); logService.log(LogService.LOG_DEBUG, trackerName + " Service added to service map: " + objClassName[0]); retval = obj; if (canStart()) { logService.log(LogService.LOG_DEBUG, trackerName + " Starting tracker, all services are available."); doStart(); started = true; } } return retval; } public void modifiedService(ServiceReference reference, Object service) { } /** * Used by OSGi to signal that a service was removed. * */ public void removedService(ServiceReference reference, Object service) { Object obj = context.getService(reference); boolean serviceRemoved = false; String[] objClassName = (String[]) reference.getProperty(Constants.OBJECTCLASS); if (servicesMap.get(objClassName[0]).equals(obj)) { logService.log(LogService.LOG_DEBUG, trackerName + " removing service: " + objClassName[0]); servicesMap.remove(objClassName[0]); serviceRemoved = true; } if (hasStarted() && serviceRemoved) { try { logService.log(LogService.LOG_DEBUG, trackerName + " stopping tracker."); doStop(); } catch (Exception e) { logService.log(LogService.LOG_ERROR, e.getMessage()); } started = false; } } /** * Determines if the application can be started. * * @returns true when the application is not running and there's a handle * for each service. */ protected boolean canStart() { if (hasStarted()) { return false; } Iterator servicesIter = services.iterator(); while (servicesIter.hasNext()) { if (servicesMap.get((String) servicesIter.next()) == null) { return false; } } return true; } /** * Helper method to retrieve a service of type class. * */ public Object getService(Class clazz) { return servicesMap.get(clazz.getName()); } /** * Helps set up the serviceProperties map created to make generated code * simpler * * @param serviceName * @param properties */ protected final void addServiceFilters(String serviceName, String[][] properties) { Map propMap = new HashMap(); for (int i = 0; i < properties.length; i++) { propMap.put(properties[i][0], properties[i][1]); } getServicePropertiesMap().put(serviceName, propMap); // also add it to the services list getServices().add(serviceName); } /** * returns the map of services and properties that represent the service * dependencies for this tracker the map, in pseudo-generic code, is: * Map<String serviceName, Map<String propertyKey, String propertyVal>> * * @return */ public final SortedMap getServicePropertiesMap() { if (servicePropertiesMap == null) { servicePropertiesMap = new TreeMap(); } return servicePropertiesMap; } /** * Used to retrieve a list of qualified service names. If you want your * application to depend on another service, simply add the fully qualified * name of the service to this list. * * @return a list of Strings containing the fully qualified name of each * service. * */ public List getServices() { if (services == null) { services = new ArrayList(); } return services; } public BundleContext getBundleContext() { return context; } public boolean hasStarted() { return started; } public void stop() { if (hasStarted()) { doStop(); started = false; } } }