FileDocCategorySizeDatePackage
SunoneInterceptor.javaAPI DocGlassfish v2 API33605Fri May 04 22:33:48 BST 2007com.sun.enterprise.admin.server.core.jmx

SunoneInterceptor

public final class SunoneInterceptor extends Object implements com.sun.enterprise.interceptor.DynamicInterceptorHook
A class that is a poor man's interceptor. There are following reasons that led to use this interceptor and not the standard JMX 1.2 interceptor.
  • Tight deadlines and smoke test has to work :(
  • We have lazy loading going on. (Again poor man's) This means that any MBean has to be registered first before it can be invoked. We did not have any good solution at the architectural level for that, nor does JMX 1.2 have it. The way we do it is to check that persistent medium and/or Java Beans derived from the dtd and initialized from domain.xml (in memory) indicate that such an element should exist, and then we register the mbean before invoking it. This solves the problem of initialization meaning the MBeans for all the elements in configuration file (domain.xml) do not have to be registered in order to invoke the operation.
  • Still, we want a JMX 1.2 implementation of the MBeanServer as some immediate future work may need it.
  • Ugliness to begin with gives birth to more ugliness. This class has to handle the case of config files being hand edited. :(((
  • Hence this interceptor results. All it does is the following:
  • Implements the javax.management.MBeanServer as sincerely as possible.
  • Uses Lazy loading meaning that the MBeans will be registered if they do not already exist in registry of the MBeanServer. An attempt will be made to see that config bean already exists. (This is not a violation per se, but an interpretation of the MBeanServer specification).
  • see
    javax.management.MBeanServer
    since
    8.0

    Fields Summary
    protected final com.sun.appserv.management.helper.AMXDebugHelper
    mDebug
    private static final String
    HOT_CONFIG_METHOD_NAME
    private static final String
    FORCE_APPLY_METHOD_NAME
    private static final String
    APPLY_METHOD_NAME
    private static final String
    USE_MANUAL_METHOD_NAME
    private static final String
    GET_HOST_AND_PORT_METHOD_NAME
    private static final Logger
    sLogger
    private static final com.sun.enterprise.util.i18n.StringManager
    localStrings
    private final com.sun.enterprise.admin.AdminContext
    adminContext
    private final MBeanServer
    delegateMBeanServer
    private final MBeanServer
    proxyMBeanServer
    private final MBeanServer
    outerMBeanServer
    private static SunoneInterceptor
    _Instance
    private static final String
    DottedMBeansIniterClassName
    Load the MBeans which support dotted names.
    private static boolean
    _alreadyCalled
    Constructors Summary
    private SunoneInterceptor(com.sun.enterprise.admin.AdminContext adminContextIn, MBeanServer outerMBeanServerIn, MBeanServer delegateMBeanServerIn)

    param
    adminContextIn the AdminContext
    param
    outerMBeanServer the MBeanServer to be used for registering MBeans
    param
    delegateMBeanServer the MBeanServer to which requests are forwarded

            
            mDebug  = new AMXDebugHelper( "__SunoneInterceptor__" );
            mDebug.setEchoToStdOut( true );
            debug( "SunoneInterceptor.SunoneInterceptor" );
    
    
            adminContext        = adminContextIn;
            delegateMBeanServer = delegateMBeanServerIn;
            
            outerMBeanServer = outerMBeanServerIn;
            proxyMBeanServer = (MBeanServer)ProxyFactory.createProxy(
                        MBeanServer.class, delegateMBeanServer,
                        adminContext.getMBeanServerInterceptor());
            logMBeanServerInfo();
            try {
                initialize(); 
            } catch( Exception e ) {
                throw new RuntimeException(e);
            }
        
    Methods Summary
    private voidcheckHotConfigChanges(javax.management.ObjectName mbeanName)

            //different case
            try {
                //check whether the mbeanName pertains to a server instance.
    //            String instanceName = ObjectNameHelper.getServerInstanceName(mbeanName);
    String instanceName = ApplicationServer.getServerContext().getInstanceName();
                ObjectName instanceObjectName = ObjectNames.getServerInstanceObjectName(instanceName);
                Object canApply = this.invoke(instanceObjectName, HOT_CONFIG_METHOD_NAME,
                    null, null);
                //debug("return value" + canApply);
                if (canApply.equals(Boolean.FALSE)) {
    				String msg = localStrings.getString(
                           "admin.server.core.jmx.configuration_changed_apply_changes",
                           instanceName);
                    throw new AFRuntimeStoreException( msg );
                }
            } catch(AFRuntimeStoreException af) { 
                throw af;
            } catch (Exception e) {
    			String msg = localStrings.getString( "admin.server.core.jmx.bad_server_configuration" );
                sLogger.log(Level.INFO, msg, e);
                throw new AFRuntimeException( msg, e );
            }
        
    private javax.management.ObjectInstancecreateAndRegister(java.lang.String className, javax.management.ObjectName objectName)

            final Class  mbeanClass				= Class.forName( className );
            final Object mbeanImpl				= mbeanClass.newInstance();
            final ObjectInstance mbeanInstance	= this.registerMBean( mbeanImpl, objectName );
            
            sLogger.log(Level.FINE, "core.system_mbean_init_ok", objectName.toString() );
            return( mbeanInstance );
    	
    public static synchronized com.sun.enterprise.admin.server.core.jmx.SunoneInterceptorcreateInstance(com.sun.enterprise.admin.AdminContext adminContext, javax.management.MBeanServer outerMBeanServer, javax.management.MBeanServer delegateMBeanServer)

            if ( _Instance != null ) {
                throw new IllegalStateException();
            }
            _Instance = new SunoneInterceptor(
                adminContext, outerMBeanServer, delegateMBeanServer );
            return _Instance;
        
    protected final voiddebug(java.lang.Object args)

        
              
           
        
            mDebug.println( args );
        
    private voidgenerateEntryContext(java.lang.Object obj)

            ServerEntryHelper.generateMbeanEntryContext((ObjectName) obj);
        
    public java.lang.ObjectgetAttribute(javax.management.ObjectName objectName, java.lang.String attributeName)

            if(isInstanceMBean(objectName)) {
                checkHotConfigChanges(objectName);
            }
            registerWithPersistenceCheck(objectName);
            //logMBeanInfo(objectName);
            Object value = proxyMBeanServer.getAttribute(objectName, attributeName);
            return ( value );
        
    public javax.management.AttributeListgetAttributes(javax.management.ObjectName objectName, java.lang.String[] attrNames)

    //, RuntimeOperationsException
    //        if(isInstanceMBean(objectName)) 
            {
                checkHotConfigChanges(objectName);
            }
            
            registerWithPersistenceCheck(objectName);
            return ( proxyMBeanServer.getAttributes(objectName, attrNames) );
        
    public java.lang.ClassLoadergetClassLoader(javax.management.ObjectName objectName)

            debug( "SunoneInterceptor: getClassLoader: " + objectName );
            registerWithPersistenceCheck(objectName);
            return proxyMBeanServer.getClassLoader( objectName );
        
    public java.lang.ClassLoadergetClassLoaderFor(javax.management.ObjectName objectName)

            debug( "SunoneInterceptor: getClassLoaderFor: " + objectName );
            registerWithPersistenceCheck(objectName);
            return proxyMBeanServer.getClassLoaderFor( objectName );
        
    private javax.management.loading.ClassLoaderRepositorygetClassLoaderRepository()

            debug( "SunoneInterceptor: getClassLoaderRepository()" );
    		return ( proxyMBeanServer.getClassLoaderRepository() );
        
    public static synchronized com.sun.enterprise.admin.server.core.jmx.SunoneInterceptorgetInstance()

            if ( _Instance == null ) {
                throw new IllegalStateException();
            }
            return _Instance;
        
    public javax.management.MBeanInfogetMBeanInfo(javax.management.ObjectName objName)

    		registerWithPersistenceCheck(objName);
            return ( proxyMBeanServer.getMBeanInfo(objName) );
        
    private voidinitialize()
    Initializes the MBeanServer. This method registers the System MBeans. The System MBeans are assumed to have default constructor.

    throws
    InitException if any of the System MBeans can't be initialized.

            final ObjectName controllerObjectName 
                    = ObjectNames.getControllerObjectName();
            final ObjectName configObjectName     
                    = ObjectNames.getGenericConfiguratorObjectName();
            final ObjectName[] objectNames = { 
                controllerObjectName,
                configObjectName };
            final String controllerClassName = 
                "com.sun.enterprise.admin.server.core.mbean.config.ServerController";
            final String configClassName = 
                "com.sun.enterprise.admin.server.core.mbean.config.GenericConfigurator";
            final String[] clNames = {controllerClassName, configClassName};
                for (int i = 0 ; i < clNames.length ; i++) {
                    createAndRegister( clNames[i], objectNames[ i ] );
                }
            registerDottedNameSupport();
         
    public java.lang.Objectinvoke(javax.management.ObjectName objectName, java.lang.String operationName, java.lang.Object[] params, java.lang.String[] signature)

            generateEntryContext(objectName);
    	  
            if(isInstanceMBean(objectName) && isConfigCheckRequired(operationName)) {
                checkHotConfigChanges(objectName);
            }
            
             if(FORCE_APPLY_METHOD_NAME.equals(operationName)) {
                 // Manual changes to config will be overwritten, so persist the
                 // state restart is required.
                 String instanceName =
                         ObjectNameHelper.getServerInstanceName(objectName);
                 AdminEventCache cache = AdminEventCache.getInstance(instanceName);
                 cache.setRestartNeeded(true);
                //operationName = APPLY_METHOD_NAME;
             }
            registerWithPersistenceCheck(objectName);
            //logMBeanInfo(objectName);
            Object actualResult = proxyMBeanServer.invoke(objectName, operationName,
                params, signature );
            return ( actualResult );
        
    private booleanisConfigCheckRequired(java.lang.String operationName)

            //debug("Entering isConfigCheckRequired:" + operationName);
            
            if(GET_HOST_AND_PORT_METHOD_NAME.equals(operationName)) {
                //debug("getHostAndPort: returning FALSE");
                return false;
            }
            
            if(FORCE_APPLY_METHOD_NAME.equals(operationName)) {
                    //debug("overwriteConfigChanges: returning FALSE");
                    return false;
            }
            
            if(USE_MANUAL_METHOD_NAME.equals(operationName)) {
                //debug("useManualConfigChanges: returning FALSE");
                return false;
            }
            
           
            if(HOT_CONFIG_METHOD_NAME.equals(operationName)) {
                return false;
            }
            
            //START: Optimization to prevent multiple checks for changes
            if("getMBeanInfo".equals(operationName)) {
                return false;
            }
            //END: Optimization to prevent multiple checks for changes
             
            //debug("RETURNING true");
            return true;
        
    private booleanisInstanceMBean(javax.management.ObjectName mbeanName)

            if(ObjectNameHelper.getServerInstanceName(mbeanName) != null) { 
                return true;
            } else {
                return false;
            }
        
    private voidlogMBeanInfo(javax.management.ObjectName oName)

            
            // if we are not logging at the finest level, just return
            if (!sLogger.isLoggable(Level.FINEST)) {
                return;            
            }
            
            //This method assumes that the mbean is registered.
    	MBeanInfo info = null;
    	try {
    	    info = proxyMBeanServer.getMBeanInfo(oName);
    	} catch (Exception e) {
    	    e.printStackTrace();
    	    return;
    	}
    	sLogger.log(Level.FINEST,"\nCLASSNAME: \t"+ info.getClassName());
    	sLogger.log(Level.FINEST,"\nDESCRIPTION: \t"+ info.getDescription());
    	sLogger.log(Level.FINEST,"\nATTRIBUTES");
    	MBeanAttributeInfo[] attrInfo = info.getAttributes();
    	if (attrInfo.length>0) {
    	    for(int i=0; i<attrInfo.length; i++) {
    		sLogger.log(Level.FINEST," ** NAME: \t"+ attrInfo[i].getName());
    		sLogger.log(Level.FINEST,"    DESCR: \t"+ attrInfo[i].getDescription());
    		sLogger.log(Level.FINEST,"    TYPE: \t"+ attrInfo[i].getType() +
    		     "\tREAD: "+ attrInfo[i].isReadable() +
    		     "\tWRITE: "+ attrInfo[i].isWritable());
    	    }
    	} else 
                sLogger.log(Level.FINEST," ** No attributes **");
    	sLogger.log(Level.FINEST,"\nCONSTRUCTORS");
    	MBeanConstructorInfo[] constrInfo = info.getConstructors();
    	for(int i=0; i<constrInfo.length; i++) {
    	    sLogger.log(Level.FINEST," ** NAME: \t"+ constrInfo[i].getName());
    	    sLogger.log(Level.FINEST,"    DESCR: \t"+ constrInfo[i].getDescription());
    	    sLogger.log(Level.FINEST,"    PARAM: \t"+ constrInfo[i].getSignature().length +" parameter(s)");
    	}
    	sLogger.log(Level.FINEST,"\nOPERATIONS");
    	MBeanOperationInfo[] opInfo = info.getOperations();
    	if (opInfo.length>0) {
    	    for(int i=0; i<opInfo.length; i++) {
    		sLogger.log(Level.FINEST," ** NAME: \t"+ opInfo[i].getName());
    		sLogger.log(Level.FINEST,"    DESCR: \t"+ opInfo[i].getDescription());
    		sLogger.log(Level.FINEST,"    PARAM: \t"+ opInfo[i].getSignature().length +" parameter(s)");
    	    }
    	} else 
                sLogger.log(Level.FINEST," ** No operations ** ");
    	sLogger.log(Level.FINEST,"\nNOTIFICATIONS");
    	MBeanNotificationInfo[] notifInfo = info.getNotifications();
    	if (notifInfo.length>0) {
    	    for(int i=0; i<notifInfo.length; i++) {
    		sLogger.log(Level.FINEST," ** NAME: \t"+ notifInfo[i].getName());
    		sLogger.log(Level.FINEST,"    DESCR: \t"+ notifInfo[i].getDescription());
    	    }
    	} else 
                 sLogger.log(Level.FINEST," ** No notifications **");
        
    private voidlogMBeanServerInfo()
    Logs the MBeanServer information. It is logged to the server's output/error log, to convey the information about MBeanServer implementation used.

    throws
    RuntimeException if there are some problems in invoking implementation methods.

            try {
                final String        name  = "JMImplementation:type=MBeanServerDelegate";
                final ObjectName    oName = new ObjectName(name);
                
                sLogger.log(Level.FINE, "core.mbs_info");
                //log the implementation name
                String attrName     = "ImplementationName";
                String result       = (String) proxyMBeanServer.
                        getAttribute(oName, attrName);
                sLogger.log(Level.FINE, "core.mbs_implementation", result);
                //log the implementation vendor
                attrName    = "ImplementationVendor";
                result      = (String) proxyMBeanServer.getAttribute(oName, attrName);
                sLogger.log(Level.FINE, "core.mbs_vendor", result);
                //log the impl version
                attrName = "ImplementationVersion";
                result = (String) proxyMBeanServer.getAttribute(oName, attrName);
                sLogger.log(Level.FINE, "core.jmx_impl_version", result);
                //log the MBeanServerId
                attrName = "MBeanServerId";
                result = (String) proxyMBeanServer.getAttribute(oName, attrName);
                sLogger.log(Level.FINE, "core.mbs_id", result);
                result = proxyMBeanServer.getClass().getName();
                sLogger.log(Level.FINE, "core_mbs_classname", result);            
            }
            catch(Exception e) {
                throw new RuntimeException (e);
            }
        
    private synchronized voidmanufactureAndRegisterMBean(javax.management.ObjectName oName)
    this method added to synchronize lazy loaded MBeans manufacturing and registering

            //the "second" check inside synchronized area (it will perevent double manufacturing)
            if ( outerMBeanServer.isRegistered(oName) ) {
                //sLogger.log(Level.FINE, "core.mbean_exists", oName);
                debug( "manufactureAndRegisterMBean: already registered: " + oName );
                return;  //already registered
            }
            //call to lazy loading here
            final Object product = manufactureMBean(oName);
            if(product==null)
            {
                debug( "manufactureAndRegisterMBean: can't manufacture: " + oName );
                final String msg = localStrings.getString(
                       "admin.server.core.jmx.lazybean_not_found",
                       oName.toString());
                throw new InstanceNotFoundException(msg);
            }
            //register MBean.
            debug( "manufactureAndRegisterMBean: registering: " + oName );
            this.registerMBean(product, oName);
            debug( "manufactureAndRegisterMBean: registered: " + oName );
            sLogger.log(Level.FINE, "core.create_and_register", oName);
        
    private java.lang.ObjectmanufactureMBean(javax.management.ObjectName oName)

            final PersistenceChecker checker         = new PersistenceChecker();
            checker.setAdminContext(adminContext);
            final Object             storedObject	 = checker.findElement(oName);
            Object                   match           = null;
            if (storedObject != null) {
                MBeanManufacturer producer = new MBeanManufacturer(oName, storedObject);
                producer.setAdminContext(adminContext);
                match = producer.createMBeanInstance();
            }
            else {
                //this is severe - storage is not in sync with whatever is requested to be done.
                sLogger.log(Level.FINEST, "core.not_in_config", oName);
            }
            //Actually it should be asserted that match is NOT null.
            return ( match );
        
    public synchronized voidregisterConfigMBeans()

    
            
            if(! _alreadyCalled ) {
                _alreadyCalled = true;
                try {
                    final MBeanRegistry mr = MBeanRegistryFactory.getAdminMBeanRegistry();   
                    mr.instantiateAndRegisterAllConfigMBeans(
                         adminContext.getAdminConfigContext(), 
                         ApplicationServer.getServerContext().getDefaultDomainName());
                }
                catch (Throwable t) {
                     sLogger.log(Level.WARNING, "Error in registering configMBeans", t);
                }
            }
        
    private voidregisterDottedNameSupport()

    			
    		 
    	
              
                 
                
    	
    		final Class		initerClass	= Class.forName( DottedMBeansIniterClassName );
    		
    		// invoke new DottedNamesMBeanIniter( MBeanServer m )
    		final Class []		signature	= new Class [] { MBeanServer.class };
    		final java.lang.reflect.Constructor	constructor	= initerClass.getConstructor( signature );
    		constructor.newInstance( new Object [] { outerMBeanServer } );
    		// done--it will have done its job
    	
    private javax.management.ObjectInstanceregisterMBean(java.lang.Object object, javax.management.ObjectName objectName)

            // !!! registration must be done with 'outerMBeanServer';
            // we are not delegating here and so the "outside world" must see
            // the registration
            return outerMBeanServer.registerMBean(object, objectName);
        
    private voidregisterWithPersistenceCheck(javax.management.ObjectName oName)
    This method does the following in a sequential manner:
  • If the MBean with given ObjectName is registered, do nothing.
  • If the MBean does not exist, create the MBean by "manufacturing process".
  • If the MBean is thus manufactured, then register that MBean in MBeanServer.
  • param
    oName ObjectName that corresponds to a single MBean - should not be a pattern.
    since
    8.0.
    exception
    IllegalArgumentException if oName is a pattern.
    exception
    RuntimeException with actual exception embedded in case operation fails.

            if ( "ias".equals( oName.getDomain() ) ) {
                throw new RuntimeException( "JMX domain 'ias' not suppported" );
            }
            
            if (! outerMBeanServer.isRegistered(oName) ) {
        debug( "MBean NOT registered, will try to manufacture: " + oName );
                try {
                    //Manufacture the MBean now.
                    manufactureAndRegisterMBean(oName);
        debug( "Manufactured: " + oName );
                }
                catch (InstanceNotFoundException infe)
                {
        debug( "FAILED to manufacture: " + oName + " | " + infe );
                    throw infe;
                }
                catch (RuntimeException re)
                {
        debug( "FAILED to manufacture: " + oName + " | " + re );
                    throw re;
                }
                catch (Exception e) {
        debug( "FAILED to manufacture: " + oName + " | " + e );
                    throw new RuntimeException(e);
                }
            }
        
    public voidsetAttribute(javax.management.ObjectName objectName, javax.management.Attribute attribute)

            if(isInstanceMBean(objectName)) {
                checkHotConfigChanges(objectName);
            }
            registerWithPersistenceCheck(objectName);
            //logMBeanInfo(objectName);
            proxyMBeanServer.setAttribute(objectName, attribute);
        
    public javax.management.AttributeListsetAttributes(javax.management.ObjectName objectName, javax.management.AttributeList attributeList)

            if(isInstanceMBean(objectName)) {
                checkHotConfigChanges(objectName);
            }
    
            registerWithPersistenceCheck(objectName);
            return ( proxyMBeanServer.setAttributes(objectName, attributeList) );
        
    private voidshutdown()

            MBeanServerFactory.releaseMBeanServer(proxyMBeanServer);
            sLogger.log(Level.FINE, "core.release_mbs");