/*
 * Copyright (c) 1999, 2011, 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.EventObject;

import javax.naming.*;
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<NotifierArgs, NamingEventNotifier> notifiers =
            new Hashtable<>(11);

    /**
     * List of unsolicited notification listeners.
     */
    private Vector<UnsolicitedNotificationListener> 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 = 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((UnsolicitedNotificationListener)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 = 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((UnsolicitedNotificationListener)l);
        }
    }

    /**
     * Removes <tt>l</tt> from all notifiers in this context.
     */
    synchronized void removeNamingListener(NamingListener l) {
        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.
        for (NamingEventNotifier notifier : notifiers.values()) {
            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 (NamingEventNotifier notifier : notifiers.values()) {
                notifier.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<? extends NamingListener> 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.
         */
        @SuppressWarnings("unchecked") // clone()
        Vector<NamingListener> v =
                (Vector<NamingListener>)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().
}
