package services;

import java.rmi.RMISecurityManager;
import net.jini.discovery.LookupDiscovery;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.lookup.ServiceDiscoveryManager;
import net.jini.lookup.LookupCache;
import net.jini.core.lookup.ServiceItem;
import net.jini.lease.LeaseRenewalManager;
import net.jini.lookup.JoinManager;
import net.jini.lookup.ServiceIDListener;
import net.jini.core.lookup.ServiceID;
import net.jini.core.discovery.LookupLocator;
import net.jini.discovery.LookupLocatorDiscovery;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lease.Lease;
import net.jini.core.lookup.ServiceRegistration;

import java.net.InetAddress;
import java.net.UnknownHostException;

import servicefinder.*;

/**
 * Server.java
 */

public class Server implements ServiceIDListener  {

    public static void main(String argv[]) {
        new Server();

        // keep server running forever
        Object keepAlive = new Object();
        synchronized(keepAlive) {
            try {
                keepAlive.wait();
            } catch(java.lang.InterruptedException e) {
                // do nothing
            }
        }
    }

    public Server() {

        System.setSecurityManager(new RMISecurityManager());

	// This server will register a ServiceFinderImpl with a local LUS
	// It will find all services on this LUS as well as on other
	// LUS's registered later. We have to avoid a race condition here:
	// if we register in one thread and lookup in another, then
	// this service may or may not be discovered. So we can't use
	// LookupLocatorDiscovery in discovery and another in registration
	// since they perform unicast lookups in their own threads.
	// Instead, we need to ensure e.g. registration is completed
	// before doing lookup




	// create a service finder that knows about no LUS's
	ServiceFinderImpl finder = null;
	try {
	    finder = new ServiceFinderImpl();
	} catch(java.rmi.RemoteException e) {
	    System.err.println(e.toString());
	    System.exit(1);
	}

	// Register the Finder service on localhost
	registerFinder(finder);

	// create a unicast discovery object that initially
	// knows about a LUS on localhost
	LookupLocatorDiscovery discovery = null;

	// com/sun/jini/reggie/RegistrarImpl.java treats localhost
	// specially, so we do the same - can we rely on this on
	// all LUS? We have to - localhost doesn't mean anything
	// when on a different machine
	InetAddress localHost = null;
	try {
	    localHost = InetAddress.getLocalHost();
	} catch(UnknownHostException e) {
	    e.printStackTrace();
	    System.exit(1);
	}
	LookupLocator[] locators = null;
	try {
	    locators = new LookupLocator[] 
	                     {new LookupLocator("jini://" +
						localHost.getHostName())};
	} catch(Exception e) {
	    // ignore
	}
	discovery = new LookupLocatorDiscovery(locators);
	finder.addDiscovery(discovery);


	/*

        JoinManager joinMgr = null;
	LookupLocatorDiscovery localMgr = null;
        try {
	    LookupLocator[] locators = {new LookupLocator("jini://localhost/")};
	    localMgr = new LookupLocatorDiscovery(locators);
            joinMgr = new JoinManager(finder,
                                      null,
                                      this,
                                      localMgr,
                                      new LeaseRenewalManager());
        } catch(Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
	*/
     }

    public void serviceIDNotify(ServiceID serviceID) {
        // called as a ServiceIDListener
        // Should save the id to permanent storage
        System.out.println("got service ID " + serviceID.toString());
    }

    public void registerFinder(ServiceFinder finder) {
	// Now register us as a service with local LUS only
	// We use a separate LookupLocatorDiscovery since we
	// don;t want to add to this one
        LookupLocator lookup = null;
        ServiceRegistrar registrar = null;

        try {
            lookup = new LookupLocator("jini://localhost");
        } catch(java.net.MalformedURLException e) {
            System.err.println("lookup failed: " + e.toString());
	    System.exit(1);
        }
        try {
            registrar = lookup.getRegistrar();
        } catch (java.io.IOException e) {
            System.err.println("Registrar search failed: " + e.toString());
            System.exit(1);
        } catch (java.lang.ClassNotFoundException e) {
            System.err.println("Registrar search failed: " + e.toString());
            System.exit(1);
        }
 
        ServiceItem item = new ServiceItem(null, finder, null);
        ServiceRegistration reg = null;
        try {
            // ask to register for 10,000,000 milliseconds
            reg = registrar.register(item, 10000000L);
        } catch(java.rmi.RemoteException e) {
            System.err.println("Register exception: " + e.toString());
        }
	LeaseRenewalManager leaseMgr = new LeaseRenewalManager(reg.getLease(), 
							       Lease.FOREVER,
							       null); 
	System.out.println("Finder registered with service id " +
			   reg.getServiceID());
    }
    
} // Server

