servicetracker.java
来自「OSGI这是一个中间件,与UPNP齐名,是用于移植到嵌入式平台之上」· Java 代码 · 共 703 行 · 第 1/2 页
JAVA
703 行
/* * Copyright (c) 2003, KNOPFLERFISH project * 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 the KNOPFLERFISH project 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 org.osgi.util.tracker;import org.osgi.framework.*;import java.util.*;/** * Utility class for grabbing services matching certain criteria. * * <p> * Typical use would be: * * <pre> * // Create and open a tracker for the log service * ServiceTracker logTracker = * new ServiceTracker(bc, LogService.class.getname(), null); * * logTracker.open(); * * ... * * // use the service * ((LogService)logTracker.getService()).log(LogService.LOG_INFO, "message")); * * </pre> * Note that the above code might fail with <tt>NullPointerException</tt> * if no <tt>LogService</tt> is available. */public class ServiceTracker implements ServiceTrackerCustomizer { // Context used for getting services protected BundleContext context; // Either a user-specified filter, or one generated by the // convenience constructors. protected Filter filter; // possibly /this/ if no customizer is specified protected ServiceTrackerCustomizer customizer; // ServiceReference - Service Object protected Hashtable tracked = new Hashtable(); // Listener doing all the work - only non-null when tracker is open protected ServiceListener srListener = null; // Cache best service reference and it's rank protected ServiceReference bestSR = null; protected long bestSRRank = -1; protected long bestSRID = -1; // increment at every add/remove protected int trackingCount = 0; /** * Create a <tt>ServiceTracker</tt> object on the * specified <tt>ServiceReference</tt> object. * * <p>The service referenced by the specified * <tt>ServiceReference</tt> object * will be tracked by this <tt>ServiceTracker</tt> object. * * @param context <tt>BundleContext</tt> object against which * the tracking is done. * @param reference <tt>ServiceReference</tt> object for the * service to be tracked. * @param customizer The customizer object to call when services are * added, modified, or removed in this * <tt>ServiceTracker</tt> object. * If customizer is <tt>null</tt>, then this * <tt>ServiceTracker</tt> object will be used * as the <tt>ServiceTrackerCustomizer</tt> object * and the <tt>ServiceTracker</tt> object will call * the <tt>ServiceTrackerCustomizer</tt> methods on * itself. */ public ServiceTracker(BundleContext context, ServiceReference reference, ServiceTrackerCustomizer customizer) { try { Filter filter = context .createFilter("(" + Constants.SERVICE_ID + "=" + reference.getProperty(Constants.SERVICE_ID) + ")"); init(context, filter, customizer); } catch (InvalidSyntaxException e) { throw new RuntimeException("Filter syntax error: " + e.getMessage()); } } public String toString() { return "ServiceTracker[" + "filter=" + filter + ", size=" + size() + ", bestId=" + bestSRID + "]"; } /** * Create a <tt>ServiceTracker</tt> object on the specified class name. * * <p>Services registered under the specified class name will be tracked * by this <tt>ServiceTracker</tt> object. * * @param context <tt>BundleContext</tt> object against which the * tracking is done. * @param clazz Class name of the services to be tracked. * @param customizer The customizer object to call when services are * added, modified, or removed in * this <tt>ServiceTracker</tt> object. * If customizer is <tt>null</tt>, then this * <tt>ServiceTracker</tt> object will be used * as the <tt>ServiceTrackerCustomizer</tt> object * and the <tt>ServiceTracker</tt> object * will call the <tt>ServiceTrackerCustomizer</tt> * methods on itself. * * @throws IllegalArgumentException if the class name is <tt>null</tt>, * empty string or causes a * <tt>InvalidSyntaxException</tt> */ public ServiceTracker(BundleContext context, String clazz, ServiceTrackerCustomizer customizer) { if(clazz == null) { throw new IllegalArgumentException("Class name can't be null"); } if("".equals(clazz)) { throw new IllegalArgumentException("Class name can't be empty string"); } try { Filter filter = context .createFilter("(" + Constants.OBJECTCLASS + "=" + clazz + ")"); init(context, filter, customizer); } catch (InvalidSyntaxException e) { throw new IllegalArgumentException("Filter syntax error: " + e.getMessage() + " - possibly junk in the class name=\"" + clazz + "\""); } } /** * Create a <tt>ServiceTracker</tt> object on the * specified <tt>Filter</tt> object. * * <p>Services which match the specified <tt>Filter</tt> object * will be tracked by this <tt>ServiceTracker</tt> object. * * @param context <tt>BundleContext</tt> object against which the * tracking is done. * @param filter <tt>Filter</tt> object to select the * services to be tracked. * @param customizer The customizer object to call when services are * added, modified, or removed in this * <tt>ServiceTracker</tt> object. * If customizer is null, then this * <tt>ServiceTracker</tt> object will be used * as the <tt>ServiceTrackerCustomizer</tt> object * and the <tt>ServiceTracker</tt> * object will call the <tt>ServiceTrackerCustomizer</tt> * methods on itself. * @since 1.1 */ public ServiceTracker(BundleContext context, Filter filter, ServiceTrackerCustomizer customizer) { init(context, filter, customizer); } /** * Used by all constrcutors. * * <p> * If <i>customizer</i> is <tt>null</tt>, use the * <tt>ServicerTracker.this</tt> as customizer. * * @throws IllegalArgumentException if filter is <tt>null</tt> */ private void init(BundleContext context, Filter filter, ServiceTrackerCustomizer customizer) { if(filter == null) { throw new IllegalArgumentException("Filter can't be null"); } this.context = context; this.filter = filter; this.customizer = customizer != null ? customizer : this; } /** * Open this <tt>ServiceTracker</tt> and begin tracking services. * * <p>Tracking is done by adding a <tt>ServiceListener</tt> to the * bundlecontext used when creating the tracker. * * <p>If the tracker is already opened, do nothing. * * @throws java.lang.IllegalStateException if the <tt>BundleContext</tt> * object with which this <tt>ServiceTracker</tt> object was * created is no longer valid. */ public void open() { if(srListener != null) { return; // already open } trackingCount = 0; // create listener and add it. Also call REGISTERED for // all services already installed srListener = new ServiceListener() { public void serviceChanged(ServiceEvent ev) { ServiceReference ref = ev.getServiceReference(); switch(ev.getType()) { case ServiceEvent.REGISTERED: { if(filter.match(ref)) { Object obj = null; // ask customizer for actual service object try { obj = customizer.addingService(ref); add(ref, obj); } catch (Exception verybadstyle) { verybadstyle.printStackTrace(); } } } break; case ServiceEvent.MODIFIED: { if(!filter.match(ref)) { remove(ref); } else { try { // We have possibly regained an object after a property // change Object obj = tracked.get(ref); if(obj == null) { // if we don't have it, ask customizer for actual // service object obj = customizer.addingService(ref); add(ref, obj); } // ...and check again and most likely call // modifiedService() if(obj != null) { customizer.modifiedService(ref, obj); updateBest(ref); } } catch (Exception verybadstyle) { verybadstyle.printStackTrace(); } } } break; case ServiceEvent.UNREGISTERING: { if(filter.match(ref)) { remove(ref); } } break; } } }; // Add the listener and initialize all services already registered // Note that we listen for ALL services and filter them later // in the listener. This is because the tracker spec says we // should be able to catch property modifications outside of the // current filter. try { String anyFilter = null; context.addServiceListener(srListener, anyFilter); // we have to do this manually the first time ServiceReference[] srl = context.getServiceReferences(null, anyFilter); for(int i = 0; srl != null && i < srl.length; i++) { srListener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, srl[i])); } } catch (Exception verybadstyle) { verybadstyle.printStackTrace(); } // System.out.println("***** created tracker for #" + context.getBundle().getBundleId() + ", filter=" + filter); } /** * Close this <tt>ServiceTracker</tt> object. * * <p>This method should be called when this <tt>ServiceTracker</tt> object * should end the tracking of services. * * <p>If the tracker is not opened, do nothing. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?