FileDocCategorySizeDatePackage
Registry.javaAPI DocApache Tomcat 6.0.1433667Fri Jul 20 04:20:32 BST 2007org.apache.tomcat.util.modeler

Registry

public class Registry extends Object implements RegistryMBean, MBeanRegistration
Registry for modeler MBeans. This is the main entry point into modeler. It provides methods to create and manipulate model mbeans and simplify their use. Starting with version 1.1, this is no longer a singleton and the static methods are strongly deprecated. In a container environment we can expect different applications to use different registries. This class is itself an mbean. IMPORTANT: public methods not marked with @since x.x are experimental or internal. Should not be used.
author
Craig R. McClanahan
author
Costin Manolache

Fields Summary
private static org.apache.juli.logging.Log
log
The Log instance to which we will write our log messages.
private static HashMap
perLoaderRegistries
Will be used to isolate different apps and enhance security.
private static Registry
registry
The registry instance created by our factory method the first time it is called.
private MBeanServer
server
The MBeanServer instance that we will use to register management beans.
private HashMap
descriptors
The set of ManagedBean instances for the beans this registry knows about, keyed by name.
private HashMap
descriptorsByClass
List of managed byeans, keyed by class name
private HashMap
searchedPaths
private Object
guard
private Hashtable
idDomains
private Hashtable
ids
Constructors Summary
public Registry()


    
    // ----------------------------------------------------------- Constructors

         
       
        super();
    
Methods Summary
public voidaddManagedBean(ManagedBean bean)
Add a new bean metadata to the set of beans known to this registry. This is used by internal components.

param
bean The managed bean to be added
since
1.0

        // XXX Use group + name
        descriptors.put(bean.getName(), bean);
        if( bean.getType() != null ) {
            descriptorsByClass.put( bean.getType(), bean );
        }
    
public java.lang.ObjectconvertValue(java.lang.String type, java.lang.String value)
EXPERIMENTAL Convert a string to object, based on type. Used by several components. We could provide some pluggability. It is here to keep things consistent and avoid duplication in other tasks

param
type Fully qualified class name of the resulting value
param
value String value to be converted
return
Converted value

        Object objValue=value;
        
        if( type==null || "java.lang.String".equals( type )) {
            // string is default
            objValue=value;
        } else if( "javax.management.ObjectName".equals( type ) ||
                "ObjectName".equals( type )) {
            try {
                objValue=new ObjectName( value );
            } catch (MalformedObjectNameException e) {
                return null;
            }
        } else if( "java.lang.Integer".equals( type ) ||
                "int".equals( type )) {
            objValue=new Integer( value );
        } else if( "java.lang.Long".equals( type ) ||
                "long".equals( type )) {
            objValue=new Long( value );
        } else if( "java.lang.Boolean".equals( type ) ||
                "boolean".equals( type )) {
            objValue=new Boolean( value );
        }
        return objValue;
    
private voidfindDescriptor(java.lang.Class beanClass, java.lang.String type)
Lookup the component descriptor in the package and in the parent packages.

param
beanClass
param
type

        if( type==null ) {
            type=beanClass.getName();
        }
        ClassLoader classLoader=null;
        if( beanClass!=null ) {
            classLoader=beanClass.getClassLoader();
        }
        if( classLoader==null ) {
            classLoader=Thread.currentThread().getContextClassLoader();
        }
        if( classLoader==null ) {
            classLoader=this.getClass().getClassLoader();
        }
        
        String className=type;
        String pkg=className;
        while( pkg.indexOf( ".") > 0 ) {
            int lastComp=pkg.lastIndexOf( ".");
            if( lastComp <= 0 ) return;
            pkg=pkg.substring(0, lastComp);
            if( searchedPaths.get( pkg ) != null ) {
                return;
            }
            loadDescriptors(pkg, classLoader);
        }
        return;
    
public ManagedBeanfindManagedBean(java.lang.String name)
Find and return the managed bean definition for the specified bean name, if any; otherwise return null.

param
name Name of the managed bean to be returned. Since 1.1, both short names or the full name of the class can be used.
since
1.0

        // XXX Group ?? Use Group + Type
        ManagedBean mb=((ManagedBean) descriptors.get(name));
        if( mb==null )
            mb=(ManagedBean)descriptorsByClass.get(name);
        return mb;
    
public ManagedBeanfindManagedBean(java.lang.Object bean, java.lang.Class beanClass, java.lang.String type)
Find or load metadata.

        if( bean!=null && beanClass==null ) {
            beanClass=bean.getClass();
        }
        
        if( type==null ) {
            type=beanClass.getName();
        }
        
        // first look for existing descriptor
        ManagedBean managed = findManagedBean(type);

        // Search for a descriptor in the same package
        if( managed==null ) {
            // check package and parent packages
            if( log.isDebugEnabled() ) {
                log.debug( "Looking for descriptor ");
            }
            findDescriptor( beanClass, type );

            managed=findManagedBean(type);
        }
        
        if( bean instanceof DynamicMBean ) {
            if( log.isDebugEnabled() ) {
                log.debug( "Dynamic mbean support ");
            }
            // Dynamic mbean
            loadDescriptors("MbeansDescriptorsDynamicMBeanSource",
                    bean, type);

            managed=findManagedBean(type);
        }

        // Still not found - use introspection
        if( managed==null ) {
            if( log.isDebugEnabled() ) {
                log.debug( "Introspecting ");
            }

            // introspection
            loadDescriptors("MbeansDescriptorsIntrospectionSource",
                    beanClass, type);

            managed=findManagedBean(type);
            if( managed==null ) {
                log.warn( "No metadata found for " + type );
                return null;
            }
            managed.setName( type );
            addManagedBean(managed);
        }
        return managed;
    
public ManagedBeanfindManagedBean(java.lang.Class beanClass, java.lang.String type)

        return findManagedBean(null, beanClass, type);        
    
public java.lang.String[]findManagedBeans()
Return the set of bean names for all managed beans known to this registry.

since
1.0

        return ((String[]) descriptors.keySet().toArray(new String[0]));
    
public java.lang.String[]findManagedBeans(java.lang.String group)
Return the set of bean names for all managed beans known to this registry that belong to the specified group.

param
group Name of the group of interest, or null to select beans that do not belong to a group
since
1.0


        ArrayList results = new ArrayList();
        Iterator items = descriptors.values().iterator();
        while (items.hasNext()) {
            ManagedBean item = (ManagedBean) items.next();
            if ((group == null) && (item.getGroup() == null)) {
                results.add(item.getName());
            } else if (group.equals(item.getGroup())) {
                results.add(item.getName());
            }
        }
        String values[] = new String[results.size()];
        return ((String[]) results.toArray(values));

    
public synchronized intgetId(java.lang.String domain, java.lang.String name)
Return an int ID for faster access. Will be used for notifications and for other operations we want to optimize.

param
domain Namespace
param
name Type of the notification
return
An unique id for the domain:name combination
since
1.1

        if( domain==null) {
            domain="";
        }
        Hashtable domainTable=(Hashtable)idDomains.get( domain );
        if( domainTable == null ) {
            domainTable=new Hashtable();
            idDomains.put( domain, domainTable); 
        }
        if( name==null ) {
            name="";
        }
        Integer i=(Integer)domainTable.get(name);
        
        if( i!= null ) {
            return i.intValue();
        }

        int id[]=(int [])ids.get( domain );
        if( id == null ) {
            id=new int[1];
            ids.put( domain, id); 
        }
        int code=id[0]++;
        domainTable.put( name, new Integer( code ));
        return code;
    
public synchronized javax.management.MBeanServergetMBeanServer()
Factory method to create (if necessary) and return our MBeanServer instance.

        long t1=System.currentTimeMillis();

        if (server == null) {
            if( MBeanServerFactory.findMBeanServer(null).size() > 0 ) {
                server=(MBeanServer)MBeanServerFactory.findMBeanServer(null).get(0);
                if( log.isDebugEnabled() ) {
                    log.debug("Using existing MBeanServer " + (System.currentTimeMillis() - t1 ));
                }
            } else {
                server=MBeanServerFactory.createMBeanServer();
                if( log.isDebugEnabled() ) {
                    log.debug("Creating MBeanServer"+ (System.currentTimeMillis() - t1 ));
                }
            }
        }
        return (server);
    
public javax.management.MBeanOperationInfogetMethodInfo(javax.management.ObjectName oname, java.lang.String opName)
Find the operation info for a method

param
oname
param
opName
return
the operation info for the specified operation

        String type=null;
        MBeanInfo info=null;
        try {
            info=server.getMBeanInfo(oname);
        } catch (Exception e) {
            log.info( "Can't find metadata " + oname );
            return null;
        }
        MBeanOperationInfo attInfo[]=info.getOperations();
        for( int i=0; i<attInfo.length; i++ ) {
            if( opName.equals(attInfo[i].getName())) {
                return attInfo[i];
            }
        }
        return null;
    
private org.apache.tomcat.util.modeler.modules.ModelerSourcegetModelerSource(java.lang.String type)

        if( type==null ) type="MbeansDescriptorsDigesterSource";
        if( type.indexOf( ".") < 0 ) {
            type="org.apache.tomcat.util.modeler.modules." + type;
        }

        Class c=Class.forName( type );
        ModelerSource ds=(ModelerSource)c.newInstance();
        return ds;
    
public static synchronized org.apache.tomcat.util.modeler.RegistrygetRegistry()
Get a "singelton" registry, or one per thread if setUseContextLoader was called

deprecated
Not enough info - use the method that takes CL and domain
since
1.0

        return getRegistry(null, null);
    
public static synchronized org.apache.tomcat.util.modeler.RegistrygetRegistry(java.lang.Object key, java.lang.Object guard)
Factory method to create (if necessary) and return our Registry instance. Use this method to obtain a Registry - all other static methods are deprecated and shouldn't be used. The current version uses a static - future versions could use the thread class loader.

param
key Support for application isolation. If null, the context class loader will be used ( if setUseContextClassLoader is called ) or the default registry is returned.
param
guard Prevent access to the registry by untrusted components
since
1.1

        Registry localRegistry;
        if( perLoaderRegistries!=null ) {
            if( key==null ) 
                key=Thread.currentThread().getContextClassLoader();
            if( key != null ) {
                localRegistry=(Registry)perLoaderRegistries.get(key);
                if( localRegistry == null ) {
                    localRegistry=new Registry();
//                    localRegistry.key=key;
                    localRegistry.guard=guard;
                    perLoaderRegistries.put( key, localRegistry );
                    return localRegistry;
                }
                if( localRegistry.guard != null &&
                        localRegistry.guard != guard ) {
                    return null; // XXX Should I throw a permission ex ? 
                }
                return localRegistry;
            }
        }

        // static 
        if (registry == null) {
            registry = new Registry();
        }
        if( registry.guard != null &&
                registry.guard != guard ) {
            return null;
        }
        return (registry);
    
public static javax.management.MBeanServergetServer()
Factory method to create (if necessary) and return our MBeanServer instance.

since
1.0
deprecated
Use the instance method

        return Registry.getRegistry().getMBeanServer();
    
public java.lang.StringgetType(javax.management.ObjectName oname, java.lang.String attName)
Get the type of an attribute of the object, from the metadata.

param
oname
param
attName
return
null if metadata about the attribute is not found
since
1.1

        String type=null;
        MBeanInfo info=null;
        try {
            info=server.getMBeanInfo(oname);
        } catch (Exception e) {
            log.info( "Can't find metadata for object" + oname );
            return null;
        }

        MBeanAttributeInfo attInfo[]=info.getAttributes();
        for( int i=0; i<attInfo.length; i++ ) {
            if( attName.equals(attInfo[i].getName())) {
                type=attInfo[i].getType();
                return type;
            }
        }
        return null;
    
public voidinvoke(java.util.List mbeans, java.lang.String operation, boolean failFirst)
Invoke a operation on a list of mbeans. Can be used to implement lifecycle operations.

param
mbeans list of ObjectName on which we'll invoke the operations
param
operation Name of the operation ( init, start, stop, etc)
param
failFirst If false, exceptions will be ignored
throws
Exception
since
1.1

        if( mbeans==null ) {
            return;
        }
        Iterator itr=mbeans.iterator();
        while(itr.hasNext()) {
            Object current=itr.next();
            ObjectName oN=null;
            try {
                if( current instanceof ObjectName) {
                    oN=(ObjectName)current;
                }
                if( current instanceof String ) {
                    oN=new ObjectName( (String)current );
                }
                if( oN==null ) {
                    continue;
                }
                if( getMethodInfo(oN, operation) == null) {
                    continue;
                }
                getMBeanServer().invoke(oN, operation,
                        new Object[] {}, new String[] {});

            } catch( Exception t ) {
                if( failFirst ) throw t;
                log.info("Error initializing " + current + " " + t.toString());
            }
        }
    
public java.util.Listload(java.lang.String sourceType, java.lang.Object source, java.lang.String param)
Experimental.

param
sourceType
param
source
param
param
return
List of descriptors
throws
Exception
deprecated
bad interface, mixing of metadata and mbeans

        if( log.isTraceEnabled()) {
            log.trace("load " + source );
        }
        String location=null;
        String type=null;
        Object inputsource=null;

        if( source instanceof DynamicMBean ) {
            sourceType="MbeansDescriptorsDynamicMBeanSource";
            inputsource=source;
        } else if( source instanceof URL ) {
            URL url=(URL)source;
            location=url.toString();
            type=param;
            inputsource=url.openStream();
            if( sourceType == null ) {
                sourceType = sourceTypeFromExt(location);
            }
        } else if( source instanceof File ) {
            location=((File)source).getAbsolutePath();
            inputsource=new FileInputStream((File)source);            
            type=param;
            if( sourceType == null ) {
                sourceType = sourceTypeFromExt(location);
            }
        } else if( source instanceof InputStream ) {
            type=param;
            inputsource=source;
        } else if( source instanceof Class ) {
            location=((Class)source).getName();
            type=param;
            inputsource=source;
            if( sourceType== null ) {
                sourceType="MbeansDescriptorsIntrospectionSource";
            }
        }
        
        if( sourceType==null ) {
            sourceType="MbeansDescriptorsDigesterSource";
        }
        ModelerSource ds=getModelerSource(sourceType);
        List mbeans=ds.loadDescriptors(this, location, type, inputsource);

        return mbeans;
    
public voidloadCachedDescriptors(java.lang.Object source)
Load the registry from a cached .ser file. This is typically 2-3 times faster than parsing the XML.

param
source Source to be used to load. Can be an InputStream or URL.
exception
Exception if any parsing or processing error occurs
deprecated
Loaded automatically or using a File or Url ending in .ser

        loadDescriptors("MbeansDescriptorsSerSource", source, null );
    
public voidloadDescriptors(java.lang.String packageName, java.lang.ClassLoader classLoader)
Lookup the component descriptor in the package and in the parent packages.

param
packageName

        String res=packageName.replace( '.", '/");

        if( log.isTraceEnabled() ) {
            log.trace("Finding descriptor " + res );
        }

        if( searchedPaths.get( packageName ) != null ) {
            return;
        }
        String descriptors=res + "/mbeans-descriptors.ser";

        URL dURL=classLoader.getResource( descriptors );

        if( dURL == null ) {
            descriptors=res + "/mbeans-descriptors.xml";
            dURL=classLoader.getResource( descriptors );
        }
        if( dURL == null ) {
            return;
        }

        log.debug( "Found " + dURL);
        searchedPaths.put( packageName,  dURL );
        try {
            if( descriptors.endsWith(".xml" ))
                loadDescriptors("MbeansDescriptorsDigesterSource", dURL, null);
            else
                loadDescriptors("MbeansDescriptorsSerSource", dURL, null);
            return;
        } catch(Exception ex ) {
            log.error("Error loading " + dURL);
        }

        return;
    
public voidloadDescriptors(java.lang.String sourceType, java.lang.Object source, java.lang.String param)
Experimental. Will become private, some code may still use it

param
sourceType
param
source
param
param
throws
Exception
deprecated

        List mbeans=load( sourceType, source, param );
        if( mbeans == null) return;

        Iterator itr=mbeans.iterator();
        while( itr.hasNext() ) {
            Object mb=itr.next();
            if( mb instanceof ManagedBean) {
                addManagedBean((ManagedBean)mb);
            }
        }
    
public voidloadDescriptors(java.lang.Object source)
Load the registry from the XML input found in the specified input stream.

param
source Source to be used to load. Can be an InputStream or URL.
exception
Exception if any parsing or processing error occurs

        loadDescriptors("MbeansDescriptorsDigesterSource", source, null );
    
public java.util.ListloadMBeans(java.lang.Object source, java.lang.ClassLoader cl)
Load an extended mlet file. The source can be an URL, File or InputStream. All mbeans will be instantiated, registered and the attributes will be set. The result is a list of ObjectNames.

param
source InputStream or URL of the file
param
cl ClassLoader to be used to load the mbeans, or null to use the default JMX mechanism ( i.e. all registered loaders )
return
List of ObjectName for the loaded mbeans
throws
Exception
since
1.1

        return load("MbeansSource", source, null );
    
public voidloadMetadata(java.lang.Object source)
Load descriptors. The source can be a File or URL or InputStream for the descriptors file. In the case of File and URL, if the extension is ".ser" a serialized version will be loaded. This method should be used to explicitely load metadata - but this is not required in most cases. The registerComponent() method will find metadata in the same pacakge.

param
source

        loadDescriptors( null, source, null );
    
public static voidloadRegistry(java.io.InputStream stream)
Load the registry from the XML input found in the specified input stream.

param
stream InputStream containing the registry configuration information
exception
Exception if any parsing or processing error occurs
deprecated
use normal class method instead
since
1.0

        Registry registry = getRegistry();
        registry.loadMetadata(stream);
    
public voidpostDeregister()

    
public voidpostRegister(java.lang.Boolean registrationDone)

    
public voidpreDeregister()

    
public javax.management.ObjectNamepreRegister(javax.management.MBeanServer server, javax.management.ObjectName name)

        this.server=server;
        return name;
    
public voidregisterComponent(java.lang.Object bean, javax.management.ObjectName oname, java.lang.String type)
Register a component XXX make it private

param
bean
param
oname
param
type
throws
Exception

        if( log.isDebugEnabled() ) {
            log.debug( "Managed= "+ oname);
        }

        if( bean ==null ) {
            log.error("Null component " + oname );
            return;
        }

        try {
            if( type==null ) {
                type=bean.getClass().getName();
            }

            ManagedBean managed = findManagedBean(bean.getClass(), type);

            // The real mbean is created and registered
            DynamicMBean mbean = managed.createMBean(bean);

            if(  getMBeanServer().isRegistered( oname )) {
                if( log.isDebugEnabled()) {
                    log.debug("Unregistering existing component " + oname );
                }
                getMBeanServer().unregisterMBean( oname );
            }

            getMBeanServer().registerMBean( mbean, oname);
        } catch( Exception ex) {
            log.error("Error registering " + oname, ex );
            throw ex;
        }
    
public voidregisterComponent(java.lang.Object bean, java.lang.String domain, java.lang.String type, java.lang.String name)

deprecated
- may still be used in code using pre-1.1 builds

        StringBuffer sb=new StringBuffer();
        sb.append( domain ).append(":");
        sb.append( name );
        String nameStr=sb.toString();
        ObjectName oname=new ObjectName( nameStr );
        registerComponent(bean, oname, type );
    
public voidregisterComponent(java.lang.Object bean, java.lang.String oname, java.lang.String type)
Register a bean by creating a modeler mbean and adding it to the MBeanServer. If metadata is not loaded, we'll look up and read a file named "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package or parent. If the bean is an instance of DynamicMBean. it's metadata will be converted to a model mbean and we'll wrap it - so modeler services will be supported If the metadata is still not found, introspection will be used to extract it automatically. If an mbean is already registered under this name, it'll be first unregistered. If the component implements MBeanRegistration, the methods will be called. If the method has a method "setRegistry" that takes a RegistryMBean as parameter, it'll be called with the current registry.

param
bean Object to be registered
param
oname Name used for registration
param
type The type of the mbean, as declared in mbeans-descriptors. If null, the name of the class will be used. This can be used as a hint or by subclasses.
since
1.1

        registerComponent(bean, new ObjectName(oname), type);        
    
public voidremoveManagedBean(ManagedBean bean)
Remove an existing bean from the set of beans known to this registry.

param
bean The managed bean to be removed
since
1.0

       // TODO: change this to use group/name
        descriptors.remove(bean.getName());
        descriptorsByClass.remove( bean.getType());
    
public voidresetMetadata()

        stop();
    
public voidsetMBeanServer(javax.management.MBeanServer server)
Set the MBeanServer to be utilized for our registered management beans.

param
server The new MBeanServer instance

        this.server=server;
    
public static voidsetServer(javax.management.MBeanServer mbeanServer)
Set the MBeanServer to be utilized for our registered management beans.

param
mbeanServer The new MBeanServer instance
since
1.0
deprecated
Use the instance method

        Registry.getRegistry().setMBeanServer(mbeanServer);
    
public static voidsetUseContextClassLoader(boolean enable)
Allow containers to isolate apps. Can be called only once. It is highly recommended you call this method if using Registry in a container environment. The default is false for backward compatibility

param
enable
since
1.1

        if( enable ) {
            perLoaderRegistries=new HashMap();
        }
    
private java.lang.StringsourceTypeFromExt(java.lang.String s)

        if( s.endsWith( ".ser")) {
            return "MbeansDescriptorsSerSource";
        }
        else if( s.endsWith(".xml")) {
            return "MbeansDescriptorsDigesterSource";
        }
        return null;
    
public voidstop()
Lifecycle method - clean up the registry metadata. Called from resetMetadata().

since
1.1

        descriptorsByClass = new HashMap();
        descriptors = new HashMap();
        searchedPaths=new HashMap();
    
public voidunregisterComponent(javax.management.ObjectName oname)
Unregister a component. This is just a helper that avoids exceptions by checking if the mbean is already registered

param
oname

        try {
            if( getMBeanServer().isRegistered(oname)) {
                getMBeanServer().unregisterMBean(oname);
            }
        } catch( Throwable t ) {
            log.error( "Error unregistering mbean ", t);
        }
    
public voidunregisterComponent(java.lang.String domain, java.lang.String name)

        try {
            ObjectName oname=new ObjectName( domain + ":" + name );

            // XXX remove from our tables.
            getMBeanServer().unregisterMBean( oname );
        } catch( Throwable t ) {
            log.error( "Error unregistering mbean ", t );
        }
    
public voidunregisterComponent(java.lang.String oname)
Unregister a component. We'll first check if it is registered, and mask all errors. This is mostly a helper.

param
oname
since
1.1

        try {
            unregisterComponent(new ObjectName(oname));
        } catch (MalformedObjectNameException e) {
            log.info("Error creating object name " + e );
        }
    
public voidunregisterRegistry(java.lang.ClassLoader loader)
Called by a registry or by the container to unload a loader

param
loader

        // XXX Cleanup ?
        perLoaderRegistries.remove(loader);