|
Monitoring Changes in ServicesServices will start and stop. When they start, they will inform the lookup services, and sometime after they stop, they will be removed from the lookup services. However, there are a lot of times when other services or clients will want to know when services start or are removed. For example, an editor may want to know if a disk service has started so that it can save its file; a graphics display program may want to know when printer services start up; the user interface for a camera may want to track changes in disk and printer services so that it can update the Save and Print buttons . A service registrar acts as a generator of ServiceEvent type events, which sub-class from RemoteEvent . These events are generated in response to changes in the state of services that match (or fail to match) a template pattern for services. This event type has three categories from the ServiceEvent.getTransition() method:
A client that wants to monitor changes of services on a lookup service must first create a template for the types of services it is interested in. A client that wants to monitor all changes could prepare a template such as this: ServiceTemplate templ = new ServiceTemplate(null, null, null); // or ServiceTemplate templ = new ServiceTemplate(null, new Class[] {}, new Entry[] {}); // or ServiceTemplate templ = new ServiceTemplate(null, new Class[] {Object.class}, null); It then sets up a transition mask as a bit-wise OR of the three service transitions, and then calls notify() on the ServiceRegistrar object. The following is a program to monitor all changes. /** * RegistrarObserver.java */ package observer; import net.jini.core.event.RemoteEventListener; import net.jini.core.event.RemoteEvent; import net.jini.core.lookup.ServiceEvent; import net.jini.core.lookup.ServiceRegistrar; import net.jini.core.lease.Lease; import net.jini.core.lookup.ServiceTemplate; import net.jini.core.lookup.ServiceID; import net.jini.core.event.EventRegistration; // import com.sun.jini.lease.LeaseRenewalManager; // Jini 1.0 import net.jini.lease.LeaseRenewalManager; // Jini 1.1 import net.jini.core.lookup.ServiceMatches; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import net.jini.core.entry.Entry; import net.jini.core.event.UnknownEventException; public class RegistrarObserver extends UnicastRemoteObject implements RemoteEventListener { protected static LeaseRenewalManager leaseManager = new LeaseRenewalManager(); protected ServiceRegistrar registrar; protected final int transitions = ServiceRegistrar.TRANSITION_MATCH_NOMATCH ServiceRegistrar.TRANSITION_NOMATCH_MATCH ServiceRegistrar.TRANSITION_MATCH_MATCH; public RegistrarObserver() throws RemoteException { } public RegistrarObserver(ServiceRegistrar registrar) throws RemoteException { this.registrar = registrar; ServiceTemplate templ = new ServiceTemplate(null, null, null); EventRegistration reg = null; try { // eventCatcher = new MyEventListener(); reg = registrar.notify(templ, transitions, this, null, Lease.ANY); System.out.println("notified id " + reg.getID()); } catch(RemoteException e) { e.printStackTrace(); } leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, null); } public void notify(RemoteEvent evt) throws RemoteException, UnknownEventException { try { ServiceEvent sevt = (ServiceEvent) evt; int transition = sevt.getTransition(); System.out.println("transition " + transition); switch (transition) { case ServiceRegistrar.TRANSITION_NOMATCH_MATCH: System.out.println("nomatch -> match"); break; case ServiceRegistrar.TRANSITION_MATCH_MATCH: System.out.println("match -> match"); break; case ServiceRegistrar.TRANSITION_MATCH_NOMATCH: System.out.println("match -> nomatch"); break; } System.out.println(sevt.toString()); if (sevt.getServiceItem() == null) { System.out.println("now null"); } else { Object service = sevt.getServiceItem().service; System.out.println("Service is " + service.toString()); } } catch(Exception e) { e.printStackTrace(); } } // RegistrarObserver The following is a suitable driver for the preceding observer class: package client; import java.rmi.RMISecurityManager; import java.rmi.RemoteException; import net.jini.discovery.LookupDiscovery; import net.jini.discovery.DiscoveryListener; import net.jini.discovery.DiscoveryEvent; import net.jini.core.lookup.ServiceRegistrar; import net.jini.core.lookup.ServiceTemplate; import net.jini.core.lookup.ServiceMatches; import java.util.Vector; import observer.RegistrarObserver; /** * ReggieMonitor.java */ public class ReggieMonitor implements DiscoveryListener { protected Vector observers = new Vector(); public static void main(String argv[]) { new ReggieMonitor(); // stay around long enough to receive replies try { Thread.currentThread().sleep(100000L); } catch(java.lang.InterruptedException e) { // do nothing } } public ReggieMonitor() { System.setSecurityManager(new RMISecurityManager()); LookupDiscovery discover = null; try { discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS); } catch(Exception e) { System.err.println(e.toString()); System.exit(1); } discover.addDiscoveryListener(this); } public void discovered(DiscoveryEvent evt) { ServiceRegistrar[] registrars = evt.getRegistrars(); for (int n = 0; n < registrars.length; n++) { System.out.println("Service lookup found"); ServiceRegistrar registrar = registrars[n]; if (registrar == null) { System.out.println("registrar null"); continue; } try { System.out.println("Lookup service at " + registrar.getLocator().getHost()); } catch(RemoteException e) { System.out.println("Lookup service info unavailable"); } try { observers.add(new RegistrarObserver(registrar)); } catch(RemoteException e) { System.out.println("adding observer failed"); } ServiceTemplate templ = new ServiceTemplate(null, new Class[] {Object.class}, null); ServiceMatches matches = null; try { matches = registrar.lookup(templ, 10); } catch(RemoteException e) { System.out.println("lookup failed"); } for (int m = 0; m < matches.items.length; m++) { if (matches.items[m] != null && matches.items[m].service != null) { System.out.println("Reg knows about " + matches.items[m].service.toString() + " with id " + matches.items[m].servieID); } } } } public void discarded(DiscoveryEvent evt) { // remove observer } } // ReggieMonitor |