package net.hyperic.hq.product.mx4j;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Set;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import net.hyperic.hq.product.Metric;
import net.hyperic.hq.product.MetricInvalidException;
import net.hyperic.hq.product.MetricNotFoundException;
import net.hyperic.hq.product.MetricUnreachableException;
import net.hyperic.hq.product.PluginException;

public class MX4JUtil {

    public static final String PROP_JMXURL = "jmxUrl";

    static Object getValue(Metric metric)
        throws MetricNotFoundException,
               MetricInvalidException,
               MetricUnreachableException,
               PluginException
    {
        String jmxUrl = metric.getProperties().getProperty(PROP_JMXURL);
        String objectName = metric.getObjectName();
        String attribute = metric.getAttributeName();

        try {
            return getValue(jmxUrl, objectName, attribute);
        } catch (MalformedURLException e) {
            throw new PluginException("Malformed URL: " + jmxUrl, e);
        } catch (MalformedObjectNameException e) {
            throw new PluginException("Malformed ObjectName: " +
                                      objectName, e);
        } catch (IOException e) {
            throw new MetricUnreachableException("Unable to connect to " +
                                                 "MBeanServer", e);
        } catch (MBeanException e) {
            throw new MetricUnreachableException("MBeanException", e);
        } catch (AttributeNotFoundException e) {
            throw new MetricInvalidException("Invalid attribute: " + 
                                             attribute, e);
        } catch (InstanceNotFoundException e) {
            throw new MetricInvalidException("Instance not found", e);
        } catch (ReflectionException e) {
            throw new MetricInvalidException("Reflection error", e);
        }
    }

    static Object getValue(String jmxUrl, String objectName,
                           String attribute)
        throws MalformedURLException,
               MalformedObjectNameException,
               IOException,
               MBeanException,
               AttributeNotFoundException,
               InstanceNotFoundException,
               ReflectionException
    {
        JMXServiceURL url = new JMXServiceURL(jmxUrl);
        JMXConnector connector = JMXConnectorFactory.connect(url);
        MBeanServerConnection conn = connector.getMBeanServerConnection();
        
        ObjectName objName = new ObjectName(objectName);
        return conn.getAttribute(objName, attribute);
    }

    static Set queryNames(String jmxUrl, String objectName)
        throws PluginException {
        
        try {
            JMXServiceURL url = new JMXServiceURL(jmxUrl);
            JMXConnector connector = JMXConnectorFactory.connect(url);
            MBeanServerConnection conn = connector.getMBeanServerConnection();
            ObjectName object = new ObjectName(objectName);

            return conn.queryNames(object, null);
        } catch (MalformedObjectNameException e) {
            throw new PluginException("Malformed ObjectName: " +
                                      objectName, e);
        } catch (IOException e) {
            throw new PluginException("Unable to connect to " +
                                      "MBeanServer", e);
        }
    }

    static void invoke(String jmxUrl, String objectName,
                       String method)
        throws PluginException {
        
        try {
            JMXServiceURL url = new JMXServiceURL(jmxUrl);
            JMXConnector connector = JMXConnectorFactory.connect(url);
            MBeanServerConnection conn = connector.getMBeanServerConnection();
            ObjectName object = new ObjectName(objectName);

            conn.invoke(object, method, null, null);
        } catch (MalformedObjectNameException e) {
            throw new PluginException("Malformed ObjectName: " +
                                      objectName, e);
        } catch (IOException e) {
            throw new PluginException("Unable to connect to " +
                                      "MBeanServer", e);
        } catch (InstanceNotFoundException e) {
            throw new PluginException("Instance not found", e);
        } catch (MBeanException e) {
            throw new PluginException("MBeanException", e);
        } catch (ReflectionException e) {
            throw new MetricInvalidException("Reflection error", e);
        }

    }
}

