1 23 package com.sun.enterprise.management.support; 24 25 import java.util.Set ; 26 import java.util.HashSet ; 27 import java.util.List ; 28 import java.util.LinkedList ; 29 import java.util.Map ; 30 import java.util.HashMap ; 31 import java.util.Collections ; 32 import java.io.Serializable ; 33 34 import javax.management.MBeanServer ; 35 import javax.management.ObjectName ; 36 import javax.management.Notification ; 37 import javax.management.MBeanServerNotification ; 38 import javax.management.NotificationListener ; 39 import javax.management.NotificationFilter ; 40 import javax.management.NotificationFilterSupport ; 41 import javax.management.ListenerNotFoundException ; 42 import javax.management.InstanceNotFoundException ; 43 import javax.management.NotificationEmitter ; 44 import javax.management.MBeanNotificationInfo ; 45 46 47 import com.sun.appserv.management.base.NotificationService; 48 import com.sun.appserv.management.base.XTypes; 49 import com.sun.appserv.management.base.AMX; 50 51 import com.sun.appserv.management.util.misc.GSetUtil; 52 import com.sun.appserv.management.util.misc.OverflowHandler; 53 import com.sun.appserv.management.util.jmx.JMXUtil; 54 import com.sun.appserv.management.util.jmx.NotificationBuilder; 55 56 57 58 60 public final class NotificationServiceImpl extends AMXImplBase 61 implements NotificationListener , NotificationEmitter 62 { 63 private Map <ObjectName ,NotificationFilter > mListenees; 64 private final Object mUserData; 65 66 private final Map <ObjectName ,NotificationFilter > mIncludePatterns; 67 private final Map <ObjectName ,NotificationFilter > mExcludePatterns; 68 69 private final Map <Object ,NotificationBuffer> mBuffers; 70 71 public 72 NotificationServiceImpl( 73 final Object userData, 74 final int bufferSize ) 75 { 76 if ( userData == null || !(userData instanceof Serializable ) ) 77 { 78 throw new IllegalArgumentException (); 79 } 80 81 mUserData = userData; 82 83 mListenees = Collections.synchronizedMap( new HashMap <ObjectName ,NotificationFilter >() ); 84 85 mBuffers = Collections.synchronizedMap( new HashMap <Object ,NotificationBuffer>() ); 86 87 mIncludePatterns = new HashMap <ObjectName ,NotificationFilter >(); 88 mExcludePatterns = new HashMap <ObjectName ,NotificationFilter >(); 89 } 90 91 public final Object 92 getUserData() 93 { 94 return( mUserData ); 95 } 96 97 private final String [] NOTIF_TYPES = new String [] 98 { 99 NotificationService.BUFFER_OVERFLOW_NOTIFICATION_TYPE, 100 }; 101 102 public MBeanNotificationInfo [] 103 getNotificationInfo() 104 { 105 final MBeanNotificationInfo info = new MBeanNotificationInfo ( 106 NOTIF_TYPES, 107 Notification .class.getName(), 108 "" ); 109 final MBeanNotificationInfo [] selfInfos = new MBeanNotificationInfo [] { info }; 110 111 return( JMXUtil.mergeMBeanNotificationInfos( super.getNotificationInfo(), selfInfos ) ); 112 } 113 114 116 protected void 117 issueBufferOverflowNotification( final Notification oldNotif ) 118 { 119 if ( shouldEmitNotifications() ) 120 { 121 sendNotification( NotificationService.BUFFER_OVERFLOW_NOTIFICATION_TYPE, 122 NotificationService.OVERFLOWED_NOTIFICATION_KEY, 123 oldNotif ); 124 } 125 } 126 127 public void 128 handleNotification( 129 final Notification notif, 130 final Object handback) 131 { 132 synchronized( mBuffers ) 133 { 134 for( final Object id : mBuffers.keySet() ) 135 { 136 getBuffer( id ).bufferNotification( notif ); 137 } 138 } 139 140 sendNotification( notif ); 142 } 143 144 private NotificationBuffer 145 getBuffer( final Object bufferID ) 146 { 147 return( (NotificationBuffer)mBuffers.get( bufferID ) ); 148 } 149 150 private final class OverflowHandlerImpl implements OverflowHandler 151 { 152 public OverflowHandlerImpl() {} 153 154 public void 155 handleBufferOverflow( Object o ) 156 { 157 final Notification notif = (Notification )o; 158 issueBufferOverflowNotification( notif ); 159 } 160 } 161 162 private static int sBufferID = 0; 163 public Object 164 createBuffer( 165 final int bufferSize, 166 final NotificationFilter filter ) 167 { 168 final OverflowHandler handler = new OverflowHandlerImpl(); 169 170 final NotificationBuffer buffer = 171 new NotificationBuffer( bufferSize, filter, handler ); 172 173 Object id = null; 174 175 synchronized( mBuffers ) 176 { 177 ++sBufferID; 178 id = "" + sBufferID; 179 180 mBuffers.put( id, buffer ); 181 } 182 183 return( id ); 184 } 185 186 public void 187 removeBuffer( final Object bufferID ) 188 { 189 final NotificationBuffer buffer = 190 (NotificationBuffer)mBuffers.remove( bufferID ); 191 } 192 193 public Map 194 getBufferNotifications( 195 final Object bufferID, 196 final long sequenceNumberIn ) 197 { 198 final NotificationBuffer buffer = getBuffer( bufferID ); 199 200 return( buffer.getNotifications( sequenceNumberIn ) ); 201 } 202 203 204 public String 205 getGroup() 206 { 207 return( AMX.GROUP_UTILITY ); 208 } 209 210 protected Set <ObjectName > 211 getMatchingObjectNames( final ObjectName pattern ) 212 { 213 Set <ObjectName > s = null; 214 215 if ( pattern.isPattern() ) 216 { 217 s = JMXUtil.queryNames( getMBeanServer(), pattern, null ); 218 } 219 else 220 { 221 s = GSetUtil.newSingletonSet( pattern ); 222 } 223 224 return( s ); 225 } 226 227 protected void 228 listenToIfMatch( final ObjectName objectName ) 229 { 230 if ( ! mListenees.keySet().contains( objectName ) ) 231 { 232 final String defaultDomain = getMBeanServer().getDefaultDomain(); 233 234 for( final ObjectName pattern : mIncludePatterns.keySet() ) 235 { 236 if ( JMXUtil.matchesPattern( defaultDomain, pattern, objectName ) ) 237 { 238 final NotificationFilter filter = 239 (NotificationFilter )mIncludePatterns.get( pattern ); 240 241 listenToSingle( objectName, filter ); 242 } 243 } 244 } 245 } 246 247 protected void 248 listenToSingle( 249 final ObjectName objectName, 250 final NotificationFilter filter ) 251 { 252 mListenees.put( objectName, filter ); 253 try 254 { 255 getMBeanServer().addNotificationListener( objectName, this, filter, null ); 256 } 257 catch( Exception e ) 258 { 259 mListenees.remove( objectName ); 260 } 261 } 262 263 public void 264 listenTo( 265 final ObjectName pattern, 266 final NotificationFilter filter ) 267 throws InstanceNotFoundException 268 { 269 mIncludePatterns.put( pattern, filter ); 270 271 final Set <ObjectName > listenees = getMatchingObjectNames( pattern ); 272 273 final MBeanServer server = getMBeanServer(); 274 for( final ObjectName objectName : listenees ) 275 { 276 if ( objectName.equals( getObjectName() ) ) 277 { 278 continue; 279 } 280 281 listenToSingle( objectName, filter ); 282 } 283 } 284 285 private void 286 checkListeningTo( final ObjectName objectName ) 287 { 288 if ( ! mListenees.containsKey( objectName ) ) 289 { 290 throw new IllegalArgumentException ( objectName.toString() ); 291 } 292 } 293 294 public void 295 dontListenTo( final ObjectName pattern ) 296 { 297 mIncludePatterns.remove( pattern ); 298 299 final Set <ObjectName > listenees = getMatchingObjectNames( pattern ); 300 301 final MBeanServer server = getMBeanServer(); 302 for( final ObjectName objectName : listenees ) 303 { 304 try 305 { 306 server.removeNotificationListener( objectName, this ); 307 mListenees.remove( objectName ); 308 } 309 catch( ListenerNotFoundException e ) 310 { 311 } 312 catch( InstanceNotFoundException e ) 313 { 314 } 315 } 316 } 317 318 319 public Set <ObjectName > 320 getListeneeObjectNameSet() 321 { 322 final Set <ObjectName > objectNames = new HashSet <ObjectName >(); 323 324 synchronized( mListenees ) 325 { 326 objectNames.addAll( mListenees.keySet() ); 327 } 328 329 return( objectNames ); 330 } 331 332 private NotificationFilter 333 _getFilter( final ObjectName objectName) 334 { 335 final NotificationFilter filter = 336 (NotificationFilter )mListenees.get( objectName ); 337 338 return( filter ); 339 } 340 341 public NotificationFilter 342 getFilter( final ObjectName objectName) 343 { 344 checkListeningTo( objectName ); 345 346 return( _getFilter( objectName ) ); 347 } 348 349 private final class RegistrationListener implements NotificationListener 352 { 353 public RegistrationListener() {} 354 355 public void 356 handleNotification( 357 final Notification notifIn, 358 final Object handback) 359 { 360 if ( notifIn instanceof MBeanServerNotification ) 361 { 362 final MBeanServerNotification notif = (MBeanServerNotification )notifIn; 363 364 final ObjectName objectName = notif.getMBeanName(); 365 final String type = notif.getType(); 366 367 if ( type.equals( MBeanServerNotification.REGISTRATION_NOTIFICATION ) ) 368 { 369 listenToIfMatch( objectName ); 370 } 371 else if ( type.equals( MBeanServerNotification.UNREGISTRATION_NOTIFICATION ) ) 372 { 373 dontListenTo( objectName ); 374 } 375 } 376 377 } 378 } 379 380 protected void 381 preRegisterDone() 382 throws Exception 383 { 384 super.preRegisterDone(); 385 386 JMXUtil.listenToMBeanServerDelegate( getMBeanServer(), 389 new RegistrationListener(), null, null ); 390 } 391 392 public void 393 preDeregisterHook() 394 { 395 super.preDeregisterHook(); 396 397 synchronized( mListenees ) 398 { 399 final Set <ObjectName > s = getListeneeObjectNameSet(); 400 401 final ObjectName [] objectNames = new ObjectName [ s.size() ]; 402 s.toArray( objectNames ); 403 404 for( int i = 0; i < objectNames.length; ++i ) 405 { 406 dontListenTo( objectNames[ i ] ); 407 } 408 } 409 410 synchronized( mBuffers ) 411 { 412 for( final NotificationBuffer buffer : mBuffers.values() ) 413 { 414 removeBuffer( buffer ); 415 } 416 } 417 } 418 } 419 420 421 422 423 424 425 426 427 428 429 430 | Popular Tags |