View Javadoc

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.commons.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 }