1 /*
   2  * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.tools.jconsole.inspector;
  27 
  28 import java.awt.*;
  29 import java.awt.event.*;
  30 import java.util.*;
  31 import java.util.Timer;
  32 
  33 import javax.swing.*;
  34 
  35 import sun.tools.jconsole.*;
  36 
  37 @SuppressWarnings("serial")
  38 public class XPlottingViewer extends PlotterPanel implements ActionListener {
  39     // TODO: Make number of decimal places customizable
  40     private static final int PLOTTER_DECIMALS = 4;
  41 
  42     private JButton plotButton;
  43     // The plotter cache holds Plotter instances for the various attributes
  44     private static HashMap<String, XPlottingViewer> plotterCache =
  45         new HashMap<String, XPlottingViewer>();
  46      private static HashMap<String, Timer> timerCache =
  47          new HashMap<String, Timer>();
  48     private MBeansTab tab;
  49     private String attributeName;
  50     private String key;
  51     private JTable table;
  52     private XPlottingViewer(String key,
  53                             XMBean mbean,
  54                             String attributeName,
  55                             Object value,
  56                             JTable table,
  57                             MBeansTab tab) {
  58         super(null);
  59 
  60         this.tab = tab;
  61         this.key = key;
  62         this.table = table;
  63         this.attributeName = attributeName;
  64         Plotter plotter = createPlotter(mbean, attributeName, key, table);
  65         setupDisplay(plotter);
  66     }
  67 
  68     static void dispose(MBeansTab tab) {
  69         Iterator<String> it = plotterCache.keySet().iterator();
  70         while(it.hasNext()) {
  71             String key = it.next();
  72             if(key.startsWith(String.valueOf(tab.hashCode()))) {
  73                 it.remove();
  74             }
  75         }
  76         //plotterCache.clear();
  77         it = timerCache.keySet().iterator();
  78         while(it.hasNext()) {
  79             String key = (String) it.next();
  80             if(key.startsWith(String.valueOf(tab.hashCode()))) {
  81                 Timer t = timerCache.get(key);
  82                 t.cancel();
  83                 it.remove();
  84             }
  85         }
  86     }
  87 
  88     public static boolean isViewableValue(Object value) {
  89         return (value instanceof Number);
  90     }
  91 
  92     //Fired by dbl click
  93     public  static Component loadPlotting(XMBean mbean,
  94                                           String attributeName,
  95                                           Object value,
  96                                           JTable table,
  97                                           MBeansTab tab) {
  98         Component comp = null;
  99         if(isViewableValue(value)) {
 100             String key = String.valueOf(tab.hashCode()) + " " + String.valueOf(mbean.hashCode()) + " " + mbean.getObjectName().getCanonicalName() + attributeName;
 101             XPlottingViewer plotter = plotterCache.get(key);
 102             if(plotter == null) {
 103                 plotter = new XPlottingViewer(key,
 104                                               mbean,
 105                                               attributeName,
 106                                               value,
 107                                               table,
 108                                               tab);
 109                 plotterCache.put(key, plotter);
 110             }
 111 
 112             comp = plotter;
 113         }
 114         return comp;
 115     }
 116 
 117     /*public void paintComponent(Graphics g) {
 118         super.paintComponent(g);
 119         setBackground(g.getColor());
 120         plotter.paintComponent(g);
 121         }*/
 122     @Override
 123     public void actionPerformed(ActionEvent evt) {
 124         plotterCache.remove(key);
 125         Timer t = timerCache.remove(key);
 126         t.cancel();
 127         ((XMBeanAttributes) table).collapse(attributeName, this);
 128     }
 129 
 130     //Create plotter instance
 131     public Plotter createPlotter(final XMBean xmbean,
 132                                  final String attributeName,
 133                                  String key,
 134                                  JTable table) {
 135         final Plotter plotter = new XPlotter(table, Plotter.Unit.NONE) {
 136                 Dimension prefSize = new Dimension(400, 170);
 137             @Override
 138                 public Dimension getPreferredSize() {
 139                     return prefSize;
 140                 }
 141             @Override
 142                 public Dimension getMinimumSize() {
 143                     return prefSize;
 144                 }
 145             };
 146 
 147         plotter.createSequence(attributeName, attributeName, null, true);
 148 
 149         TimerTask timerTask = new TimerTask() {
 150                 public void run() {
 151                     tab.workerAdd(new Runnable() {
 152                             public void run() {
 153                                 try {
 154                                     Number n =
 155                                         (Number) xmbean.getSnapshotMBeanServerConnection().getAttribute(xmbean.getObjectName(), attributeName);
 156                                     long v;
 157                                     if (n instanceof Float || n instanceof Double) {
 158                                         plotter.setDecimals(PLOTTER_DECIMALS);
 159                                         double d = (n instanceof Float) ? (Float)n : (Double)n;
 160                                         v = Math.round(d * Math.pow(10.0, PLOTTER_DECIMALS));
 161                                     } else {
 162                                         v = n.longValue();
 163                                     }
 164                                     plotter.addValues(System.currentTimeMillis(), v);
 165                                 } catch (Exception ex) {
 166                                     // Should have a trace logged with proper
 167                                     // trace mecchanism
 168                                 }
 169                             }
 170                         });
 171                 }
 172             };
 173 
 174         String timerName = "Timer-" + key;
 175         Timer timer = new Timer(timerName, true);
 176         timer.schedule(timerTask, 0, tab.getUpdateInterval());
 177         timerCache.put(key, timer);
 178         return plotter;
 179     }
 180 
 181     private void setupDisplay(Plotter plotter) {
 182         final JPanel buttonPanel = new JPanel();
 183         final GridBagLayout gbl = new GridBagLayout();
 184         buttonPanel.setLayout(gbl);
 185         setLayout(new BorderLayout());
 186         plotButton = new JButton(Messages.DISCARD_CHART);
 187         plotButton.addActionListener(this);
 188         plotButton.setEnabled(true);
 189 
 190         GridBagConstraints buttonConstraints = new GridBagConstraints();
 191         buttonConstraints.gridx = 0;
 192         buttonConstraints.gridy = 0;
 193         buttonConstraints.fill = GridBagConstraints.VERTICAL;
 194         buttonConstraints.anchor = GridBagConstraints.CENTER;
 195         gbl.setConstraints(plotButton, buttonConstraints);
 196         buttonPanel.add(plotButton);
 197 
 198         if (attributeName != null && attributeName.length()!=0) {
 199             final JPanel plotterLabelPanel = new JPanel();
 200             final JLabel label = new JLabel(attributeName);
 201             final GridBagLayout gbl2 = new GridBagLayout();
 202             plotterLabelPanel.setLayout(gbl2);
 203             final GridBagConstraints labelConstraints = new GridBagConstraints();
 204             labelConstraints.gridx = 0;
 205             labelConstraints.gridy = 0;
 206             labelConstraints.fill = GridBagConstraints.VERTICAL;
 207             labelConstraints.anchor = GridBagConstraints.CENTER;
 208             labelConstraints.ipady = 10;
 209             gbl2.setConstraints(label, labelConstraints);
 210             plotterLabelPanel.add(label);
 211             add(plotterLabelPanel, BorderLayout.NORTH);
 212         }
 213         setPlotter(plotter);
 214         add(buttonPanel, BorderLayout.SOUTH);
 215         repaint();
 216     }
 217 
 218 }