1 /* 2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jndi.ldap; 27 28 import java.util.Vector; 29 import java.util.EventObject; 30 31 import javax.naming.event.NamingEvent; 32 import javax.naming.event.NamingExceptionEvent; 33 import javax.naming.event.NamingListener; 34 import javax.naming.ldap.UnsolicitedNotificationEvent; 35 import javax.naming.ldap.UnsolicitedNotificationListener; 36 37 /** 38 * Package private class used by EventSupport to dispatch events. 39 * This class implements an event queue, and a dispatcher thread that 40 * dequeues and dispatches events from the queue. 41 * 42 * Pieces stolen from sun.misc.Queue. 43 * 44 * @author Bill Shannon (from javax.mail.event) 45 * @author Rosanna Lee (modified for JNDI-related events) 46 */ 47 final class EventQueue implements Runnable { 48 final static private boolean debug = false; 49 50 private static class QueueElement { 51 QueueElement next = null; 52 QueueElement prev = null; 53 EventObject event = null; 54 Vector<NamingListener> vector = null; 55 56 QueueElement(EventObject event, Vector<NamingListener> vector) { 57 this.event = event; 58 this.vector = vector; 59 } 60 } 61 62 private QueueElement head = null; 63 private QueueElement tail = null; 64 private Thread qThread; 65 66 // package private 67 EventQueue() { 68 qThread = Obj.helper.createThread(this); 69 qThread.setDaemon(true); // not a user thread 70 qThread.start(); 71 } 72 73 // package private; 74 /** 75 * Enqueue an event. 76 * @param event Either a {@code NamingExceptionEvent} or a subclass 77 * of {@code NamingEvent} or 78 * {@code UnsolicitedNotificationEvent}. 79 * If it is a subclass of {@code NamingEvent}, all listeners must implement 80 * the corresponding subinterface of {@code NamingListener}. 81 * For example, for a {@code ObjectAddedEvent}, all listeners <em>must</em> 82 * implement the {@code ObjectAddedListener} interface. 83 * <em>The current implementation does not check this before dispatching 84 * the event.</em> 85 * If the event is a {@code NamingExceptionEvent}, then all listeners 86 * are notified. 87 * @param vector List of NamingListeners that will be notified of event. 88 */ 89 synchronized void enqueue(EventObject event, Vector<NamingListener> vector) { 90 QueueElement newElt = new QueueElement(event, vector); 91 92 if (head == null) { 93 head = newElt; 94 tail = newElt; 95 } else { 96 newElt.next = head; 97 head.prev = newElt; 98 head = newElt; 99 } 100 notify(); 101 } 102 103 /** 104 * Dequeue the oldest object on the queue. 105 * Used only by the run() method. 106 * 107 * @return the oldest object on the queue. 108 * @exception java.lang.InterruptedException if any thread has 109 * interrupted this thread. 110 */ 111 private synchronized QueueElement dequeue() 112 throws InterruptedException { 113 while (tail == null) 114 wait(); 115 QueueElement elt = tail; 116 tail = elt.prev; 117 if (tail == null) { 118 head = null; 119 } else { 120 tail.next = null; 121 } 122 elt.prev = elt.next = null; 123 return elt; 124 } 125 126 /** 127 * Pull events off the queue and dispatch them. 128 */ 129 public void run() { 130 QueueElement qe; 131 132 try { 133 while ((qe = dequeue()) != null) { 134 EventObject e = qe.event; 135 Vector<NamingListener> v = qe.vector; 136 137 for (int i = 0; i < v.size(); i++) { 138 139 // Dispatch to corresponding NamingListener 140 // The listener should only be getting the event that 141 // it is interested in. (No need to check mask or 142 // instanceof subinterfaces.) 143 // It is the responsibility of the enqueuer to 144 // only enqueue events with listeners of the correct type. 145 146 if (e instanceof NamingEvent) { 147 ((NamingEvent)e).dispatch(v.elementAt(i)); 148 149 // An exception occurred: if notify all naming listeners 150 } else if (e instanceof NamingExceptionEvent) { 151 ((NamingExceptionEvent)e).dispatch(v.elementAt(i)); 152 } else if (e instanceof UnsolicitedNotificationEvent) { 153 ((UnsolicitedNotificationEvent)e).dispatch( 154 (UnsolicitedNotificationListener)v.elementAt(i)); 155 } 156 } 157 158 qe = null; e = null; v = null; 159 } 160 } catch (InterruptedException e) { 161 // just die 162 } 163 } 164 165 // package private; used by EventSupport; 166 /** 167 * Stop the dispatcher so we can be destroyed. 168 */ 169 void stop() { 170 if (debug) System.err.println("EventQueue stopping"); 171 if (qThread != null) { 172 qThread.interrupt(); // kill our thread 173 qThread = null; 174 } 175 } 176 }