org.graalvm.visualvm.modules.mbeans.XMBeanNotifications Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org-graalvm-visualvm-modules-mbeans Show documentation
Show all versions of org-graalvm-visualvm-modules-mbeans Show documentation
The MBeans plugin integrates JConsole's MBeans tab functionality into VisualVM.
/*
* Copyright (c) 2007, 2018, 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 org.graalvm.visualvm.modules.mbeans;
import javax.swing.*;
import javax.swing.event.*;
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 java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.*;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
class XMBeanNotifications extends JTable implements NotificationListener {
private final static String[] columnNames = {
Resources.getText("LBL_TimeStamp"), // NOI18N
Resources.getText("LBL_Type"), // NOI18N
Resources.getText("LBL_UserData"), // NOI18N
Resources.getText("LBL_SeqNum"), // NOI18N
Resources.getText("LBL_Message"), // NOI18N
Resources.getText("LBL_Event"), // NOI18N
Resources.getText("LBL_Source")}; // NOI18N
private final static Logger LOGGER = Logger.getLogger(XMBeanNotifications.class.getName());
private HashMap listeners =
new HashMap();
private volatile boolean subscribed;
private XMBeanNotificationsListener currentListener;
public final static String NOTIFICATION_RECEIVED_EVENT =
"jconsole.xnotification.received"; // NOI18N
private List 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"); // NOI18N
private static TableCellEditor editor =
new Utils.ReadOnlyTableCellEditor(new JTextField());
public XMBeanNotifications() {
super(new TableSorter(columnNames,0));
setColumnSelectionAllowed(false);
setRowSelectionAllowed(false);
getTableHeader().setReorderingAllowed(false);
ArrayList l =
new ArrayList(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 = Resources.getText("LBL_DoubleClickToExpandCollapse") + // NOI18N
". " + cell.toString(); // NOI18N
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) {
LOGGER.log(Level.SEVERE, "Error adding listener for delegate", e); // NOI18N
}
}
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) { // NOI18N
unregister(mbean);
}
}
} catch(Exception e) {
LOGGER.log(Level.SEVERE, "Error unregistering notification", e); // NOI18N
}
}
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