/*
*
* Copyright (c) 2000 Scott Oaks and Henry Wong. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and
* without fee is hereby granted.
*
* This sample source code is provided for example only,
* on an unsupported, as-is basis.
*
* AUTHOR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. AUTHOR SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). AUTHOR
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*/
import java.io.*;
import java.rmi.*;
import java.util.*;
import net.jini.discovery.*;
import net.jini.core.lookup.*;
import net.jini.core.entry.*;
import net.jini.core.event.*;
import net.jini.core.lease.*;
import com.sun.jini.lease.*;
public class ServiceFinder implements DiscoveryListener {
private static String[] publicGroup = new String[] { "" };
private ServiceItem returnObject = null;
private Hashtable items = new Hashtable();
private Hashtable leases = new Hashtable();
private LeaseRenewalManager lrm;
private ServiceFinderListener sfl;
private LookupDiscovery reg;
private ServiceTemplate template;
public ServiceFinder(Class serviceInterface) throws IOException {
this(publicGroup, serviceInterface, (Entry[])null);
}
public ServiceFinder(Class serviceInterface, Entry attribute)
throws IOException {
this(publicGroup, serviceInterface, new Entry[] { attribute });
}
public ServiceFinder(Class serviceInterface, Entry[] attributes)
throws IOException {
this(publicGroup, serviceInterface, attributes);
}
public ServiceFinder(String[] groups, Class serviceInterface,
Entry[] attributes) throws IOException {
// Construct the template here for matching in the lookup service
// We don't use the template until we actually discover a service
Class[] name = new Class[] { serviceInterface };
template = new ServiceTemplate(null, name, attributes);
// Initialize for receiving events from the lookup service
lrm = new LeaseRenewalManager();
sfl = new ServiceFinderListener(this);
// Create the facility to perform multicast discovery for all
// lookup services
reg = new LookupDiscovery(groups);
reg.addDiscoveryListener(this);
}
// Automatically called when a lookup service is discovered
// (the listener callback of the addDiscoveryListener method)
public synchronized void discovered(DiscoveryEvent dev) {
ServiceRegistrar[] lookup = dev.getRegistrars();
// We may have discovered one or more lookup services
for (int i = 0; i < lookup.length; i++) {
try {
EventRegistration reg = lookup[i].notify(template,
ServiceRegistrar.TRANSITION_NOMATCH_MATCH,
sfl, null, Lease.FOREVER);
lrm.renewUntil(reg.getLease(), Lease.FOREVER, null);
leases.put(lookup[i], reg);
} catch (RemoteException rex) {
System.out.println("Registration error " + rex);
}
try {
ServiceMatches items = lookup[i].lookup(template,
Integer.MAX_VALUE);
// Each lookup service may have zero or more registered
// servers that implement our desired template
for (int j = 0; j < items.items.length; j++) {
if (items.items[j].service != null)
// Put each matching service into our vector
addServiceItem(items.items[j]);
// else the service item couldn't be deserialized
// so the lookup() method skipped it
}
} catch (RemoteException ex) {
System.out.println("ServiceFinder Error: " + ex);
}
}
}
// An error talking to a lookup service caused it to be discarded
// Remove any references to it from our hashtable, and cancel
// our leases to that service
public synchronized void discarded(DiscoveryEvent dev) {
ServiceRegistrar[] lookup = dev.getRegistrars();
for (int i = 0; i < lookup.length; i++) {
try {
EventRegistration reg = (EventRegistration) leases.get(lookup[i]);
if (reg != null) {
leases.remove(lookup[i]);
lrm.remove(reg.getLease());
}
} catch (UnknownLeaseException ule) {}
}
}
public synchronized void addServiceItem(ServiceItem item) {
items.put(item.serviceID, item);
notifyAll();
}
// This class is to be used by the client. It will return only
// the first service object that satisfies the template request.
public synchronized Object getObject() {
if (returnObject == null) {
while (items.isEmpty()) {
try {
wait();
} catch (InterruptedException ie) {}
}
returnObject = (ServiceItem) items.elements().nextElement();
}
return returnObject.service;
}
// If an error is encountered when using a service object, the client
// should call this method.
// A new object can then be gotten from the getObject() method.
public synchronized void errored(Object obj) {
if ((obj != null) && (returnObject != null)) {
if (obj.equals(returnObject.service)) {
items.remove(returnObject.serviceID);
returnObject = null;
}
}
}
}
|