/*
 * Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jndi.ldap;

import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import java.util.EventObject;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.event.*;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.UnsolicitedNotificationListener;
import javax.naming.ldap.UnsolicitedNotificationEvent;
import javax.naming.ldap.UnsolicitedNotification;

/**
 * This is a utility class that can be used by a context that supports
 * event notification.  You can use an instance of this class as a member field
 * of your context and delegate various work to it.
 * It is currently structured so that each context should have its own
 * EventSupport (instead of static version shared by all contexts
 * of a service provider).
 *<p>
 * This class supports two types of listeners: those that register for
 * NamingEvents, and those for UnsolicitedNotificationEvents (they can be mixed
 * into the same listener).
 * For NamingEvent listeners, it maintains a hashtable that maps
 * registration requests--the key--to
 * <em>notifiers</em>--the value. Each registration request consists of:
 *<ul>
 *<li>The name argument of the registration.
 *<li>The filter (default is "(objectclass=*)").
 *<li>The search controls (default is null SearchControls).
 *<li>The events that the listener is interested in. This is determined by
 * finding out which <tt>NamingListener</tt> interface the listener supports.
 *</ul>
 *<p>
 *A notifier (<tt>NamingEventNotifier</tt>) is a worker thread that is responsible
 *for gathering information for generating events requested by its listeners.
 *Each notifier maintains its own list of listeners; these listeners have
 *all made the same registration request (at different times) and implements
 *the same <tt>NamingListener</tt> interfaces.
 *<p>
 *For unsolicited listeners, this class maintains a vector, unsolicited.
 *When an unsolicited listener is registered, this class adds itself
 *to the context's LdapClient. When LdapClient receives an unsolicited
 *notification, it notifies this EventSupport to fire an event to the
 *the listeners. Special handling in LdapClient is done for the DISCONNECT
 *notification. [It results in the EventSupport firing also a
 *NamingExceptionEvent to the unsolicited listeners.]
 *<p>
 *
 *When a context no longer needs this EventSupport, it should invoke
 *cleanup() on it.
 *<p>
 *<h4>Registration</h4>
 *When a registration request is made, this class attempts to find an
 *existing notifier that's already working on the request. If one is
 *found, the listener is added to the notifier's list. If one is not found,
 *a new notifier is created for the listener.
 *
 *<h4>Deregistration</h4>
 *When a deregistration request is made, this class attemps to find its
 *corresponding notifier. If the notifier is found, the listener is removed
 *from the notifier's list. If the listener is the last listener on the list,
 *the notifier's thread is terminated and removed from this class's hashtable.
 *Nothing happens if the notifier is not found.
 *
 *<h4>Event Dispatching</h4>
 *The notifiers are responsible for gather information for generating events
 *requested by their respective listeners. When a notifier gets sufficient
 *information to generate an event, it creates invokes the
 *appropriate <tt>fireXXXEvent</tt> on this class with the information and list of
 *listeners. This causes an event and the list of listeners to be added
 *to the <em>event queue</em>.
 *This class maintains an event queue and a dispatching thread that dequeues
 *events from the queue and dispatches them to the listeners.
 *
 *<h4>Synchronization</h4>
 *This class is used by the main thread (LdapCtx) to add/remove listeners.
 *It is also used asynchronously by NamingEventNotifiers threads and
 *the context's Connection thread. It is used by the notifier threads to
 *queue events and to update the notifiers list when the notifiers exit.
 *It is used by the Connection thread to fire unsolicited notifications.
 *Methods that access/update the 'unsolicited' and 'notifiers' lists are
 *thread-safe.
 *
 * @author Rosanna Lee
 */
final class EventSupport {
    final static private boolean debug = false;

    private LdapCtx ctx;

    /**
     * NamingEventNotifiers; hashed by search arguments;
     */
    private Hashtable notifiers = new Hashtable(11);

    /**
     * List of unsolicited notification listeners.
     */
    private Vector unsolicited = null;

    /**
     * Constructs EventSupport for ctx.
     * <em>Do we need to record the name of the target context?
     * Or can we assume that EventSupport is called on a resolved
     * context? Do we need other add/remove-NamingListener methods?
     * package private;
     */
    EventSupport(LdapCtx ctx) {
        this.ctx = ctx;
    }

    /**
     * Adds <tt>l</tt> to list of listeners interested in <tt>nm</tt>.
     */
    /*
     * Make the add/removeNamingListeners synchronized to:
     * 1. protect usage of 'unsolicited', which may be read by
     *    the Connection thread when dispatching unsolicited notification.
     * 2. ensure that NamingEventNotifier thread's access to 'notifiers'
     *    is safe
     */
    synchronized void addNamingListener(String nm, int scope,
        NamingListener l) throws NamingException {

        if (l instanceof ObjectChangeListener ||
            l instanceof NamespaceChangeListener) {
            NotifierArgs args = new NotifierArgs(nm, scope, l);

            NamingEventNotifier notifier =
                (NamingEventNotifier) notifiers.get(args);
            if (notifier == null) {
                notifier = new NamingEventNotifier(this, ctx, args, l);
                notifiers.put(args, notifier);
            } else {
                notifier.addNamingListener(l);
            }
        }
        if (l instanceof UnsolicitedNotificationListener) {
            // Add listener to this's list of unsolicited notifiers
            if (unsolicited == null) {
                unsolicited = new Vector(3);
            }

            unsolicited.addElement(l);
        }
    }

    /**
     * Adds <tt>l</tt> to list of listeners interested in <tt>nm</tt>
     * and filter.
     */
    synchronized void addNamingListener(String nm, String filter,
        SearchControls ctls, NamingListener l) throws NamingException {

        if (l instanceof ObjectChangeListener ||
            l instanceof NamespaceChangeListener) {
            NotifierArgs args = new NotifierArgs(nm, filter, ctls, l);

            NamingEventNotifier notifier =
                (NamingEventNotifier) notifiers.get(args);
            if (notifier == null) {
                notifier = new NamingEventNotifier(this, ctx, args, l);
                notifiers.put(args, notifier);
            } else {
                notifier.addNamingListener(l);
            }
        }
        if (l instanceof UnsolicitedNotificationListener) {
            // Add listener to this's list of unsolicited notifiers
            if (unsolicited == null) {
                unsolicited = new Vector(3);
            }
            unsolicited.addElement(l);
        }
    }

    /**
     * Removes <tt>l</tt> from all notifiers in this context.
     */
    synchronized void removeNamingListener(NamingListener l) {
        Enumeration allnotifiers = notifiers.elements();
        NamingEventNotifier notifier;

        if (debug) System.err.println("EventSupport removing listener");

        // Go through list of notifiers, remove 'l' from each.
        // If 'l' is notifier's only listener, remove notifier too.
        while (allnotifiers.hasMoreElements()) {
            notifier = (NamingEventNotifier)allnotifiers.nextElement();
            if (notifier != null) {
                if (debug)
                    System.err.println("EventSupport removing listener from notifier");
                notifier.removeNamingListener(l);
                if (!notifier.hasNamingListeners()) {
                    if (debug)
                        System.err.println("EventSupport stopping notifier");
                    notifier.stop();
                    notifiers.remove(notifier.info);
                }
            }
        }

        // Remove from list of unsolicited notifier
        if (debug) System.err.println("EventSupport removing unsolicited: " +
            unsolicited);
        if (unsolicited != null) {
            unsolicited.removeElement(l);
        }

    }

    synchronized boolean hasUnsolicited() {
        return (unsolicited != null && unsolicited.size() > 0);
    }

    /**
      * package private;
      * Called by NamingEventNotifier to remove itself when it encounters
      * a NamingException.
      */
    synchronized void removeDeadNotifier(NotifierArgs info) {
        if (debug) {
            System.err.println("EventSupport.removeDeadNotifier: " + info.name);
        }
        notifiers.remove(info);
    }

    /**
     * Fire an event to unsolicited listeners.
     * package private;
     * Called by LdapCtx when its clnt receives an unsolicited notification.
     */
    synchronized void fireUnsolicited(Object obj) {
        if (debug) {
            System.err.println("EventSupport.fireUnsolicited: " + obj + " "
                + unsolicited);
        }
        if (unsolicited == null || unsolicited.size() == 0) {
            // This shouldn't really happen, but might in case
            // there is a timing problem that removes a listener
            // before a fired event event reaches here.
            return;
        }

        if (obj instanceof UnsolicitedNotification) {

            // Fire UnsolicitedNotification to unsolicited listeners

            UnsolicitedNotificationEvent evt =
                new UnsolicitedNotificationEvent(ctx, (UnsolicitedNotification)obj);
            queueEvent(evt, unsolicited);

        } else if (obj instanceof NamingException) {

            // Fire NamingExceptionEvent to unsolicited listeners.

            NamingExceptionEvent evt =
                new NamingExceptionEvent(ctx, (NamingException)obj);
            queueEvent(evt, unsolicited);

            // When an exception occurs, the unsolicited listeners
            // are automatically deregistered.
            // When LdapClient.processUnsolicited() fires a NamingException,
            // it will update its listener list so we don't have to.
            // Likewise for LdapCtx.

            unsolicited = null;
        }
    }

    /**
     * Stops notifier threads that are collecting event data and
     * stops the event queue from dispatching events.
     * Package private; used by LdapCtx.
     */
    synchronized void cleanup() {
        if (debug) System.err.println("EventSupport clean up");
        if (notifiers != null) {
            for (Enumeration ns = notifiers.elements(); ns.hasMoreElements(); ) {
                ((NamingEventNotifier) ns.nextElement()).stop();
            }
            notifiers = null;
        }
        if (eventQueue != null) {
            eventQueue.stop();
            eventQueue = null;
        }
        // %%% Should we fire NamingExceptionEvents to unsolicited listeners?
    }

    /*
     * The queue of events to be delivered.
     */
    private EventQueue eventQueue;

    /**
     * Add the event and vector of listeners to the queue to be delivered.
     * An event dispatcher thread dequeues events from the queue and dispatches
     * them to the registered listeners.
     * Package private; used by NamingEventNotifier to fire events
     */
    synchronized void queueEvent(EventObject event, Vector vector) {
        if (eventQueue == null)
            eventQueue = new EventQueue();

        /*
         * Copy the vector in order to freeze the state of the set
         * of EventListeners the event should be delivered to prior
         * to delivery.  This ensures that any changes made to the
         * Vector from a target listener's method during the delivery
         * of this event will not take effect until after the event is
         * delivered.
         */
        Vector v = (Vector)vector.clone();
        eventQueue.enqueue(event, v);
    }

    // No finalize() needed because EventSupport is always owned by
    // an LdapCtx. LdapCtx's finalize() and close() always call cleanup() so
    // there is no need for EventSupport to have a finalize().
}
