/*
 * MBeanComponentManager.java
 *
 * Created on July 15, 2001, 12:52 PM
 */

package org.apache.avalon.excalibur.component.jmx;


import javax.management.*;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import java.lang.reflect.Proxy;

/**
 *
 * @author  
 * @version
 */
public class MBeanComponentManager implements ComponentManager {
    
    private ComponentManager parentManager;
    private MBeanServer server;
    private String domain;
    
    /** Creates new MBeanComponentManager */
    public MBeanComponentManager(ComponentManager manager, 
        MBeanServer server) {            
        this(manager, server, server.getDefaultDomain());
    }
    
    /** Creates new MBeanComponentManager */
    public MBeanComponentManager(ComponentManager manager, MBeanServer server, 
        String domain) {
            
        this.parentManager = manager;    
        this.server = server;
        this.domain = domain;
    }
    
    public void release(Component component) {
    }
    
    public Component lookup(String role) throws ComponentException {
        try {
            ObjectName objectName = this.getObjectName(role);            
            
            if (this.server.isRegistered(objectName)) {
                
                //the interface name of the registered MBean... relies on JMX 
                //specs for interfaces
                String className = this.server.getMBeanInfo(objectName)
                    .getClassName()+"MBean";
                Class clazz = Class.forName(className);

                MBeanInvocationHandler handler = 
                    new MBeanInvocationHandler(this.server, objectName);            
                ClassLoader loader = 
                    Thread.currentThread().getContextClassLoader();

                //returns the proxy to the registered MBean
                return (Component) Proxy
                    .newProxyInstance(loader, new Class[] { clazz }, handler);                                    
            } 
            
            if (this.parentManager != null) {
                return this.parentManager.lookup(role);
            }
            
        //crappy exception handling for now
        } catch (Exception e) {
            throw new ComponentException(e.getMessage(), e);
        }
        
        return null;
    }
    
    public void addComponent(final String role,
        final Class component) throws ComponentException {
        
        try {
            ObjectName objectName = this.getObjectName(role);

            //registers the component with the MBeanServer
            this.server.createMBean(component.getName(), objectName);
            
        //crappy exception handling for now
        } catch (Exception e) {
            throw new ComponentException(e.getMessage(), e);
        }
    }
    
    /**
     * Creates an MBean object name like 'domain:role= ...'
     */
    private ObjectName getObjectName(String role) 
        throws MalformedObjectNameException {
            
        return new ObjectName(this.domain, "role", role);
    }        
}

