blob: bd6da17dd1437d483dc6b473b0934b60ee325baa [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.jndi.ldap;
27
28import java.io.*;
29import java.util.Vector;
30import java.util.EventObject;
31
32import javax.naming.event.NamingEvent;
33import javax.naming.event.NamingExceptionEvent;
34import javax.naming.event.NamingListener;
35import javax.naming.ldap.UnsolicitedNotificationEvent;
36import javax.naming.ldap.UnsolicitedNotificationListener;
37
38/**
39 * Package private class used by EventSupport to dispatch events.
40 * This class implements an event queue, and a dispatcher thread that
41 * dequeues and dispatches events from the queue.
42 *
43 * Pieces stolen from sun.misc.Queue.
44 *
45 * @author Bill Shannon (from javax.mail.event)
46 * @author Rosanna Lee (modified for JNDI-related events)
47 */
48final class EventQueue implements Runnable {
49 final static private boolean debug = false;
50
51 private static class QueueElement {
52 QueueElement next = null;
53 QueueElement prev = null;
54 EventObject event = null;
55 Vector vector = null;
56
57 QueueElement(EventObject event, Vector vector) {
58 this.event = event;
59 this.vector = vector;
60 }
61 }
62
63 private QueueElement head = null;
64 private QueueElement tail = null;
65 private Thread qThread;
66
67 // package private
68 EventQueue() {
69 qThread = Obj.helper.createThread(this);
70 qThread.setDaemon(true); // not a user thread
71 qThread.start();
72 }
73
74 // package private;
75 /**
76 * Enqueue an event.
77 * @param event Either a <tt>NamingExceptionEvent</tt> or a subclass
78 * of <tt>NamingEvent</tt> or
79 * <tt>UnsolicitedNotificatoniEvent</tt>.
80 * If it is a subclass of <tt>NamingEvent</tt>, all listeners must implement
81 * the corresponding subinterface of <tt>NamingListener</tt>.
82 * For example, for a <tt>ObjectAddedEvent</tt>, all listeners <em>must</em>
83 * implement the <tt>ObjectAddedListener</tt> interface.
84 * <em>The current implementation does not check this before dispatching
85 * the event.</em>
86 * If the event is a <tt>NamingExceptionEvent</tt>, then all listeners
87 * are notified.
88 * @param vector List of NamingListeners that will be notified of event.
89 */
90 synchronized void enqueue(EventObject event, Vector vector) {
91 QueueElement newElt = new QueueElement(event, vector);
92
93 if (head == null) {
94 head = newElt;
95 tail = newElt;
96 } else {
97 newElt.next = head;
98 head.prev = newElt;
99 head = newElt;
100 }
101 notify();
102 }
103
104 /**
105 * Dequeue the oldest object on the queue.
106 * Used only by the run() method.
107 *
108 * @return the oldest object on the queue.
109 * @exception java.lang.InterruptedException if any thread has
110 * interrupted this thread.
111 */
112 private synchronized QueueElement dequeue()
113 throws InterruptedException {
114 while (tail == null)
115 wait();
116 QueueElement elt = tail;
117 tail = elt.prev;
118 if (tail == null) {
119 head = null;
120 } else {
121 tail.next = null;
122 }
123 elt.prev = elt.next = null;
124 return elt;
125 }
126
127 /**
128 * Pull events off the queue and dispatch them.
129 */
130 public void run() {
131 QueueElement qe;
132
133 try {
134 while ((qe = dequeue()) != null) {
135 EventObject e = qe.event;
136 Vector v = qe.vector;
137
138 for (int i = 0; i < v.size(); i++) {
139
140 // Dispatch to corresponding NamingListener
141 // The listener should only be getting the event that
142 // it is interested in. (No need to check mask or
143 // instanceof subinterfaces.)
144 // It is the responsibility of the enqueuer to
145 // only enqueue events with listseners of the correct type.
146
147 if (e instanceof NamingEvent) {
148 ((NamingEvent)e).dispatch((NamingListener)v.elementAt(i));
149
150 // An exception occurred: if notify all naming listeners
151 } else if (e instanceof NamingExceptionEvent) {
152 ((NamingExceptionEvent)e).dispatch(
153 (NamingListener)v.elementAt(i));
154 } else if (e instanceof UnsolicitedNotificationEvent) {
155 ((UnsolicitedNotificationEvent)e).dispatch(
156 (UnsolicitedNotificationListener)v.elementAt(i));
157 }
158 }
159
160 qe = null; e = null; v = null;
161 }
162 } catch (InterruptedException e) {
163 // just die
164 }
165 }
166
167 // package private; used by EventSupport;
168 /**
169 * Stop the dispatcher so we can be destroyed.
170 */
171 void stop() {
172 if (debug) System.err.println("EventQueue stopping");
173 if (qThread != null) {
174 qThread.interrupt(); // kill our thread
175 qThread = null;
176 }
177 }
178}