1 23 24 26 27 package com.sun.enterprise.management.support; 28 29 import java.util.List ; 30 import java.util.ArrayList ; 31 import java.util.Map ; 32 import java.util.HashMap ; 33 import java.util.Collections ; 34 import java.util.Iterator ; 35 import java.io.IOException ; 36 37 import java.lang.reflect.Proxy ; 38 39 import javax.management.ObjectName ; 40 import javax.management.MBeanServer ; 41 import javax.management.Notification ; 42 import javax.management.MBeanServerNotification ; 43 import javax.management.InstanceNotFoundException ; 44 import javax.management.MBeanRegistrationException ; 45 import javax.management.InstanceAlreadyExistsException ; 46 import javax.management.NotCompliantMBeanException ; 47 48 import javax.management.relation.MBeanServerNotificationFilter ; 49 50 51 import com.sun.appserv.management.base.XTypes; 52 import com.sun.appserv.management.base.Util; 53 54 import com.sun.appserv.management.util.jmx.stringifier.NotificationStringifier; 55 import com.sun.appserv.management.util.jmx.JMXUtil; 56 import com.sun.appserv.management.util.jmx.MBeanProxyHandler; 57 import com.sun.appserv.management.util.jmx.MBeanServerConnectionSource; 58 import com.sun.appserv.management.util.jmx.stringifier.StringifierRegistryIniter; 59 60 import com.sun.appserv.management.util.misc.ExceptionUtil; 61 62 import com.sun.appserv.management.util.stringifier.StringifierRegistryIniterImpl; 63 import com.sun.appserv.management.util.stringifier.StringifierRegistryImpl; 64 65 import com.sun.appserv.management.DomainRoot; 66 import com.sun.appserv.management.client.ProxyFactory; 67 68 import com.sun.enterprise.management.support.TypeInfos; 69 import com.sun.enterprise.management.DomainRootImpl; 70 71 74 public final class Loader extends LoaderBase 75 { 76 private boolean mQueuedAll; 77 private List <LoaderOfOld> mLoaders; 78 private Map <ObjectName ,ObjectName > mOldToNewObjectNames; 79 private LoaderRegThread mRegThread; 80 81 private final DeferredRegistrationThread mDeferredRegistrationThread; 82 83 public 84 Loader() 85 { 86 mOldToNewObjectNames = 87 Collections.synchronizedMap( new HashMap <ObjectName ,ObjectName >() ); 88 89 mQueuedAll = false; 90 91 mLoaders = null; 92 93 mRegThread = null; 94 95 mDeferredRegistrationThread = new DeferredRegistrationThread(); 96 mDeferredRegistrationThread.start(); 97 98 } 99 100 protected void 101 preRegisterHook() 102 { 103 mRegThread = new LoaderRegThread( this, mLogger ); 104 mRegThread.start(); 105 } 106 107 111 private static final boolean SYNCHRONOUS_NOTIFICATION_HANDLING = true; 112 113 public void 114 handleNotification( 115 final Notification notifIn, 116 final Object handback) 117 { 118 final String type = notifIn.getType(); 119 120 if ( notifIn instanceof MBeanServerNotification ) 121 { 122 trace( "Loader.handleNotification: received: " + 123 NotificationStringifier.toString( notifIn ) ); 124 125 final MBeanServerNotification notif = (MBeanServerNotification )notifIn; 126 127 final ObjectName objectName = notif.getMBeanName(); 128 129 if ( shouldSync( objectName ) ) 130 { 131 final boolean register = 132 type == MBeanServerNotification.REGISTRATION_NOTIFICATION; 133 134 135 if ( SYNCHRONOUS_NOTIFICATION_HANDLING ) 136 { 137 if ( register ) 138 { 139 mRegThread.processRegistration( objectName ); 140 } 141 else 142 { 143 mRegThread.processUnregistration( objectName ); 144 } 145 } 146 else 147 { 148 mRegThread.enqueue( register, objectName ); 149 } 150 } 151 } 152 } 153 154 private static final long WAIT_THRESHOLD_MILLIS = 5 * 1000; 156 public void 157 handleMBeanRegistered( final ObjectName oldObjectName ) 158 throws InstanceNotFoundException 159 { 160 trace( "handleMBeanRegistered: " + oldObjectName ); 161 162 if ( shouldSync( oldObjectName ) ) 163 { 164 final long start = now(); 165 166 while ( ! getMBeanServer().isRegistered( oldObjectName ) && 167 (now() - start) < WAIT_THRESHOLD_MILLIS ) 168 { 169 mySleep( 50 ); 170 } 171 172 if ( ! getMBeanServer().isRegistered( oldObjectName ) ) 173 { 174 trace( "Loader.handleMBeanRegistered: not found!!!" ); 175 throw new InstanceNotFoundException ( oldObjectName.toString() ); 176 } 177 178 try 179 { 180 sync( oldObjectName ); 181 } 182 catch( Exception e ) 183 { 184 final Throwable rootCause = ExceptionUtil.getRootCause( e ); 185 if ( rootCause instanceof DeferRegistrationException ) 186 { 187 mDeferredRegistrationThread.defer( oldObjectName ); 188 } 189 } 190 } 191 } 192 193 202 private final class DeferredRegistrationThread extends Thread 203 { 204 private final List <DeferredItem> mDeferredItems; 205 private boolean mSleeping; 206 207 private final class DeferredItem 208 { 209 public long mStartMillis; 210 public final ObjectName mObjectName; 211 212 public 213 DeferredItem( final ObjectName objectName ) 214 { 215 mObjectName = objectName; 216 mStartMillis = now(); 217 } 218 }; 219 220 private final long RETRY_INTERVAL_MILLIS = 1000; 221 private final long MAX_DELAY_MILLIS = 1 * 60 * 1000; 222 223 public 224 DeferredRegistrationThread( ) 225 { 226 mDeferredItems = Collections.synchronizedList( new ArrayList <DeferredItem>() ); 227 228 mSleeping = false; 229 } 230 231 private synchronized void 232 internalDefer( final DeferredItem item ) 233 { 234 synchronized( mDeferredItems ) 238 { 239 mDeferredItems.add( item ); 240 } 241 } 242 243 public synchronized void 244 defer( final ObjectName oldObjectName ) 245 { 246 logFine( "Deferring registration for " + quote( oldObjectName ) ); 247 248 internalDefer( new DeferredItem( oldObjectName ) ); 249 250 if ( mSleeping ) 251 { 252 this.interrupt(); 253 } 254 255 } 256 257 private DeferredItem[] 258 takeAllItems() 259 { 260 synchronized( mDeferredItems ) 261 { 262 final DeferredItem[] items = new DeferredItem[ mDeferredItems.size() ]; 263 mDeferredItems.toArray( items ); 264 mDeferredItems.clear(); 265 return( items ); 266 } 267 } 268 269 private ObjectName 270 retry( final ObjectName oldObjectName ) 271 { 272 return sync( oldObjectName ); 273 } 274 275 276 private void 277 retryItem( final DeferredItem item) 278 { 279 final ObjectName oldObjectName = item.mObjectName; 280 281 final String prefix = "DeferredRegistrationThread.retryItem: "; 282 final long elapsed = now() - item.mStartMillis; 283 try 284 { 285 final ObjectName result = retry( oldObjectName ); 286 287 final String msg = prefix + "deferred registration SUCCEEDED after " + 288 elapsed + " milliseconds for " + quote( oldObjectName ) + 289 ", amx ObjectName = " + quote( result ); 290 291 getMBeanLogger().info( msg ); 292 } 293 catch( Throwable t ) 294 { 295 final Throwable rootCause = ExceptionUtil.getRootCause( t ); 296 297 if ( rootCause instanceof DeferRegistrationException ) 298 { 299 if ( elapsed < MAX_DELAY_MILLIS ) 300 { 301 logWarning( prefix + 302 "deferred registration RETRY failed after " + 303 elapsed + " milliseconds for " + quote( oldObjectName ) + " (DEFERRING AGAIN)" ); 304 internalDefer( item ); 305 } 306 else 307 { 308 logWarning( prefix + 309 "Deferred registration FAILED for " + quote( oldObjectName ) + 310 "after deferral of " + elapsed + " ms, ignoring MBean." ); 311 } 312 } 313 else 314 { 315 logWarning( prefix + 316 "Deferred registration FAILED for " + quote( oldObjectName ) + 317 "due to Exception of type " + rootCause.getClass().getName() ); 318 } 319 } 320 } 321 322 private void 323 checkList() 324 { 325 final DeferredItem[] items = takeAllItems(); 326 327 logFine( "DeferredRegistrationThread.checkList: numItems = " + items.length ); 328 329 for( int i = 0; i < items.length; ++i ) 330 { 331 final DeferredItem item = items[ i ]; 332 333 if ( getMBeanServer().isRegistered( item.mObjectName ) ) 334 { 335 retryItem( item ); 336 } 337 else 338 { 339 logInfo( 340 "DeferredRegistrationThread.checkList: " + 341 "MBean is no longer registered: " + quote( item.mObjectName ) ); 342 } 343 } 344 } 345 346 public void 347 run() 348 { 349 while ( true ) 350 { 351 try 352 { 353 getMBeanLogger().fine( "DeferredRegistrationThread.run: CHECKING LIST@" + now() ); 354 checkList(); 355 356 final long sleepMillis = mDeferredItems.size() == 0 ? 60 * 1000 : RETRY_INTERVAL_MILLIS; 358 getMBeanLogger().fine( "DeferredRegistrationThread.run: SLEEPING FOR: " + sleepMillis + "@" + now() ); 359 mSleeping = true; 360 final boolean interrupted = mySleep( sleepMillis ); 361 mSleeping = false; 362 } 363 catch( Throwable t ) 364 { 365 getMBeanLogger().warning( "DeferredRegistrationThread.run: caught Throwable:\n" + 366 ExceptionUtil.getStackTrace( t ) ); 367 } 368 } 369 } 370 } 371 372 public void 373 handleMBeanUnregistered( final ObjectName oldObjectName ) 374 throws InstanceNotFoundException , MBeanRegistrationException 375 { 376 trace( "handleMBeanUnregistered: " + oldObjectName ); 377 378 final ObjectName newObjectName = 379 mOldToNewObjectNames.remove( oldObjectName ); 380 381 if ( newObjectName != null && getMBeanServer().isRegistered( newObjectName ) ) 382 { 383 debug( "unregistering: " + newObjectName + " corresponding to " + oldObjectName ); 384 getMBeanServer().unregisterMBean( newObjectName ); 385 } 386 } 387 388 synchronized ObjectName 389 registerNew( 390 final Object impl, 391 final ObjectName implObjectName, 392 final ObjectName oldObjectName ) 393 throws MBeanRegistrationException , 394 InstanceAlreadyExistsException , NotCompliantMBeanException 395 { 396 debug( "registering: " + implObjectName + " corresponding to " + oldObjectName ); 397 398 final ObjectName resultName = 399 getMBeanServer().registerMBean( impl, implObjectName ).getObjectName(); 400 401 mOldToNewObjectNames.put( oldObjectName, resultName ); 402 403 return( resultName ); 404 } 405 406 public ObjectName 407 loadSystemInfo( final MBeanServer server ) 408 throws NotCompliantMBeanException , MBeanRegistrationException , 409 InstanceAlreadyExistsException 410 { 411 final BootUtil bootUtil = BootUtil.getInstance(); 412 413 final SystemInfoImpl systemInfo = new SystemInfoImpl( server, bootUtil ); 414 415 final ObjectName tempName = mObjectNames.getSingletonObjectName( systemInfo.J2EE_TYPE ); 416 417 final ObjectName objectName = mServer.registerMBean( systemInfo, tempName ).getObjectName(); 418 419 debug( "loaded SystemInfo" ); 420 return( objectName ); 421 } 422 423 private void 424 addLoaders() 425 { 426 assert( getMBeanServer() != null ); 427 assert( getMBeanLogger() != null ); 428 429 final List <LoaderOfOld> loaders = new ArrayList <LoaderOfOld>(); 430 loaders.add( new LoaderOfOldConfig( this ) ); 431 loaders.add( new LoaderOfOld77( this ) ); 432 loaders.add( new LoaderOfOldMonitor( this ) ); 433 mLoaders = Collections.unmodifiableList( loaders ); 434 } 435 436 437 438 private boolean 439 shouldSync( ObjectName oldObjectName ) 440 { 441 return( findLoaderOfOld( oldObjectName ) != null ); 442 } 443 444 private LoaderOfOld 445 findLoaderOfOld( final ObjectName candidate ) 446 { 447 LoaderOfOld oldLoader = null; 448 449 for( final LoaderOfOld loo : mLoaders ) 450 { 451 if ( loo.shouldSync( candidate ) ) 452 { 453 oldLoader = loo; 454 break; 455 } 456 } 457 return( oldLoader ); 458 } 459 460 public ObjectName 461 sync( final ObjectName oldObjectName ) 462 { 463 if ( ! mStarted ) 464 { 465 throw new IllegalArgumentException (); 466 } 467 468 if ( ! shouldSync( oldObjectName ) ) 469 { 470 throw new IllegalArgumentException ( oldObjectName.toString() ); 471 } 472 473 474 long millis = 200; 477 while ( ! getMBeanServer().isRegistered( oldObjectName ) ) 478 { 479 mySleep( millis ); 480 millis *= 2; 481 if ( millis > 500 ) 482 { 483 getMBeanLogger().info( "Loader.sync: waiting for MBean to load: " + oldObjectName ); 484 } 485 } 486 487 488 ObjectName result = null; 489 try 490 { 491 final LoaderOfOld loaderOfOld = findLoaderOfOld( oldObjectName ); 492 493 if ( loaderOfOld != null ) 494 { 495 result = loaderOfOld.syncWithOld( oldObjectName ); 496 if ( result == null ) 497 { 498 throw new IllegalArgumentException ( oldObjectName.toString() ); 499 } 500 } 501 } 502 catch( Exception e ) 503 { 504 final String msg = ExceptionUtil.toString( e ); 505 debug( msg ); 506 getMBeanLogger().fine( msg ); 507 508 if ( e instanceof RuntimeException ) 509 { 510 throw (RuntimeException )e; 511 } 512 else 513 { 514 throw new RuntimeException ( e ); 515 } 516 } 517 518 return( result ); 519 } 520 521 private void 522 queueAll() 523 { 524 for( final LoaderOfOld oldLoader : mLoaders ) 525 { 526 final List oldObjectNames = oldLoader.findAllOld(); 527 mRegThread.enqueue( true, oldObjectNames ); 528 529 getMBeanLogger().fine( "Loader: Queued " + oldObjectNames.size() + 530 " MBeans for loader " + oldLoader.getClass().getName() ); 531 } 532 } 533 534 535 protected void 536 startHook() 537 { 538 super.startHook(); 539 540 addLoaders(); 541 queueAll(); 542 mQueuedAll = true; 543 } 544 545 public boolean 546 isStarted( ) 547 { 548 return super.isStarted() && mQueuedAll && 549 mRegThread.getRegistrationQueueSize() == 0; 550 } 551 552 protected Object 553 createDomainRoot() 554 { 555 return new DomainRootImpl(); 556 } 557 558 public boolean 559 isDAS() 560 { 561 return true; 562 } 563 564 public ObjectName 565 resyncAMXMBean( final ObjectName amx ) 566 throws InstanceNotFoundException , MBeanRegistrationException 567 { 568 if ( ! getMBeanServer().isRegistered( amx ) ) 569 { 570 throw new InstanceNotFoundException (); 571 } 572 if ( ! getAMXJMXDomainName().equals( amx.getDomain() ) ) 573 { 574 throw new IllegalArgumentException ( "" + amx ); 575 } 576 577 debug( "resyncAMXMBean: looking for matching delegate MBean" ); 578 ObjectName old = null; 579 for( final ObjectName oldTemp : mOldToNewObjectNames.keySet() ) 580 { 581 if ( mOldToNewObjectNames.get( oldTemp ).equals( amx ) ) 582 { 583 old = oldTemp; 584 debug( "resyncAMXMBean: found matching delegate MBean: " + old ); 585 break; 586 } 587 } 588 589 if ( old == null ) 590 { 591 throw new IllegalArgumentException ( "" + amx ); 592 } 593 594 debug( "resyncAMXMBean: removing mapping from: " + old + " TO " + amx ); 595 mOldToNewObjectNames.remove( old ); 596 debug( "resyncAMXMBean: unregistering: " + amx ); 597 getMBeanServer().unregisterMBean( amx ); 598 debug( "resyncAMXMBean: handleMBeanRegistered: " + amx ); 599 handleMBeanRegistered( old ); 600 601 final ObjectName newAMX = mOldToNewObjectNames.get( old ); 602 assert( newAMX != null ); 603 604 debug( "resyncAMXMBean: new ObjectName: " + newAMX ); 605 return newAMX; 606 } 607 608 } 609 610 611 612 613 614 615 616 617 | Popular Tags |