177 lines
6.1 KiB
Java
177 lines
6.1 KiB
Java
/*
|
|
* 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;
|
|
}
|
|
}
|
|
}
|