feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2006, 2013, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyVetoException;
import java.net.URI;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import static sun.misc.Version.jdkMinorVersion;
import static java.awt.BorderLayout.*;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
public class AboutDialog extends InternalDialog {
private static final Color textColor = new Color(87, 88, 89);
private static final Color bgColor = new Color(232, 237, 241);
private static final Color borderColor = Color.black;
private Icon mastheadIcon =
new MastheadIcon(Messages.HELP_ABOUT_DIALOG_MASTHEAD_TITLE);
private static AboutDialog aboutDialog;
private JLabel statusBar;
private Action closeAction;
public AboutDialog(JConsole jConsole) {
super(jConsole, Messages.HELP_ABOUT_DIALOG_TITLE, false);
setAccessibleDescription(this, Messages.HELP_ABOUT_DIALOG_ACCESSIBLE_DESCRIPTION);
setDefaultCloseOperation(HIDE_ON_CLOSE);
setResizable(false);
JComponent cp = (JComponent)getContentPane();
createActions();
JLabel mastheadLabel = new JLabel(mastheadIcon);
setAccessibleName(mastheadLabel,
Messages.HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME);
JPanel mainPanel = new TPanel(0, 0);
mainPanel.add(mastheadLabel, NORTH);
String jConsoleVersion = Version.getVersion();
String vmName = System.getProperty("java.vm.name");
String vmVersion = System.getProperty("java.vm.version");
String urlStr = getOnlineDocUrl();
if (isBrowseSupported()) {
urlStr = "<a style='color:#35556b' href=\"" + urlStr + "\">" + urlStr + "</a>";
}
JPanel infoAndLogoPanel = new JPanel(new BorderLayout(10, 10));
infoAndLogoPanel.setBackground(bgColor);
String colorStr = String.format("%06x", textColor.getRGB() & 0xFFFFFF);
JEditorPane helpLink = new JEditorPane("text/html",
"<html><font color=#"+ colorStr + ">" +
Resources.format(Messages.HELP_ABOUT_DIALOG_JCONSOLE_VERSION, jConsoleVersion) +
"<p>" + Resources.format(Messages.HELP_ABOUT_DIALOG_JAVA_VERSION, (vmName +", "+ vmVersion)) +
"<p>" + urlStr + "</html>");
helpLink.setOpaque(false);
helpLink.setEditable(false);
helpLink.setForeground(textColor);
mainPanel.setBorder(BorderFactory.createLineBorder(borderColor));
infoAndLogoPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
helpLink.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
browse(e.getDescription());
}
}
});
infoAndLogoPanel.add(helpLink, NORTH);
ImageIcon brandLogoIcon = new ImageIcon(getClass().getResource("resources/brandlogo.png"));
JLabel brandLogo = new JLabel(brandLogoIcon, JLabel.LEADING);
JButton closeButton = new JButton(closeAction);
JPanel bottomPanel = new TPanel(0, 0);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
buttonPanel.setOpaque(false);
mainPanel.add(infoAndLogoPanel, CENTER);
cp.add(bottomPanel, SOUTH);
infoAndLogoPanel.add(brandLogo, SOUTH);
buttonPanel.setBorder(new EmptyBorder(2, 12, 2, 12));
buttonPanel.add(closeButton);
bottomPanel.add(buttonPanel, NORTH);
statusBar = new JLabel(" ");
bottomPanel.add(statusBar, SOUTH);
cp.add(mainPanel, NORTH);
pack();
setLocationRelativeTo(jConsole);
Utilities.updateTransparency(this);
}
public void showDialog() {
statusBar.setText(" ");
setVisible(true);
try {
// Bring to front of other dialogs
setSelected(true);
} catch (PropertyVetoException e) {
// ignore
}
}
private static AboutDialog getAboutDialog(JConsole jConsole) {
if (aboutDialog == null) {
aboutDialog = new AboutDialog(jConsole);
}
return aboutDialog;
}
static void showAboutDialog(JConsole jConsole) {
getAboutDialog(jConsole).showDialog();
}
static void browseUserGuide(JConsole jConsole) {
getAboutDialog(jConsole).browse(getOnlineDocUrl());
}
static boolean isBrowseSupported() {
return (Desktop.isDesktopSupported() &&
Desktop.getDesktop().isSupported(Desktop.Action.BROWSE));
}
void browse(String urlStr) {
try {
Desktop.getDesktop().browse(new URI(urlStr));
} catch (Exception ex) {
showDialog();
statusBar.setText(ex.getLocalizedMessage());
if (JConsole.isDebug()) {
ex.printStackTrace();
}
}
}
private void createActions() {
closeAction = new AbstractAction(Messages.CLOSE) {
public void actionPerformed(ActionEvent ev) {
setVisible(false);
statusBar.setText("");
}
};
}
private static String getOnlineDocUrl() {
String version = Integer.toString(jdkMinorVersion());
return Resources.format(Messages.HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL,
version);
}
private static class TPanel extends JPanel {
TPanel(int hgap, int vgap) {
super(new BorderLayout(hgap, vgap));
setOpaque(false);
}
}
}

View File

@@ -0,0 +1,564 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import static javax.swing.SwingConstants.*;
import static sun.tools.jconsole.JConsole.*;
@SuppressWarnings("serial")
public class BorderedComponent extends JPanel implements ActionListener {
JButton moreOrLessButton;
String valueLabelStr;
JLabel label;
JComponent comp;
boolean collapsed = false;
private Icon collapseIcon;
private Icon expandIcon;
private static Image getImage(String name) {
Toolkit tk = Toolkit.getDefaultToolkit();
name = "resources/" + name + ".png";
return tk.getImage(BorderedComponent.class.getResource(name));
}
public BorderedComponent(String text) {
this(text, null, false);
}
public BorderedComponent(String text, JComponent comp) {
this(text, comp, false);
}
public BorderedComponent(String text, JComponent comp, boolean collapsible) {
super(null);
this.comp = comp;
// Only add border if text is not null
if (text != null) {
TitledBorder border;
if (collapsible) {
final JLabel textLabel = new JLabel(text);
JPanel borderLabel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0)) {
public int getBaseline(int w, int h) {
Dimension dim = textLabel.getPreferredSize();
return textLabel.getBaseline(dim.width, dim.height) + textLabel.getY();
}
};
borderLabel.add(textLabel);
border = new LabeledBorder(borderLabel);
textLabel.setForeground(border.getTitleColor());
if (IS_WIN) {
collapseIcon = new ImageIcon(getImage("collapse-winlf"));
expandIcon = new ImageIcon(getImage("expand-winlf"));
} else {
collapseIcon = new ArrowIcon(SOUTH, textLabel);
expandIcon = new ArrowIcon(EAST, textLabel);
}
moreOrLessButton = new JButton(collapseIcon);
moreOrLessButton.setContentAreaFilled(false);
moreOrLessButton.setBorderPainted(false);
moreOrLessButton.setMargin(new Insets(0, 0, 0, 0));
moreOrLessButton.addActionListener(this);
String toolTip =
Messages.BORDERED_COMPONENT_MORE_OR_LESS_BUTTON_TOOLTIP;
moreOrLessButton.setToolTipText(toolTip);
borderLabel.add(moreOrLessButton);
borderLabel.setSize(borderLabel.getPreferredSize());
add(borderLabel);
} else {
border = new TitledBorder(text);
}
setBorder(new CompoundBorder(new FocusBorder(this), border));
} else {
setBorder(new FocusBorder(this));
}
if (comp != null) {
add(comp);
}
}
public void setComponent(JComponent comp) {
if (this.comp != null) {
remove(this.comp);
}
this.comp = comp;
if (!collapsed) {
LayoutManager lm = getLayout();
if (lm instanceof BorderLayout) {
add(comp, BorderLayout.CENTER);
} else {
add(comp);
}
}
revalidate();
}
public void setValueLabel(String str) {
this.valueLabelStr = str;
if (label != null) {
label.setText(Resources.format(Messages.CURRENT_VALUE,
valueLabelStr));
}
}
public void actionPerformed(ActionEvent ev) {
if (collapsed) {
if (label != null) {
remove(label);
}
add(comp);
moreOrLessButton.setIcon(collapseIcon);
} else {
remove(comp);
if (valueLabelStr != null) {
if (label == null) {
label = new JLabel(Resources.format(Messages.CURRENT_VALUE,
valueLabelStr));
}
add(label);
}
moreOrLessButton.setIcon(expandIcon);
}
collapsed = !collapsed;
JComponent container = (JComponent)getParent();
if (container != null &&
container.getLayout() instanceof VariableGridLayout) {
((VariableGridLayout)container.getLayout()).setFillRow(this, !collapsed);
container.revalidate();
}
}
public Dimension getMinimumSize() {
if (getLayout() != null) {
// A layout manager has been set, so delegate to it
return super.getMinimumSize();
}
if (moreOrLessButton != null) {
Dimension d = moreOrLessButton.getMinimumSize();
Insets i = getInsets();
d.width += i.left + i.right;
d.height += i.top + i.bottom;
return d;
} else {
return super.getMinimumSize();
}
}
public void doLayout() {
if (getLayout() != null) {
// A layout manager has been set, so delegate to it
super.doLayout();
return;
}
Dimension d = getSize();
Insets i = getInsets();
if (collapsed) {
if (label != null) {
Dimension p = label.getPreferredSize();
label.setBounds(i.left,
i.top + (d.height - i.top - i.bottom - p.height) / 2,
p.width,
p.height);
}
} else {
if (comp != null) {
comp.setBounds(i.left,
i.top,
d.width - i.left - i.right,
d.height - i.top - i.bottom);
}
}
}
private static class ArrowIcon implements Icon {
private int direction;
private JLabel textLabel;
public ArrowIcon(int direction, JLabel textLabel) {
this.direction = direction;
this.textLabel = textLabel;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
int w = getIconWidth();
int h = w;
Polygon p = new Polygon();
switch (direction) {
case EAST:
p.addPoint(x + 2, y);
p.addPoint(x + w - 2, y + h / 2);
p.addPoint(x + 2, y + h - 1);
break;
case SOUTH:
p.addPoint(x, y + 2);
p.addPoint(x + w / 2, y + h - 2);
p.addPoint(x + w - 1, y + 2);
break;
}
g.fillPolygon(p);
}
public int getIconWidth() {
return getIconHeight();
}
public int getIconHeight() {
Graphics g = textLabel.getGraphics();
if (g != null) {
int h = g.getFontMetrics(textLabel.getFont()).getAscent() * 6/10;
if (h % 2 == 0) {
h += 1; // Make it odd
}
return h;
} else {
return 7;
}
}
}
/**
* A subclass of <code>TitledBorder</code> which implements an arbitrary border
* with the addition of a JComponent (JLabel, JPanel, etc) in the
* default position.
* <p>
* If the border property value is not
* specified in the constructor or by invoking the appropriate
* set method, the property value will be defined by the current
* look and feel, using the following property name in the
* Defaults Table:
* <ul>
* <li>&quot;TitledBorder.border&quot;
* </ul>
*/
protected static class LabeledBorder extends TitledBorder {
protected JComponent label;
private Point compLoc = new Point();
/**
* Creates a LabeledBorder instance.
*
* @param label the label the border should display
*/
public LabeledBorder(JComponent label) {
this(null, label);
}
/**
* Creates a LabeledBorder instance with the specified border
* and an empty label.
*
* @param border the border
*/
public LabeledBorder(Border border) {
this(border, null);
}
/**
* Creates a LabeledBorder instance with the specified border and
* label.
*
* @param border the border
* @param label the label the border should display
*/
public LabeledBorder(Border border, JComponent label) {
super(border);
this.label = label;
if (label instanceof JLabel &&
label.getForeground() instanceof ColorUIResource) {
label.setForeground(getTitleColor());
}
}
/**
* Paints the border for the specified component with the
* specified position and size.
* @param c the component for which this border is being painted
* @param g the paint graphics
* @param x the x position of the painted border
* @param y the y position of the painted border
* @param width the width of the painted border
* @param height the height of the painted border
*/
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Border border = getBorder();
if (label == null) {
if (border != null) {
border.paintBorder(c, g, x, y, width, height);
}
return;
}
Rectangle grooveRect = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING,
width - (EDGE_SPACING * 2),
height - (EDGE_SPACING * 2));
Dimension labelDim = label.getPreferredSize();
int baseline = label.getBaseline(labelDim.width, labelDim.height);
int ascent = Math.max(0, baseline);
int descent = labelDim.height - ascent;
int diff;
Insets insets;
if (border != null) {
insets = border.getBorderInsets(c);
} else {
insets = new Insets(0, 0, 0, 0);
}
diff = Math.max(0, ascent/2 + TEXT_SPACING - EDGE_SPACING);
grooveRect.y += diff;
grooveRect.height -= diff;
compLoc.y = grooveRect.y + insets.top/2 - (ascent + descent) / 2 - 1;
int justification;
if (c.getComponentOrientation().isLeftToRight()) {
justification = LEFT;
} else {
justification = RIGHT;
}
switch (justification) {
case LEFT:
compLoc.x = grooveRect.x + TEXT_INSET_H + insets.left;
break;
case RIGHT:
compLoc.x = (grooveRect.x + grooveRect.width
- (labelDim.width + TEXT_INSET_H + insets.right));
break;
}
// If title is positioned in middle of border AND its fontsize
// is greater than the border's thickness, we'll need to paint
// the border in sections to leave space for the component's background
// to show through the title.
//
if (border != null) {
if (grooveRect.y > compLoc.y - ascent) {
Rectangle clipRect = new Rectangle();
// save original clip
Rectangle saveClip = g.getClipBounds();
// paint strip left of text
clipRect.setBounds(saveClip);
if (computeIntersection(clipRect, x, y, compLoc.x-1-x, height)) {
g.setClip(clipRect);
border.paintBorder(c, g, grooveRect.x, grooveRect.y,
grooveRect.width, grooveRect.height);
}
// paint strip right of text
clipRect.setBounds(saveClip);
if (computeIntersection(clipRect, compLoc.x+ labelDim.width +1, y,
x+width-(compLoc.x+ labelDim.width +1), height)) {
g.setClip(clipRect);
border.paintBorder(c, g, grooveRect.x, grooveRect.y,
grooveRect.width, grooveRect.height);
}
// paint strip below text
clipRect.setBounds(saveClip);
if (computeIntersection(clipRect,
compLoc.x - 1, compLoc.y + ascent + descent,
labelDim.width + 2,
y + height - compLoc.y - ascent - descent)) {
g.setClip(clipRect);
border.paintBorder(c, g, grooveRect.x, grooveRect.y,
grooveRect.width, grooveRect.height);
}
// restore clip
g.setClip(saveClip);
} else {
border.paintBorder(c, g, grooveRect.x, grooveRect.y,
grooveRect.width, grooveRect.height);
}
label.setLocation(compLoc);
label.setSize(labelDim);
}
}
/**
* Reinitialize the insets parameter with this Border's current Insets.
* @param c the component for which this border insets value applies
* @param insets the object to be reinitialized
*/
public Insets getBorderInsets(Component c, Insets insets) {
Border border = getBorder();
if (border != null) {
if (border instanceof AbstractBorder) {
((AbstractBorder)border).getBorderInsets(c, insets);
} else {
// Can't reuse border insets because the Border interface
// can't be enhanced.
Insets i = border.getBorderInsets(c);
insets.top = i.top;
insets.right = i.right;
insets.bottom = i.bottom;
insets.left = i.left;
}
} else {
insets.left = insets.top = insets.right = insets.bottom = 0;
}
insets.left += EDGE_SPACING + TEXT_SPACING;
insets.right += EDGE_SPACING + TEXT_SPACING;
insets.top += EDGE_SPACING + TEXT_SPACING;
insets.bottom += EDGE_SPACING + TEXT_SPACING;
if (c == null || label == null) {
return insets;
}
insets.top += label.getHeight();
return insets;
}
/**
* Returns the label of the labeled border.
*/
public JComponent getLabel() {
return label;
}
/**
* Sets the title of the titled border.
* param title the title for the border
*/
public void setLabel(JComponent label) {
this.label = label;
}
/**
* Returns the minimum dimensions this border requires
* in order to fully display the border and title.
* @param c the component where this border will be drawn
*/
public Dimension getMinimumSize(Component c) {
Insets insets = getBorderInsets(c);
Dimension minSize = new Dimension(insets.right + insets.left,
insets.top + insets.bottom);
minSize.width += label.getWidth();
return minSize;
}
private static boolean computeIntersection(Rectangle dest,
int rx, int ry, int rw, int rh) {
int x1 = Math.max(rx, dest.x);
int x2 = Math.min(rx + rw, dest.x + dest.width);
int y1 = Math.max(ry, dest.y);
int y2 = Math.min(ry + rh, dest.y + dest.height);
dest.x = x1;
dest.y = y1;
dest.width = x2 - x1;
dest.height = y2 - y1;
if (dest.width <= 0 || dest.height <= 0) {
return false;
}
return true;
}
}
protected static class FocusBorder extends AbstractBorder implements FocusListener {
private Component comp;
private Color focusColor;
private boolean focusLostTemporarily = false;
public FocusBorder(Component comp) {
this.comp = comp;
comp.addFocusListener(this);
// This is the best guess for a L&F specific color
focusColor = UIManager.getColor("TabbedPane.focus");
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
if (comp.hasFocus() || focusLostTemporarily) {
Color color = g.getColor();
g.setColor(focusColor);
BasicGraphicsUtils.drawDashedRect(g, x, y, width, height);
g.setColor(color);
}
}
public Insets getBorderInsets(Component c, Insets insets) {
insets.set(2, 2, 2, 2);
return insets;
}
public void focusGained(FocusEvent e) {
comp.repaint();
}
public void focusLost(FocusEvent e) {
// We will still paint focus even if lost temporarily
focusLostTemporarily = e.isTemporary();
if (!focusLostTemporarily) {
comp.repaint();
}
}
}
}

View File

@@ -0,0 +1,248 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.management.*;
import java.lang.reflect.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.concurrent.*;
import static sun.tools.jconsole.Formatter.*;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
class ClassTab extends Tab implements ActionListener {
PlotterPanel loadedClassesMeter;
TimeComboBox timeComboBox;
private JCheckBox verboseCheckBox;
private HTMLPane details;
private ClassOverviewPanel overviewPanel;
private boolean plotterListening = false;
private static final String loadedPlotterKey = "loaded";
private static final String totalLoadedPlotterKey = "totalLoaded";
private static final Color loadedPlotterColor = Plotter.defaultColor;
private static final Color totalLoadedPlotterColor = Color.red;
/*
Hierarchy of panels and layouts for this tab:
ClassTab (BorderLayout)
North: topPanel (BorderLayout)
Center: controlPanel (FlowLayout)
timeComboBox
East: topRightPanel (FlowLayout)
verboseCheckBox
Center: plotterPanel (BorderLayout)
Center: plotter
South: bottomPanel (BorderLayout)
Center: details
*/
public static String getTabName() {
return Messages.CLASSES;
}
public ClassTab(VMPanel vmPanel) {
super(vmPanel, getTabName());
setLayout(new BorderLayout(0, 0));
setBorder(new EmptyBorder(4, 4, 3, 4));
JPanel topPanel = new JPanel(new BorderLayout());
JPanel plotterPanel = new JPanel(new BorderLayout());
JPanel bottomPanel = new JPanel(new BorderLayout());
add(topPanel, BorderLayout.NORTH);
add(plotterPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.SOUTH);
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5));
topPanel.add(controlPanel, BorderLayout.CENTER);
verboseCheckBox = new JCheckBox(Messages.VERBOSE_OUTPUT);
verboseCheckBox.addActionListener(this);
verboseCheckBox.setToolTipText(Messages.VERBOSE_OUTPUT_TOOLTIP);
JPanel topRightPanel = new JPanel();
topRightPanel.setBorder(new EmptyBorder(0, 65-8, 0, 70));
topRightPanel.add(verboseCheckBox);
topPanel.add(topRightPanel, BorderLayout.AFTER_LINE_ENDS);
loadedClassesMeter = new PlotterPanel(Messages.NUMBER_OF_LOADED_CLASSES,
Plotter.Unit.NONE, false);
loadedClassesMeter.plotter.createSequence(loadedPlotterKey,
Messages.LOADED,
loadedPlotterColor,
true);
loadedClassesMeter.plotter.createSequence(totalLoadedPlotterKey,
Messages.TOTAL_LOADED,
totalLoadedPlotterColor,
true);
setAccessibleName(loadedClassesMeter.plotter,
Messages.CLASS_TAB_LOADED_CLASSES_PLOTTER_ACCESSIBLE_NAME);
plotterPanel.add(loadedClassesMeter);
timeComboBox = new TimeComboBox(loadedClassesMeter.plotter);
controlPanel.add(new LabeledComponent(Messages.TIME_RANGE_COLON,
Resources.getMnemonicInt(Messages.TIME_RANGE_COLON),
timeComboBox));
LabeledComponent.layout(plotterPanel);
bottomPanel.setBorder(new CompoundBorder(new TitledBorder(Messages.DETAILS),
new EmptyBorder(10, 10, 10, 10)));
details = new HTMLPane();
setAccessibleName(details, Messages.DETAILS);
JScrollPane scrollPane = new JScrollPane(details);
scrollPane.setPreferredSize(new Dimension(0, 150));
bottomPanel.add(scrollPane, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent ev) {
final boolean b = verboseCheckBox.isSelected();
workerAdd(new Runnable() {
public void run() {
ProxyClient proxyClient = vmPanel.getProxyClient();
try {
proxyClient.getClassLoadingMXBean().setVerbose(b);
} catch (UndeclaredThrowableException e) {
proxyClient.markAsDead();
} catch (IOException ex) {
// Ignore
}
}
});
}
public SwingWorker<?, ?> newSwingWorker() {
final ProxyClient proxyClient = vmPanel.getProxyClient();
if (!plotterListening) {
proxyClient.addWeakPropertyChangeListener(loadedClassesMeter.plotter);
plotterListening = true;
}
return new SwingWorker<Boolean, Object>() {
private long clCount, cuCount, ctCount;
private boolean isVerbose;
private String detailsStr;
private long timeStamp;
public Boolean doInBackground() {
try {
ClassLoadingMXBean classLoadingMBean = proxyClient.getClassLoadingMXBean();
clCount = classLoadingMBean.getLoadedClassCount();
cuCount = classLoadingMBean.getUnloadedClassCount();
ctCount = classLoadingMBean.getTotalLoadedClassCount();
isVerbose = classLoadingMBean.isVerbose();
detailsStr = formatDetails();
timeStamp = System.currentTimeMillis();
return true;
} catch (UndeclaredThrowableException e) {
proxyClient.markAsDead();
return false;
} catch (IOException e) {
return false;
}
}
protected void done() {
try {
if (get()) {
loadedClassesMeter.plotter.addValues(timeStamp, clCount, ctCount);
if (overviewPanel != null) {
overviewPanel.updateClassInfo(ctCount, clCount);
overviewPanel.getPlotter().addValues(timeStamp, clCount);
}
loadedClassesMeter.setValueLabel(clCount + "");
verboseCheckBox.setSelected(isVerbose);
details.setText(detailsStr);
}
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
if (JConsole.isDebug()) {
ex.printStackTrace();
}
}
}
private String formatDetails() {
String text = "<table cellspacing=0 cellpadding=0>";
long time = System.currentTimeMillis();
String timeStamp = formatDateTime(time);
text += newRow(Messages.TIME, timeStamp);
text += newRow(Messages.CURRENT_CLASSES_LOADED, justify(clCount, 5));
text += newRow(Messages.TOTAL_CLASSES_LOADED, justify(ctCount, 5));
text += newRow(Messages.TOTAL_CLASSES_UNLOADED, justify(cuCount, 5));
return text;
}
};
}
OverviewPanel[] getOverviewPanels() {
if (overviewPanel == null) {
overviewPanel = new ClassOverviewPanel();
}
return new OverviewPanel[] { overviewPanel };
}
private static class ClassOverviewPanel extends OverviewPanel {
ClassOverviewPanel() {
super(Messages.CLASSES, loadedPlotterKey, Messages.LOADED, null);
}
private void updateClassInfo(long total, long loaded) {
long unloaded = (total - loaded);
getInfoLabel().setText(Resources.format(Messages.CLASS_TAB_INFO_LABEL_FORMAT,
loaded, unloaded, total));
}
}
}

View File

@@ -0,0 +1,768 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole;
import java.util.List;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.BasicRadioButtonUI;
import javax.swing.table.*;
import static java.awt.BorderLayout.*;
import static javax.swing.ListSelectionModel.*;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
public class ConnectDialog extends InternalDialog
implements DocumentListener, FocusListener,
ItemListener, ListSelectionListener, KeyListener {
private static final int COL_NAME = 0;
private static final int COL_PID = 1;
JConsole jConsole;
JTextField userNameTF, passwordTF;
JRadioButton localRadioButton, remoteRadioButton;
JLabel localMessageLabel, remoteMessageLabel;
JTextField remoteTF;
JButton connectButton, cancelButton;
JPanel radioButtonPanel;
private Icon mastheadIcon =
new MastheadIcon(Messages.CONNECT_DIALOG_MASTHEAD_TITLE);
private Color hintTextColor, disabledTableCellColor;
// The table of managed VM (local process)
JTable vmTable;
ManagedVmTableModel vmModel = null;
JScrollPane localTableScrollPane = null;
private Action connectAction, cancelAction;
public ConnectDialog(JConsole jConsole) {
super(jConsole, Messages.CONNECT_DIALOG_TITLE, true);
this.jConsole = jConsole;
setAccessibleDescription(this,
Messages.CONNECT_DIALOG_ACCESSIBLE_DESCRIPTION);
setDefaultCloseOperation(HIDE_ON_CLOSE);
setResizable(false);
Container cp = (JComponent)getContentPane();
radioButtonPanel = new JPanel(new BorderLayout(0, 12));
radioButtonPanel.setBorder(new EmptyBorder(6, 12, 12, 12));
ButtonGroup radioButtonGroup = new ButtonGroup();
JPanel bottomPanel = new JPanel(new BorderLayout());
statusBar = new JLabel(" ", JLabel.CENTER);
setAccessibleName(statusBar,
Messages.CONNECT_DIALOG_STATUS_BAR_ACCESSIBLE_NAME);
Font normalLabelFont = statusBar.getFont();
Font boldLabelFont = normalLabelFont.deriveFont(Font.BOLD);
Font smallLabelFont = normalLabelFont.deriveFont(normalLabelFont.getSize2D() - 1);
JLabel mastheadLabel = new JLabel(mastheadIcon);
setAccessibleName(mastheadLabel,
Messages.CONNECT_DIALOG_MASTHEAD_ACCESSIBLE_NAME);
cp.add(mastheadLabel, NORTH);
cp.add(radioButtonPanel, CENTER);
cp.add(bottomPanel, SOUTH);
createActions();
remoteTF = new JTextField();
remoteTF.addActionListener(connectAction);
remoteTF.getDocument().addDocumentListener(this);
remoteTF.addFocusListener(this);
remoteTF.setPreferredSize(remoteTF.getPreferredSize());
setAccessibleName(remoteTF,
Messages.REMOTE_PROCESS_TEXT_FIELD_ACCESSIBLE_NAME);
//
// If the VM supports the local attach mechanism (is: Sun
// implementation) then the Local Process panel is created.
//
if (JConsole.isLocalAttachAvailable()) {
vmModel = new ManagedVmTableModel();
vmTable = new LocalTabJTable(vmModel);
vmTable.setSelectionMode(SINGLE_SELECTION);
vmTable.setPreferredScrollableViewportSize(new Dimension(400, 250));
vmTable.setColumnSelectionAllowed(false);
vmTable.addFocusListener(this);
vmTable.getSelectionModel().addListSelectionListener(this);
TableColumnModel columnModel = vmTable.getColumnModel();
TableColumn pidColumn = columnModel.getColumn(COL_PID);
pidColumn.setMaxWidth(getLabelWidth("9999999"));
pidColumn.setResizable(false);
TableColumn cmdLineColumn = columnModel.getColumn(COL_NAME);
cmdLineColumn.setResizable(false);
localRadioButton = new JRadioButton(Messages.LOCAL_PROCESS_COLON);
localRadioButton.setMnemonic(Resources.getMnemonicInt(Messages.LOCAL_PROCESS_COLON));
localRadioButton.setFont(boldLabelFont);
localRadioButton.addItemListener(this);
radioButtonGroup.add(localRadioButton);
JPanel localPanel = new JPanel(new BorderLayout());
JPanel localTablePanel = new JPanel(new BorderLayout());
radioButtonPanel.add(localPanel, NORTH);
localPanel.add(localRadioButton, NORTH);
localPanel.add(new Padder(localRadioButton), LINE_START);
localPanel.add(localTablePanel, CENTER);
localTableScrollPane = new JScrollPane(vmTable);
localTablePanel.add(localTableScrollPane, NORTH);
localMessageLabel = new JLabel(" ");
localMessageLabel.setFont(smallLabelFont);
localMessageLabel.setForeground(hintTextColor);
localTablePanel.add(localMessageLabel, SOUTH);
}
remoteRadioButton = new JRadioButton(Messages.REMOTE_PROCESS_COLON);
remoteRadioButton.setMnemonic(Resources.getMnemonicInt(Messages.REMOTE_PROCESS_COLON));
remoteRadioButton.setFont(boldLabelFont);
radioButtonGroup.add(remoteRadioButton);
JPanel remotePanel = new JPanel(new BorderLayout());
if (localRadioButton != null) {
remotePanel.add(remoteRadioButton, NORTH);
remotePanel.add(new Padder(remoteRadioButton), LINE_START);
Action nextRadioButtonAction =
new AbstractAction("nextRadioButton") {
public void actionPerformed(ActionEvent ev) {
JRadioButton rb =
(ev.getSource() == localRadioButton) ? remoteRadioButton
: localRadioButton;
rb.doClick();
rb.requestFocus();
}
};
localRadioButton.getActionMap().put("nextRadioButton", nextRadioButtonAction);
remoteRadioButton.getActionMap().put("nextRadioButton", nextRadioButtonAction);
localRadioButton.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),
"nextRadioButton");
remoteRadioButton.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),
"nextRadioButton");
} else {
JLabel remoteLabel = new JLabel(remoteRadioButton.getText());
remoteLabel.setFont(boldLabelFont);
remotePanel.add(remoteLabel, NORTH);
}
radioButtonPanel.add(remotePanel, SOUTH);
JPanel remoteTFPanel = new JPanel(new BorderLayout());
remotePanel.add(remoteTFPanel, CENTER);
remoteTFPanel.add(remoteTF, NORTH);
remoteMessageLabel = new JLabel("<html>" + Messages.REMOTE_TF_USAGE + "</html>");
remoteMessageLabel.setFont(smallLabelFont);
remoteMessageLabel.setForeground(hintTextColor);
remoteTFPanel.add(remoteMessageLabel, CENTER);
JPanel userPwdPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
userPwdPanel.setBorder(new EmptyBorder(12, 0, 0, 0)); // top padding
int tfWidth = JConsole.IS_WIN ? 12 : 8;
userNameTF = new JTextField(tfWidth);
userNameTF.addActionListener(connectAction);
userNameTF.getDocument().addDocumentListener(this);
userNameTF.addFocusListener(this);
setAccessibleName(userNameTF,
Messages.USERNAME_ACCESSIBLE_NAME);
LabeledComponent lc;
lc = new LabeledComponent(Messages.USERNAME_COLON_,
Resources.getMnemonicInt(Messages.USERNAME_COLON_),
userNameTF);
lc.label.setFont(boldLabelFont);
userPwdPanel.add(lc);
passwordTF = new JPasswordField(tfWidth);
// Heights differ, so fix here
passwordTF.setPreferredSize(userNameTF.getPreferredSize());
passwordTF.addActionListener(connectAction);
passwordTF.getDocument().addDocumentListener(this);
passwordTF.addFocusListener(this);
setAccessibleName(passwordTF,
Messages.PASSWORD_ACCESSIBLE_NAME);
lc = new LabeledComponent(Messages.PASSWORD_COLON_,
Resources.getMnemonicInt(Messages.PASSWORD_COLON_),
passwordTF);
lc.setBorder(new EmptyBorder(0, 12, 0, 0)); // Left padding
lc.label.setFont(boldLabelFont);
userPwdPanel.add(lc);
remoteTFPanel.add(userPwdPanel, SOUTH);
String connectButtonToolTipText =
Messages.CONNECT_DIALOG_CONNECT_BUTTON_TOOLTIP;
connectButton = new JButton(connectAction);
connectButton.setToolTipText(connectButtonToolTipText);
cancelButton = new JButton(cancelAction);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
buttonPanel.setBorder(new EmptyBorder(12, 12, 2, 12));
if (JConsole.IS_GTK) {
buttonPanel.add(cancelButton);
buttonPanel.add(connectButton);
} else {
buttonPanel.add(connectButton);
buttonPanel.add(cancelButton);
}
bottomPanel.add(buttonPanel, NORTH);
bottomPanel.add(statusBar, SOUTH);
updateButtonStates();
Utilities.updateTransparency(this);
}
public void revalidate() {
// Adjust some colors
Color disabledForeground = UIManager.getColor("Label.disabledForeground");
if (disabledForeground == null) {
// fall back for Nimbus that doesn't support 'Label.disabledForeground'
disabledForeground = UIManager.getColor("Label.disabledText");
}
hintTextColor =
ensureContrast(disabledForeground,
UIManager.getColor("Panel.background"));
disabledTableCellColor =
ensureContrast(new Color(0x808080),
UIManager.getColor("Table.background"));
if (remoteMessageLabel != null) {
remoteMessageLabel.setForeground(hintTextColor);
// Update html color setting
String colorStr =
String.format("%06x", hintTextColor.getRGB() & 0xFFFFFF);
remoteMessageLabel.setText("<html><font color=#" + colorStr + ">" +
Messages.REMOTE_TF_USAGE);
}
if (localMessageLabel != null) {
localMessageLabel.setForeground(hintTextColor);
// Update html color setting
valueChanged(null);
}
super.revalidate();
}
private void createActions() {
connectAction = new AbstractAction(Messages.CONNECT) {
/* init */ {
putValue(Action.MNEMONIC_KEY, Resources.getMnemonicInt(Messages.CONNECT));
}
public void actionPerformed(ActionEvent ev) {
if (!isEnabled() || !isVisible()) {
return;
}
setVisible(false);
statusBar.setText("");
if (remoteRadioButton.isSelected()) {
String txt = remoteTF.getText().trim();
String userName = userNameTF.getText().trim();
userName = userName.equals("") ? null : userName;
String password = passwordTF.getText();
password = password.equals("") ? null : password;
try {
if (txt.startsWith(JConsole.ROOT_URL)) {
String url = txt;
jConsole.addUrl(url, userName, password, false);
remoteTF.setText(JConsole.ROOT_URL);
return;
} else {
String host = remoteTF.getText().trim();
String port = "0";
int index = host.lastIndexOf(":");
if (index >= 0) {
port = host.substring(index + 1);
host = host.substring(0, index);
}
if (host.length() > 0 && port.length() > 0) {
int p = Integer.parseInt(port.trim());
jConsole.addHost(host, p, userName, password);
remoteTF.setText("");
userNameTF.setText("");
passwordTF.setText("");
return;
}
}
} catch (Exception ex) {
statusBar.setText(ex.toString());
}
setVisible(true);
} else if (localRadioButton != null && localRadioButton.isSelected()) {
// Try to connect to selected VM. If a connection
// cannot be established for some reason (the process has
// terminated for example) then keep the dialog open showing
// the connect error.
//
int row = vmTable.getSelectedRow();
if (row >= 0) {
jConsole.addVmid(vmModel.vmAt(row));
}
refresh();
}
}
};
cancelAction = new AbstractAction(Messages.CANCEL) {
public void actionPerformed(ActionEvent ev) {
setVisible(false);
statusBar.setText("");
}
};
}
// a label used solely for calculating the width
private static JLabel tmpLabel = new JLabel();
public static int getLabelWidth(String text) {
tmpLabel.setText(text);
return (int) tmpLabel.getPreferredSize().getWidth() + 1;
}
private class LocalTabJTable extends JTable {
ManagedVmTableModel vmModel;
Border rendererBorder = new EmptyBorder(0, 6, 0, 6);
public LocalTabJTable(ManagedVmTableModel model) {
super(model);
this.vmModel = model;
// Remove vertical lines, expect for GTK L&F.
// (because GTK doesn't show header dividers)
if (!JConsole.IS_GTK) {
setShowVerticalLines(false);
setIntercellSpacing(new Dimension(0, 1));
}
// Double-click handler
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() == 2) {
connectButton.doClick();
}
}
});
// Enter should call default action
getActionMap().put("connect", connectAction);
InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "connect");
}
public String getToolTipText(MouseEvent e) {
String tip = null;
java.awt.Point p = e.getPoint();
int rowIndex = rowAtPoint(p);
int colIndex = columnAtPoint(p);
int realColumnIndex = convertColumnIndexToModel(colIndex);
if (realColumnIndex == COL_NAME) {
LocalVirtualMachine vmd = vmModel.vmAt(rowIndex);
tip = vmd.toString();
}
return tip;
}
public TableCellRenderer getCellRenderer(int row, int column) {
return new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
Component comp =
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
if (!isSelected) {
LocalVirtualMachine lvm = vmModel.vmAt(row);
if (!lvm.isManageable() && !lvm.isAttachable()) {
comp.setForeground(disabledTableCellColor);
}
}
if (comp instanceof JLabel) {
JLabel label = (JLabel)comp;
label.setBorder(rendererBorder);
if (value instanceof Integer) {
label.setHorizontalAlignment(JLabel.RIGHT);
}
}
return comp;
}
};
}
}
public void setConnectionParameters(String url,
String host,
int port,
String userName,
String password,
String msg) {
if ((url != null && url.length() > 0) ||
(host != null && host.length() > 0 && port > 0)) {
remoteRadioButton.setSelected(true);
if (url != null && url.length() > 0) {
remoteTF.setText(url);
} else {
remoteTF.setText(host+":"+port);
}
userNameTF.setText((userName != null) ? userName : "");
passwordTF.setText((password != null) ? password : "");
statusBar.setText((msg != null) ? msg : "");
if (getPreferredSize().width > getWidth()) {
pack();
}
remoteTF.requestFocus();
remoteTF.selectAll();
}
}
public void itemStateChanged(ItemEvent ev) {
if (!localRadioButton.isSelected()) {
vmTable.getSelectionModel().clearSelection();
}
updateButtonStates();
}
private void updateButtonStates() {
boolean connectEnabled = false;
if (remoteRadioButton.isSelected()) {
connectEnabled = JConsole.isValidRemoteString(remoteTF.getText());
} else if (localRadioButton != null && localRadioButton.isSelected()) {
int row = vmTable.getSelectedRow();
if (row >= 0) {
LocalVirtualMachine lvm = vmModel.vmAt(row);
connectEnabled = (lvm.isManageable() || lvm.isAttachable());
}
}
connectAction.setEnabled(connectEnabled);
}
public void insertUpdate(DocumentEvent e) {
updateButtonStates();
}
public void removeUpdate(DocumentEvent e) {
updateButtonStates();
}
public void changedUpdate(DocumentEvent e) {
updateButtonStates();
}
public void focusGained(FocusEvent e) {
Object source = e.getSource();
Component opposite = e.getOppositeComponent();
if (!e.isTemporary() &&
source instanceof JTextField &&
opposite instanceof JComponent &&
SwingUtilities.getRootPane(opposite) == getRootPane()) {
((JTextField)source).selectAll();
}
if (source == remoteTF) {
remoteRadioButton.setSelected(true);
} else if (source == vmTable) {
localRadioButton.setSelected(true);
if (vmModel.getRowCount() == 1) {
// if there's only one process then select the row
vmTable.setRowSelectionInterval(0, 0);
}
}
updateButtonStates();
}
public void focusLost(FocusEvent e) {
}
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if (c == KeyEvent.VK_ESCAPE) {
setVisible(false);
} else if (!(Character.isDigit(c) ||
c == KeyEvent.VK_BACK_SPACE ||
c == KeyEvent.VK_DELETE)) {
getToolkit().beep();
e.consume();
}
}
public void setVisible(boolean b) {
boolean wasVisible = isVisible();
super.setVisible(b);
if (b && !wasVisible) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (remoteRadioButton.isSelected()) {
remoteTF.requestFocus();
remoteTF.selectAll();
}
}
});
}
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
// ListSelectionListener interface
public void valueChanged(ListSelectionEvent e) {
updateButtonStates();
String labelText = " "; // Non-empty to reserve vertical space
int row = vmTable.getSelectedRow();
if (row >= 0) {
LocalVirtualMachine lvm = vmModel.vmAt(row);
if (!lvm.isManageable()) {
if (lvm.isAttachable()) {
labelText = Messages.MANAGEMENT_WILL_BE_ENABLED;
} else {
labelText = Messages.MANAGEMENT_NOT_ENABLED;
}
}
}
String colorStr =
String.format("%06x", hintTextColor.getRGB() & 0xFFFFFF);
localMessageLabel.setText("<html><font color=#" + colorStr + ">" + labelText);
}
// ----
// Refresh the list of managed VMs
public void refresh() {
if (vmModel != null) {
// Remember selection
LocalVirtualMachine selected = null;
int row = vmTable.getSelectedRow();
if (row >= 0) {
selected = vmModel.vmAt(row);
}
vmModel.refresh();
int selectRow = -1;
int n = vmModel.getRowCount();
if (selected != null) {
for (int i = 0; i < n; i++) {
LocalVirtualMachine lvm = vmModel.vmAt(i);
if (selected.vmid() == lvm.vmid() &&
selected.toString().equals(lvm.toString())) {
selectRow = i;
break;
}
}
}
if (selectRow > -1) {
vmTable.setRowSelectionInterval(selectRow, selectRow);
} else {
vmTable.getSelectionModel().clearSelection();
}
Dimension dim = vmTable.getPreferredSize();
// Tricky. Reduce height by one to avoid double line at bottom,
// but that causes a scroll bar to appear, so remove it.
dim.height = Math.min(dim.height-1, 100);
localTableScrollPane.setVerticalScrollBarPolicy((dim.height < 100)
? JScrollPane.VERTICAL_SCROLLBAR_NEVER
: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
localTableScrollPane.getViewport().setMinimumSize(dim);
localTableScrollPane.getViewport().setPreferredSize(dim);
}
pack();
setLocationRelativeTo(jConsole);
}
// Represents the list of managed VMs as a tabular data model.
private static class ManagedVmTableModel extends AbstractTableModel {
private static String[] columnNames = {
Messages.COLUMN_NAME,
Messages.COLUMN_PID,
};
private List<LocalVirtualMachine> vmList;
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int col) {
return columnNames[col];
}
public synchronized int getRowCount() {
return vmList.size();
}
public synchronized Object getValueAt(int row, int col) {
assert col >= 0 && col <= columnNames.length;
LocalVirtualMachine vm = vmList.get(row);
switch (col) {
case COL_NAME: return vm.displayName();
case COL_PID: return vm.vmid();
default: return null;
}
}
public Class<?> getColumnClass(int column) {
switch (column) {
case COL_NAME: return String.class;
case COL_PID: return Integer.class;
default: return super.getColumnClass(column);
}
}
public ManagedVmTableModel() {
refresh();
}
public synchronized LocalVirtualMachine vmAt(int pos) {
return vmList.get(pos);
}
public synchronized void refresh() {
Map<Integer, LocalVirtualMachine> map =
LocalVirtualMachine.getAllVirtualMachines();
vmList = new ArrayList<LocalVirtualMachine>();
vmList.addAll(map.values());
// data has changed
fireTableDataChanged();
}
}
// A blank component that takes up as much space as the
// button part of a JRadioButton.
private static class Padder extends JPanel {
JRadioButton radioButton;
Padder(JRadioButton radioButton) {
this.radioButton = radioButton;
setAccessibleName(this, Messages.BLANK);
}
public Dimension getPreferredSize() {
Rectangle r = getTextRectangle(radioButton);
int w = (r != null && r.x > 8) ? r.x : 22;
return new Dimension(w, 0);
}
private static Rectangle getTextRectangle(AbstractButton button) {
String text = button.getText();
Icon icon = (button.isEnabled()) ? button.getIcon() : button.getDisabledIcon();
if (icon == null && button.getUI() instanceof BasicRadioButtonUI) {
icon = ((BasicRadioButtonUI)button.getUI()).getDefaultIcon();
}
if ((icon == null) && (text == null)) {
return null;
}
Rectangle paintIconR = new Rectangle();
Rectangle paintTextR = new Rectangle();
Rectangle paintViewR = new Rectangle();
Insets paintViewInsets = new Insets(0, 0, 0, 0);
paintViewInsets = button.getInsets(paintViewInsets);
paintViewR.x = paintViewInsets.left;
paintViewR.y = paintViewInsets.top;
paintViewR.width = button.getWidth() - (paintViewInsets.left + paintViewInsets.right);
paintViewR.height = button.getHeight() - (paintViewInsets.top + paintViewInsets.bottom);
Graphics g = button.getGraphics();
if (g == null) {
return null;
}
SwingUtilities.layoutCompoundLabel(button,
g.getFontMetrics(),
text,
icon,
button.getVerticalAlignment(),
button.getHorizontalAlignment(),
button.getVerticalTextPosition(),
button.getHorizontalTextPosition(),
paintViewR,
paintIconR,
paintTextR,
button.getIconTextGap());
return paintTextR;
}
}
}

View File

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.TreeSet;
import java.util.Comparator;
import javax.swing.*;
import javax.swing.border.*;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
public class CreateMBeanDialog extends InternalDialog
implements ActionListener {
JConsole jConsole;
JComboBox<ProxyClient> connections;
JButton createMBeanButton, unregisterMBeanButton, cancelButton;
private static final String HOTSPOT_MBEAN =
"sun.management.HotspotInternal";
private static final String HOTSPOT_MBEAN_OBJECTNAME =
"sun.management:type=HotspotInternal";
public CreateMBeanDialog(JConsole jConsole) {
super(jConsole, "JConsole: Hotspot MBeans", true);
this.jConsole = jConsole;
setAccessibleDescription(this,
Messages.HOTSPOT_MBEANS_DIALOG_ACCESSIBLE_DESCRIPTION);
Container cp = getContentPane();
((JComponent)cp).setBorder(new EmptyBorder(10, 10, 4, 10));
JPanel centerPanel = new JPanel(new VariableGridLayout(0,
1,
4,
4,
false,
true));
cp.add(centerPanel, BorderLayout.CENTER);
connections = new JComboBox<ProxyClient>();
updateConnections();
centerPanel.add(new LabeledComponent(Resources.format(Messages.MANAGE_HOTSPOT_MBEANS_IN_COLON_),
connections));
JPanel bottomPanel = new JPanel(new BorderLayout());
cp.add(bottomPanel, BorderLayout.SOUTH);
JPanel buttonPanel = new JPanel();
bottomPanel.add(buttonPanel, BorderLayout.NORTH);
buttonPanel.add(createMBeanButton =
new JButton(Messages.CREATE));
buttonPanel.add(unregisterMBeanButton =
new JButton(Messages.UNREGISTER));
buttonPanel.add(cancelButton =
new JButton(Messages.CANCEL));
statusBar = new JLabel(" ", JLabel.CENTER);
bottomPanel.add(statusBar, BorderLayout.SOUTH);
createMBeanButton.addActionListener(this);
unregisterMBeanButton.addActionListener(this);
cancelButton.addActionListener(this);
LabeledComponent.layout(centerPanel);
pack();
setLocationRelativeTo(jConsole);
}
private void updateConnections() {
List<VMInternalFrame> frames = jConsole.getInternalFrames();
TreeSet<ProxyClient> data =
new TreeSet<ProxyClient>(new Comparator<ProxyClient>() {
public int compare(ProxyClient o1, ProxyClient o2) {
// TODO: Need to understand how this method being used?
return o1.connectionName().compareTo(o2.connectionName());
}
});
if (frames.size() == 0) {
JComponent cp = (JComponent)jConsole.getContentPane();
Component comp = ((BorderLayout)cp.getLayout()).
getLayoutComponent(BorderLayout.CENTER);
if (comp instanceof VMPanel) {
VMPanel vmpanel = (VMPanel) comp;
ProxyClient client = vmpanel.getProxyClient(false);
if (client != null && client.hasPlatformMXBeans()) {
data.add(client);
}
}
} else {
for (VMInternalFrame f : frames) {
ProxyClient client = f.getVMPanel().getProxyClient(false);
if (client != null && client.hasPlatformMXBeans()) {
data.add(client);
}
}
}
connections.invalidate();
connections.setModel(new DefaultComboBoxModel<ProxyClient>
(data.toArray(new ProxyClient[data.size()])));
connections.validate();
}
public void actionPerformed(final ActionEvent ev) {
setVisible(false);
statusBar.setText("");
if (ev.getSource() != cancelButton) {
new Thread("CreateMBeanDialog.actionPerformed") {
public void run() {
try {
Object c = connections.getSelectedItem();
if(c == null) return;
if(ev.getSource() == createMBeanButton) {
MBeanServerConnection connection =
((ProxyClient) c).
getMBeanServerConnection();
connection.createMBean(HOTSPOT_MBEAN, null);
} else {
if(ev.getSource() == unregisterMBeanButton) {
MBeanServerConnection connection =
((ProxyClient) c).
getMBeanServerConnection();
connection.unregisterMBean(new
ObjectName(HOTSPOT_MBEAN_OBJECTNAME));
}
}
return;
} catch(InstanceAlreadyExistsException e) {
statusBar.setText(Messages.ERROR_COLON_MBEANS_ALREADY_EXIST);
} catch(InstanceNotFoundException e) {
statusBar.setText(Messages.ERROR_COLON_MBEANS_DO_NOT_EXIST);
} catch(Exception e) {
statusBar.setText(e.toString());
}
setVisible(true);
}
}.start();
}
}
public void setVisible(boolean b) {
boolean wasVisible = isVisible();
if(b) {
setLocationRelativeTo(jConsole);
invalidate();
updateConnections();
validate();
repaint();
}
super.setVisible(b);
if (b && !wasVisible) {
// Need to delay this to make focus stick
SwingUtilities.invokeLater(new Runnable() {
public void run() {
connections.requestFocus();
}
});
}
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2013, 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 sun.tools.jconsole;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import com.sun.tools.jconsole.JConsolePlugin;
/**
* Proxy that shields GUI from plug-in exceptions.
*
*/
final class ExceptionSafePlugin extends JConsolePlugin {
private static boolean ignoreExceptions;
private final JConsolePlugin plugin;
public ExceptionSafePlugin(JConsolePlugin plugin) {
this.plugin = plugin;
}
@Override
public Map<String, JPanel> getTabs() {
try {
return plugin.getTabs();
} catch (RuntimeException e) {
handleException(e);
}
return new HashMap<>();
}
@Override
public SwingWorker<?, ?> newSwingWorker() {
try {
return plugin.newSwingWorker();
} catch (RuntimeException e) {
handleException(e);
}
return null;
}
@Override
public void dispose() {
try {
plugin.dispose();
} catch (RuntimeException e) {
handleException(e);
}
}
public void executeSwingWorker(SwingWorker<?, ?> sw) {
try {
sw.execute();
} catch (RuntimeException e) {
handleException(e);
}
}
private void handleException(Exception e) {
if (JConsole.isDebug()) {
System.err.println("Plug-in exception:");
e.printStackTrace();
} else {
if (!ignoreExceptions) {
showExceptionDialog(e);
}
}
}
private void showExceptionDialog(Exception e) {
Object[] buttonTexts = {
Messages.PLUGIN_EXCEPTION_DIALOG_BUTTON_OK,
Messages.PLUGIN_EXCEPTION_DIALOG_BUTTON_EXIT,
Messages.PLUGIN_EXCEPTION_DIALOG_BUTTON_IGNORE
};
String message = String.format(
Messages.PLUGIN_EXCEPTION_DIALOG_MESSAGE,
plugin.getClass().getSimpleName(),
String.valueOf(e.getMessage())
);
int buttonIndex = JOptionPane.showOptionDialog(
null,
message,
Messages.PLUGIN_EXCEPTION_DIALOG_TITLE,
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
buttonTexts,
buttonTexts[0]
);
if (buttonIndex == 1) {
System.exit(0);
}
ignoreExceptions = buttonIndex == 2;
}
}

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.text.*;
import java.util.*;
class Formatter {
final static long SECOND = 1000;
final static long MINUTE = 60 * SECOND;
final static long HOUR = 60 * MINUTE;
final static long DAY = 24 * HOUR;
final static String cr = System.getProperty("line.separator");
final static DateFormat timeDF = new SimpleDateFormat("HH:mm");
private final static DateFormat timeWithSecondsDF = new SimpleDateFormat("HH:mm:ss");
private final static DateFormat dateDF = new SimpleDateFormat("yyyy-MM-dd");
private final static String decimalZero =
new DecimalFormatSymbols().getDecimalSeparator() + "0";
static String formatTime(long t) {
String str;
if (t < 1 * MINUTE) {
String seconds = String.format("%.3f", t / (double)SECOND);
str = Resources.format(Messages.DURATION_SECONDS, seconds);
} else {
long remaining = t;
long days = remaining / DAY;
remaining %= 1 * DAY;
long hours = remaining / HOUR;
remaining %= 1 * HOUR;
long minutes = remaining / MINUTE;
if (t >= 1 * DAY) {
str = Resources.format(Messages.DURATION_DAYS_HOURS_MINUTES,
days, hours, minutes);
} else if (t >= 1 * HOUR) {
str = Resources.format(Messages.DURATION_HOURS_MINUTES,
hours, minutes);
} else {
str = Resources.format(Messages.DURATION_MINUTES, minutes);
}
}
return str;
}
static String formatNanoTime(long t) {
long ms = t / 1000000;
return formatTime(ms);
}
static String formatClockTime(long time) {
return timeDF.format(time);
}
static String formatDate(long time) {
return dateDF.format(time);
}
static String formatDateTime(long time) {
return dateDF.format(time) + " " + timeWithSecondsDF.format(time);
}
static DateFormat getDateTimeFormat(String dtfStr) {
int dateStyle = -1;
int timeStyle = -1;
if (dtfStr.startsWith("SHORT")) {
dateStyle = DateFormat.SHORT;
} else if (dtfStr.startsWith("MEDIUM")) {
dateStyle = DateFormat.MEDIUM;
} else if (dtfStr.startsWith("LONG")) {
dateStyle = DateFormat.LONG;
} else if (dtfStr.startsWith("FULL")) {
dateStyle = DateFormat.FULL;
}
if (dtfStr.endsWith("SHORT")) {
timeStyle = DateFormat.SHORT;
} else if (dtfStr.endsWith("MEDIUM")) {
timeStyle = DateFormat.MEDIUM;
} else if (dtfStr.endsWith("LONG")) {
timeStyle = DateFormat.LONG;
} else if (dtfStr.endsWith("FULL")) {
timeStyle = DateFormat.FULL;
}
if (dateStyle != -1 && timeStyle != -1) {
return DateFormat.getDateTimeInstance(dateStyle, timeStyle);
} else if (dtfStr.length() > 0) {
return new SimpleDateFormat(dtfStr);
} else {
return DateFormat.getDateTimeInstance();
}
}
static double toExcelTime(long time) {
// Excel is bug compatible with Lotus 1-2-3 and pretends
// that 1900 was a leap year, so count from 1899-12-30.
// Note that the month index is zero-based in Calendar.
Calendar cal = new GregorianCalendar(1899, 11, 30);
// Adjust for the fact that now may be DST but then wasn't
Calendar tmpCal = new GregorianCalendar();
tmpCal.setTimeInMillis(time);
int dst = tmpCal.get(Calendar.DST_OFFSET);
if (dst > 0) {
cal.set(Calendar.DST_OFFSET, dst);
}
long millisSince1900 = time - cal.getTimeInMillis();
double value = (double)millisSince1900 / (24 * 60 * 60 * 1000);
return value;
}
static String[] formatKByteStrings(long... bytes) {
int n = bytes.length;
for (int i = 0; i < n; i++) {
if (bytes[i] > 0) {
bytes[i] /= 1024;
}
}
String[] strings = formatLongs(bytes);
for (int i = 0; i < n; i++) {
strings[i] = Resources.format(Messages.KBYTES, strings[i]);
}
return strings;
}
static String formatKBytes(long bytes) {
if (bytes == -1) {
return Resources.format(Messages.KBYTES, "-1");
}
long kb = bytes / 1024;
return Resources.format(Messages.KBYTES, justify(kb, 10));
}
static String formatBytes(long v, boolean html) {
return formatBytes(v, v, html);
}
static String formatBytes(long v, long vMax) {
return formatBytes(v, vMax, false);
}
static String formatBytes(long v, long vMax, boolean html) {
String s;
int exp = (int)Math.log10((double)vMax);
if (exp < 3) {
s = Resources.format(Messages.SIZE_BYTES, v);
} else if (exp < 6) {
s = Resources.format(Messages.SIZE_KB, trimDouble(v / Math.pow(10.0, 3)));
} else if (exp < 9) {
s = Resources.format(Messages.SIZE_MB, trimDouble(v / Math.pow(10.0, 6)));
} else {
s = Resources.format(Messages.SIZE_GB, trimDouble(v / Math.pow(10.0, 9)));
}
if (html) {
s = s.replace(" ", "&nbsp;");
}
return s;
}
/*
* Return the input value rounded to one decimal place. If after
* rounding the string ends in the (locale-specific) decimal point
* followed by a zero then trim that off as well.
*/
private static String trimDouble(double d) {
String s = String.format("%.1f", d);
if (s.length() > 3 && s.endsWith(decimalZero)) {
s = s.substring(0, s.length()-2);
}
return s;
}
static String formatLong(long value) {
return String.format("%,d", value);
}
static String[] formatLongs(long... longs) {
int n = longs.length;
int size = 0;
String[] strings = new String[n];
for (int i = 0; i < n; i++) {
strings[i] = formatLong(longs[i]);
size = Math.max(size, strings[i].length());
}
for (int i = 0; i < n; i++) {
strings[i] = justify(strings[i], size);
}
return strings;
}
// A poor attempt at right-justifying for numerical data
static String justify(long value, int size) {
return justify(formatLong(value), size);
}
static String justify(String str, int size) {
StringBuffer buf = new StringBuffer();
buf.append("<TT>");
int n = size - str.length();
for (int i = 0; i < n; i++) {
buf.append("&nbsp;");
}
buf.append(str);
buf.append("</TT>");
return buf.toString();
}
static String newRow(String label, String value) {
return newRow(label, value, 2);
}
static String newRow(String label, String value, int columnPerRow) {
if (label == null) {
label = "";
} else {
label += ":&nbsp;";
}
label = "<th nowrap align=right valign=top>" + label;
value = "<td colspan=" + (columnPerRow-1) + "> <font size =-1>" + value;
return "<tr>" + label + value + "</tr>";
}
static String newRow(String label1, String value1,
String label2, String value2) {
label1 = "<th nowrap align=right valign=top>" + label1 + ":&nbsp;";
value1 = "<td><font size =-1>" + value1;
label2 = "<th nowrap align=right valign=top>" + label2 + ":&nbsp;";
value2 = "<td><font size =-1>" + value2;
return "<tr>" + label1 + value1 + label2 + value2 + "</tr>";
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2006, 2012, 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 sun.tools.jconsole;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
@SuppressWarnings("serial")
public class HTMLPane extends JEditorPane {
private boolean hasSelection = false;
public HTMLPane() {
setContentType("text/html");
setEditable(false);
((DefaultCaret)getCaret()).setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
addCaretListener(new CaretListener() {
// Listen for selection changes
public void caretUpdate(CaretEvent e) {
setHasSelection(e.getDot() != e.getMark());
}
});
}
public synchronized void setHasSelection(boolean b) {
hasSelection = b;
}
public synchronized boolean getHasSelection() {
return hasSelection;
}
public void setText(String text) {
// Apply update only if a selection is not active
if (!getHasSelection()) {
// JEditorPane does not automatically pick up fg color
String textColor =
String.format("%06x", getForeground().getRGB() & 0xFFFFFF);
super.setText("<html><body text=#"+textColor+">" + text + "</body></html>");
}
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2005, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import static javax.swing.JLayeredPane.*;
/**
* Used instead of JDialog in a JDesktopPane/JInternalFrame environment.
*/
@SuppressWarnings("serial")
public class InternalDialog extends JInternalFrame {
protected JLabel statusBar;
public InternalDialog(JConsole jConsole, String title, boolean modal) {
super(title, true, true, false, false);
setLayer(PALETTE_LAYER);
putClientProperty("JInternalFrame.frameType", "optionDialog");
jConsole.getDesktopPane().add(this);
getActionMap().put("cancel", new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
setVisible(false);
if (statusBar != null) {
statusBar.setText("");
}
}
});
InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel");
}
public void setLocationRelativeTo(Component c) {
setLocation((c.getWidth() - getWidth()) / 2,
(c.getHeight() - getHeight()) / 2);
}
protected class MastheadIcon implements Icon {
// Important: Assume image background is white!
private ImageIcon leftIcon =
new ImageIcon(InternalDialog.class.getResource("resources/masthead-left.png"));
private ImageIcon rightIcon =
new ImageIcon(InternalDialog.class.getResource("resources/masthead-right.png"));
private Font font = Font.decode(Messages.MASTHEAD_FONT);
private int gap = 10;
private String title;
public MastheadIcon(String title) {
this.title = title;
}
public synchronized void paintIcon(Component c, Graphics g, int x, int y) {
// Clone the Graphics object
g = g.create();
// Ignore x to make sure we fill entire component width
x = 0;
int width = c.getWidth();
int lWidth = leftIcon.getIconWidth();
int rWidth = rightIcon.getIconWidth();
int height = getIconHeight();
int textHeight = g.getFontMetrics(font).getAscent();
g.setColor(Color.white);
g.fillRect(x, y, width, height);
leftIcon.paintIcon(c, g, x, y);
rightIcon.paintIcon(c, g, width - rWidth, y);
g.setFont(font);
((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setColor(new Color(0x35556b));
g.drawString(title, lWidth + gap, height/2 + textHeight/2);
}
public int getIconWidth() {
int textWidth = 0;
Graphics g = getGraphics();
if (g != null) {
FontMetrics fm = g.getFontMetrics(font);
if (fm != null) {
textWidth = fm.stringWidth(title);
}
}
return (leftIcon.getIconWidth() + gap + textWidth +
gap + rightIcon.getIconWidth());
}
public int getIconHeight() {
return leftIcon.getIconHeight();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class LabeledComponent extends JPanel {
JPanel rightPanel;
String labelStr, valueLabelStr, compoundStr;
JLabel label;
JComponent comp;
public LabeledComponent(String text, JComponent comp) {
this(text, 0, comp);
}
public LabeledComponent(String text, int mnemonic, JComponent comp) {
super(new BorderLayout(6, 6));
this.labelStr = text;
this.label = new JLabel(text, JLabel.RIGHT);
this.comp = comp;
label.setLabelFor(comp);
if (mnemonic > 0) {
label.setDisplayedMnemonic(mnemonic);
}
add(label, BorderLayout.WEST);
add(comp, BorderLayout.CENTER);
}
public void setLabel(String str) {
this.labelStr = str;
updateLabel();
}
public void setValueLabel(String str) {
this.valueLabelStr = str;
updateLabel();
}
private void updateLabel() {
String str = labelStr;
label.setText(str);
this.compoundStr = str;
JComponent container = (JComponent)getParent();
LabeledComponent.layout(container);
}
public static void layout(Container container) {
int wMax = 0;
for (Component c : container.getComponents()) {
if (c instanceof LabeledComponent) {
LabeledComponent lc = (LabeledComponent)c;
lc.label.setPreferredSize(null);
// int w = lc.label.getMinimumSize().width;
int w = lc.label.getPreferredSize().width;
if (w > wMax) {
wMax = w;
}
}
}
for (Component c : container.getComponents()) {
if (c instanceof LabeledComponent) {
LabeledComponent lc = (LabeledComponent)c;
JLabel label = lc.label;
int h = label.getPreferredSize().height;
label.setPreferredSize(new Dimension(wMax, h));
label.setHorizontalAlignment(JLabel.RIGHT);
}
}
}
}

View File

@@ -0,0 +1,247 @@
/*
* Copyright (c) 2005, 2014, 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 sun.tools.jconsole;
import java.util.*;
import java.io.IOException;
import java.io.File;
// Sun specific
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import com.sun.tools.attach.AttachNotSupportedException;
// Sun private
import sun.management.ConnectorAddressLink;
import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.MonitorException;
import sun.jvmstat.monitor.VmIdentifier;
public class LocalVirtualMachine {
private String address;
private String commandLine;
private String displayName;
private int vmid;
private boolean isAttachSupported;
public LocalVirtualMachine(int vmid, String commandLine, boolean canAttach, String connectorAddress) {
this.vmid = vmid;
this.commandLine = commandLine;
this.address = connectorAddress;
this.isAttachSupported = canAttach;
this.displayName = getDisplayName(commandLine);
}
private static String getDisplayName(String commandLine) {
// trim the pathname of jar file if it's a jar
String[] res = commandLine.split(" ", 2);
if (res[0].endsWith(".jar")) {
File jarfile = new File(res[0]);
String displayName = jarfile.getName();
if (res.length == 2) {
displayName += " " + res[1];
}
return displayName;
}
return commandLine;
}
public int vmid() {
return vmid;
}
public boolean isManageable() {
return (address != null);
}
public boolean isAttachable() {
return isAttachSupported;
}
public void startManagementAgent() throws IOException {
if (address != null) {
// already started
return;
}
if (!isAttachable()) {
throw new IOException("This virtual machine \"" + vmid +
"\" does not support dynamic attach.");
}
loadManagementAgent();
// fails to load or start the management agent
if (address == null) {
// should never reach here
throw new IOException("Fails to find connector address");
}
}
public String connectorAddress() {
// return null if not available or no JMX agent
return address;
}
public String displayName() {
return displayName;
}
public String toString() {
return commandLine;
}
// This method returns the list of all virtual machines currently
// running on the machine
public static Map<Integer, LocalVirtualMachine> getAllVirtualMachines() {
Map<Integer, LocalVirtualMachine> map =
new HashMap<Integer, LocalVirtualMachine>();
getMonitoredVMs(map);
getAttachableVMs(map);
return map;
}
private static void getMonitoredVMs(Map<Integer, LocalVirtualMachine> map) {
MonitoredHost host;
Set<Integer> vms;
try {
host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null));
vms = host.activeVms();
} catch (java.net.URISyntaxException | MonitorException x) {
throw new InternalError(x.getMessage(), x);
}
for (Object vmid: vms) {
if (vmid instanceof Integer) {
int pid = ((Integer) vmid).intValue();
String name = vmid.toString(); // default to pid if name not available
boolean attachable = false;
String address = null;
try {
MonitoredVm mvm = host.getMonitoredVm(new VmIdentifier(name));
// use the command line as the display name
name = MonitoredVmUtil.commandLine(mvm);
attachable = MonitoredVmUtil.isAttachable(mvm);
address = ConnectorAddressLink.importFrom(pid);
mvm.detach();
} catch (Exception x) {
// ignore
}
map.put((Integer) vmid,
new LocalVirtualMachine(pid, name, attachable, address));
}
}
}
private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
"com.sun.management.jmxremote.localConnectorAddress";
private static void getAttachableVMs(Map<Integer, LocalVirtualMachine> map) {
List<VirtualMachineDescriptor> vms = VirtualMachine.list();
for (VirtualMachineDescriptor vmd : vms) {
try {
Integer vmid = Integer.valueOf(vmd.id());
if (!map.containsKey(vmid)) {
boolean attachable = false;
String address = null;
try {
VirtualMachine vm = VirtualMachine.attach(vmd);
attachable = true;
Properties agentProps = vm.getAgentProperties();
address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
vm.detach();
} catch (AttachNotSupportedException x) {
// not attachable
} catch (IOException x) {
// ignore
}
map.put(vmid, new LocalVirtualMachine(vmid.intValue(),
vmd.displayName(),
attachable,
address));
}
} catch (NumberFormatException e) {
// do not support vmid different than pid
}
}
}
public static LocalVirtualMachine getLocalVirtualMachine(int vmid) {
Map<Integer, LocalVirtualMachine> map = getAllVirtualMachines();
LocalVirtualMachine lvm = map.get(vmid);
if (lvm == null) {
// Check if the VM is attachable but not included in the list
// if it's running with a different security context.
// For example, Windows services running
// local SYSTEM account are attachable if you have Adminstrator
// privileges.
boolean attachable = false;
String address = null;
String name = String.valueOf(vmid); // default display name to pid
try {
VirtualMachine vm = VirtualMachine.attach(name);
attachable = true;
Properties agentProps = vm.getAgentProperties();
address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
vm.detach();
lvm = new LocalVirtualMachine(vmid, name, attachable, address);
} catch (AttachNotSupportedException x) {
// not attachable
if (JConsole.isDebug()) {
x.printStackTrace();
}
} catch (IOException x) {
// ignore
if (JConsole.isDebug()) {
x.printStackTrace();
}
}
}
return lvm;
}
// load the management agent into the target VM
private void loadManagementAgent() throws IOException {
VirtualMachine vm = null;
String name = String.valueOf(vmid);
try {
vm = VirtualMachine.attach(name);
} catch (AttachNotSupportedException x) {
IOException ioe = new IOException(x.getMessage());
ioe.initCause(x);
throw ioe;
}
vm.startLocalManagementAgent();
// get the connector address
Properties agentProps = vm.getAgentProperties();
address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
vm.detach();
}
}

View File

@@ -0,0 +1,281 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.*;
import java.io.*;
import java.util.Set;
import javax.management.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import sun.tools.jconsole.ProxyClient.SnapshotMBeanServerConnection;
import sun.tools.jconsole.inspector.*;
import com.sun.tools.jconsole.JConsoleContext;
@SuppressWarnings("serial")
public class MBeansTab extends Tab implements
NotificationListener, PropertyChangeListener,
TreeSelectionListener, TreeWillExpandListener {
private XTree tree;
private XSheet sheet;
private XDataViewer viewer;
public static String getTabName() {
return Messages.MBEANS;
}
public MBeansTab(final VMPanel vmPanel) {
super(vmPanel, getTabName());
addPropertyChangeListener(this);
setupTab();
}
public XDataViewer getDataViewer() {
return viewer;
}
public XTree getTree() {
return tree;
}
public XSheet getSheet() {
return sheet;
}
@Override
public void dispose() {
super.dispose();
sheet.dispose();
}
public int getUpdateInterval() {
return vmPanel.getUpdateInterval();
}
private void buildMBeanServerView() {
new SwingWorker<Set<ObjectName>, Void>() {
@Override
public Set<ObjectName> doInBackground() {
// Register listener for MBean registration/unregistration
//
try {
getMBeanServerConnection().addNotificationListener(
MBeanServerDelegate.DELEGATE_NAME,
MBeansTab.this,
null,
null);
} catch (InstanceNotFoundException e) {
// Should never happen because the MBeanServerDelegate
// is always present in any standard MBeanServer
//
if (JConsole.isDebug()) {
e.printStackTrace();
}
} catch (IOException e) {
if (JConsole.isDebug()) {
e.printStackTrace();
}
vmPanel.getProxyClient().markAsDead();
return null;
}
// Retrieve MBeans from MBeanServer
//
Set<ObjectName> mbeans = null;
try {
mbeans = getMBeanServerConnection().queryNames(null, null);
} catch (IOException e) {
if (JConsole.isDebug()) {
e.printStackTrace();
}
vmPanel.getProxyClient().markAsDead();
return null;
}
return mbeans;
}
@Override
protected void done() {
try {
// Wait for mbsc.queryNames() result
Set<ObjectName> mbeans = get();
// Do not display anything until the new tree has been built
//
tree.setVisible(false);
// Cleanup current tree
//
tree.removeAll();
// Add MBeans to tree
//
tree.addMBeansToView(mbeans);
// Display the new tree
//
tree.setVisible(true);
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem at MBean tree construction");
t.printStackTrace();
}
}
}
}.execute();
}
public MBeanServerConnection getMBeanServerConnection() {
return vmPanel.getProxyClient().getMBeanServerConnection();
}
public SnapshotMBeanServerConnection getSnapshotMBeanServerConnection() {
return vmPanel.getProxyClient().getSnapshotMBeanServerConnection();
}
@Override
public void update() {
// Ping the connection to see if it is still alive. At
// some point the ProxyClient class should centralize
// the connection aliveness monitoring and no longer
// rely on the custom tabs to ping the connections.
//
try {
getMBeanServerConnection().getDefaultDomain();
} catch (IOException ex) {
vmPanel.getProxyClient().markAsDead();
}
}
private void setupTab() {
// set up the split pane with the MBean tree and MBean sheet panels
setLayout(new BorderLayout());
JSplitPane mainSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
mainSplit.setDividerLocation(160);
mainSplit.setBorder(BorderFactory.createEmptyBorder());
// set up the MBean tree panel (left pane)
tree = new XTree(this);
tree.setCellRenderer(new XTreeRenderer());
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addTreeSelectionListener(this);
tree.addTreeWillExpandListener(this);
tree.addMouseListener(ml);
JScrollPane theScrollPane = new JScrollPane(
tree,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JPanel treePanel = new JPanel(new BorderLayout());
treePanel.add(theScrollPane, BorderLayout.CENTER);
mainSplit.add(treePanel, JSplitPane.LEFT, 0);
// set up the MBean sheet panel (right pane)
viewer = new XDataViewer(this);
sheet = new XSheet(this);
mainSplit.add(sheet, JSplitPane.RIGHT, 0);
add(mainSplit);
}
/* notification listener: handleNotification */
public void handleNotification(
final Notification notification, Object handback) {
EventQueue.invokeLater(new Runnable() {
public void run() {
if (notification instanceof MBeanServerNotification) {
ObjectName mbean =
((MBeanServerNotification) notification).getMBeanName();
if (notification.getType().equals(
MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
tree.addMBeanToView(mbean);
} else if (notification.getType().equals(
MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
tree.removeMBeanFromView(mbean);
}
}
}
});
}
/* property change listener: propertyChange */
public void propertyChange(PropertyChangeEvent evt) {
if (JConsoleContext.CONNECTION_STATE_PROPERTY.equals(evt.getPropertyName())) {
boolean connected = (Boolean) evt.getNewValue();
if (connected) {
buildMBeanServerView();
} else {
sheet.dispose();
}
}
}
/* tree selection listener: valueChanged */
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
sheet.displayNode(node);
}
/* tree mouse listener: mousePressed */
private MouseListener ml = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (e.getClickCount() == 1) {
int selRow = tree.getRowForLocation(e.getX(), e.getY());
if (selRow != -1) {
TreePath selPath =
tree.getPathForLocation(e.getX(), e.getY());
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) selPath.getLastPathComponent();
if (sheet.isMBeanNode(node)) {
tree.expandPath(selPath);
}
}
}
}
};
/* tree will expand listener: treeWillExpand */
public void treeWillExpand(TreeExpansionEvent e)
throws ExpandVetoException {
TreePath path = e.getPath();
if (!tree.hasBeenExpanded(path)) {
DefaultMutableTreeNode node =
(DefaultMutableTreeNode) path.getLastPathComponent();
if (sheet.isMBeanNode(node) && !tree.hasMetadataNodes(node)) {
tree.addMetadataNodes(node);
}
}
}
/* tree will expand listener: treeWillCollapse */
public void treeWillCollapse(TreeExpansionEvent e)
throws ExpandVetoException {
}
}

View File

@@ -0,0 +1,345 @@
/*
* Copyright (c) 2006, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import java.beans.*;
import java.lang.reflect.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
/**
* This class is a temporary workaround for bug 4834918:
* Win L&F: JInternalFrame should merge with JMenuBar when maximized.
* It is not a general solution, but intended for use within the
* limited scope of JConsole when running with XP/Vista styles.
*/
@SuppressWarnings("serial")
public class MaximizableInternalFrame extends JInternalFrame {
private boolean isXP;
private JFrame mainFrame;
private JMenuBar mainMenuBar;
private String mainTitle;
private JComponent titlePane;
private Border normalBorder;
private PropertyChangeListener pcl;
public MaximizableInternalFrame(String title, boolean resizable,
boolean closable, boolean maximizable,
boolean iconifiable) {
super(title, resizable, closable, maximizable, iconifiable);
init();
}
private void init() {
normalBorder = getBorder();
isXP = normalBorder.getClass().getName().endsWith("XPBorder");
if (isXP) {
setRootPaneCheckingEnabled(false);
titlePane = ((BasicInternalFrameUI)getUI()).getNorthPane();
if (pcl == null) {
pcl = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
String prop = ev.getPropertyName();
if (prop.equals("icon") ||
prop.equals("maximum") ||
prop.equals("closed")) {
updateFrame();
}
}
};
addPropertyChangeListener(pcl);
}
} else if (pcl != null) {
removePropertyChangeListener(pcl);
pcl = null;
}
}
private void updateFrame() {
JFrame mainFrame;
if (!isXP || (mainFrame = getMainFrame()) == null) {
return;
}
JMenuBar menuBar = getMainMenuBar();
BasicInternalFrameUI ui = (BasicInternalFrameUI)getUI();
if (isMaximum() && !isIcon() && !isClosed()) {
if (ui.getNorthPane() != null) {
// Merge title bar into menu bar
mainTitle = mainFrame.getTitle();
mainFrame.setTitle(mainTitle + " - " + getTitle());
if (menuBar != null) {
// Move buttons to menu bar
updateButtonStates();
menuBar.add(Box.createGlue());
for (Component c : titlePane.getComponents()) {
if (c instanceof JButton) {
menuBar.add(c);
} else if (c instanceof JLabel) {
// This is the system menu icon
menuBar.add(Box.createHorizontalStrut(3), 0);
menuBar.add(c, 1);
menuBar.add(Box.createHorizontalStrut(3), 2);
}
}
ui.setNorthPane(null);
setBorder(null);
}
}
} else {
if (ui.getNorthPane() == null) {
// Restore title bar
mainFrame.setTitle(mainTitle);
if (menuBar != null) {
// Move buttons back to title bar
for (Component c : menuBar.getComponents()) {
if (c instanceof JButton || c instanceof JLabel) {
titlePane.add(c);
} else if (c instanceof Box.Filler) {
menuBar.remove(c);
}
}
menuBar.repaint();
updateButtonStates();
ui.setNorthPane(titlePane);
setBorder(normalBorder);
}
}
}
}
public void updateUI() {
boolean isMax = (isXP && getBorder() == null);
if (isMax) {
try {
setMaximum(false);
} catch (PropertyVetoException ex) { }
}
super.updateUI();
init();
if (isMax) {
try {
setMaximum(true);
} catch (PropertyVetoException ex) { }
}
}
private JFrame getMainFrame() {
if (mainFrame == null) {
JDesktopPane desktop = getDesktopPane();
if (desktop != null) {
mainFrame = (JFrame)SwingUtilities.getWindowAncestor(desktop);
}
}
return mainFrame;
}
private JMenuBar getMainMenuBar() {
if (mainMenuBar == null) {
JFrame mainFrame = getMainFrame();
if (mainFrame != null) {
mainMenuBar = mainFrame.getJMenuBar();
if (mainMenuBar != null &&
!(mainMenuBar.getLayout() instanceof FixedMenuBarLayout)) {
mainMenuBar.setLayout(new FixedMenuBarLayout(mainMenuBar,
BoxLayout.X_AXIS));
}
}
}
return mainMenuBar;
}
public void setTitle(String title) {
if (isXP && isMaximum()) {
if (getMainFrame() != null) {
getMainFrame().setTitle(mainTitle + " - " + title);
}
}
super.setTitle(title);
}
private class FixedMenuBarLayout extends BoxLayout {
public FixedMenuBarLayout(Container target, int axis) {
super(target, axis);
}
public void layoutContainer(Container target) {
super.layoutContainer(target);
for (Component c : target.getComponents()) {
if (c instanceof JButton) {
int y = (target.getHeight() - c.getHeight()) / 2;
c.setLocation(c.getX(), Math.max(2, y));
}
}
}
}
// The rest of this class is messy and should not be relied upon. It
// uses reflection to access private, undocumented, and unsupported
// classes and fields.
//
// Install icon wrappers to display MDI icons when the buttons
// are in the menubar.
//
// Please note that this will very likely fail in a future version
// of Swing, but at least it should fail silently.
//
private static Object WP_MINBUTTON, WP_RESTOREBUTTON, WP_CLOSEBUTTON,
WP_MDIMINBUTTON, WP_MDIRESTOREBUTTON, WP_MDICLOSEBUTTON;
static {
if (JConsole.IS_WIN) {
try {
Class<?> Part =
Class.forName("com.sun.java.swing.plaf.windows.TMSchema$Part");
if (Part != null) {
WP_MINBUTTON = Part.getField("WP_MINBUTTON").get(null);
WP_RESTOREBUTTON = Part.getField("WP_RESTOREBUTTON").get(null);
WP_CLOSEBUTTON = Part.getField("WP_CLOSEBUTTON").get(null);
WP_MDIMINBUTTON = Part.getField("WP_MDIMINBUTTON").get(null);
WP_MDIRESTOREBUTTON = Part.getField("WP_MDIRESTOREBUTTON").get(null);
WP_MDICLOSEBUTTON = Part.getField("WP_MDICLOSEBUTTON").get(null);
}
for (String str : new String[] { "maximize", "minimize",
"iconify", "close" }) {
String key = "InternalFrame." + str + "Icon";
UIManager.put(key,
new MDIButtonIcon(UIManager.getIcon(key)));
}
} catch (ClassNotFoundException ex) {
if (JConsole.debug) {
ex.printStackTrace();
}
} catch (NoSuchFieldException ex) {
if (JConsole.debug) {
ex.printStackTrace();
}
} catch (IllegalAccessException ex) {
if (JConsole.debug) {
ex.printStackTrace();
}
}
}
}
// A wrapper class for the title pane button icons.
// This code should really go in the WindowsIconsFactory class.
private static class MDIButtonIcon implements Icon {
Icon windowsIcon;
Field part;
MDIButtonIcon(Icon icon) {
windowsIcon = icon;
if (WP_MINBUTTON != null) {
try {
part = windowsIcon.getClass().getDeclaredField("part");
part.setAccessible(true);
} catch (NoSuchFieldException ex) {
if (JConsole.debug) {
ex.printStackTrace();
}
}
}
}
public void paintIcon(Component c, Graphics g, int x, int y) {
if (part != null) {
try {
Object v = part.get(windowsIcon);
if (c.getParent() instanceof JMenuBar) {
// Use MDI icons
if (v == WP_MINBUTTON) {
part.set(windowsIcon, WP_MDIMINBUTTON);
} else if (v == WP_RESTOREBUTTON) {
part.set(windowsIcon, WP_MDIRESTOREBUTTON);
} else if (v == WP_CLOSEBUTTON) {
part.set(windowsIcon, WP_MDICLOSEBUTTON);
}
} else {
// Use regular icons
if (v == WP_MDIMINBUTTON) {
part.set(windowsIcon, WP_MINBUTTON);
} else if (v == WP_MDIRESTOREBUTTON) {
part.set(windowsIcon, WP_RESTOREBUTTON);
} else if (v == WP_MDICLOSEBUTTON) {
part.set(windowsIcon, WP_CLOSEBUTTON);
}
}
} catch (IllegalAccessException ex) {
if (JConsole.debug) {
ex.printStackTrace();
}
}
}
windowsIcon.paintIcon(c, g, x, y);
}
public int getIconWidth(){
return windowsIcon.getIconWidth();
}
public int getIconHeight() {
return windowsIcon.getIconHeight();
}
}
// Use reflection to invoke protected methods in BasicInternalFrameTitlePane
private Method setButtonIcons;
private Method enableActions;
private void updateButtonStates() {
try {
if (setButtonIcons == null) {
Class<? extends JComponent> cls = titlePane.getClass();
Class<?> superCls = cls.getSuperclass();
setButtonIcons = cls.getDeclaredMethod("setButtonIcons");
enableActions = superCls.getDeclaredMethod("enableActions");
setButtonIcons.setAccessible(true);
enableActions.setAccessible(true);
}
setButtonIcons.invoke(titlePane);
enableActions.invoke(titlePane);
} catch (Exception ex) {
if (JConsole.debug) {
ex.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import javax.management.ObjectName;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import com.sun.management.GarbageCollectorMXBean;
import com.sun.management.GcInfo;
import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import static java.lang.management.ManagementFactory.*;
public class MemoryPoolProxy {
private String poolName;
private ProxyClient client;
private MemoryPoolMXBean pool;
private Map<ObjectName,Long> gcMBeans;
private GcInfo lastGcInfo;
public MemoryPoolProxy(ProxyClient client, ObjectName poolName) throws java.io.IOException {
this.client = client;
this.pool = client.getMXBean(poolName, MemoryPoolMXBean.class);
this.poolName = this.pool.getName();
this.gcMBeans = new HashMap<ObjectName,Long>();
this.lastGcInfo = null;
String[] mgrNames = pool.getMemoryManagerNames();
for (String name : mgrNames) {
try {
ObjectName mbeanName = new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE +
",name=" + name);
if (client.isRegistered(mbeanName)) {
gcMBeans.put(mbeanName, new Long(0));
}
} catch (Exception e) {
assert false;
}
}
}
public boolean isCollectedMemoryPool() {
return (gcMBeans.size() != 0);
}
public MemoryPoolStat getStat() throws java.io.IOException {
long usageThreshold = (pool.isUsageThresholdSupported()
? pool.getUsageThreshold()
: -1);
long collectThreshold = (pool.isCollectionUsageThresholdSupported()
? pool.getCollectionUsageThreshold()
: -1);
long lastGcStartTime = 0;
long lastGcEndTime = 0;
MemoryUsage beforeGcUsage = null;
MemoryUsage afterGcUsage = null;
long gcId = 0;
if (lastGcInfo != null) {
gcId = lastGcInfo.getId();
lastGcStartTime = lastGcInfo.getStartTime();
lastGcEndTime = lastGcInfo.getEndTime();
beforeGcUsage = lastGcInfo.getMemoryUsageBeforeGc().get(poolName);
afterGcUsage = lastGcInfo.getMemoryUsageAfterGc().get(poolName);
}
Set<Map.Entry<ObjectName,Long>> set = gcMBeans.entrySet();
for (Map.Entry<ObjectName,Long> e : set) {
GarbageCollectorMXBean gc =
client.getMXBean(e.getKey(),
com.sun.management.GarbageCollectorMXBean.class);
Long gcCount = e.getValue();
Long newCount = gc.getCollectionCount();
if (newCount > gcCount) {
gcMBeans.put(e.getKey(), new Long(newCount));
lastGcInfo = gc.getLastGcInfo();
if (lastGcInfo.getEndTime() > lastGcEndTime) {
gcId = lastGcInfo.getId();
lastGcStartTime = lastGcInfo.getStartTime();
lastGcEndTime = lastGcInfo.getEndTime();
beforeGcUsage = lastGcInfo.getMemoryUsageBeforeGc().get(poolName);
afterGcUsage = lastGcInfo.getMemoryUsageAfterGc().get(poolName);
assert(beforeGcUsage != null);
assert(afterGcUsage != null);
}
}
}
MemoryUsage usage = pool.getUsage();
return new MemoryPoolStat(poolName,
usageThreshold,
usage,
gcId,
lastGcStartTime,
lastGcEndTime,
collectThreshold,
beforeGcUsage,
afterGcUsage);
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.lang.management.MemoryUsage;
public class MemoryPoolStat {
private String poolName;
private long usageThreshold;
private MemoryUsage usage;
private long lastGcId;
private long lastGcStartTime;
private long lastGcEndTime;
private long collectThreshold;
private MemoryUsage beforeGcUsage;
private MemoryUsage afterGcUsage;
MemoryPoolStat(String name,
long usageThreshold,
MemoryUsage usage,
long lastGcId,
long lastGcStartTime,
long lastGcEndTime,
long collectThreshold,
MemoryUsage beforeGcUsage,
MemoryUsage afterGcUsage) {
this.poolName = name;
this.usageThreshold = usageThreshold;
this.usage = usage;
this.lastGcId = lastGcId;
this.lastGcStartTime = lastGcStartTime;
this.lastGcEndTime = lastGcEndTime;
this.collectThreshold = collectThreshold;
this.beforeGcUsage = beforeGcUsage;
this.afterGcUsage = afterGcUsage;
}
/**
* Returns the memory pool name.
*/
public String getPoolName() {
return poolName;
}
/**
* Returns the current memory usage.
*/
public MemoryUsage getUsage() {
return usage;
}
/**
* Returns the current usage threshold.
* -1 if not supported.
*/
public long getUsageThreshold() {
return usageThreshold;
}
/**
* Returns the current collection usage threshold.
* -1 if not supported.
*/
public long getCollectionUsageThreshold() {
return collectThreshold;
}
/**
* Returns the Id of GC.
*/
public long getLastGcId() {
return lastGcId;
}
/**
* Returns the start time of the most recent GC on
* the memory pool for this statistics in milliseconds.
*
* Return 0 if no GC occurs.
*/
public long getLastGcStartTime() {
return lastGcStartTime;
}
/**
* Returns the end time of the most recent GC on
* the memory pool for this statistics in milliseconds.
*
* Return 0 if no GC occurs.
*/
public long getLastGcEndTime() {
return lastGcEndTime;
}
/**
* Returns the memory usage before the most recent GC started.
* null if no GC occurs.
*/
public MemoryUsage getBeforeGcUsage() {
return beforeGcUsage;
}
/**
* Returns the memory usage after the most recent GC finished.
* null if no GC occurs.
*/
public MemoryUsage getAfterGcUsage() {
return afterGcUsage;
}
}

View File

@@ -0,0 +1,768 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.management.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import javax.accessibility.*;
import javax.management.*;
import javax.management.openmbean.CompositeData;
import javax.swing.*;
import javax.swing.border.*;
import static sun.tools.jconsole.Formatter.*;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
class MemoryTab extends Tab implements ActionListener, ItemListener {
JComboBox<Plotter> plotterChoice;
TimeComboBox timeComboBox;
JButton gcButton;
PlotterPanel plotterPanel;
JPanel bottomPanel;
HTMLPane details;
PoolChart poolChart;
ArrayList<Plotter> plotterList;
Plotter heapPlotter, nonHeapPlotter;
private MemoryOverviewPanel overviewPanel;
private static final String usedKey = "used";
private static final String committedKey = "committed";
private static final String maxKey = "max";
private static final String thresholdKey = "threshold";
private static final Color usedColor = Plotter.defaultColor;
private static final Color committedColor = null;
private static final Color maxColor = null;
private static final Color thresholdColor = Color.red;
/*
Hierarchy of panels and layouts for this tab:
MemoryTab (BorderLayout)
North: topPanel (BorderLayout)
Center: controlPanel (FlowLayout)
plotterChoice, timeComboBox
East: topRightPanel (FlowLayout)
gcButton
Center: plotterPanel
Center: plotter
South: bottomPanel (BorderLayout)
Center: details
East: poolChart
*/
public static String getTabName() {
return Messages.MEMORY;
}
public MemoryTab(VMPanel vmPanel) {
super(vmPanel, getTabName());
setLayout(new BorderLayout(0, 0));
setBorder(new EmptyBorder(4, 4, 3, 4));
JPanel topPanel = new JPanel(new BorderLayout());
plotterPanel = new PlotterPanel(null);
bottomPanel = new JPanel(new BorderLayout());
add(topPanel, BorderLayout.NORTH);
add(plotterPanel, BorderLayout.CENTER);
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 20, 5));
topPanel.add(controlPanel, BorderLayout.CENTER);
// Plotter choice
plotterChoice = new JComboBox<Plotter>();
plotterChoice.addItemListener(this);
controlPanel.add(new LabeledComponent(Messages.CHART_COLON,
Resources.getMnemonicInt(Messages.CHART_COLON),
plotterChoice));
// Range control
timeComboBox = new TimeComboBox();
controlPanel.add(new LabeledComponent(Messages.TIME_RANGE_COLON,
Resources.getMnemonicInt(Messages.TIME_RANGE_COLON),
timeComboBox));
gcButton = new JButton(Messages.PERFORM_GC);
gcButton.setMnemonic(Resources.getMnemonicInt(Messages.PERFORM_GC));
gcButton.addActionListener(this);
gcButton.setToolTipText(Messages.PERFORM_GC_TOOLTIP);
JPanel topRightPanel = new JPanel();
topRightPanel.setBorder(new EmptyBorder(0, 65-8, 0, 70));
topRightPanel.add(gcButton);
topPanel.add(topRightPanel, BorderLayout.AFTER_LINE_ENDS);
bottomPanel.setBorder(new CompoundBorder(new TitledBorder(Messages.DETAILS),
new EmptyBorder(10, 10, 10, 10)));
details = new HTMLPane();
setAccessibleName(details, Messages.DETAILS);
bottomPanel.add(new JScrollPane(details), BorderLayout.CENTER);
poolChart = new PoolChart();
bottomPanel.add(poolChart, BorderLayout.AFTER_LINE_ENDS);
}
private void createPlotters() throws IOException {
plotterList = new ArrayList<Plotter>();
ProxyClient proxyClient = vmPanel.getProxyClient();
heapPlotter = new Plotter(Plotter.Unit.BYTES) {
public String toString() {
return Messages.HEAP_MEMORY_USAGE;
}
};
proxyClient.addWeakPropertyChangeListener(heapPlotter);
nonHeapPlotter = new Plotter(Plotter.Unit.BYTES) {
public String toString() {
return Messages.NON_HEAP_MEMORY_USAGE;
}
};
setAccessibleName(heapPlotter,
Messages.MEMORY_TAB_HEAP_PLOTTER_ACCESSIBLE_NAME);
setAccessibleName(nonHeapPlotter,
Messages.MEMORY_TAB_NON_HEAP_PLOTTER_ACCESSIBLE_NAME);
proxyClient.addWeakPropertyChangeListener(nonHeapPlotter);
heapPlotter.createSequence(usedKey, Messages.USED, usedColor, true);
heapPlotter.createSequence(committedKey, Messages.COMMITTED, committedColor, false);
heapPlotter.createSequence(maxKey, Messages.MAX, maxColor, false);
nonHeapPlotter.createSequence(usedKey, Messages.USED, usedColor, true);
nonHeapPlotter.createSequence(committedKey, Messages.COMMITTED, committedColor, false);
nonHeapPlotter.createSequence(maxKey, Messages.MAX, maxColor, false);
plotterList.add(heapPlotter);
plotterList.add(nonHeapPlotter);
// Now add memory pools
Map<ObjectName, MBeanInfo> mBeanMap = proxyClient.getMBeans("java.lang");
Set<ObjectName> keys = mBeanMap.keySet();
ObjectName[] objectNames = keys.toArray(new ObjectName[keys.size()]);
ArrayList<PoolPlotter> nonHeapPlotters = new ArrayList<PoolPlotter>(2);
for (ObjectName objectName : objectNames) {
String type = objectName.getKeyProperty("type");
if (type.equals("MemoryPool")) {
String name = Resources.format(Messages.MEMORY_POOL_LABEL,
objectName.getKeyProperty("name"));
// Heap or non-heap?
boolean isHeap = false;
AttributeList al =
proxyClient.getAttributes(objectName,
new String[] { "Type" });
if (al.size() > 0) {
isHeap = MemoryType.HEAP.name().equals(((Attribute)al.get(0)).getValue());
}
PoolPlotter poolPlotter = new PoolPlotter(objectName, name, isHeap);
proxyClient.addWeakPropertyChangeListener(poolPlotter);
poolPlotter.createSequence(usedKey, Messages.USED, usedColor, true);
poolPlotter.createSequence(committedKey, Messages.COMMITTED, committedColor, false);
poolPlotter.createSequence(maxKey, Messages.MAX, maxColor, false);
poolPlotter.createSequence(thresholdKey, Messages.THRESHOLD, thresholdColor, false);
poolPlotter.setUseDashedTransitions(thresholdKey, true);
if (isHeap) {
plotterList.add(poolPlotter);
} else {
// Will be added to plotterList below
nonHeapPlotters.add(poolPlotter);
}
}
}
// Add non-heap plotters last
for (PoolPlotter poolPlotter : nonHeapPlotters) {
plotterList.add(poolPlotter);
}
}
public void itemStateChanged(ItemEvent ev) {
if (ev.getStateChange() == ItemEvent.SELECTED) {
Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
plotterPanel.setPlotter(plotter);
plotterPanel.repaint();
}
}
public void gc() {
new Thread("MemoryPanel.gc") {
public void run() {
ProxyClient proxyClient = vmPanel.getProxyClient();
try {
proxyClient.getMemoryMXBean().gc();
} catch (UndeclaredThrowableException e) {
proxyClient.markAsDead();
} catch (IOException e) {
// Ignore
}
}
}.start();
}
public SwingWorker<?, ?> newSwingWorker() {
return new SwingWorker<Boolean, Object>() {
private long[] used, committed, max, threshold;
private long timeStamp;
private String detailsStr;
private boolean initialRun = false;
public Boolean doInBackground() {
ProxyClient proxyClient = vmPanel.getProxyClient();
if (plotterList == null) {
try {
createPlotters();
} catch (UndeclaredThrowableException e) {
proxyClient.markAsDead();
return false;
} catch (final IOException ex) {
return false;
}
initialRun = true;
}
int n = plotterList.size();
used = new long[n];
committed = new long[n];
max = new long[n];
threshold = new long[n];
timeStamp = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
Plotter plotter = plotterList.get(i);
MemoryUsage mu = null;
used[i] = -1L;
threshold[i] = -1L;
try {
if (plotter instanceof PoolPlotter) {
PoolPlotter poolPlotter = (PoolPlotter)plotter;
ObjectName objectName = poolPlotter.objectName;
AttributeList al =
proxyClient.getAttributes(objectName,
new String[] { "Usage", "UsageThreshold" });
if (al.size() > 0) {
CompositeData cd = (CompositeData)((Attribute)al.get(0)).getValue();
mu = MemoryUsage.from(cd);
if (al.size() > 1) {
threshold[i] = (Long)((Attribute)al.get(1)).getValue();
}
}
} else if (plotter == heapPlotter) {
mu = proxyClient.getMemoryMXBean().getHeapMemoryUsage();
} else if (plotter == nonHeapPlotter) {
mu = proxyClient.getMemoryMXBean().getNonHeapMemoryUsage();
}
} catch (UndeclaredThrowableException e) {
proxyClient.markAsDead();
return false;
} catch (IOException ex) {
// Skip this plotter
}
if (mu != null) {
used[i] = mu.getUsed();
committed[i] = mu.getCommitted();
max[i] = mu.getMax();
}
}
detailsStr = formatDetails();
return true;
}
protected void done() {
try {
if (!get()) {
return;
}
} catch (InterruptedException ex) {
return;
} catch (ExecutionException ex) {
if (JConsole.isDebug()) {
ex.printStackTrace();
}
return;
}
if (initialRun) {
// Add Memory Pools
for (Plotter p : plotterList) {
plotterChoice.addItem(p);
timeComboBox.addPlotter(p);
}
add(bottomPanel, BorderLayout.SOUTH);
}
int n = plotterList.size();
int poolCount = 0;
for (int i = 0; i < n; i++) {
Plotter plotter = plotterList.get(i);
if (used[i] >= 0L) {
if (plotter instanceof PoolPlotter) {
plotter.addValues(timeStamp, used[i], committed[i], max[i], threshold[i]);
if (threshold[i] > 0L) {
plotter.setIsPlotted(thresholdKey, true);
}
poolChart.setValue(poolCount++, (PoolPlotter)plotter,
used[i], threshold[i], max[i]);
} else {
plotter.addValues(timeStamp, used[i], committed[i], max[i]);
}
if (plotter == heapPlotter && overviewPanel != null) {
overviewPanel.getPlotter().addValues(timeStamp, used[i]);
overviewPanel.updateMemoryInfo(used[i], committed[i], max[i]);
}
}
}
details.setText(detailsStr);
}
};
}
private String formatDetails() {
ProxyClient proxyClient = vmPanel.getProxyClient();
if (proxyClient.isDead()) {
return "";
}
String text = "<table cellspacing=0 cellpadding=0>";
Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
if (plotter == null) {
return "";
}
//long time = plotter.getLastTimeStamp();
long time = System.currentTimeMillis();
String timeStamp = formatDateTime(time);
text += newRow(Messages.TIME, timeStamp);
long used = plotter.getLastValue(usedKey);
long committed = plotter.getLastValue(committedKey);
long max = plotter.getLastValue(maxKey);
long threshold = plotter.getLastValue(thresholdKey);
text += newRow(Messages.USED, formatKBytes(used));
if (committed > 0L) {
text += newRow(Messages.COMMITTED, formatKBytes(committed));
}
if (max > 0L) {
text += newRow(Messages.MAX, formatKBytes(max));
}
if (threshold > 0L) {
text += newRow(Messages.USAGE_THRESHOLD, formatKBytes(threshold));
}
try {
Collection<GarbageCollectorMXBean> garbageCollectors =
proxyClient.getGarbageCollectorMXBeans();
boolean descPrinted = false;
for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) {
String gcName = garbageCollectorMBean.getName();
long gcCount = garbageCollectorMBean.getCollectionCount();
long gcTime = garbageCollectorMBean.getCollectionTime();
String str = Resources.format(Messages.GC_TIME_DETAILS, justify(formatTime(gcTime), 14),
gcName,
String.format("%,d",gcCount));
if (!descPrinted) {
text += newRow(Messages.GC_TIME, str);
descPrinted = true;
} else {
text += newRow(null, str);
}
}
} catch (IOException e) {
}
return text;
}
public void actionPerformed(ActionEvent ev) {
Object src = ev.getSource();
if (src == gcButton) {
gc();
}
}
private class PoolPlotter extends Plotter {
ObjectName objectName;
String name;
boolean isHeap;
long value, threshold, max;
int barX;
public PoolPlotter(ObjectName objectName, String name, boolean isHeap) {
super(Plotter.Unit.BYTES);
this.objectName = objectName;
this.name = name;
this.isHeap = isHeap;
setAccessibleName(this,
Resources.format(Messages.MEMORY_TAB_POOL_PLOTTER_ACCESSIBLE_NAME,
name));
}
public String toString() {
return name;
}
}
private class PoolChart extends BorderedComponent
implements Accessible, MouseListener {
final int height = 150;
final int leftMargin = 50;
final int rightMargin = 23;
final int bottomMargin = 35;
final int barWidth = 22;
final int barGap = 3;
final int groupGap = 8;
final int barHeight = height * 2 / 3;
final Color greenBar = new Color(100, 255, 100);
final Color greenBarBackground = new Color(210, 255, 210);
final Color redBarBackground = new Color(255, 210, 210);
Font smallFont = null;
ArrayList<PoolPlotter> poolPlotters = new ArrayList<PoolPlotter>(5);
int nHeapPools = 0;
int nNonHeapPools = 0;
Rectangle heapRect = new Rectangle(leftMargin, height - bottomMargin + 6, barWidth, 20);
Rectangle nonHeapRect = new Rectangle(leftMargin + groupGap, height - bottomMargin + 6, barWidth, 20);
public PoolChart() {
super(null, null);
setFocusable(true);
addMouseListener(this);
ToolTipManager.sharedInstance().registerComponent(this);
}
public void setValue(int poolIndex, PoolPlotter poolPlotter,
long value, long threshold, long max) {
poolPlotter.value = value;
poolPlotter.threshold = threshold;
poolPlotter.max = max;
if (poolIndex == poolPlotters.size()) {
poolPlotters.add(poolPlotter);
if (poolPlotter.isHeap) {
poolPlotter.barX = nHeapPools * (barWidth + barGap);
nHeapPools++;
heapRect.width = nHeapPools * barWidth + (nHeapPools - 1) * barGap;
nonHeapRect.x = leftMargin + heapRect.width + groupGap;
} else {
poolPlotter.barX = nonHeapRect.x - leftMargin + nNonHeapPools * (barWidth + barGap);
nNonHeapPools++;
nonHeapRect.width = nNonHeapPools * barWidth + (nNonHeapPools - 1) * barGap;
}
} else {
poolPlotters.set(poolIndex, poolPlotter);
}
repaint();
}
private void paintPoolBar(Graphics g, PoolPlotter poolPlotter) {
Rectangle barRect = getBarRect(poolPlotter);
g.setColor(Color.gray);
g.drawRect(barRect.x, barRect.y, barRect.width, barRect.height);
long value = poolPlotter.value;
long max = poolPlotter.max;
if (max > 0L) {
g.translate(barRect.x, barRect.y);
// Paint green background
g.setColor(greenBarBackground);
g.fillRect(1, 1, barRect.width - 1, barRect.height - 1);
int greenHeight = (int)(value * barRect.height / max);
long threshold = poolPlotter.threshold;
if (threshold > 0L) {
int redHeight = (int)(threshold * barRect.height / max);
// Paint red background
g.setColor(redBarBackground);
g.fillRect(1, 1, barRect.width - 1, barRect.height - redHeight);
if (value > threshold) {
// Over threshold, paint red bar
g.setColor(thresholdColor);
g.fillRect(1, barRect.height - greenHeight,
barRect.width - 1, greenHeight - redHeight);
greenHeight = redHeight;
}
}
// Paint green bar
g.setColor(greenBar);
g.fillRect(1, barRect.height - greenHeight,
barRect.width - 1, greenHeight);
g.translate(-barRect.x, -barRect.y);
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (poolPlotters.size() == 0) {
return;
}
if (smallFont == null) {
smallFont = g.getFont().deriveFont(9.0F);
}
// Paint background for chart area
g.setColor(getBackground());
Rectangle r = g.getClipBounds();
g.fillRect(r.x, r.y, r.width, r.height);
g.setFont(smallFont);
FontMetrics fm = g.getFontMetrics();
int fontDescent = fm.getDescent();
// Paint percentage axis
g.setColor(getForeground());
for (int pc : new int[] { 0, 25, 50, 75, 100 }) {
String str = pc + "% --";
g.drawString(str,
leftMargin - fm.stringWidth(str) - 4,
height - bottomMargin - (pc * barHeight / 100) + fontDescent + 1);
}
for (PoolPlotter poolPlotter : poolPlotters) {
paintPoolBar(g, poolPlotter);
}
g.setColor(Color.gray);
g.drawRect(heapRect.x, heapRect.y, heapRect.width, heapRect.height);
g.drawRect(nonHeapRect.x, nonHeapRect.y, nonHeapRect.width, nonHeapRect.height);
Color heapColor = greenBar;
Color nonHeapColor = greenBar;
for (PoolPlotter poolPlotter : poolPlotters) {
if (poolPlotter.threshold > 0L && poolPlotter.value > poolPlotter.threshold) {
if (poolPlotter.isHeap) {
heapColor = thresholdColor;
} else {
nonHeapColor = thresholdColor;
}
}
}
g.setColor(heapColor);
g.fillRect(heapRect.x + 1, heapRect.y + 1, heapRect.width - 1, heapRect.height - 1);
g.setColor(nonHeapColor);
g.fillRect(nonHeapRect.x + 1, nonHeapRect.y + 1, nonHeapRect.width - 1, nonHeapRect.height - 1);
String str = Messages.HEAP;
int stringWidth = fm.stringWidth(str);
int x = heapRect.x + (heapRect.width - stringWidth) / 2;
int y = heapRect.y + heapRect.height - 6;
g.setColor(Color.white);
g.drawString(str, x-1, y-1);
g.drawString(str, x+1, y-1);
g.drawString(str, x-1, y+1);
g.drawString(str, x+1, y+1);
g.setColor(Color.black);
g.drawString(str, x, y);
str = Messages.NON_HEAP;
stringWidth = fm.stringWidth(str);
x = nonHeapRect.x + (nonHeapRect.width - stringWidth) / 2;
y = nonHeapRect.y + nonHeapRect.height - 6;
g.setColor(Color.white);
g.drawString(str, x-1, y-1);
g.drawString(str, x+1, y-1);
g.drawString(str, x-1, y+1);
g.drawString(str, x+1, y+1);
g.setColor(Color.black);
g.drawString(str, x, y);
// Highlight current plotter
g.setColor(Color.blue);
r = null;
Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
if (plotter == heapPlotter) {
r = heapRect;
} else if (plotter == nonHeapPlotter) {
r = nonHeapRect;
} else if (plotter instanceof PoolPlotter) {
r = getBarRect((PoolPlotter)plotter);
}
if (r != null) {
g.drawRect(r.x - 1, r.y - 1, r.width + 2, r.height + 2);
}
}
private Rectangle getBarRect(PoolPlotter poolPlotter) {
return new Rectangle(leftMargin + poolPlotter.barX,
height - bottomMargin - barHeight,
barWidth, barHeight);
}
public Dimension getPreferredSize() {
return new Dimension(nonHeapRect.x + nonHeapRect.width + rightMargin,
height);
}
public void mouseClicked(MouseEvent e) {
requestFocusInWindow();
Plotter plotter = getPlotter(e);
if (plotter != null && plotter != plotterChoice.getSelectedItem()) {
plotterChoice.setSelectedItem(plotter);
repaint();
}
}
public String getToolTipText(MouseEvent e) {
Plotter plotter = getPlotter(e);
return (plotter != null) ? plotter.toString() : null;
}
private Plotter getPlotter(MouseEvent e) {
Point p = e.getPoint();
Plotter plotter = null;
if (heapRect.contains(p)) {
plotter = heapPlotter;
} else if (nonHeapRect.contains(p)) {
plotter = nonHeapPlotter;
} else {
for (PoolPlotter poolPlotter : poolPlotters) {
if (getBarRect(poolPlotter).contains(p)) {
plotter = poolPlotter;
break;
}
}
}
return plotter;
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessiblePoolChart();
}
return accessibleContext;
}
protected class AccessiblePoolChart extends AccessibleJPanel {
public String getAccessibleName() {
String name = Messages.MEMORY_TAB_POOL_CHART_ACCESSIBLE_NAME;
String keyValueList = "";
for (PoolPlotter poolPlotter : poolPlotters) {
String value = (poolPlotter.value * 100 / poolPlotter.max) + "%";
// Assume format string ends with newline
keyValueList +=
Resources.format(Messages.PLOTTER_ACCESSIBLE_NAME_KEY_AND_VALUE,
poolPlotter.toString(), value);
if (poolPlotter.threshold > 0L) {
String threshold =
(poolPlotter.threshold * 100 / poolPlotter.max) + "%";
if (poolPlotter.value > poolPlotter.threshold) {
keyValueList +=
Resources.format(Messages.MEMORY_TAB_POOL_CHART_ABOVE_THRESHOLD,
threshold);
} else {
keyValueList +=
Resources.format(Messages.MEMORY_TAB_POOL_CHART_BELOW_THRESHOLD,
threshold);
}
}
}
return name + "\n" + keyValueList + ".";
}
}
}
OverviewPanel[] getOverviewPanels() {
if (overviewPanel == null) {
overviewPanel = new MemoryOverviewPanel();
}
return new OverviewPanel[] { overviewPanel };
}
private static class MemoryOverviewPanel extends OverviewPanel {
MemoryOverviewPanel() {
super(Messages.HEAP_MEMORY_USAGE, usedKey, Messages.USED, Plotter.Unit.BYTES);
}
private void updateMemoryInfo(long used, long committed, long max) {
getInfoLabel().setText(Resources.format(Messages.MEMORY_TAB_INFO_LABEL_FORMAT,
formatBytes(used, true),
formatBytes(committed, true),
formatBytes(max, true)));
}
}
}

View File

@@ -0,0 +1,325 @@
/*
* Copyright (c) 2013, 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 sun.tools.jconsole;
/**
* Class that contains localized messages.
*
*/
final public class Messages {
private static final String BUNDLE_NAME = "sun.tools.jconsole.resources.messages";
static {
Resources.initializeMessages(Messages.class, BUNDLE_NAME);
}
// TODO:
// The names of some of the constants below look strange.
// That's because they were generated programmatically
// from the messages. They should be cleaned up,
// ___ should be removed etc.
public static String ONE_DAY;
public static String ONE_HOUR;
public static String ONE_MIN;
public static String ONE_MONTH;
public static String ONE_YEAR;
public static String TWO_HOURS;
public static String THREE_HOURS;
public static String THREE_MONTHS;
public static String FIVE_MIN;
public static String SIX_HOURS;
public static String SIX_MONTHS;
public static String SEVEN_DAYS;
public static String TEN_MIN;
public static String TWELVE_HOURS;
public static String THIRTY_MIN;
public static String LESS_THAN;
public static String A_LOT_LESS_THAN;
public static String GREATER_THAN;
public static String ACTION_CAPITALIZED;
public static String ACTION_INFO_CAPITALIZED;
public static String ALL;
public static String ARCHITECTURE;
public static String ATTRIBUTE;
public static String ATTRIBUTE_VALUE;
public static String ATTRIBUTE_VALUES;
public static String ATTRIBUTES;
public static String BLANK;
public static String BLOCKED_COUNT_WAITED_COUNT;
public static String BOOT_CLASS_PATH;
public static String BORDERED_COMPONENT_MORE_OR_LESS_BUTTON_TOOLTIP;
public static String CPU_USAGE;
public static String CPU_USAGE_FORMAT;
public static String CANCEL;
public static String CASCADE;
public static String CHART_COLON;
public static String CLASS_PATH;
public static String CLASS_NAME;
public static String CLASS_TAB_INFO_LABEL_FORMAT;
public static String CLASS_TAB_LOADED_CLASSES_PLOTTER_ACCESSIBLE_NAME;
public static String CLASSES;
public static String CLOSE;
public static String COLUMN_NAME;
public static String COLUMN_PID;
public static String COMMITTED_MEMORY;
public static String COMMITTED_VIRTUAL_MEMORY;
public static String COMMITTED;
public static String CONNECT;
public static String CONNECT_DIALOG_CONNECT_BUTTON_TOOLTIP;
public static String CONNECT_DIALOG_ACCESSIBLE_DESCRIPTION;
public static String CONNECT_DIALOG_MASTHEAD_ACCESSIBLE_NAME;
public static String CONNECT_DIALOG_MASTHEAD_TITLE;
public static String CONNECT_DIALOG_STATUS_BAR_ACCESSIBLE_NAME;
public static String CONNECT_DIALOG_TITLE;
public static String CONNECTED_PUNCTUATION_CLICK_TO_DISCONNECT_;
public static String CONNECTION_FAILED;
public static String CONNECTION;
public static String CONNECTION_NAME;
public static String CONNECTION_NAME__DISCONNECTED_;
public static String CONSTRUCTOR;
public static String CURRENT_CLASSES_LOADED;
public static String CURRENT_HEAP_SIZE;
public static String CURRENT_VALUE;
public static String CREATE;
public static String DAEMON_THREADS;
public static String DISCONNECTED_PUNCTUATION_CLICK_TO_CONNECT_;
public static String DOUBLE_CLICK_TO_EXPAND_FORWARD_SLASH_COLLAPSE;
public static String DOUBLE_CLICK_TO_VISUALIZE;
public static String DESCRIPTION;
public static String DESCRIPTOR;
public static String DETAILS;
public static String DETECT_DEADLOCK;
public static String DETECT_DEADLOCK_TOOLTIP;
public static String DIMENSION_IS_NOT_SUPPORTED_COLON;
public static String DISCARD_CHART;
public static String DURATION_DAYS_HOURS_MINUTES;
public static String DURATION_HOURS_MINUTES;
public static String DURATION_MINUTES;
public static String DURATION_SECONDS;
public static String EMPTY_ARRAY;
public static String ERROR;
public static String ERROR_COLON_MBEANS_ALREADY_EXIST;
public static String ERROR_COLON_MBEANS_DO_NOT_EXIST;
public static String EVENT;
public static String EXIT;
public static String FAIL_TO_LOAD_PLUGIN;
public static String FILE_CHOOSER_FILE_EXISTS_CANCEL_OPTION;
public static String FILE_CHOOSER_FILE_EXISTS_MESSAGE;
public static String FILE_CHOOSER_FILE_EXISTS_OK_OPTION;
public static String FILE_CHOOSER_FILE_EXISTS_TITLE;
public static String FILE_CHOOSER_SAVED_FILE;
public static String FILE_CHOOSER_SAVE_FAILED_MESSAGE;
public static String FILE_CHOOSER_SAVE_FAILED_TITLE;
public static String FREE_PHYSICAL_MEMORY;
public static String FREE_SWAP_SPACE;
public static String GARBAGE_COLLECTOR;
public static String GC_INFO;
public static String GC_TIME;
public static String GC_TIME_DETAILS;
public static String HEAP_MEMORY_USAGE;
public static String HEAP;
public static String HELP_ABOUT_DIALOG_ACCESSIBLE_DESCRIPTION;
public static String HELP_ABOUT_DIALOG_JCONSOLE_VERSION;
public static String HELP_ABOUT_DIALOG_JAVA_VERSION;
public static String HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME;
public static String HELP_ABOUT_DIALOG_MASTHEAD_TITLE;
public static String HELP_ABOUT_DIALOG_TITLE;
public static String HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL;
public static String HELP_MENU_ABOUT_TITLE;
public static String HELP_MENU_USER_GUIDE_TITLE;
public static String HELP_MENU_TITLE;
public static String HOTSPOT_MBEANS_ELLIPSIS;
public static String HOTSPOT_MBEANS_DIALOG_ACCESSIBLE_DESCRIPTION;
public static String IMPACT;
public static String INFO;
public static String INFO_CAPITALIZED;
public static String INSECURE;
public static String INVALID_PLUGIN_PATH;
public static String INVALID_URL;
public static String IS;
public static String JAVA_MONITORING___MANAGEMENT_CONSOLE;
public static String JCONSOLE_COLON_;
public static String JCONSOLE_VERSION; // in version template
public static String JCONSOLE_ACCESSIBLE_DESCRIPTION;
public static String JIT_COMPILER;
public static String LIBRARY_PATH;
public static String LIVE_THREADS;
public static String LOADED;
public static String LOCAL_PROCESS_COLON;
public static String MASTHEAD_FONT;
public static String MANAGEMENT_NOT_ENABLED;
public static String MANAGEMENT_WILL_BE_ENABLED;
public static String MBEAN_ATTRIBUTE_INFO;
public static String MBEAN_INFO;
public static String MBEAN_NOTIFICATION_INFO;
public static String MBEAN_OPERATION_INFO;
public static String MBEANS;
public static String MBEANS_TAB_CLEAR_NOTIFICATIONS_BUTTON;
public static String MBEANS_TAB_CLEAR_NOTIFICATIONS_BUTTON_TOOLTIP;
public static String MBEANS_TAB_COMPOSITE_NAVIGATION_MULTIPLE;
public static String MBEANS_TAB_COMPOSITE_NAVIGATION_SINGLE;
public static String MBEANS_TAB_REFRESH_ATTRIBUTES_BUTTON;
public static String MBEANS_TAB_REFRESH_ATTRIBUTES_BUTTON_TOOLTIP;
public static String MBEANS_TAB_SUBSCRIBE_NOTIFICATIONS_BUTTON;
public static String MBEANS_TAB_SUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP;
public static String MBEANS_TAB_TABULAR_NAVIGATION_MULTIPLE;
public static String MBEANS_TAB_TABULAR_NAVIGATION_SINGLE;
public static String MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON;
public static String MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP;
public static String MANAGE_HOTSPOT_MBEANS_IN_COLON_;
public static String MAX;
public static String MAXIMUM_HEAP_SIZE;
public static String MEMORY;
public static String MEMORY_POOL_LABEL;
public static String MEMORY_TAB_HEAP_PLOTTER_ACCESSIBLE_NAME;
public static String MEMORY_TAB_INFO_LABEL_FORMAT;
public static String MEMORY_TAB_NON_HEAP_PLOTTER_ACCESSIBLE_NAME;
public static String MEMORY_TAB_POOL_CHART_ABOVE_THRESHOLD;
public static String MEMORY_TAB_POOL_CHART_ACCESSIBLE_NAME;
public static String MEMORY_TAB_POOL_CHART_BELOW_THRESHOLD;
public static String MEMORY_TAB_POOL_PLOTTER_ACCESSIBLE_NAME;
public static String MESSAGE;
public static String METHOD_SUCCESSFULLY_INVOKED;
public static String MINIMIZE_ALL;
public static String MONITOR_LOCKED;
public static String NAME;
public static String NAME_STATE;
public static String NAME_STATE_LOCK_NAME;
public static String NAME_STATE_LOCK_NAME_LOCK_OWNER;
public static String NAME_AND_BUILD;// in version template
public static String NEW_CONNECTION_ELLIPSIS;
public static String NO_DEADLOCK_DETECTED;
public static String NON_HEAP_MEMORY_USAGE;
public static String NON_HEAP;
public static String NOTIFICATION;
public static String NOTIFICATION_BUFFER;
public static String NOTIFICATIONS;
public static String NOTIF_TYPES;
public static String NUMBER_OF_THREADS;
public static String NUMBER_OF_LOADED_CLASSES;
public static String NUMBER_OF_PROCESSORS;
public static String OBJECT_NAME;
public static String OPERATING_SYSTEM;
public static String OPERATION;
public static String OPERATION_INVOCATION;
public static String OPERATION_RETURN_VALUE;
public static String OPERATIONS;
public static String OVERVIEW;
public static String OVERVIEW_PANEL_PLOTTER_ACCESSIBLE_NAME;
public static String PARAMETER;
public static String PASSWORD_COLON_;
public static String PASSWORD_ACCESSIBLE_NAME;
public static String PEAK;
public static String PERFORM_GC;
public static String PERFORM_GC_TOOLTIP;
public static String PLOTTER_ACCESSIBLE_NAME;
public static String PLOTTER_ACCESSIBLE_NAME_KEY_AND_VALUE;
public static String PLOTTER_ACCESSIBLE_NAME_NO_DATA;
public static String PLOTTER_SAVE_AS_MENU_ITEM;
public static String PLOTTER_TIME_RANGE_MENU;
public static String PLUGIN_EXCEPTION_DIALOG_BUTTON_EXIT;
public static String PLUGIN_EXCEPTION_DIALOG_BUTTON_IGNORE;
public static String PLUGIN_EXCEPTION_DIALOG_BUTTON_OK;
public static String PLUGIN_EXCEPTION_DIALOG_MESSAGE;
public static String PLUGIN_EXCEPTION_DIALOG_TITLE;
public static String PROBLEM_ADDING_LISTENER;
public static String PROBLEM_DISPLAYING_MBEAN;
public static String PROBLEM_INVOKING;
public static String PROBLEM_REMOVING_LISTENER;
public static String PROBLEM_SETTING_ATTRIBUTE;
public static String PROCESS_CPU_TIME;
public static String READABLE;
public static String RECONNECT;
public static String REMOTE_PROCESS_COLON;
public static String REMOTE_PROCESS_TEXT_FIELD_ACCESSIBLE_NAME;
public static String RESTORE_ALL;
public static String RETURN_TYPE;
public static String SEQ_NUM;
public static String SIZE_BYTES;
public static String SIZE_GB;
public static String SIZE_KB;
public static String SIZE_MB;
public static String SOURCE;
public static String STACK_TRACE;
public static String SUMMARY_TAB_HEADER_DATE_TIME_FORMAT;
public static String SUMMARY_TAB_PENDING_FINALIZATION_LABEL;
public static String SUMMARY_TAB_PENDING_FINALIZATION_VALUE;
public static String SUMMARY_TAB_TAB_NAME;
public static String SUMMARY_TAB_VM_VERSION;
public static String THREADS;
public static String THREAD_TAB_INFO_LABEL_FORMAT;
public static String THREAD_TAB_THREAD_INFO_ACCESSIBLE_NAME;
public static String THREAD_TAB_THREAD_PLOTTER_ACCESSIBLE_NAME;
public static String THREAD_TAB_INITIAL_STACK_TRACE_MESSAGE;
public static String THRESHOLD;
public static String TILE;
public static String TIME_RANGE_COLON;
public static String TIME;
public static String TIME_STAMP;
public static String TOTAL_LOADED;
public static String TOTAL_CLASSES_LOADED;
public static String TOTAL_CLASSES_UNLOADED;
public static String TOTAL_COMPILE_TIME;
public static String TOTAL_PHYSICAL_MEMORY;
public static String TOTAL_THREADS_STARTED;
public static String TOTAL_SWAP_SPACE;
public static String TYPE;
public static String UNAVAILABLE;
public static String UNKNOWN_CAPITALIZED;
public static String UNKNOWN_HOST;
public static String UNREGISTER;
public static String UPTIME;
public static String USAGE_THRESHOLD;
public static String REMOTE_TF_USAGE;
public static String USED;
public static String USERNAME_COLON_;
public static String USERNAME_ACCESSIBLE_NAME;
public static String USER_DATA;
public static String VIRTUAL_MACHINE;
public static String VM_ARGUMENTS;
public static String VMINTERNAL_FRAME_ACCESSIBLE_DESCRIPTION;
public static String VALUE;
public static String VENDOR;
public static String VERBOSE_OUTPUT;
public static String VERBOSE_OUTPUT_TOOLTIP;
public static String VIEW;
public static String WINDOW;
public static String WINDOWS;
public static String WRITABLE;
public static String CONNECTION_FAILED1;
public static String CONNECTION_FAILED2;
public static String CONNECTION_FAILED_SSL1;
public static String CONNECTION_FAILED_SSL2;
public static String CONNECTION_LOST1;
public static String CONNECTING_TO1;
public static String CONNECTING_TO2;
public static String DEADLOCK_TAB;
public static String DEADLOCK_TAB_N;
public static String EXPAND;
public static String KBYTES;
public static String PLOT;
public static String VISUALIZE;
public static String ZZ_USAGE_TEXT;
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2006, 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 sun.tools.jconsole;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import javax.swing.*;
/**
* A simple console window to display messages sent to System.out and
* System.err.
*
* A stop-gap solution until an error dialog is implemented.
*/
public class OutputViewer {
private static JFrame frame;
private static JTextArea ta;
static {
System.setOut(PipeListener.create("System.out"));
System.setErr(PipeListener.create("System.err"));
}
// Dummy to cause class to be loaded
public static void init() { }
private static void append(String s) {
if (frame == null) {
// FIXME: The frame title should be a localized string.
frame = new JFrame("JConsole: Output");
ta = new JTextArea();
ta.setEditable(false);
frame.getContentPane().add(new JScrollPane(ta));
ta.setFont(new Font("Monospaced", Font.BOLD, 14));
frame.setSize(500, 600);
frame.setLocation(1024-500, 768-600);
// Exit JConsole if no window remains.
// e.g. jconsole -version only creates the OutputViewer
// but no other window.
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (JFrame.getFrames().length == 1) {
System.exit(0);
}
}
});
}
ta.append(s);
ta.setCaretPosition(ta.getText().length());
frame.setVisible(true);
}
private static void appendln(String s) {
append(s+"\n");
}
private static class PipeListener extends Thread {
public PrintStream ps;
private String name;
private PipedInputStream inPipe;
private BufferedReader br;
public static PrintStream create(String name) {
return new PipeListener(name).ps;
}
private PipeListener(String name) {
this.name = name;
try {
inPipe = new PipedInputStream();
ps = new PrintStream(new PipedOutputStream(inPipe));
br = new BufferedReader(new InputStreamReader(inPipe));
} catch (IOException e) {
appendln("PipeListener<init>("+name+"): " + e);
}
start();
}
public void run() {
try {
String str;
while ((str = br.readLine()) != null) {
appendln(str);
// Hack: Turn off thread check in PipedInputStream.
// Any thread should be allowed to write except this one
// but we just use this one to keep the pipe alive.
try {
java.lang.reflect.Field f =
PipedInputStream.class.getDeclaredField("writeSide");
f.setAccessible(true);
f.set(inPipe, this);
} catch (Exception e) {
appendln("PipeListener("+name+").run: "+e);
}
}
appendln("-- "+name+" closed --");
br.close();
} catch (IOException e) {
appendln("PipeListener("+name+").run: "+e);
}
}
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2006, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import javax.swing.*;
import static javax.swing.SwingConstants.*;
import static sun.tools.jconsole.JConsole.*;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
abstract class OverviewPanel extends PlotterPanel {
private static final Dimension PREFERRED_PLOTTER_SIZE = new Dimension(300, 200);
private static final Dimension MINIMUM_PLOTTER_SIZE = new Dimension(200, 150);
// This is the default view range for all the overview plotters
static final int VIEW_RANGE = -1; // Show all data
static Color PLOTTER_COLOR = IS_GTK ? new Color(231, 111, 80) : null;
private JLabel infoLabel;
public OverviewPanel(String title) {
this(title, null, null, null);
}
public OverviewPanel(String title, String plotterKey,
String plotterName, Plotter.Unit plotterUnit) {
super(title);
setLayout(new BorderLayout(0, 0));
if (plotterKey != null && plotterName != null) {
Plotter plotter = new Plotter();
plotter.setPreferredSize(PREFERRED_PLOTTER_SIZE);
plotter.setMinimumSize(MINIMUM_PLOTTER_SIZE);
plotter.setViewRange(VIEW_RANGE);
if (plotterUnit != null) {
plotter.setUnit(plotterUnit);
}
plotter.createSequence(plotterKey, plotterName, PLOTTER_COLOR, true);
setAccessibleName(plotter,
Resources.format(Messages.OVERVIEW_PANEL_PLOTTER_ACCESSIBLE_NAME,
title));
setPlotter(plotter);
}
}
public JLabel getInfoLabel() {
if (infoLabel == null) {
infoLabel = new JLabel("", CENTER) {
@Override
public void setText(String text) {
if (text.startsWith("<html>")) {
// Replace spaces with nbsp, except the
// last one of two or more (to allow wrapping)
StringBuilder buf = new StringBuilder();
char[] chars = text.toCharArray();
int n = chars.length;
for (int i = 0; i < n; i++) {
if (chars[i] == ' '
&& ((i < n-1 && chars[i+1] == ' ')
|| ((i == 0 || chars[i-1] != ' ')
&& (i == n-1 || chars[i+1] != ' ')))) {
buf.append("&nbsp;");
} else {
buf.append(chars[i]);
}
}
text = buf.toString();
}
super.setText(text);
}
};
if (IS_GTK) {
JPanel southPanel = new JPanel(new BorderLayout());
JSeparator separator = new JSeparator(JSeparator.HORIZONTAL);
southPanel.add(separator, BorderLayout.NORTH);
southPanel.add(infoLabel, BorderLayout.SOUTH);
add(southPanel, BorderLayout.SOUTH);
} else {
add(infoLabel, BorderLayout.SOUTH);
}
}
return infoLabel;
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (c) 2006, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.*;
@SuppressWarnings("serial")
class OverviewTab extends Tab {
JPanel gridPanel;
TimeComboBox timeComboBox;
public static String getTabName() {
return Messages.OVERVIEW;
}
public OverviewTab(VMPanel vmPanel) {
super(vmPanel, getTabName());
setBorder(new EmptyBorder(4, 4, 3, 4));
setLayout(new BorderLayout());
JPanel topPanel = new JPanel(new BorderLayout());
add(topPanel, BorderLayout.NORTH);
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5));
topPanel.add(controlPanel, BorderLayout.CENTER);
timeComboBox = new TimeComboBox();
LabeledComponent lc = new LabeledComponent(Messages.TIME_RANGE_COLON,
Resources.getMnemonicInt(Messages.TIME_RANGE_COLON),
timeComboBox);
controlPanel.add(lc);
gridPanel = new JPanel(new AutoGridLayout(10, 6));
gridPanel.setBorder(null);
JScrollPane sp = new JScrollPane(gridPanel);
sp.setBorder(null);
sp.setViewportBorder(null);
add(sp, BorderLayout.CENTER);
// Note that panels are added on first update
}
public SwingWorker<?, ?> newSwingWorker() {
return new SwingWorker<Object, Object>() {
public Object doInBackground() {
return null;
}
protected void done() {
if (gridPanel.getComponentCount() == 0) {
final ArrayList<Plotter> plotters = new ArrayList<Plotter>();
for (Tab tab : vmPanel.getTabs()) {
OverviewPanel[] ops = tab.getOverviewPanels();
if (ops != null) {
for (OverviewPanel op : ops) {
gridPanel.add(op);
Plotter plotter = op.getPlotter();
if (plotter != null) {
plotters.add(plotter);
timeComboBox.addPlotter(plotter);
}
}
}
}
if (plotters.size() > 0) {
workerAdd(new Runnable() {
public void run() {
ProxyClient proxyClient = vmPanel.getProxyClient();
for (Plotter plotter : plotters) {
proxyClient.addWeakPropertyChangeListener(plotter);
}
}
});
}
if (getParent() instanceof JTabbedPane) {
Utilities.updateTransparency((JTabbedPane)getParent());
}
}
}
};
}
private class AutoGridLayout extends GridLayout {
public AutoGridLayout(int hGap, int vGap) {
super(0, 1, hGap, vGap);
}
public Dimension preferredLayoutSize(Container parent) {
return minimumLayoutSize(parent);
}
public Dimension minimumLayoutSize(Container parent) {
updateColumns(parent);
return super.minimumLayoutSize(parent);
}
private void updateColumns(Container parent) {
// Use the outer panel width, not the scrolling gridPanel
int parentWidth = OverviewTab.this.getWidth();
int columnWidth = 1;
for (Component c : parent.getComponents()) {
columnWidth = Math.max(columnWidth, c.getPreferredSize().width);
}
int n = parent.getComponentCount();
int maxCols = Math.min(n, parentWidth / columnWidth);
for (int columns = maxCols; columns >= 1; columns--) {
if (columns == 1) {
setColumns(maxCols);
} else if ((n % columns) == 0) {
setColumns(columns);
break;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.awt.event.*;
import javax.accessibility.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class PlotterPanel extends BorderedComponent {
Plotter plotter;
public PlotterPanel(String labelStr, Plotter.Unit unit, boolean collapsible) {
super(labelStr, new Plotter(unit), collapsible);
this.plotter = (Plotter)comp;
init();
}
public PlotterPanel(String labelStr) {
super(labelStr, null);
init();
}
public Plotter getPlotter() {
return this.plotter;
}
public void setPlotter(Plotter plotter) {
this.plotter = plotter;
setComponent(plotter);
}
private void init() {
setFocusable(true);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
requestFocusInWindow();
}
});
}
public JPopupMenu getComponentPopupMenu() {
return (getPlotter() != null)? getPlotter().getComponentPopupMenu() : null;
}
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessiblePlotterPanel();
}
return accessibleContext;
}
protected class AccessiblePlotterPanel extends AccessibleJComponent {
public String getAccessibleName() {
String name = null;
if (getPlotter() != null) {
name = getPlotter().getAccessibleContext().getAccessibleName();
}
if (name == null) {
name = super.getAccessibleName();
}
return name;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,209 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole;
import java.awt.event.KeyEvent;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Toolkit that provides resource support for JConsole.
*/
public final class Resources {
private static Map<String, Integer> MNEMONIC_LOOKUP = Collections
.synchronizedMap(new IdentityHashMap<String, Integer>());
private Resources() {
throw new AssertionError();
}
/**
* Convenience method for {@link MessageFormat#format(String, Object...)}.
*
* @param pattern the pattern
* @param objects the arguments for the pattern
*
* @return a formatted string
*/
public static String format(String pattern, Object... arguments) {
return MessageFormat.format(pattern, arguments);
}
/**
* Returns the mnemonic for a message.
*
* @param message the message
*
* @return the mnemonic <code>int</code>
*/
public static int getMnemonicInt(String message) {
Integer integer = MNEMONIC_LOOKUP.get(message);
if (integer != null) {
return integer.intValue();
}
return 0;
}
/**
* Initializes all non-final public static fields in the given class with
* messages from a {@link ResourceBundle}.
*
* @param clazz the class containing the fields
*/
public static void initializeMessages(Class<?> clazz, String rbName) {
ResourceBundle rb = null;
try {
rb = ResourceBundle.getBundle(rbName);
} catch (MissingResourceException mre) {
// fall through, handled later
}
for (Field field : clazz.getFields()) {
if (isWritableField(field)) {
String key = field.getName();
String message = getMessage(rb, key);
int mnemonicInt = findMnemonicInt(message);
message = removeMnemonicAmpersand(message);
message = replaceWithPlatformLineFeed(message);
setFieldValue(field, message);
MNEMONIC_LOOKUP.put(message, mnemonicInt);
}
}
}
private static boolean isWritableField(Field field) {
int modifiers = field.getModifiers();
return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
&& !Modifier.isFinal(modifiers);
}
/**
* Returns the message corresponding to the key in the bundle or a text
* describing it's missing.
*
* @param rb the resource bundle
* @param key the key
*
* @return the message
*/
private static String getMessage(ResourceBundle rb, String key) {
if (rb == null) {
return "missing resource bundle";
}
try {
return rb.getString(key);
} catch (MissingResourceException mre) {
return "missing message for key = \"" + key
+ "\" in resource bundle ";
}
}
private static void setFieldValue(Field field, String value) {
try {
field.set(null, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new Error("Unable to access or set message for field " + field.getName());
}
}
/**
* Returns a {@link String} where all <code>\n</code> in the <text> have
* been replaced with the line separator for the platform.
*
* @param text the to be replaced
*
* @return the replaced text
*/
private static String replaceWithPlatformLineFeed(String text) {
return text.replace("\n", System.getProperty("line.separator"));
}
/**
* Removes the mnemonic identifier (<code>&</code>) from a string unless
* it's escaped by <code>&&</code> or placed at the end.
*
* @param message the message
*
* @return a message with the mnemonic identifier removed
*/
private static String removeMnemonicAmpersand(String message) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < message.length(); i++) {
char current = message.charAt(i);
if (current != '&' || i == message.length() - 1
|| message.charAt(i + 1) == '&') {
s.append(current);
}
}
return s.toString();
}
/**
* Finds the mnemonic character in a message.
*
* The mnemonic character is the first character followed by the first
* <code>&</code> that is not followed by another <code>&</code>.
*
* @return the mnemonic as an <code>int</code>, or <code>0</code> if it
* can't be found.
*/
private static int findMnemonicInt(String s) {
for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) == '&') {
if (s.charAt(i + 1) != '&') {
return lookupMnemonicInt(s.substring(i + 1, i + 2));
} else {
i++;
}
}
}
return 0;
}
/**
* Lookups the mnemonic for a key in the {@link KeyEvent} class.
*
* @param c the character to lookup
*
* @return the mnemonic as an <code>int</code>, or <code>0</code> if it
* can't be found.
*/
private static int lookupMnemonicInt(String c) {
try {
return KeyEvent.class.getDeclaredField("VK_" + c.toUpperCase())
.getInt(null);
} catch (IllegalArgumentException | IllegalAccessException
| NoSuchFieldException | SecurityException e) {
// Missing VK is okay
return 0;
}
}
}

View File

@@ -0,0 +1,263 @@
/*
* Copyright (c) 2005, 2006, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.*;
import static javax.swing.JOptionPane.*;
@SuppressWarnings("serial")
public final class SheetDialog {
// Reusable objects
private static Rectangle iconR = new Rectangle();
private static Rectangle textR = new Rectangle();
private static Rectangle viewR = new Rectangle();
private static Insets viewInsets = new Insets(0, 0, 0, 0);
/** Don't let anyone instantiate this class */
private SheetDialog() {
}
static JOptionPane showOptionDialog(final VMPanel vmPanel, Object message,
int optionType, int messageType,
Icon icon, Object[] options, Object initialValue) {
JRootPane rootPane = SwingUtilities.getRootPane(vmPanel);
JPanel glassPane = (JPanel)rootPane.getGlassPane();
if (!(glassPane instanceof SlideAndFadeGlassPane)) {
glassPane = new SlideAndFadeGlassPane();
glassPane.setName(rootPane.getName()+".glassPane");
rootPane.setGlassPane(glassPane);
rootPane.revalidate();
}
final SlideAndFadeGlassPane safGlassPane = (SlideAndFadeGlassPane)glassPane;
// Workaround for the fact that JOptionPane does not handle
// limiting the width when using multi-line html messages.
// See Swing bug 5074006 and JConsole bug 6426317
message = fixWrapping(message, rootPane.getWidth() - 75); // Leave room for icon
final SheetOptionPane optionPane = new SheetOptionPane(message, messageType, optionType,
icon, options, initialValue);
optionPane.setComponentOrientation(vmPanel.getComponentOrientation());
optionPane.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals(VALUE_PROPERTY) &&
event.getNewValue() != null &&
event.getNewValue() != UNINITIALIZED_VALUE) {
((SlideAndFadeGlassPane)optionPane.getParent()).hide(optionPane);
}
}
});
// Delay this (even though we're already on the EDT)
EventQueue.invokeLater(new Runnable() {
public void run() {
safGlassPane.show(optionPane);
}
});
return optionPane;
}
private static Object fixWrapping(Object message, final int maxWidth) {
if (message instanceof Object[]) {
Object[] arr = (Object[])message;
for (int i = 0; i < arr.length; i++) {
arr[i] = fixWrapping(arr[i], maxWidth);
}
} else if (message instanceof String &&
((String)message).startsWith("<html>")) {
message = new JLabel((String)message) {
public Dimension getPreferredSize() {
String text = getText();
Insets insets = getInsets(viewInsets);
FontMetrics fm = getFontMetrics(getFont());
Dimension pref = super.getPreferredSize();
Dimension min = getMinimumSize();
iconR.x = iconR.y = iconR.width = iconR.height = 0;
textR.x = textR.y = textR.width = textR.height = 0;
int dx = insets.left + insets.right;
int dy = insets.top + insets.bottom;
viewR.x = dx;
viewR.y = dy;
viewR.width = viewR.height = Short.MAX_VALUE;
View v = (View)getClientProperty("html");
if (v != null) {
// Use pref width if less than 300, otherwise
// min width up to size of window.
int w = Math.min(maxWidth,
Math.min(pref.width,
Math.max(min.width, 300)));
v.setSize((float)w, 0F);
SwingUtilities.layoutCompoundLabel(this, fm, text, null,
getVerticalAlignment(),
getHorizontalAlignment(),
getVerticalTextPosition(),
getHorizontalTextPosition(),
viewR, iconR, textR,
getIconTextGap());
return new Dimension(textR.width + dx,
textR.height + dy);
} else {
return pref; // Should not happen
}
}
};
}
return message;
}
private static class SlideAndFadeGlassPane extends JPanel {
SheetOptionPane optionPane;
int fade = 20;
boolean slideIn = true;
SlideAndFadeGlassPane() {
super(null);
setVisible(false);
setOpaque(false);
// Grab mouse input, making the dialog modal
addMouseListener(new MouseAdapter() {});
}
public void show(SheetOptionPane optionPane) {
this.optionPane = optionPane;
removeAll();
add(optionPane);
setVisible(true);
slideIn = true;
revalidate();
repaint();
doSlide();
}
public void hide(SheetOptionPane optionPane) {
if (optionPane != this.optionPane) {
return;
}
slideIn = false;
revalidate();
repaint();
doSlide();
}
private void doSlide() {
if (optionPane.getParent() == null) {
return;
}
if (optionPane.getWidth() == 0) {
optionPane.setSize(optionPane.getPreferredSize());
}
int glassPaneWidth = getWidth();
if (glassPaneWidth == 0 && getParent() != null) {
glassPaneWidth = getParent().getWidth();
}
int x = (glassPaneWidth - optionPane.getWidth()) / 2;
if (!slideIn) {
remove(optionPane);
setVisible(false);
return;
} else {
optionPane.setLocation(x, 0);
setGrayLevel(fade);
return;
}
}
public void setGrayLevel(int gray) {
gray = gray * 255 / 100;
setBackground(new Color(0, 0, 0, gray));
}
public void paint(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
super.paint(g);
}
}
static class SheetOptionPane extends JOptionPane {
SheetOptionPane(Object message, int messageType, int optionType,
Icon icon, Object[] options, Object initialValue) {
super(message, messageType, optionType, icon, options, initialValue);
setBorder(new CompoundBorder(new LineBorder(new Color(204, 204, 204), 1),
new EmptyBorder(4, 4, 4, 4)));
}
private static Composite comp =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8F);
private static Color bgColor = new Color(241, 239, 239);
public void setVisible(boolean visible) {
SlideAndFadeGlassPane glassPane = (SlideAndFadeGlassPane)getParent();
if (glassPane != null) {
if (visible) {
glassPane.show(this);
} else {
glassPane.hide(this);
}
}
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
Composite oldComp = g2d.getComposite();
g2d.setComposite(comp);
Color oldColor = g2d.getColor();
g2d.setColor(bgColor);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(oldColor);
g2d.setComposite(oldComp);
super.paint(g);
}
}
}

View File

@@ -0,0 +1,374 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole;
import java.awt.*;
import java.io.*;
import java.lang.management.*;
import java.lang.reflect.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import javax.swing.*;
import static sun.tools.jconsole.Formatter.*;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
class SummaryTab extends Tab {
private static final String cpuUsageKey = "cpu";
private static final String newDivider = "<tr><td colspan=4><font size =-1><hr>";
private static final String newTable = "<tr><td colspan=4 align=left><table cellpadding=1>";
private static final String newLeftTable = "<tr><td colspan=2 align=left><table cellpadding=1>";
private static final String newRightTable = "<td colspan=2 align=left><table cellpadding=1>";
private static final String endTable = "</table>";
private static final int CPU_DECIMALS = 1;
private CPUOverviewPanel overviewPanel;
private DateFormat headerDateTimeFormat;
private String pathSeparator = null;
HTMLPane info;
private static class Result {
long upTime = -1L;
long processCpuTime = -1L;
long timeStamp;
int nCPUs;
String summary;
}
public static String getTabName() {
return Messages.SUMMARY_TAB_TAB_NAME;
}
public SummaryTab(VMPanel vmPanel) {
super(vmPanel, getTabName());
setLayout(new BorderLayout());
info = new HTMLPane();
setAccessibleName(info, getTabName());
add(new JScrollPane(info));
headerDateTimeFormat =
Formatter.getDateTimeFormat(Messages.SUMMARY_TAB_HEADER_DATE_TIME_FORMAT);
}
public SwingWorker<?, ?> newSwingWorker() {
return new SwingWorker<Result, Object>() {
public Result doInBackground() {
return formatSummary();
}
protected void done() {
try {
Result result = get();
if (result != null) {
info.setText(result.summary);
if (overviewPanel != null &&
result.upTime > 0L &&
result.processCpuTime >= 0L) {
overviewPanel.updateCPUInfo(result);
}
}
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
if (JConsole.isDebug()) {
ex.printStackTrace();
}
}
}
};
}
StringBuilder buf;
synchronized Result formatSummary() {
Result result = new Result();
ProxyClient proxyClient = vmPanel.getProxyClient();
if (proxyClient.isDead()) {
return null;
}
buf = new StringBuilder();
append("<table cellpadding=1>");
try {
RuntimeMXBean rmBean = proxyClient.getRuntimeMXBean();
CompilationMXBean cmpMBean = proxyClient.getCompilationMXBean();
ThreadMXBean tmBean = proxyClient.getThreadMXBean();
MemoryMXBean memoryBean = proxyClient.getMemoryMXBean();
ClassLoadingMXBean clMBean = proxyClient.getClassLoadingMXBean();
OperatingSystemMXBean osMBean = proxyClient.getOperatingSystemMXBean();
com.sun.management.OperatingSystemMXBean sunOSMBean =
proxyClient.getSunOperatingSystemMXBean();
append("<tr><td colspan=4>");
append("<center><b>" + Messages.SUMMARY_TAB_TAB_NAME + "</b></center>");
String dateTime =
headerDateTimeFormat.format(System.currentTimeMillis());
append("<center>" + dateTime + "</center>");
append(newDivider);
{ // VM info
append(newLeftTable);
append(Messages.CONNECTION_NAME, vmPanel.getDisplayName());
append(Messages.VIRTUAL_MACHINE,
Resources.format(Messages.SUMMARY_TAB_VM_VERSION,
rmBean.getVmName(), rmBean.getVmVersion()));
append(Messages.VENDOR, rmBean.getVmVendor());
append(Messages.NAME, rmBean.getName());
append(endTable);
append(newRightTable);
result.upTime = rmBean.getUptime();
append(Messages.UPTIME, formatTime(result.upTime));
if (sunOSMBean != null) {
result.processCpuTime = sunOSMBean.getProcessCpuTime();
append(Messages.PROCESS_CPU_TIME, formatNanoTime(result.processCpuTime));
}
if (cmpMBean != null) {
append(Messages.JIT_COMPILER, cmpMBean.getName());
append(Messages.TOTAL_COMPILE_TIME,
cmpMBean.isCompilationTimeMonitoringSupported()
? formatTime(cmpMBean.getTotalCompilationTime())
: Messages.UNAVAILABLE);
} else {
append(Messages.JIT_COMPILER, Messages.UNAVAILABLE);
}
append(endTable);
}
append(newDivider);
{ // Threads and Classes
append(newLeftTable);
int tlCount = tmBean.getThreadCount();
int tdCount = tmBean.getDaemonThreadCount();
int tpCount = tmBean.getPeakThreadCount();
long ttCount = tmBean.getTotalStartedThreadCount();
String[] strings1 = formatLongs(tlCount, tpCount,
tdCount, ttCount);
append(Messages.LIVE_THREADS, strings1[0]);
append(Messages.PEAK, strings1[1]);
append(Messages.DAEMON_THREADS, strings1[2]);
append(Messages.TOTAL_THREADS_STARTED, strings1[3]);
append(endTable);
append(newRightTable);
long clCount = clMBean.getLoadedClassCount();
long cuCount = clMBean.getUnloadedClassCount();
long ctCount = clMBean.getTotalLoadedClassCount();
String[] strings2 = formatLongs(clCount, cuCount, ctCount);
append(Messages.CURRENT_CLASSES_LOADED, strings2[0]);
append(Messages.TOTAL_CLASSES_LOADED, strings2[2]);
append(Messages.TOTAL_CLASSES_UNLOADED, strings2[1]);
append(null, "");
append(endTable);
}
append(newDivider);
{ // Memory
MemoryUsage u = memoryBean.getHeapMemoryUsage();
append(newLeftTable);
String[] strings1 = formatKByteStrings(u.getUsed(), u.getMax());
append(Messages.CURRENT_HEAP_SIZE, strings1[0]);
append(Messages.MAXIMUM_HEAP_SIZE, strings1[1]);
append(endTable);
append(newRightTable);
String[] strings2 = formatKByteStrings(u.getCommitted());
append(Messages.COMMITTED_MEMORY, strings2[0]);
append(Messages.SUMMARY_TAB_PENDING_FINALIZATION_LABEL,
Resources.format(Messages.SUMMARY_TAB_PENDING_FINALIZATION_VALUE,
memoryBean.getObjectPendingFinalizationCount()));
append(endTable);
append(newTable);
Collection<GarbageCollectorMXBean> garbageCollectors =
proxyClient.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) {
String gcName = garbageCollectorMBean.getName();
long gcCount = garbageCollectorMBean.getCollectionCount();
long gcTime = garbageCollectorMBean.getCollectionTime();
append(Messages.GARBAGE_COLLECTOR,
Resources.format(Messages.GC_INFO, gcName, gcCount,
(gcTime >= 0) ? formatTime(gcTime)
: Messages.UNAVAILABLE),
4);
}
append(endTable);
}
append(newDivider);
{ // Operating System info
append(newLeftTable);
String osName = osMBean.getName();
String osVersion = osMBean.getVersion();
String osArch = osMBean.getArch();
result.nCPUs = osMBean.getAvailableProcessors();
append(Messages.OPERATING_SYSTEM, osName + " " + osVersion);
append(Messages.ARCHITECTURE, osArch);
append(Messages.NUMBER_OF_PROCESSORS, result.nCPUs+"");
if (pathSeparator == null) {
// Must use separator of remote OS, not File.pathSeparator
// from this local VM. In the future, consider using
// RuntimeMXBean to get the remote system property.
pathSeparator = osName.startsWith("Windows ") ? ";" : ":";
}
if (sunOSMBean != null) {
String[] kbStrings1 =
formatKByteStrings(sunOSMBean.getCommittedVirtualMemorySize());
String[] kbStrings2 =
formatKByteStrings(sunOSMBean.getTotalPhysicalMemorySize(),
sunOSMBean.getFreePhysicalMemorySize(),
sunOSMBean.getTotalSwapSpaceSize(),
sunOSMBean.getFreeSwapSpaceSize());
append(Messages.COMMITTED_VIRTUAL_MEMORY, kbStrings1[0]);
append(endTable);
append(newRightTable);
append(Messages.TOTAL_PHYSICAL_MEMORY, kbStrings2[0]);
append(Messages.FREE_PHYSICAL_MEMORY, kbStrings2[1]);
append(Messages.TOTAL_SWAP_SPACE, kbStrings2[2]);
append(Messages.FREE_SWAP_SPACE, kbStrings2[3]);
}
append(endTable);
}
append(newDivider);
{ // VM arguments and paths
append(newTable);
String args = "";
java.util.List<String> inputArguments = rmBean.getInputArguments();
for (String arg : inputArguments) {
args += arg + " ";
}
append(Messages.VM_ARGUMENTS, args, 4);
append(Messages.CLASS_PATH, rmBean.getClassPath(), 4);
append(Messages.LIBRARY_PATH, rmBean.getLibraryPath(), 4);
append(Messages.BOOT_CLASS_PATH,
rmBean.isBootClassPathSupported()
? rmBean.getBootClassPath()
: Messages.UNAVAILABLE,
4);
append(endTable);
}
} catch (IOException e) {
if (JConsole.isDebug()) {
e.printStackTrace();
}
proxyClient.markAsDead();
return null;
} catch (UndeclaredThrowableException e) {
if (JConsole.isDebug()) {
e.printStackTrace();
}
proxyClient.markAsDead();
return null;
}
append("</table>");
result.timeStamp = System.currentTimeMillis();
result.summary = buf.toString();
return result;
}
private synchronized void append(String str) {
buf.append(str);
}
void append(String label, String value) {
append(newRow(label, value));
}
private void append(String label, String value, int columnPerRow) {
if (columnPerRow == 4 && pathSeparator != null) {
value = value.replace(pathSeparator,
"<b></b>" + pathSeparator);
}
append(newRow(label, value, columnPerRow));
}
OverviewPanel[] getOverviewPanels() {
if (overviewPanel == null) {
overviewPanel = new CPUOverviewPanel();
}
return new OverviewPanel[] { overviewPanel };
}
private static class CPUOverviewPanel extends OverviewPanel {
private long prevUpTime, prevProcessCpuTime;
CPUOverviewPanel() {
super(Messages.CPU_USAGE, cpuUsageKey, Messages.CPU_USAGE, Plotter.Unit.PERCENT);
getPlotter().setDecimals(CPU_DECIMALS);
}
public void updateCPUInfo(Result result) {
if (prevUpTime > 0L && result.upTime > prevUpTime) {
// elapsedCpu is in ns and elapsedTime is in ms.
long elapsedCpu = result.processCpuTime - prevProcessCpuTime;
long elapsedTime = result.upTime - prevUpTime;
// cpuUsage could go higher than 100% because elapsedTime
// and elapsedCpu are not fetched simultaneously. Limit to
// 99% to avoid Plotter showing a scale from 0% to 200%.
float cpuUsage =
Math.min(99F,
elapsedCpu / (elapsedTime * 10000F * result.nCPUs));
cpuUsage = Math.max(0F, cpuUsage);
getPlotter().addValues(result.timeStamp,
Math.round(cpuUsage * Math.pow(10.0, CPU_DECIMALS)));
getInfoLabel().setText(Resources.format(Messages.CPU_USAGE_FORMAT,
String.format("%."+CPU_DECIMALS+"f", cpuUsage)));
}
this.prevUpTime = result.upTime;
this.prevProcessCpuTime = result.processCpuTime;
}
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import javax.swing.*;
public abstract class Tab extends JPanel {
private String name;
private Worker worker;
protected VMPanel vmPanel;
private SwingWorker<?, ?> prevSW;
public Tab(VMPanel vmPanel, String name) {
this.vmPanel = vmPanel;
this.name = name;
}
public SwingWorker<?, ?> newSwingWorker() {
return null;
}
public void update() {
final ProxyClient proxyClient = vmPanel.getProxyClient();
if (!proxyClient.hasPlatformMXBeans()) {
throw new UnsupportedOperationException(
"Platform MXBeans not registered in MBeanServer");
}
SwingWorker<?,?> sw = newSwingWorker();
// schedule SwingWorker to run only if the previous
// SwingWorker has finished its task and it hasn't started.
if (prevSW == null || prevSW.isDone()) {
if (sw == null || sw.getState() == SwingWorker.StateValue.PENDING) {
prevSW = sw;
if (sw != null) {
sw.execute();
}
}
}
}
public synchronized void dispose() {
if(worker != null)
worker.stopWorker();
// Subclasses will override to clean up
}
protected VMPanel getVMPanel() {
return vmPanel;
}
OverviewPanel[] getOverviewPanels() {
return null;
}
public synchronized void workerAdd(Runnable job) {
if (worker == null) {
worker = new Worker(name+"-"+vmPanel.getConnectionName());
worker.start();
}
worker.add(job);
}
public Dimension getPreferredSize() {
return new Dimension(700, 500);
}
}

View File

@@ -0,0 +1,695 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.management.*;
import java.lang.reflect.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.List;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
class ThreadTab extends Tab implements ActionListener, DocumentListener, ListSelectionListener {
PlotterPanel threadMeter;
TimeComboBox timeComboBox;
JTabbedPane threadListTabbedPane;
DefaultListModel<Long> listModel;
JTextField filterTF;
JLabel messageLabel;
JSplitPane threadsSplitPane;
HashMap<Long, String> nameCache = new HashMap<Long, String>();
private ThreadOverviewPanel overviewPanel;
private boolean plotterListening = false;
private static final String threadCountKey = "threadCount";
private static final String peakKey = "peak";
private static final Color threadCountColor = Plotter.defaultColor;
private static final Color peakColor = Color.red;
private static final Border thinEmptyBorder = new EmptyBorder(2, 2, 2, 2);
/*
Hierarchy of panels and layouts for this tab:
ThreadTab (BorderLayout)
North: topPanel (BorderLayout)
Center: controlPanel (FlowLayout)
timeComboBox
Center: plotterPanel (BorderLayout)
Center: plotter
*/
public static String getTabName() {
return Messages.THREADS;
}
public ThreadTab(VMPanel vmPanel) {
super(vmPanel, getTabName());
setLayout(new BorderLayout(0, 0));
setBorder(new EmptyBorder(4, 4, 3, 4));
JPanel topPanel = new JPanel(new BorderLayout());
JPanel plotterPanel = new JPanel(new VariableGridLayout(0, 1, 4, 4, true, true));
add(topPanel, BorderLayout.NORTH);
add(plotterPanel, BorderLayout.CENTER);
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 5));
topPanel.add(controlPanel, BorderLayout.CENTER);
threadMeter = new PlotterPanel(Messages.NUMBER_OF_THREADS,
Plotter.Unit.NONE, true);
threadMeter.plotter.createSequence(threadCountKey, Messages.LIVE_THREADS, threadCountColor, true);
threadMeter.plotter.createSequence(peakKey, Messages.PEAK, peakColor, true);
setAccessibleName(threadMeter.plotter,
Messages.THREAD_TAB_THREAD_PLOTTER_ACCESSIBLE_NAME);
plotterPanel.add(threadMeter);
timeComboBox = new TimeComboBox(threadMeter.plotter);
controlPanel.add(new LabeledComponent(Messages.TIME_RANGE_COLON,
Resources.getMnemonicInt(Messages.TIME_RANGE_COLON),
timeComboBox));
listModel = new DefaultListModel<Long>();
JTextArea textArea = new JTextArea();
textArea.setBorder(thinEmptyBorder);
textArea.setEditable(false);
setAccessibleName(textArea,
Messages.THREAD_TAB_THREAD_INFO_ACCESSIBLE_NAME);
ThreadJList list = new ThreadJList(listModel, textArea);
Dimension di = new Dimension(super.getPreferredSize());
di.width = Math.min(di.width, 200);
JScrollPane threadlistSP = new JScrollPane(list);
threadlistSP.setPreferredSize(di);
threadlistSP.setBorder(null);
JScrollPane textAreaSP = new JScrollPane(textArea);
textAreaSP.setBorder(null);
threadListTabbedPane = new JTabbedPane(JTabbedPane.TOP);
threadsSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
threadlistSP, textAreaSP);
threadsSplitPane.setOneTouchExpandable(true);
threadsSplitPane.setBorder(null);
JPanel firstTabPanel = new JPanel(new BorderLayout());
firstTabPanel.setOpaque(false);
JPanel firstTabToolPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 2));
firstTabToolPanel.setOpaque(false);
filterTF = new PromptingTextField("Filter", 20);
filterTF.getDocument().addDocumentListener(this);
firstTabToolPanel.add(filterTF);
JSeparator separator = new JSeparator(JSeparator.VERTICAL);
separator.setPreferredSize(new Dimension(separator.getPreferredSize().width,
filterTF.getPreferredSize().height));
firstTabToolPanel.add(separator);
JButton detectDeadlockButton = new JButton(Messages.DETECT_DEADLOCK);
detectDeadlockButton.setMnemonic(Resources.getMnemonicInt(Messages.DETECT_DEADLOCK));
detectDeadlockButton.setActionCommand("detectDeadlock");
detectDeadlockButton.addActionListener(this);
detectDeadlockButton.setToolTipText(Messages.DETECT_DEADLOCK_TOOLTIP);
firstTabToolPanel.add(detectDeadlockButton);
messageLabel = new JLabel();
firstTabToolPanel.add(messageLabel);
firstTabPanel.add(threadsSplitPane, BorderLayout.CENTER);
firstTabPanel.add(firstTabToolPanel, BorderLayout.SOUTH);
threadListTabbedPane.addTab(Messages.THREADS, firstTabPanel);
plotterPanel.add(threadListTabbedPane);
}
private long oldThreads[] = new long[0];
public SwingWorker<?, ?> newSwingWorker() {
final ProxyClient proxyClient = vmPanel.getProxyClient();
if (!plotterListening) {
proxyClient.addWeakPropertyChangeListener(threadMeter.plotter);
plotterListening = true;
}
return new SwingWorker<Boolean, Object>() {
private int tlCount;
private int tpCount;
private long ttCount;
private long[] threads;
private long timeStamp;
public Boolean doInBackground() {
try {
ThreadMXBean threadMBean = proxyClient.getThreadMXBean();
tlCount = threadMBean.getThreadCount();
tpCount = threadMBean.getPeakThreadCount();
if (overviewPanel != null) {
ttCount = threadMBean.getTotalStartedThreadCount();
} else {
ttCount = 0L;
}
threads = threadMBean.getAllThreadIds();
for (long newThread : threads) {
if (nameCache.get(newThread) == null) {
ThreadInfo ti = threadMBean.getThreadInfo(newThread);
if (ti != null) {
String name = ti.getThreadName();
if (name != null) {
nameCache.put(newThread, name);
}
}
}
}
timeStamp = System.currentTimeMillis();
return true;
} catch (IOException e) {
return false;
} catch (UndeclaredThrowableException e) {
return false;
}
}
protected void done() {
try {
if (!get()) {
return;
}
} catch (InterruptedException ex) {
return;
} catch (ExecutionException ex) {
if (JConsole.isDebug()) {
ex.printStackTrace();
}
return;
}
threadMeter.plotter.addValues(timeStamp, tlCount, tpCount);
threadMeter.setValueLabel(tlCount+"");
if (overviewPanel != null) {
overviewPanel.updateThreadsInfo(tlCount, tpCount, ttCount, timeStamp);
}
String filter = filterTF.getText().toLowerCase(Locale.ENGLISH);
boolean doFilter = (filter.length() > 0);
ArrayList<Long> l = new ArrayList<Long>();
for (long t : threads) {
l.add(t);
}
Iterator<Long> iterator = l.iterator();
while (iterator.hasNext()) {
long newThread = iterator.next();
String name = nameCache.get(newThread);
if (doFilter && name != null &&
name.toLowerCase(Locale.ENGLISH).indexOf(filter) < 0) {
iterator.remove();
}
}
long[] newThreads = threads;
if (l.size() < threads.length) {
newThreads = new long[l.size()];
for (int i = 0; i < newThreads.length; i++) {
newThreads[i] = l.get(i);
}
}
for (long oldThread : oldThreads) {
boolean found = false;
for (long newThread : newThreads) {
if (newThread == oldThread) {
found = true;
break;
}
}
if (!found) {
listModel.removeElement(oldThread);
if (!doFilter) {
nameCache.remove(oldThread);
}
}
}
// Threads are in reverse chronological order
for (int i = newThreads.length - 1; i >= 0; i--) {
long newThread = newThreads[i];
boolean found = false;
for (long oldThread : oldThreads) {
if (newThread == oldThread) {
found = true;
break;
}
}
if (!found) {
listModel.addElement(newThread);
}
}
oldThreads = newThreads;
}
};
}
long lastSelected = -1;
public void valueChanged(ListSelectionEvent ev) {
ThreadJList list = (ThreadJList)ev.getSource();
final JTextArea textArea = list.textArea;
Long selected = (Long)list.getSelectedValue();
if (selected == null) {
if (lastSelected != -1) {
selected = lastSelected;
}
} else {
lastSelected = selected;
}
textArea.setText("");
if (selected != null) {
final long threadID = selected;
workerAdd(new Runnable() {
public void run() {
ProxyClient proxyClient = vmPanel.getProxyClient();
StringBuilder sb = new StringBuilder();
try {
ThreadMXBean threadMBean = proxyClient.getThreadMXBean();
ThreadInfo ti = null;
MonitorInfo[] monitors = null;
if (proxyClient.isLockUsageSupported() &&
threadMBean.isObjectMonitorUsageSupported()) {
// VMs that support the monitor usage monitoring
ThreadInfo[] infos = threadMBean.dumpAllThreads(true, false);
for (ThreadInfo info : infos) {
if (info.getThreadId() == threadID) {
ti = info;
monitors = info.getLockedMonitors();
break;
}
}
} else {
// VM doesn't support monitor usage monitoring
ti = threadMBean.getThreadInfo(threadID, Integer.MAX_VALUE);
}
if (ti != null) {
if (ti.getLockName() == null) {
sb.append(Resources.format(Messages.NAME_STATE,
ti.getThreadName(),
ti.getThreadState().toString()));
} else if (ti.getLockOwnerName() == null) {
sb.append(Resources.format(Messages.NAME_STATE_LOCK_NAME,
ti.getThreadName(),
ti.getThreadState().toString(),
ti.getLockName()));
} else {
sb.append(Resources.format(Messages.NAME_STATE_LOCK_NAME_LOCK_OWNER,
ti.getThreadName(),
ti.getThreadState().toString(),
ti.getLockName(),
ti.getLockOwnerName()));
}
sb.append(Resources.format(Messages.BLOCKED_COUNT_WAITED_COUNT,
ti.getBlockedCount(),
ti.getWaitedCount()));
sb.append(Messages.STACK_TRACE);
int index = 0;
for (StackTraceElement e : ti.getStackTrace()) {
sb.append(e.toString()+"\n");
if (monitors != null) {
for (MonitorInfo mi : monitors) {
if (mi.getLockedStackDepth() == index) {
sb.append(Resources.format(Messages.MONITOR_LOCKED, mi.toString()));
}
}
}
index++;
}
}
} catch (IOException ex) {
// Ignore
} catch (UndeclaredThrowableException e) {
proxyClient.markAsDead();
}
final String text = sb.toString();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.setText(text);
textArea.setCaretPosition(0);
}
});
}
});
}
}
private void doUpdate() {
workerAdd(new Runnable() {
public void run() {
update();
}
});
}
private void detectDeadlock() {
workerAdd(new Runnable() {
public void run() {
try {
final Long[][] deadlockedThreads = getDeadlockedThreadIds();
if (deadlockedThreads == null || deadlockedThreads.length == 0) {
// Display message for 30 seconds. Do it on a separate thread so
// the sleep won't hold up the worker queue.
// This will be replaced later by separate statusbar logic.
new Thread() {
public void run() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
String msg = Messages.NO_DEADLOCK_DETECTED;
messageLabel.setText(msg);
threadListTabbedPane.revalidate();
}
});
sleep(30 * 1000);
} catch (InterruptedException ex) {
// Ignore
} catch (InvocationTargetException ex) {
// Ignore
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
messageLabel.setText("");
}
});
}
}.start();
return;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Remove old deadlock tabs
while (threadListTabbedPane.getTabCount() > 1) {
threadListTabbedPane.removeTabAt(1);
}
if (deadlockedThreads != null) {
for (int i = 0; i < deadlockedThreads.length; i++) {
DefaultListModel<Long> listModel = new DefaultListModel<Long>();
JTextArea textArea = new JTextArea();
textArea.setBorder(thinEmptyBorder);
textArea.setEditable(false);
setAccessibleName(textArea,
Messages.THREAD_TAB_THREAD_INFO_ACCESSIBLE_NAME);
ThreadJList list = new ThreadJList(listModel, textArea);
JScrollPane threadlistSP = new JScrollPane(list);
JScrollPane textAreaSP = new JScrollPane(textArea);
threadlistSP.setBorder(null);
textAreaSP.setBorder(null);
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
threadlistSP, textAreaSP);
splitPane.setOneTouchExpandable(true);
splitPane.setBorder(null);
splitPane.setDividerLocation(threadsSplitPane.getDividerLocation());
String tabName;
if (deadlockedThreads.length > 1) {
tabName = Resources.format(Messages.DEADLOCK_TAB_N, i+1);
} else {
tabName = Messages.DEADLOCK_TAB;
}
threadListTabbedPane.addTab(tabName, splitPane);
for (long t : deadlockedThreads[i]) {
listModel.addElement(t);
}
}
threadListTabbedPane.setSelectedIndex(1);
}
}
});
} catch (IOException e) {
// Ignore
} catch (UndeclaredThrowableException e) {
vmPanel.getProxyClient().markAsDead();
}
}
});
}
// Return deadlocked threads or null
public Long[][] getDeadlockedThreadIds() throws IOException {
ProxyClient proxyClient = vmPanel.getProxyClient();
ThreadMXBean threadMBean = proxyClient.getThreadMXBean();
long[] ids = proxyClient.findDeadlockedThreads();
if (ids == null) {
return null;
}
ThreadInfo[] infos = threadMBean.getThreadInfo(ids, Integer.MAX_VALUE);
List<Long[]> dcycles = new ArrayList<Long[]>();
List<Long> cycle = new ArrayList<Long>();
// keep track of which thread is visited
// one thread can only be in one cycle
boolean[] visited = new boolean[ids.length];
int deadlockedThread = -1; // Index into arrays
while (true) {
if (deadlockedThread < 0) {
if (cycle.size() > 0) {
// a cycle found
dcycles.add(cycle.toArray(new Long[0]));
cycle = new ArrayList<Long>();
}
// start a new cycle from a non-visited thread
for (int j = 0; j < ids.length; j++) {
if (!visited[j]) {
deadlockedThread = j;
visited[j] = true;
break;
}
}
if (deadlockedThread < 0) {
// done
break;
}
}
cycle.add(ids[deadlockedThread]);
long nextThreadId = infos[deadlockedThread].getLockOwnerId();
for (int j = 0; j < ids.length; j++) {
ThreadInfo ti = infos[j];
if (ti.getThreadId() == nextThreadId) {
if (visited[j]) {
deadlockedThread = -1;
} else {
deadlockedThread = j;
visited[j] = true;
}
break;
}
}
}
return dcycles.toArray(new Long[0][0]);
}
// ActionListener interface
public void actionPerformed(ActionEvent evt) {
String cmd = ((AbstractButton)evt.getSource()).getActionCommand();
if (cmd == "detectDeadlock") {
messageLabel.setText("");
detectDeadlock();
}
}
// DocumentListener interface
public void insertUpdate(DocumentEvent e) {
doUpdate();
}
public void removeUpdate(DocumentEvent e) {
doUpdate();
}
public void changedUpdate(DocumentEvent e) {
doUpdate();
}
private class ThreadJList extends JList<Long> {
private JTextArea textArea;
ThreadJList(DefaultListModel<Long> listModel, JTextArea textArea) {
super(listModel);
this.textArea = textArea;
setBorder(thinEmptyBorder);
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
textArea.setText(Messages.THREAD_TAB_INITIAL_STACK_TRACE_MESSAGE);
addListSelectionListener(ThreadTab.this);
setCellRenderer(new DefaultListCellRenderer() {
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value != null) {
String name = nameCache.get(value);
if (name == null) {
name = value.toString();
}
setText(name);
}
return this;
}
});
}
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.width = Math.max(d.width, 100);
return d;
}
}
private class PromptingTextField extends JTextField implements FocusListener {
private String prompt;
boolean promptRemoved = false;
Color fg;
public PromptingTextField(String prompt, int columns) {
super(prompt, columns);
this.prompt = prompt;
updateForeground();
addFocusListener(this);
setAccessibleName(this, prompt);
}
@Override
public void revalidate() {
super.revalidate();
updateForeground();
}
private void updateForeground() {
this.fg = UIManager.getColor("TextField.foreground");
if (promptRemoved) {
setForeground(fg);
} else {
setForeground(Color.gray);
}
}
public String getText() {
if (!promptRemoved) {
return "";
} else {
return super.getText();
}
}
public void focusGained(FocusEvent e) {
if (!promptRemoved) {
setText("");
setForeground(fg);
promptRemoved = true;
}
}
public void focusLost(FocusEvent e) {
if (promptRemoved && getText().equals("")) {
setText(prompt);
setForeground(Color.gray);
promptRemoved = false;
}
}
}
OverviewPanel[] getOverviewPanels() {
if (overviewPanel == null) {
overviewPanel = new ThreadOverviewPanel();
}
return new OverviewPanel[] { overviewPanel };
}
private static class ThreadOverviewPanel extends OverviewPanel {
ThreadOverviewPanel() {
super(Messages.THREADS, threadCountKey, Messages.LIVE_THREADS, null);
}
private void updateThreadsInfo(long tlCount, long tpCount, long ttCount, long timeStamp) {
getPlotter().addValues(timeStamp, tlCount);
getInfoLabel().setText(Resources.format(Messages.THREAD_TAB_INFO_LABEL_FORMAT, tlCount, tpCount, ttCount));
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2004, 2006, 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 sun.tools.jconsole;
import java.awt.event.*;
import java.beans.*;
import java.util.*;
import javax.swing.*;
/**
* A combo box to control the visible time range for one or more Plotter components.
* When used with two or more Plotters, it also acts to coordinate the range between
* them.
*/
@SuppressWarnings("serial")
public class TimeComboBox extends JComboBox implements ItemListener, PropertyChangeListener {
private ArrayList<Plotter> plotters = new ArrayList<Plotter>();
public TimeComboBox(Plotter... plotterArray) {
super(Plotter.rangeNames);
addItemListener(this);
if (plotterArray != null && plotterArray.length > 0) {
plotters.addAll(Arrays.asList(plotterArray));
selectValue(plotterArray[0].getViewRange());
for (Plotter plotter : plotters) {
plotter.addPropertyChangeListener(this);
}
}
}
public void addPlotter(Plotter plotter) {
plotters.add(plotter);
if (plotters.size() == 1) {
selectValue(plotter.getViewRange());
}
plotter.addPropertyChangeListener(this);
}
public void itemStateChanged(ItemEvent ev) {
for (Plotter plotter : plotters) {
plotter.setViewRange(Plotter.rangeValues[getSelectedIndex()]);
}
}
private void selectValue(int value) {
// Set the selected value
for (int i = 0; i < Plotter.rangeValues.length; i++) {
if (Plotter.rangeValues[i] == value) {
setSelectedItem(Plotter.rangeNames[i]);
}
}
// Make sure all plotters show this value
if (plotters.size() > 1) {
for (Plotter plotter : plotters) {
plotter.setViewRange(value);
}
}
}
public void propertyChange(PropertyChangeEvent ev) {
if (ev.getPropertyName() == "viewRange") {
selectValue((Integer)ev.getNewValue());
}
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2005, 2006, 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 sun.tools.jconsole;
import java.awt.*;
import javax.accessibility.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.tree.*;
import sun.tools.jconsole.inspector.*;
import static java.lang.Math.*;
/**
* Miscellaneous utility methods for JConsole
*/
public class Utilities {
private static final String windowsLaF =
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
public static void updateTransparency(JComponent comp) {
LookAndFeel laf = UIManager.getLookAndFeel();
boolean transparent = laf.getClass().getName().equals(windowsLaF);
setTabbedPaneTransparency(comp, transparent);
}
private static void setTabbedPaneTransparency(JComponent comp, boolean transparent) {
for (Component child : comp.getComponents()) {
if (comp instanceof JTabbedPane) {
setTransparency((JComponent)child, transparent);
} else if (child instanceof JComponent) {
setTabbedPaneTransparency((JComponent)child, transparent);
}
}
}
private static void setTransparency(JComponent comp, boolean transparent) {
comp.setOpaque(!transparent);
for (Component child : comp.getComponents()) {
if (child instanceof JPanel ||
child instanceof JSplitPane ||
child instanceof JScrollPane ||
child instanceof JViewport ||
child instanceof JCheckBox) {
setTransparency((JComponent)child, transparent);
}
if (child instanceof XTree) {
XTree t = (XTree)child;
DefaultTreeCellRenderer cr = (DefaultTreeCellRenderer)t.getCellRenderer();
cr.setBackground(null);
cr.setBackgroundNonSelectionColor(new Color(0, 0, 0, 1));
t.setCellRenderer(cr);
setTransparency((JComponent)child, transparent);
}
}
}
/**
* A slightly modified border for JScrollPane to be used with a JTable inside
* a JTabbedPane. It has only top part and the rest is clipped to make the
* overall border less thick.
* The top border helps differentiating the containing table from its container.
*/
public static JScrollPane newTableScrollPane(JComponent comp) {
return new TableScrollPane(comp);
}
@SuppressWarnings("serial")
private static class TableScrollPane extends JScrollPane {
public TableScrollPane(JComponent comp) {
super(comp);
}
protected void paintBorder(Graphics g) {
Border border = getBorder();
if (border != null) {
Insets insets = border.getBorderInsets(this);
if (insets != null) {
Shape oldClip = g.getClip();
g.clipRect(0, 0, getWidth(), insets.top);
super.paintBorder(g);
g.setClip(oldClip);
}
}
}
}
public static void setAccessibleName(Accessible comp, String name) {
comp.getAccessibleContext().setAccessibleName(name);
}
public static void setAccessibleDescription(Accessible comp, String description) {
comp.getAccessibleContext().setAccessibleDescription(description);
}
/**
* Modifies color c1 to ensure it has acceptable contrast
* relative to color c2.
*
* http://www.w3.org/TR/AERT#color-contrast
* http://www.cs.rit.edu/~ncs/color/t_convert.html#RGB%20to%20YIQ%20&%20YIQ%20to%20RGB
*/
public static Color ensureContrast(Color c1, Color c2) {
double y1 = getColorBrightness(c1);
double y2 = getColorBrightness(c2);
if (abs(y1 - y2) < 125.0) {
if (y2 < 128.0) {
c1 = setColorBrightness(c1, y2 + 125.0);
} else {
c1 = setColorBrightness(c1, y2 - 125.0);
}
}
return c1;
}
public static double getColorBrightness(Color c) {
// Convert RGB -> YIQ and return the Y value
return (c.getRed() * 0.299 + c.getGreen() * 0.587 + c.getBlue() * 0.114);
}
private static Color setColorBrightness(Color c, double y) {
// Convert YIQ -> RGB
double i = (c.getRed() * 0.596 - c.getGreen() * 0.275 - c.getBlue() * 0.321);
double q = (c.getRed() * 0.212 - c.getGreen() * 0.523 + c.getBlue() * 0.311);
// Keep values in legal range. This may reduce the
// achieved contrast somewhat.
int r = max(0, min(255, (int)round(y + i * 0.956 + q * 0.621)));
int g = max(0, min(255, (int)round(y - i * 0.272 - q * 0.647)));
int b = max(0, min(255, (int)round(y - i * 1.105 + q * 1.702)));
return new Color(r, g, b);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import javax.swing.*;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
public class VMInternalFrame extends MaximizableInternalFrame {
private VMPanel vmPanel;
public VMInternalFrame(VMPanel vmPanel) {
super("", true, true, true, true);
this.vmPanel = vmPanel;
setAccessibleDescription(this,
Messages.VMINTERNAL_FRAME_ACCESSIBLE_DESCRIPTION);
getContentPane().add(vmPanel, BorderLayout.CENTER);
pack();
vmPanel.updateFrameTitle();
}
public VMPanel getVMPanel() {
return vmPanel;
}
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
JDesktopPane desktop = getDesktopPane();
if (desktop != null) {
Dimension desktopSize = desktop.getSize();
if (desktopSize.width > 0 && desktopSize.height > 0) {
d.width = Math.min(desktopSize.width - 40, d.width);
d.height = Math.min(desktopSize.height - 40, d.height);
}
}
return d;
}
}

View File

@@ -0,0 +1,668 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.List;
import java.util.Timer;
import javax.swing.*;
import javax.swing.plaf.*;
import com.sun.tools.jconsole.JConsolePlugin;
import com.sun.tools.jconsole.JConsoleContext;
import static sun.tools.jconsole.ProxyClient.*;
@SuppressWarnings("serial")
public class VMPanel extends JTabbedPane implements PropertyChangeListener {
private ProxyClient proxyClient;
private Timer timer;
private int updateInterval;
private String hostName;
private int port;
private String userName;
private String password;
private String url;
private VMInternalFrame vmIF = null;
private static ArrayList<TabInfo> tabInfos = new ArrayList<TabInfo>();
private boolean wasConnected = false;
private boolean userDisconnected = false;
private boolean shouldUseSSL = true;
// The everConnected flag keeps track of whether the window can be
// closed if the user clicks Cancel after a failed connection attempt.
//
private boolean everConnected = false;
// The initialUpdate flag is used to enable/disable tabs each time
// a connect or reconnect takes place. This flag avoids having to
// enable/disable tabs on each update call.
//
private boolean initialUpdate = true;
// Each VMPanel has its own instance of the JConsolePlugin
// A map of JConsolePlugin to the previous SwingWorker
private Map<ExceptionSafePlugin, SwingWorker<?, ?>> plugins = null;
private boolean pluginTabsAdded = false;
// Update these only on the EDT
private JOptionPane optionPane;
private JProgressBar progressBar;
private long time0;
static {
tabInfos.add(new TabInfo(OverviewTab.class, OverviewTab.getTabName(), true));
tabInfos.add(new TabInfo(MemoryTab.class, MemoryTab.getTabName(), true));
tabInfos.add(new TabInfo(ThreadTab.class, ThreadTab.getTabName(), true));
tabInfos.add(new TabInfo(ClassTab.class, ClassTab.getTabName(), true));
tabInfos.add(new TabInfo(SummaryTab.class, SummaryTab.getTabName(), true));
tabInfos.add(new TabInfo(MBeansTab.class, MBeansTab.getTabName(), true));
}
public static TabInfo[] getTabInfos() {
return tabInfos.toArray(new TabInfo[tabInfos.size()]);
}
VMPanel(ProxyClient proxyClient, int updateInterval) {
this.proxyClient = proxyClient;
this.updateInterval = updateInterval;
this.hostName = proxyClient.getHostName();
this.port = proxyClient.getPort();
this.userName = proxyClient.getUserName();
this.password = proxyClient.getPassword();
this.url = proxyClient.getUrl();
for (TabInfo tabInfo : tabInfos) {
if (tabInfo.tabVisible) {
addTab(tabInfo);
}
}
plugins = new LinkedHashMap<ExceptionSafePlugin, SwingWorker<?, ?>>();
for (JConsolePlugin p : JConsole.getPlugins()) {
p.setContext(proxyClient);
plugins.put(new ExceptionSafePlugin(p), null);
}
Utilities.updateTransparency(this);
ToolTipManager.sharedInstance().registerComponent(this);
// Start listening to connection state events
//
proxyClient.addPropertyChangeListener(this);
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (connectedIconBounds != null && (e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0 && connectedIconBounds.contains(e.getPoint())) {
if (isConnected()) {
userDisconnected = true;
disconnect();
wasConnected = false;
} else {
connect();
}
repaint();
}
}
});
}
private static Icon connectedIcon16 =
new ImageIcon(VMPanel.class.getResource("resources/connected16.png"));
private static Icon connectedIcon24 =
new ImageIcon(VMPanel.class.getResource("resources/connected24.png"));
private static Icon disconnectedIcon16 =
new ImageIcon(VMPanel.class.getResource("resources/disconnected16.png"));
private static Icon disconnectedIcon24 =
new ImageIcon(VMPanel.class.getResource("resources/disconnected24.png"));
private Rectangle connectedIconBounds;
// Override to increase right inset for tab area,
// in order to reserve space for the connect toggle.
public void setUI(TabbedPaneUI ui) {
Insets insets = (Insets) UIManager.getLookAndFeelDefaults().get("TabbedPane.tabAreaInsets");
if (insets != null) {
insets = (Insets) insets.clone();
insets.right += connectedIcon24.getIconWidth() + 8;
UIManager.put("TabbedPane.tabAreaInsets", insets);
}
super.setUI(ui);
}
// Override to paint the connect toggle
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Icon icon;
Component c0 = getComponent(0);
if (c0 != null && c0.getY() > 24) {
icon = isConnected() ? connectedIcon24 : disconnectedIcon24;
} else {
icon = isConnected() ? connectedIcon16 : disconnectedIcon16;
}
Insets insets = getInsets();
int x = getWidth() - insets.right - icon.getIconWidth() - 4;
int y = insets.top;
if (c0 != null) {
y = (c0.getY() - icon.getIconHeight()) / 2;
}
icon.paintIcon(this, g, x, y);
connectedIconBounds = new Rectangle(x, y, icon.getIconWidth(), icon.getIconHeight());
}
public String getToolTipText(MouseEvent event) {
if (connectedIconBounds.contains(event.getPoint())) {
if (isConnected()) {
return Messages.CONNECTED_PUNCTUATION_CLICK_TO_DISCONNECT_;
} else {
return Messages.DISCONNECTED_PUNCTUATION_CLICK_TO_CONNECT_;
}
} else {
return super.getToolTipText(event);
}
}
private synchronized void addTab(TabInfo tabInfo) {
Tab tab = instantiate(tabInfo);
if (tab != null) {
addTab(tabInfo.name, tab);
} else {
tabInfo.tabVisible = false;
}
}
private synchronized void insertTab(TabInfo tabInfo, int index) {
Tab tab = instantiate(tabInfo);
if (tab != null) {
insertTab(tabInfo.name, null, tab, null, index);
} else {
tabInfo.tabVisible = false;
}
}
public synchronized void removeTabAt(int index) {
super.removeTabAt(index);
}
private Tab instantiate(TabInfo tabInfo) {
try {
Constructor<?> con = tabInfo.tabClass.getConstructor(VMPanel.class);
return (Tab) con.newInstance(this);
} catch (Exception ex) {
System.err.println(ex);
return null;
}
}
boolean isConnected() {
return proxyClient.isConnected();
}
public int getUpdateInterval() {
return updateInterval;
}
/**
* WARNING NEVER CALL THIS METHOD TO MAKE JMX REQUEST
* IF assertThread == false.
* DISPATCHER THREAD IS NOT ASSERTED.
* IT IS USED TO MAKE SOME LOCAL MANIPULATIONS.
*/
ProxyClient getProxyClient(boolean assertThread) {
if (assertThread) {
return getProxyClient();
} else {
return proxyClient;
}
}
public ProxyClient getProxyClient() {
String threadClass = Thread.currentThread().getClass().getName();
if (threadClass.equals("java.awt.EventDispatchThread")) {
String msg = "Calling VMPanel.getProxyClient() from the Event Dispatch Thread!";
new RuntimeException(msg).printStackTrace();
System.exit(1);
}
return proxyClient;
}
public void cleanUp() {
//proxyClient.disconnect();
for (Tab tab : getTabs()) {
tab.dispose();
}
for (JConsolePlugin p : plugins.keySet()) {
p.dispose();
}
// Cancel pending update tasks
//
if (timer != null) {
timer.cancel();
}
// Stop listening to connection state events
//
proxyClient.removePropertyChangeListener(this);
}
// Call on EDT
public void connect() {
if (isConnected()) {
// create plugin tabs if not done
createPluginTabs();
// Notify tabs
fireConnectedChange(true);
// Enable/disable tabs on initial update
initialUpdate = true;
// Start/Restart update timer on connect/reconnect
startUpdateTimer();
} else {
new Thread("VMPanel.connect") {
public void run() {
proxyClient.connect(shouldUseSSL);
}
}.start();
}
}
// Call on EDT
public void disconnect() {
proxyClient.disconnect();
updateFrameTitle();
}
// Called on EDT
public void propertyChange(PropertyChangeEvent ev) {
String prop = ev.getPropertyName();
if (prop == CONNECTION_STATE_PROPERTY) {
ConnectionState oldState = (ConnectionState) ev.getOldValue();
ConnectionState newState = (ConnectionState) ev.getNewValue();
switch (newState) {
case CONNECTING:
onConnecting();
break;
case CONNECTED:
if (progressBar != null) {
progressBar.setIndeterminate(false);
progressBar.setValue(100);
}
closeOptionPane();
updateFrameTitle();
// create tabs if not done
createPluginTabs();
repaint();
// Notify tabs
fireConnectedChange(true);
// Enable/disable tabs on initial update
initialUpdate = true;
// Start/Restart update timer on connect/reconnect
startUpdateTimer();
break;
case DISCONNECTED:
if (progressBar != null) {
progressBar.setIndeterminate(false);
progressBar.setValue(0);
closeOptionPane();
}
vmPanelDied();
if (oldState == ConnectionState.CONNECTED) {
// Notify tabs
fireConnectedChange(false);
}
break;
}
}
}
// Called on EDT
private void onConnecting() {
time0 = System.currentTimeMillis();
SwingUtilities.getWindowAncestor(this);
String connectionName = getConnectionName();
progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
JPanel progressPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
progressPanel.add(progressBar);
Object[] message = {
"<html><h3>" + Resources.format(Messages.CONNECTING_TO1, connectionName) + "</h3></html>",
progressPanel,
"<html><b>" + Resources.format(Messages.CONNECTING_TO2, connectionName) + "</b></html>"
};
optionPane =
SheetDialog.showOptionDialog(this,
message,
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE, null,
new String[]{Messages.CANCEL},
0);
}
// Called on EDT
private void closeOptionPane() {
if (optionPane != null) {
new Thread("VMPanel.sleeper") {
public void run() {
long elapsed = System.currentTimeMillis() - time0;
if (elapsed < 2000) {
try {
sleep(2000 - elapsed);
} catch (InterruptedException ex) {
// Ignore
}
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
optionPane.setVisible(false);
progressBar = null;
}
});
}
}.start();
}
}
void updateFrameTitle() {
VMInternalFrame vmIF = getFrame();
if (vmIF != null) {
String displayName = getDisplayName();
if (!proxyClient.isConnected()) {
displayName = Resources.format(Messages.CONNECTION_NAME__DISCONNECTED_, displayName);
}
vmIF.setTitle(displayName);
}
}
private VMInternalFrame getFrame() {
if (vmIF == null) {
vmIF = (VMInternalFrame) SwingUtilities.getAncestorOfClass(VMInternalFrame.class,
this);
}
return vmIF;
}
// TODO: this method is not needed when all JConsole tabs
// are migrated to use the new JConsolePlugin API.
//
// A thread safe clone of all JConsole tabs
synchronized List<Tab> getTabs() {
ArrayList<Tab> list = new ArrayList<Tab>();
int n = getTabCount();
for (int i = 0; i < n; i++) {
Component c = getComponentAt(i);
if (c instanceof Tab) {
list.add((Tab) c);
}
}
return list;
}
private void startUpdateTimer() {
if (timer != null) {
timer.cancel();
}
TimerTask timerTask = new TimerTask() {
public void run() {
update();
}
};
String timerName = "Timer-" + getConnectionName();
timer = new Timer(timerName, true);
timer.schedule(timerTask, 0, updateInterval);
}
// Call on EDT
private void vmPanelDied() {
disconnect();
if (userDisconnected) {
userDisconnected = false;
return;
}
JOptionPane optionPane;
String msgTitle, msgExplanation, buttonStr;
if (wasConnected) {
wasConnected = false;
msgTitle = Messages.CONNECTION_LOST1;
msgExplanation = Resources.format(Messages.CONNECTING_TO2, getConnectionName());
buttonStr = Messages.RECONNECT;
} else if (shouldUseSSL) {
msgTitle = Messages.CONNECTION_FAILED_SSL1;
msgExplanation = Resources.format(Messages.CONNECTION_FAILED_SSL2, getConnectionName());
buttonStr = Messages.INSECURE;
} else {
msgTitle = Messages.CONNECTION_FAILED1;
msgExplanation = Resources.format(Messages.CONNECTION_FAILED2, getConnectionName());
buttonStr = Messages.CONNECT;
}
optionPane =
SheetDialog.showOptionDialog(this,
"<html><h3>" + msgTitle + "</h3>" +
"<b>" + msgExplanation + "</b>",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE, null,
new String[]{buttonStr, Messages.CANCEL},
0);
optionPane.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) {
Object value = event.getNewValue();
if (value == Messages.RECONNECT || value == Messages.CONNECT) {
connect();
} else if (value == Messages.INSECURE) {
shouldUseSSL = false;
connect();
} else if (!everConnected) {
try {
getFrame().setClosed(true);
} catch (PropertyVetoException ex) {
// Should not happen, but can be ignored.
}
}
}
}
});
}
// Note: This method is called on a TimerTask thread. Any GUI manipulation
// must be performed with invokeLater() or invokeAndWait().
private Object lockObject = new Object();
private void update() {
synchronized (lockObject) {
if (!isConnected()) {
if (wasConnected) {
EventQueue.invokeLater(new Runnable() {
public void run() {
vmPanelDied();
}
});
}
wasConnected = false;
return;
} else {
wasConnected = true;
everConnected = true;
}
proxyClient.flush();
List<Tab> tabs = getTabs();
final int n = tabs.size();
for (int i = 0; i < n; i++) {
final int index = i;
try {
if (!proxyClient.isDead()) {
// Update tab
//
tabs.get(index).update();
// Enable tab on initial update
//
if (initialUpdate) {
EventQueue.invokeLater(new Runnable() {
public void run() {
setEnabledAt(index, true);
}
});
}
}
} catch (Exception e) {
// Disable tab on initial update
//
if (initialUpdate) {
EventQueue.invokeLater(new Runnable() {
public void run() {
setEnabledAt(index, false);
}
});
}
}
}
// plugin GUI update
for (ExceptionSafePlugin p : plugins.keySet()) {
SwingWorker<?, ?> sw = p.newSwingWorker();
SwingWorker<?, ?> prevSW = plugins.get(p);
// schedule SwingWorker to run only if the previous
// SwingWorker has finished its task and it hasn't started.
if (prevSW == null || prevSW.isDone()) {
if (sw == null || sw.getState() == SwingWorker.StateValue.PENDING) {
plugins.put(p, sw);
if (sw != null) {
p.executeSwingWorker(sw);
}
}
}
}
// Set the first enabled tab in the tab's list
// as the selected tab on initial update
//
if (initialUpdate) {
EventQueue.invokeLater(new Runnable() {
public void run() {
// Select first enabled tab if current tab isn't.
int index = getSelectedIndex();
if (index < 0 || !isEnabledAt(index)) {
for (int i = 0; i < n; i++) {
if (isEnabledAt(i)) {
setSelectedIndex(i);
break;
}
}
}
}
});
initialUpdate = false;
}
}
}
public String getHostName() {
return hostName;
}
public int getPort() {
return port;
}
public String getUserName() {
return userName;
}
public String getUrl() {
return url;
}
public String getPassword() {
return password;
}
public String getConnectionName() {
return proxyClient.connectionName();
}
public String getDisplayName() {
return proxyClient.getDisplayName();
}
static class TabInfo {
Class<? extends Tab> tabClass;
String name;
boolean tabVisible;
TabInfo(Class<? extends Tab> tabClass, String name, boolean tabVisible) {
this.tabClass = tabClass;
this.name = name;
this.tabVisible = tabVisible;
}
}
private void createPluginTabs() {
// add plugin tabs if not done
if (!pluginTabsAdded) {
for (JConsolePlugin p : plugins.keySet()) {
Map<String, JPanel> tabs = p.getTabs();
for (Map.Entry<String, JPanel> e : tabs.entrySet()) {
addTab(e.getKey(), e.getValue());
}
}
pluginTabsAdded = true;
}
}
private void fireConnectedChange(boolean connected) {
for (Tab tab : getTabs()) {
tab.firePropertyChange(JConsoleContext.CONNECTION_STATE_PROPERTY, !connected, connected);
}
}
}

View File

@@ -0,0 +1,238 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.awt.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class VariableGridLayout extends GridLayout {
private boolean fillRows, fillColumns;
public VariableGridLayout(int rows, int cols,
int hgap, int vgap,
boolean fillRows, boolean fillColumns) {
super(rows, cols, hgap, vgap);
this.fillRows = fillRows;
this.fillColumns = fillColumns;
}
public void setFillRow(JComponent c, boolean b) {
c.putClientProperty("VariableGridLayout.fillRow", b);
}
public void setFillColumn(JComponent c, boolean b) {
c.putClientProperty("VariableGridLayout.fillColumn", b);
}
public boolean getFillRow(JComponent c) {
Boolean b = (Boolean)c.getClientProperty("VariableGridLayout.fillRow");
return (b != null) ? b : fillRows;
}
public boolean getFillColumn(JComponent c) {
Boolean b = (Boolean)c.getClientProperty("VariableGridLayout.fillColumn");
return (b != null) ? b : fillColumns;
}
public void layoutContainer(Container parent) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = getRows();
int ncols = getColumns();
int hgap = getHgap();
int vgap = getVgap();
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
// Set heights
int x;
int y;
int nFills = 0;
boolean[] fills = new boolean[nrows];
int lastFillRow = -1;
int nComps = parent.getComponentCount();
y = insets.top;
for (int row = 0; row < nrows; row++) {
// Find largest minimum height for this row
int h = 0;
for (int col = 0; col < ncols; col++) {
if (row * ncols + col < nComps) {
Component c = parent.getComponent(row * ncols + col);
h = Math.max(h, c.getMinimumSize().height);
}
}
// Set heights for this row
x = insets.left;
for (int col = 0; col < ncols; col++) {
if (row * ncols + col < nComps) {
JComponent c = (JComponent)parent.getComponent(row * ncols + col);
int w = c.getWidth();
c.setBounds(x, y, w, h);
x += w + hgap;
if (col == 0 && getFillRow(c)) {
fills[row] = true;
}
}
}
y += h + vgap;
if (fills[row]) {
nFills++;
lastFillRow = row;
}
}
// Fill heights
if (nFills > 0 && y < parent.getHeight()) {
// How much height to add
int hAdd = (parent.getHeight() - y) / nFills;
int hAdded = 0;
for (int row = 0; row < nrows; row++) {
if (fills[row]) {
if (row == lastFillRow) {
// Compensate for rounding error
hAdd = parent.getHeight() - (y+hAdded);
}
for (int col = 0; col < ncols; col++) {
if (row * ncols + col < nComps) {
Component c = parent.getComponent(row * ncols + col);
Rectangle b = c.getBounds();
c.setBounds(b.x, b.y + hAdded, b.width, b.height + hAdd);
}
}
hAdded += hAdd;
}
}
}
// Set widths
nFills = 0;
fills = new boolean[ncols];
int lastFillCol = -1;
x = insets.left;
for (int col = 0; col < ncols; col++) {
// Find largest minimum width for this column
int w = 0;
for (int row = 0; row < nrows; row++) {
if (row * ncols + col < nComps) {
Component c = parent.getComponent(row * ncols + col);
w = Math.max(w, c.getMinimumSize().width);
}
}
// Set widths for this column
y = insets.top;
for (int row = 0; row < nrows; row++) {
if (row * ncols + col < nComps) {
JComponent c = (JComponent)parent.getComponent(row * ncols + col);
int h = c.getHeight();
c.setBounds(x, y, w, h);
y += h + vgap;
if (row == 0 && getFillColumn(c)) {
fills[col] = true;
}
}
}
x += w + hgap;
if (fills[col]) {
nFills++;
lastFillCol = col;
}
}
// Fill widths
if (nFills > 0 && x < parent.getWidth()) {
// How much width to add
int wAdd = (parent.getWidth() - x) / nFills;
int wAdded = 0;
for (int col = 0; col < ncols; col++) {
if (fills[col]) {
if (col == lastFillCol) {
wAdd = parent.getWidth() - (x+wAdded);
}
for (int row = 0; row < nrows; row++) {
if (row * ncols + col < nComps) {
Component c = parent.getComponent(row * ncols + col);
Rectangle b = c.getBounds();
c.setBounds(b.x + wAdded, b.y, b.width + wAdd, b.height);
}
}
wAdded += wAdd;
}
}
}
}
public Dimension preferredLayoutSize(Container parent) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = getRows();
int ncols = getColumns();
int hgap = getHgap();
int vgap = getVgap();
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int nComps = parent.getComponentCount();
int y = insets.top;
for (int row = 0; row < nrows; row++) {
int h = 0;
for (int col = 0; col < ncols; col++) {
if (row * ncols + col < nComps) {
Component c = parent.getComponent(row * ncols + col);
h = Math.max(h, c.getMinimumSize().height);
}
}
y += h + vgap;
}
int x = insets.left;
for (int col = 0; col < ncols; col++) {
int w = 0;
for (int row = 0; row < nrows; row++) {
if (row * ncols + col < nComps) {
Component c = parent.getComponent(row * ncols + col);
w = Math.max(w, c.getMinimumSize().width);
}
}
x += w + hgap;
}
return new Dimension(x, y);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole;
import java.io.PrintStream;
import sun.tools.jconsole.Messages;
public class Version {
private static final String jconsole_version =
"1.8.0_462-b08";
public static void print(PrintStream ps) {
printFullVersion(ps);
ps.println(Resources.format(Messages.NAME_AND_BUILD,
System.getProperty("java.runtime.name"),
System.getProperty("java.runtime.version")));
ps.println(Resources.format(Messages.NAME_AND_BUILD,
System.getProperty("java.vm.name"),
System.getProperty("java.vm.version"),
System.getProperty("java.vm.info")));
}
public static void printFullVersion(PrintStream ps) {
ps.println(Resources.format(Messages.JCONSOLE_VERSION, jconsole_version));
}
static String getVersion() {
return jconsole_version;
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2004, 2020 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 sun.tools.jconsole;
import java.util.*;
public class Worker extends Thread {
ArrayList<Runnable> jobs = new ArrayList<Runnable>();
private volatile boolean stopped = false;
public Worker(String name) {
super("Worker-"+name);
setPriority(NORM_PRIORITY - 1);
}
public void run() {
while (!stopped) {
Runnable job;
synchronized(jobs) {
while (!stopped && jobs.size() == 0) {
try {
jobs.wait();
} catch (InterruptedException ex) {
}
}
if(stopped) break;
job = jobs.remove(0);
}
job.run();
}
}
public void stopWorker() {
stopped = true;
synchronized(jobs) {
jobs.notify();
}
}
public void add(Runnable job) {
synchronized(jobs) {
jobs.add(job);
jobs.notify();
}
}
public boolean queueFull() {
synchronized(jobs) {
return (jobs.size() > 0);
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2004, 2006, 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 sun.tools.jconsole.inspector;
import java.awt.Image;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import sun.tools.jconsole.JConsole;
public class IconManager {
public static Icon MBEAN =
getSmallIcon(getImage("mbean.gif"));
public static Icon MBEANSERVERDELEGATE =
getSmallIcon(getImage("mbeanserverdelegate.gif"));
public static Icon DEFAULT_XOBJECT =
getSmallIcon(getImage("xobject.gif"));
private static ImageIcon getImage(String img) {
return new ImageIcon(JConsole.class.getResource("resources/" + img));
}
private static ImageIcon getSmallIcon(ImageIcon icon) {
return new ImageIcon(
icon.getImage().getScaledInstance(16, 16, Image.SCALE_SMOOTH));
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import java.awt.*;
import javax.swing.*;
import javax.management.*;
@SuppressWarnings("serial")
public class OperationEntry extends JPanel {
private MBeanOperationInfo operation;
private JComboBox sigs;
private XTextField inputs[];
public OperationEntry (MBeanOperationInfo operation,
boolean isCallable,
JButton button,
XOperations xoperations) {
super(new BorderLayout());
this.operation = operation;
setLayout(new FlowLayout(FlowLayout.LEFT));
setPanel(isCallable, button, xoperations);
}
private void setPanel(boolean isCallable,
JButton button,
XOperations xoperations) {
try {
MBeanParameterInfo params[] = operation.getSignature();
add(new JLabel("(",JLabel.CENTER));
inputs = new XTextField[params.length];
for (int i = 0; i < params.length; i++) {
if(params[i].getName() != null) {
JLabel name =
new JLabel(params[i].getName(), JLabel.CENTER);
name.setToolTipText(params[i].getDescription());
add(name);
}
String defaultTextValue =
Utils.getDefaultValue(params[i].getType());
int fieldWidth = defaultTextValue.length();
if (fieldWidth > 15) fieldWidth = 15;
else
if (fieldWidth < 10) fieldWidth = 10;
add(inputs[i] =
new XTextField(Utils.getReadableClassName(defaultTextValue),
Utils.getClass(params[i].getType()),
fieldWidth,
isCallable,
button,
xoperations));
inputs[i].setHorizontalAlignment(SwingConstants.CENTER);
if (i < params.length-1)
add(new JLabel(",",JLabel.CENTER));
}
add(new JLabel(")",JLabel.CENTER));
validate();
doLayout();
}
catch (Exception e) {
System.out.println("Error setting Operation panel :"+
e.getMessage());
}
}
public String[] getSignature() {
MBeanParameterInfo params[] = operation.getSignature();
String result[] = new String[params.length];
for (int i = 0; i < params.length; i++) {
result[i] = params[i].getType();
}
return result;
}
public Object[] getParameters() throws Exception {
MBeanParameterInfo params[] = operation.getSignature();
String signature[] = new String[params.length];
for (int i = 0; i < params.length; i++)
signature[i] = params[i].getType();
return Utils.getParameters(inputs,signature);
}
public String getReturnType() {
return operation.getReturnType();
}
}

View File

@@ -0,0 +1,292 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
// Imports for picking up mouse events from the JTable.
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import sun.tools.jconsole.JConsole;
@SuppressWarnings("serial")
public class TableSorter extends DefaultTableModel implements MouseListener {
private boolean ascending = true;
private TableColumnModel columnModel;
private JTable tableView;
private Vector<TableModelListener> evtListenerList;
private int sortColumn = 0;
private int[] invertedIndex;
public TableSorter() {
super();
evtListenerList = new Vector<TableModelListener>();
}
public TableSorter(Object[] columnNames, int numRows) {
super(columnNames,numRows);
evtListenerList = new Vector<TableModelListener>();
}
@Override
public void newDataAvailable(TableModelEvent e) {
super.newDataAvailable(e);
invertedIndex = new int[getRowCount()];
for (int i = 0; i < invertedIndex.length; i++) {
invertedIndex[i] = i;
}
sort(this.sortColumn, this.ascending);
}
@Override
public void addTableModelListener(TableModelListener l) {
evtListenerList.add(l);
super.addTableModelListener(l);
}
@Override
public void removeTableModelListener(TableModelListener l) {
evtListenerList.remove(l);
super.removeTableModelListener(l);
}
private void removeListeners() {
for(TableModelListener tnl : evtListenerList)
super.removeTableModelListener(tnl);
}
private void restoreListeners() {
for(TableModelListener tnl : evtListenerList)
super.addTableModelListener(tnl);
}
@SuppressWarnings("unchecked")
private int compare(Object o1, Object o2) {
// take care of the case where both o1 & o2 are null. Needed to keep
// the method symmetric. Without this quickSort gives surprising results.
if (o1 == o2)
return 0;
if (o1==null)
return 1;
if (o2==null)
return -1;
//two object of the same class and that are comparable
else if ((o1.getClass().equals(o2.getClass())) &&
(o1 instanceof Comparable)) {
return (((Comparable) o1).compareTo(o2));
}
else {
return o1.toString().compareTo(o2.toString());
}
}
private void sort(int column, boolean isAscending) {
final XMBeanAttributes attrs =
(tableView instanceof XMBeanAttributes)
?(XMBeanAttributes) tableView
:null;
// We cannot sort rows when a cell is being
// edited - so we're going to cancel cell editing here if needed.
// This might happen when the user is editing a row, and clicks on
// another row without validating. In that case there are two events
// that compete: one is the validation of the value that was previously
// edited, the other is the mouse click that opens the new editor.
//
// When we reach here the previous value is already validated, and the
// old editor is closed, but the new editor might have opened.
// It's this new editor that wil be cancelled here, if needed.
//
if (attrs != null && attrs.isEditing())
attrs.cancelCellEditing();
// remove registered listeners
removeListeners();
// do the sort
if (JConsole.isDebug()) {
System.err.println("sorting table against column="+column
+" ascending="+isAscending);
}
quickSort(0,getRowCount()-1,column,isAscending);
// restore registered listeners
restoreListeners();
// update row heights in XMBeanAttributes (required by expandable cells)
if (attrs != null) {
for (int i = 0; i < getRowCount(); i++) {
Vector data = (Vector) dataVector.elementAt(i);
attrs.updateRowHeight(data.elementAt(1), i);
}
}
}
private boolean compareS(Object s1, Object s2, boolean isAscending) {
if (isAscending)
return (compare(s1,s2) > 0);
else
return (compare(s1,s2) < 0);
}
private boolean compareG(Object s1, Object s2, boolean isAscending) {
if (isAscending)
return (compare(s1,s2) < 0);
else
return (compare(s1,s2) > 0);
}
private void quickSort(int lo0,int hi0, int key, boolean isAscending) {
int lo = lo0;
int hi = hi0;
Object mid;
if ( hi0 > lo0)
{
mid = getValueAt( ( lo0 + hi0 ) / 2 , key);
while( lo <= hi )
{
/* find the first element that is greater than
* or equal to the partition element starting
* from the left Index.
*/
while( ( lo < hi0 ) &&
( compareS(mid,getValueAt(lo,key), isAscending) ))
++lo;
/* find an element that is smaller than or equal to
* the partition element starting from the right Index.
*/
while( ( hi > lo0 ) &&
( compareG(mid,getValueAt(hi,key), isAscending) ))
--hi;
// if the indexes have not crossed, swap
if( lo <= hi )
{
swap(lo, hi, key);
++lo;
--hi;
}
}
/* If the right index has not reached the
* left side of array
* must now sort the left partition.
*/
if( lo0 < hi )
quickSort(lo0, hi , key, isAscending);
/* If the left index has not reached the right
* side of array
* must now sort the right partition.
*/
if( lo <= hi0 )
quickSort(lo, hi0 , key, isAscending);
}
}
private Vector getRow(int row) {
return (Vector) dataVector.elementAt(row);
}
@SuppressWarnings("unchecked")
private void setRow(Vector data, int row) {
dataVector.setElementAt(data,row);
}
private void swap(int i, int j, int column) {
Vector data = getRow(i);
setRow(getRow(j),i);
setRow(data,j);
int a = invertedIndex[i];
invertedIndex[i] = invertedIndex[j];
invertedIndex[j] = a;
}
public void sortByColumn(int column) {
sortByColumn(column, !ascending);
}
public void sortByColumn(int column, boolean ascending) {
this.ascending = ascending;
this.sortColumn = column;
sort(column,ascending);
}
public int getIndexOfRow(int row) {
return invertedIndex[row];
}
// Add a mouse listener to the Table to trigger a table sort
// when a column heading is clicked in the JTable.
public void addMouseListenerToHeaderInTable(JTable table) {
tableView = table;
columnModel = tableView.getColumnModel();
JTableHeader th = tableView.getTableHeader();
th.addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
int viewColumn = columnModel.getColumnIndexAtX(e.getX());
int column = tableView.convertColumnIndexToModel(viewColumn);
if (e.getClickCount() == 1 && column != -1) {
if (tableView instanceof XTable) {
XTable attrs = (XTable) tableView;
// inform the table view that the rows are going to be sorted
// against the values in a given column. This gives the
// chance to the table view to close its editor - if needed.
//
attrs.sortRequested(column);
}
tableView.invalidate();
sortByColumn(column);
tableView.validate();
tableView.repaint();
}
}
public void mousePressed(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
// java import
import java.awt.*;
import javax.swing.*;
//
public class ThreadDialog implements Runnable {
Component parentComponent;
Object message;
String title;
int messageType;
public ThreadDialog(Component parentComponent,
Object message,
String title,
int messageType) {
this.parentComponent = parentComponent;
this.message = message;
this.title = title;
this.messageType = messageType;
}
public void run() {
JOptionPane pane = new JOptionPane(message, messageType);
JDialog dialog = pane.createDialog(parentComponent, title);
dialog.setResizable(true);
dialog.setVisible(true);
}
}

View File

@@ -0,0 +1,462 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole.inspector;
import java.awt.event.*;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ExecutionException;
import javax.management.*;
import javax.management.openmbean.*;
import javax.swing.*;
import javax.swing.text.*;
public class Utils {
private Utils() {
}
private static Set<Integer> tableNavigationKeys =
new HashSet<Integer>(Arrays.asList(new Integer[]{
KeyEvent.VK_TAB, KeyEvent.VK_ENTER,
KeyEvent.VK_HOME, KeyEvent.VK_END,
KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT,
KeyEvent.VK_UP, KeyEvent.VK_DOWN,
KeyEvent.VK_PAGE_UP, KeyEvent.VK_PAGE_DOWN
}));
private static final Set<Class<?>> primitiveWrappers =
new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{
Byte.class, Short.class, Integer.class, Long.class,
Float.class, Double.class, Character.class, Boolean.class
}));
private static final Set<Class<?>> primitives = new HashSet<Class<?>>();
private static final Map<String, Class<?>> primitiveMap =
new HashMap<String, Class<?>>();
private static final Map<String, Class<?>> primitiveToWrapper =
new HashMap<String, Class<?>>();
private static final Set<String> editableTypes = new HashSet<String>();
private static final Set<Class<?>> extraEditableClasses =
new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{
BigDecimal.class, BigInteger.class, Number.class,
String.class, ObjectName.class
}));
private static final Set<String> numericalTypes = new HashSet<String>();
private static final Set<String> extraNumericalTypes =
new HashSet<String>(Arrays.asList(new String[]{
BigDecimal.class.getName(), BigInteger.class.getName(),
Number.class.getName()
}));
private static final Set<String> booleanTypes =
new HashSet<String>(Arrays.asList(new String[]{
Boolean.TYPE.getName(), Boolean.class.getName()
}));
static {
// compute primitives/primitiveMap/primitiveToWrapper
for (Class<?> c : primitiveWrappers) {
try {
Field f = c.getField("TYPE");
Class<?> p = (Class<?>) f.get(null);
primitives.add(p);
primitiveMap.put(p.getName(), p);
primitiveToWrapper.put(p.getName(), c);
} catch (Exception e) {
throw new AssertionError(e);
}
}
// compute editableTypes
for (Class<?> c : primitives) {
editableTypes.add(c.getName());
}
for (Class<?> c : primitiveWrappers) {
editableTypes.add(c.getName());
}
for (Class<?> c : extraEditableClasses) {
editableTypes.add(c.getName());
}
// compute numericalTypes
for (Class<?> c : primitives) {
String name = c.getName();
if (!name.equals(Boolean.TYPE.getName())) {
numericalTypes.add(name);
}
}
for (Class<?> c : primitiveWrappers) {
String name = c.getName();
if (!name.equals(Boolean.class.getName())) {
numericalTypes.add(name);
}
}
}
/**
* This method returns the class matching the name className.
* It's used to cater for the primitive types.
*/
public static Class<?> getClass(String className)
throws ClassNotFoundException {
Class<?> c;
if ((c = primitiveMap.get(className)) != null) {
return c;
}
return Class.forName(className);
}
/**
* Check if the given collection is a uniform collection of the given type.
*/
public static boolean isUniformCollection(Collection<?> c, Class<?> e) {
if (e == null) {
throw new IllegalArgumentException("Null reference type");
}
if (c == null) {
throw new IllegalArgumentException("Null collection");
}
if (c.isEmpty()) {
return false;
}
for (Object o : c) {
if (o == null || !e.isAssignableFrom(o.getClass())) {
return false;
}
}
return true;
}
/**
* Check if the given element denotes a supported array-friendly data
* structure, i.e. a data structure jconsole can render as an array.
*/
public static boolean canBeRenderedAsArray(Object elem) {
if (isSupportedArray(elem)) {
return true;
}
if (elem instanceof Collection) {
Collection<?> c = (Collection<?>) elem;
if (c.isEmpty()) {
// Empty collections of any Java type are not handled as arrays
//
return false;
} else {
// - Collections of CompositeData/TabularData are not handled
// as arrays
// - Collections of other Java types are handled as arrays
//
return !isUniformCollection(c, CompositeData.class) &&
!isUniformCollection(c, TabularData.class);
}
}
if (elem instanceof Map) {
return !(elem instanceof TabularData);
}
return false;
}
/**
* Check if the given element is an array.
*
* Multidimensional arrays are not supported.
*
* Non-empty 1-dimensional arrays of CompositeData
* and TabularData are not handled as arrays but as
* tabular data.
*/
public static boolean isSupportedArray(Object elem) {
if (elem == null || !elem.getClass().isArray()) {
return false;
}
Class<?> ct = elem.getClass().getComponentType();
if (ct.isArray()) {
return false;
}
if (Array.getLength(elem) > 0 &&
(CompositeData.class.isAssignableFrom(ct) ||
TabularData.class.isAssignableFrom(ct))) {
return false;
}
return true;
}
/**
* This method provides a readable classname if it's an array,
* i.e. either the classname of the component type for arrays
* of java reference types or the name of the primitive type
* for arrays of java primitive types. Otherwise, it returns null.
*/
public static String getArrayClassName(String name) {
String className = null;
if (name.startsWith("[")) {
int index = name.lastIndexOf("[");
className = name.substring(index, name.length());
if (className.startsWith("[L")) {
className = className.substring(2, className.length() - 1);
} else {
try {
Class<?> c = Class.forName(className);
className = c.getComponentType().getName();
} catch (ClassNotFoundException e) {
// Should not happen
throw new IllegalArgumentException(
"Bad class name " + name, e);
}
}
}
return className;
}
/**
* This methods provides a readable classname. If the supplied name
* parameter denotes an array this method returns either the classname
* of the component type for arrays of java reference types or the name
* of the primitive type for arrays of java primitive types followed by
* n-times "[]" where 'n' denotes the arity of the array. Otherwise, if
* the supplied name doesn't denote an array it returns the same classname.
*/
public static String getReadableClassName(String name) {
String className = getArrayClassName(name);
if (className == null) {
return name;
}
int index = name.lastIndexOf("[");
StringBuilder brackets = new StringBuilder(className);
for (int i = 0; i <= index; i++) {
brackets.append("[]");
}
return brackets.toString();
}
/**
* This method tells whether the type is editable
* (means can be created with a String or not)
*/
public static boolean isEditableType(String type) {
return editableTypes.contains(type);
}
/**
* This method inserts a default value for the standard java types,
* else it inserts the text name of the expected class type.
* It acts to give a clue as to the input type.
*/
public static String getDefaultValue(String type) {
if (numericalTypes.contains(type) ||
extraNumericalTypes.contains(type)) {
return "0";
}
if (booleanTypes.contains(type)) {
return "true";
}
type = getReadableClassName(type);
int i = type.lastIndexOf('.');
if (i > 0) {
return type.substring(i + 1, type.length());
} else {
return type;
}
}
/**
* Try to create a Java object using a one-string-param constructor.
*/
public static Object newStringConstructor(String type, String param)
throws Exception {
Constructor<?> c = Utils.getClass(type).getConstructor(String.class);
try {
return c.newInstance(param);
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof Exception) {
throw (Exception) t;
} else {
throw e;
}
}
}
/**
* Try to convert a string value into a numerical value.
*/
private static Number createNumberFromStringValue(String value)
throws NumberFormatException {
final String suffix = value.substring(value.length() - 1);
if ("L".equalsIgnoreCase(suffix)) {
return Long.valueOf(value.substring(0, value.length() - 1));
}
if ("F".equalsIgnoreCase(suffix)) {
return Float.valueOf(value.substring(0, value.length() - 1));
}
if ("D".equalsIgnoreCase(suffix)) {
return Double.valueOf(value.substring(0, value.length() - 1));
}
try {
return Integer.valueOf(value);
} catch (NumberFormatException e) {
// OK: Ignore exception...
}
try {
return Long.valueOf(value);
} catch (NumberFormatException e1) {
// OK: Ignore exception...
}
try {
return Double.valueOf(value);
} catch (NumberFormatException e2) {
// OK: Ignore exception...
}
throw new NumberFormatException("Cannot convert string value '" +
value + "' into a numerical value");
}
/**
* This method attempts to create an object of the given "type"
* using the "value" parameter.
* e.g. calling createObjectFromString("java.lang.Integer", "10")
* will return an Integer object initialized to 10.
*/
public static Object createObjectFromString(String type, String value)
throws Exception {
Object result;
if (primitiveToWrapper.containsKey(type)) {
if (type.equals(Character.TYPE.getName())) {
result = new Character(value.charAt(0));
} else {
result = newStringConstructor(
((Class<?>) primitiveToWrapper.get(type)).getName(),
value);
}
} else if (type.equals(Character.class.getName())) {
result = new Character(value.charAt(0));
} else if (Number.class.isAssignableFrom(Utils.getClass(type))) {
result = createNumberFromStringValue(value);
} else if (value == null || value.equals("null")) {
// hack for null value
result = null;
} else {
// try to create a Java object using
// the one-string-param constructor
result = newStringConstructor(type, value);
}
return result;
}
/**
* This method is responsible for converting the inputs given by the user
* into a useful object array for passing into a parameter array.
*/
public static Object[] getParameters(XTextField[] inputs, String[] params)
throws Exception {
Object result[] = new Object[inputs.length];
Object userInput;
for (int i = 0; i < inputs.length; i++) {
userInput = inputs[i].getValue();
// if it's already a complex object, use the value
// else try to instantiate with string constructor
if (userInput instanceof XObject) {
result[i] = ((XObject) userInput).getObject();
} else {
result[i] = createObjectFromString(params[i].toString(),
(String) userInput);
}
}
return result;
}
/**
* If the exception is wrapped, unwrap it.
*/
public static Throwable getActualException(Throwable e) {
if (e instanceof ExecutionException) {
e = e.getCause();
}
if (e instanceof MBeanException ||
e instanceof RuntimeMBeanException ||
e instanceof RuntimeOperationsException ||
e instanceof ReflectionException) {
Throwable t = e.getCause();
if (t != null) {
return t;
}
}
return e;
}
@SuppressWarnings("serial")
public static class ReadOnlyTableCellEditor
extends DefaultCellEditor {
public ReadOnlyTableCellEditor(JTextField tf) {
super(tf);
tf.addFocusListener(new Utils.EditFocusAdapter(this));
tf.addKeyListener(new Utils.CopyKeyAdapter());
}
}
public static class EditFocusAdapter extends FocusAdapter {
private CellEditor editor;
public EditFocusAdapter(CellEditor editor) {
this.editor = editor;
}
@Override
public void focusLost(FocusEvent e) {
editor.stopCellEditing();
}
}
public static class CopyKeyAdapter extends KeyAdapter {
private static final String defaultEditorKitCopyActionName =
DefaultEditorKit.copyAction;
private static final String transferHandlerCopyActionName =
(String) TransferHandler.getCopyAction().getValue(Action.NAME);
@Override
public void keyPressed(KeyEvent e) {
// Accept "copy" key strokes
KeyStroke ks = KeyStroke.getKeyStroke(
e.getKeyCode(), e.getModifiers());
JComponent comp = (JComponent) e.getSource();
for (int i = 0; i < 3; i++) {
InputMap im = comp.getInputMap(i);
Object key = im.get(ks);
if (defaultEditorKitCopyActionName.equals(key) ||
transferHandlerCopyActionName.equals(key)) {
return;
}
}
// Accept JTable navigation key strokes
if (!tableNavigationKeys.contains(e.getKeyCode())) {
e.consume();
}
}
@Override
public void keyTyped(KeyEvent e) {
e.consume();
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import java.awt.Color;
import java.awt.Component;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
class XArrayDataViewer {
private XArrayDataViewer() {}
public static boolean isViewableValue(Object value) {
return Utils.canBeRenderedAsArray(value);
}
public static Component loadArray(Object value) {
Component comp = null;
if (isViewableValue(value)) {
Object[] arr;
if (value instanceof Collection) {
arr = ((Collection<?>) value).toArray();
} else if (value instanceof Map) {
arr = ((Map<?,?>) value).entrySet().toArray();
} else if (value instanceof Object[]) {
arr = (Object[]) value;
} else {
int length = Array.getLength(value);
arr = new Object[length];
for (int i = 0; i < length; i++) {
arr[i] = Array.get(value, i);
}
}
JEditorPane arrayEditor = new JEditorPane();
arrayEditor.setContentType("text/html");
arrayEditor.setEditable(false);
Color evenRowColor = arrayEditor.getBackground();
int red = evenRowColor.getRed();
int green = evenRowColor.getGreen();
int blue = evenRowColor.getBlue();
String evenRowColorStr =
"rgb(" + red + "," + green + "," + blue + ")";
Color oddRowColor = new Color(
red < 20 ? red + 20 : red - 20,
green < 20 ? green + 20 : green - 20,
blue < 20 ? blue + 20 : blue - 20);
String oddRowColorStr =
"rgb(" + oddRowColor.getRed() + "," +
oddRowColor.getGreen() + "," +
oddRowColor.getBlue() + ")";
Color foreground = arrayEditor.getForeground();
String textColor = String.format("%06x",
foreground.getRGB() & 0xFFFFFF);
StringBuilder sb = new StringBuilder();
sb.append("<html><body text=#"+textColor+"><table width=\"100%\">");
for (int i = 0; i < arr.length; i++) {
if (i % 2 == 0) {
sb.append("<tr style=\"background-color: " +
evenRowColorStr + "\"><td><pre>" +
(arr[i] == null ?
arr[i] : htmlize(arr[i].toString())) +
"</pre></td></tr>");
} else {
sb.append("<tr style=\"background-color: " +
oddRowColorStr + "\"><td><pre>" +
(arr[i] == null ?
arr[i] : htmlize(arr[i].toString())) +
"</pre></td></tr>");
}
}
if (arr.length == 0) {
sb.append("<tr style=\"background-color: " +
evenRowColorStr + "\"><td></td></tr>");
}
sb.append("</table></body></html>");
arrayEditor.setText(sb.toString());
JScrollPane scrollp = new JScrollPane(arrayEditor);
comp = scrollp;
}
return comp;
}
private static String htmlize(String value) {
return value.replace("&", "&amp;").replace("<", "&lt;");
}
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.JButton;
import java.awt.event.MouseListener;
import java.awt.Component;
import java.awt.Container;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.Messages;
public class XDataViewer {
public static final int OPEN = 1;
public static final int ARRAY = 2;
public static final int NUMERIC = 3;
public static final int NOT_SUPPORTED = 4;
private MBeansTab tab;
public XDataViewer(MBeansTab tab) {
this.tab = tab;
}
public static void registerForMouseEvent(Component comp,
MouseListener mouseListener) {
if(comp instanceof JScrollPane) {
JScrollPane pane = (JScrollPane) comp;
comp = pane.getViewport().getView();
}
if(comp instanceof Container) {
Container container = (Container) comp;
Component[] components = container.getComponents();
for(int i = 0; i < components.length; i++) {
registerForMouseEvent(components[i], mouseListener);
}
}
//No registration for XOpenTypedata that are themselves clickable.
//No registration for JButton that are themselves clickable.
if(comp != null &&
(!(comp instanceof XOpenTypeViewer.XOpenTypeData) &&
!(comp instanceof JButton)) )
comp.addMouseListener(mouseListener);
}
public static void dispose(MBeansTab tab) {
XPlottingViewer.dispose(tab);
}
public static boolean isViewableValue(Object value) {
boolean ret = false;
if((ret = XArrayDataViewer.isViewableValue(value)))
return ret;
if((ret = XOpenTypeViewer.isViewableValue(value)))
return ret;
if((ret = XPlottingViewer.isViewableValue(value)))
return ret;
return ret;
}
public static int getViewerType(Object data) {
if(XArrayDataViewer.isViewableValue(data))
return ARRAY;
if(XOpenTypeViewer.isViewableValue(data))
return OPEN;
if(XPlottingViewer.isViewableValue(data))
return NUMERIC;
return NOT_SUPPORTED;
}
public static String getActionLabel(int type) {
if(type == ARRAY ||
type == OPEN)
return Messages.VISUALIZE;
if(type == NUMERIC)
return Messages.PLOT;
return Messages.EXPAND;
}
public Component createOperationViewer(Object value,
XMBean mbean) {
if(value instanceof Number) return null;
if(value instanceof Component) return (Component) value;
return createAttributeViewer(value, mbean, null, null);
}
public static Component createNotificationViewer(Object value) {
Component comp = null;
if(value instanceof Number) return null;
if((comp = XArrayDataViewer.loadArray(value)) != null)
return comp;
if((comp = XOpenTypeViewer.loadOpenType(value)) != null)
return comp;
return comp;
}
public Component createAttributeViewer(Object value,
XMBean mbean,
String attributeName,
JTable table) {
Component comp = null;
if((comp = XArrayDataViewer.loadArray(value)) != null)
return comp;
if((comp = XOpenTypeViewer.loadOpenType(value)) != null)
return comp;
if((comp = XPlottingViewer.loadPlotting(mbean,
attributeName,
value,
table,
tab)) != null)
return comp;
return comp;
}
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright (c) 2004, 2008, 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 sun.tools.jconsole.inspector;
import java.io.IOException;
import javax.management.*;
import javax.swing.Icon;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.ProxyClient.SnapshotMBeanServerConnection;
public class XMBean {
private final MBeansTab mbeansTab;
private final ObjectName objectName;
private Icon icon;
private String text;
private Boolean broadcaster;
private final Object broadcasterLock = new Object();
private MBeanInfo mbeanInfo;
private final Object mbeanInfoLock = new Object();
public XMBean(ObjectName objectName, MBeansTab mbeansTab) {
this.mbeansTab = mbeansTab;
this.objectName = objectName;
text = objectName.getKeyProperty("name");
if (text == null) {
text = objectName.getDomain();
}
if (MBeanServerDelegate.DELEGATE_NAME.equals(objectName)) {
icon = IconManager.MBEANSERVERDELEGATE;
} else {
icon = IconManager.MBEAN;
}
}
MBeanServerConnection getMBeanServerConnection() {
return mbeansTab.getMBeanServerConnection();
}
SnapshotMBeanServerConnection getSnapshotMBeanServerConnection() {
return mbeansTab.getSnapshotMBeanServerConnection();
}
public Boolean isBroadcaster() {
synchronized (broadcasterLock) {
if (broadcaster == null) {
try {
broadcaster = getMBeanServerConnection().isInstanceOf(
getObjectName(),
"javax.management.NotificationBroadcaster");
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Couldn't check if MBean [" +
objectName + "] is a notification broadcaster");
e.printStackTrace();
}
return false;
}
}
return broadcaster;
}
}
public Object invoke(String operationName) throws Exception {
Object result = getMBeanServerConnection().invoke(
getObjectName(), operationName, new Object[0], new String[0]);
return result;
}
public Object invoke(String operationName, Object params[], String sig[])
throws Exception {
Object result = getMBeanServerConnection().invoke(
getObjectName(), operationName, params, sig);
return result;
}
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException, InstanceNotFoundException,
InvalidAttributeValueException, MBeanException,
ReflectionException, IOException {
getMBeanServerConnection().setAttribute(getObjectName(), attribute);
}
public Object getAttribute(String attributeName)
throws AttributeNotFoundException, InstanceNotFoundException,
MBeanException, ReflectionException, IOException {
return getSnapshotMBeanServerConnection().getAttribute(
getObjectName(), attributeName);
}
public AttributeList getAttributes(String attributeNames[])
throws AttributeNotFoundException, InstanceNotFoundException,
MBeanException, ReflectionException, IOException {
return getSnapshotMBeanServerConnection().getAttributes(
getObjectName(), attributeNames);
}
public AttributeList getAttributes(MBeanAttributeInfo attributeNames[])
throws AttributeNotFoundException, InstanceNotFoundException,
MBeanException, ReflectionException, IOException {
String attributeString[] = new String[attributeNames.length];
for (int i = 0; i < attributeNames.length; i++) {
attributeString[i] = attributeNames[i].getName();
}
return getAttributes(attributeString);
}
public ObjectName getObjectName() {
return objectName;
}
public MBeanInfo getMBeanInfo() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
synchronized (mbeanInfoLock) {
if (mbeanInfo == null) {
mbeanInfo = getMBeanServerConnection().getMBeanInfo(objectName);
}
return mbeanInfo;
}
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (!(obj instanceof XMBean)) {
return false;
}
XMBean that = (XMBean) obj;
return getObjectName().equals(that.getObjectName());
}
@Override
public int hashCode() {
return (objectName == null ? 0 : objectName.hashCode());
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Icon getIcon() {
return icon;
}
public void setIcon(Icon icon) {
this.icon = icon;
}
@Override
public String toString() {
return getText();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,413 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.util.*;
import javax.management.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.*;
import javax.swing.table.*;
import sun.tools.jconsole.Messages;
import static sun.tools.jconsole.Utilities.*;
@SuppressWarnings("serial")
public class XMBeanInfo extends JPanel {
private static final Color lightYellow = new Color(255, 255, 128);
private final int NAME_COLUMN = 0;
private final int VALUE_COLUMN = 1;
private final String[] columnNames = {
Messages.NAME,
Messages.VALUE
};
private JTable infoTable = new JTable();
private JTable descTable = new JTable();
private JPanel infoBorderPanel = new JPanel(new BorderLayout());
private JPanel descBorderPanel = new JPanel(new BorderLayout());
private static class ReadOnlyDefaultTableModel extends DefaultTableModel {
@Override
public void setValueAt(Object value, int row, int col) {
}
}
private static class TableRowDivider {
private String tableRowDividerText;
public TableRowDivider(String tableRowDividerText) {
this.tableRowDividerText = tableRowDividerText;
}
@Override
public String toString() {
return tableRowDividerText;
}
}
private static MBeanInfoTableCellRenderer renderer =
new MBeanInfoTableCellRenderer();
private static class MBeanInfoTableCellRenderer
extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Component comp = super.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
if (value instanceof TableRowDivider) {
JLabel label = new JLabel(value.toString());
label.setBackground(ensureContrast(lightYellow,
label.getForeground()));
label.setOpaque(true);
return label;
}
return comp;
}
}
private static TableCellEditor editor =
new MBeanInfoTableCellEditor(new JTextField());
private static class MBeanInfoTableCellEditor
extends Utils.ReadOnlyTableCellEditor {
public MBeanInfoTableCellEditor(JTextField tf) {
super(tf);
}
@Override
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected,
int row, int column) {
Component comp = super.getTableCellEditorComponent(
table, value, isSelected, row, column);
if (value instanceof TableRowDivider) {
JLabel label = new JLabel(value.toString());
label.setBackground(ensureContrast(lightYellow,
label.getForeground()));
label.setOpaque(true);
return label;
}
return comp;
}
}
public XMBeanInfo() {
// Use the grid layout to display the two tables
//
super(new GridLayout(2, 1));
// MBean*Info table
//
infoTable.setModel(new ReadOnlyDefaultTableModel());
infoTable.setRowSelectionAllowed(false);
infoTable.setColumnSelectionAllowed(false);
infoTable.getTableHeader().setReorderingAllowed(false);
((DefaultTableModel) infoTable.getModel()).setColumnIdentifiers(columnNames);
infoTable.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(140);
infoTable.getColumnModel().getColumn(NAME_COLUMN).setMaxWidth(140);
infoTable.getColumnModel().getColumn(NAME_COLUMN).setCellRenderer(renderer);
infoTable.getColumnModel().getColumn(VALUE_COLUMN).setCellRenderer(renderer);
infoTable.getColumnModel().getColumn(NAME_COLUMN).setCellEditor(editor);
infoTable.getColumnModel().getColumn(VALUE_COLUMN).setCellEditor(editor);
infoTable.addKeyListener(new Utils.CopyKeyAdapter());
infoTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
JScrollPane infoTableScrollPane = new JScrollPane(infoTable);
infoBorderPanel.setBorder(
BorderFactory.createTitledBorder("MBeanInfoPlaceHolder"));
infoBorderPanel.add(infoTableScrollPane);
// Descriptor table
//
descTable.setModel(new ReadOnlyDefaultTableModel());
descTable.setRowSelectionAllowed(false);
descTable.setColumnSelectionAllowed(false);
descTable.getTableHeader().setReorderingAllowed(false);
((DefaultTableModel) descTable.getModel()).setColumnIdentifiers(columnNames);
descTable.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(140);
descTable.getColumnModel().getColumn(NAME_COLUMN).setMaxWidth(140);
descTable.getColumnModel().getColumn(NAME_COLUMN).setCellRenderer(renderer);
descTable.getColumnModel().getColumn(VALUE_COLUMN).setCellRenderer(renderer);
descTable.getColumnModel().getColumn(NAME_COLUMN).setCellEditor(editor);
descTable.getColumnModel().getColumn(VALUE_COLUMN).setCellEditor(editor);
descTable.addKeyListener(new Utils.CopyKeyAdapter());
descTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
JScrollPane descTableScrollPane = new JScrollPane(descTable);
descBorderPanel.setBorder(
BorderFactory.createTitledBorder(Messages.DESCRIPTOR));
descBorderPanel.add(descTableScrollPane);
// Add the two tables to the grid
//
add(infoBorderPanel);
add(descBorderPanel);
}
// Call on EDT
public void emptyInfoTable() {
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
while (tableModel.getRowCount() > 0) {
tableModel.removeRow(0);
}
}
// Call on EDT
public void emptyDescTable() {
DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel();
while (tableModel.getRowCount() > 0) {
tableModel.removeRow(0);
}
}
// Call on EDT
private void addDescriptor(Descriptor desc, String text) {
if (desc != null && desc.getFieldNames().length > 0) {
DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
for (String fieldName : desc.getFieldNames()) {
rowData[0] = fieldName;
Object fieldValue = desc.getFieldValue(fieldName);
if (fieldValue instanceof boolean[]) {
rowData[1] = Arrays.toString((boolean[]) fieldValue);
} else if (fieldValue instanceof byte[]) {
rowData[1] = Arrays.toString((byte[]) fieldValue);
} else if (fieldValue instanceof char[]) {
rowData[1] = Arrays.toString((char[]) fieldValue);
} else if (fieldValue instanceof double[]) {
rowData[1] = Arrays.toString((double[]) fieldValue);
} else if (fieldValue instanceof float[]) {
rowData[1] = Arrays.toString((float[]) fieldValue);
} else if (fieldValue instanceof int[]) {
rowData[1] = Arrays.toString((int[]) fieldValue);
} else if (fieldValue instanceof long[]) {
rowData[1] = Arrays.toString((long[]) fieldValue);
} else if (fieldValue instanceof short[]) {
rowData[1] = Arrays.toString((short[]) fieldValue);
} else if (fieldValue instanceof Object[]) {
rowData[1] = Arrays.toString((Object[]) fieldValue);
} else {
rowData[1] = fieldValue;
}
tableModel.addRow(rowData);
}
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
}
// Call on EDT
public void addMBeanInfo(XMBean mbean, MBeanInfo mbeanInfo) {
emptyInfoTable();
emptyDescTable();
((TitledBorder) infoBorderPanel.getBorder()).setTitle(
Messages.MBEAN_INFO);
String text = Messages.INFO + ":";
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.OBJECT_NAME;
rowData[1] = mbean.getObjectName();
tableModel.addRow(rowData);
rowData[0] = Messages.CLASS_NAME;
rowData[1] = mbeanInfo.getClassName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbeanInfo.getDescription();
tableModel.addRow(rowData);
addDescriptor(mbeanInfo.getDescriptor(), text);
// MBeanConstructorInfo
//
int i = 0;
for (MBeanConstructorInfo mbci : mbeanInfo.getConstructors()) {
addMBeanConstructorInfo(mbci,
Messages.CONSTRUCTOR + "-" + i + ":");
// MBeanParameterInfo
//
int j = 0;
for (MBeanParameterInfo mbpi : mbci.getSignature()) {
addMBeanParameterInfo(mbpi,
Messages.PARAMETER + "-" + i + "-" + j + ":");
j++;
}
i++;
}
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
public void addMBeanAttributeInfo(MBeanAttributeInfo mbai) {
emptyInfoTable();
emptyDescTable();
((TitledBorder) infoBorderPanel.getBorder()).setTitle(
Messages.MBEAN_ATTRIBUTE_INFO);
String text = Messages.ATTRIBUTE + ":";
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mbai.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbai.getDescription();
tableModel.addRow(rowData);
rowData[0] = Messages.READABLE;
rowData[1] = mbai.isReadable();
tableModel.addRow(rowData);
rowData[0] = Messages.WRITABLE;
rowData[1] = mbai.isWritable();
tableModel.addRow(rowData);
rowData[0] = Messages.IS;
rowData[1] = mbai.isIs();
tableModel.addRow(rowData);
rowData[0] = Messages.TYPE;
rowData[1] = mbai.getType();
tableModel.addRow(rowData);
addDescriptor(mbai.getDescriptor(), text);
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
public void addMBeanOperationInfo(MBeanOperationInfo mboi) {
emptyInfoTable();
emptyDescTable();
((TitledBorder) infoBorderPanel.getBorder()).setTitle(
Messages.MBEAN_OPERATION_INFO);
String text = Messages.OPERATION + ":";
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mboi.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mboi.getDescription();
tableModel.addRow(rowData);
rowData[0] = Messages.IMPACT;
switch (mboi.getImpact()) {
case MBeanOperationInfo.INFO:
rowData[1] = Messages.INFO_CAPITALIZED;
break;
case MBeanOperationInfo.ACTION:
rowData[1] = Messages.ACTION_CAPITALIZED;
break;
case MBeanOperationInfo.ACTION_INFO:
rowData[1] = Messages.ACTION_INFO_CAPITALIZED;
break;
case MBeanOperationInfo.UNKNOWN:
rowData[1] = Messages.UNKNOWN_CAPITALIZED;
break;
}
tableModel.addRow(rowData);
rowData[0] = Messages.RETURN_TYPE;
rowData[1] = mboi.getReturnType();
tableModel.addRow(rowData);
addDescriptor(mboi.getDescriptor(), text);
// MBeanParameterInfo
//
int i = 0;
for (MBeanParameterInfo mbpi : mboi.getSignature()) {
addMBeanParameterInfo(mbpi,
Messages.PARAMETER + "-" + i++ + ":");
}
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
public void addMBeanNotificationInfo(MBeanNotificationInfo mbni) {
emptyInfoTable();
emptyDescTable();
((TitledBorder) infoBorderPanel.getBorder()).setTitle(
Messages.MBEAN_NOTIFICATION_INFO);
String text = Messages.NOTIFICATION + ":";
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mbni.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbni.getDescription();
tableModel.addRow(rowData);
rowData[0] = Messages.NOTIF_TYPES;
rowData[1] = Arrays.toString(mbni.getNotifTypes());
tableModel.addRow(rowData);
addDescriptor(mbni.getDescriptor(), text);
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
private void addMBeanConstructorInfo(MBeanConstructorInfo mbci, String text) {
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mbci.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbci.getDescription();
tableModel.addRow(rowData);
addDescriptor(mbci.getDescriptor(), text);
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
// Call on EDT
private void addMBeanParameterInfo(MBeanParameterInfo mbpi, String text) {
DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
Object rowData[] = new Object[2];
rowData[0] = new TableRowDivider(text);
rowData[1] = new TableRowDivider("");
tableModel.addRow(rowData);
rowData[0] = Messages.NAME;
rowData[1] = mbpi.getName();
tableModel.addRow(rowData);
rowData[0] = Messages.DESCRIPTION;
rowData[1] = mbpi.getDescription();
tableModel.addRow(rowData);
rowData[0] = Messages.TYPE;
rowData[1] = mbpi.getType();
tableModel.addRow(rowData);
addDescriptor(mbpi.getDescriptor(), text);
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
}

View File

@@ -0,0 +1,711 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.tree.*;
import java.awt.Font;
import java.text.SimpleDateFormat;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.*;
import java.awt.Dimension;
import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import javax.management.*;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.Messages;
@SuppressWarnings("serial")
public class XMBeanNotifications extends JTable implements NotificationListener {
private final static String[] columnNames = {
Messages.TIME_STAMP,
Messages.TYPE,
Messages.USER_DATA,
Messages.SEQ_NUM,
Messages.MESSAGE,
Messages.EVENT,
Messages.SOURCE
};
private HashMap<ObjectName, XMBeanNotificationsListener> listeners =
new HashMap<ObjectName, XMBeanNotificationsListener>();
private volatile boolean subscribed;
private XMBeanNotificationsListener currentListener;
public final static String NOTIFICATION_RECEIVED_EVENT =
"jconsole.xnotification.received";
private List<NotificationListener> notificationListenersList;
private volatile boolean enabled;
private Font normalFont, boldFont;
private int rowMinHeight = -1;
private TableCellEditor userDataEditor = new UserDataCellEditor();
private NotifMouseListener mouseListener = new NotifMouseListener();
private SimpleDateFormat timeFormater = new SimpleDateFormat("HH:mm:ss:SSS");
private static TableCellEditor editor =
new Utils.ReadOnlyTableCellEditor(new JTextField());
public XMBeanNotifications() {
super(new TableSorter(columnNames, 0));
setColumnSelectionAllowed(false);
setRowSelectionAllowed(false);
getTableHeader().setReorderingAllowed(false);
ArrayList<NotificationListener> l =
new ArrayList<NotificationListener>(1);
notificationListenersList = Collections.synchronizedList(l);
addMouseListener(mouseListener);
TableColumnModel colModel = getColumnModel();
colModel.getColumn(0).setPreferredWidth(45);
colModel.getColumn(1).setPreferredWidth(50);
colModel.getColumn(2).setPreferredWidth(50);
colModel.getColumn(3).setPreferredWidth(40);
colModel.getColumn(4).setPreferredWidth(50);
colModel.getColumn(5).setPreferredWidth(50);
setColumnEditors();
addKeyListener(new Utils.CopyKeyAdapter());
}
// Call on EDT
public void cancelCellEditing() {
TableCellEditor tce = getCellEditor();
if (tce != null) {
tce.cancelCellEditing();
}
}
// Call on EDT
public void stopCellEditing() {
TableCellEditor tce = getCellEditor();
if (tce != null) {
tce.stopCellEditing();
}
}
// Call on EDT
@Override
public boolean isCellEditable(int row, int col) {
UserDataCell cell = getUserDataCell(row, col);
if (cell != null) {
return cell.isMaximized();
}
return true;
}
// Call on EDT
@Override
public void setValueAt(Object value, int row, int column) {
}
// Call on EDT
@Override
public synchronized Component prepareRenderer(
TableCellRenderer renderer, int row, int column) {
//In case we have a repaint thread that is in the process of
//repainting an obsolete table, just ignore the call.
//It can happen when MBean selection is switched at a very quick rate
if (row >= getRowCount()) {
return null;
}
Component comp = super.prepareRenderer(renderer, row, column);
if (normalFont == null) {
normalFont = comp.getFont();
boldFont = normalFont.deriveFont(Font.BOLD);
}
UserDataCell cell = getUserDataCell(row, 2);
if (column == 2 && cell != null) {
comp.setFont(boldFont);
int size = cell.getHeight();
if (size > 0) {
if (getRowHeight(row) != size) {
setRowHeight(row, size);
}
}
} else {
comp.setFont(normalFont);
}
return comp;
}
// Call on EDT
@Override
public synchronized TableCellRenderer getCellRenderer(int row, int column) {
//In case we have a repaint thread that is in the process of
//repainting an obsolete table, just ignore the call.
//It can happen when MBean selection is switched at a very quick rate
if (row >= getRowCount()) {
return null;
}
DefaultTableCellRenderer renderer;
String toolTip = null;
UserDataCell cell = getUserDataCell(row, column);
if (cell != null && cell.isInited()) {
renderer = (DefaultTableCellRenderer) cell.getRenderer();
} else {
renderer =
(DefaultTableCellRenderer) super.getCellRenderer(row, column);
}
if (cell != null) {
toolTip = Messages.DOUBLE_CLICK_TO_EXPAND_FORWARD_SLASH_COLLAPSE+
". " + cell.toString();
} else {
Object val =
((DefaultTableModel) getModel()).getValueAt(row, column);
if (val != null) {
toolTip = val.toString();
}
}
renderer.setToolTipText(toolTip);
return renderer;
}
// Call on EDT
private UserDataCell getUserDataCell(int row, int column) {
Object obj = ((DefaultTableModel) getModel()).getValueAt(row, column);
if (obj instanceof UserDataCell) {
return (UserDataCell) obj;
}
return null;
}
synchronized void dispose() {
listeners.clear();
}
public long getReceivedNotifications(XMBean mbean) {
XMBeanNotificationsListener listener =
listeners.get(mbean.getObjectName());
if (listener == null) {
return 0;
} else {
return listener.getReceivedNotifications();
}
}
public synchronized boolean clearCurrentNotifications() {
emptyTable();
if (currentListener != null) {
currentListener.clear();
return true;
} else {
return false;
}
}
public synchronized boolean unregisterListener(DefaultMutableTreeNode node) {
XMBean mbean = (XMBean) ((XNodeInfo) node.getUserObject()).getData();
return unregister(mbean.getObjectName());
}
public synchronized void registerListener(DefaultMutableTreeNode node)
throws InstanceNotFoundException, IOException {
XMBean mbean = (XMBean) ((XNodeInfo) node.getUserObject()).getData();
if (!subscribed) {
try {
mbean.getMBeanServerConnection().addNotificationListener(
MBeanServerDelegate.DELEGATE_NAME, this, null, null);
subscribed = true;
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error adding listener for delegate:");
e.printStackTrace();
}
}
}
XMBeanNotificationsListener listener =
listeners.get(mbean.getObjectName());
if (listener == null) {
listener = new XMBeanNotificationsListener(
this, mbean, node, columnNames);
listeners.put(mbean.getObjectName(), listener);
} else {
if (!listener.isRegistered()) {
emptyTable();
listener.register(node);
}
}
enabled = true;
currentListener = listener;
}
public synchronized void handleNotification(
Notification notif, Object handback) {
try {
if (notif instanceof MBeanServerNotification) {
ObjectName mbean =
((MBeanServerNotification) notif).getMBeanName();
if (notif.getType().indexOf("JMX.mbean.unregistered") >= 0) {
unregister(mbean);
}
}
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error unregistering notification:");
e.printStackTrace();
}
}
}
public synchronized void disableNotifications() {
emptyTable();
currentListener = null;
enabled = false;
}
private synchronized boolean unregister(ObjectName mbean) {
XMBeanNotificationsListener listener = listeners.get(mbean);
if (listener != null && listener.isRegistered()) {
listener.unregister();
return true;
} else {
return false;
}
}
public void addNotificationsListener(NotificationListener nl) {
notificationListenersList.add(nl);
}
public void removeNotificationsListener(NotificationListener nl) {
notificationListenersList.remove(nl);
}
// Call on EDT
void fireNotificationReceived(
XMBeanNotificationsListener listener, XMBean mbean,
DefaultMutableTreeNode node, Object[] rowData, long received) {
if (enabled) {
DefaultTableModel tableModel = (DefaultTableModel) getModel();
if (listener == currentListener) {
tableModel.insertRow(0, rowData);
repaint();
}
}
Notification notif =
new Notification(NOTIFICATION_RECEIVED_EVENT, this, 0);
notif.setUserData(received);
for (NotificationListener nl : notificationListenersList) {
nl.handleNotification(notif, node);
}
}
// Call on EDT
private void updateModel(List<Object[]> data) {
emptyTable();
DefaultTableModel tableModel = (DefaultTableModel) getModel();
for (Object[] rowData : data) {
tableModel.addRow(rowData);
}
}
public synchronized boolean isListenerRegistered(XMBean mbean) {
XMBeanNotificationsListener listener =
listeners.get(mbean.getObjectName());
if (listener == null) {
return false;
}
return listener.isRegistered();
}
// Call on EDT
public synchronized void loadNotifications(XMBean mbean) {
XMBeanNotificationsListener listener =
listeners.get(mbean.getObjectName());
emptyTable();
if (listener != null) {
enabled = true;
List<Object[]> data = listener.getData();
updateModel(data);
currentListener = listener;
validate();
repaint();
} else {
enabled = false;
}
}
// Call on EDT
private void setColumnEditors() {
TableColumnModel tcm = getColumnModel();
for (int i = 0; i < columnNames.length; i++) {
TableColumn tc = tcm.getColumn(i);
if (i == 2) {
tc.setCellEditor(userDataEditor);
} else {
tc.setCellEditor(editor);
}
}
}
// Call on EDT
public boolean isTableEditable() {
return true;
}
// Call on EDT
public synchronized void emptyTable() {
DefaultTableModel model = (DefaultTableModel) getModel();
//invalidate();
while (model.getRowCount() > 0) {
model.removeRow(0);
}
validate();
}
// Call on EDT
synchronized void updateUserDataCell(int row, int col) {
Object obj = getModel().getValueAt(row, 2);
if (obj instanceof UserDataCell) {
UserDataCell cell = (UserDataCell) obj;
if (!cell.isInited()) {
if (rowMinHeight == -1) {
rowMinHeight = getRowHeight(row);
}
cell.init(super.getCellRenderer(row, col), rowMinHeight);
}
cell.switchState();
setRowHeight(row, cell.getHeight());
if (!cell.isMaximized()) {
cancelCellEditing();
//Back to simple editor.
editCellAt(row, 2);
}
invalidate();
repaint();
}
}
class UserDataCellRenderer extends DefaultTableCellRenderer {
Component comp;
UserDataCellRenderer(Component comp) {
this.comp = comp;
Dimension d = comp.getPreferredSize();
if (d.getHeight() > 200) {
comp.setPreferredSize(new Dimension((int) d.getWidth(), 200));
}
}
@Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
return comp;
}
public Component getComponent() {
return comp;
}
}
class UserDataCell {
TableCellRenderer minRenderer;
UserDataCellRenderer maxRenderer;
int minHeight;
boolean minimized = true;
boolean init = false;
Object userData;
UserDataCell(Object userData, Component max) {
this.userData = userData;
this.maxRenderer = new UserDataCellRenderer(max);
}
@Override
public String toString() {
if (userData == null) {
return null;
}
if (userData.getClass().isArray()) {
String name =
Utils.getArrayClassName(userData.getClass().getName());
int length = Array.getLength(userData);
return name + "[" + length + "]";
}
if (userData instanceof CompositeData ||
userData instanceof TabularData) {
return userData.getClass().getName();
}
return userData.toString();
}
boolean isInited() {
return init;
}
void init(TableCellRenderer minRenderer, int minHeight) {
this.minRenderer = minRenderer;
this.minHeight = minHeight;
init = true;
}
void switchState() {
minimized = !minimized;
}
boolean isMaximized() {
return !minimized;
}
void minimize() {
minimized = true;
}
void maximize() {
minimized = false;
}
int getHeight() {
if (minimized) {
return minHeight;
} else {
return (int) maxRenderer.getComponent().
getPreferredSize().getHeight();
}
}
TableCellRenderer getRenderer() {
if (minimized) {
return minRenderer;
} else {
return maxRenderer;
}
}
}
class NotifMouseListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
if (e.getClickCount() >= 2) {
int row = XMBeanNotifications.this.getSelectedRow();
int col = XMBeanNotifications.this.getSelectedColumn();
if (col != 2) {
return;
}
if (col == -1 || row == -1) {
return;
}
XMBeanNotifications.this.updateUserDataCell(row, col);
}
}
}
}
class UserDataCellEditor extends XTextFieldEditor {
// implements javax.swing.table.TableCellEditor
@Override
public Component getTableCellEditorComponent(
JTable table,
Object value,
boolean isSelected,
int row,
int column) {
Object val = value;
if (column == 2) {
Object obj = getModel().getValueAt(row, column);
if (obj instanceof UserDataCell) {
UserDataCell cell = (UserDataCell) obj;
if (cell.getRenderer() instanceof UserDataCellRenderer) {
UserDataCellRenderer zr =
(UserDataCellRenderer) cell.getRenderer();
return zr.getComponent();
}
} else {
Component comp = super.getTableCellEditorComponent(
table, val, isSelected, row, column);
textField.setEditable(false);
return comp;
}
}
return super.getTableCellEditorComponent(
table,
val,
isSelected,
row,
column);
}
@Override
public boolean stopCellEditing() {
int editingRow = getEditingRow();
int editingColumn = getEditingColumn();
if (editingColumn == 2) {
Object obj = getModel().getValueAt(editingRow, editingColumn);
if (obj instanceof UserDataCell) {
UserDataCell cell = (UserDataCell) obj;
if (cell.isMaximized()) {
cancelCellEditing();
return true;
}
}
}
return super.stopCellEditing();
}
}
class XMBeanNotificationsListener implements NotificationListener {
private XMBean xmbean;
private DefaultMutableTreeNode node;
private volatile long received;
private XMBeanNotifications notifications;
private volatile boolean unregistered;
private ArrayList<Object[]> data = new ArrayList<Object[]>();
public XMBeanNotificationsListener(
XMBeanNotifications notifications,
XMBean xmbean,
DefaultMutableTreeNode node,
String[] columnNames) {
this.notifications = notifications;
this.xmbean = xmbean;
this.node = node;
register(node);
}
public synchronized List<Object[]> getData() {
return data;
}
public synchronized void clear() {
data.clear();
received = 0;
}
public synchronized boolean isRegistered() {
return !unregistered;
}
public synchronized void unregister() {
try {
xmbean.getMBeanServerConnection().removeNotificationListener(
xmbean.getObjectName(), this, null, null);
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error removing listener:");
e.printStackTrace();
}
}
unregistered = true;
}
public synchronized long getReceivedNotifications() {
return received;
}
public synchronized void register(DefaultMutableTreeNode node) {
clear();
this.node = node;
try {
xmbean.getMBeanServerConnection().addNotificationListener(
xmbean.getObjectName(), this, null, null);
unregistered = false;
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error adding listener:");
e.printStackTrace();
}
}
}
public synchronized void handleNotification(
final Notification n, Object hb) {
EventQueue.invokeLater(new Runnable() {
public void run() {
synchronized (XMBeanNotificationsListener.this) {
try {
if (unregistered) {
return;
}
Date receivedDate = new Date(n.getTimeStamp());
String time = timeFormater.format(receivedDate);
Object userData = n.getUserData();
Component comp = null;
UserDataCell cell = null;
if ((comp = XDataViewer.createNotificationViewer(userData)) != null) {
XDataViewer.registerForMouseEvent(comp, mouseListener);
cell = new UserDataCell(userData, comp);
}
Object[] rowData = {
time,
n.getType(),
(cell == null ? userData : cell),
n.getSequenceNumber(),
n.getMessage(),
n,
n.getSource()
};
received++;
data.add(0, rowData);
notifications.fireNotificationReceived(
XMBeanNotificationsListener.this,
xmbean, node, rowData, received);
} catch (Exception e) {
if (JConsole.isDebug()) {
System.err.println("Error handling notification:");
e.printStackTrace();
}
}
}
}
});
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2004, 2008, 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 sun.tools.jconsole.inspector;
import javax.management.*;
import java.util.ArrayList;
import sun.tools.jconsole.MBeansTab;
@SuppressWarnings("serial")
public class XMBeanOperations extends XOperations {
public XMBeanOperations(MBeansTab mbeansTab) {
super(mbeansTab);
}
protected MBeanOperationInfo[] updateOperations(MBeanOperationInfo[] operations) {
//remove get,set and is
ArrayList<MBeanOperationInfo> mbeanOperations =
new ArrayList<MBeanOperationInfo>(operations.length);
for(MBeanOperationInfo operation : operations) {
if (!( (operation.getSignature().length == 0 &&
operation.getName().startsWith("get") &&
!operation.getReturnType().equals("void")) ||
(operation.getSignature().length == 1 &&
operation.getName().startsWith("set") &&
operation.getReturnType().equals("void")) ||
(operation.getName().startsWith("is") &&
operation.getReturnType().equals("boolean"))
) ) {
mbeanOperations.add(operation);
}
}
return mbeanOperations.toArray(new MBeanOperationInfo[0]);
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2006, 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 sun.tools.jconsole.inspector;
/**
* <p>This class represents the user object of the nodes in the MBean tree.</p>
*
* <p>It encapsulates the node's info, i.e. the type of the node, the label to
* be used when displaying the node in the MBean tree, the node's tool tip text
* and arbitrary data which varies depending on the type of the node: an XMBean
* reference for MBEAN, ATTRIBUTES, OPERATIONS and NOTIFICATIONS nodes; the
* corresponding MBeanInfo for ATTRIBUTE, OPERATION and NOTIFICATION nodes;
* it is not used for NONMBEAN nodes.</p>
*/
public class XNodeInfo {
public static enum Type {
MBEAN, NONMBEAN,
ATTRIBUTES, OPERATIONS, NOTIFICATIONS,
ATTRIBUTE, OPERATION, NOTIFICATION
};
public XNodeInfo(Type type, Object data, String label, String tooltip) {
this.type = type;
this.data = data;
this.label = label;
this.tooltip = tooltip;
}
public Type getType() {
return type;
}
public Object getData() {
return data;
}
public String getLabel() {
return label;
}
public String getToolTipText() {
return tooltip;
}
public String toString() {
return label;
}
private Type type;
private Object data;
private String label;
private String tooltip;
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole.inspector;
// java import
import javax.swing.*;
import java.util.Objects;
/**
* This provides a wrapper to the Object class to allow it to be
displayed/manipulated as a GUI object.
*/
@SuppressWarnings("serial")
public class XObject extends JLabel {
private Object object;
private static boolean useHashCodeRepresentation = true;
public final static XObject NULL_OBJECT = new XObject("null");
public XObject (Object object, Icon icon) {
this(object);
setIcon(icon);
}
public XObject (Object object) {
setObject(object);
setHorizontalAlignment(SwingConstants.LEFT);
}
public boolean equals(Object o) {
if (o instanceof XObject) {
return Objects.equals(object, ((XObject)o).getObject());
}
return false;
}
@Override
public int hashCode() {
return object.hashCode();
}
public Object getObject() {
return object;
}
//if true the the object.hashcode is added to the label
public static void
useHashCodeRepresentation(boolean useHashCodeRepresentation) {
XObject.useHashCodeRepresentation = useHashCodeRepresentation;
}
public static boolean hashCodeRepresentation() {
return useHashCodeRepresentation;
}
public void setObject(Object object) {
this.object = object;
// if the object is not a swing component,
// use default icon
try {
String text = null;
if (object instanceof JLabel) {
setIcon(((JLabel)object).getIcon());
if (getText() != null) {
text = ((JLabel)object).getText();
}
}
else if (object instanceof JButton) {
setIcon(((JButton)object).getIcon());
if (getText() != null) {
text = ((JButton)object).getText();
}
}
else if (getText() != null) {
text = object.toString();
setIcon(IconManager.DEFAULT_XOBJECT);
}
if (text != null) {
if (useHashCodeRepresentation && (this != NULL_OBJECT)) {
text = text + " ("+object.hashCode()+")";
}
setText(text);
}
}
catch (Exception e) {
System.out.println("Error setting XObject object :"+
e.getMessage());
}
}
}

View File

@@ -0,0 +1,816 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Component;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.*;
import java.awt.Dimension;
import java.util.*;
import java.lang.reflect.Array;
import javax.management.openmbean.*;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.Messages;
import sun.tools.jconsole.Resources;
@SuppressWarnings("serial")
public class XOpenTypeViewer extends JPanel implements ActionListener {
JButton prev, incr, decr, tabularPrev, tabularNext;
JLabel compositeLabel, tabularLabel;
JScrollPane container;
XOpenTypeData current;
XOpenTypeDataListener listener = new XOpenTypeDataListener();
private static final String compositeNavigationSingle =
Messages.MBEANS_TAB_COMPOSITE_NAVIGATION_SINGLE;
private static final String tabularNavigationSingle =
Messages.MBEANS_TAB_TABULAR_NAVIGATION_SINGLE;
private static TableCellEditor editor =
new Utils.ReadOnlyTableCellEditor(new JTextField());
class XOpenTypeDataListener extends MouseAdapter {
XOpenTypeDataListener() {
}
public void mousePressed(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1) {
if(e.getClickCount() >= 2) {
XOpenTypeData elem = getSelectedViewedOpenType();
if(elem != null) {
try {
elem.viewed(XOpenTypeViewer.this);
}catch(Exception ex) {
//Nothing to change, the element
//can't be displayed
}
}
}
}
}
private XOpenTypeData getSelectedViewedOpenType() {
int row = XOpenTypeViewer.this.current.getSelectedRow();
int col = XOpenTypeViewer.this.current.getSelectedColumn();
Object elem =
XOpenTypeViewer.this.current.getModel().getValueAt(row, col);
if(elem instanceof XOpenTypeData)
return (XOpenTypeData) elem;
else
return null;
}
}
static interface Navigatable {
public void incrElement();
public void decrElement();
public boolean canDecrement();
public boolean canIncrement();
public int getElementCount();
public int getSelectedElementIndex();
}
static interface XViewedTabularData extends Navigatable {
}
static interface XViewedArrayData extends Navigatable {
}
static abstract class XOpenTypeData extends JTable {
XOpenTypeData parent;
protected int col1Width = -1;
protected int col2Width = -1;
private boolean init;
private Font normalFont, boldFont;
protected XOpenTypeData(XOpenTypeData parent) {
this.parent = parent;
}
public XOpenTypeData getViewedParent() {
return parent;
}
public String getToolTip(int row, int col) {
if(col == 1) {
Object value = getModel().getValueAt(row, col);
if (value != null) {
if(isClickableElement(value))
return Messages.DOUBLE_CLICK_TO_VISUALIZE
+ ". " + value.toString();
else
return value.toString();
}
}
return null;
}
public TableCellRenderer getCellRenderer(int row, int column) {
DefaultTableCellRenderer tcr =
(DefaultTableCellRenderer)super.getCellRenderer(row,column);
tcr.setToolTipText(getToolTip(row,column));
return tcr;
}
public void renderKey(String key, Component comp) {
comp.setFont(normalFont);
}
public Component prepareRenderer(TableCellRenderer renderer,
int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
if (normalFont == null) {
normalFont = comp.getFont();
boldFont = normalFont.deriveFont(Font.BOLD);
}
Object o = ((DefaultTableModel) getModel()).getValueAt(row, column);
if (column == 0) {
String key = o.toString();
renderKey(key, comp);
} else {
if (isClickableElement(o)) {
comp.setFont(boldFont);
} else {
comp.setFont(normalFont);
}
}
return comp;
}
protected boolean isClickableElement(Object obj) {
if (obj instanceof XOpenTypeData) {
if (obj instanceof Navigatable) {
return (((Navigatable) obj).getElementCount() != 0);
} else {
return (obj instanceof XCompositeData);
}
}
return false;
}
protected void updateColumnWidth() {
if (!init) {
TableColumnModel colModel = getColumnModel();
if (col2Width == -1) {
col1Width = col1Width * 7;
if (col1Width <
getPreferredScrollableViewportSize().getWidth()) {
col1Width = (int)
getPreferredScrollableViewportSize().getWidth();
}
colModel.getColumn(0).setPreferredWidth(col1Width);
init = true;
return;
}
col1Width = (col1Width * 7) + 7;
col1Width = Math.max(col1Width, 70);
col2Width = (col2Width * 7) + 7;
if (col1Width + col2Width <
getPreferredScrollableViewportSize().getWidth()) {
col2Width = (int)
getPreferredScrollableViewportSize().getWidth() -
col1Width;
}
colModel.getColumn(0).setPreferredWidth(col1Width);
colModel.getColumn(1).setPreferredWidth(col2Width);
init = true;
}
}
public abstract void viewed(XOpenTypeViewer viewer) throws Exception;
protected void initTable(String[] columnNames) {
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
getTableHeader().setReorderingAllowed(false);
((DefaultTableModel) getModel()).setColumnIdentifiers(columnNames);
for (Enumeration<TableColumn> e = getColumnModel().getColumns();
e.hasMoreElements();) {
TableColumn tc = e.nextElement();
tc.setCellEditor(editor);
}
addKeyListener(new Utils.CopyKeyAdapter());
setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
setPreferredScrollableViewportSize(new Dimension(350, 200));
}
protected void emptyTable() {
invalidate();
while (getModel().getRowCount()>0)
((DefaultTableModel) getModel()).removeRow(0);
validate();
}
public void setValueAt(Object value, int row, int col) {
}
}
static class TabularDataComparator implements Comparator<CompositeData> {
private final List<String> indexNames;
public TabularDataComparator(TabularType type) {
indexNames = type.getIndexNames();
}
@SuppressWarnings("unchecked")
public int compare(CompositeData o1, CompositeData o2) {
for (String key : indexNames) {
Object c1 = o1.get(key);
Object c2 = o2.get(key);
if (c1 instanceof Comparable && c2 instanceof Comparable) {
int result = ((Comparable<Object>) c1).compareTo(c2);
if (result != 0)
return result;
}
}
return 0;
}
}
static class XTabularData extends XCompositeData
implements XViewedTabularData {
final TabularData tabular;
final TabularType type;
int currentIndex = 0;
final Object[] elements;
final int size;
private Font normalFont, italicFont;
@SuppressWarnings("unchecked")
public XTabularData(XOpenTypeData parent, TabularData tabular) {
super(parent, accessFirstElement(tabular));
this.tabular = tabular;
type = tabular.getTabularType();
size = tabular.values().size();
if (size > 0) {
// Order tabular data elements using index names
List<CompositeData> data = new ArrayList<CompositeData>(
(Collection<CompositeData>) tabular.values());
Collections.sort(data, new TabularDataComparator(type));
elements = data.toArray();
loadCompositeData((CompositeData) elements[0]);
} else {
elements = new Object[0];
}
}
private static CompositeData accessFirstElement(TabularData tabular) {
if(tabular.values().size() == 0) return null;
return (CompositeData) tabular.values().toArray()[0];
}
public void renderKey(String key, Component comp) {
if (normalFont == null) {
normalFont = comp.getFont();
italicFont = normalFont.deriveFont(Font.ITALIC);
}
for(Object k : type.getIndexNames()) {
if(key.equals(k))
comp.setFont(italicFont);
}
}
public int getElementCount() {
return size;
}
public int getSelectedElementIndex() {
return currentIndex;
}
public void incrElement() {
currentIndex++;
loadCompositeData((CompositeData)elements[currentIndex]);
}
public void decrElement() {
currentIndex--;
loadCompositeData((CompositeData)elements[currentIndex]);
}
public boolean canDecrement() {
if(currentIndex == 0)
return false;
else
return true;
}
public boolean canIncrement(){
if(size == 0 ||
currentIndex == size -1)
return false;
else
return true;
}
public String toString() {
return type == null ? "" : type.getDescription();
}
}
static class XCompositeData extends XOpenTypeData {
protected final String[] columnNames = {
Messages.NAME, Messages.VALUE
};
CompositeData composite;
public XCompositeData() {
super(null);
initTable(columnNames);
}
//In sync with array, no init table.
public XCompositeData(XOpenTypeData parent) {
super(parent);
}
public XCompositeData(XOpenTypeData parent,
CompositeData composite) {
super(parent);
initTable(columnNames);
if(composite != null) {
this.composite = composite;
loadCompositeData(composite);
}
}
public void viewed(XOpenTypeViewer viewer) throws Exception {
viewer.setOpenType(this);
updateColumnWidth();
}
public String toString() {
return composite == null ? "" :
composite.getCompositeType().getTypeName();
}
protected Object formatKey(String key) {
return key;
}
private void load(CompositeData data) {
CompositeType type = data.getCompositeType();
Set<String> keys = type.keySet();
Iterator<String> it = keys.iterator();
Object[] rowData = new Object[2];
while (it.hasNext()) {
String key = (String) it.next();
Object val = data.get(key);
rowData[0] = formatKey(key);
if (val == null) {
rowData[1] = "";
} else {
OpenType<?> openType = type.getType(key);
if (openType instanceof CompositeType) {
rowData[1] =
new XCompositeData(this, (CompositeData) val);
} else if (openType instanceof ArrayType) {
rowData[1] =
new XArrayData(this, (ArrayType<?>) openType, val);
} else if (openType instanceof SimpleType) {
rowData[1] = val;
} else if (openType instanceof TabularType) {
rowData[1] = new XTabularData(this, (TabularData) val);
}
}
// Update column width
String str = null;
if (rowData[0] != null) {
str = rowData[0].toString();
if (str.length() > col1Width) {
col1Width = str.length();
}
}
if (rowData[1] != null) {
str = rowData[1].toString();
if (str.length() > col2Width) {
col2Width = str.length();
}
}
((DefaultTableModel) getModel()).addRow(rowData);
}
}
protected void loadCompositeData(CompositeData data) {
composite = data;
emptyTable();
load(data);
DefaultTableModel tableModel = (DefaultTableModel) getModel();
tableModel.newDataAvailable(new TableModelEvent(tableModel));
}
}
static class XArrayData extends XCompositeData
implements XViewedArrayData {
private int dimension;
private int size;
private OpenType<?> elemType;
private Object val;
private boolean isCompositeType;
private boolean isTabularType;
private int currentIndex;
private CompositeData[] elements;
private final String[] arrayColumns = {Messages.VALUE};
private Font normalFont, boldFont;
XArrayData(XOpenTypeData parent, ArrayType<?> type, Object val) {
this(parent, type.getDimension(), type.getElementOpenType(), val);
}
XArrayData(XOpenTypeData parent, int dimension,
OpenType<?> elemType, Object val) {
super(parent);
this.dimension = dimension;
this.elemType = elemType;
this.val = val;
String[] columns = null;
if (dimension > 1) return;
isCompositeType = (elemType instanceof CompositeType);
isTabularType = (elemType instanceof TabularType);
columns = isCompositeType ? columnNames : arrayColumns;
initTable(columns);
loadArray();
}
public void viewed(XOpenTypeViewer viewer) throws Exception {
if (size == 0)
throw new Exception(Messages.EMPTY_ARRAY);
if (dimension > 1)
throw new Exception(Messages.DIMENSION_IS_NOT_SUPPORTED_COLON +
dimension);
super.viewed(viewer);
}
public int getElementCount() {
return size;
}
public int getSelectedElementIndex() {
return currentIndex;
}
public void renderKey(String key, Component comp) {
if (normalFont == null) {
normalFont = comp.getFont();
boldFont = normalFont.deriveFont(Font.BOLD);
}
if (isTabularType) {
comp.setFont(boldFont);
}
}
public void incrElement() {
currentIndex++;
loadCompositeData(elements[currentIndex]);
}
public void decrElement() {
currentIndex--;
loadCompositeData(elements[currentIndex]);
}
public boolean canDecrement() {
if (isCompositeType && currentIndex > 0) {
return true;
}
return false;
}
public boolean canIncrement() {
if (isCompositeType && currentIndex < size - 1) {
return true;
}
return false;
}
private void loadArray() {
if (isCompositeType) {
elements = (CompositeData[]) val;
size = elements.length;
if (size != 0) {
loadCompositeData(elements[0]);
}
} else {
load();
}
}
private void load() {
Object[] rowData = new Object[1];
size = Array.getLength(val);
for (int i = 0; i < size; i++) {
rowData[0] = isTabularType ?
new XTabularData(this, (TabularData) Array.get(val, i)) :
Array.get(val, i);
String str = rowData[0].toString();
if (str.length() > col1Width) {
col1Width = str.length();
}
((DefaultTableModel) getModel()).addRow(rowData);
}
}
public String toString() {
if (dimension > 1) {
return Messages.DIMENSION_IS_NOT_SUPPORTED_COLON +
dimension;
} else {
return elemType.getTypeName() + "[" + size + "]";
}
}
}
/**
* The supplied value is viewable iff:
* - it's a CompositeData/TabularData, or
* - it's a non-empty array of CompositeData/TabularData, or
* - it's a non-empty Collection of CompositeData/TabularData.
*/
public static boolean isViewableValue(Object value) {
// Check for CompositeData/TabularData
//
if (value instanceof CompositeData || value instanceof TabularData) {
return true;
}
// Check for non-empty array of CompositeData/TabularData
//
if (value instanceof CompositeData[] || value instanceof TabularData[]) {
return Array.getLength(value) > 0;
}
// Check for non-empty Collection of CompositeData/TabularData
//
if (value instanceof Collection) {
Collection<?> c = (Collection<?>) value;
if (c.isEmpty()) {
// Empty Collections are not viewable
//
return false;
} else {
// Only Collections of CompositeData/TabularData are viewable
//
return Utils.isUniformCollection(c, CompositeData.class) ||
Utils.isUniformCollection(c, TabularData.class);
}
}
return false;
}
public static Component loadOpenType(Object value) {
Component comp = null;
if(isViewableValue(value)) {
XOpenTypeViewer open =
new XOpenTypeViewer(value);
comp = open;
}
return comp;
}
private XOpenTypeViewer(Object value) {
XOpenTypeData comp = null;
if (value instanceof CompositeData) {
comp = new XCompositeData(null, (CompositeData) value);
} else if (value instanceof TabularData) {
comp = new XTabularData(null, (TabularData) value);
} else if (value instanceof CompositeData[]) {
CompositeData cda[] = (CompositeData[]) value;
CompositeType ct = cda[0].getCompositeType();
comp = new XArrayData(null, 1, ct, cda);
} else if (value instanceof TabularData[]) {
TabularData tda[] = (TabularData[]) value;
TabularType tt = tda[0].getTabularType();
comp = new XArrayData(null, 1, tt, tda);
} else if (value instanceof Collection) {
// At this point we know 'value' is a uniform collection, either
// Collection<CompositeData> or Collection<TabularData>, because
// isViewableValue() has been called before calling the private
// XOpenTypeViewer() constructor.
//
Object e = ((Collection<?>) value).iterator().next();
if (e instanceof CompositeData) {
Collection<?> cdc = (Collection<?>) value;
CompositeData cda[] = cdc.toArray(new CompositeData[0]);
CompositeType ct = cda[0].getCompositeType();
comp = new XArrayData(null, 1, ct, cda);
} else if (e instanceof TabularData) {
Collection<?> tdc = (Collection<?>) value;
TabularData tda[] = tdc.toArray(new TabularData[0]);
TabularType tt = tda[0].getTabularType();
comp = new XArrayData(null, 1, tt, tda);
}
}
setupDisplay(comp);
try {
comp.viewed(this);
} catch (Exception e) {
// Nothing to change, the element can't be displayed
if (JConsole.isDebug()) {
System.out.println("Exception viewing openType : " + e);
e.printStackTrace();
}
}
}
void setOpenType(XOpenTypeData data) {
if (current != null) {
current.removeMouseListener(listener);
}
current = data;
// Enable/Disable the previous (<<) button
if (current.getViewedParent() == null) {
prev.setEnabled(false);
} else {
prev.setEnabled(true);
}
// Set the listener to handle double-click mouse events
current.addMouseListener(listener);
// Enable/Disable the tabular buttons
if (!(data instanceof XViewedTabularData)) {
tabularPrev.setEnabled(false);
tabularNext.setEnabled(false);
tabularLabel.setText(tabularNavigationSingle);
tabularLabel.setEnabled(false);
} else {
XViewedTabularData tabular = (XViewedTabularData) data;
tabularNext.setEnabled(tabular.canIncrement());
tabularPrev.setEnabled(tabular.canDecrement());
boolean hasMoreThanOneElement =
tabular.canIncrement() || tabular.canDecrement();
if (hasMoreThanOneElement) {
tabularLabel.setText(
Resources.format(Messages.MBEANS_TAB_TABULAR_NAVIGATION_MULTIPLE,
String.format("%d", tabular.getSelectedElementIndex() + 1),
String.format("%d", tabular.getElementCount())));
} else {
tabularLabel.setText(tabularNavigationSingle);
}
tabularLabel.setEnabled(hasMoreThanOneElement);
}
// Enable/Disable the composite buttons
if (!(data instanceof XViewedArrayData)) {
incr.setEnabled(false);
decr.setEnabled(false);
compositeLabel.setText(compositeNavigationSingle);
compositeLabel.setEnabled(false);
} else {
XViewedArrayData array = (XViewedArrayData) data;
incr.setEnabled(array.canIncrement());
decr.setEnabled(array.canDecrement());
boolean hasMoreThanOneElement =
array.canIncrement() || array.canDecrement();
if (hasMoreThanOneElement) {
compositeLabel.setText(
Resources.format(Messages.MBEANS_TAB_COMPOSITE_NAVIGATION_MULTIPLE,
String.format("%d", array.getSelectedElementIndex() + 1),
String.format("%d", array.getElementCount())));
} else {
compositeLabel.setText(compositeNavigationSingle);
}
compositeLabel.setEnabled(hasMoreThanOneElement);
}
container.invalidate();
container.setViewportView(current);
container.validate();
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() instanceof JButton) {
JButton b = (JButton) event.getSource();
if (b == prev) {
XOpenTypeData parent = current.getViewedParent();
try {
parent.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
} else if (b == incr) {
((XViewedArrayData) current).incrElement();
try {
current.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
} else if (b == decr) {
((XViewedArrayData) current).decrElement();
try {
current.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
} else if (b == tabularNext) {
((XViewedTabularData) current).incrElement();
try {
current.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
} else if (b == tabularPrev) {
((XViewedTabularData) current).decrElement();
try {
current.viewed(this);
} catch (Exception e) {
//Nothing to change, the element can't be displayed
}
}
}
}
private void setupDisplay(XOpenTypeData data) {
setBackground(Color.white);
container =
new JScrollPane(data,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
tabularPrev = new JButton(Messages.LESS_THAN);
tabularNext = new JButton(Messages.GREATER_THAN);
JPanel tabularButtons = new JPanel(new FlowLayout(FlowLayout.LEFT));
tabularButtons.add(tabularPrev);
tabularPrev.addActionListener(this);
tabularLabel = new JLabel(tabularNavigationSingle);
tabularLabel.setEnabled(false);
tabularButtons.add(tabularLabel);
tabularButtons.add(tabularNext);
tabularNext.addActionListener(this);
tabularButtons.setBackground(Color.white);
prev = new JButton(Messages.A_LOT_LESS_THAN);
prev.addActionListener(this);
buttons.add(prev);
incr = new JButton(Messages.GREATER_THAN);
incr.addActionListener(this);
decr = new JButton(Messages.LESS_THAN);
decr.addActionListener(this);
JPanel array = new JPanel();
array.setBackground(Color.white);
array.add(decr);
compositeLabel = new JLabel(compositeNavigationSingle);
compositeLabel.setEnabled(false);
array.add(compositeLabel);
array.add(incr);
buttons.add(array);
setLayout(new BorderLayout());
buttons.setBackground(Color.white);
JPanel navigationPanel = new JPanel(new BorderLayout());
navigationPanel.setBackground(Color.white);
navigationPanel.add(tabularButtons, BorderLayout.NORTH);
navigationPanel.add(buttons, BorderLayout.WEST);
add(navigationPanel, BorderLayout.NORTH);
add(container, BorderLayout.CENTER);
Dimension d = new Dimension((int)container.getPreferredSize().
getWidth() + 20,
(int)container.getPreferredSize().
getHeight() + 20);
setPreferredSize(d);
}
}

View File

@@ -0,0 +1,222 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.FlowLayout;
import java.awt.Component;
import java.awt.event.*;
import java.util.*;
import javax.management.*;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.Messages;
public abstract class XOperations extends JPanel implements ActionListener {
public final static String OPERATION_INVOCATION_EVENT =
"jam.xoperations.invoke.result";
private java.util.List<NotificationListener> notificationListenersList;
private Hashtable<JButton, OperationEntry> operationEntryTable;
private XMBean mbean;
private MBeanInfo mbeanInfo;
private MBeansTab mbeansTab;
public XOperations(MBeansTab mbeansTab) {
super(new GridLayout(1, 1));
this.mbeansTab = mbeansTab;
operationEntryTable = new Hashtable<JButton, OperationEntry>();
ArrayList<NotificationListener> l =
new ArrayList<NotificationListener>(1);
notificationListenersList =
Collections.synchronizedList(l);
}
// Call on EDT
public void removeOperations() {
removeAll();
}
// Call on EDT
public void loadOperations(XMBean mbean, MBeanInfo mbeanInfo) {
this.mbean = mbean;
this.mbeanInfo = mbeanInfo;
// add operations information
MBeanOperationInfo operations[] = mbeanInfo.getOperations();
invalidate();
// remove listeners, if any
Component listeners[] = getComponents();
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] instanceof JButton) {
((JButton) listeners[i]).removeActionListener(this);
}
}
removeAll();
setLayout(new BorderLayout());
JButton methodButton;
JLabel methodLabel;
JPanel innerPanelLeft, innerPanelRight;
JPanel outerPanelLeft, outerPanelRight;
outerPanelLeft = new JPanel(new GridLayout(operations.length, 1));
outerPanelRight = new JPanel(new GridLayout(operations.length, 1));
for (int i = 0; i < operations.length; i++) {
innerPanelLeft = new JPanel(new FlowLayout(FlowLayout.RIGHT));
innerPanelRight = new JPanel(new FlowLayout(FlowLayout.LEFT));
String returnType = operations[i].getReturnType();
if (returnType == null) {
methodLabel = new JLabel("null", JLabel.RIGHT);
if (JConsole.isDebug()) {
System.err.println(
"WARNING: The operation's return type " +
"shouldn't be \"null\". Check how the " +
"MBeanOperationInfo for the \"" +
operations[i].getName() + "\" operation has " +
"been defined in the MBean's implementation code.");
}
} else {
methodLabel = new JLabel(
Utils.getReadableClassName(returnType), JLabel.RIGHT);
}
innerPanelLeft.add(methodLabel);
if (methodLabel.getText().length() > 20) {
methodLabel.setText(methodLabel.getText().
substring(methodLabel.getText().
lastIndexOf(".") + 1,
methodLabel.getText().length()));
}
methodButton = new JButton(operations[i].getName());
methodButton.setToolTipText(operations[i].getDescription());
boolean callable = isCallable(operations[i].getSignature());
if (callable) {
methodButton.addActionListener(this);
} else {
methodButton.setEnabled(false);
}
MBeanParameterInfo[] signature = operations[i].getSignature();
OperationEntry paramEntry = new OperationEntry(operations[i],
callable,
methodButton,
this);
operationEntryTable.put(methodButton, paramEntry);
innerPanelRight.add(methodButton);
if (signature.length == 0) {
innerPanelRight.add(new JLabel("( )", JLabel.CENTER));
} else {
innerPanelRight.add(paramEntry);
}
outerPanelLeft.add(innerPanelLeft, BorderLayout.WEST);
outerPanelRight.add(innerPanelRight, BorderLayout.CENTER);
}
add(outerPanelLeft, BorderLayout.WEST);
add(outerPanelRight, BorderLayout.CENTER);
validate();
}
private boolean isCallable(MBeanParameterInfo[] signature) {
for (int i = 0; i < signature.length; i++) {
if (!Utils.isEditableType(signature[i].getType())) {
return false;
}
}
return true;
}
// Call on EDT
public void actionPerformed(final ActionEvent e) {
performInvokeRequest((JButton) e.getSource());
}
void performInvokeRequest(final JButton button) {
final OperationEntry entryIf = operationEntryTable.get(button);
new SwingWorker<Object, Void>() {
@Override
public Object doInBackground() throws Exception {
return mbean.invoke(button.getText(),
entryIf.getParameters(), entryIf.getSignature());
}
@Override
protected void done() {
try {
Object result = get();
// sends result notification to upper level if
// there is a return value
if (entryIf.getReturnType() != null &&
!entryIf.getReturnType().equals(Void.TYPE.getName()) &&
!entryIf.getReturnType().equals(Void.class.getName())) {
fireChangedNotification(OPERATION_INVOCATION_EVENT, button, result);
} else {
new ThreadDialog(
button,
Messages.METHOD_SUCCESSFULLY_INVOKED,
Messages.INFO,
JOptionPane.INFORMATION_MESSAGE).run();
}
} catch (Throwable t) {
t = Utils.getActualException(t);
if (JConsole.isDebug()) {
t.printStackTrace();
}
new ThreadDialog(
button,
Messages.PROBLEM_INVOKING + " " +
button.getText() + " : " + t.toString(),
Messages.ERROR,
JOptionPane.ERROR_MESSAGE).run();
}
}
}.execute();
}
public void addOperationsListener(NotificationListener nl) {
notificationListenersList.add(nl);
}
public void removeOperationsListener(NotificationListener nl) {
notificationListenersList.remove(nl);
}
// Call on EDT
private void fireChangedNotification(
String type, Object source, Object handback) {
Notification n = new Notification(type, source, 0);
for (NotificationListener nl : notificationListenersList) {
nl.handleNotification(n, handback);
}
}
protected abstract MBeanOperationInfo[] updateOperations(MBeanOperationInfo[] operations);
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import sun.tools.jconsole.Plotter;
import javax.swing.JTable;
@SuppressWarnings("serial")
public class XPlotter extends Plotter {
JTable table;
public XPlotter(JTable table,
Plotter.Unit unit) {
super(unit,0,false);
this.table = table;
}
@Override
public void addValues(long time, long... values) {
super.addValues(time, values);
table.repaint();
}
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.Timer;
import javax.swing.*;
import sun.tools.jconsole.*;
@SuppressWarnings("serial")
public class XPlottingViewer extends PlotterPanel implements ActionListener {
// 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 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.table = table;
this.attributeName = attributeName;
Plotter plotter = createPlotter(mbean, attributeName, key, table);
setupDisplay(plotter);
}
static void dispose(MBeansTab tab) {
Iterator<String> it = plotterCache.keySet().iterator();
while(it.hasNext()) {
String key = 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.cancel();
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()) + " " + String.valueOf(mbean.hashCode()) + " " + mbean.getObjectName().getCanonicalName() + attributeName;
XPlottingViewer plotter = plotterCache.get(key);
if(plotter == null) {
plotter = new XPlottingViewer(key,
mbean,
attributeName,
value,
table,
tab);
plotterCache.put(key, plotter);
}
comp = plotter;
}
return comp;
}
/*public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(g.getColor());
plotter.paintComponent(g);
}*/
@Override
public void actionPerformed(ActionEvent evt) {
plotterCache.remove(key);
Timer t = timerCache.remove(key);
t.cancel();
((XMBeanAttributes) table).collapse(attributeName, this);
}
//Create plotter instance
public Plotter createPlotter(final XMBean xmbean,
final String attributeName,
String key,
JTable table) {
final Plotter plotter = new XPlotter(table, Plotter.Unit.NONE) {
Dimension prefSize = new Dimension(400, 170);
@Override
public Dimension getPreferredSize() {
return prefSize;
}
@Override
public Dimension getMinimumSize() {
return prefSize;
}
};
plotter.createSequence(attributeName, attributeName, null, true);
TimerTask timerTask = new TimerTask() {
public void run() {
tab.workerAdd(new Runnable() {
public void run() {
try {
Number n =
(Number) xmbean.getSnapshotMBeanServerConnection().getAttribute(xmbean.getObjectName(), attributeName);
long v;
if (n instanceof Float || n instanceof Double) {
plotter.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();
}
plotter.addValues(System.currentTimeMillis(), v);
} catch (Exception ex) {
// Should have a trace logged with proper
// trace mecchanism
}
}
});
}
};
String timerName = "Timer-" + key;
Timer timer = new Timer(timerName, true);
timer.schedule(timerTask, 0, tab.getUpdateInterval());
timerCache.put(key, timer);
return plotter;
}
private void setupDisplay(Plotter plotter) {
final JPanel buttonPanel = new JPanel();
final GridBagLayout gbl = new GridBagLayout();
buttonPanel.setLayout(gbl);
setLayout(new BorderLayout());
plotButton = new JButton(Messages.DISCARD_CHART);
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 label = 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(label, labelConstraints);
plotterLabelPanel.add(label);
add(plotterLabelPanel, BorderLayout.NORTH);
}
setPlotter(plotter);
add(buttonPanel, BorderLayout.SOUTH);
repaint();
}
}

View File

@@ -0,0 +1,749 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.management.IntrospectionException;
import javax.management.NotificationListener;
import javax.management.MBeanInfo;
import javax.management.InstanceNotFoundException;
import javax.management.ReflectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.border.LineBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import sun.tools.jconsole.*;
import sun.tools.jconsole.inspector.XNodeInfo.Type;
@SuppressWarnings("serial")
public class XSheet extends JPanel
implements ActionListener, NotificationListener {
private JPanel mainPanel;
private JPanel southPanel;
// Node being currently displayed
private volatile DefaultMutableTreeNode currentNode;
// MBean being currently displayed
private volatile XMBean mbean;
// XMBeanAttributes container
private XMBeanAttributes mbeanAttributes;
// XMBeanOperations container
private XMBeanOperations mbeanOperations;
// XMBeanNotifications container
private XMBeanNotifications mbeanNotifications;
// XMBeanInfo container
private XMBeanInfo mbeanInfo;
// Refresh JButton (mbean attributes case)
private JButton refreshButton;
// Subscribe/Unsubscribe/Clear JButton (mbean notifications case)
private JButton clearButton, subscribeButton, unsubscribeButton;
// Reference to MBeans tab
private MBeansTab mbeansTab;
public XSheet(MBeansTab mbeansTab) {
this.mbeansTab = mbeansTab;
setupScreen();
}
public void dispose() {
clear();
XDataViewer.dispose(mbeansTab);
mbeanNotifications.dispose();
}
private void setupScreen() {
setLayout(new BorderLayout());
setBorder(BorderFactory.createLineBorder(Color.GRAY));
// add main panel to XSheet
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
// add south panel to XSheet
southPanel = new JPanel();
add(southPanel, BorderLayout.SOUTH);
// create the refresh button
refreshButton = new JButton(Messages.MBEANS_TAB_REFRESH_ATTRIBUTES_BUTTON);
refreshButton.setMnemonic(Resources.getMnemonicInt(Messages.MBEANS_TAB_REFRESH_ATTRIBUTES_BUTTON));
refreshButton.setToolTipText(Messages.MBEANS_TAB_REFRESH_ATTRIBUTES_BUTTON_TOOLTIP);
refreshButton.addActionListener(this);
// create the clear button
clearButton = new JButton(Messages.MBEANS_TAB_CLEAR_NOTIFICATIONS_BUTTON);
clearButton.setMnemonic(Resources.getMnemonicInt(Messages.MBEANS_TAB_CLEAR_NOTIFICATIONS_BUTTON));
clearButton.setToolTipText(Messages.MBEANS_TAB_CLEAR_NOTIFICATIONS_BUTTON_TOOLTIP);
clearButton.addActionListener(this);
// create the subscribe button
subscribeButton = new JButton(Messages.MBEANS_TAB_SUBSCRIBE_NOTIFICATIONS_BUTTON);
subscribeButton.setMnemonic(Resources.getMnemonicInt(Messages.MBEANS_TAB_SUBSCRIBE_NOTIFICATIONS_BUTTON));
subscribeButton.setToolTipText(Messages.MBEANS_TAB_SUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP);
subscribeButton.addActionListener(this);
// create the unsubscribe button
unsubscribeButton = new JButton(Messages.MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON);
unsubscribeButton.setMnemonic(Resources.getMnemonicInt(Messages.MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON));
unsubscribeButton.setToolTipText(Messages.MBEANS_TAB_UNSUBSCRIBE_NOTIFICATIONS_BUTTON_TOOLTIP);
unsubscribeButton.addActionListener(this);
// create XMBeanAttributes container
mbeanAttributes = new XMBeanAttributes(mbeansTab);
// create XMBeanOperations container
mbeanOperations = new XMBeanOperations(mbeansTab);
mbeanOperations.addOperationsListener(this);
// create XMBeanNotifications container
mbeanNotifications = new XMBeanNotifications();
mbeanNotifications.addNotificationsListener(this);
// create XMBeanInfo container
mbeanInfo = new XMBeanInfo();
}
private boolean isSelectedNode(DefaultMutableTreeNode n, DefaultMutableTreeNode cn) {
return (cn == n);
}
// Call on EDT
private void showErrorDialog(Object message, String title) {
new ThreadDialog(this, message, title, JOptionPane.ERROR_MESSAGE).run();
}
public boolean isMBeanNode(DefaultMutableTreeNode node) {
Object userObject = node.getUserObject();
if (userObject instanceof XNodeInfo) {
XNodeInfo uo = (XNodeInfo) userObject;
return uo.getType().equals(Type.MBEAN);
}
return false;
}
// Call on EDT
public synchronized void displayNode(DefaultMutableTreeNode node) {
clear();
displayEmptyNode();
if (node == null) {
return;
}
currentNode = node;
Object userObject = node.getUserObject();
if (userObject instanceof XNodeInfo) {
XNodeInfo uo = (XNodeInfo) userObject;
switch (uo.getType()) {
case MBEAN:
displayMBeanNode(node);
break;
case NONMBEAN:
displayEmptyNode();
break;
case ATTRIBUTES:
displayMBeanAttributesNode(node);
break;
case OPERATIONS:
displayMBeanOperationsNode(node);
break;
case NOTIFICATIONS:
displayMBeanNotificationsNode(node);
break;
case ATTRIBUTE:
case OPERATION:
case NOTIFICATION:
displayMetadataNode(node);
break;
default:
displayEmptyNode();
break;
}
} else {
displayEmptyNode();
}
}
// Call on EDT
private void displayMBeanNode(final DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
if (!uo.getType().equals(Type.MBEAN)) {
return;
}
mbean = (XMBean) uo.getData();
SwingWorker<MBeanInfo, Void> sw = new SwingWorker<MBeanInfo, Void>() {
@Override
public MBeanInfo doInBackground() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
return mbean.getMBeanInfo();
}
@Override
protected void done() {
try {
MBeanInfo mbi = get();
if (mbi != null) {
if (!isSelectedNode(node, currentNode)) {
return;
}
mbeanInfo.addMBeanInfo(mbean, mbi);
invalidate();
mainPanel.removeAll();
mainPanel.add(mbeanInfo, BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Couldn't get MBeanInfo for MBean [" +
mbean.getObjectName() + "]");
t.printStackTrace();
}
showErrorDialog(t.toString(),
Messages.PROBLEM_DISPLAYING_MBEAN);
}
}
};
sw.execute();
}
// Call on EDT
private void displayMetadataNode(final DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
final XMBeanInfo mbi = mbeanInfo;
switch (uo.getType()) {
case ATTRIBUTE:
SwingWorker<MBeanAttributeInfo, Void> sw =
new SwingWorker<MBeanAttributeInfo, Void>() {
@Override
public MBeanAttributeInfo doInBackground() {
Object attrData = uo.getData();
mbean = (XMBean) ((Object[]) attrData)[0];
MBeanAttributeInfo mbai =
(MBeanAttributeInfo) ((Object[]) attrData)[1];
mbeanAttributes.loadAttributes(mbean, new MBeanInfo(
null, null, new MBeanAttributeInfo[]{mbai},
null, null, null));
return mbai;
}
@Override
protected void done() {
try {
MBeanAttributeInfo mbai = get();
if (!isSelectedNode(node, currentNode)) {
return;
}
invalidate();
mainPanel.removeAll();
JPanel attributePanel =
new JPanel(new BorderLayout());
JPanel attributeBorderPanel =
new JPanel(new BorderLayout());
attributeBorderPanel.setBorder(
BorderFactory.createTitledBorder(
Messages.ATTRIBUTE_VALUE));
JPanel attributeValuePanel =
new JPanel(new BorderLayout());
attributeValuePanel.setBorder(
LineBorder.createGrayLineBorder());
attributeValuePanel.add(mbeanAttributes.getTableHeader(),
BorderLayout.PAGE_START);
attributeValuePanel.add(mbeanAttributes,
BorderLayout.CENTER);
attributeBorderPanel.add(attributeValuePanel,
BorderLayout.CENTER);
JPanel refreshButtonPanel = new JPanel();
refreshButtonPanel.add(refreshButton);
attributeBorderPanel.add(refreshButtonPanel,
BorderLayout.SOUTH);
refreshButton.setEnabled(true);
attributePanel.add(attributeBorderPanel,
BorderLayout.NORTH);
mbi.addMBeanAttributeInfo(mbai);
attributePanel.add(mbi, BorderLayout.CENTER);
mainPanel.add(attributePanel,
BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem displaying MBean " +
"attribute for MBean [" +
mbean.getObjectName() + "]");
t.printStackTrace();
}
showErrorDialog(t.toString(),
Messages.PROBLEM_DISPLAYING_MBEAN);
}
}
};
sw.execute();
break;
case OPERATION:
Object operData = uo.getData();
mbean = (XMBean) ((Object[]) operData)[0];
MBeanOperationInfo mboi =
(MBeanOperationInfo) ((Object[]) operData)[1];
mbeanOperations.loadOperations(mbean,
new MBeanInfo(null, null, null, null,
new MBeanOperationInfo[]{mboi}, null));
invalidate();
mainPanel.removeAll();
JPanel operationPanel = new JPanel(new BorderLayout());
JPanel operationBorderPanel = new JPanel(new BorderLayout());
operationBorderPanel.setBorder(BorderFactory.createTitledBorder(
Messages.OPERATION_INVOCATION));
operationBorderPanel.add(new JScrollPane(mbeanOperations));
operationPanel.add(operationBorderPanel, BorderLayout.NORTH);
mbi.addMBeanOperationInfo(mboi);
operationPanel.add(mbi, BorderLayout.CENTER);
mainPanel.add(operationPanel, BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
break;
case NOTIFICATION:
Object notifData = uo.getData();
invalidate();
mainPanel.removeAll();
mbi.addMBeanNotificationInfo((MBeanNotificationInfo) notifData);
mainPanel.add(mbi, BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
break;
}
}
// Call on EDT
private void displayMBeanAttributesNode(final DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
if (!uo.getType().equals(Type.ATTRIBUTES)) {
return;
}
mbean = (XMBean) uo.getData();
final XMBean xmb = mbean;
SwingWorker<MBeanInfo,Void> sw = new SwingWorker<MBeanInfo,Void>() {
@Override
public MBeanInfo doInBackground() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
MBeanInfo mbi = xmb.getMBeanInfo();
return mbi;
}
@Override
protected void done() {
try {
MBeanInfo mbi = get();
if (mbi != null && mbi.getAttributes() != null &&
mbi.getAttributes().length > 0) {
mbeanAttributes.loadAttributes(xmb, mbi);
if (!isSelectedNode(node, currentNode)) {
return;
}
invalidate();
mainPanel.removeAll();
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.setBorder(BorderFactory.createTitledBorder(
Messages.ATTRIBUTE_VALUES));
borderPanel.add(new JScrollPane(mbeanAttributes));
mainPanel.add(borderPanel, BorderLayout.CENTER);
// add the refresh button to the south panel
southPanel.removeAll();
southPanel.add(refreshButton, BorderLayout.SOUTH);
southPanel.setVisible(true);
refreshButton.setEnabled(true);
validate();
repaint();
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem displaying MBean " +
"attributes for MBean [" +
mbean.getObjectName() + "]");
t.printStackTrace();
}
showErrorDialog(t.toString(),
Messages.PROBLEM_DISPLAYING_MBEAN);
}
}
};
sw.execute();
}
// Call on EDT
private void displayMBeanOperationsNode(final DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
if (!uo.getType().equals(Type.OPERATIONS)) {
return;
}
mbean = (XMBean) uo.getData();
SwingWorker<MBeanInfo, Void> sw = new SwingWorker<MBeanInfo, Void>() {
@Override
public MBeanInfo doInBackground() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
return mbean.getMBeanInfo();
}
@Override
protected void done() {
try {
MBeanInfo mbi = get();
if (mbi != null) {
if (!isSelectedNode(node, currentNode)) {
return;
}
mbeanOperations.loadOperations(mbean, mbi);
invalidate();
mainPanel.removeAll();
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.setBorder(BorderFactory.createTitledBorder(
Messages.OPERATION_INVOCATION));
borderPanel.add(new JScrollPane(mbeanOperations));
mainPanel.add(borderPanel, BorderLayout.CENTER);
southPanel.setVisible(false);
southPanel.removeAll();
validate();
repaint();
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem displaying MBean " +
"operations for MBean [" +
mbean.getObjectName() + "]");
t.printStackTrace();
}
showErrorDialog(t.toString(),
Messages.PROBLEM_DISPLAYING_MBEAN);
}
}
};
sw.execute();
}
// Call on EDT
private void displayMBeanNotificationsNode(DefaultMutableTreeNode node) {
final XNodeInfo uo = (XNodeInfo) node.getUserObject();
if (!uo.getType().equals(Type.NOTIFICATIONS)) {
return;
}
mbean = (XMBean) uo.getData();
mbeanNotifications.loadNotifications(mbean);
updateNotifications();
invalidate();
mainPanel.removeAll();
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.setBorder(BorderFactory.createTitledBorder(
Messages.NOTIFICATION_BUFFER));
borderPanel.add(new JScrollPane(mbeanNotifications));
mainPanel.add(borderPanel, BorderLayout.CENTER);
// add the subscribe/unsubscribe/clear buttons to the south panel
southPanel.removeAll();
southPanel.add(subscribeButton, BorderLayout.WEST);
southPanel.add(unsubscribeButton, BorderLayout.CENTER);
southPanel.add(clearButton, BorderLayout.EAST);
southPanel.setVisible(true);
subscribeButton.setEnabled(true);
unsubscribeButton.setEnabled(true);
clearButton.setEnabled(true);
validate();
repaint();
}
// Call on EDT
private void displayEmptyNode() {
invalidate();
mainPanel.removeAll();
southPanel.removeAll();
validate();
repaint();
}
/**
* Subscribe button action.
*/
private void registerListener() {
new SwingWorker<Void, Void>() {
@Override
public Void doInBackground()
throws InstanceNotFoundException, IOException {
mbeanNotifications.registerListener(currentNode);
return null;
}
@Override
protected void done() {
try {
get();
updateNotifications();
validate();
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem adding listener");
t.printStackTrace();
}
showErrorDialog(t.getMessage(),
Messages.PROBLEM_ADDING_LISTENER);
}
}
}.execute();
}
/**
* Unsubscribe button action.
*/
private void unregisterListener() {
new SwingWorker<Boolean, Void>() {
@Override
public Boolean doInBackground() {
return mbeanNotifications.unregisterListener(currentNode);
}
@Override
protected void done() {
try {
if (get()) {
updateNotifications();
validate();
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
System.err.println("Problem removing listener");
t.printStackTrace();
}
showErrorDialog(t.getMessage(),
Messages.PROBLEM_REMOVING_LISTENER);
}
}
}.execute();
}
/**
* Refresh button action.
*/
private void refreshAttributes() {
mbeanAttributes.refreshAttributes();
}
// Call on EDT
private void updateNotifications() {
if (mbeanNotifications.isListenerRegistered(mbean)) {
long received = mbeanNotifications.getReceivedNotifications(mbean);
updateReceivedNotifications(currentNode, received, false);
} else {
clearNotifications();
}
}
/**
* Update notification node label in MBean tree: "Notifications[received]".
*/
// Call on EDT
private void updateReceivedNotifications(
DefaultMutableTreeNode emitter, long received, boolean bold) {
String text = Messages.NOTIFICATIONS + "[" + received + "]";
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) mbeansTab.getTree().getLastSelectedPathComponent();
if (bold && emitter != selectedNode) {
text = "<html><b>" + text + "</b></html>";
}
updateNotificationsNodeLabel(emitter, text);
}
/**
* Update notification node label in MBean tree: "Notifications".
*/
// Call on EDT
private void clearNotifications() {
updateNotificationsNodeLabel(currentNode,
Messages.NOTIFICATIONS);
}
/**
* Update notification node label in MBean tree: "Notifications[0]".
*/
// Call on EDT
private void clearNotifications0() {
updateNotificationsNodeLabel(currentNode,
Messages.NOTIFICATIONS + "[0]");
}
/**
* Update the label of the supplied MBean tree node.
*/
// Call on EDT
private void updateNotificationsNodeLabel(
DefaultMutableTreeNode node, String label) {
synchronized (mbeansTab.getTree()) {
invalidate();
XNodeInfo oldUserObject = (XNodeInfo) node.getUserObject();
XNodeInfo newUserObject = new XNodeInfo(
oldUserObject.getType(), oldUserObject.getData(),
label, oldUserObject.getToolTipText());
node.setUserObject(newUserObject);
DefaultTreeModel model =
(DefaultTreeModel) mbeansTab.getTree().getModel();
model.nodeChanged(node);
validate();
repaint();
}
}
/**
* Clear button action.
*/
// Call on EDT
private void clearCurrentNotifications() {
mbeanNotifications.clearCurrentNotifications();
if (mbeanNotifications.isListenerRegistered(mbean)) {
// Update notifs in MBean tree "Notifications[0]".
//
// Notification buffer has been cleared with a listener been
// registered so add "[0]" at the end of the node label.
//
clearNotifications0();
} else {
// Update notifs in MBean tree "Notifications".
//
// Notification buffer has been cleared without a listener been
// registered so don't add "[0]" at the end of the node label.
//
clearNotifications();
}
}
// Call on EDT
private void clear() {
mbeanAttributes.stopCellEditing();
mbeanAttributes.emptyTable();
mbeanAttributes.removeAttributes();
mbeanOperations.removeOperations();
mbeanNotifications.stopCellEditing();
mbeanNotifications.emptyTable();
mbeanNotifications.disableNotifications();
mbean = null;
currentNode = null;
}
/**
* Notification listener: handles asynchronous reception
* of MBean operation results and MBean notifications.
*/
// Call on EDT
public void handleNotification(Notification e, Object handback) {
// Operation result
if (e.getType().equals(XOperations.OPERATION_INVOCATION_EVENT)) {
final Object message;
if (handback == null) {
JTextArea textArea = new JTextArea("null");
textArea.setEditable(false);
textArea.setEnabled(true);
textArea.setRows(textArea.getLineCount());
message = textArea;
} else {
Component comp = mbeansTab.getDataViewer().
createOperationViewer(handback, mbean);
if (comp == null) {
JTextArea textArea = new JTextArea(handback.toString());
textArea.setEditable(false);
textArea.setEnabled(true);
textArea.setRows(textArea.getLineCount());
JScrollPane scrollPane = new JScrollPane(textArea);
Dimension d = scrollPane.getPreferredSize();
if (d.getWidth() > 400 || d.getHeight() > 250) {
scrollPane.setPreferredSize(new Dimension(400, 250));
}
message = scrollPane;
} else {
if (!(comp instanceof JScrollPane)) {
comp = new JScrollPane(comp);
}
Dimension d = comp.getPreferredSize();
if (d.getWidth() > 400 || d.getHeight() > 250) {
comp.setPreferredSize(new Dimension(400, 250));
}
message = comp;
}
}
new ThreadDialog(
(Component) e.getSource(),
message,
Messages.OPERATION_RETURN_VALUE,
JOptionPane.INFORMATION_MESSAGE).run();
} // Got notification
else if (e.getType().equals(
XMBeanNotifications.NOTIFICATION_RECEIVED_EVENT)) {
DefaultMutableTreeNode emitter = (DefaultMutableTreeNode) handback;
Long received = (Long) e.getUserData();
updateReceivedNotifications(emitter, received.longValue(), true);
}
}
/**
* Action listener: handles actions in panel buttons
*/
// Call on EDT
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JButton) {
JButton button = (JButton) e.getSource();
// Refresh button
if (button == refreshButton) {
refreshAttributes();
return;
}
// Clear button
if (button == clearButton) {
clearCurrentNotifications();
return;
}
// Subscribe button
if (button == subscribeButton) {
registerListener();
return;
}
// Unsubscribe button
if (button == unsubscribeButton) {
unregisterListener();
return;
}
}
}
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public abstract class XTable extends JTable {
static final int NAME_COLUMN = 0;
static final int VALUE_COLUMN = 1;
private Color defaultColor, editableColor, errorColor;
private Font normalFont, boldFont;
public XTable () {
super();
@SuppressWarnings("serial")
final TableSorter sorter = new TableSorter();
setModel(sorter);
sorter.addMouseListenerToHeaderInTable(this);
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
}
Color getDefaultColor() {
return defaultColor;
}
Color getEditableColor() {
return editableColor;
}
/**
* Called by TableSorter if a mouse event requests to sort the rows.
* @param column the column against which the rows are sorted
*/
void sortRequested(int column) {
// This is a hook for subclasses
}
/**
* This returns the select index as the table was at initialization
*/
public int getSelectedIndex() {
return convertRowToIndex(getSelectedRow());
}
/*
* Converts the row into index (before sorting)
*/
public int convertRowToIndex(int row) {
if (row == -1) return row;
if (getModel() instanceof TableSorter) {
return ((TableSorter) getModel()).getIndexOfRow(row);
} else {
return row;
}
}
public void emptyTable() {
DefaultTableModel model = (DefaultTableModel)getModel();
while (model.getRowCount()>0)
model.removeRow(0);
}
public abstract boolean isTableEditable();
public abstract boolean isColumnEditable(int column);
public abstract boolean isReadable(int row);
public abstract boolean isWritable(int row);
public abstract boolean isCellError(int row, int col);
public abstract boolean isAttributeViewable(int row, int col);
public abstract void setTableValue(Object value,int row);
public abstract Object getValue(int row);
public abstract String getClassName(int row);
public abstract String getValueName(int row);
public boolean isReadWrite(int row) {
return (isReadable(row) && isWritable(row));
}
//JTable re-implementation
//attribute can be editable even if unavailable
@Override
public boolean isCellEditable(int row, int col) {
return ((isTableEditable() && isColumnEditable(col)
&& isWritable(row)
&& Utils.isEditableType(getClassName(row))));
}
//attribute can be droppable even if unavailable
public boolean isCellDroppable(int row, int col) {
return (isTableEditable() && isColumnEditable(col)
&& isWritable(row));
}
//returns null, means no tool tip
public String getToolTip(int row, int column) {
return null;
}
/**
* This method sets read write rows to be blue, and other rows to be their
* default rendered colour.
*/
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
DefaultTableCellRenderer tcr =
(DefaultTableCellRenderer) super.getCellRenderer(row,column);
tcr.setToolTipText(getToolTip(row,column));
if (defaultColor == null) {
defaultColor = tcr.getForeground();
editableColor = Color.blue;
errorColor = Color.red;
// this sometimes happens for some reason
if (defaultColor == null) {
return tcr;
}
}
if (column != VALUE_COLUMN) {
tcr.setForeground(defaultColor);
return tcr;
}
if (isCellError(row,column)) {
tcr.setForeground(errorColor);
} else if (isCellEditable(row, column)) {
tcr.setForeground(editableColor);
} else {
tcr.setForeground(defaultColor);
}
return tcr;
}
@Override
public Component prepareRenderer(TableCellRenderer renderer,
int row, int column) {
Component comp = super.prepareRenderer(renderer, row, column);
if (normalFont == null) {
normalFont = comp.getFont();
boldFont = normalFont.deriveFont(Font.BOLD);
}
if (column == VALUE_COLUMN && isAttributeViewable(row, VALUE_COLUMN)) {
comp.setFont(boldFont);
} else {
comp.setFont(normalFont);
}
return comp;
}
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright (c) 2004, 2013, 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 sun.tools.jconsole.inspector;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.*;
/**
* This list implements the drag and drop functionality.
*/
@SuppressWarnings("serial")
public class XTextField extends JPanel
implements DocumentListener,
ActionListener {
private XObject selectedObject;
protected JTextField textField;
private static boolean allowNullSelection = false;
protected final static int COMPATIBLE_VALUE = 1;
protected final static int CURRENT_VALUE = 2;
protected final static int NULL_VALUE = 3;
private JButton button;
private XOperations operation;
//used in XTestFieldEditor
public XTextField() {
super(new BorderLayout());
add(textField = new JTextField(),BorderLayout.CENTER);
textField.addActionListener(this);
//
}
public XTextField(Object value) {
this(value,value.toString().length());
}
public XTextField(Object value, int colWidth) {
this(value,value.getClass(),colWidth, true, null, null);
}
public XTextField(Object value,
Class<?> expectedClass,
int colWidth,
boolean isCallable,
JButton button,
XOperations operation) {
super(new BorderLayout());
this.button = button;
this.operation = operation;
add(textField = new JTextField(value.toString(),colWidth),
BorderLayout.CENTER);
if(isCallable)
textField.addActionListener(this);
boolean fieldEditable = Utils.isEditableType(expectedClass.getName());
if (fieldEditable && isCallable) {
textField.setEditable(true);
}
else {
textField.setEditable(false);
}
}
public static void setNullSelectionAllowed(boolean allowNullSelection) {
XTextField.allowNullSelection = allowNullSelection;
}
public static boolean getNullSelectionAllowed() {
return allowNullSelection;
}
protected void init(Object value, Class<?> expectedClass) {
boolean fieldEditable = Utils.isEditableType(expectedClass.getName());
clearObject();
if (value != null) {
textField.setText(value.toString());
}
else {
//null String value for the moment
textField.setText("");
}
textField.setToolTipText(null);
if (fieldEditable) {
if (!textField.isEditable()) {
textField.setEditable(true);
}
}
else {
if (textField.isEditable()) {
textField.setEditable(false);
}
}
}
private synchronized void clearObject() {
textField.getDocument().removeDocumentListener(this);
selectedObject = null;
setDefaultColors();
}
private synchronized void setDefaultColors() {
// if (fore != null) textField.setForeground(fore);
// if (back != null) textField.setBackground(back);
}
public void setHorizontalAlignment(int h) {
textField.setHorizontalAlignment(h);
}
//can be overwritten
protected JMenuItem buildJMenuItem(XObject xobject, int valueType) {
if (valueType == COMPATIBLE_VALUE) {
return new JMenuItem(xobject.getText());
}
else if (valueType == CURRENT_VALUE) {
return new JMenuItem("> "+xobject.getText());
}
else if (valueType == NULL_VALUE) {
return new JMenuItem("null");
}
else {
return null;
}
}
// ACTIONLISTENER IMPLEMENTATION
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JTextField) {
if(operation != null)
operation.performInvokeRequest(button);
}
}
/**
* This method returns either the user inputted String, or an XObject
* if one was dropped on the input field.
*/
public Object getValue() {
if (selectedObject!=null) {
if (selectedObject == XObject.NULL_OBJECT) {
//null case
return null;
}
else {
return selectedObject;
}
}
else {
return textField.getText();
}
}
public void changedUpdate(DocumentEvent e) {
// the user typed something, so remove references
// to the object that was dropped.
clearObject();
}
public void removeUpdate(DocumentEvent e) {
// the user typed something, so remove references
// to the object that was dropped.
clearObject();
}
public void insertUpdate(DocumentEvent e) {
// the user typed something, so remove references
// to the object that was dropped.
clearObject();
}
}

View File

@@ -0,0 +1,156 @@
/*
* Copyright (c) 2004, 2008, 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 sun.tools.jconsole.inspector;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.EventObject;
import javax.swing.JMenuItem;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import javax.swing.table.TableCellEditor;
@SuppressWarnings("serial")
public class XTextFieldEditor extends XTextField implements TableCellEditor {
protected EventListenerList evtListenerList = new EventListenerList();
protected ChangeEvent changeEvent = new ChangeEvent(this);
private FocusListener editorFocusListener = new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
// fireEditingStopped();
// must not call fireEditingStopped() here!
}
};
public XTextFieldEditor() {
super();
textField.addFocusListener(editorFocusListener);
}
//edition stopped ou JMenuItem selection & JTextField selection
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if ((e.getSource() instanceof JMenuItem) ||
(e.getSource() instanceof JTextField)) {
fireEditingStopped();
}
}
//edition stopped on drag & drop success
protected void dropSuccess() {
fireEditingStopped();
}
//TableCellEditor implementation
public void addCellEditorListener(CellEditorListener listener) {
evtListenerList.add(CellEditorListener.class,listener);
}
public void removeCellEditorListener(CellEditorListener listener) {
evtListenerList.remove(CellEditorListener.class, listener);
}
protected void fireEditingStopped() {
CellEditorListener listener;
Object[] listeners = evtListenerList.getListenerList();
for (int i=0;i< listeners.length;i++) {
if (listeners[i] == CellEditorListener.class) {
listener = (CellEditorListener) listeners[i+1];
listener.editingStopped(changeEvent);
}
}
}
protected void fireEditingCanceled() {
CellEditorListener listener;
Object[] listeners = evtListenerList.getListenerList();
for (int i=0;i< listeners.length;i++) {
if (listeners[i] == CellEditorListener.class) {
listener = (CellEditorListener) listeners[i+1];
listener.editingCanceled(changeEvent);
}
}
}
public void cancelCellEditing() {
fireEditingCanceled();
}
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
public boolean isCellEditable(EventObject event) {
return true;
}
public boolean shouldSelectCell(EventObject event) {
return true;
}
public Object getCellEditorValue() {
Object object = getValue();
if (object instanceof XObject) {
return ((XObject) object).getObject();
}
else {
return object;
}
}
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean isSelected,
int row,
int column) {
String className;
if (table instanceof XTable) {
XTable mytable = (XTable) table;
className = mytable.getClassName(row);
} else {
className = String.class.getName();
}
try {
init(value,Utils.getClass(className));
}
catch(Exception e) {}
return this;
}
}

View File

@@ -0,0 +1,834 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import java.io.IOException;
import java.util.*;
import javax.management.*;
import javax.swing.*;
import javax.swing.tree.*;
import sun.tools.jconsole.JConsole;
import sun.tools.jconsole.MBeansTab;
import sun.tools.jconsole.Messages;
import sun.tools.jconsole.inspector.XNodeInfo;
import static sun.tools.jconsole.inspector.XNodeInfo.Type;
@SuppressWarnings("serial")
public class XTree extends JTree {
private static final List<String> orderedKeyPropertyList =
new ArrayList<String>();
static {
String keyPropertyList =
System.getProperty("com.sun.tools.jconsole.mbeans.keyPropertyList");
if (keyPropertyList == null) {
orderedKeyPropertyList.add("type");
orderedKeyPropertyList.add("j2eeType");
} else {
StringTokenizer st = new StringTokenizer(keyPropertyList, ",");
while (st.hasMoreTokens()) {
orderedKeyPropertyList.add(st.nextToken());
}
}
}
private MBeansTab mbeansTab;
private Map<String, DefaultMutableTreeNode> nodes =
new HashMap<String, DefaultMutableTreeNode>();
public XTree(MBeansTab mbeansTab) {
this(new DefaultMutableTreeNode("MBeanTreeRootNode"), mbeansTab);
}
public XTree(TreeNode root, MBeansTab mbeansTab) {
super(root, true);
this.mbeansTab = mbeansTab;
setRootVisible(false);
setShowsRootHandles(true);
ToolTipManager.sharedInstance().registerComponent(this);
}
/**
* This method removes the node from its parent
*/
// Call on EDT
private synchronized void removeChildNode(DefaultMutableTreeNode child) {
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.removeNodeFromParent(child);
}
/**
* This method adds the child to the specified parent node
* at specific index.
*/
// Call on EDT
private synchronized void addChildNode(
DefaultMutableTreeNode parent,
DefaultMutableTreeNode child,
int index) {
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.insertNodeInto(child, parent, index);
}
/**
* This method adds the child to the specified parent node.
* The index where the child is to be added depends on the
* child node being Comparable or not. If the child node is
* not Comparable then it is added at the end, i.e. right
* after the current parent's children.
*/
// Call on EDT
private synchronized void addChildNode(
DefaultMutableTreeNode parent, DefaultMutableTreeNode child) {
int childCount = parent.getChildCount();
if (childCount == 0) {
addChildNode(parent, child, 0);
return;
}
if (child instanceof ComparableDefaultMutableTreeNode) {
ComparableDefaultMutableTreeNode comparableChild =
(ComparableDefaultMutableTreeNode) child;
for (int i = childCount - 1; i >= 0; i--) {
DefaultMutableTreeNode brother =
(DefaultMutableTreeNode) parent.getChildAt(i);
// expr1: child node must be inserted after metadata nodes
// - OR -
// expr2: "child >= brother"
if ((i <= 2 && isMetadataNode(brother)) ||
comparableChild.compareTo(brother) >= 0) {
addChildNode(parent, child, i + 1);
return;
}
}
// "child < all brothers", add at the beginning
addChildNode(parent, child, 0);
return;
}
// "child not comparable", add at the end
addChildNode(parent, child, childCount);
}
/**
* This method removes all the displayed nodes from the tree,
* but does not affect actual MBeanServer contents.
*/
// Call on EDT
@Override
public synchronized void removeAll() {
DefaultTreeModel model = (DefaultTreeModel) getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
root.removeAllChildren();
model.nodeStructureChanged(root);
nodes.clear();
}
// Call on EDT
public synchronized void removeMBeanFromView(ObjectName mbean) {
// We assume here that MBeans are removed one by one (on MBean
// unregistered notification). Deletes the tree node associated
// with the given MBean and recursively all the node parents
// which are leaves and non XMBean.
//
DefaultMutableTreeNode node = null;
Dn dn = new Dn(mbean);
if (dn.getTokenCount() > 0) {
DefaultTreeModel model = (DefaultTreeModel) getModel();
Token token = dn.getToken(0);
String hashKey = dn.getHashKey(token);
node = nodes.get(hashKey);
if ((node != null) && (!node.isRoot())) {
if (hasNonMetadataNodes(node)) {
removeMetadataNodes(node);
String label = token.getValue();
XNodeInfo userObject = new XNodeInfo(
Type.NONMBEAN, label,
label, token.getTokenValue());
changeNodeValue(node, userObject);
} else {
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode) node.getParent();
model.removeNodeFromParent(node);
nodes.remove(hashKey);
removeParentFromView(dn, 1, parent);
}
}
}
}
/**
* Returns true if any of the children nodes is a non MBean metadata node.
*/
private boolean hasNonMetadataNodes(DefaultMutableTreeNode node) {
for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
Object uo = n.getUserObject();
if (uo instanceof XNodeInfo) {
switch (((XNodeInfo) uo).getType()) {
case ATTRIBUTES:
case NOTIFICATIONS:
case OPERATIONS:
break;
default:
return true;
}
} else {
return true;
}
}
return false;
}
/**
* Returns true if any of the children nodes is an MBean metadata node.
*/
public boolean hasMetadataNodes(DefaultMutableTreeNode node) {
for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
Object uo = n.getUserObject();
if (uo instanceof XNodeInfo) {
switch (((XNodeInfo) uo).getType()) {
case ATTRIBUTES:
case NOTIFICATIONS:
case OPERATIONS:
return true;
default:
break;
}
} else {
return false;
}
}
return false;
}
/**
* Returns true if the given node is an MBean metadata node.
*/
public boolean isMetadataNode(DefaultMutableTreeNode node) {
Object uo = node.getUserObject();
if (uo instanceof XNodeInfo) {
switch (((XNodeInfo) uo).getType()) {
case ATTRIBUTES:
case NOTIFICATIONS:
case OPERATIONS:
return true;
default:
return false;
}
} else {
return false;
}
}
/**
* Remove the metadata nodes associated with a given MBean node.
*/
// Call on EDT
private void removeMetadataNodes(DefaultMutableTreeNode node) {
Set<DefaultMutableTreeNode> metadataNodes =
new HashSet<DefaultMutableTreeNode>();
DefaultTreeModel model = (DefaultTreeModel) getModel();
for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();
Object uo = n.getUserObject();
if (uo instanceof XNodeInfo) {
switch (((XNodeInfo) uo).getType()) {
case ATTRIBUTES:
case NOTIFICATIONS:
case OPERATIONS:
metadataNodes.add(n);
break;
default:
break;
}
}
}
for (DefaultMutableTreeNode n : metadataNodes) {
model.removeNodeFromParent(n);
}
}
/**
* Removes only the parent nodes which are non MBean and leaf.
* This method assumes the child nodes have been removed before.
*/
// Call on EDT
private DefaultMutableTreeNode removeParentFromView(
Dn dn, int index, DefaultMutableTreeNode node) {
if ((!node.isRoot()) && node.isLeaf() &&
(!(((XNodeInfo) node.getUserObject()).getType().equals(Type.MBEAN)))) {
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode) node.getParent();
removeChildNode(node);
String hashKey = dn.getHashKey(dn.getToken(index));
nodes.remove(hashKey);
removeParentFromView(dn, index + 1, parent);
}
return node;
}
// Call on EDT
public synchronized void addMBeansToView(Set<ObjectName> mbeans) {
Set<Dn> dns = new TreeSet<Dn>();
for (ObjectName mbean : mbeans) {
Dn dn = new Dn(mbean);
dns.add(dn);
}
for (Dn dn : dns) {
ObjectName mbean = dn.getObjectName();
XMBean xmbean = new XMBean(mbean, mbeansTab);
addMBeanToView(mbean, xmbean, dn);
}
}
// Call on EDT
public synchronized void addMBeanToView(ObjectName mbean) {
// Build XMBean for the given MBean
//
XMBean xmbean = new XMBean(mbean, mbeansTab);
// Build Dn for the given MBean
//
Dn dn = new Dn(mbean);
// Add the new nodes to the MBean tree from leaf to root
//
addMBeanToView(mbean, xmbean, dn);
}
// Call on EDT
private synchronized void addMBeanToView(
ObjectName mbean, XMBean xmbean, Dn dn) {
DefaultMutableTreeNode childNode = null;
DefaultMutableTreeNode parentNode = null;
// Add the node or replace its user object if already added
//
Token token = dn.getToken(0);
String hashKey = dn.getHashKey(token);
if (nodes.containsKey(hashKey)) {
// Found existing node previously created when adding another node
//
childNode = nodes.get(hashKey);
// Replace user object to reflect that this node is an MBean
//
Object data = createNodeValue(xmbean, token);
String label = data.toString();
XNodeInfo userObject =
new XNodeInfo(Type.MBEAN, data, label, mbean.toString());
changeNodeValue(childNode, userObject);
return;
}
// Create new leaf node
//
childNode = createDnNode(dn, token, xmbean);
nodes.put(hashKey, childNode);
// Add intermediate non MBean nodes
//
for (int i = 1; i < dn.getTokenCount(); i++) {
token = dn.getToken(i);
hashKey = dn.getHashKey(token);
if (nodes.containsKey(hashKey)) {
// Intermediate node already present, add new node as child
//
parentNode = nodes.get(hashKey);
addChildNode(parentNode, childNode);
return;
} else {
// Create new intermediate node
//
if ("domain".equals(token.getTokenType())) {
parentNode = createDomainNode(dn, token);
DefaultMutableTreeNode root =
(DefaultMutableTreeNode) getModel().getRoot();
addChildNode(root, parentNode);
} else {
parentNode = createSubDnNode(dn, token);
}
nodes.put(hashKey, parentNode);
addChildNode(parentNode, childNode);
}
childNode = parentNode;
}
}
// Call on EDT
private synchronized void changeNodeValue(
DefaultMutableTreeNode node, XNodeInfo nodeValue) {
if (node instanceof ComparableDefaultMutableTreeNode) {
// should it stay at the same place?
DefaultMutableTreeNode clone =
(DefaultMutableTreeNode) node.clone();
clone.setUserObject(nodeValue);
if (((ComparableDefaultMutableTreeNode) node).compareTo(clone) == 0) {
// the order in the tree didn't change
node.setUserObject(nodeValue);
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.nodeChanged(node);
} else {
// delete the node and re-order it in case the
// node value modifies the order in the tree
DefaultMutableTreeNode parent =
(DefaultMutableTreeNode) node.getParent();
removeChildNode(node);
node.setUserObject(nodeValue);
addChildNode(parent, node);
}
} else {
// not comparable stays at the same place
node.setUserObject(nodeValue);
DefaultTreeModel model = (DefaultTreeModel) getModel();
model.nodeChanged(node);
}
// Load the MBean metadata if type is MBEAN
if (nodeValue.getType().equals(Type.MBEAN)) {
removeMetadataNodes(node);
TreeNode[] treeNodes = node.getPath();
TreePath path = new TreePath(treeNodes);
if (isExpanded(path)) {
addMetadataNodes(node);
}
}
// Clear the current selection and set it
// again so valueChanged() gets called
if (node == getLastSelectedPathComponent()) {
TreePath selectionPath = getSelectionPath();
clearSelection();
setSelectionPath(selectionPath);
}
}
/**
* Creates the domain node.
*/
private DefaultMutableTreeNode createDomainNode(Dn dn, Token token) {
DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();
String label = dn.getDomain();
XNodeInfo userObject =
new XNodeInfo(Type.NONMBEAN, label, label, label);
node.setUserObject(userObject);
return node;
}
/**
* Creates the node corresponding to the whole Dn, i.e. an MBean.
*/
private DefaultMutableTreeNode createDnNode(
Dn dn, Token token, XMBean xmbean) {
DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();
Object data = createNodeValue(xmbean, token);
String label = data.toString();
XNodeInfo userObject = new XNodeInfo(Type.MBEAN, data, label,
xmbean.getObjectName().toString());
node.setUserObject(userObject);
return node;
}
/**
* Creates the node corresponding to a subDn, i.e. a non-MBean
* intermediate node.
*/
private DefaultMutableTreeNode createSubDnNode(Dn dn, Token token) {
DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();
String label = isKeyValueView() ? token.getTokenValue() : token.getValue();
XNodeInfo userObject =
new XNodeInfo(Type.NONMBEAN, label, label, token.getTokenValue());
node.setUserObject(userObject);
return node;
}
private Object createNodeValue(XMBean xmbean, Token token) {
String label = isKeyValueView() ? token.getTokenValue() : token.getValue();
xmbean.setText(label);
return xmbean;
}
/**
* Parses the MBean ObjectName comma-separated properties string and puts
* the individual key/value pairs into the map. Key order in the properties
* string is preserved by the map.
*/
private static Map<String, String> extractKeyValuePairs(
String props, ObjectName mbean) {
Map<String, String> map = new LinkedHashMap<String, String>();
int eq = props.indexOf("=");
while (eq != -1) {
String key = props.substring(0, eq);
String value = mbean.getKeyProperty(key);
map.put(key, value);
props = props.substring(key.length() + 1 + value.length());
if (props.startsWith(",")) {
props = props.substring(1);
}
eq = props.indexOf("=");
}
return map;
}
/**
* Returns the ordered key property list that will be used to build the
* MBean tree. If the "com.sun.tools.jconsole.mbeans.keyPropertyList" system
* property is not specified, then the ordered key property list used
* to build the MBean tree will be the one returned by the method
* ObjectName.getKeyPropertyListString() with "type" as first key,
* and "j2eeType" as second key, if present. If any of the keys specified
* in the comma-separated key property list does not apply to the given
* MBean then it will be discarded.
*/
private static String getKeyPropertyListString(ObjectName mbean) {
String props = mbean.getKeyPropertyListString();
Map<String, String> map = extractKeyValuePairs(props, mbean);
StringBuilder sb = new StringBuilder();
// Add the key/value pairs to the buffer following the
// key order defined by the "orderedKeyPropertyList"
for (String key : orderedKeyPropertyList) {
if (map.containsKey(key)) {
sb.append(key + "=" + map.get(key) + ",");
map.remove(key);
}
}
// Add the remaining key/value pairs to the buffer
for (Map.Entry<String, String> entry : map.entrySet()) {
sb.append(entry.getKey() + "=" + entry.getValue() + ",");
}
String orderedKeyPropertyListString = sb.toString();
orderedKeyPropertyListString = orderedKeyPropertyListString.substring(
0, orderedKeyPropertyListString.length() - 1);
return orderedKeyPropertyListString;
}
// Call on EDT
public void addMetadataNodes(DefaultMutableTreeNode node) {
XMBean mbean = (XMBean) ((XNodeInfo) node.getUserObject()).getData();
DefaultTreeModel model = (DefaultTreeModel) getModel();
MBeanInfoNodesSwingWorker sw =
new MBeanInfoNodesSwingWorker(model, node, mbean);
if (sw != null) {
sw.execute();
}
}
private static class MBeanInfoNodesSwingWorker
extends SwingWorker<Object[], Void> {
private final DefaultTreeModel model;
private final DefaultMutableTreeNode node;
private final XMBean mbean;
public MBeanInfoNodesSwingWorker(
DefaultTreeModel model,
DefaultMutableTreeNode node,
XMBean mbean) {
this.model = model;
this.node = node;
this.mbean = mbean;
}
@Override
public Object[] doInBackground() throws InstanceNotFoundException,
IntrospectionException, ReflectionException, IOException {
Object result[] = new Object[2];
// Retrieve MBeanInfo for this MBean
result[0] = mbean.getMBeanInfo();
// Check if this MBean is a notification emitter
result[1] = mbean.isBroadcaster();
return result;
}
@Override
protected void done() {
try {
Object result[] = get();
MBeanInfo mbeanInfo = (MBeanInfo) result[0];
Boolean isBroadcaster = (Boolean) result[1];
if (mbeanInfo != null) {
addMBeanInfoNodes(model, node, mbean, mbeanInfo, isBroadcaster);
}
} catch (Exception e) {
Throwable t = Utils.getActualException(e);
if (JConsole.isDebug()) {
t.printStackTrace();
}
}
}
// Call on EDT
private void addMBeanInfoNodes(
DefaultTreeModel tree, DefaultMutableTreeNode node,
XMBean mbean, MBeanInfo mbeanInfo, Boolean isBroadcaster) {
MBeanAttributeInfo[] ai = mbeanInfo.getAttributes();
MBeanOperationInfo[] oi = mbeanInfo.getOperations();
MBeanNotificationInfo[] ni = mbeanInfo.getNotifications();
// Insert the Attributes/Operations/Notifications metadata nodes as
// the three first children of this MBean node. This is only useful
// when this MBean node denotes an MBean but it's not a leaf in the
// MBean tree
//
int childIndex = 0;
// MBeanAttributeInfo node
//
if (ai != null && ai.length > 0) {
DefaultMutableTreeNode attributes = new DefaultMutableTreeNode();
XNodeInfo attributesUO = new XNodeInfo(Type.ATTRIBUTES, mbean,
Messages.ATTRIBUTES, null);
attributes.setUserObject(attributesUO);
node.insert(attributes, childIndex++);
for (MBeanAttributeInfo mbai : ai) {
DefaultMutableTreeNode attribute = new DefaultMutableTreeNode();
XNodeInfo attributeUO = new XNodeInfo(Type.ATTRIBUTE,
new Object[]{mbean, mbai}, mbai.getName(), null);
attribute.setUserObject(attributeUO);
attribute.setAllowsChildren(false);
attributes.add(attribute);
}
}
// MBeanOperationInfo node
//
if (oi != null && oi.length > 0) {
DefaultMutableTreeNode operations = new DefaultMutableTreeNode();
XNodeInfo operationsUO = new XNodeInfo(Type.OPERATIONS, mbean,
Messages.OPERATIONS, null);
operations.setUserObject(operationsUO);
node.insert(operations, childIndex++);
for (MBeanOperationInfo mboi : oi) {
// Compute the operation's tool tip text:
// "operationname(param1type,param2type,...)"
//
StringBuilder sb = new StringBuilder();
for (MBeanParameterInfo mbpi : mboi.getSignature()) {
sb.append(mbpi.getType() + ",");
}
String signature = sb.toString();
if (signature.length() > 0) {
// Remove the trailing ','
//
signature = signature.substring(0, signature.length() - 1);
}
String toolTipText = mboi.getName() + "(" + signature + ")";
// Create operation node
//
DefaultMutableTreeNode operation = new DefaultMutableTreeNode();
XNodeInfo operationUO = new XNodeInfo(Type.OPERATION,
new Object[]{mbean, mboi}, mboi.getName(), toolTipText);
operation.setUserObject(operationUO);
operation.setAllowsChildren(false);
operations.add(operation);
}
}
// MBeanNotificationInfo node
//
if (isBroadcaster != null && isBroadcaster.booleanValue()) {
DefaultMutableTreeNode notifications = new DefaultMutableTreeNode();
XNodeInfo notificationsUO = new XNodeInfo(Type.NOTIFICATIONS, mbean,
Messages.NOTIFICATIONS, null);
notifications.setUserObject(notificationsUO);
node.insert(notifications, childIndex++);
if (ni != null && ni.length > 0) {
for (MBeanNotificationInfo mbni : ni) {
DefaultMutableTreeNode notification =
new DefaultMutableTreeNode();
XNodeInfo notificationUO = new XNodeInfo(Type.NOTIFICATION,
mbni, mbni.getName(), null);
notification.setUserObject(notificationUO);
notification.setAllowsChildren(false);
notifications.add(notification);
}
}
}
// Update tree model
//
model.reload(node);
}
}
//
// Tree preferences
//
private static boolean treeView;
private static boolean treeViewInit = false;
private static boolean isTreeView() {
if (!treeViewInit) {
treeView = getTreeViewValue();
treeViewInit = true;
}
return treeView;
}
private static boolean getTreeViewValue() {
String tv = System.getProperty("treeView");
return ((tv == null) ? true : !(tv.equals("false")));
}
//
// MBean key-value preferences
//
private boolean keyValueView = Boolean.getBoolean("keyValueView");
private boolean isKeyValueView() {
return keyValueView;
}
//
// Utility classes
//
private static class ComparableDefaultMutableTreeNode
extends DefaultMutableTreeNode
implements Comparable<DefaultMutableTreeNode> {
public int compareTo(DefaultMutableTreeNode node) {
return (this.toString().compareTo(node.toString()));
}
}
private static class Dn implements Comparable<Dn> {
private ObjectName mbean;
private String domain;
private String keyPropertyList;
private String hashDn;
private List<Token> tokens = new ArrayList<Token>();
public Dn(ObjectName mbean) {
this.mbean = mbean;
this.domain = mbean.getDomain();
this.keyPropertyList = getKeyPropertyListString(mbean);
if (isTreeView()) {
// Tree view
Map<String, String> map =
extractKeyValuePairs(keyPropertyList, mbean);
for (Map.Entry<String, String> entry : map.entrySet()) {
tokens.add(new Token("key", entry.getKey() + "=" + entry.getValue()));
}
} else {
// Flat view
tokens.add(new Token("key", "properties=" + keyPropertyList));
}
// Add the domain as the first token in the Dn
tokens.add(0, new Token("domain", "domain=" + domain));
// Reverse the Dn (from leaf to root)
Collections.reverse(tokens);
// Compute hash for Dn
computeHashDn();
}
public ObjectName getObjectName() {
return mbean;
}
public String getDomain() {
return domain;
}
public String getKeyPropertyList() {
return keyPropertyList;
}
public Token getToken(int index) {
return tokens.get(index);
}
public int getTokenCount() {
return tokens.size();
}
public String getHashDn() {
return hashDn;
}
public String getHashKey(Token token) {
final int begin = hashDn.indexOf(token.getTokenValue());
return hashDn.substring(begin, hashDn.length());
}
private void computeHashDn() {
if (tokens.isEmpty()) {
return;
}
final StringBuilder hdn = new StringBuilder();
for (int i = 0; i < tokens.size(); i++) {
hdn.append(tokens.get(i).getTokenValue());
hdn.append(",");
}
hashDn = hdn.substring(0, hdn.length() - 1);
}
@Override
public String toString() {
return domain + ":" + keyPropertyList;
}
public int compareTo(Dn dn) {
return this.toString().compareTo(dn.toString());
}
}
private static class Token {
private String tokenType;
private String tokenValue;
private String key;
private String value;
public Token(String tokenType, String tokenValue) {
this.tokenType = tokenType;
this.tokenValue = tokenValue;
buildKeyValue();
}
public String getTokenType() {
return tokenType;
}
public String getTokenValue() {
return tokenValue;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
private void buildKeyValue() {
int index = tokenValue.indexOf("=");
if (index < 0) {
key = tokenValue;
value = tokenValue;
} else {
key = tokenValue.substring(0, index);
value = tokenValue.substring(index + 1, tokenValue.length());
}
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2004, 2012, 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 sun.tools.jconsole.inspector;
import java.awt.Component;
import javax.swing.ImageIcon;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
@SuppressWarnings("serial")
public class XTreeRenderer extends DefaultTreeCellRenderer {
public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(
tree, value, selected, expanded, leaf, row, hasFocus);
Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
if (userObject instanceof XNodeInfo) {
XNodeInfo node = (XNodeInfo) userObject;
setToolTipText(node.getToolTipText());
switch (node.getType()) {
case MBEAN:
XMBean xmbean = (XMBean) node.getData();
setIcon((ImageIcon) xmbean.getIcon());
break;
case NONMBEAN:
break;
case ATTRIBUTES:
case OPERATIONS:
case NOTIFICATIONS:
setIcon(null);
break;
case ATTRIBUTE:
case OPERATION:
case NOTIFICATION:
setIcon(null);
break;
}
} else {
setToolTipText(null);
}
return this;
}
}