/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.visualvm.modules.mbeans;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.Timer;
@SuppressWarnings("serial")
class XPlottingViewer extends PlotterPanel implements ActionListener {
private final static Logger LOGGER =
Logger.getLogger(XPlottingViewer.class.getName());
// TODO: Make number of decimal places customizable
private static final int PLOTTER_DECIMALS = 4;
private JButton plotButton;
// The plotter cache holds Plotter instances for the various attributes
private static HashMap<String, XPlottingViewer> plotterCache =
new HashMap<String, XPlottingViewer>();
private static HashMap<String, Timer> timerCache =
new HashMap<String, Timer>();
private MBeansTab tab;
private XMBean mbean;
private String attributeName;
private String key;
private JTable table;
private XPlottingViewer(String key,
XMBean mbean,
String attributeName,
Object value,
JTable table,
MBeansTab tab) {
super(null);
this.tab = tab;
this.key = key;
this.mbean = mbean;
this.table = table;
this.attributeName = attributeName;
setupDisplay(createPlotter(mbean, attributeName, key, table));
}
static void dispose(MBeansTab tab) {
Iterator it = plotterCache.keySet().iterator();
while(it.hasNext()) {
String key = (String) it.next();
if(key.startsWith(String.valueOf(tab.hashCode()))) {
it.remove();
}
}
//plotterCache.clear();
it = timerCache.keySet().iterator();
while(it.hasNext()) {
String key = (String) it.next();
if(key.startsWith(String.valueOf(tab.hashCode()))) {
Timer t = timerCache.get(key);
t.stop();
it.remove();
}
}
}
public static boolean isViewableValue(Object value) {
return (value instanceof Number);
}
// Fired by dbl click
public static Component loadPlotting(
XMBean mbean, String attributeName, Object value, JTable table,
MBeansTab tab) {
Component comp = null;
if (isViewableValue(value)) {
String key = String.valueOf(tab.hashCode()) + " " + // NOI18N
String.valueOf(mbean.hashCode()) + " " + // NOI18N
mbean.getObjectName().getCanonicalName() + attributeName;
XPlottingViewer p = plotterCache.get(key);
if (p == null) {
p = new XPlottingViewer(key, mbean, attributeName, value,
table, tab);
plotterCache.put(key, p);
}
comp = p;
}
return comp;
}
@Override
public void actionPerformed(ActionEvent evt) {
plotterCache.remove(key);
Timer t = timerCache.remove(key);
t.stop();
((XMBeanAttributes) table).collapse(attributeName, this);
}
// Create plotter instance
public Plotter createPlotter(final XMBean xmbean,
final String attributeName,
String key,
JTable table) {
final Plotter p = new XPlotter(table, Plotter.Unit.NONE) {
Dimension prefSize = new Dimension(400, 170);
@Override
public Dimension getPreferredSize() {
return prefSize;
}
@Override
public Dimension getMinimumSize() {
return prefSize;
}
};
p.createSequence(attributeName, attributeName, null, true);
Timer timer = new Timer(tab.getUpdateInterval(), new ActionListener() {
public void actionPerformed(ActionEvent e) {
intervalElapsed(p);
}
});
timer.setCoalesce(true);
timer.setInitialDelay(0);
timer.start();
timerCache.put(key, timer);
return p;
}
void intervalElapsed(final Plotter p) {
tab.getRequestProcessor().post(new Runnable() {
public void run() {
try {
Number n = (Number) mbean.getCachedMBeanServerConnection().
getAttribute(
mbean.getObjectName(), attributeName);
long v;
if (n instanceof Float || n instanceof Double) {
p.setDecimals(PLOTTER_DECIMALS);
double d = (n instanceof Float) ? (Float) n : (Double) n;
v = Math.round(d * Math.pow(10.0, PLOTTER_DECIMALS));
} else {
v = n.longValue();
}
p.addValues(System.currentTimeMillis(), v);
} catch (Exception e) {
LOGGER.throwing(XPlottingViewer.class.getName(),
"intervalElapsed", e); // NOI18N
}
}
});
}
// Create Plotter display
private void setupDisplay(Plotter p) {
final JPanel buttonPanel = new JPanel();
final GridBagLayout gbl = new GridBagLayout();
buttonPanel.setLayout(gbl);
setLayout(new BorderLayout());
plotButton = new JButton(Resources.getText("LBL_DiscardChart")); // NOI18N
plotButton.addActionListener(this);
plotButton.setEnabled(true);
GridBagConstraints buttonConstraints = new GridBagConstraints();
buttonConstraints.gridx = 0;
buttonConstraints.gridy = 0;
buttonConstraints.fill = GridBagConstraints.VERTICAL;
buttonConstraints.anchor = GridBagConstraints.CENTER;
gbl.setConstraints(plotButton, buttonConstraints);
buttonPanel.add(plotButton);
if (attributeName != null && attributeName.length()!=0) {
final JPanel plotterLabelPanel = new JPanel();
final JLabel atlabel = new JLabel(attributeName);
final GridBagLayout gbl2 = new GridBagLayout();
plotterLabelPanel.setLayout(gbl2);
final GridBagConstraints labelConstraints = new GridBagConstraints();
labelConstraints.gridx = 0;
labelConstraints.gridy = 0;
labelConstraints.fill = GridBagConstraints.VERTICAL;
labelConstraints.anchor = GridBagConstraints.CENTER;
labelConstraints.ipady = 10;
gbl2.setConstraints(atlabel, labelConstraints);
plotterLabelPanel.add(atlabel);
add(plotterLabelPanel, BorderLayout.NORTH);
}
setPlotter(p);
add(buttonPanel, BorderLayout.SOUTH);
repaint();
}
}