1. /*
  2. * $Header: /home/cvspublic/jakarta-commons/modeler/src/java/org/apache/commons/modeler/BaseNotificationBroadcaster.java,v 1.5 2003/07/20 07:35:13 ggregory Exp $
  3. * $Revision: 1.5 $
  4. * $Date: 2003/07/20 07:35:13 $
  5. *
  6. * ====================================================================
  7. *
  8. * The Apache Software License, Version 1.1
  9. *
  10. * Copyright (c) 1999 The Apache Software Foundation. All rights
  11. * reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions
  15. * are met:
  16. *
  17. * 1. Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. *
  20. * 2. Redistributions in binary form must reproduce the above copyright
  21. * notice, this list of conditions and the following disclaimer in
  22. * the documentation and/or other materials provided with the
  23. * distribution.
  24. *
  25. * 3. The end-user documentation included with the redistribution, if
  26. * any, must include the following acknowlegement:
  27. * "This product includes software developed by the
  28. * Apache Software Foundation (http://www.apache.org/)."
  29. * Alternately, this acknowlegement may appear in the software itself,
  30. * if and wherever such third-party acknowlegements normally appear.
  31. *
  32. * 4. The names "The Jakarta Project", "Commons", and "Apache Software
  33. * Foundation" must not be used to endorse or promote products derived
  34. * from this software without prior written permission. For written
  35. * permission, please contact apache@apache.org.
  36. *
  37. * 5. Products derived from this software may not be called "Apache"
  38. * nor may "Apache" appear in their names without prior written
  39. * permission of the Apache Group.
  40. *
  41. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  42. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  43. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  44. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  45. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  46. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  47. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  48. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  49. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  50. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  51. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  52. * SUCH DAMAGE.
  53. * ====================================================================
  54. *
  55. * This software consists of voluntary contributions made by many
  56. * individuals on behalf of the Apache Software Foundation. For more
  57. * information on the Apache Software Foundation, please see
  58. * <http://www.apache.org/>.
  59. *
  60. * [Additional notices, if required by prior licensing conditions]
  61. *
  62. */
  63. package org.apache.commons.modeler;
  64. import java.util.ArrayList;
  65. import java.util.Iterator;
  66. import javax.management.ListenerNotFoundException;
  67. import javax.management.MBeanNotificationInfo;
  68. import javax.management.Notification;
  69. import javax.management.NotificationBroadcaster;
  70. import javax.management.NotificationFilter;
  71. import javax.management.NotificationListener;
  72. /**
  73. * <p>Implementation of <code>NotificationBroadcaster</code> for attribute
  74. * change notifications. This class is used by <code>BaseModelMBean</code> to
  75. * handle notifications of attribute change events to interested listeners.
  76. *</p>
  77. *
  78. * @author Craig R. McClanahan
  79. * @author Costin Manolache
  80. */
  81. public class BaseNotificationBroadcaster implements NotificationBroadcaster {
  82. // ----------------------------------------------------------- Constructors
  83. // ----------------------------------------------------- Instance Variables
  84. /**
  85. * The set of registered <code>BaseNotificationBroadcasterEntry</code>
  86. * entries.
  87. */
  88. protected ArrayList entries = new ArrayList();
  89. // --------------------------------------------------------- Public Methods
  90. /**
  91. * Add a notification event listener to this MBean.
  92. *
  93. * @param listener Listener that will receive event notifications
  94. * @param filter Filter object used to filter event notifications
  95. * actually delivered, or <code>null</code> for no filtering
  96. * @param handback Handback object to be sent along with event
  97. * notifications
  98. *
  99. * @exception IllegalArgumentException if the listener parameter is null
  100. */
  101. public void addNotificationListener(NotificationListener listener,
  102. NotificationFilter filter,
  103. Object handback)
  104. throws IllegalArgumentException {
  105. synchronized (entries) {
  106. // Optimization to coalesce attribute name filters
  107. if (filter instanceof BaseAttributeFilter) {
  108. BaseAttributeFilter newFilter = (BaseAttributeFilter) filter;
  109. Iterator items = entries.iterator();
  110. while (items.hasNext()) {
  111. BaseNotificationBroadcasterEntry item =
  112. (BaseNotificationBroadcasterEntry) items.next();
  113. if ((item.listener == listener) &&
  114. (item.filter != null) &&
  115. (item.filter instanceof BaseAttributeFilter) &&
  116. (item.handback == handback)) {
  117. BaseAttributeFilter oldFilter =
  118. (BaseAttributeFilter) item.filter;
  119. String newNames[] = newFilter.getNames();
  120. String oldNames[] = oldFilter.getNames();
  121. if (newNames.length == 0) {
  122. oldFilter.clear();
  123. } else {
  124. if (oldNames.length != 0) {
  125. for (int i = 0; i < newNames.length; i++)
  126. oldFilter.addAttribute(newNames[i]);
  127. }
  128. }
  129. return;
  130. }
  131. }
  132. }
  133. // General purpose addition of a new entry
  134. entries.add(new BaseNotificationBroadcasterEntry
  135. (listener, filter, handback));
  136. }
  137. }
  138. /**
  139. * Return an <code>MBeanNotificationInfo</code> object describing the
  140. * notifications sent by this MBean.
  141. */
  142. public MBeanNotificationInfo[] getNotificationInfo() {
  143. return (new MBeanNotificationInfo[0]);
  144. }
  145. /**
  146. * Remove a notification event listener from this MBean.
  147. *
  148. * @param listener The listener to be removed (any and all registrations
  149. * for this listener will be eliminated)
  150. *
  151. * @exception ListenerNotFoundException if this listener is not
  152. * registered in the MBean
  153. */
  154. public void removeNotificationListener(NotificationListener listener)
  155. throws ListenerNotFoundException {
  156. synchronized (entries) {
  157. Iterator items = entries.iterator();
  158. while (items.hasNext()) {
  159. BaseNotificationBroadcasterEntry item =
  160. (BaseNotificationBroadcasterEntry) items.next();
  161. if (item.listener == listener)
  162. items.remove();
  163. }
  164. }
  165. }
  166. /**
  167. * Remove a notification event listener from this MBean.
  168. *
  169. * @param listener The listener to be removed (any and all registrations
  170. * for this listener will be eliminated)
  171. * @param handback Handback object to be sent along with event
  172. * notifications
  173. *
  174. * @exception ListenerNotFoundException if this listener is not
  175. * registered in the MBean
  176. */
  177. public void removeNotificationListener(NotificationListener listener,
  178. Object handback)
  179. throws ListenerNotFoundException {
  180. removeNotificationListener(listener);
  181. }
  182. /**
  183. * Remove a notification event listener from this MBean.
  184. *
  185. * @param listener The listener to be removed (any and all registrations
  186. * for this listener will be eliminated)
  187. * @param filter Filter object used to filter event notifications
  188. * actually delivered, or <code>null</code> for no filtering
  189. * @param handback Handback object to be sent along with event
  190. * notifications
  191. *
  192. * @exception ListenerNotFoundException if this listener is not
  193. * registered in the MBean
  194. */
  195. public void removeNotificationListener(NotificationListener listener,
  196. NotificationFilter filter,
  197. Object handback)
  198. throws ListenerNotFoundException {
  199. removeNotificationListener(listener);
  200. }
  201. /**
  202. * Send the specified notification to all interested listeners.
  203. *
  204. * @param notification The notification to be sent
  205. */
  206. public void sendNotification(Notification notification) {
  207. synchronized (entries) {
  208. Iterator items = entries.iterator();
  209. while (items.hasNext()) {
  210. BaseNotificationBroadcasterEntry item =
  211. (BaseNotificationBroadcasterEntry) items.next();
  212. if ((item.filter != null) &&
  213. (!item.filter.isNotificationEnabled(notification)))
  214. continue;
  215. item.listener.handleNotification(notification, item.handback);
  216. }
  217. }
  218. }
  219. // -------------------- Internal Extensions --------------------
  220. // Fast access. First index is the hook type
  221. // ( FixedNotificationFilter.getType() ).
  222. NotificationListener hooks[][]=new NotificationListener[20][];
  223. int hookCount[]=new int[20];
  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. * Utility class representing a particular registered listener entry.
  241. */
  242. class BaseNotificationBroadcasterEntry {
  243. public BaseNotificationBroadcasterEntry(NotificationListener listener,
  244. NotificationFilter filter,
  245. Object handback) {
  246. this.listener = listener;
  247. this.filter = filter;
  248. this.handback = handback;
  249. }
  250. public NotificationFilter filter = null;
  251. public Object handback = null;
  252. public NotificationListener listener = null;
  253. }