//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.jmx;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Map;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;

import org.eclipse.jetty.util.HostPort;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ShutdownThread;


/* ------------------------------------------------------------ */
/**
 * AbstractLifeCycle wrapper for JMXConnector Server
 */
public class ConnectorServer extends AbstractLifeCycle
{
    private static final Logger LOG = Log.getLogger(ConnectorServer.class);

    JMXConnectorServer _connectorServer;
    Registry _registry;

    /* ------------------------------------------------------------ */
    /**
     * Constructs connector server
     *
     * @param serviceURL the address of the new connector server.
     * The actual address of the new connector server, as returned
     * by its getAddress method, will not necessarily be exactly the same.
     * @param name object name string to be assigned to connector server bean
     * @throws Exception if unable to setup connector server
     */
    public ConnectorServer(JMXServiceURL serviceURL, String name)
        throws Exception
    {
        this(serviceURL, null, name);
    }

    /* ------------------------------------------------------------ */
    /**
     * Constructs connector server
     *
     * @param svcUrl the address of the new connector server.
     * The actual address of the new connector server, as returned
     * by its getAddress method, will not necessarily be exactly the same.
     * @param environment  a set of attributes to control the new connector
     * server's behavior. This parameter can be null. Keys in this map must
     * be Strings. The appropriate type of each associated value depends on
     * the attribute. The contents of environment are not changed by this call.
     * @param name object name string to be assigned to connector server bean
     * @throws Exception if unable to create connector server
     */
    public ConnectorServer(JMXServiceURL svcUrl, Map<String,?> environment, String name)
         throws Exception
    {
        String urlPath = svcUrl.getURLPath();
        int idx = urlPath.indexOf("rmi://");
        if (idx > 0)
        {
            String hostPort = urlPath.substring(idx+6, urlPath.indexOf('/', idx+6));
            String regHostPort = startRegistry(hostPort);
            if (regHostPort != null) {
                urlPath = urlPath.replace(hostPort,regHostPort);
                svcUrl = new JMXServiceURL(svcUrl.getProtocol(), svcUrl.getHost(), svcUrl.getPort(), urlPath);
            }
        }
        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
        _connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(svcUrl, environment, mbeanServer);
        mbeanServer.registerMBean(_connectorServer,new ObjectName(name));
    }

        /* ------------------------------------------------------------ */
    /**
     * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
     */
    @Override
    public void doStart()
        throws Exception
    {
        _connectorServer.start();
        ShutdownThread.register(0, this);

        LOG.info("JMX Remote URL: {}", _connectorServer.getAddress().toString());
    }

    /* ------------------------------------------------------------ */
    /**
     * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
     */
    @Override
    public void doStop()
        throws Exception
    {
        ShutdownThread.deregister(this);
        _connectorServer.stop();
        stopRegistry();
    }

    /**
     * Check that local RMI registry is used, and ensure it is started. If local RMI registry is being used and not started, start it.
     *
     * @param hostPath
     *            hostname and port number of RMI registry
     * @throws Exception
     */
    private String startRegistry(String hostPath) throws Exception
    {
        HostPort hostPort = new HostPort(hostPath);

        String rmiHost = hostPort.getHost();
        int rmiPort = hostPort.getPort(1099);

        // Verify that local registry is being used
        InetAddress hostAddress = InetAddress.getByName(rmiHost);
        if(hostAddress.isLoopbackAddress())
        {
            if (rmiPort == 0)
            {
                ServerSocket socket = new ServerSocket(0);
                rmiPort = socket.getLocalPort();
                socket.close();
            }
            else
            {
                try
                {
                    // Check if a local registry is already running
                    LocateRegistry.getRegistry(rmiPort).list();
                    return null;
                }
                catch (Exception ex)
                {
                    LOG.ignore(ex);
                }
            }

            _registry = LocateRegistry.createRegistry(rmiPort);
            Thread.sleep(1000);

            rmiHost = HostPort.normalizeHost(InetAddress.getLocalHost().getCanonicalHostName());
            return rmiHost + ':' + Integer.toString(rmiPort);
        }

        return null;
    }

    private void stopRegistry()
    {
        if (_registry != null)
        {
            try
            {
                UnicastRemoteObject.unexportObject(_registry,true);
            }
            catch (Exception ex)
            {
                LOG.ignore(ex);
            }
        }
    }
}
