package org.apache.activemq.tests;

import com.sun.tools.attach.*;

import java.util.List;
import java.io.File;

import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.activemq.broker.jmx.BrokerViewMBean;

public class JMXDiscoveryAgent {

    static final String CONNECTOR_ADDRESS =
         "com.sun.management.jmxremote.localConnectorAddress";
    protected String domain = "org.apache.activemq";

    static public void findAndPrintAllVms() {
        for (VirtualMachineDescriptor desc : VirtualMachine.list()) {
            System.out.println(desc);
        }
    }

    public JMXConnector findActiveMQ() {

        List<VirtualMachineDescriptor> allVMs = VirtualMachine.list();

        for (VirtualMachineDescriptor descriptor : allVMs) {
            if (descriptor.displayName().contains("apache-activemq")) {
                String id = descriptor.id();

                try {
                    return connectToVM(id);
                } catch(Exception ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }

        return null;
    }

    public void describeBroker(JMXConnector activemq) throws Exception {
        MBeanServerConnection connection = activemq.getMBeanServerConnection();
        BrokerViewMBean broker = null;
        ObjectName brokerName = new ObjectName(domain + ":Type=Broker,BrokerName=localhost");

        if (!connection.isRegistered(brokerName)) {
            System.out.println("Couldn't find the Broker MBean for some reason.");
            return;
        }

        broker = (BrokerViewMBean)MBeanServerInvocationHandler.newProxyInstance(connection, brokerName, BrokerViewMBean.class, true);
        if (broker == null) {
            throw new NullPointerException("Broker Proxy failed to create.");
        }

        System.out.println("----------------------------------------------------------------");
        System.out.println("Broker Name:     " + broker.getBrokerName());
        System.out.println("Broker Version:  " + broker.getBrokerVersion());
        System.out.println("Broker Version:  " + broker.getBrokerId());
        System.out.println("----------------------------------------------------------------");
    }

    private JMXConnector connectToVM(String id) throws Exception {

        // attach to the target application
        VirtualMachine vm = VirtualMachine.attach(id);

        // get the connector address
        String connectorAddress =
            vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);

        // no connector address, so we start the JMX agent
        if (connectorAddress == null) {
           String agent = vm.getSystemProperties().getProperty("java.home") +
               File.separator + "lib" + File.separator + "management-agent.jar";
           vm.loadAgent(agent);

           // agent is started, get the connector address
           connectorAddress =
               vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
        }

        // establish connection to connector server
        JMXServiceURL url = new JMXServiceURL(connectorAddress);
        return JMXConnectorFactory.connect(url);
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        JMXDiscoveryAgent discoverer = new JMXDiscoveryAgent();

        JMXConnector activemq = discoverer.findActiveMQ();
        if (activemq != null) {
            discoverer.describeBroker(activemq);
        } else {
            System.out.println("Did not find any ActiveMQ instances on this machine.");
        }
    }

}
