1 /*
   2  * Copyright (c) 2004, 2008, 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 
  39 import sun.tools.jconsole.resources.Messages;
  40 
  41 import static sun.tools.jconsole.Utilities.*;
  42 
  43 @SuppressWarnings("serial")
  44 public class XMBeanInfo extends JPanel {
  45 
  46     private static final Color lightYellow = new Color(255, 255, 128);
  47      private final int NAME_COLUMN = 0;
  48     private final int VALUE_COLUMN = 1;
  49     private final String[] columnNames = {
  50         Messages.NAME,
  51         Messages.VALUE
  52     };
  53     private JTable infoTable = new JTable();
  54     private JTable descTable = new JTable();
  55     private JPanel infoBorderPanel = new JPanel(new BorderLayout());
  56     private JPanel descBorderPanel = new JPanel(new BorderLayout());
  57 
  58     private static class ReadOnlyDefaultTableModel extends DefaultTableModel {
  59 
  60         @Override
  61         public void setValueAt(Object value, int row, int col) {
  62         }
  63     }
  64 
  65     private static class TableRowDivider {
  66 
  67         private String tableRowDividerText;
  68 
  69         public TableRowDivider(String tableRowDividerText) {
  70             this.tableRowDividerText = tableRowDividerText;
  71         }
  72 
  73         @Override
  74         public String toString() {
  75             return tableRowDividerText;
  76         }
  77     }
  78     private static MBeanInfoTableCellRenderer renderer =
  79             new MBeanInfoTableCellRenderer();
  80 
  81     private static class MBeanInfoTableCellRenderer
  82             extends DefaultTableCellRenderer {
  83 
  84         @Override
  85         public Component getTableCellRendererComponent(
  86                 JTable table, Object value, boolean isSelected,
  87                 boolean hasFocus, int row, int column) {
  88             Component comp = super.getTableCellRendererComponent(
  89                     table, value, isSelected, hasFocus, row, column);
  90             if (value instanceof TableRowDivider) {
  91                 JLabel label = new JLabel(value.toString());
  92                 label.setBackground(ensureContrast(lightYellow,
  93                         label.getForeground()));
  94                 label.setOpaque(true);
  95                 return label;
  96             }
  97             return comp;
  98         }
  99     }
 100     private static TableCellEditor editor =
 101             new MBeanInfoTableCellEditor(new JTextField());
 102 
 103     private static class MBeanInfoTableCellEditor
 104             extends Utils.ReadOnlyTableCellEditor {
 105 
 106         public MBeanInfoTableCellEditor(JTextField tf) {
 107             super(tf);
 108         }
 109 
 110         @Override
 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(Messages.DESCRIPTOR));
 168         descBorderPanel.add(descTableScrollPane);
 169         // Add the two tables to the grid
 170         //
 171         add(infoBorderPanel);
 172         add(descBorderPanel);
 173     }
 174 
 175     // Call on EDT
 176     public void emptyInfoTable() {
 177         DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
 178         while (tableModel.getRowCount() > 0) {
 179             tableModel.removeRow(0);
 180         }
 181     }
 182 
 183     // Call on EDT
 184     public void emptyDescTable() {
 185         DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel();
 186         while (tableModel.getRowCount() > 0) {
 187             tableModel.removeRow(0);
 188         }
 189     }
 190 
 191     // Call on EDT
 192     private void addDescriptor(Descriptor desc, String text) {
 193         if (desc != null && desc.getFieldNames().length > 0) {
 194             DefaultTableModel tableModel = (DefaultTableModel) descTable.getModel();
 195             Object rowData[] = new Object[2];
 196             rowData[0] = new TableRowDivider(text);
 197             rowData[1] = new TableRowDivider("");
 198             tableModel.addRow(rowData);
 199             for (String fieldName : desc.getFieldNames()) {
 200                 rowData[0] = fieldName;
 201                 Object fieldValue = desc.getFieldValue(fieldName);
 202                 if (fieldValue instanceof boolean[]) {
 203                     rowData[1] = Arrays.toString((boolean[]) fieldValue);
 204                 } else if (fieldValue instanceof byte[]) {
 205                     rowData[1] = Arrays.toString((byte[]) fieldValue);
 206                 } else if (fieldValue instanceof char[]) {
 207                     rowData[1] = Arrays.toString((char[]) fieldValue);
 208                 } else if (fieldValue instanceof double[]) {
 209                     rowData[1] = Arrays.toString((double[]) fieldValue);
 210                 } else if (fieldValue instanceof float[]) {
 211                     rowData[1] = Arrays.toString((float[]) fieldValue);
 212                 } else if (fieldValue instanceof int[]) {
 213                     rowData[1] = Arrays.toString((int[]) fieldValue);
 214                 } else if (fieldValue instanceof long[]) {
 215                     rowData[1] = Arrays.toString((long[]) fieldValue);
 216                 } else if (fieldValue instanceof short[]) {
 217                     rowData[1] = Arrays.toString((short[]) fieldValue);
 218                 } else if (fieldValue instanceof Object[]) {
 219                     rowData[1] = Arrays.toString((Object[]) fieldValue);
 220                 } else {
 221                     rowData[1] = fieldValue;
 222                 }
 223                 tableModel.addRow(rowData);
 224             }
 225             tableModel.newDataAvailable(new TableModelEvent(tableModel));
 226         }
 227     }
 228 
 229     // Call on EDT
 230     public void addMBeanInfo(XMBean mbean, MBeanInfo mbeanInfo) {
 231         emptyInfoTable();
 232         emptyDescTable();
 233         ((TitledBorder) infoBorderPanel.getBorder()).setTitle(
 234                 Messages.MBEAN_INFO);
 235         String text = Messages.INFO + ":";
 236         DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
 237         Object rowData[] = new Object[2];
 238         rowData[0] = new TableRowDivider(text);
 239         rowData[1] = new TableRowDivider("");
 240         tableModel.addRow(rowData);
 241         rowData[0] = Messages.OBJECT_NAME;
 242         rowData[1] = mbean.getObjectName();
 243         tableModel.addRow(rowData);
 244         rowData[0] = Messages.CLASS_NAME;
 245         rowData[1] = mbeanInfo.getClassName();
 246         tableModel.addRow(rowData);
 247         rowData[0] = Messages.DESCRIPTION;
 248         rowData[1] = mbeanInfo.getDescription();
 249         tableModel.addRow(rowData);
 250         addDescriptor(mbeanInfo.getDescriptor(), text);
 251         // MBeanConstructorInfo
 252         //
 253         int i = 0;
 254         for (MBeanConstructorInfo mbci : mbeanInfo.getConstructors()) {
 255             addMBeanConstructorInfo(mbci,
 256                     Messages.CONSTRUCTOR + "-" + i + ":");
 257             // MBeanParameterInfo
 258             //
 259             int j = 0;
 260             for (MBeanParameterInfo mbpi : mbci.getSignature()) {
 261                 addMBeanParameterInfo(mbpi,
 262                         Messages.PARAMETER + "-" + i + "-" + j + ":");
 263                 j++;
 264             }
 265             i++;
 266         }
 267         tableModel.newDataAvailable(new TableModelEvent(tableModel));
 268     }
 269 
 270     // Call on EDT
 271     public void addMBeanAttributeInfo(MBeanAttributeInfo mbai) {
 272         emptyInfoTable();
 273         emptyDescTable();
 274         ((TitledBorder) infoBorderPanel.getBorder()).setTitle(
 275                 Messages.MBEAN_ATTRIBUTE_INFO);
 276         String text = Messages.ATTRIBUTE + ":";
 277         DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
 278         Object rowData[] = new Object[2];
 279         rowData[0] = new TableRowDivider(text);
 280         rowData[1] = new TableRowDivider("");
 281         tableModel.addRow(rowData);
 282         rowData[0] = Messages.NAME;
 283         rowData[1] = mbai.getName();
 284         tableModel.addRow(rowData);
 285         rowData[0] = Messages.DESCRIPTION;
 286         rowData[1] = mbai.getDescription();
 287         tableModel.addRow(rowData);
 288         rowData[0] = Messages.READABLE;
 289         rowData[1] = mbai.isReadable();
 290         tableModel.addRow(rowData);
 291         rowData[0] = Messages.WRITABLE;
 292         rowData[1] = mbai.isWritable();
 293         tableModel.addRow(rowData);
 294         rowData[0] = Messages.IS;
 295         rowData[1] = mbai.isIs();
 296         tableModel.addRow(rowData);
 297         rowData[0] = Messages.TYPE;
 298         rowData[1] = mbai.getType();
 299         tableModel.addRow(rowData);
 300         addDescriptor(mbai.getDescriptor(), text);
 301         tableModel.newDataAvailable(new TableModelEvent(tableModel));
 302     }
 303 
 304     // Call on EDT
 305     public void addMBeanOperationInfo(MBeanOperationInfo mboi) {
 306         emptyInfoTable();
 307         emptyDescTable();
 308         ((TitledBorder) infoBorderPanel.getBorder()).setTitle(
 309                 Messages.MBEAN_OPERATION_INFO);
 310         String text = Messages.OPERATION + ":";
 311         DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
 312         Object rowData[] = new Object[2];
 313         rowData[0] = new TableRowDivider(text);
 314         rowData[1] = new TableRowDivider("");
 315         tableModel.addRow(rowData);
 316         rowData[0] = Messages.NAME;
 317         rowData[1] = mboi.getName();
 318         tableModel.addRow(rowData);
 319         rowData[0] = Messages.DESCRIPTION;
 320         rowData[1] = mboi.getDescription();
 321         tableModel.addRow(rowData);
 322         rowData[0] = Messages.IMPACT;
 323         switch (mboi.getImpact()) {
 324             case MBeanOperationInfo.INFO:
 325                 rowData[1] = Messages.INFO_CAPITALIZED;
 326                 break;
 327             case MBeanOperationInfo.ACTION:
 328                 rowData[1] = Messages.ACTION_CAPITALIZED;
 329                 break;
 330             case MBeanOperationInfo.ACTION_INFO:
 331                 rowData[1] = Messages.ACTION_INFO_CAPITALIZED;
 332                 break;
 333             case MBeanOperationInfo.UNKNOWN:
 334                 rowData[1] = Messages.UNKNOWN_CAPITALIZED;
 335                 break;
 336         }
 337         tableModel.addRow(rowData);
 338         rowData[0] = Messages.RETURN_TYPE;
 339         rowData[1] = mboi.getReturnType();
 340         tableModel.addRow(rowData);
 341         addDescriptor(mboi.getDescriptor(), text);
 342         // MBeanParameterInfo
 343         //
 344         int i = 0;
 345         for (MBeanParameterInfo mbpi : mboi.getSignature()) {
 346             addMBeanParameterInfo(mbpi,
 347                     Messages.PARAMETER + "-" + i++ + ":");
 348         }
 349         tableModel.newDataAvailable(new TableModelEvent(tableModel));
 350     }
 351 
 352     // Call on EDT
 353     public void addMBeanNotificationInfo(MBeanNotificationInfo mbni) {
 354         emptyInfoTable();
 355         emptyDescTable();
 356         ((TitledBorder) infoBorderPanel.getBorder()).setTitle(
 357                 Messages.MBEAN_NOTIFICATION_INFO);
 358         String text = Messages.NOTIFICATION + ":";
 359         DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
 360         Object rowData[] = new Object[2];
 361         rowData[0] = new TableRowDivider(text);
 362         rowData[1] = new TableRowDivider("");
 363         tableModel.addRow(rowData);
 364         rowData[0] = Messages.NAME;
 365         rowData[1] = mbni.getName();
 366         tableModel.addRow(rowData);
 367         rowData[0] = Messages.DESCRIPTION;
 368         rowData[1] = mbni.getDescription();
 369         tableModel.addRow(rowData);
 370         rowData[0] = Messages.NOTIF_TYPES;
 371         rowData[1] = Arrays.toString(mbni.getNotifTypes());
 372         tableModel.addRow(rowData);
 373         addDescriptor(mbni.getDescriptor(), text);
 374         tableModel.newDataAvailable(new TableModelEvent(tableModel));
 375     }
 376 
 377     // Call on EDT
 378     private void addMBeanConstructorInfo(MBeanConstructorInfo mbci, String text) {
 379         DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
 380         Object rowData[] = new Object[2];
 381         rowData[0] = new TableRowDivider(text);
 382         rowData[1] = new TableRowDivider("");
 383         tableModel.addRow(rowData);
 384         rowData[0] = Messages.NAME;
 385         rowData[1] = mbci.getName();
 386         tableModel.addRow(rowData);
 387         rowData[0] = Messages.DESCRIPTION;
 388         rowData[1] = mbci.getDescription();
 389         tableModel.addRow(rowData);
 390         addDescriptor(mbci.getDescriptor(), text);
 391         tableModel.newDataAvailable(new TableModelEvent(tableModel));
 392     }
 393 
 394     // Call on EDT
 395     private void addMBeanParameterInfo(MBeanParameterInfo mbpi, String text) {
 396         DefaultTableModel tableModel = (DefaultTableModel) infoTable.getModel();
 397         Object rowData[] = new Object[2];
 398         rowData[0] = new TableRowDivider(text);
 399         rowData[1] = new TableRowDivider("");
 400         tableModel.addRow(rowData);
 401         rowData[0] = Messages.NAME;
 402         rowData[1] = mbpi.getName();
 403         tableModel.addRow(rowData);
 404         rowData[0] = Messages.DESCRIPTION;
 405         rowData[1] = mbpi.getDescription();
 406         tableModel.addRow(rowData);
 407         rowData[0] = Messages.TYPE;
 408         rowData[1] = mbpi.getType();
 409         tableModel.addRow(rowData);
 410         addDescriptor(mbpi.getDescriptor(), text);
 411         tableModel.newDataAvailable(new TableModelEvent(tableModel));
 412     }
 413 }