org.ngrinder.monitor.share.domain.MBeanClient.java Source code

Java tutorial

Introduction

Here is the source code for org.ngrinder.monitor.share.domain.MBeanClient.java

Source

/* 
 * Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */
package org.ngrinder.monitor.share.domain;

import org.apache.commons.io.IOUtils;
import org.ngrinder.common.exception.NGrinderRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.concurrent.*;

import static org.ngrinder.common.util.ExceptionUtils.processException;

/**
 * Client for the JMX monitor server.
 *
 * @author Mavlarn
 * @since 2.0
 */
public class MBeanClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(MBeanClient.class);

    private static final String JMX_URI = "/jndi/rmi://%s:%s/jmxrmi";

    private JMXServiceURL jmxUrl = null;

    private volatile boolean connected = false;

    private MBeanServerConnection mbeanServerConnection = null;
    private JMXConnector jmxConnector = null;

    private int timeout = 2000;

    /**
     * Used to connect remote monitor JMX.
     *
     * @param hostName is the server name of target server
     * @param port     is the JMX server's listener port of target monitor server
     * @param timeout  the connection timeout og mbean client.
     * @throws IOException wraps JMX MalformedURLException exception
     */
    public MBeanClient(String hostName, int port, int timeout) throws IOException {
        this(hostName, port);
        this.timeout = timeout;
    }

    /**
     * Used to connect remote monitor JMX.
     *
     * @param hostName is the server name of target server
     * @param port     is the JMX server's listener port of target monitor server
     * @throws IOException wraps JMX MalformedURLException exception
     */
    public MBeanClient(String hostName, int port) throws IOException {
        this.jmxUrl = new JMXServiceURL("rmi", hostName, port, String.format(JMX_URI, hostName, port));
    }

    /**
     * connect with target JMX.
     */
    public void connect() {
        try {
            connectClient();
        } catch (Exception e) {
            LOGGER.info("Timeout while connecting to {}:{} monitor : {}", jmxUrl.getHost(), jmxUrl.getPort());
        }
    }

    @SuppressWarnings("UnusedDeclaration")
    public MBeanServerConnection getMBeanServerConnection() {
        return this.mbeanServerConnection;
    }

    /**
     * disconnect the MBeanClient. If it is remote JMX server, disconnect the connection. If it is
     * local, disconnect the binding.
     */
    public void disconnect() {
        connected = false;
        IOUtils.closeQuietly(jmxConnector);
        mbeanServerConnection = null;
    }

    /**
     * get the monitor object of the object name and attribute name. See
     * {@link org.ngrinder.monitor.domain.MonitorCollectionInfoDomain}.
     *
     * @param objName  is the object name of the object in JMX MBean server.
     * @param attrName is the attribute name
     * @return the monitor object from MBean
     * @throws Exception wraps all JMX related exception
     */
    public Object getAttribute(ObjectName objName, String attrName) throws Exception {
        return mbeanServerConnection.getAttribute(objName, attrName);
    }

    private void connectClient() throws IOException, TimeoutException {
        if (jmxUrl == null || ("localhost".equals(jmxUrl.getHost()) && jmxUrl.getPort() == 0)) {
            mbeanServerConnection = ManagementFactory.getPlatformMBeanServer();
        } else {
            jmxConnector = connectWithTimeout(jmxUrl, timeout);
            mbeanServerConnection = jmxConnector.getMBeanServerConnection();
        }
        this.connected = true;
    }

    private JMXConnector connectWithTimeout(final JMXServiceURL jmxUrl, int timeout)
            throws NGrinderRuntimeException, TimeoutException {
        try {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            Future<JMXConnector> future = executor.submit(new Callable<JMXConnector>() {
                public JMXConnector call() throws IOException {
                    return JMXConnectorFactory.connect(jmxUrl);
                }
            });

            return future.get(timeout, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            throw e;
        } catch (Exception e) {
            throw processException(e);
        }

    }

    public boolean isConnected() {
        return connected;
    }
}