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 + -
显示快捷键?