1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 19 package org.apache.tomcat.util.modeler; 20 21 22 import java.util.ArrayList; 23 import java.util.Iterator; 24 25 import javax.management.ListenerNotFoundException; 26 import javax.management.MBeanNotificationInfo; 27 import javax.management.Notification; 28 import javax.management.NotificationBroadcaster; 29 import javax.management.NotificationFilter; 30 import javax.management.NotificationListener; 31 32 33 /** 34 * <p>Implementation of <code>NotificationBroadcaster</code> for attribute 35 * change notifications. This class is used by <code>BaseModelMBean</code> to 36 * handle notifications of attribute change events to interested listeners. 37 *</p> 38 * 39 * @author Craig R. McClanahan 40 * @author Costin Manolache 41 */ 42 43 public class BaseNotificationBroadcaster implements NotificationBroadcaster { 44 45 46 // ----------------------------------------------------------- Constructors 47 48 49 // ----------------------------------------------------- Instance Variables 50 51 52 /** 53 * The set of registered <code>BaseNotificationBroadcasterEntry</code> 54 * entries. 55 */ 56 protected ArrayList entries = new ArrayList(); 57 58 59 // --------------------------------------------------------- Public Methods 60 61 62 /** 63 * Add a notification event listener to this MBean. 64 * 65 * @param listener Listener that will receive event notifications 66 * @param filter Filter object used to filter event notifications 67 * actually delivered, or <code>null</code> for no filtering 68 * @param handback Handback object to be sent along with event 69 * notifications 70 * 71 * @exception IllegalArgumentException if the listener parameter is null 72 */ 73 public void addNotificationListener(NotificationListener listener, 74 NotificationFilter filter, 75 Object handback) 76 throws IllegalArgumentException { 77 78 synchronized (entries) { 79 80 // Optimization to coalesce attribute name filters 81 if (filter instanceof BaseAttributeFilter) { 82 BaseAttributeFilter newFilter = (BaseAttributeFilter) filter; 83 Iterator items = entries.iterator(); 84 while (items.hasNext()) { 85 BaseNotificationBroadcasterEntry item = 86 (BaseNotificationBroadcasterEntry) items.next(); 87 if ((item.listener == listener) && 88 (item.filter != null) && 89 (item.filter instanceof BaseAttributeFilter) && 90 (item.handback == handback)) { 91 BaseAttributeFilter oldFilter = 92 (BaseAttributeFilter) item.filter; 93 String newNames[] = newFilter.getNames(); 94 String oldNames[] = oldFilter.getNames(); 95 if (newNames.length == 0) { 96 oldFilter.clear(); 97 } else { 98 if (oldNames.length != 0) { 99 for (int i = 0; i < newNames.length; i++) 100 oldFilter.addAttribute(newNames[i]); 101 } 102 } 103 return; 104 } 105 } 106 } 107 108 // General purpose addition of a new entry 109 entries.add(new BaseNotificationBroadcasterEntry 110 (listener, filter, handback)); 111 } 112 113 } 114 115 116 /** 117 * Return an <code>MBeanNotificationInfo</code> object describing the 118 * notifications sent by this MBean. 119 */ 120 public MBeanNotificationInfo[] getNotificationInfo() { 121 122 return (new MBeanNotificationInfo[0]); 123 124 } 125 126 127 /** 128 * Remove a notification event listener from this MBean. 129 * 130 * @param listener The listener to be removed (any and all registrations 131 * for this listener will be eliminated) 132 * 133 * @exception ListenerNotFoundException if this listener is not 134 * registered in the MBean 135 */ 136 public void removeNotificationListener(NotificationListener listener) 137 throws ListenerNotFoundException { 138 139 synchronized (entries) { 140 Iterator items = entries.iterator(); 141 while (items.hasNext()) { 142 BaseNotificationBroadcasterEntry item = 143 (BaseNotificationBroadcasterEntry) items.next(); 144 if (item.listener == listener) 145 items.remove(); 146 } 147 } 148 149 } 150 151 152 /** 153 * Remove a notification event listener from this MBean. 154 * 155 * @param listener The listener to be removed (any and all registrations 156 * for this listener will be eliminated) 157 * @param handback Handback object to be sent along with event 158 * notifications 159 * 160 * @exception ListenerNotFoundException if this listener is not 161 * registered in the MBean 162 */ 163 public void removeNotificationListener(NotificationListener listener, 164 Object handback) 165 throws ListenerNotFoundException { 166 167 removeNotificationListener(listener); 168 169 } 170 171 172 /** 173 * Remove a notification event listener from this MBean. 174 * 175 * @param listener The listener to be removed (any and all registrations 176 * for this listener will be eliminated) 177 * @param filter Filter object used to filter event notifications 178 * actually delivered, or <code>null</code> for no filtering 179 * @param handback Handback object to be sent along with event 180 * notifications 181 * 182 * @exception ListenerNotFoundException if this listener is not 183 * registered in the MBean 184 */ 185 public void removeNotificationListener(NotificationListener listener, 186 NotificationFilter filter, 187 Object handback) 188 throws ListenerNotFoundException { 189 190 removeNotificationListener(listener); 191 192 } 193 194 195 /** 196 * Send the specified notification to all interested listeners. 197 * 198 * @param notification The notification to be sent 199 */ 200 public void sendNotification(Notification notification) { 201 202 synchronized (entries) { 203 Iterator items = entries.iterator(); 204 while (items.hasNext()) { 205 BaseNotificationBroadcasterEntry item = 206 (BaseNotificationBroadcasterEntry) items.next(); 207 if ((item.filter != null) && 208 (!item.filter.isNotificationEnabled(notification))) 209 continue; 210 item.listener.handleNotification(notification, item.handback); 211 } 212 } 213 214 } 215 216 217 // -------------------- Internal Extensions -------------------- 218 219 // Fast access. First index is the hook type 220 // ( FixedNotificationFilter.getType() ). 221 NotificationListener hooks[][]=new NotificationListener[20][]; 222 int hookCount[]=new int[20]; 223 224 private synchronized void registerNotifications( FixedNotificationFilter filter ) { 225 String names[]=filter.getNames(); 226 Registry reg=Registry.getRegistry(); 227 for( int i=0; i<names.length; i++ ) { 228 int code=reg.getId(null, names[i]); 229 if( hooks.length < code ) { 230 // XXX reallocate 231 throw new RuntimeException( "Too many hooks " + code ); 232 } 233 NotificationListener listeners[]=hooks[code]; 234 if( listeners== null ) { 235 236 } 237 238 239 } 240 } 241 242 } 243 244 245 /** 246 * Utility class representing a particular registered listener entry. 247 */ 248 249 class BaseNotificationBroadcasterEntry { 250 251 public BaseNotificationBroadcasterEntry(NotificationListener listener, 252 NotificationFilter filter, 253 Object handback) { 254 this.listener = listener; 255 this.filter = filter; 256 this.handback = handback; 257 } 258 259 public NotificationFilter filter = null; 260 261 public Object handback = null; 262 263 public NotificationListener listener = null; 264 265 }