flens.query.JMXQuery.java Source code

Java tutorial

Introduction

Here is the source code for flens.query.JMXQuery.java

Source

/**
 *
 *     Copyright 2013 KU Leuven Research and Development - iMinds - Distrinet
 *
 *     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.
 *
 *     Administrative Contact: dnet-project-office@cs.kuleuven.be
 *     Technical Contact: wouter.deborger@cs.kuleuven.be
 */
package flens.query;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimerTask;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import com.google.gson.Gson;
import com.sun.tools.classfile.Dependency.Finder;

import flens.core.Constants;
import flens.core.Query;
import flens.core.QueryHandler;
import flens.core.Record;
import flens.core.Tagger;
import flens.core.util.AbstractPlugin;
import flens.input.jmx.JMXUtils;
import flens.input.jmx.JVM;
import flens.input.jmx.VMSelectionException;
import flens.input.util.AbstractPeriodicInput;

public class JMXQuery extends AbstractPlugin implements QueryHandler {

    private MBeanServerConnection connection;
    private JMXConnector con;

    private String host;
    private int port;

    private boolean running = true;

    private synchronized void connect() throws IOException {
        if (!running)
            throw new IllegalStateException("connecting while shutting down");
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi");
        con = JMXConnectorFactory.connect(url, null);
        connection = con.getMBeanServerConnection();
    }

    private String name;

    public JMXQuery(String name, String host, int port) {
        this.host = host;
        this.port = port;
        this.name = name;
    }

    @Override
    public synchronized void stop() {
        running = false;
        try {
            if (con != null) {

                con.close();

                con = null;
                connection = null;
            }
        } catch (IOException e) {
            err("could not close", e);
        }
    }

    @Override
    public synchronized void start() {
        // lazy is fine!
        running = true;
    }

    @Override
    public boolean canHandle(Query q) {
        if (!q.getQuery().startsWith("jmx:"))
            return false;
        if (q.getQuery().startsWith("jmx:*://"))
            return true;
        if (q.getQuery().startsWith("jmx:" + getName() + "://"))
            return true;
        return false;
    }

    @Override
    // fixme: make non-sync, but handle connect well
    public synchronized void handle(Query q) {
        try {
            if (con == null)
                connect();
            String url = q.getQuery();
            String[] parts = url.split("/");
            String method = parts[2];
            String[] rest = ArrayUtils.subarray(parts, 3, Integer.MAX_VALUE);

            switch (method) {
            case "list-names":
                list(q);
                break;
            case "list":
                listLong(q);
                break;
            case "details":
                details(q, rest);
                break;
            case "call":
                call(q, rest);
                break;
            case "get":
                get(q, rest);
                break;
            }

        } catch (Exception e) {
            q.fail(500, e.getMessage());
        }

    }

    @SuppressWarnings("unchecked")
    private void call(Query q, String[] rest) throws MalformedObjectNameException, NullPointerException,
            IOException, InstanceNotFoundException, MBeanException, ReflectionException {
        String name = rest[0];
        String oppname = rest[1];

        Set<ObjectName> names = new TreeSet<ObjectName>(connection.queryNames(ObjectName.getInstance(name), null));

        Map<String, Object> out = new HashMap<>();

        for (ObjectName objectName : names) {
            List<Object> o = (List<Object>) q.getPayload().get("params");
            List<String> sig = (List<String>) q.getPayload().get("sig");
            out.put(objectName.getCanonicalName(),
                    connection.invoke(objectName, oppname, o.toArray(), sig.toArray(new String[sig.size()])));
        }

        q.respond(out);

    }

    private void listLong(Query q) throws IOException {
        Set<ObjectName> names = new TreeSet<ObjectName>(connection.queryNames(null, null));
        List<String> out = new LinkedList<>();
        for (ObjectName objectName : names) {
            out.add(objectName.getCanonicalName());
        }
        q.respond(out);
    }

    private void details(Query q, String[] rest) throws MalformedObjectNameException, NullPointerException,
            IOException, InstanceNotFoundException, IntrospectionException, ReflectionException {
        String name = rest[0];

        Set<ObjectName> names = new TreeSet<ObjectName>(connection.queryNames(ObjectName.getInstance(name), null));

        Map<String, Object> out = new HashMap<>();

        for (ObjectName objectName : names) {
            out.put(objectName.getCanonicalName(), getDetails(objectName));
        }

        q.respond(out);

    }

    private void get(Query q, String[] rest)
            throws MalformedObjectNameException, NullPointerException, IOException, InstanceNotFoundException,
            IntrospectionException, ReflectionException, AttributeNotFoundException, MBeanException {
        String name = rest[0];
        String att = rest[1];

        Set<ObjectName> names = new TreeSet<ObjectName>(connection.queryNames(ObjectName.getInstance(name), null));

        Map<String, Object> out = new HashMap<>();

        for (ObjectName objectName : names) {
            out.put(objectName.getCanonicalName(), connection.getAttribute(objectName, att));
        }

        q.respond(out);

    }

    private Map<String, Object> getDetails(ObjectName objectName)
            throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException {
        Map<String, Object> out = new HashMap<>();
        MBeanInfo info = connection.getMBeanInfo(objectName);
        out.put("description", info.getDescription());
        out.put("attributes", getAttributes(info));
        out.put("operations", getOpperations(info));
        out.put("notifications", getNotifications(info));
        return out;

    }

    private Map<String, Object> getNotifications(MBeanInfo info) {
        Map<String, Object> outc = new HashMap<>();
        MBeanNotificationInfo[] atts = info.getNotifications();
        for (MBeanNotificationInfo att : atts) {
            Map<String, Object> out = new HashMap<>();
            outc.put(att.getName(), out);
            out.put("description", att.getDescription());
            out.put("type", att.getNotifTypes());
        }
        return outc;
    }

    private Map<String, Object> getAttributes(MBeanInfo info) {
        Map<String, Object> outc = new HashMap<>();
        MBeanAttributeInfo[] atts = info.getAttributes();
        for (MBeanAttributeInfo att : atts) {
            Map<String, Object> out = new HashMap<>();
            outc.put(att.getName(), out);
            out.put("description", att.getDescription());
            out.put("type", att.getType());
        }
        return outc;
    }

    private Map<String, Object> getOpperations(MBeanInfo info) {
        Map<String, Object> outc = new HashMap<>();
        MBeanOperationInfo[] atts = info.getOperations();
        for (MBeanOperationInfo att : atts) {
            Map<String, Object> out = new HashMap<>();
            outc.put(att.getName(), out);
            out.put("description", att.getDescription());
            out.put("return-type", att.getReturnType());
            out.put("signature", getSig(att.getSignature()));

        }
        return outc;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private List getSig(MBeanParameterInfo[] signature) {
        List outc = new LinkedList<>();

        for (MBeanParameterInfo att : signature) {
            Map<String, Object> out = new HashMap<>();
            outc.add(out);
            out.put("name", att.getName());
            out.put("description", att.getDescription());
            out.put("type", att.getType());
        }
        return outc;
    }

    private void list(Query q) throws IOException {
        q.respond(StringUtils.join(connection.getDomains(), ","));
    }

    @Override
    public void join() {

    }

    @Override
    public String getName() {
        return name;
    }

}