1 23 package com.sun.appserv.management.client; 24 25 import java.util.Collection ; 26 import java.util.Set ; 27 import java.util.HashSet ; 28 import java.util.List ; 29 import java.util.ArrayList ; 30 import java.util.Map ; 31 import java.util.HashMap ; 32 import java.util.Collections ; 33 import java.util.logging.Logger ; 34 import java.io.IOException ; 35 import java.lang.reflect.Proxy ; 36 37 import javax.management.MBeanServerConnection ; 38 import javax.management.InstanceNotFoundException ; 39 import javax.management.ObjectName ; 40 import javax.management.MBeanServer ; 41 import javax.management.MalformedObjectNameException ; 42 import javax.management.JMException ; 43 import javax.management.relation.MBeanServerNotificationFilter ; 44 import javax.management.MBeanServerNotification ; 45 import javax.management.Notification ; 46 import javax.management.NotificationListener ; 47 import javax.management.remote.JMXConnector ; 48 import javax.management.remote.JMXConnectionNotification ; 49 50 import com.sun.appserv.management.DomainRoot; 51 import com.sun.appserv.management.base.AMX; 52 import com.sun.appserv.management.base.AMXAttributes; 53 import com.sun.appserv.management.base.XTypes; 54 import com.sun.appserv.management.base.Util; 55 import com.sun.appserv.management.util.jmx.MBeanProxyHandler; 56 import com.sun.appserv.management.util.jmx.MBeanServerConnectionSource; 57 import com.sun.appserv.management.util.jmx.MBeanServerConnectionConnectionSource; 58 import com.sun.appserv.management.util.misc.ClassUtil; 59 import com.sun.appserv.management.util.misc.TypeCast; 60 61 import com.sun.appserv.management.client.ConnectionSource; 62 import com.sun.appserv.management.client.handler.ConverterHandlerFactory; 63 import com.sun.appserv.management.client.handler.ConverterHandlerUtil; 64 import com.sun.appserv.management.client.handler.ProxyCache; 65 66 import com.sun.appserv.management.util.misc.GSetUtil; 67 import com.sun.appserv.management.util.misc.ExceptionUtil; 68 import com.sun.appserv.management.util.jmx.JMXUtil; 69 import com.sun.appserv.management.base.AMXClientLogger; 70 71 78 public final class ProxyFactory implements NotificationListener 79 { 80 private final ProxyCache mProxyCache; 81 private final ConnectionSource mConnectionSource; 82 private final ObjectName mDomainRootObjectName; 83 private final DomainRoot mDomainRoot; 84 private final String mMBeanServerID; 85 86 private static final Map <MBeanServerConnection ,ProxyFactory> INSTANCES = 87 Collections.synchronizedMap( new HashMap <MBeanServerConnection ,ProxyFactory>() ); 88 89 90 private 91 ProxyFactory( final ConnectionSource connSource ) 92 { 93 assert( connSource != null ); 94 95 mConnectionSource = connSource; 96 mProxyCache = new ProxyCache(); 97 98 try 99 { 100 final MBeanServerConnection conn = getConnection(); 101 102 mMBeanServerID = JMXUtil.getMBeanServerID( conn ); 103 104 mDomainRootObjectName = initDomainRootObjectName(); 105 mDomainRoot = initDomainRoot(); 106 107 try 110 { 111 final MBeanServerNotificationFilter filter = 112 new MBeanServerNotificationFilter (); 113 filter.enableAllObjectNames(); 114 filter.disableAllTypes(); 115 filter.enableType( MBeanServerNotification.UNREGISTRATION_NOTIFICATION ); 116 117 JMXUtil.listenToMBeanServerDelegate( conn, this, filter, null ); 118 } 119 catch( Exception e ) 120 { 121 getLogger().warning( "ProxyFactory: connection does not support notifications: " + 122 connSource.toString() ); 123 } 124 125 final JMXConnector connector = connSource.getJMXConnector( false ); 128 if ( connector != null ) 129 { 130 try 131 { 132 connector.addConnectionNotificationListener( this, null, null ); 133 } 134 catch( Exception e ) 135 { 136 getLogger().warning( 137 "ProxyFactory: connector does not support addConnectionNotificationListener: " + 138 connSource ); 139 } 140 } 141 } 142 catch( Exception e ) 143 { 144 getLogger().throwing( getClass().getName(), "ProxyFactory", e ); 145 throw new RuntimeException ( e ); 146 } 147 } 148 149 150 153 private void 154 connectionBad() 155 { 156 synchronized( mProxyCache ) 157 { 158 final Set <ObjectName > keySet = mProxyCache.keySet(); 159 for( final ObjectName key : keySet ) 160 { 161 final AMX proxy = mProxyCache.getCachedProxy( key ); 162 163 mProxyCache.remove( Util.getObjectName( proxy ) ); 164 ConverterHandlerUtil.connectionBad( proxy ); 165 } 166 } 167 } 168 169 172 public boolean 173 checkConnection() 174 { 175 boolean connectionGood = true; 176 177 try 178 { 179 getConnection().isRegistered( JMXUtil.getMBeanServerDelegateObjectName() ); 180 connectionGood = true; 181 } 182 catch( Exception e ) 183 { 184 connectionBad(); 185 } 186 187 return( connectionGood ); 188 } 189 190 191 void 192 notifsLost() 193 { 194 } 196 197 204 public void 205 handleNotification( 206 final Notification notifIn, 207 final Object handback) 208 { 209 final String type = notifIn.getType(); 210 211 if ( type.equals( MBeanServerNotification.UNREGISTRATION_NOTIFICATION) ) 212 { 213 final MBeanServerNotification notif = (MBeanServerNotification )notifIn; 214 final ObjectName objectName = notif.getMBeanName(); 215 final AMX proxy = getProxy( objectName, AMX.class, false ); 216 mProxyCache.remove( objectName ); 217 ConverterHandlerUtil.targetUnregistered(proxy); 218 219 getLogger().fine( "ProxyFactory.handleNotification: UNREGISTERED: " + objectName ); 220 } 221 else if ( notifIn instanceof JMXConnectionNotification ) 222 { 223 if ( type.equals( JMXConnectionNotification.CLOSED ) || 224 type.equals( JMXConnectionNotification.FAILED ) ) 225 { 226 connectionBad(); 227 } 228 else if ( type.equals( JMXConnectionNotification.NOTIFS_LOST ) ) 229 { 230 notifsLost(); 231 } 232 } 233 else 234 { 235 getLogger().fine( "ProxyFactory.handleNotification: UNKNOWN notif: " + type ); 236 } 237 } 238 239 private static Logger 240 getLogger() 241 { 242 return( AMXClientLogger.getInstance() ); 243 } 244 245 private ObjectName 246 initDomainRootObjectName() 247 throws IOException 248 { 249 final MBeanServerConnection conn = mConnectionSource.getMBeanServerConnection( false ); 250 251 final String patternString = "*:" + 252 AMX.J2EE_TYPE_KEY + "=" + XTypes.DOMAIN_ROOT + ",*"; 253 254 ObjectName pattern = null; 255 try 256 { 257 pattern = new ObjectName ( patternString ); 258 } 259 catch ( MalformedObjectNameException e ) 260 { 261 assert( false ); throw new RuntimeException ( e ); 263 } 264 265 final Set <ObjectName > objectNames = JMXUtil.queryNames( conn, pattern, null ); 266 if ( objectNames.size() != 1 ) 267 { 268 throw new IllegalArgumentException ( "Can't find DomainRoot MBean using pattern " + pattern ); 269 } 270 271 final ObjectName objectName = GSetUtil.getSingleton( objectNames ); 272 273 return( objectName ); 274 } 275 276 private final static String DOMAIN_ROOT_KEY = "DomainRoot"; 277 278 public DomainRoot 279 createDomainRoot( ) 280 throws IOException 281 { 282 return( mDomainRoot ); 283 } 284 285 public DomainRoot 286 initDomainRoot( ) 287 throws IOException 288 { 289 final ObjectName domainRootObjectName = getDomainRootObjectName( ); 290 291 final DomainRoot domainRoot = (DomainRoot) 292 newProxyInstance( 293 domainRootObjectName, 294 new Class [] { DomainRoot.class } ); 295 296 return( domainRoot ); 297 } 298 299 306 public DomainRoot 307 getDomainRoot( ) 308 { 309 return getDomainRoot( false ); 310 } 311 312 320 public DomainRoot 321 getDomainRoot( boolean waitReady ) 322 { 323 if ( waitReady ) 324 { 325 mDomainRoot.waitAMXReady(); 326 } 327 328 return( mDomainRoot ); 329 } 330 331 332 335 public ConnectionSource 336 getConnectionSource() 337 { 338 return( mConnectionSource ); 339 } 340 341 344 public String 345 getMBeanServerID() 346 { 347 return( mMBeanServerID ); 348 } 349 350 353 public ObjectName 354 getDomainRootObjectName() 355 throws IOException 356 { 357 return( mDomainRootObjectName ); 358 } 359 360 366 public static ProxyFactory 367 getInstance( final MBeanServer server ) 368 { 369 return( getInstance( new MBeanServerConnectionSource( server ), true ) ); 370 } 371 372 376 public static ProxyFactory 377 getInstance( final MBeanServerConnection conn ) 378 { 379 return( getInstance( new MBeanServerConnectionConnectionSource( conn ), true ) ); 380 } 381 382 385 public static ProxyFactory 386 getInstance( final ConnectionSource conn ) 387 { 388 return( getInstance( conn, true ) ); 389 } 390 391 401 public static synchronized ProxyFactory 402 getInstance( 403 final ConnectionSource connSource, 404 final boolean useMBeanServerID ) 405 { 406 ProxyFactory instance = findInstance( connSource ); 407 408 if ( instance == null ) 409 { 410 try 411 { 412 final MBeanServerConnection conn = 415 connSource.getMBeanServerConnection( false ); 416 417 instance = findInstance( conn ); 418 419 if ( instance == null && 422 ( useMBeanServerID || connSource instanceof MBeanServerConnectionSource ) ) 423 { 424 final String id = JMXUtil.getMBeanServerID( conn ); 425 instance = findInstanceByID( id ); 426 } 427 428 if ( instance == null ) 429 { 430 instance = new ProxyFactory( connSource ); 431 INSTANCES.put( conn, instance ); 432 433 getLogger().fine( "\n----------------\n" + 434 "ProxyFactory.getInstance: created new factory for: " + 435 instance.getMBeanServerID() + 436 "\n----------------\n" ); 437 } 438 } 439 catch( Exception e ) 440 { 441 getLogger().severe( "ProxyFactory.getInstance: " + 442 "Failure trying to create a new ProxyFactory: " + ExceptionUtil.toString( e ) ); 443 throw new RuntimeException ( e ); 444 } 445 } 446 447 return( instance ); 448 } 449 450 453 public static synchronized ProxyFactory 454 findInstance( final ConnectionSource conn ) 455 { 456 return( INSTANCES.get( conn ) ); 457 } 458 459 462 public static synchronized ProxyFactory 463 findInstance( final MBeanServerConnection conn ) 464 { 465 ProxyFactory instance = null; 466 467 final Collection <ProxyFactory> values = INSTANCES.values(); 468 for( final ProxyFactory factory : values ) 469 { 470 if ( factory.getConnectionSource().getExistingMBeanServerConnection( ) == conn ) 471 { 472 instance = factory; 473 break; 474 } 475 } 476 return( instance ); 477 } 478 479 480 483 public static synchronized ProxyFactory 484 findInstanceByID( final String mbeanServerID ) 485 { 486 ProxyFactory instance = null; 487 488 final Collection <ProxyFactory> values = INSTANCES.values(); 489 for( final ProxyFactory factory : values ) 490 { 491 if ( factory.getMBeanServerID().equals( mbeanServerID ) ) 492 { 493 instance = factory; 494 break; 495 } 496 } 497 498 return( instance ); 499 } 500 501 502 506 public AMX 507 getProxy( final ObjectName objectName ) 508 { 509 return getProxy( objectName, true ); 510 } 511 512 520 public AMX 521 getProxy( final ObjectName objectName, boolean create ) 522 { 523 return getProxy( objectName, AMX.class, create ); 524 } 525 526 533 public synchronized <T extends AMX> T 534 getProxy( 535 final ObjectName objectName, 536 final Class <T> theInterface ) 537 { 538 return getProxy( objectName, theInterface, true ); 539 } 540 541 549 public synchronized <T extends AMX> T 550 getProxy( 551 final ObjectName objectName, 552 Class <T> theClass, 553 boolean create ) 554 { 555 AMX proxy = mProxyCache.getCachedProxy( objectName ); 556 557 if ( proxy == null && create ) 558 { 559 proxy = createProxy( objectName ); 560 } 561 return theClass.cast( proxy ); 562 } 563 564 567 protected MBeanServerConnection 568 getConnection() 569 throws IOException 570 { 571 return( getConnectionSource().getMBeanServerConnection( false ) ); 572 } 573 574 579 private AMX 580 createProxy( final ObjectName objectName ) 581 { 582 AMX proxy = null; 583 584 try 585 { 586 String proxyInterfaceName = null; 587 Class proxyInterface = null; 588 589 proxyInterfaceName = (String ) 590 getConnection().getAttribute( objectName, AMXAttributes.ATTR_INTERFACE_NAME ); 591 592 proxyInterface = ClassUtil.getClassFromName( proxyInterfaceName ); 593 594 proxy = newProxyInstance( objectName, new Class [] { proxyInterface } ); 595 } 596 catch( IllegalArgumentException e ) 597 { 598 throw e; 599 } 600 catch( Exception e ) 601 { 602 throw new RuntimeException ( e ); 603 } 604 605 return( proxy ); 606 } 607 608 private MBeanProxyHandler 609 createProxyHandler( final ObjectName objectName ) 610 throws IOException 611 { 612 return ConverterHandlerFactory.createHandler( mConnectionSource, objectName ); 613 } 614 615 616 628 public AMX 629 newProxyInstance( 630 final ObjectName objectName, 631 final Class <?>[] interfaceClasses ) 632 throws IOException 633 { 634 final MBeanProxyHandler handler = createProxyHandler( objectName ); 635 636 final ClassLoader classLoader = interfaceClasses[ 0 ].getClassLoader(); 637 638 final AMX proxy = Util.asAMX(Proxy.newProxyInstance( classLoader, interfaceClasses, handler)); 639 if ( proxy != null ) 640 { 641 mProxyCache.remove( objectName ); 642 mProxyCache.cacheProxy( proxy ); 643 } 644 645 return( proxy ); 646 } 647 648 protected static String 649 toString( final Object o ) 650 { 651 return( com.sun.appserv.management.util.stringifier.SmartStringifier.toString( o ) ); 652 } 653 654 655 660 public Set <AMX> 661 toProxySet( final Set <ObjectName > objectNames ) 662 { 663 final Set <AMX> s = new HashSet <AMX>(); 664 665 for( final ObjectName objectName : objectNames ) 666 { 667 try 668 { 669 final AMX proxy = getProxy( objectName, AMX.class, true ); 670 assert( ! s.contains( proxy ) ); 671 s.add( proxy ); 672 } 673 catch( Exception e ) 674 { 675 final Throwable rootCause = ExceptionUtil.getRootCause( e ); 676 677 System.out.println( "ProxyFactory.toProxySet: exception for MBean " + 679 objectName + " = " + rootCause ); 680 } 681 } 682 683 return( s ); 684 } 685 686 691 public List <AMX> 692 toProxyList( final Collection <ObjectName > objectNames ) 693 { 694 final List <AMX> list = new ArrayList <AMX>(); 695 696 for( final ObjectName objectName : objectNames ) 697 { 698 try 699 { 700 final AMX proxy = getProxy( objectName, AMX.class, true ); 701 list.add( proxy ); 702 } 703 catch( Exception e ) 704 { 705 final Throwable rootCause = ExceptionUtil.getRootCause( e ); 706 707 System.out.println( "ProxyFactory.toProxyList: exception for MBean " + 709 objectName + " = " + rootCause ); 710 } 711 } 712 713 return( list ); 714 } 715 716 722 public Map <String ,AMX> 723 toProxyMap( 724 final Map <String ,ObjectName > objectNameMap ) 725 { 726 final Map <String ,AMX> resultMap = new HashMap <String ,AMX>(); 727 728 final Set <String > keys = objectNameMap.keySet(); 729 730 for( final String key : keys ) 731 { 732 final ObjectName objectName = objectNameMap.get( key ); 733 734 try 735 { 736 final AMX proxy = getProxy( objectName, AMX.class, true ); 737 resultMap.put( key, proxy ); 738 } 739 catch( Exception e ) 740 { 741 final Throwable rootCause = ExceptionUtil.getRootCause( e ); 742 743 System.out.println( "ProxyFactory.toProxyMap: exception for MBean " + 744 objectName + " = " + rootCause ); 745 } 746 } 747 748 return( resultMap ); 749 } 750 751 } 752 753 754 755 756 757 758 759 760 761 762 763 | Popular Tags |