FileDocCategorySizeDatePackage
DynamicMBeanProxy.javaAPI DocGlassfish v2 API14810Fri May 04 22:33:16 BST 2007org.apache.tomcat.util.mx

DynamicMBeanProxy

public class DynamicMBeanProxy extends Object implements DynamicMBean
DynamicMBean implementation using introspection to manage any component that follows the bean/ant/Interceptor/Valve/Jk2 patterns. The class will wrap any component conforming to those patterns.
deprecated
The same functionality ( and more ) is now available in commons-modeler
author
Costin Manolache

Fields Summary
Object
real
String
name
Method[]
methods
Hashtable
attMap
Hashtable
getAttMap
Hashtable
setAttMap
Hashtable
invokeAttMap
static MBeanServer
mserver
static Hashtable
instances
static final Object[]
NO_ARGS_PARAM
private static com.sun.org.apache.commons.logging.Log
log
Constructors Summary
public DynamicMBeanProxy()
Create a Dynamic proxy, using introspection to manage a real tomcat component.

    
                      
      
        
    
Methods Summary
public static java.lang.StringcreateMBean(java.lang.Object proxy, java.lang.String domain, java.lang.String name)

        try {
            DynamicMBeanProxy mbean=new DynamicMBeanProxy();
            mbean.setReal( proxy );
            if( name!=null ) {
                mbean.setName( name );
            } else {
                mbean.setName( generateName( proxy.getClass() ));
            }

            return mbean.registerMBean( domain );
        } catch( Throwable t ) {
            log.error( "Error creating mbean ", t );
            return null;
        }
    
public static java.lang.StringgenerateName(java.lang.Class realClass)
If a name was not provided, generate a name based on the class name and a sequence number.

        String name=realClass.getName();
        name=name.substring( name.lastIndexOf( ".") + 1 );
        Integer iInt=(Integer)instances.get(name );
        int seq=0;
        if (iInt != null) {
            seq = iInt.intValue();
            seq++;
            instances.put(name, Integer.valueOf(seq));
        }
        else {
            instances.put(name, Integer.valueOf(0));
        }
        return "name=" + name + ",seq=" + seq;
    
public java.lang.ObjectgetAttribute(java.lang.String attribute)

    
       
           
    
        if( methods==null ) init();
        Method m=(Method)getAttMap.get( attribute );
        if( m==null ) throw new AttributeNotFoundException(attribute);

        try {
            if( log.isDebugEnabled() )
                log.debug(real.getClass().getName() +  " getAttribute " + attribute);
            return m.invoke(real, NO_ARGS_PARAM );
        } catch( IllegalAccessException ex ) {
            ex.printStackTrace();
            throw new MBeanException( ex );
        } catch( InvocationTargetException ex1 ) {
            ex1.printStackTrace();
            throw new MBeanException( ex1 );
        }
    
public javax.management.AttributeListgetAttributes(java.lang.String[] attributes)

        AttributeList al=new AttributeList();
        if( attributes==null ) return null;
        
        for( int i=0; i<attributes.length; i++ ) {
            try {
                Attribute att=new Attribute( attributes[i], getAttribute( attributes[i] ));
                al.add( att );
            } catch( Exception ex ) {
                ex.printStackTrace();
            }
        }
        return al;
    
public javax.management.MBeanInfogetMBeanInfo()

todo
Find if the 'className' is the name of the MBean or the real class ( I suppose first )
todo
Read (optional) descriptions from a .properties, generated from source
todo
Deal with constructors

        if( methods==null ) {
            init();
        }
        try {
            MBeanAttributeInfo attributes[]=new MBeanAttributeInfo[attMap.size()];

            Enumeration en=attMap.keys();
            int i=0;
            while( en.hasMoreElements() ) {
                String name=(String)en.nextElement();
                attributes[i++]=new MBeanAttributeInfo(name, "Attribute " + name ,
                                                       (Method)getAttMap.get(name),
                                                       (Method)setAttMap.get(name));
            }
            
            MBeanOperationInfo operations[]=new MBeanOperationInfo[invokeAttMap.size()];
            
            en=invokeAttMap.keys();
            i=0;
            while( en.hasMoreElements() ) {
                String name=(String)en.nextElement();
                Method m=(Method)invokeAttMap.get(name);
                if( m!=null && name != null ) {
                    operations[i++]=new MBeanOperationInfo(name, m);
                } else {
                    if (log.isDebugEnabled())
                        log.debug("Null arg " + name + " " + m );
                }
            }
            
            if( log.isDebugEnabled() )
                log.debug(real.getClass().getName() +  " getMBeanInfo()");
            
            return new MBeanInfo( real.getClass().getName(), /* ??? */
                                  "MBean for " + getName(),
                                  attributes,
                                  new MBeanConstructorInfo[0],
                                  operations,
                                  new MBeanNotificationInfo[0]);
        } catch( Exception ex ) {
            ex.printStackTrace();
            return null;
        }
    
public static javax.management.MBeanServergetMBeanServer()

        if( mserver==null ) {
            if( MBeanServerFactory.findMBeanServer(null).size() > 0 ) {
                mserver=(MBeanServer)MBeanServerFactory.findMBeanServer(null).get(0);
            } else {
                mserver=MBeanServerFactory.createMBeanServer();
            }
        }
        
        return mserver;
    
public java.lang.StringgetName()

        if( name!=null ) return name;

        if( real==null ) return null;

        name=generateName(real.getClass());
        return name;
    
private voidinit()

        if( methods!=null ) return;
        methods = real.getClass().getMethods();
        for (int j = 0; j < methods.length; ++j) {
            String name=methods[j].getName();
            
            if( name.startsWith( "get" ) ) {
                if( methods[j].getParameterTypes().length != 0 ) {
                    continue;
                }
                if( ! Modifier.isPublic( methods[j].getModifiers() ) ) {
                    //log.debug("not public " + methods[j] );
                    continue;
                }
                Class ret=methods[j].getReturnType();
                if( ! supportedType( ret ) ) {
                    if( log.isDebugEnabled() )
                        log.debug("Unsupported " + ret );
                    continue;
                }
                name=unCapitalize( name.substring(3));

                getAttMap.put( name, methods[j] );
                // just a marker, we don't use the value 
                attMap.put( name, methods[j] );
            } else if( name.startsWith( "is" ) ) {
                // not used in our code. Add later

            } else if( name.startsWith( "set" ) ) {
                Class params[]=methods[j].getParameterTypes();
                if( params.length != 1 ) {
                    continue;
                }
                if( ! Modifier.isPublic( methods[j].getModifiers() ) )
                    continue;
                Class ret=params[0];
                if( ! supportedType( ret ) ) {
                    continue;
                }
                name=unCapitalize( name.substring(3));
                setAttMap.put( name, methods[j] );
                attMap.put( name, methods[j] );
            } else {
                if( methods[j].getParameterTypes().length != 0 ) {
                    continue;
                }
                if( methods[j].getDeclaringClass() == Object.class )
                    continue;
                if( ! Modifier.isPublic( methods[j].getModifiers() ) )
                    continue;
                invokeAttMap.put( name, methods[j]);
            }
        }
    
public java.lang.Objectinvoke(java.lang.String method, java.lang.Object[] arguments, java.lang.String[] params)
Invoke a method. Only no param methods are supported at the moment ( init, start, execute, etc ) ( that's the most common pattern we have in tomcat/ant/etc )

todo
Implement invoke for methods with more arguments.

        if( methods==null ) init();
        Method m=(Method)invokeAttMap.get( method );
        if( m==null ) return null;

        try {
            log.info(real.getClass().getName() +  "invoke " + m.getName());
            return m.invoke(real, NO_ARGS_PARAM );
        } catch( IllegalAccessException ex ) {
            throw new MBeanException( ex );
        } catch( InvocationTargetException ex1 ) {
            throw new MBeanException( ex1 );
        }
    
public java.lang.StringregisterMBean(java.lang.String domain)

        try {
            // XXX use aliases, suffix only, proxy.getName(), etc
            String fullName=domain + ": " +  getName();
            ObjectName oname=new ObjectName( fullName );

            if(  getMBeanServer().isRegistered( oname )) {
                log.info("Unregistering " + oname );
                getMBeanServer().unregisterMBean( oname );
            }
            getMBeanServer().registerMBean( this, oname );
            return fullName;
        } catch( Throwable t ) {
            log.error( "Error creating mbean ", t );
            return null;
        }
    
public voidsetAttribute(javax.management.Attribute attribute)

        if( methods==null ) init();
        // XXX Send notification !!!
        Method m=(Method)setAttMap.get( attribute.getName() );
        if( m==null ) throw new AttributeNotFoundException(attribute.getName());

        try {
            log.info(real.getClass().getName() +  "setAttribute " + attribute.getName());
            m.invoke(real, new Object[] { attribute.getValue() } );
        } catch( IllegalAccessException ex ) {
            ex.printStackTrace();
            throw new MBeanException( ex );
        } catch( InvocationTargetException ex1 ) {
            ex1.printStackTrace();
            throw new MBeanException( ex1 );
        }
    
public javax.management.AttributeListsetAttributes(javax.management.AttributeList attributes)

        Iterator attE=attributes.iterator();
        while( attE.hasNext() ) {
            Attribute att=(Attribute)attE.next();

            try {
                setAttribute( att );
            } catch( Exception ex ) {
                ex.printStackTrace();
            }
        }
        return attributes;
    
public voidsetName(java.lang.String name)

        this.name=name;
    
public voidsetReal(java.lang.Object realBean)
Set the managed object.

todo
Read an XML ( or .properties ) file containing descriptions, generated from source comments
todo
Also filter methods based on config ( hide methods/attributes )
todo
Adapters for notifications ( Interceptor hooks, etc ).

        real=realBean;
    
private booleansupportedType(java.lang.Class ret)

        return ret == String.class ||
            ret == Integer.class ||
            ret == Integer.TYPE ||
            ret == Long.class ||
            ret == Long.TYPE ||
            ret == java.io.File.class ||
            ret == Boolean.class ||
            ret == Boolean.TYPE 
            ; 
    
public static java.lang.StringunCapitalize(java.lang.String name)

	if (name == null || name.length() == 0) {
	    return name;
	}
	char chars[] = name.toCharArray();
	chars[0] = Character.toLowerCase(chars[0]);
	return new String(chars);
    
public static voidunregisterMBean(java.lang.Object o, java.lang.String name)

        try {
            ObjectName oname=new ObjectName( name );

            getMBeanServer().unregisterMBean( oname );
        } catch( Throwable t ) {
            log.error( "Error unregistering mbean ", t );
        }