834 lines · 30.4 KB · Java
RawDownload
/* * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.tools.jconsole.inspector; import java.io.IOException;import java.util.*;import javax.management.*;import javax.swing.*;import javax.swing.tree.*;import sun.tools.jconsole.JConsole;import sun.tools.jconsole.MBeansTab;import sun.tools.jconsole.Resources;import sun.tools.jconsole.inspector.XNodeInfo;import static sun.tools.jconsole.inspector.XNodeInfo.Type; @SuppressWarnings("serial")public class XTree extends JTree {     private static final List<String> orderedKeyPropertyList =            new ArrayList<String>();     static {        String keyPropertyList =                System.getProperty("com.sun.tools.jconsole.mbeans.keyPropertyList");        if (keyPropertyList == null) {            orderedKeyPropertyList.add("type");            orderedKeyPropertyList.add("j2eeType");        } else {            StringTokenizer st = new StringTokenizer(keyPropertyList, ",");            while (st.hasMoreTokens()) {                orderedKeyPropertyList.add(st.nextToken());            }        }    }    private MBeansTab mbeansTab;    private Map<String, DefaultMutableTreeNode> nodes =            new HashMap<String, DefaultMutableTreeNode>();     public XTree(MBeansTab mbeansTab) {        this(new DefaultMutableTreeNode("MBeanTreeRootNode"), mbeansTab);    }     public XTree(TreeNode root, MBeansTab mbeansTab) {        super(root, true);        this.mbeansTab = mbeansTab;        setRootVisible(false);        setShowsRootHandles(true);        ToolTipManager.sharedInstance().registerComponent(this);    }     /**     * This method removes the node from its parent     */    // Call on EDT    private synchronized void removeChildNode(DefaultMutableTreeNode child) {        DefaultTreeModel model = (DefaultTreeModel) getModel();        model.removeNodeFromParent(child);    }     /**     * This method adds the child to the specified parent node     * at specific index.     */    // Call on EDT    private synchronized void addChildNode(            DefaultMutableTreeNode parent,            DefaultMutableTreeNode child,            int index) {        DefaultTreeModel model = (DefaultTreeModel) getModel();        model.insertNodeInto(child, parent, index);    }     /**     * This method adds the child to the specified parent node.     * The index where the child is to be added depends on the     * child node being Comparable or not. If the child node is     * not Comparable then it is added at the end, i.e. right     * after the current parent's children.     */    // Call on EDT    private synchronized void addChildNode(            DefaultMutableTreeNode parent, DefaultMutableTreeNode child) {        int childCount = parent.getChildCount();        if (childCount == 0) {            addChildNode(parent, child, 0);            return;        }        if (child instanceof ComparableDefaultMutableTreeNode) {            ComparableDefaultMutableTreeNode comparableChild =                    (ComparableDefaultMutableTreeNode) child;            for (int i = childCount - 1; i >= 0; i--) {                DefaultMutableTreeNode brother =                        (DefaultMutableTreeNode) parent.getChildAt(i);                // expr1: child node must be inserted after metadata nodes                // - OR -                // expr2: "child >= brother"                if ((i <= 2 && isMetadataNode(brother)) ||                        comparableChild.compareTo(brother) >= 0) {                    addChildNode(parent, child, i + 1);                    return;                }            }            // "child < all brothers", add at the beginning            addChildNode(parent, child, 0);            return;        }        // "child not comparable", add at the end        addChildNode(parent, child, childCount);    }     /**     * This method removes all the displayed nodes from the tree,     * but does not affect actual MBeanServer contents.     */    // Call on EDT    @Override    public synchronized void removeAll() {        DefaultTreeModel model = (DefaultTreeModel) getModel();        DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();        root.removeAllChildren();        model.nodeStructureChanged(root);        nodes.clear();    }     // Call on EDT    public synchronized void removeMBeanFromView(ObjectName mbean) {        // We assume here that MBeans are removed one by one (on MBean        // unregistered notification). Deletes the tree node associated        // with the given MBean and recursively all the node parents        // which are leaves and non XMBean.        //        DefaultMutableTreeNode node = null;        Dn dn = new Dn(mbean);        if (dn.getTokenCount() > 0) {            DefaultTreeModel model = (DefaultTreeModel) getModel();            Token token = dn.getToken(0);            String hashKey = dn.getHashKey(token);            node = nodes.get(hashKey);            if ((node != null) && (!node.isRoot())) {                if (hasNonMetadataNodes(node)) {                    removeMetadataNodes(node);                    String label = token.getValue();                    XNodeInfo userObject = new XNodeInfo(                            Type.NONMBEAN, label,                            label, token.getTokenValue());                    changeNodeValue(node, userObject);                } else {                    DefaultMutableTreeNode parent =                            (DefaultMutableTreeNode) node.getParent();                    model.removeNodeFromParent(node);                    nodes.remove(hashKey);                    removeParentFromView(dn, 1, parent);                }            }        }    }     /**     * Returns true if any of the children nodes is a non MBean metadata node.     */    private boolean hasNonMetadataNodes(DefaultMutableTreeNode node) {        for (Enumeration e = node.children(); e.hasMoreElements();) {            DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();            Object uo = n.getUserObject();            if (uo instanceof XNodeInfo) {                switch (((XNodeInfo) uo).getType()) {                    case ATTRIBUTES:                    case NOTIFICATIONS:                    case OPERATIONS:                        break;                    default:                        return true;                }            } else {                return true;            }        }        return false;    }     /**     * Returns true if any of the children nodes is an MBean metadata node.     */    public boolean hasMetadataNodes(DefaultMutableTreeNode node) {        for (Enumeration e = node.children(); e.hasMoreElements();) {            DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();            Object uo = n.getUserObject();            if (uo instanceof XNodeInfo) {                switch (((XNodeInfo) uo).getType()) {                    case ATTRIBUTES:                    case NOTIFICATIONS:                    case OPERATIONS:                        return true;                    default:                        break;                }            } else {                return false;            }        }        return false;    }     /**     * Returns true if the given node is an MBean metadata node.     */    public boolean isMetadataNode(DefaultMutableTreeNode node) {        Object uo = node.getUserObject();        if (uo instanceof XNodeInfo) {            switch (((XNodeInfo) uo).getType()) {                case ATTRIBUTES:                case NOTIFICATIONS:                case OPERATIONS:                    return true;                default:                    return false;            }        } else {            return false;        }    }     /**     * Remove the metadata nodes associated with a given MBean node.     */    // Call on EDT    private void removeMetadataNodes(DefaultMutableTreeNode node) {        Set<DefaultMutableTreeNode> metadataNodes =                new HashSet<DefaultMutableTreeNode>();        DefaultTreeModel model = (DefaultTreeModel) getModel();        for (Enumeration e = node.children(); e.hasMoreElements();) {            DefaultMutableTreeNode n = (DefaultMutableTreeNode) e.nextElement();            Object uo = n.getUserObject();            if (uo instanceof XNodeInfo) {                switch (((XNodeInfo) uo).getType()) {                    case ATTRIBUTES:                    case NOTIFICATIONS:                    case OPERATIONS:                        metadataNodes.add(n);                        break;                    default:                        break;                }            }        }        for (DefaultMutableTreeNode n : metadataNodes) {            model.removeNodeFromParent(n);        }    }     /**     * Removes only the parent nodes which are non MBean and leaf.     * This method assumes the child nodes have been removed before.     */    // Call on EDT    private DefaultMutableTreeNode removeParentFromView(            Dn dn, int index, DefaultMutableTreeNode node) {        if ((!node.isRoot()) && node.isLeaf() &&                (!(((XNodeInfo) node.getUserObject()).getType().equals(Type.MBEAN)))) {            DefaultMutableTreeNode parent =                    (DefaultMutableTreeNode) node.getParent();            removeChildNode(node);            String hashKey = dn.getHashKey(dn.getToken(index));            nodes.remove(hashKey);            removeParentFromView(dn, index + 1, parent);        }        return node;    }     // Call on EDT    public synchronized void addMBeansToView(Set<ObjectName> mbeans) {        Set<Dn> dns = new TreeSet<Dn>();        for (ObjectName mbean : mbeans) {            Dn dn = new Dn(mbean);            dns.add(dn);        }        for (Dn dn : dns) {            ObjectName mbean = dn.getObjectName();            XMBean xmbean = new XMBean(mbean, mbeansTab);            addMBeanToView(mbean, xmbean, dn);        }    }     // Call on EDT    public synchronized void addMBeanToView(ObjectName mbean) {        // Build XMBean for the given MBean        //        XMBean xmbean = new XMBean(mbean, mbeansTab);        // Build Dn for the given MBean        //        Dn dn = new Dn(mbean);        // Add the new nodes to the MBean tree from leaf to root        //        addMBeanToView(mbean, xmbean, dn);    }     // Call on EDT    private synchronized void addMBeanToView(            ObjectName mbean, XMBean xmbean, Dn dn) {         DefaultMutableTreeNode childNode = null;        DefaultMutableTreeNode parentNode = null;         // Add the node or replace its user object if already added        //        Token token = dn.getToken(0);        String hashKey = dn.getHashKey(token);        if (nodes.containsKey(hashKey)) {            // Found existing node previously created when adding another node            //            childNode = nodes.get(hashKey);            // Replace user object to reflect that this node is an MBean            //            Object data = createNodeValue(xmbean, token);            String label = data.toString();            XNodeInfo userObject =                    new XNodeInfo(Type.MBEAN, data, label, mbean.toString());            changeNodeValue(childNode, userObject);            return;        }         // Create new leaf node        //        childNode = createDnNode(dn, token, xmbean);        nodes.put(hashKey, childNode);         // Add intermediate non MBean nodes        //        for (int i = 1; i < dn.getTokenCount(); i++) {            token = dn.getToken(i);            hashKey = dn.getHashKey(token);            if (nodes.containsKey(hashKey)) {                // Intermediate node already present, add new node as child                //                parentNode = nodes.get(hashKey);                addChildNode(parentNode, childNode);                return;            } else {                // Create new intermediate node                //                if ("domain".equals(token.getTokenType())) {                    parentNode = createDomainNode(dn, token);                    DefaultMutableTreeNode root =                            (DefaultMutableTreeNode) getModel().getRoot();                    addChildNode(root, parentNode);                } else {                    parentNode = createSubDnNode(dn, token);                }                nodes.put(hashKey, parentNode);                addChildNode(parentNode, childNode);            }            childNode = parentNode;        }    }     // Call on EDT    private synchronized void changeNodeValue(            DefaultMutableTreeNode node, XNodeInfo nodeValue) {        if (node instanceof ComparableDefaultMutableTreeNode) {            // should it stay at the same place?            DefaultMutableTreeNode clone =                    (DefaultMutableTreeNode) node.clone();            clone.setUserObject(nodeValue);            if (((ComparableDefaultMutableTreeNode) node).compareTo(clone) == 0) {                // the order in the tree didn't change                node.setUserObject(nodeValue);                DefaultTreeModel model = (DefaultTreeModel) getModel();                model.nodeChanged(node);            } else {                // delete the node and re-order it in case the                // node value modifies the order in the tree                DefaultMutableTreeNode parent =                        (DefaultMutableTreeNode) node.getParent();                removeChildNode(node);                node.setUserObject(nodeValue);                addChildNode(parent, node);            }        } else {            // not comparable stays at the same place            node.setUserObject(nodeValue);            DefaultTreeModel model = (DefaultTreeModel) getModel();            model.nodeChanged(node);        }        // Load the MBean metadata if type is MBEAN        if (nodeValue.getType().equals(Type.MBEAN)) {            removeMetadataNodes(node);            TreeNode[] treeNodes = node.getPath();            TreePath path = new TreePath(treeNodes);            if (isExpanded(path)) {                addMetadataNodes(node);            }        }        // Clear the current selection and set it        // again so valueChanged() gets called        if (node == getLastSelectedPathComponent()) {            TreePath selectionPath = getSelectionPath();            clearSelection();            setSelectionPath(selectionPath);        }    }     /**     * Creates the domain node.     */    private DefaultMutableTreeNode createDomainNode(Dn dn, Token token) {        DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();        String label = dn.getDomain();        XNodeInfo userObject =                new XNodeInfo(Type.NONMBEAN, label, label, label);        node.setUserObject(userObject);        return node;    }     /**     * Creates the node corresponding to the whole Dn, i.e. an MBean.     */    private DefaultMutableTreeNode createDnNode(            Dn dn, Token token, XMBean xmbean) {        DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();        Object data = createNodeValue(xmbean, token);        String label = data.toString();        XNodeInfo userObject = new XNodeInfo(Type.MBEAN, data, label,                xmbean.getObjectName().toString());        node.setUserObject(userObject);        return node;    }     /**     * Creates the node corresponding to a subDn, i.e. a non-MBean     * intermediate node.     */    private DefaultMutableTreeNode createSubDnNode(Dn dn, Token token) {        DefaultMutableTreeNode node = new ComparableDefaultMutableTreeNode();        String label = isKeyValueView() ? token.getTokenValue() : token.getValue();        XNodeInfo userObject =                new XNodeInfo(Type.NONMBEAN, label, label, token.getTokenValue());        node.setUserObject(userObject);        return node;    }     private Object createNodeValue(XMBean xmbean, Token token) {        String label = isKeyValueView() ? token.getTokenValue() : token.getValue();        xmbean.setText(label);        return xmbean;    }     /**     * Parses the MBean ObjectName comma-separated properties string and puts     * the individual key/value pairs into the map. Key order in the properties     * string is preserved by the map.     */    private static Map<String, String> extractKeyValuePairs(            String props, ObjectName mbean) {        Map<String, String> map = new LinkedHashMap<String, String>();        int eq = props.indexOf("=");        while (eq != -1) {            String key = props.substring(0, eq);            String value = mbean.getKeyProperty(key);            map.put(key, value);            props = props.substring(key.length() + 1 + value.length());            if (props.startsWith(",")) {                props = props.substring(1);            }            eq = props.indexOf("=");        }        return map;    }     /**     * Returns the ordered key property list that will be used to build the     * MBean tree. If the "com.sun.tools.jconsole.mbeans.keyPropertyList" system     * property is not specified, then the ordered key property list used     * to build the MBean tree will be the one returned by the method     * ObjectName.getKeyPropertyListString() with "type" as first key,     * and "j2eeType" as second key, if present. If any of the keys specified     * in the comma-separated key property list does not apply to the given     * MBean then it will be discarded.

Lines 1–500 of 834.