servicetracker.java

来自「OSGI这是一个中间件,与UPNP齐名,是用于移植到嵌入式平台之上」· Java 代码 · 共 703 行 · 第 1/2 页

JAVA
703
字号
  public void close() {        if(srListener != null) {            // off we go      try {	context.removeServiceListener(srListener);      } catch (IllegalStateException ignored) {	//	System.err.println("ServiceTracker.close called on invalid bundle " + context);	// Simply ignore bad bundles      }          // Cleanup on a clone to avoid remove/next problems in hashtable      Hashtable tr = (Hashtable)tracked.clone();            // and do all the cleanup in the same way we did the initialization      for(Enumeration e = tr.keys(); e.hasMoreElements(); ) {	ServiceReference ref = (ServiceReference)e.nextElement();	remove(ref);      }      srListener = null;    }    trackingCount = 0;  }    /**   * Calls the <tt>close</tt> method.   */  protected void finalize() throws Throwable {    close();  }    /**   * Default implementation of the    * <tt>ServiceTrackerCustomizer.addingService</tt> method.   *   * <p>This method is only called when this <tt>ServiceTracker</tt> object   * has been constructed with a <tt>null</tt>    * <tt>ServiceTrackerCustomizer</tt> argument.   *   * The default implementation returns the result of   * calling <tt>getService(reference)</tt>.   *   * <p>This method can be overridden to customize   * the service object to be tracked for the service   * being added.   *   * @param reference Reference to service being added to this   *                  <tt>ServiceTracker</tt> object.   * @return The service object to be tracked for the service   *         added to this <tt>ServiceTracker</tt> object.   */  public Object addingService(ServiceReference reference) {    Object obj = context.getService(reference);    return obj;  }    /**   * Default implementation of the    * <tt>ServiceTrackerCustomizer.modifiedService</tt> method.   *   * <p>This method is only called when this <tt>ServiceTracker</tt> object   * has been constructed with a <tt>null</tt>    * <tt>ServiceTrackerCustomizer</tt> argument.   *   * The default implementation does nothing.   *   * @param reference Reference to modified service.   * @param service The modified service.   */  public void modifiedService(ServiceReference reference, Object service) {    //     System.out.println("---- modifiedService " + reference.getProperty(Constants.SERVICE_ID));  }    /**   * Default implementation of the    * <tt>ServiceTrackerCustomizer.removedService</tt> method.   *   * <p>This method is only called when this <tt>ServiceTracker</tt> object   * has been constructed with a <tt>null</tt>    * <tt>ServiceTrackerCustomizer</tt> argument.   *   * The default implementation calls <tt>ungetService</tt>, on the   * <tt>BundleContext</tt> object with which this    * <tt>ServiceTracker</tt> object was created,   * passing the specified <tt>ServiceReference</tt> object.   *   * @param reference Reference to removed service.   * @param service The service object for the removed service.   */  public void removedService(ServiceReference reference, Object service) {    try {      context.ungetService(reference);    } catch (IllegalStateException ignored) {    }  }    /**   * Wait for at least one service to be tracked by this    * <tt>ServiceTracker</tt> object.   *   * <p>   * <b>Don't</b> use this method. You'll get bad karma for a long time.   * If you really need the functionity, you're probably <b>much</b>    * better off using a <tt>ServiceListener</tt> directly.   * </p>   *   * @param timeout time interval in milliseconds to wait.  If zero,   *                 the method will wait indefinately.   * @return Returns the result of <tt>getService()</tt>.   */  public Object waitForService(long timeout) throws InterruptedException  {    if(srListener == null) {      return null;    }    synchronized(tracked) {      if (tracked.size() == 0) {	tracked.wait(timeout);      }    }        return getService();  }    /**   * Return an array of <tt>ServiceReference</tt> objects for all services   * being tracked.   *   * @return Array of <tt>ServiceReference</tt> objects or <tt>null</tt>    *         if no service are being tracked.   */  public ServiceReference[] getServiceReferences() {    // This is just plain stupid. Should return an     // array of size zero instead /EW    if(size() == 0) {      return null;    }    ServiceReference[] srl = new ServiceReference[size()];     int                n   = 0;    for(Enumeration e = tracked.keys(); e.hasMoreElements(); ) {      srl[n++] = (ServiceReference)e.nextElement();    }    return srl;  }    /**   * Return an array of service objects for all services   * being tracked.   *   * @return Array of service objects or <tt>null</tt> if no service   *         are being tracked.   */  public Object[] getServices() {    // This is just plain stupid. Should return an     // array of size zero instead /EW    if(size() == 0) {      return null;    }    Object[] srl = new Object[size()];     int      n   = 0;    for(Enumeration e = tracked.keys(); e.hasMoreElements(); ) {      ServiceReference ref = (ServiceReference)e.nextElement();      srl[n++]             = tracked.get(ref);    }    return srl;  }  /*   * Update the bestSR and bestSR rank according to spec in    * <tt>getServiceReference</tt>.   */  protected void updateBest(ServiceReference sr) {    synchronized(tracked) {            long id   = ((Long)sr.getProperty(Constants.SERVICE_ID)).longValue();      int  rank = 0;      //      System.out.println("**** updateBest " + id);            Object r = sr.getProperty(Constants.SERVICE_RANKING);      if(r != null && (r instanceof Integer)) {	rank = ((Integer)r).intValue();      }            if(bestSR == null) {	bestSR     = sr;	bestSRRank = rank;	bestSRID   = id;      } else {	if(rank > bestSRRank) {	  bestSR     = sr;	  bestSRRank = rank;	  bestSRID   = id;	} else if(rank == bestSRRank) {	  if(id < ((Long)bestSR.getProperty(Constants.SERVICE_ID)).longValue()) {	    bestSR     = sr;	    bestSRID   = id;	  }	}      }    }  }  /**   * Returns a <tt>ServiceReference</tt> object for one of the services   * being tracked by this <tt>ServiceTracker</tt> object.   *   * <p>If multiple services are being tracked, the service   * with the highest ranking (as specified in its    * <tt>service.ranking</tt> property) is returned.   * </p>   *   * <p>If there is a tie in ranking, the service with the lowest   * service ID (as specified in its <tt>service.id</tt> property); that is,   * the service that was registered first is returned.   * </p>   *   * <p>This is the same algorithm used by    * <tt>BundleContext.getServiceReference</tt>.   * </p>   *   * <p>   * Implementation note: This code uses a cached best service reference for   * quick retrieval. The cache is rebuilt at service    * registration/unregistation.   * </p>   *   *   * @return <tt>ServiceReference</tt> object or <tt>null</tt>    *         if no service is being tracked.   * @since 1.1   */  public ServiceReference getServiceReference() {    // avoid expensive loop of all references        return bestSR;  }    /**   * Returns the service object for the specified    * <tt>ServiceReference</tt> object   * if the referenced service is being tracked.   *   * @param reference Reference to a service.   * @return Service object or <tt>null</tt> if the service referenced by the   * specified <tt>ServiceReference</tt> object is not being tracked.   */  public Object getService(ServiceReference reference) {    Object obj = reference == null ? null : tracked.get(reference);    return obj;  }    /**   * Returns a service object for one of the services   * being tracked by this <tt>ServiceTracker</tt> object.   *   * <p>If any services are being tracked, this method returns the result   * of calling <tt>getService(getServiceReference())</tt>.   *   * @return Service object or <tt>null</tt> if no service is being tracked.   */  public Object getService() {    return getService(getServiceReference());  }    /**   * Remove a service from this <tt>ServiceTracker</tt> object.   *   * The specified service will be removed from this   * <tt>ServiceTracker</tt> object.   * If the specified service was being tracked then the   * <tt>ServiceTrackerCustomizer.removedService</tt> method will be   * called for that service.   *   * @param reference Reference to the service to be removed.   */  public void remove(ServiceReference reference)  {    synchronized(tracked) {      trackingCount++;      Object obj = tracked.get(reference);      if(obj != null) {	// No longer tracked internally	tracked.remove(reference);		// Notify customizer	try {	  customizer.removedService(reference, obj);	} catch (Exception verybadstyle) {	  // Very bad style of customizer to throw exceptions, but	  // catch them to be nice.	  verybadstyle.printStackTrace();	}	// possibly rebuild cached best reference	if(reference.equals(bestSR)) 	{	  bestSR = null;	  	  // OK - this is a bit expensive, but my guess is that	  // getServiceReference() is called much more often than	  // services gets uninstalled.	  for(Enumeration e = tracked.keys(); e.hasMoreElements(); ) {	    ServiceReference sr = (ServiceReference)e.nextElement();	    updateBest(sr);	  }	}      }    }  }    /**   * Number of services being tracked.   */    public int size() {    return tracked.size();  }    public int getTrackingCount() {    return trackingCount;  }    private void add(ServiceReference ref, Object obj) {    if(obj != null) {      synchronized(tracked) {	tracked.put(ref, obj);	trackingCount++;		// update cached service reference	updateBest(ref);		// if someone is waiting in waitForService()	tracked.notifyAll(); 			      }    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?