/*
 * 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.Vector;
import java.util.EventObject;

import javax.naming.event.NamingEvent;
import javax.naming.event.NamingExceptionEvent;
import javax.naming.event.NamingListener;
import javax.naming.ldap.UnsolicitedNotificationEvent;
import javax.naming.ldap.UnsolicitedNotificationListener;

/**
 * Package private class used by EventSupport to dispatch events.
 * This class implements an event queue, and a dispatcher thread that
 * dequeues and dispatches events from the queue.
 *
 * Pieces stolen from sun.misc.Queue.
 *
 * @author      Bill Shannon (from javax.mail.event)
 * @author      Rosanna Lee (modified for JNDI-related events)
 */
final class EventQueue implements Runnable {
    final static private boolean debug = false;

    private static class QueueElement {
        QueueElement next = null;
        QueueElement prev = null;
        EventObject event = null;
        Vector<NamingListener> vector = null;

        QueueElement(EventObject event, Vector<NamingListener> vector) {
            this.event = event;
            this.vector = vector;
        }
    }

    private QueueElement head = null;
    private QueueElement tail = null;
    private Thread qThread;

    // package private
    EventQueue() {
        qThread = Obj.helper.createThread(this);
        qThread.setDaemon(true);  // not a user thread
        qThread.start();
    }

    // package private;
    /**
     * Enqueue an event.
     * @param event Either a <tt>NamingExceptionEvent</tt> or a subclass
     *              of <tt>NamingEvent</tt> or
     * <tt>UnsolicitedNotificatoniEvent</tt>.
     * If it is a subclass of <tt>NamingEvent</tt>, all listeners must implement
     * the corresponding subinterface of <tt>NamingListener</tt>.
     * For example, for a <tt>ObjectAddedEvent</tt>, all listeners <em>must</em>
     * implement the <tt>ObjectAddedListener</tt> interface.
     * <em>The current implementation does not check this before dispatching
     * the event.</em>
     * If the event is a <tt>NamingExceptionEvent</tt>, then all listeners
     * are notified.
     * @param vector List of NamingListeners that will be notified of event.
     */
    synchronized void enqueue(EventObject event, Vector<NamingListener> vector) {
        QueueElement newElt = new QueueElement(event, vector);

        if (head == null) {
            head = newElt;
            tail = newElt;
        } else {
            newElt.next = head;
            head.prev = newElt;
            head = newElt;
        }
        notify();
    }

    /**
     * Dequeue the oldest object on the queue.
     * Used only by the run() method.
     *
     * @return    the oldest object on the queue.
     * @exception java.lang.InterruptedException if any thread has
     *              interrupted this thread.
     */
    private synchronized QueueElement dequeue()
                                throws InterruptedException {
        while (tail == null)
            wait();
        QueueElement elt = tail;
        tail = elt.prev;
        if (tail == null) {
            head = null;
        } else {
            tail.next = null;
        }
        elt.prev = elt.next = null;
        return elt;
    }

    /**
     * Pull events off the queue and dispatch them.
     */
    public void run() {
        QueueElement qe;

        try {
            while ((qe = dequeue()) != null) {
                EventObject e = qe.event;
                Vector<NamingListener> v = qe.vector;

                for (int i = 0; i < v.size(); i++) {

                    // Dispatch to corresponding NamingListener
                    // The listener should only be getting the event that
                    // it is interested in. (No need to check mask or
                    // instanceof subinterfaces.)
                    // It is the responsibility of the enqueuer to
                    // only enqueue events with listseners of the correct type.

                    if (e instanceof NamingEvent) {
                        ((NamingEvent)e).dispatch(v.elementAt(i));

                    // An exception occurred: if notify all naming listeners
                    } else if (e instanceof NamingExceptionEvent) {
                        ((NamingExceptionEvent)e).dispatch(v.elementAt(i));
                    } else if (e instanceof UnsolicitedNotificationEvent) {
                        ((UnsolicitedNotificationEvent)e).dispatch(
                            (UnsolicitedNotificationListener)v.elementAt(i));
                    }
                }

                qe = null; e = null; v = null;
            }
        } catch (InterruptedException e) {
            // just die
        }
    }

    // package private; used by EventSupport;
    /**
     * Stop the dispatcher so we can be destroyed.
     */
    void stop() {
        if (debug) System.err.println("EventQueue stopping");
        if (qThread != null) {
            qThread.interrupt();        // kill our thread
            qThread = null;
        }
    }
}
