View Javadoc

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