/*
 * EventLandlord
 *
 * An implementation of the Landlord interface to support management
 * of RemoteEventListener resources
 *
 * Author: Brian Jeltema
 */

import java.util.* ;
import com.sun.jini.lease.* ;
import com.sun.jini.lease.landlord.* ;
import net.jini.core.lease.* ;
import java.rmi.server.* ;
import java.rmi.* ;
import net.jini.core.event.* ;

public class EventLandlord extends UnicastRemoteObject
                           implements Landlord {
    
    // the max lease duration is kept short to make it easy
    // to demonstrate lease cancellation, renewal, and expiration
    // behavior

    private Vector eventResources = new Vector(5,5) ;
    EventLeaseManager manager ;

    // constuct the landlord. The manager takes care of adding EventResources
    // to the managed set, and expiring EventResources
  
    EventLandlord() throws RemoteException {
        manager = new EventLeaseManager(this,eventResources) ;
    }

    // the policy manager calles the lease manager, who will add
    // the event resource to the managed set

    public Lease reserveListener(RemoteEventListener l,long duration) throws LeaseDeniedException {
        EventResource r = new EventResource(l) ;
        return manager.getPolicy().leaseFor(r,duration) ;
    }

    public Enumeration getEnumeration() {
        return new ResourceEnumeration() ;
    }

    public void cancel(Object cookie) throws RemoteException {
	synchronized (eventResources) {
	    for (int i=eventResources.size() ; --i>=0 ; ) {
		EventResource r = (EventResource)eventResources.elementAt(i) ;
		if (r.getCookie().equals(cookie)) {
		    eventResources.removeElementAt(i) ;
		    System.out.println("canceling lease " + cookie) ;
		    break ;
		}
	    }
	}
    }

    public long renew(Object cookie,long extension) throws RemoteException,
                                                           UnknownLeaseException,
                                                           LeaseDeniedException {
	EventResource resource ;
      long ret = 0L ;
	synchronized (eventResources) {
	    resource = null ;
	    for (int i=eventResources.size() ; --i>=0 ; ) {
		EventResource r = (EventResource)eventResources.elementAt(i) ;
		if (r.getCookie().equals(cookie)) {
                    resource = r ;
                    break ;
                }
	    }
	}
	if (resource != null) {
	    ret = manager.getPolicy().renew(resource,extension) ;
            System.out.println("renewing lease " + cookie) ;
	}
	else System.out.println("Couldn't find lease for cookie = " + cookie) ;
        return ret ;
    }

    // not using leasemaps, so just noop these

    public void cancelAll(Object[] cookie) throws RemoteException {
    }

    public Landlord.RenewResults renewAll(Object[] cookie,long[] extension) throws RemoteException {
        return null ;
    }

    // An enumeration of current EventResources, used to obtain
    // the current set of listeners to send events to. A private
    // copy of the vector is used to provide thread safety

    class ResourceEnumeration implements Enumeration {
        int i=0 ;
        Vector resourceClone ;

        public ResourceEnumeration() {
            resourceClone = (Vector)eventResources.clone() ;
        }

        public boolean hasMoreElements() {
            return i<resourceClone.size() ;
        }

        public Object nextElement() {
            return resourceClone.elementAt(i++) ;
        }
    }
}
