|
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; |
|
27 |
|
28 import java.awt.BorderLayout; |
|
29 import java.awt.EventQueue; |
|
30 import java.awt.event.MouseAdapter; |
|
31 import java.awt.event.MouseEvent; |
|
32 import java.awt.event.MouseListener; |
|
33 import java.beans.*; |
|
34 import java.io.*; |
|
35 import java.util.Set; |
|
36 import javax.management.*; |
|
37 import javax.swing.*; |
|
38 import javax.swing.event.*; |
|
39 import javax.swing.tree.*; |
|
40 import sun.tools.jconsole.ProxyClient.SnapshotMBeanServerConnection; |
|
41 import sun.tools.jconsole.inspector.*; |
|
42 |
|
43 import com.sun.tools.jconsole.JConsoleContext; |
|
44 |
|
45 @SuppressWarnings("serial") |
|
46 public class MBeansTab extends Tab implements |
|
47 NotificationListener, PropertyChangeListener, |
|
48 TreeSelectionListener, TreeWillExpandListener { |
|
49 |
|
50 private XTree tree; |
|
51 private XSheet sheet; |
|
52 private XDataViewer viewer; |
|
53 |
|
54 public static String getTabName() { |
|
55 return Messages.MBEANS; |
|
56 } |
|
57 |
|
58 public MBeansTab(final VMPanel vmPanel) { |
|
59 super(vmPanel, getTabName()); |
|
60 addPropertyChangeListener(this); |
|
61 setupTab(); |
|
62 } |
|
63 |
|
64 public XDataViewer getDataViewer() { |
|
65 return viewer; |
|
66 } |
|
67 |
|
68 public XTree getTree() { |
|
69 return tree; |
|
70 } |
|
71 |
|
72 public XSheet getSheet() { |
|
73 return sheet; |
|
74 } |
|
75 |
|
76 @Override |
|
77 public void dispose() { |
|
78 super.dispose(); |
|
79 sheet.dispose(); |
|
80 } |
|
81 |
|
82 public int getUpdateInterval() { |
|
83 return vmPanel.getUpdateInterval(); |
|
84 } |
|
85 |
|
86 private void buildMBeanServerView() { |
|
87 new SwingWorker<Set<ObjectName>, Void>() { |
|
88 @Override |
|
89 public Set<ObjectName> doInBackground() { |
|
90 // Register listener for MBean registration/unregistration |
|
91 // |
|
92 try { |
|
93 getMBeanServerConnection().addNotificationListener( |
|
94 MBeanServerDelegate.DELEGATE_NAME, |
|
95 MBeansTab.this, |
|
96 null, |
|
97 null); |
|
98 } catch (InstanceNotFoundException e) { |
|
99 // Should never happen because the MBeanServerDelegate |
|
100 // is always present in any standard MBeanServer |
|
101 // |
|
102 if (JConsole.isDebug()) { |
|
103 e.printStackTrace(); |
|
104 } |
|
105 } catch (IOException e) { |
|
106 if (JConsole.isDebug()) { |
|
107 e.printStackTrace(); |
|
108 } |
|
109 vmPanel.getProxyClient().markAsDead(); |
|
110 return null; |
|
111 } |
|
112 // Retrieve MBeans from MBeanServer |
|
113 // |
|
114 Set<ObjectName> mbeans = null; |
|
115 try { |
|
116 mbeans = getMBeanServerConnection().queryNames(null, null); |
|
117 } catch (IOException e) { |
|
118 if (JConsole.isDebug()) { |
|
119 e.printStackTrace(); |
|
120 } |
|
121 vmPanel.getProxyClient().markAsDead(); |
|
122 return null; |
|
123 } |
|
124 return mbeans; |
|
125 } |
|
126 @Override |
|
127 protected void done() { |
|
128 try { |
|
129 // Wait for mbsc.queryNames() result |
|
130 Set<ObjectName> mbeans = get(); |
|
131 // Do not display anything until the new tree has been built |
|
132 // |
|
133 tree.setVisible(false); |
|
134 // Cleanup current tree |
|
135 // |
|
136 tree.removeAll(); |
|
137 // Add MBeans to tree |
|
138 // |
|
139 tree.addMBeansToView(mbeans); |
|
140 // Display the new tree |
|
141 // |
|
142 tree.setVisible(true); |
|
143 } catch (Exception e) { |
|
144 Throwable t = Utils.getActualException(e); |
|
145 if (JConsole.isDebug()) { |
|
146 System.err.println("Problem at MBean tree construction"); |
|
147 t.printStackTrace(); |
|
148 } |
|
149 } |
|
150 } |
|
151 }.execute(); |
|
152 } |
|
153 |
|
154 public MBeanServerConnection getMBeanServerConnection() { |
|
155 return vmPanel.getProxyClient().getMBeanServerConnection(); |
|
156 } |
|
157 |
|
158 public SnapshotMBeanServerConnection getSnapshotMBeanServerConnection() { |
|
159 return vmPanel.getProxyClient().getSnapshotMBeanServerConnection(); |
|
160 } |
|
161 |
|
162 @Override |
|
163 public void update() { |
|
164 // Ping the connection to see if it is still alive. At |
|
165 // some point the ProxyClient class should centralize |
|
166 // the connection aliveness monitoring and no longer |
|
167 // rely on the custom tabs to ping the connections. |
|
168 // |
|
169 try { |
|
170 getMBeanServerConnection().getDefaultDomain(); |
|
171 } catch (IOException ex) { |
|
172 vmPanel.getProxyClient().markAsDead(); |
|
173 } |
|
174 } |
|
175 |
|
176 private void setupTab() { |
|
177 // set up the split pane with the MBean tree and MBean sheet panels |
|
178 setLayout(new BorderLayout()); |
|
179 JSplitPane mainSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); |
|
180 mainSplit.setDividerLocation(160); |
|
181 mainSplit.setBorder(BorderFactory.createEmptyBorder()); |
|
182 |
|
183 // set up the MBean tree panel (left pane) |
|
184 tree = new XTree(this); |
|
185 tree.setCellRenderer(new XTreeRenderer()); |
|
186 tree.getSelectionModel().setSelectionMode( |
|
187 TreeSelectionModel.SINGLE_TREE_SELECTION); |
|
188 tree.addTreeSelectionListener(this); |
|
189 tree.addTreeWillExpandListener(this); |
|
190 tree.addMouseListener(ml); |
|
191 JScrollPane theScrollPane = new JScrollPane( |
|
192 tree, |
|
193 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, |
|
194 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); |
|
195 JPanel treePanel = new JPanel(new BorderLayout()); |
|
196 treePanel.add(theScrollPane, BorderLayout.CENTER); |
|
197 mainSplit.add(treePanel, JSplitPane.LEFT, 0); |
|
198 |
|
199 // set up the MBean sheet panel (right pane) |
|
200 viewer = new XDataViewer(this); |
|
201 sheet = new XSheet(this); |
|
202 mainSplit.add(sheet, JSplitPane.RIGHT, 0); |
|
203 |
|
204 add(mainSplit); |
|
205 } |
|
206 |
|
207 /* notification listener: handleNotification */ |
|
208 public void handleNotification( |
|
209 final Notification notification, Object handback) { |
|
210 EventQueue.invokeLater(new Runnable() { |
|
211 public void run() { |
|
212 if (notification instanceof MBeanServerNotification) { |
|
213 ObjectName mbean = |
|
214 ((MBeanServerNotification) notification).getMBeanName(); |
|
215 if (notification.getType().equals( |
|
216 MBeanServerNotification.REGISTRATION_NOTIFICATION)) { |
|
217 tree.addMBeanToView(mbean); |
|
218 } else if (notification.getType().equals( |
|
219 MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) { |
|
220 tree.removeMBeanFromView(mbean); |
|
221 } |
|
222 } |
|
223 } |
|
224 }); |
|
225 } |
|
226 |
|
227 /* property change listener: propertyChange */ |
|
228 public void propertyChange(PropertyChangeEvent evt) { |
|
229 if (JConsoleContext.CONNECTION_STATE_PROPERTY.equals(evt.getPropertyName())) { |
|
230 boolean connected = (Boolean) evt.getNewValue(); |
|
231 if (connected) { |
|
232 buildMBeanServerView(); |
|
233 } else { |
|
234 sheet.dispose(); |
|
235 } |
|
236 } |
|
237 } |
|
238 |
|
239 /* tree selection listener: valueChanged */ |
|
240 public void valueChanged(TreeSelectionEvent e) { |
|
241 DefaultMutableTreeNode node = |
|
242 (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); |
|
243 sheet.displayNode(node); |
|
244 } |
|
245 /* tree mouse listener: mousePressed */ |
|
246 private MouseListener ml = new MouseAdapter() { |
|
247 @Override |
|
248 public void mousePressed(MouseEvent e) { |
|
249 if (e.getClickCount() == 1) { |
|
250 int selRow = tree.getRowForLocation(e.getX(), e.getY()); |
|
251 if (selRow != -1) { |
|
252 TreePath selPath = |
|
253 tree.getPathForLocation(e.getX(), e.getY()); |
|
254 DefaultMutableTreeNode node = |
|
255 (DefaultMutableTreeNode) selPath.getLastPathComponent(); |
|
256 if (sheet.isMBeanNode(node)) { |
|
257 tree.expandPath(selPath); |
|
258 } |
|
259 } |
|
260 } |
|
261 } |
|
262 }; |
|
263 |
|
264 /* tree will expand listener: treeWillExpand */ |
|
265 public void treeWillExpand(TreeExpansionEvent e) |
|
266 throws ExpandVetoException { |
|
267 TreePath path = e.getPath(); |
|
268 if (!tree.hasBeenExpanded(path)) { |
|
269 DefaultMutableTreeNode node = |
|
270 (DefaultMutableTreeNode) path.getLastPathComponent(); |
|
271 if (sheet.isMBeanNode(node) && !tree.hasMetadataNodes(node)) { |
|
272 tree.addMetadataNodes(node); |
|
273 } |
|
274 } |
|
275 } |
|
276 |
|
277 /* tree will expand listener: treeWillCollapse */ |
|
278 public void treeWillCollapse(TreeExpansionEvent e) |
|
279 throws ExpandVetoException { |
|
280 } |
|
281 } |