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