KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > appserv > management > util > jmx > NotificationEmitterSupport


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.appserv.management.util.jmx;
24
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.Collections JavaDoc;
30
31 import javax.management.NotificationBroadcasterSupport JavaDoc;
32 import javax.management.NotificationListener JavaDoc;
33 import javax.management.NotificationFilter JavaDoc;
34 import javax.management.relation.MBeanServerNotificationFilter JavaDoc;
35 import javax.management.AttributeChangeNotificationFilter JavaDoc;
36 import javax.management.NotificationFilterSupport JavaDoc;
37 import javax.management.Notification JavaDoc;
38 import javax.management.AttributeChangeNotification JavaDoc;
39 import javax.management.MBeanServerNotification JavaDoc;
40 import javax.management.ListenerNotFoundException JavaDoc;
41
42
43 import com.sun.appserv.management.util.misc.ListUtil;
44
45 /**
46     Features:
47     <ul>
48     <li>Maintains information on all NotificationListeners so that queries can
49     be made on the number of listeners, and the number of listeners of each type</li>
50     <li>optionally sends all Notifications asynchronously via a separate Thread</li>
51     </ul>
52  */

53 public class NotificationEmitterSupport
54     extends NotificationBroadcasterSupport JavaDoc
55 {
56     private final boolean mAsyncDelivery;
57     private SenderThread mSenderThread;
58     private final Map JavaDoc<String JavaDoc,Integer JavaDoc> mListenerTypeCounts;
59     private final NotificationListenerTracking mListeners;
60     
61     
62         public
63     NotificationEmitterSupport(
64         final boolean asyncDelivery)
65     {
66         mAsyncDelivery = asyncDelivery;
67         // don't create a thread until needed
68
mSenderThread = null;
69         
70         mListenerTypeCounts = Collections.synchronizedMap( new HashMap JavaDoc<String JavaDoc,Integer JavaDoc>() );
71         
72         mListeners = new NotificationListenerTracking( true );
73     }
74     
75         private synchronized SenderThread
76     getSenderThread()
77     {
78         if ( mSenderThread == null )
79         {
80             mSenderThread = mAsyncDelivery ? new SenderThread() : null;
81             if ( mSenderThread != null )
82             {
83                 mSenderThread.start();
84             }
85         }
86         
87         return( mSenderThread );
88     }
89     
90         public synchronized void
91     cleanup()
92     {
93         if ( mSenderThread != null )
94         {
95             mSenderThread.quit();
96             mSenderThread = null;
97         }
98     }
99     
100     /**
101         Synchronously (on current thread), ensure that all Notifications
102         have been delivered.
103      */

104         public void
105     sendAll( )
106     {
107         if ( mSenderThread != null )
108         {
109             mSenderThread.sendAll();
110         }
111     }
112     
113         public int
114     getListenerCount()
115     {
116         return( mListeners.getListenerCount() );
117     }
118     
119         public int
120     getNotificationTypeListenerCount( final String JavaDoc type )
121     {
122         final Integer JavaDoc count = mListenerTypeCounts.get( type );
123         
124         int resultCount = 0;
125         
126         if ( count == null )
127         {
128             final Integer JavaDoc allCount = mListenerTypeCounts.get( WILDCARD_TYPE );
129             if ( allCount != null )
130             {
131                 resultCount = allCount;
132             }
133             else
134             {
135                 // no wildcards are in use
136
}
137         }
138         
139         return( resultCount );
140     }
141     
142     
143     private static final String JavaDoc[] NO_TYPES = new String JavaDoc[0];
144     private static final String JavaDoc WILDCARD_TYPE = "***";
145     private static final String JavaDoc[] ALL_TYPES = new String JavaDoc[] { WILDCARD_TYPE };
146     
147     private static final String JavaDoc[] ATTRIBUTE_CHANGE_TYPES = new String JavaDoc[]
148     {
149         AttributeChangeNotification.ATTRIBUTE_CHANGE
150     };
151     
152     private static final String JavaDoc[] MBEAN_SERVER_NOTIFICATION_TYPES = new String JavaDoc[]
153     {
154         MBeanServerNotification.REGISTRATION_NOTIFICATION,
155         MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
156     };
157     
158     
159     private final Integer JavaDoc COUNT_1 = new Integer JavaDoc( 1 );
160     
161         private void
162     incrementListenerCountForType( final String JavaDoc type )
163     {
164         synchronized( mListenerTypeCounts )
165         {
166             final Integer JavaDoc count = mListenerTypeCounts.get( type );
167             
168             final Integer JavaDoc newCount = (count == null ) ?
169                                         COUNT_1 : new Integer JavaDoc( count.intValue() + 1 );
170             
171             mListenerTypeCounts.put( type, newCount );
172         }
173     }
174     
175        private void
176     decrementListenerCountForType( final String JavaDoc type )
177     {
178         synchronized( mListenerTypeCounts )
179         {
180             final Integer JavaDoc count = mListenerTypeCounts.get( type );
181             if ( count == null )
182             {
183                 throw new IllegalArgumentException JavaDoc( type );
184             }
185             
186             final int oldValue = count.intValue();
187             if ( oldValue == 1 )
188             {
189                 mListenerTypeCounts.remove( count );
190             }
191             else
192             {
193                 mListenerTypeCounts.put( type, new Integer JavaDoc( oldValue - 1 ) );
194             }
195         }
196     }
197     
198     
199         private String JavaDoc[]
200     getTypes(
201         final NotificationFilter JavaDoc filter )
202     {
203         String JavaDoc[] types = NO_TYPES;
204         
205         if ( filter instanceof NotificationFilterSupport JavaDoc )
206         {
207             final NotificationFilterSupport JavaDoc fs = (NotificationFilterSupport JavaDoc)filter;
208             
209             types = ListUtil.toStringArray( fs.getEnabledTypes() );
210         }
211         else if ( filter instanceof AttributeChangeNotificationFilter JavaDoc )
212         {
213             types = ATTRIBUTE_CHANGE_TYPES;
214         }
215         else if ( filter instanceof MBeanServerNotificationFilter JavaDoc )
216         {
217             types = MBEAN_SERVER_NOTIFICATION_TYPES;
218         }
219         else
220         {
221             // no filter, or non-standard one, have to assume all types
222
types = ALL_TYPES;
223         }
224         
225         return types;
226     }
227     
228         private void
229     addFilterTypeCounts( final NotificationFilter JavaDoc filter )
230     {
231         String JavaDoc[] types = getTypes( filter );
232             
233         for( String JavaDoc type : types )
234         {
235             incrementListenerCountForType( type );
236         }
237     }
238     
239         private void
240     removeFilterTypeCounts( final NotificationFilter JavaDoc filter )
241     {
242         final String JavaDoc[] types = getTypes( filter );
243             
244         for( String JavaDoc type : types )
245         {
246             decrementListenerCountForType( type );
247         }
248     }
249     
250         private void
251     removeFilterTypeCounts( final List JavaDoc<NotificationListenerInfo> infos )
252     {
253         for( NotificationListenerInfo info : infos )
254         {
255             removeFilterTypeCounts( info.getFilter() );
256         }
257     }
258     
259         public void
260     addNotificationListener(
261         final NotificationListener JavaDoc listener,
262         final NotificationFilter JavaDoc filter,
263         final Object JavaDoc handback)
264     {
265         super.addNotificationListener( listener, filter, handback );
266         
267         mListeners.addNotificationListener( listener, filter, handback );
268         addFilterTypeCounts( filter );
269     }
270     
271         public void
272     removeNotificationListener(final NotificationListener JavaDoc listener)
273         throws ListenerNotFoundException JavaDoc
274     {
275         super.removeNotificationListener( listener );
276         
277         final List JavaDoc<NotificationListenerInfo> infos =
278             mListeners.removeNotificationListener( listener );
279         removeFilterTypeCounts( infos );
280     }
281     
282         public void
283     removeNotificationListener(
284         final NotificationListener JavaDoc listener,
285         final NotificationFilter JavaDoc filter,
286         final Object JavaDoc handback)
287         throws ListenerNotFoundException JavaDoc
288     {
289         super.removeNotificationListener( listener, filter, handback );
290         
291         mListeners.removeNotificationListener( listener );
292         if ( filter != null )
293         {
294             removeFilterTypeCounts( filter );
295         }
296         
297     }
298     
299         protected void
300     internalSendNotification( final Notification JavaDoc notif )
301     {
302         super.sendNotification( notif );
303     }
304
305     /**
306         Send the Notification. If created with async=true,
307         then this routine returns immediately and the Notification is sent
308         on a separate Thread.
309      */

310         public void
311     sendNotification( final Notification JavaDoc notif )
312     {
313         if ( getListenerCount() != 0 )
314         {
315             if ( getSenderThread() != null )
316             {
317                 mSenderThread.enqueue( notif );
318             }
319             else
320             {
321                 internalSendNotification( notif );
322             }
323         }
324     }
325     
326     private final class SenderThread extends Thread JavaDoc
327     {
328         private boolean mQuit;
329         private List JavaDoc<Notification JavaDoc> mPendingNotifications;
330         
331             public
332         SenderThread()
333         {
334             mQuit = false;
335             mPendingNotifications =
336                 Collections.synchronizedList( new LinkedList JavaDoc<Notification JavaDoc>() );
337         }
338         
339             public void
340         quit()
341         {
342             mQuit = true;
343             notifySelf();
344         }
345         
346         
347             private void
348         notifySelf()
349         {
350             synchronized( this )
351             {
352                 this.notify();
353             }
354         }
355         
356             private void
357         enqueue( final Notification JavaDoc notif )
358         {
359             mPendingNotifications.add( notif );
360             notifySelf();
361         }
362         
363             public boolean
364         sendAll()
365         {
366             Notification JavaDoc notif = null;
367             boolean sentSomething = false;
368             
369             while ( ! mPendingNotifications.isEmpty() )
370             {
371                 sentSomething = true; // or rather, we'll try to
372

373                 try
374                 {
375                     notif = mPendingNotifications.remove( 0 );
376                     internalSendNotification( notif );
377                 }
378                 catch( ArrayIndexOutOfBoundsException JavaDoc e )
379                 {
380                     // can happen if more than one Thread is in here
381
}
382             }
383             
384             return( sentSomething );
385         }
386         
387             public void
388         run()
389         {
390             // wake up every 5 minutes
391
final int INTERVAL = 5 * 1000;
392             
393             mQuit = false;
394             
395             while ( ! mQuit )
396             {
397                 try
398                 {
399                     synchronized( this )
400                     {
401                         wait( INTERVAL );
402                     }
403                 }
404                 catch( InterruptedException JavaDoc e )
405                 {
406                 }
407                 
408                 if ( mQuit )
409                 {
410                     break;
411                 }
412                 
413                 final boolean sentSomething = sendAll();
414                 
415                 // nothing available, get rid of ourself till needed
416
if ( ! sentSomething )
417                 {
418                     cleanup();
419                     // now no new ones can be added, but ensure any pending are sent
420
sendAll();
421                     break;
422                 }
423             }
424         }
425     }
426
427 }
428
429
Popular Tags