/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.hadoop.hdfs.tools;

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;

import javax.management.AttributeNotFoundException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import org.apache.hadoop.classification.InterfaceAudience;

/**
 * tool to get data from NameNode or DataNode using MBeans currently the
 * following MBeans are available (under hadoop domain):
 * hadoop:service=NameNode,name=FSNamesystemState (static)
 * hadoop:service=NameNode,name=NameNodeActivity (dynamic)
 * hadoop:service=NameNode,name=RpcActivityForPort9000 (dynamic)
 * hadoop:service=DataNode,name=RpcActivityForPort50020 (dynamic)
 * hadoop:name=service=DataNode,FSDatasetState-UndefinedStorageId663800459
 * (static)
 * hadoop:service=DataNode,name=DataNodeActivity-UndefinedStorageId-520845215
 * (dynamic)
 * 
 * 
 * implementation note: all logging is sent to System.err (since it is a command
 * line tool)
 */
@InterfaceAudience.Private
public class JMXGet {

  private static final String format = "%s=%s\n";
  private ArrayList<ObjectName> hadoopObjectNames;
  private MBeanServerConnection mbsc;
  private String service = "NameNode", port = "", server = "localhost";
  private String localVMUrl = null;

  public JMXGet() {
  }

  public void setService(String service) {
    this.service = service;
  }

  public void setPort(String port) {
    this.port = port;
  }

  public void setServer(String server) {
    this.server = server;
  }

  public void setLocalVMUrl(String url) {
    this.localVMUrl = url;
  }

  /**
   * print all attributes' values
   */
  public void printAllValues() throws Exception {
    err("List of all the available keys:");

    Object val = null;

    for (ObjectName oname : hadoopObjectNames) {
      err(">>>>>>>>jmx name: " + oname.getCanonicalKeyPropertyListString());
      MBeanInfo mbinfo = mbsc.getMBeanInfo(oname);
      MBeanAttributeInfo[] mbinfos = mbinfo.getAttributes();

      for (MBeanAttributeInfo mb : mbinfos) {
        val = mbsc.getAttribute(oname, mb.getName());
        System.out.format(format, mb.getName(), (val==null)?"":val.toString());
      }
    }
  }

  /**
   * get single value by key
   */
  public String getValue(String key) throws Exception {

    Object val = null;

    for (ObjectName oname : hadoopObjectNames) {
      try {
        val = mbsc.getAttribute(oname, key);
      } catch (AttributeNotFoundException anfe) {
        /* just go to the next */
        continue;
      } catch (ReflectionException re) {
        if (re.getCause() instanceof NoSuchMethodException) {
          continue;
        }
      }
      err("Info: key = " + key + "; val = "+ val.getClass() +":"+ val);
      break;
    }

    return (val == null) ? "" : val.toString();
  }

  /**
   * @throws Exception
   *           initializes MBeanServer
   */
  public void init() throws Exception {

    err("init: server=" + server + ";port=" + port + ";service=" + service
        + ";localVMUrl=" + localVMUrl);

    String url_string = null;
    // build connection url
    if (localVMUrl != null) {
      // use
      // jstat -snap <vmpid> | grep sun.management.JMXConnectorServer.address
      // to get url
      url_string = localVMUrl;
      err("url string for local pid = " + localVMUrl + " = " + url_string);

    } else if (!port.isEmpty() && !server.isEmpty()) {
      // using server and port
      url_string = "service:jmx:rmi:///jndi/rmi://" + server + ":" + port
      + "/jmxrmi";
    } // else url stays null

    // Create an RMI connector client and
    // connect it to the RMI connector server

    if (url_string == null) { // assume local vm (for example for Testing)
      mbsc = ManagementFactory.getPlatformMBeanServer();
    } else {
      JMXServiceURL url = new JMXServiceURL(url_string);

      err("Create RMI connector and connect to the RMI connector server" + url);

      JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
      // Get an MBeanServerConnection
      //
      err("\nGet an MBeanServerConnection");
      mbsc = jmxc.getMBeanServerConnection();
    }

    // Get domains from MBeanServer
    //
    err("\nDomains:");

    String domains[] = mbsc.getDomains();
    Arrays.sort(domains);
    for (String domain : domains) {
      err("\tDomain = " + domain);
    }

    // Get MBeanServer's default domain
    //
    err("\nMBeanServer default domain = " + mbsc.getDefaultDomain());

    // Get MBean count
    //
    err("\nMBean count = " + mbsc.getMBeanCount());

    // Query MBean names for specific domain "hadoop" and service
    ObjectName query = new ObjectName("Hadoop:service=" + service + ",*");
    hadoopObjectNames = new ArrayList<ObjectName>(5);
    err("\nQuery MBeanServer MBeans:");
    Set<ObjectName> names = new TreeSet<ObjectName>(mbsc
        .queryNames(query, null));

    for (ObjectName name : names) {
      hadoopObjectNames.add(name);
      err("Hadoop service: " + name);
    }

  }

  /**
   * Print JMXGet usage information
   */
  static void printUsage(Options opts) {
    HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp("jmxget options are: ", opts);
  }

  /**
   * @param msg
   */
  private static void err(String msg) {
    System.err.println(msg);
  }

  /**
   * parse args
   */
  private static CommandLine parseArgs(Options opts, String... args)
  throws IllegalArgumentException {

    OptionBuilder.withArgName("NameNode|DataNode");
    OptionBuilder.hasArg();
    OptionBuilder.withDescription("specify jmx service (NameNode by default)");
    Option jmx_service = OptionBuilder.create("service");

    OptionBuilder.withArgName("mbean server");
    OptionBuilder.hasArg();
    OptionBuilder
    .withDescription("specify mbean server (localhost by default)");
    Option jmx_server = OptionBuilder.create("server");

    OptionBuilder.withDescription("print help");
    Option jmx_help = OptionBuilder.create("help");

    OptionBuilder.withArgName("mbean server port");
    OptionBuilder.hasArg();
    OptionBuilder.withDescription("specify mbean server port, "
        + "if missing - it will try to connect to MBean Server in the same VM");
    Option jmx_port = OptionBuilder.create("port");

    OptionBuilder.withArgName("VM's connector url");
    OptionBuilder.hasArg();
    OptionBuilder.withDescription("connect to the VM on the same machine;"
        + "\n use:\n jstat -J-Djstat.showUnsupported=true -snap <vmpid> | "
        + "grep sun.management.JMXConnectorServer.address\n "
        + "to find the url");
    Option jmx_localVM = OptionBuilder.create("localVM");

    opts.addOption(jmx_server);
    opts.addOption(jmx_help);
    opts.addOption(jmx_service);
    opts.addOption(jmx_port);
    opts.addOption(jmx_localVM);

    CommandLine commandLine = null;
    CommandLineParser parser = new GnuParser();
    try {
      commandLine = parser.parse(opts, args, true);
    } catch (ParseException e) {
      printUsage(opts);
      throw new IllegalArgumentException("invalid args: " + e.getMessage());
    }
    return commandLine;
  }

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

    int res = -1;

    // parse arguments
    Options opts = new Options();
    CommandLine commandLine = null;
    try {
      commandLine = parseArgs(opts, args);
    } catch (IllegalArgumentException iae) {
      commandLine = null;
    }

    if (commandLine == null) {
      // invalid arguments
      err("Invalid args");
      printUsage(opts);
      System.exit(-1);
    }

    JMXGet jm = new JMXGet();

    if (commandLine.hasOption("port")) {
      jm.setPort(commandLine.getOptionValue("port"));
    }
    if (commandLine.hasOption("service")) {
      jm.setService(commandLine.getOptionValue("service"));
    }
    if (commandLine.hasOption("server")) {
      jm.setServer(commandLine.getOptionValue("server"));
    }

    if (commandLine.hasOption("localVM")) {
      // from the file /tmp/hsperfdata*
      jm.setLocalVMUrl(commandLine.getOptionValue("localVM"));
    }

    if (commandLine.hasOption("help")) {
      printUsage(opts);
      System.exit(0);
    }

    // rest of args
    args = commandLine.getArgs();

    try {
      jm.init();

      if (args.length == 0) {
        jm.printAllValues();
      } else {
        for (String key : args) {
          err("key = " + key);
          String val = jm.getValue(key);
          if (val != null)
            System.out.format(JMXGet.format, key, val);
        }
      }
      res = 0;
    } catch (Exception re) {
      re.printStackTrace();
      res = -1;
    }

    System.exit(res);
  }
}
