FileDocCategorySizeDatePackage
MBeanProxyHandler.javaAPI DocGlassfish v2 API19619Fri May 25 13:24:12 BST 2007com.sun.appserv.management.util.jmx

MBeanProxyHandler

public class MBeanProxyHandler extends MBeanServerInvocationHandler
Implementation of a proxy handler that supports Attribute names which are not legal Java identifiers. It does so by mapping illegal Java identifiers into legal names. Any interface supplied needs to take mapped names into account.

Allows specification of either an AttributeNameMangler or AttributeNameMapper for maximum flexibility in how illegal Attribute names are mapped.

THREAD SAFE, but not clear if parent class javax.management.MBeanServerInvocationHandler is thread-safe

Fields Summary
protected static final String
GET
protected static final String
SET
protected static final String
IS
protected static final int
GET_PREFIX_LENGTH
protected static final int
IS_PREFIX_LENGTH
protected final com.sun.appserv.management.client.ConnectionSource
mConnectionSource
protected final com.sun.appserv.management.util.jmx.AttributeNameMangler
mMangler
private volatile com.sun.appserv.management.util.jmx.AttributeNameMapper
mMapper
private final ObjectName
mTargetObjectName
private volatile boolean
mCacheMBeanInfo
private volatile MBeanInfo
mCachedMBeanInfo
private volatile boolean
mMBeanInfoIsInvariant
private Logger
mLogger
private volatile boolean
mTargetValid
private final Integer
mHashCode
protected volatile com.sun.appserv.management.util.misc.Output
mDebug
protected static final String
DEBUG_ID
protected static final String
LOGGER_NAME
private final String
LOG_LEVEL_NAME
Constructors Summary
public MBeanProxyHandler(com.sun.appserv.management.client.ConnectionSource connectionSource, ObjectName objectName, com.sun.appserv.management.util.jmx.AttributeNameMangler mangler)
Same as MBeanProxyHandler( connection, objectName ), but can take a name mangler.

param
connectionSource the connection
param
objectName the ObjectName of the proxied MBean
param
mangler optional name mangler for illegal Attribute names

		this( connectionSource, objectName, null, mangler );
	
public MBeanProxyHandler(com.sun.appserv.management.client.ConnectionSource connectionSource, ObjectName objectName, com.sun.appserv.management.util.jmx.AttributeNameMapper mapper)
Same as MBeanProxyHandler( connection, objectName ), but can take a supplied mapper for illegal Attribute names.

param
connectionSource the connection
param
objectName the ObjectName of the proxied MBean
param
mapper optional name mapper for illegal Attribute names

		this( connectionSource, objectName, mapper, null );
	
public MBeanProxyHandler(com.sun.appserv.management.client.ConnectionSource connectionSource, ObjectName objectName)
Normally created through MBeanProxyFactory.newProxyInstance(). Creates a new instance to be used as a handler object for Proxy.newProxyInstance.

param
connectionSource the connection
param
objectName the ObjectName of the proxied MBean

		this( connectionSource, objectName, (AttributeNameMangler)null );
	
private MBeanProxyHandler(com.sun.appserv.management.client.ConnectionSource connectionSource, ObjectName objectName, com.sun.appserv.management.util.jmx.AttributeNameMapper mapper, com.sun.appserv.management.util.jmx.AttributeNameMangler mangler)

		super( connectionSource.getMBeanServerConnection( false ), objectName );
		
        mDebug  = AMXDebug.getInstance().getOutput( getDebugID() );
		debugMethod( "MBeanProxyHandler", connectionSource, objectName, mapper, mangler );
		mMangler			= mangler;
		mMapper				= mapper;
		mConnectionSource	= connectionSource;
		mTargetObjectName	= objectName;
		mTargetValid		= true;
		
		mCacheMBeanInfo		= true;
		mCachedMBeanInfo	= null;
		mLogger		= null;
		
		mHashCode	= this.hashCode();
	
Methods Summary
protected synchronized voidcacheMBeanInfo(boolean cacheIt)

		mCacheMBeanInfo	= cacheIt;
		mMBeanInfoIsInvariant	= cacheIt;
		if ( ! cacheIt )
		{
			mCachedMBeanInfo	= null;
		}
	
public final booleancheckValid()

		if ( mTargetValid )
		{
			try
			{
				mTargetValid	= getConnection().isRegistered( getTargetObjectName() );
			}
			catch( Exception e )
			{
			    debug( "checkValid: connection failed" );
				mTargetValid	= false;
			}
		}
		return( mTargetValid );
	
public final voidconnectionBad()

		debugMethod( "connectionBad" );
		mTargetValid	= false;
		assert( ! targetIsValid() );
	
com.sun.appserv.management.util.jmx.AttributeNameMappercreateMapper(javax.management.MBeanAttributeInfo[] attributeInfos, com.sun.appserv.management.util.jmx.AttributeNameMangler mangler)
Create a mapper based on the supplied attributeInfos

param
attributeInfos
param
mangler
return
AttributeNameMapper

		return( new AttributeNameMapperImpl( getAllAttributeNames( attributeInfos ), mangler ) );
	
protected voiddebug(java.lang.Object args)

	    if ( getDebug() )
	    {
	        mDebug.println( StringUtil.toString( "", args) );
	    }
	
protected voiddebug(java.lang.Object o)

	    mDebug.println( o );
	
protected voiddebugMethod(java.lang.String methodName, java.lang.Object args)

	    if ( getDebug() )
	    {
	        mDebug.println( AMXDebug.methodString( methodName, args ) );
	    }
	
protected voiddebugMethod(java.lang.String msg, java.lang.String methodName, java.lang.Object args)

	    if ( getDebug() )
	    {
	        mDebug.println( AMXDebug.methodString( methodName, args ) + ": " + msg );
	    }
	
public booleanequals(java.lang.Object rhs)

   	    if ( rhs == this )
   	    {
   	        return true;
   	    }
   	    
   	    final MBeanProxyHandler other   = (MBeanProxyHandler)rhs;
   	    
       	boolean equals  = mTargetObjectName.equals( other.getTargetObjectName() );
       	if ( equals )
       	{
       	    try
       	    {
           	    equals  = getConnection() == other.getConnection();
       	    }
       	    catch( Exception e )
       	    {
       	        equals  = false;
       	    }
   	    }
   	    
   	    return equals;
   	
protected java.lang.StringextractAttributeNameFromMethod(java.lang.String methodName)

		assert( methodName.startsWith( GET ) || 
				methodName.startsWith( SET ) || 
				methodName.startsWith( IS ) );
		final int startIndex = methodName.startsWith( GET ) || methodName.startsWith( SET ) ? 
			GET_PREFIX_LENGTH : IS_PREFIX_LENGTH;
		return( methodName.substring( startIndex, methodName.length() ) );
	
public static java.lang.String[]getAllAttributeNames(javax.management.MBeanAttributeInfo[] infos)

		return( JMXUtil.getAttributeNames( infos ) );
	
public java.lang.ObjectgetAttribute(java.lang.String attributeName)
Same as XAttributesAccess.getAttribute, but with exceptions

		final Object	result	=
			getConnection().getAttribute( getTargetObjectName(), attributeName );
			
   		postGetAttributeHook( attributeName, result );
	
		return( result );
	
public javax.management.AttributeListgetAttributes(java.lang.String[] attrNames)
Same as XAttributesAccess.getAttributes, but with exceptions

		final AttributeList	results	=
			getConnection().getAttributes( getTargetObjectName(), attrNames );
			
   		postGetAttributesHook( attrNames, results );
   		
   		return( results );
	
protected final booleangetCacheMBeanInfo()

		return( mCacheMBeanInfo );
	
protected final javax.management.MBeanServerConnectiongetConnection()

		return( mConnectionSource.getMBeanServerConnection( false ) );
	
public final com.sun.appserv.management.client.ConnectionSourcegetConnectionSource()

		return( mConnectionSource );
	
protected booleangetDebug()

        return AMXDebug.getInstance().getDebug( getDebugID() );
    
protected java.lang.StringgetDebugID()

	    return DEBUG_ID;
	
protected javax.management.MBeanInfogetMBeanInfo(boolean refresh)
Same as XAttributesAccess.getAttributes, but with exceptions

param
refresh whether to get a fresh copy

		if ( refresh ||
			(! mCacheMBeanInfo) ||
			mCachedMBeanInfo == null )
		{
            synchronized( this )
            {
                mCachedMBeanInfo = getConnection().getMBeanInfo( getTargetObjectName() );
            }
		}
		return( mCachedMBeanInfo );
	
public final booleangetMBeanInfoIsInvariant()

		return( mMBeanInfoIsInvariant );
	
public synchronized java.util.logging.LoggergetProxyLogger()

	
		  
	 
	
		if ( mLogger == null )
		{
			mLogger	= Logger.getLogger( this.getClass().getName() );
		}
		return( mLogger );
	
protected final javax.management.ObjectNamegetTargetObjectName()

		return( mTargetObjectName );
	
public inthashCode()

   	
 	     
 	
 	
 	    return ObjectUtil.hashCode( mTargetObjectName,
 	            mConnectionSource, mLogger, mMangler, mMapper, mCachedMBeanInfo, mDebug) ^
 	        ObjectUtil.hashCode( mCacheMBeanInfo ) ^
 	        ObjectUtil.hashCode( mMBeanInfoIsInvariant ) ^
 	        ObjectUtil.hashCode( mTargetValid );
 	
protected voidinitMapper()
Initialize a mapper based on the supplied attributeInfos. Does nothing if already initialized.

		// lazy initialization here
		if ( mMapper == null && mMangler != null)
		{
			final MBeanInfo	mbeanInfo	= getMBeanInfo( true );
			
            synchronized( this )
            {
                if ( mMapper == null )
                {
                    mMapper	= createMapper( mbeanInfo.getAttributes(), mMangler);
                }
            }
		}
	
public java.lang.Objectinvoke(java.lang.Object proxy, java.lang.reflect.Method method, java.lang.Object[] args)
Invoke the specified method. This implementation supports additional functionality over the JMX MBeanServerInvocationHandler: (1) It supports mapped Attribute names (ones that are not legal Java names) (2) it supports XAttributesAccess, which otherwise does not work correctly

For anything else, the behavior of MBeanServerInvocationHandler is used.

   		final String	methodName	= method.getName();
   		final int		numArgs	= args == null ? 0 : args.length;
   		
		debugMethod( method.getName(), args );
		
   		Object	result	= null;
   		
   		final boolean	isGetter		= JMXUtil.isIsOrGetter( method );
   		final boolean	isSetter		= isGetter ? false : JMXUtil.isSetter( method );
   		
   		boolean		handled	= false;
   		
		if ( methodName.equals( "getTargetObjectName" ) )
		{
			handled	= true;
			result	= getTargetObjectName();
		}
		else if ( methodName.equals( "getMBeanInfo" ) && numArgs <= 1)
		{
			handled	= true;
			
			if ( numArgs == 1 )
			{
				result	= getMBeanInfo( ((Boolean)args[ 0 ] ).booleanValue() );
			}
			else if ( numArgs == 0 )
			{
				result	= getMBeanInfo( mCacheMBeanInfo );
			}
			else
			{
				handled	= false;
			}
		}
		else if ( methodName.equals( "getProxyLogger" ) && numArgs == 0 )
		{
			handled	= true;
			result	= getProxyLogger();
		}
		else if ( methodName.equals( "setProxyLogger" ) &&
					numArgs == 1 &&
					method.getParameterTypes()[ 0 ] == Logger.class )
		{
			handled	= true;
			setProxyLogger( (Logger)args[ 0 ] );
		}
		else if ( (isGetter || isSetter) )
		{
			handled	= true;
			// it's a plain getFoo(), setFoo( f ) call 
			initMapper( );
			
			final String	javaName	= extractAttributeNameFromMethod( methodName );

			String	attributeName	= javaName;
			
			if ( isMappedAttributeMethod( javaName ) )
			{
	   			attributeName	= mMapper.derivedToOriginal( javaName );
	   		}
	   			
			//trace( "MBeanProxyHandler.invoke: mapped attribute: " + javaName + " => " + attributeName );
			
   			if ( isGetter )
   			{
   				result	= getAttribute( attributeName );
   			}
   			else
   			{
   				final Attribute	attr	= new Attribute( attributeName, args[ 0 ] );
   				setAttribute( attr );
   			}
   		}
   		else if ( methodName.indexOf( "etAttribute" ) == 1 )
   		{
	   		handled	= true;
	   			
   			// likely one of getAttribute(), getAttributes(), setAttribute(), setAttributes()
   			
			//p( "MBeanProxyHandler.invoke: " + method.getName() + " " + numArgs + " args." );
	   		if ( JMXUtil.isGetAttribute( method ) )
	   		{
	   			final String	attrName	= (String)args[ 0 ];
	   			result	= getAttribute( attrName );
	   		}
	   		else if ( JMXUtil.isGetAttributes( method ) )
	   		{
	   			final String[]	attrNames	= (String[])args[ 0 ];
	   			result	= (AttributeList)getAttributes( attrNames );
	   		}
	   		else if ( JMXUtil.isSetAttribute( method ) )
	   		{
	   			final Attribute	attr	= (Attribute)args[ 0 ];
	   			setAttribute( attr );
	   		}
	   		else if ( JMXUtil.isSetAttributes( method ) )
	   		{
	   			final AttributeList	requested	= (AttributeList)args[ 0 ];
	   			result	= (AttributeList)setAttributes( requested );
	   		}
	   		else
	   		{
	   			handled	= false;
	   		}
   		}
   		else if ( methodName.equals( "hashCode" ) )
	    {
   			/*
   				java.lang.reflect.Proxy will route all calls through invoke(),
   				even hashCode().  To avoid newing up an Integer every time,
   				just return a stored version.  hashCode() is called frequently
   				when proxies are inserted into Sets or Maps.  toString() and
   				equals() don't seem to get called however.
   			 */
   			result	= mHashCode;
	   		handled = true;
   		}
   		else if ( methodName.equals( "toString" ) )
	    {
	   		result  = "proxy to " + JMXUtil.toString( getTargetObjectName() );
	   		handled = true;
   		}
   		else if ( methodName.equals( "equals" ) && numArgs == 1)
	    {
	   		result  = this.equals( args[ 0 ] );
	   		handled = true;
   		}
   		
   		if ( ! handled )
   		{
   			debugMethod( getTargetObjectName().toString(), "super.invoke",
   				method.getName(), args );

   			result	= super.invoke( proxy, method, args );
   		}
			
   		return( result );
   	
protected booleanisMappedAttributeMethod(java.lang.String attributeName)

		boolean	isMapped	= false;
		
		if ( mMapper != null )
		{
			final String	originalName	= mMapper.derivedToOriginal( attributeName );
			
			isMapped	= ! attributeName.equals( originalName );
		}
		
		return( isMapped );
	
protected voidpostGetAttributeHook(java.lang.String name, java.lang.Object value)

   	
		 
	
		 		
		 		 
	
	
protected voidpostGetAttributesHook(java.lang.String[] requested, javax.management.AttributeList actual)

	
protected voidpostSetAttributeHook(javax.management.Attribute attr)

	
protected voidpostSetAttributesHook(javax.management.AttributeList requested, javax.management.AttributeList actual)

	
public voidsetAttribute(javax.management.Attribute attr)
Same as XAttributesAccess.setAttribute, but with exceptions

		getConnection().setAttribute( getTargetObjectName(), attr );
		
   		postSetAttributeHook( attr );
	
public javax.management.AttributeListsetAttributes(javax.management.AttributeList requested)
Same as XAttributesAccess.setAttributes, but with exceptions

		final AttributeList	results	= getConnection().setAttributes( getTargetObjectName(), requested );
		
   		postSetAttributesHook( requested, results );
   				
		return( results );
	
protected final voidsetMBeanInfoIsInvariant(boolean isInvariant)

		mMBeanInfoIsInvariant	= isInvariant;
	
public synchronized voidsetProxyLogger(java.util.logging.Logger logger)

		mLogger	= logger;
	
protected final booleantargetIsValid()

		return( mTargetValid );
	
public final voidtargetUnregistered()

		debugMethod( mTargetObjectName.toString(), "targetUnregistered" );
		mTargetValid	= false;
		assert( ! targetIsValid() );