1 23 package com.sun.appserv.management.util.jmx; 24 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.HashMap ; 28 import java.util.LinkedList ; 29 import java.util.Collections ; 30 31 import javax.management.NotificationBroadcasterSupport ; 32 import javax.management.NotificationListener ; 33 import javax.management.NotificationFilter ; 34 import javax.management.relation.MBeanServerNotificationFilter ; 35 import javax.management.AttributeChangeNotificationFilter ; 36 import javax.management.NotificationFilterSupport ; 37 import javax.management.Notification ; 38 import javax.management.AttributeChangeNotification ; 39 import javax.management.MBeanServerNotification ; 40 import javax.management.ListenerNotFoundException ; 41 42 43 import com.sun.appserv.management.util.misc.ListUtil; 44 45 53 public class NotificationEmitterSupport 54 extends NotificationBroadcasterSupport 55 { 56 private final boolean mAsyncDelivery; 57 private SenderThread mSenderThread; 58 private final Map <String ,Integer > mListenerTypeCounts; 59 private final NotificationListenerTracking mListeners; 60 61 62 public 63 NotificationEmitterSupport( 64 final boolean asyncDelivery) 65 { 66 mAsyncDelivery = asyncDelivery; 67 mSenderThread = null; 69 70 mListenerTypeCounts = Collections.synchronizedMap( new HashMap <String ,Integer >() ); 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 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 type ) 121 { 122 final Integer count = mListenerTypeCounts.get( type ); 123 124 int resultCount = 0; 125 126 if ( count == null ) 127 { 128 final Integer allCount = mListenerTypeCounts.get( WILDCARD_TYPE ); 129 if ( allCount != null ) 130 { 131 resultCount = allCount; 132 } 133 else 134 { 135 } 137 } 138 139 return( resultCount ); 140 } 141 142 143 private static final String [] NO_TYPES = new String [0]; 144 private static final String WILDCARD_TYPE = "***"; 145 private static final String [] ALL_TYPES = new String [] { WILDCARD_TYPE }; 146 147 private static final String [] ATTRIBUTE_CHANGE_TYPES = new String [] 148 { 149 AttributeChangeNotification.ATTRIBUTE_CHANGE 150 }; 151 152 private static final String [] MBEAN_SERVER_NOTIFICATION_TYPES = new String [] 153 { 154 MBeanServerNotification.REGISTRATION_NOTIFICATION, 155 MBeanServerNotification.UNREGISTRATION_NOTIFICATION, 156 }; 157 158 159 private final Integer COUNT_1 = new Integer ( 1 ); 160 161 private void 162 incrementListenerCountForType( final String type ) 163 { 164 synchronized( mListenerTypeCounts ) 165 { 166 final Integer count = mListenerTypeCounts.get( type ); 167 168 final Integer newCount = (count == null ) ? 169 COUNT_1 : new Integer ( count.intValue() + 1 ); 170 171 mListenerTypeCounts.put( type, newCount ); 172 } 173 } 174 175 private void 176 decrementListenerCountForType( final String type ) 177 { 178 synchronized( mListenerTypeCounts ) 179 { 180 final Integer count = mListenerTypeCounts.get( type ); 181 if ( count == null ) 182 { 183 throw new IllegalArgumentException ( 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 ( oldValue - 1 ) ); 194 } 195 } 196 } 197 198 199 private String [] 200 getTypes( 201 final NotificationFilter filter ) 202 { 203 String [] types = NO_TYPES; 204 205 if ( filter instanceof NotificationFilterSupport ) 206 { 207 final NotificationFilterSupport fs = (NotificationFilterSupport )filter; 208 209 types = ListUtil.toStringArray( fs.getEnabledTypes() ); 210 } 211 else if ( filter instanceof AttributeChangeNotificationFilter ) 212 { 213 types = ATTRIBUTE_CHANGE_TYPES; 214 } 215 else if ( filter instanceof MBeanServerNotificationFilter ) 216 { 217 types = MBEAN_SERVER_NOTIFICATION_TYPES; 218 } 219 else 220 { 221 types = ALL_TYPES; 223 } 224 225 return types; 226 } 227 228 private void 229 addFilterTypeCounts( final NotificationFilter filter ) 230 { 231 String [] types = getTypes( filter ); 232 233 for( String type : types ) 234 { 235 incrementListenerCountForType( type ); 236 } 237 } 238 239 private void 240 removeFilterTypeCounts( final NotificationFilter filter ) 241 { 242 final String [] types = getTypes( filter ); 243 244 for( String type : types ) 245 { 246 decrementListenerCountForType( type ); 247 } 248 } 249 250 private void 251 removeFilterTypeCounts( final List <NotificationListenerInfo> infos ) 252 { 253 for( NotificationListenerInfo info : infos ) 254 { 255 removeFilterTypeCounts( info.getFilter() ); 256 } 257 } 258 259 public void 260 addNotificationListener( 261 final NotificationListener listener, 262 final NotificationFilter filter, 263 final Object 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 listener) 273 throws ListenerNotFoundException 274 { 275 super.removeNotificationListener( listener ); 276 277 final List <NotificationListenerInfo> infos = 278 mListeners.removeNotificationListener( listener ); 279 removeFilterTypeCounts( infos ); 280 } 281 282 public void 283 removeNotificationListener( 284 final NotificationListener listener, 285 final NotificationFilter filter, 286 final Object handback) 287 throws ListenerNotFoundException 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 notif ) 301 { 302 super.sendNotification( notif ); 303 } 304 305 310 public void 311 sendNotification( final Notification 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 327 { 328 private boolean mQuit; 329 private List <Notification > mPendingNotifications; 330 331 public 332 SenderThread() 333 { 334 mQuit = false; 335 mPendingNotifications = 336 Collections.synchronizedList( new LinkedList <Notification >() ); 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 notif ) 358 { 359 mPendingNotifications.add( notif ); 360 notifySelf(); 361 } 362 363 public boolean 364 sendAll() 365 { 366 Notification notif = null; 367 boolean sentSomething = false; 368 369 while ( ! mPendingNotifications.isEmpty() ) 370 { 371 sentSomething = true; 373 try 374 { 375 notif = mPendingNotifications.remove( 0 ); 376 internalSendNotification( notif ); 377 } 378 catch( ArrayIndexOutOfBoundsException e ) 379 { 380 } 382 } 383 384 return( sentSomething ); 385 } 386 387 public void 388 run() 389 { 390 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 e ) 405 { 406 } 407 408 if ( mQuit ) 409 { 410 break; 411 } 412 413 final boolean sentSomething = sendAll(); 414 415 if ( ! sentSomething ) 417 { 418 cleanup(); 419 sendAll(); 421 break; 422 } 423 } 424 } 425 } 426 427 } 428 429 | Popular Tags |