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