1 /* 2 * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.tools.jconsole.inspector; 27 28 import java.awt.BorderLayout; 29 import java.awt.Color; 30 import java.awt.Component; 31 import java.awt.GridLayout; 32 import java.util.*; 33 import javax.management.*; 34 import javax.swing.*; 35 import javax.swing.border.TitledBorder; 36 import javax.swing.event.*; 37 import javax.swing.table.*; 38 import javax.swing.tree.*; 39 import sun.tools.jconsole.JConsole; 40 import sun.tools.jconsole.Resources; 41 import sun.tools.jconsole.inspector.XNodeInfo.Type; 42 43 import static sun.tools.jconsole.Utilities.*; 44 45 @SuppressWarnings("serial") 46 public class XMBeanInfo extends JPanel { 47 48 private static final Color lightYellow = new Color(255, 255, 128); 49 50 private final int NAME_COLUMN = 0; 51 private final int VALUE_COLUMN = 1; 52 53 private final String[] columnNames = { 54 Resources.getText("Name"), 55 Resources.getText("Value") 56 }; 57 58 private JTable infoTable = new JTable(); 59 private JTable descTable = new JTable(); 60 private JPanel infoBorderPanel = new JPanel(new BorderLayout()); 61 private JPanel descBorderPanel = new JPanel(new BorderLayout()); 62 63 private static class ReadOnlyDefaultTableModel extends DefaultTableModel { 64 public void setValueAt(Object value, int row, int col) { 65 } 66 } 67 68 private static class TableRowDivider { 69 70 private String tableRowDividerText; 71 72 public TableRowDivider(String tableRowDividerText) { 73 this.tableRowDividerText = tableRowDividerText; 74 } 75 76 public String toString() { 77 return tableRowDividerText; 78 } 79 } 80 81 private static MBeanInfoTableCellRenderer renderer = 82 new MBeanInfoTableCellRenderer(); 83 84 private static class MBeanInfoTableCellRenderer 85 extends DefaultTableCellRenderer { 86 87 public Component getTableCellRendererComponent( 88 JTable table, Object value, boolean isSelected, 89 boolean hasFocus, int row, int column) { 90 Component comp = super.getTableCellRendererComponent( 91 table, value, isSelected, hasFocus, row, column); 92 if (value instanceof TableRowDivider) { 93 JLabel label = new JLabel(value.toString()); 94 label.setBackground(ensureContrast(lightYellow, 95 label.getForeground())); 96 label.setOpaque(true); 97 return label; 98 } 99 return comp; 100 } 101 } 102 103 private static TableCellEditor editor = 104 new MBeanInfoTableCellEditor(new JTextField()); 105 106 private static class MBeanInfoTableCellEditor 107 extends Utils.ReadOnlyTableCellEditor { 108 public MBeanInfoTableCellEditor(JTextField tf) { 109 super(tf); 110 } 111 public Component getTableCellEditorComponent( 112 JTable table, Object value, boolean isSelected, 113 int row, int column) { 114 Component comp = super.getTableCellEditorComponent( 115 table, value, isSelected, row, column); 116 if (value instanceof TableRowDivider) { 117 JLabel label = new JLabel(value.toString()); 118 label.setBackground(ensureContrast(lightYellow, 119 label.getForeground())); 120 label.setOpaque(true); 121 return label; 122 } 123 return comp; 124 } 125 } 126 127 public XMBeanInfo() { 128 // Use the grid layout to display the two tables 129 // 130 super(new GridLayout(2, 1)); 131 // MBean*Info table 132 // 133 infoTable.setModel(new ReadOnlyDefaultTableModel()); 134 infoTable.setRowSelectionAllowed(false); 135 infoTable.setColumnSelectionAllowed(false); 136 infoTable.getTableHeader().setReorderingAllowed(false); 137 ((DefaultTableModel) infoTable.getModel()).setColumnIdentifiers(columnNames); 138 infoTable.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(140); 139 infoTable.getColumnModel().getColumn(NAME_COLUMN).setMaxWidth(140); 140 infoTable.getColumnModel().getColumn(NAME_COLUMN).setCellRenderer(renderer); 141 infoTable.getColumnModel().getColumn(VALUE_COLUMN).setCellRenderer(renderer); 142 infoTable.getColumnModel().getColumn(NAME_COLUMN).setCellEditor(editor); 143 infoTable.getColumnModel().getColumn(VALUE_COLUMN).setCellEditor(editor); 144 infoTable.addKeyListener(new Utils.CopyKeyAdapter()); 145 infoTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); 146 JScrollPane infoTableScrollPane = new JScrollPane(infoTable); 147 infoBorderPanel.setBorder( 148 BorderFactory.createTitledBorder("MBeanInfoPlaceHolder")); 149 infoBorderPanel.add(infoTableScrollPane); 150 // Descriptor table 151 // 152 descTable.setModel(new ReadOnlyDefaultTableModel()); 153 descTable.setRowSelectionAllowed(false); 154 descTable.setColumnSelectionAllowed(false); 155 descTable.getTableHeader().setReorderingAllowed(false); 156 ((DefaultTableModel) descTable.getModel()).setColumnIdentifiers(columnNames); 157 descTable.getColumnModel().getColumn(NAME_COLUMN).setPreferredWidth(140); 158 descTable.getColumnModel().getColumn(NAME_COLUMN).setMaxWidth(140); 159 descTable.getColumnModel().getColumn(NAME_COLUMN).setCellRenderer(renderer); 160 descTable.getColumnModel().getColumn(VALUE_COLUMN).setCellRenderer(renderer); 161 descTable.getColumnModel().getColumn(NAME_COLUMN).setCellEditor(editor); 162 descTable.getColumnModel().getColumn(VALUE_COLUMN).setCellEditor(editor); 163 descTable.addKeyListener(new Utils.CopyKeyAdapter()); 164 descTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); 165 JScrollPane descTableScrollPane = new JScrollPane(descTable); 166 descBorderPanel.setBorder( 167 BorderFactory.createTitledBorder(Resources.getText("Descriptor"))); 168 descBorderPanel.add(descTableScrollPane); 169 // Add the two tables to the grid 170 // 171 add(infoBorderPanel); 172 add(descBorderPanel); 173 } 174 175 public void emptyInfoTable() { 176 DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); 177 while (tableModel.getRowCount() > 0) { 178 tableModel.removeRow(0); 179 } 180 } 181 182 public void emptyDescTable() { 183 DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel(); 184 while (tableModel.getRowCount() > 0) { 185 tableModel.removeRow(0); 186 } 187 } 188 189 private void addDescriptor(Descriptor desc, String text) { 190 if (desc != null && desc.getFieldNames().length > 0) { 191 DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel(); 192 Object rowData[] = new Object[2]; 193 rowData[0] = new TableRowDivider(text); 194 rowData[1] = new TableRowDivider(""); 195 tableModel.addRow(rowData); 196 for (String fieldName : desc.getFieldNames()) { 197 rowData[0] = fieldName; 198 Object fieldValue = desc.getFieldValue(fieldName); 199 if (fieldValue instanceof boolean[]) { 200 rowData[1] = Arrays.toString((boolean[]) fieldValue); 201 } else if (fieldValue instanceof byte[]) { 202 rowData[1] = Arrays.toString((byte[]) fieldValue); 203 } else if (fieldValue instanceof char[]) { 204 rowData[1] = Arrays.toString((char[]) fieldValue); 205 } else if (fieldValue instanceof double[]) { 206 rowData[1] = Arrays.toString((double[]) fieldValue); 207 } else if (fieldValue instanceof float[]) { 208 rowData[1] = Arrays.toString((float[]) fieldValue); 209 } else if (fieldValue instanceof int[]) { 210 rowData[1] = Arrays.toString((int[]) fieldValue); 211 } else if (fieldValue instanceof long[]) { 212 rowData[1] = Arrays.toString((long[]) fieldValue); 213 } else if (fieldValue instanceof short[]) { 214 rowData[1] = Arrays.toString((short[]) fieldValue); 215 } else if (fieldValue instanceof Object[]) { 216 rowData[1] = Arrays.toString((Object[]) fieldValue); 217 } else { 218 rowData[1] = fieldValue; 219 } 220 tableModel.addRow(rowData); 221 } 222 tableModel.newDataAvailable(new TableModelEvent(tableModel)); 223 } 224 } 225 226 public void addMBeanInfo(XMBean mbean, MBeanInfo mbeanInfo) { 227 emptyInfoTable(); 228 emptyDescTable(); 229 ((TitledBorder) infoBorderPanel.getBorder()).setTitle( 230 Resources.getText("MBeanInfo")); 231 String text = Resources.getText("Info") + ":"; 232 DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); 233 Object rowData[] = new Object[2]; 234 rowData[0] = new TableRowDivider(text); 235 rowData[1] = new TableRowDivider(""); 236 tableModel.addRow(rowData); 237 rowData[0] = Resources.getText("ObjectName"); 238 rowData[1] = mbean.getObjectName(); 239 tableModel.addRow(rowData); 240 rowData[0] = Resources.getText("ClassName"); 241 rowData[1] = mbeanInfo.getClassName(); 242 tableModel.addRow(rowData); 243 rowData[0] = Resources.getText("Description"); 244 rowData[1] = mbeanInfo.getDescription(); 245 tableModel.addRow(rowData); 246 addDescriptor(mbeanInfo.getDescriptor(), text); 247 // MBeanConstructorInfo 248 // 249 int i = 0; 250 for (MBeanConstructorInfo mbci : mbeanInfo.getConstructors()) { 251 addMBeanConstructorInfo(mbci, 252 Resources.getText("Constructor") + "-" + i + ":"); 253 // MBeanParameterInfo 254 // 255 int j = 0; 256 for (MBeanParameterInfo mbpi : mbci.getSignature()) { 257 addMBeanParameterInfo(mbpi, 258 Resources.getText("Parameter") + "-" + i + "-" + j + ":"); 259 j++; 260 } 261 i++; 262 } 263 tableModel.newDataAvailable(new TableModelEvent(tableModel)); 264 } 265 266 public void addMBeanAttributeInfo(MBeanAttributeInfo mbai) { 267 emptyInfoTable(); 268 emptyDescTable(); 269 ((TitledBorder) infoBorderPanel.getBorder()).setTitle( 270 Resources.getText("MBeanAttributeInfo")); 271 String text = Resources.getText("Attribute") + ":"; 272 DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); 273 Object rowData[] = new Object[2]; 274 rowData[0] = new TableRowDivider(text); 275 rowData[1] = new TableRowDivider(""); 276 tableModel.addRow(rowData); 277 rowData[0] = Resources.getText("Name"); 278 rowData[1] = mbai.getName(); 279 tableModel.addRow(rowData); 280 rowData[0] = Resources.getText("Description"); 281 rowData[1] = mbai.getDescription(); 282 tableModel.addRow(rowData); 283 rowData[0] = Resources.getText("Readable"); 284 rowData[1] = mbai.isReadable(); 285 tableModel.addRow(rowData); 286 rowData[0] = Resources.getText("Writable"); 287 rowData[1] = mbai.isWritable(); 288 tableModel.addRow(rowData); 289 rowData[0] = Resources.getText("Is"); 290 rowData[1] = mbai.isIs(); 291 tableModel.addRow(rowData); 292 rowData[0] = Resources.getText("Type"); 293 rowData[1] = mbai.getType(); 294 tableModel.addRow(rowData); 295 addDescriptor(mbai.getDescriptor(), text); 296 tableModel.newDataAvailable(new TableModelEvent(tableModel)); 297 } 298 299 public void addMBeanOperationInfo(MBeanOperationInfo mboi) { 300 emptyInfoTable(); 301 emptyDescTable(); 302 ((TitledBorder) infoBorderPanel.getBorder()).setTitle( 303 Resources.getText("MBeanOperationInfo")); 304 String text = Resources.getText("Operation") + ":"; 305 DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); 306 Object rowData[] = new Object[2]; 307 rowData[0] = new TableRowDivider(text); 308 rowData[1] = new TableRowDivider(""); 309 tableModel.addRow(rowData); 310 rowData[0] = Resources.getText("Name"); 311 rowData[1] = mboi.getName(); 312 tableModel.addRow(rowData); 313 rowData[0] = Resources.getText("Description"); 314 rowData[1] = mboi.getDescription(); 315 tableModel.addRow(rowData); 316 rowData[0] = Resources.getText("Impact"); 317 switch (mboi.getImpact()) { 318 case MBeanOperationInfo.INFO: 319 rowData[1] = Resources.getText("INFO"); 320 break; 321 case MBeanOperationInfo.ACTION: 322 rowData[1] = Resources.getText("ACTION"); 323 break; 324 case MBeanOperationInfo.ACTION_INFO: 325 rowData[1] = Resources.getText("ACTION_INFO"); 326 break; 327 case MBeanOperationInfo.UNKNOWN: 328 rowData[1] = Resources.getText("UNKNOWN"); 329 break; 330 } 331 tableModel.addRow(rowData); 332 rowData[0] = Resources.getText("ReturnType"); 333 rowData[1] = mboi.getReturnType(); 334 tableModel.addRow(rowData); 335 addDescriptor(mboi.getDescriptor(), text); 336 // MBeanParameterInfo 337 // 338 int i = 0; 339 for (MBeanParameterInfo mbpi : mboi.getSignature()) { 340 addMBeanParameterInfo(mbpi, 341 Resources.getText("Parameter") + "-" + i++ + ":"); 342 } 343 tableModel.newDataAvailable(new TableModelEvent(tableModel)); 344 } 345 346 public void addMBeanNotificationInfo(MBeanNotificationInfo mbni) { 347 emptyInfoTable(); 348 emptyDescTable(); 349 ((TitledBorder) infoBorderPanel.getBorder()).setTitle( 350 Resources.getText("MBeanNotificationInfo")); 351 String text = Resources.getText("Notification") + ":"; 352 DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); 353 Object rowData[] = new Object[2]; 354 rowData[0] = new TableRowDivider(text); 355 rowData[1] = new TableRowDivider(""); 356 tableModel.addRow(rowData); 357 rowData[0] = Resources.getText("Name"); 358 rowData[1] = mbni.getName(); 359 tableModel.addRow(rowData); 360 rowData[0] = Resources.getText("Description"); 361 rowData[1] = mbni.getDescription(); 362 tableModel.addRow(rowData); 363 rowData[0] = Resources.getText("NotifTypes"); 364 rowData[1] = Arrays.toString(mbni.getNotifTypes()); 365 tableModel.addRow(rowData); 366 addDescriptor(mbni.getDescriptor(), text); 367 tableModel.newDataAvailable(new TableModelEvent(tableModel)); 368 } 369 370 private void addMBeanConstructorInfo(MBeanConstructorInfo mbci, String text) { 371 DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); 372 Object rowData[] = new Object[2]; 373 rowData[0] = new TableRowDivider(text); 374 rowData[1] = new TableRowDivider(""); 375 tableModel.addRow(rowData); 376 rowData[0] = Resources.getText("Name"); 377 rowData[1] = mbci.getName(); 378 tableModel.addRow(rowData); 379 rowData[0] = Resources.getText("Description"); 380 rowData[1] = mbci.getDescription(); 381 tableModel.addRow(rowData); 382 addDescriptor(mbci.getDescriptor(), text); 383 tableModel.newDataAvailable(new TableModelEvent(tableModel)); 384 } 385 386 private void addMBeanParameterInfo(MBeanParameterInfo mbpi, String text) { 387 DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel(); 388 Object rowData[] = new Object[2]; 389 rowData[0] = new TableRowDivider(text); 390 rowData[1] = new TableRowDivider(""); 391 tableModel.addRow(rowData); 392 rowData[0] = Resources.getText("Name"); 393 rowData[1] = mbpi.getName(); 394 tableModel.addRow(rowData); 395 rowData[0] = Resources.getText("Description"); 396 rowData[1] = mbpi.getDescription(); 397 tableModel.addRow(rowData); 398 rowData[0] = Resources.getText("Type"); 399 rowData[1] = mbpi.getType(); 400 tableModel.addRow(rowData); 401 addDescriptor(mbpi.getDescriptor(), text); 402 tableModel.newDataAvailable(new TableModelEvent(tableModel)); 403 } 404 405 public static void loadInfo(DefaultMutableTreeNode root) { 406 // Retrieve XMBean from XNodeInfo 407 // 408 XMBean mbean = (XMBean) ((XNodeInfo) root.getUserObject()).getData(); 409 // Initialize MBean*Info 410 // 411 final MBeanInfo mbeanInfo; 412 try { 413 mbeanInfo = mbean.getMBeanInfo(); 414 } catch (Exception e) { 415 if (JConsole.isDebug()) { 416 e.printStackTrace(); 417 } 418 return; 419 } 420 MBeanAttributeInfo[] ai = mbeanInfo.getAttributes(); 421 MBeanOperationInfo[] oi = mbeanInfo.getOperations(); 422 MBeanNotificationInfo[] ni = mbeanInfo.getNotifications(); 423 // MBeanAttributeInfo node 424 // 425 if (ai != null && ai.length > 0) { 426 DefaultMutableTreeNode attributes = new DefaultMutableTreeNode(); 427 XNodeInfo attributesUO = new XNodeInfo(Type.ATTRIBUTES, mbean, 428 Resources.getText("Attributes"), null); 429 attributes.setUserObject(attributesUO); 430 root.add(attributes); 431 for (MBeanAttributeInfo mbai : ai) { 432 DefaultMutableTreeNode attribute = new DefaultMutableTreeNode(); 433 XNodeInfo attributeUO = new XNodeInfo(Type.ATTRIBUTE, 434 new Object[] {mbean, mbai}, mbai.getName(), null); 435 attribute.setUserObject(attributeUO); 436 attributes.add(attribute); 437 } 438 } 439 // MBeanOperationInfo node 440 // 441 if (oi != null && oi.length > 0) { 442 DefaultMutableTreeNode operations = new DefaultMutableTreeNode(); 443 XNodeInfo operationsUO = new XNodeInfo(Type.OPERATIONS, mbean, 444 Resources.getText("Operations"), null); 445 operations.setUserObject(operationsUO); 446 root.add(operations); 447 for (MBeanOperationInfo mboi : oi) { 448 // Compute the operation's tool tip text: 449 // "operationname(param1type,param2type,...)" 450 // 451 StringBuilder sb = new StringBuilder(); 452 for (MBeanParameterInfo mbpi : mboi.getSignature()) { 453 sb.append(mbpi.getType() + ","); 454 } 455 String signature = sb.toString(); 456 if (signature.length() > 0) { 457 // Remove the trailing ',' 458 // 459 signature = signature.substring(0, signature.length() - 1); 460 } 461 String toolTipText = mboi.getName() + "(" + signature + ")"; 462 // Create operation node 463 // 464 DefaultMutableTreeNode operation = new DefaultMutableTreeNode(); 465 XNodeInfo operationUO = new XNodeInfo(Type.OPERATION, 466 new Object[] {mbean, mboi}, mboi.getName(), toolTipText); 467 operation.setUserObject(operationUO); 468 operations.add(operation); 469 } 470 } 471 // MBeanNotificationInfo node 472 // 473 if (mbean.isBroadcaster()) { 474 DefaultMutableTreeNode notifications = new DefaultMutableTreeNode(); 475 XNodeInfo notificationsUO = new XNodeInfo(Type.NOTIFICATIONS, mbean, 476 Resources.getText("Notifications"), null); 477 notifications.setUserObject(notificationsUO); 478 root.add(notifications); 479 if (ni != null && ni.length > 0) { 480 for (MBeanNotificationInfo mbni : ni) { 481 DefaultMutableTreeNode notification = 482 new DefaultMutableTreeNode(); 483 XNodeInfo notificationUO = new XNodeInfo(Type.NOTIFICATION, 484 mbni, mbni.getName(), null); 485 notification.setUserObject(notificationUO); 486 notifications.add(notification); 487 } 488 } 489 } 490 } 491 }