1 23 24 29 package com.sun.enterprise.management.config; 30 31 import java.util.Map ; 32 import java.util.Set ; 33 import java.util.HashSet ; 34 import java.util.HashMap ; 35 import java.util.Iterator ; 36 import java.util.Properties ; 37 import java.util.Collections ; 38 import java.util.logging.Logger ; 39 40 import java.lang.reflect.Method ; 41 42 import javax.management.ObjectName ; 43 import javax.management.MBeanServer ; 44 import javax.management.AttributeList ; 45 import javax.management.Attribute ; 46 import javax.management.InstanceNotFoundException ; 47 48 import com.sun.appserv.management.base.AMX; 49 import com.sun.appserv.management.base.Util; 50 import com.sun.appserv.management.base.Container; 51 import com.sun.appserv.management.base.QueryMgr; 52 53 import com.sun.appserv.management.DomainRoot; 54 55 import com.sun.appserv.management.util.misc.MapUtil; 56 import com.sun.appserv.management.util.misc.StringUtil; 57 import com.sun.appserv.management.util.misc.CollectionUtil; 58 import com.sun.appserv.management.util.stringifier.SmartStringifier; 59 import com.sun.appserv.management.util.misc.Output; 60 61 import com.sun.appserv.management.util.jmx.MBeanRegistrationListener; 62 import com.sun.appserv.management.util.jmx.JMXUtil; 63 64 import com.sun.appserv.management.config.DomainConfig; 65 import com.sun.appserv.management.config.PropertiesAccess; 66 import com.sun.appserv.management.config.CommonConfigKeys; 67 68 import com.sun.enterprise.management.support.ParamNameMapper; 69 import com.sun.enterprise.management.support.LoaderMBean; 70 import com.sun.enterprise.management.support.OldConfigTypes; 71 import com.sun.enterprise.management.support.OldTypeToJ2EETypeMapper; 72 import com.sun.enterprise.management.support.oldconfig.OldConfigProxies; 73 import com.sun.enterprise.management.support.oldconfig.OldResourcesMBean; 74 75 76 import com.sun.appserv.management.base.AMXDebug; 77 78 81 public class ConfigFactory 82 { 83 private final ConfigFactoryCallback mCallbacks; 84 private ParamNameMapper mParamNameMapper = null; 85 private final Output mDebug; 86 87 92 protected final static String CONFIG_NAME_KEY = "Name"; 93 94 public 95 ConfigFactory( final ConfigFactoryCallback callbacks) 96 { 97 mCallbacks = callbacks; 98 99 mDebug = AMXDebug.getInstance().getOutput( getClass().getName() ); 100 } 101 102 protected final MBeanServer 103 getMBeanServer() 104 { 105 return getCallbacks().getMBeanServer(); 106 } 107 108 protected final void 109 debug(final Object o) 110 { 111 mDebug.println( o ); 112 } 113 114 115 protected final ConfigFactoryCallback 116 getCallbacks() 117 { 118 return( mCallbacks ); 119 } 120 121 122 protected static void 123 putNonNull( 124 final Map <String ,String > m, 125 final String key, 126 final Object value) 127 { 128 if ( value != null ) 129 { 130 m.put( key, "" + value ); 131 } 132 } 133 134 protected final String 135 getConfigName() 136 { 137 return( getCallbacks().getConfigName() ); 138 } 139 140 protected final String 141 getContainerName() 142 { 143 final String name = getFactoryContainer().getName(); 144 if ( name == null ) 145 { 146 throw new IllegalArgumentException (); 147 } 148 return name; 149 } 150 151 protected final Logger 152 getLogger() 153 { 154 return( getCallbacks().getLogger() ); 155 } 156 157 protected final DomainRoot 158 getDomainRoot() 159 { 160 return( getCallbacks().getDomainRoot() ); 161 } 162 163 protected final QueryMgr 164 getQueryMgr() 165 { 166 return( getDomainRoot().getQueryMgr() ); 167 } 168 169 protected final DomainConfig 170 getDomainConfig() 171 { 172 return( getDomainRoot().getDomainConfig() ); 173 } 174 175 protected final Container 176 getFactoryContainer() 177 { 178 return( getCallbacks().getFactoryContainer() ); 179 } 180 181 protected final OldConfigProxies 182 getOldConfigProxies() 183 { 184 return( getCallbacks().getOldConfigProxies() ); 185 } 186 187 protected final void 188 remove( ) 189 { 190 throw new RuntimeException ( "form 'remove()' no longer supported" ); 191 } 192 193 protected WaitForUnregistrationListener 194 newWaitForUnregistrationListener( final ObjectName objectName ) 195 { 196 try 197 { 198 return new WaitForUnregistrationListener( objectName ); 199 } 200 catch( Exception e ) 201 { 202 throw new RuntimeException ( e ); 203 } 204 } 205 206 protected final class WaitForUnregistrationListener extends MBeanRegistrationListener 207 { 208 private final ObjectName mTarget; 209 private boolean mDone; 210 211 private WaitForUnregistrationListener( final ObjectName objectName ) 212 throws InstanceNotFoundException , java.io.IOException 213 { 214 super( getMBeanServer(), null ); 215 mDone = false; 216 mTarget = objectName; 217 } 218 219 public ObjectName getTarget() { return mTarget; } 220 public boolean done() { return mDone; } 221 protected void mbeanRegistered( final ObjectName objectName ) {} 222 223 protected void 224 mbeanUnregistered( final ObjectName objectName ) 225 { 226 if ( mTarget.equals( objectName ) ) 227 { 228 mDone = true; 229 cleanup(); 230 } 231 } 232 } 233 234 protected void 235 waitForUnregistration( final WaitForUnregistrationListener l ) 236 { 237 long total = 0; 238 final long SLEEP_MILLIS = 10; 239 final long MAX_WAIT_MILLIS = 5 * 1000; 240 241 while ( total < MAX_WAIT_MILLIS && ! l.done() ) 243 { 244 sleepMillis( SLEEP_MILLIS ); 245 total += SLEEP_MILLIS; 246 } 247 248 if ( ! l.done() ) 249 { 250 throw new RuntimeException ( "MBean failed to unregister: " + 251 JMXUtil.toString( l.getTarget() ) ); 252 } 253 } 254 255 259 public final void 260 remove( final ObjectName objectName ) 261 { 262 if ( objectName == null ) 263 { 264 throw new RuntimeException ( new InstanceNotFoundException () ); 265 } 266 267 final WaitForUnregistrationListener l = 268 newWaitForUnregistrationListener( objectName ); 269 270 internalRemove( objectName ); 271 272 waitForUnregistration( l ); 274 275 getCallbacks().sendConfigRemovedNotification( objectName ); 276 } 277 278 protected void 279 removeByName( final String name ) 280 { 281 throw new UnsupportedOperationException ( "removeByNameInternal" ); 282 } 283 284 protected void 285 internalRemove( final ObjectName objectName ) 286 { 287 removeByName( Util.getName( objectName ) ); 288 } 289 290 293 protected Map <String ,String > 294 getParamNameOverrides() 295 { 296 return( Collections.emptyMap() ); 298 } 299 300 301 protected synchronized ParamNameMapper 302 getParamNameMapper() 303 { 304 if ( mParamNameMapper == null ) 305 { 306 mParamNameMapper = 307 new ParamNameMapper( getParamNameOverrides() ); 308 } 309 310 return( mParamNameMapper ); 311 } 312 313 protected boolean 314 getBooleanOption( final Map <String ,String > m, final String key ) 315 { 316 boolean value = false; 317 final Object obj = (m == null) ? null : m.get( key ); 318 if ( obj != null ) 319 { 320 if ( obj instanceof Boolean ) 321 { 322 value = ((Boolean )obj).booleanValue(); 323 } 324 else if ( obj instanceof String ) 325 { 326 value = Boolean.valueOf( (String )obj ).booleanValue(); 327 } 328 else 329 { 330 throw new IllegalArgumentException ( "Illegal value for Boolean " + key ); 331 } 332 333 } 334 return( value ); 335 } 336 337 protected boolean 338 requireValidReferences( final Map <String ,String > options ) 339 { 340 return ! getBooleanOption( options, CommonConfigKeys.IGNORE_MISSING_REFERENCES_KEY ); 341 } 342 343 344 private final static Class [] ATTRS_ONLY_SIG = 345 new Class [] { AttributeList .class }; 346 private final static Class [] ATTRS_AND_PROPS_SIG = 347 new Class [] { AttributeList .class, Properties .class }; 348 349 350 protected final Method 351 findAnyMethod( String methodName, final Class [] sig ) 352 { 353 Method m = null; 354 try 355 { 356 m = this.getClass().getDeclaredMethod( methodName, sig ); 357 } 358 catch( NoSuchMethodException e ) 359 { 360 } 362 363 return( m ); 364 } 365 366 protected final ObjectName 367 createChild( final Map <String ,String > params ) 368 { 369 return( createNamedChild( null, params ) ); 370 } 371 372 383 protected final ObjectName 384 createNamedChild( 385 final String name, 386 final Map <String ,String > params ) 387 { 388 debug( "createNamedChild: " + name + ":\n{\n" + stringify( params ) + "\n}"); 389 390 final AttributeList attrs = new AttributeList (); 391 final Properties props = new Properties (); 392 393 translateParams( params, attrs, props ); 394 395 debug( "createNamedChild: translated attrs:\n{\n" + stringify( attrs ) + "\n}"); 396 if ( props.keySet().size() != 0 ) 397 { 398 debug( "createNamedChild: translated props:\n" + stringify( props ) ); 399 } 400 401 ObjectName oldObjectName = null; 402 boolean propertiesHandled = false; 403 404 if ( findAnyMethod( "createOldChildConfig", ATTRS_AND_PROPS_SIG ) != null ) 405 { 406 debug( "createNamedChild: calling createOldChildConfig using attrs\n" + 407 stringify( attrs ) + "\nand props \n" + stringify( props ) ); 408 409 oldObjectName = createOldChildConfig( attrs, props ); 410 propertiesHandled = true; 411 } 412 else if ( findAnyMethod( "createOldChildConfig", ATTRS_ONLY_SIG ) != null ) 413 { 414 debug( "createNamedChild: calling createOldChildConfig using attrs\n" + 415 stringify( attrs )); 416 417 oldObjectName = createOldChildConfig( attrs ); 418 } 419 else 420 { 421 throw new UnsupportedOperationException ( "createOldChildConfig" ); 422 } 423 424 return finish( oldObjectName, propertiesHandled ? null : props ); 425 } 426 427 428 protected final ObjectName 429 finish( 430 final ObjectName oldObjectName, 431 final Properties props) 432 { 433 assert( oldObjectName != null ); 434 debug( "createNamedChild: created: " + StringUtil.quote( oldObjectName.toString() ) ); 435 436 if ( ! getMBeanServer().isRegistered( oldObjectName ) ) 437 { 438 throw new RuntimeException ( new InstanceNotFoundException ( oldObjectName.toString() ) ); 439 } 440 441 final ObjectName amxName = getCallbacks().getLoader().sync( oldObjectName ); 443 debug( "createNamedChild: amx object name: " + StringUtil.quote( amxName.toString() ) ); 444 445 if ( props != null && props.size() > 0) 446 { 447 debug( "Setting properties: " + stringify( props ) ); 448 setAllProperties( amxName, props ); 449 } 450 451 getCallbacks().sendConfigCreatedNotification( amxName ); 452 return( amxName ); 453 } 454 455 456 protected static final Set <String > NO_OPTIONAL_KEYS = Collections.emptySet(); 457 460 protected Set <String > 461 getLegalOptionalCreateKeys() 462 { 463 return( NO_OPTIONAL_KEYS ); 464 } 465 466 protected void 467 checkLegalOptions( final Map <String ,String > options ) 468 { 469 if ( options != null ) 470 { 471 final Set <String > legalKeys = getLegalOptionalCreateKeys(); 472 if ( legalKeys != null ) 473 { 474 debug( "Legal optional keys: " + stringify( legalKeys ) ); 475 } 476 if ( legalKeys != null ) 477 { 478 final Map <String ,String > remaining = new HashMap <String ,String >( options ); 480 remaining.keySet().removeAll( legalKeys ); 481 482 final HashMap <String ,String > illegal = new HashMap <String ,String >(); 483 484 final Iterator iter = remaining.keySet().iterator(); 486 while ( iter.hasNext() ) 487 { 488 final String key = (String )iter.next(); 489 if ( ! key.startsWith( PropertiesAccess.PROPERTY_PREFIX ) ) 490 { 491 illegal.put( key, remaining.get( key ) ); 492 } 493 } 494 495 if ( illegal.size() != 0 ) 496 { 497 final String msg = "Illegal optional keys: " + 498 MapUtil.toString( illegal, ","); 499 500 debug( msg ); 501 throw new IllegalArgumentException ( msg ); 502 } 503 } 504 } 505 else 506 { 507 } 509 } 510 511 521 protected final Map <String ,String > 522 initParams( 523 final String name, 524 final String [] required, 525 final Map <String ,String > optional ) 526 { 527 checkLegalOptions( optional ); 528 529 final Map <String ,String > m = initParams( required, optional ); 530 531 if ( name == null || name.length() == 0 ) 532 { 533 throw new IllegalArgumentException ( "Illegal to have null or empty name" ); 534 } 535 536 m.put( CONFIG_NAME_KEY, name ); 537 return( m ); 538 } 539 540 546 protected final void 547 validateParams( final Map <String ,?> params ) 548 { 549 for( final String name : params.keySet() ) 550 { 551 final Object value = params.get( name ); 552 553 validateParam( name, value ); 554 } 555 } 556 557 565 protected final void 566 validateParam( 567 final String name, 568 final Object value ) 569 { 570 if ( name == null || name.length() == 0 ) 571 { 572 throw new IllegalArgumentException ( "parameter name must be non-null and non-empty" ); 573 } 574 575 if ( name.startsWith( PropertiesAccess.PROPERTY_PREFIX ) ) 576 { 577 if ( ! (value instanceof String ) ) 578 { 579 throw new IllegalArgumentException ( "Property value must be string: " + 580 name + ", class =" + value.getClass().getName() ); 581 } 582 } 583 } 584 585 586 589 protected final Map <String ,String > 590 initParams( 591 final String [] required, 592 final Map <String ,String > optionalIn ) 593 { 594 final Map <String ,String > optional = MapUtil.toStringStringMap( optionalIn ); 598 599 final Map <String ,String > m = new HashMap <String ,String >(); 600 601 if ( optional != null ) 602 { 603 m.putAll( optional ); 604 m.remove( CommonConfigKeys.IGNORE_MISSING_REFERENCES_KEY ); 605 } 606 if ( required != null ) 607 { 608 m.putAll( MapUtil.newMap( required ) ); 609 } 610 611 validateParams( m ); 612 613 return( m ); 614 } 615 616 619 protected final Map <String ,String > 620 initParams( final Map <String ,String > optional ) 621 { 622 return( initParams( (String [])null, optional ) ); 623 } 624 625 626 635 protected final void 636 translateParams( 637 final Map <String ,String > paramsToTranslate, 638 final AttributeList attrsOut, 639 final Properties propsOut ) 640 { 641 final ParamNameMapper mapper = getParamNameMapper(); 642 643 final Iterator iter = paramsToTranslate.keySet().iterator(); 644 final String propertyPrefix = PropertiesAccess.PROPERTY_PREFIX; 645 while( iter.hasNext() ) 646 { 647 final String key = (String )iter.next(); 648 final Object value = paramsToTranslate.get( key ); 649 650 if ( key.startsWith( propertyPrefix ) ) 651 { 652 final String name = 653 key.substring( propertyPrefix.length(), key.length() ); 654 655 propsOut.put( name, value ); 656 } 657 else 658 { 659 final String translatedName = mapper.mangleAttributeName( key ); 660 661 final Attribute attr = new Attribute ( translatedName, value ); 662 663 attrsOut.add( attr ); 664 } 665 } 666 } 667 668 675 protected ObjectName 676 createOldChildConfig( 677 final AttributeList translatedAttrs ) 678 { 679 throw new UnsupportedOperationException ( "createOldChildConfig( AttributeList )" ); 680 } 681 682 690 protected ObjectName 691 createOldChildConfig( 692 final AttributeList translatedAttrs, 693 final Properties props ) 694 { 695 throw new UnsupportedOperationException ( "createOldChildConfig( AttributeList, Properties)" ); 696 } 697 698 protected final void 699 trace( Object o ) 700 { 701 debug( o ); 702 } 703 704 protected String 705 stringify( Object o ) 706 { 707 return( SmartStringifier.toString( o ) ); 708 } 709 710 718 protected ObjectName 719 createOldChildByType( 720 final String oldChildType, 721 final AttributeList translatedAttrs ) 722 { 723 throw new UnsupportedOperationException ( "createOldChildByType( String, AttributeList )" ); 724 } 725 726 735 protected ObjectName 736 createOldChildByType( 737 final String oldChildType, 738 final AttributeList translatedAttrs, 739 final Properties props ) 740 { 741 throw new UnsupportedOperationException ( "createOldChildByType( String, AttributeList, Properties )" ); 742 } 743 744 private static final Class [] TYPE_AND_ATTRS_AND_PROPS_SIG = 745 new Class [] { String .class, AttributeList .class, Properties .class }; 746 747 private static final Class [] TYPE_AND_ATTRS_SIG = 748 new Class [] { String .class, AttributeList .class }; 749 750 751 protected final ObjectName 752 createChildByType( 753 final String childJ2EEType, 754 final Map <String ,String > params ) 755 { 756 759 final String oldType = getOldTypeToJ2EETypeMapper().j2eeTypeToOldType( childJ2EEType ); 760 761 assert oldType != null; 762 763 final Properties props = new Properties (); 764 final AttributeList attrs = new AttributeList (); 765 766 translateParams( params, attrs, props ); 767 768 ObjectName oldObjectName = null; 769 boolean propertiesHandled = false; 770 771 if ( findAnyMethod( "createOldChildByType", TYPE_AND_ATTRS_AND_PROPS_SIG ) != null ) 772 { 773 oldObjectName = createOldChildByType( oldType, attrs, props ); 774 propertiesHandled = true; 775 } 776 else if ( findAnyMethod( "createOldChildByType", TYPE_AND_ATTRS_SIG ) != null ) 777 { 778 oldObjectName = createOldChildByType( oldType, attrs ); 779 } 780 else if ( findAnyMethod( "createOldChildByType", ATTRS_ONLY_SIG ) != null ) 781 { 782 oldObjectName = createOldChildConfig( attrs ); 783 } 784 else 785 { 786 throw new UnsupportedOperationException ( "createOldChildByType" ); 787 } 788 789 assert( oldObjectName != null ); 790 debug( "createChildByType: oldObjectName: " + StringUtil.quote( oldObjectName.toString() ) ); 791 792 final ObjectName amxName = getCallbacks().getLoader().sync( oldObjectName ); 794 debug( "createChildByType: amx object name: " + StringUtil.quote( amxName.toString() ) ); 795 796 if ( props.size() > 0 && !propertiesHandled ) 797 { 798 setAllProperties( amxName, props ); 799 } 800 801 getCallbacks().sendConfigCreatedNotification( amxName ); 802 return( amxName ); 803 } 804 805 806 807 808 protected final void 809 setAllProperties( 810 final ObjectName amxObjectName, 811 final Properties props ) 812 { 813 final PropertiesAccess proxy = PropertiesAccess.class.cast( 814 getCallbacks().getProxyFactory().getProxy( amxObjectName, AMX.class) ); 815 816 setAllProperties( proxy, props ); 817 } 818 819 822 protected final void 823 setAllProperties( 824 final PropertiesAccess target, 825 final Properties props ) 826 { 827 final Iterator iter = props.keySet().iterator(); 828 829 while ( iter.hasNext() ) 830 { 831 final String key = (String )iter.next(); 832 833 target.setPropertyValue( key, (String )props.get( key ) ); 834 } 835 } 836 837 838 protected OldTypeToJ2EETypeMapper 839 getOldTypeToJ2EETypeMapper() 840 { 841 return OldConfigTypes.getInstance(); 842 } 843 844 845 846 847 protected ObjectName 848 syncNewAMXMBeanWithOld(ObjectName oldObjectName) 849 { 850 final ObjectName amxName = getCallbacks().getLoader().sync( oldObjectName ); 851 852 getCallbacks().sendConfigCreatedNotification( amxName ); 853 return amxName; 854 } 855 856 857 858 final OldResourcesMBean 859 getOldResourcesMBean() 860 { 861 return( getOldConfigProxies().getOldResourcesMBean( ) ); 862 } 863 864 protected static String 865 quote( Object o ) 866 { 867 return( StringUtil.quote( o.toString() ) ); 868 } 869 870 871 872 protected void 873 checkNonEmptyString( final String s, final String name ) 874 { 875 if ( s == null || s.length() == 0 ) 876 { 877 throw new IllegalArgumentException ( "Parameter may not be null or empty: " + 878 quote( name ) ); 879 } 880 } 881 882 protected final Object 883 getValue( final Map <String ,String > m, final String key ) 884 { 885 return (m == null) ? null : m.get( key ); 886 } 887 888 protected final String 889 getString( final Map <String ,String > m, final String key ) 890 { 891 return (String )getValue( m, key ); 892 } 893 894 protected final Boolean 895 getBoolean( 896 final Map <String ,String > m, 897 final String key, 898 final Boolean defaultValue ) 899 { 900 final Object value = getValue( m, key ); 901 902 return (value == null) ? defaultValue : Boolean.valueOf( "" + value ); 903 } 904 905 906 protected boolean 907 sleepMillis( final long millis ) 908 { 909 boolean interrupted = false; 910 911 try 912 { 913 Thread.sleep( millis ); 914 } 915 catch( InterruptedException e ) 916 { 917 Thread.interrupted(); 918 interrupted = true; 919 } 920 921 return interrupted; 922 } 923 924 protected AMX 925 requireItem( 926 final String j2eeType, 927 final String name ) 928 { 929 final AMX item = getFactoryContainer().getContainee( j2eeType, name ); 930 if ( item == null ) 931 { 932 throw new IllegalArgumentException ( j2eeType + "=" + name ); 933 } 934 return item; 935 } 936 } 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | Popular Tags |