/* |
|
* 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; |
|
} |
|
} |
|
} |