1 /*
2  * Copyright (c) 2004, 2012, 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.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
setValueAt(Object value, int row, int col)61         public void setValueAt(Object value, int row, int col) {
62         }
63     }
64 
65     private static class TableRowDivider {
66 
67         private String tableRowDividerText;
68 
TableRowDivider(String tableRowDividerText)69         public TableRowDivider(String tableRowDividerText) {
70             this.tableRowDividerText = tableRowDividerText;
71         }
72 
73         @Override
toString()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
getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)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 
MBeanInfoTableCellEditor(JTextField tf)106         public MBeanInfoTableCellEditor(JTextField tf) {
107             super(tf);
108         }
109 
110         @Override
getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column)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 
XMBeanInfo()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
emptyInfoTable()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
emptyDescTable()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
addDescriptor(Descriptor desc, String text)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
addMBeanInfo(XMBean mbean, MBeanInfo mbeanInfo)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
addMBeanAttributeInfo(MBeanAttributeInfo mbai)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
addMBeanOperationInfo(MBeanOperationInfo mboi)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
addMBeanNotificationInfo(MBeanNotificationInfo mbni)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
addMBeanConstructorInfo(MBeanConstructorInfo mbci, String text)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
addMBeanParameterInfo(MBeanParameterInfo mbpi, String text)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 }
414