/*
 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


/*
 *
 * Example of using the java.lang.management API to sort threads
 * by CPU usage.
 *
 * JTop class can be run as a standalone application.
 * It first establishs a connection to a target VM specified
 * by the given hostname and port number where the JMX agent
 * to be connected.  It then polls for the thread information
 * and the CPU consumption of each thread to display every 2
 * seconds.
 *
 * It is also used by JTopPlugin which is a JConsolePlugin
 * that can be used with JConsole (see README.txt). The JTop
 * GUI will be added as a JConsole tab by the JTop plugin.
 *
 * @see com.sun.tools.jconsole.JConsolePlugin
 *
 * @author Mandy Chung
 */
import java.lang.management.*;
import javax.management.*;
import javax.management.remote.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import java.util.concurrent.ExecutionException;
import java.text.NumberFormat;
import java.net.MalformedURLException;
import static java.lang.management.ManagementFactory.*;

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;

/**
 * JTop is a JPanel to display thread's name, CPU time, and its state
 * in a table.
 */
public class JTop extends JPanel {

    private static class StatusBar extends JPanel {
        private static final long serialVersionUID = -6483392381797633018L;
        private final JLabel statusText;

        public StatusBar(boolean defaultVisible) {
            super(new GridLayout(1, 1));
            statusText = new JLabel();
            statusText.setVisible(defaultVisible);
            add(statusText);
        }

        @Override
        public Dimension getMaximumSize() {
            Dimension maximum = super.getMaximumSize();
            Dimension minimum = getMinimumSize();
            return new Dimension(maximum.width, minimum.height);
        }

        public void setMessage(String text) {
            statusText.setText(text);
            statusText.setVisible(true);
        }
    }
    private static final long serialVersionUID = -1499762160973870696L;
    private MBeanServerConnection server;
    private ThreadMXBean tmbean;
    private MyTableModel tmodel;
    private final StatusBar statusBar;
    public JTop() {
        super(new GridBagLayout());

        tmodel = new MyTableModel();
        JTable table = new JTable(tmodel);
        table.setPreferredScrollableViewportSize(new Dimension(500, 300));

        // Set the renderer to format Double
        table.setDefaultRenderer(Double.class, new DoubleRenderer());
        // Add some space
        table.setIntercellSpacing(new Dimension(6,3));
        table.setRowHeight(table.getRowHeight() + 4);

        // Create the scroll pane and add the table to it.
        JScrollPane scrollPane = new JScrollPane(table);

        // Add the scroll pane to this panel.
        GridBagConstraints c1 = new GridBagConstraints();
        c1.fill = GridBagConstraints.BOTH;
        c1.gridy = 0;
        c1.gridx = 0;
        c1.weightx = 1;
        c1.weighty = 1;
        add(scrollPane, c1);

        statusBar = new StatusBar(false);
        GridBagConstraints c2 = new GridBagConstraints();
        c2.fill = GridBagConstraints.HORIZONTAL;
        c2.gridy = 1;
        c2.gridx = 0;
        c2.weightx = 1.0;
        c2.weighty = 0.0;
        add(statusBar, c2);
    }

    // Set the MBeanServerConnection object for communicating
    // with the target VM
    public void setMBeanServerConnection(MBeanServerConnection mbs) {
        this.server = mbs;
        try {
            this.tmbean = newPlatformMXBeanProxy(server,
                                                 THREAD_MXBEAN_NAME,
                                                 ThreadMXBean.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!tmbean.isThreadCpuTimeSupported()) {
            statusBar.setMessage("Monitored VM does not support thread CPU time measurement");
        } else {
            try {
                tmbean.setThreadCpuTimeEnabled(true);
            } catch (SecurityException e) {
                statusBar.setMessage("Monitored VM does not have permission for enabling thread cpu time measurement");
            }
        }
    }

    class MyTableModel extends AbstractTableModel {
        private static final long serialVersionUID = -7877310288576779514L;
        private String[] columnNames = {"ThreadName",
                                        "CPU(sec)",
                                        "State"};
        // List of all threads. The key of each entry is the CPU time
        // and its value is the ThreadInfo object with no stack trace.
        private List<Map.Entry<Long, ThreadInfo>> threadList =
            Collections.emptyList();

        public MyTableModel() {
        }

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public int getRowCount() {
            return threadList.size();
        }

        @Override
        public String getColumnName(int col) {
            return columnNames[col];
        }

        @Override
        public Object getValueAt(int row, int col) {
            Map.Entry<Long, ThreadInfo> me = threadList.get(row);
            switch (col) {
                case 0 :
                    // Column 0 shows the thread name
                    return me.getValue().getThreadName();
                case 1 :
                    // Column 1 shows the CPU usage
                    long ns = me.getKey().longValue();
                    double sec = ns / 1000000000;
                    return new Double(sec);
                case 2 :
                    // Column 2 shows the thread state
                    return me.getValue().getThreadState();
                default:
                    return null;
            }
        }

        @Override
        public Class<?> getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        void setThreadList(List<Map.Entry<Long, ThreadInfo>> list) {
            threadList = list;
        }
    }

    /**
     * Get the thread list with CPU consumption and the ThreadInfo
     * for each thread sorted by the CPU time.
     */
    private List<Map.Entry<Long, ThreadInfo>> getThreadList() {
        // Get all threads and their ThreadInfo objects
        // with no stack trace
        long[] tids = tmbean.getAllThreadIds();
        ThreadInfo[] tinfos = tmbean.getThreadInfo(tids);

        // build a map with key = CPU time and value = ThreadInfo
        SortedMap<Long, ThreadInfo> map = new TreeMap<Long, ThreadInfo>();
        for (int i = 0; i < tids.length; i++) {
            long cpuTime = tmbean.getThreadCpuTime(tids[i]);
            // filter out threads that have been terminated
            if (cpuTime != -1 && tinfos[i] != null) {
                map.put(new Long(cpuTime), tinfos[i]);
            }
        }

        // build the thread list and sort it with CPU time
        // in decreasing order
        Set<Map.Entry<Long, ThreadInfo>> set = map.entrySet();
        List<Map.Entry<Long, ThreadInfo>> list =
            new ArrayList<Map.Entry<Long, ThreadInfo>>(set);
        Collections.reverse(list);
        return list;
    }


    /**
     * Format Double with 4 fraction digits
     */
    class DoubleRenderer extends DefaultTableCellRenderer {
        private static final long serialVersionUID = 1704639497162584382L;
        NumberFormat formatter;
        public DoubleRenderer() {
            super();
            setHorizontalAlignment(JLabel.RIGHT);
        }

        @Override
        public void setValue(Object value) {
            if (formatter==null) {
                formatter = NumberFormat.getInstance();
                formatter.setMinimumFractionDigits(4);
            }
            setText((value == null) ? "" : formatter.format(value));
        }
    }

    // SwingWorker responsible for updating the GUI
    //
    // It first gets the thread and CPU usage information as a
    // background task done by a worker thread so that
    // it will not block the event dispatcher thread.
    //
    // When the worker thread finishes, the event dispatcher
    // thread will invoke the done() method which will update
    // the UI.
    class Worker extends SwingWorker<List<Map.Entry<Long, ThreadInfo>>,Object> {
        private MyTableModel tmodel;
        Worker(MyTableModel tmodel) {
            this.tmodel = tmodel;
        }

        // Get the current thread info and CPU time
        @Override
        public List<Map.Entry<Long, ThreadInfo>> doInBackground() {
            return getThreadList();
        }

        // fire table data changed to trigger GUI update
        // when doInBackground() is finished
        @Override
        protected void done() {
            try {
                // Set table model with the new thread list
                tmodel.setThreadList(get());
                // refresh the table model
                tmodel.fireTableDataChanged();
            } catch (InterruptedException e) {
            } catch (ExecutionException e) {
            }
        }
    }

    // Return a new SwingWorker for UI update
    public SwingWorker<?,?> newSwingWorker() {
        return new Worker(tmodel);
    }

    public static void main(String[] args) throws Exception {
        // Validate the input arguments
        if (args.length != 1) {
            usage();
        }

        String[] arg2 = args[0].split(":");
        if (arg2.length != 2) {
            usage();
        }
        String hostname = arg2[0];
        int port = -1;
        try {
            port = Integer.parseInt(arg2[1]);
        } catch (NumberFormatException x) {
            usage();
        }
        if (port < 0) {
            usage();
        }

        // Create the JTop Panel
        final JTop jtop = new JTop();
        // Set up the MBeanServerConnection to the target VM
        MBeanServerConnection server = connect(hostname, port);
        jtop.setMBeanServerConnection(server);

        // A timer task to update GUI per each interval
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                // Schedule the SwingWorker to update the GUI
                jtop.newSwingWorker().execute();
            }
        };

        // Create the standalone window with JTop panel
        // by the event dispatcher thread
        SwingUtilities.invokeAndWait(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI(jtop);
            }
        });

        // refresh every 2 seconds
        Timer timer = new Timer("JTop Sampling thread");
        timer.schedule(timerTask, 0, 2000);

    }

    // Establish a connection with the remote application
    //
    // You can modify the urlPath to the address of the JMX agent
    // of your application if it has a different URL.
    //
    // You can also modify the following code to take
    // username and password for client authentication.
    private static MBeanServerConnection connect(String hostname, int port) {
        // Create an RMI connector client and connect it to
        // the RMI connector server
        String urlPath = "/jndi/rmi://" + hostname + ":" + port + "/jmxrmi";
        MBeanServerConnection server = null;
        try {
            JMXServiceURL url = new JMXServiceURL("rmi", "", 0, urlPath);
            JMXConnector jmxc = JMXConnectorFactory.connect(url);
            server = jmxc.getMBeanServerConnection();
        } catch (MalformedURLException e) {
            // should not reach here
        } catch (IOException e) {
            System.err.println("\nCommunication error: " + e.getMessage());
            System.exit(1);
        }
        return server;
    }

    private static void usage() {
        System.out.println("Usage: java JTop <hostname>:<port>");
        System.exit(1);
    }
    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI(JPanel jtop) {
        // Create and set up the window.
        JFrame frame = new JFrame("JTop");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        // Create and set up the content pane.
        JComponent contentPane = (JComponent) frame.getContentPane();
        contentPane.add(jtop, BorderLayout.CENTER);
        contentPane.setOpaque(true); //content panes must be opaque
        contentPane.setBorder(new EmptyBorder(12, 12, 12, 12));
        frame.setContentPane(contentPane);

        // Display the window.
        frame.pack();
        frame.setVisible(true);
    }

}
