[Mc4j-cvs] mc4j/src/org/mc4j/jre15/components ThreadMBeanThreadBrowserComponent.java,NONE,1.1
Brought to you by:
ghinkl
From: Greg H. <gh...@us...> - 2004-03-31 20:13:55
|
Update of /cvsroot/mc4j/mc4j/src/org/mc4j/jre15/components In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22460/src/org/mc4j/jre15/components Added Files: ThreadMBeanThreadBrowserComponent.java Log Message: This component supports browsing Thread information from the jre15 ThreadMBean. --- NEW FILE: ThreadMBeanThreadBrowserComponent.java --- /* * Author: Greg Hinkle * * The contents of this file are subject to the Sapient Public License Version 1.0 (the "License"); * you may not use this file except in compliance with the License. You may obtain a copy of the * License at http://mc4j.sf.net/License-SPL.html. * * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, * either express or implied. See the License for the specific language governing rights and limitations * under the License. * * The Original Code is The MC4J Management Console * The Initial Developer of the Original Code is Greg Hinkle (gh...@us...) * Copyright (C) 2004 Greg Hinkle. All Rights Reserved. * * Redistributions of code or binary files using or based on this code must reproduce the * above copyright and disclaimer. For more information see <http://mc4j.sourceforge.net>. */ package org.mc4j.jre15.components; import java.awt.BorderLayout; import java.awt.Component; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMBean; import java.lang.management.ThreadState; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.management.MBeanServer; import javax.management.MBeanServerInvocationHandler; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import org.openide.ErrorManager; import org.mc4j.carbon.config.tree.ConfigurationTreeComponent; import org.mc4j.console.Refreshable; import org.mc4j.console.dashboard.Dashboard; import org.mc4j.console.dashboard.DashboardComponent; /** * This component supports viewing JVM thread information in a tree structure. It shows the thread * name, id and status as well as the current thread stack elements. * * @author Greg Hinkle (gh...@us...), Mar 31, 2004 * @version $Revision: 1.1 $($Author: ghinkl $ / $Date: 2004/03/31 20:02:04 $) */ public class ThreadMBeanThreadBrowserComponent extends JPanel implements DashboardComponent, Refreshable { protected ThreadMBean threadMBean; protected JTree threadTree; protected DefaultTreeModel treeModel; protected DefaultMutableTreeNode root; protected Map threadMap; public ThreadMBeanThreadBrowserComponent() { init(); threadMap = new HashMap(); } public void init() { setLayout(new BorderLayout()); threadTree = new JTree(); root = new DefaultMutableTreeNode("Threads"); treeModel = new DefaultTreeModel(root); threadTree.setRootVisible(false); threadTree.setModel(treeModel); threadTree.setCellRenderer(new ThreadTreeCellRenderer()); JScrollPane scrollpane = new JScrollPane(threadTree); add(scrollpane, BorderLayout.CENTER); } public void setContext(Map context) { MBeanServer mBeanServer = (MBeanServer) context.get(Dashboard.CONTEXT_MBEAN_SERVER); try { this.threadMBean = (ThreadMBean) MBeanServerInvocationHandler.newProxyInstance( mBeanServer, new ObjectName(ManagementFactory.THREAD_MBEAN_NAME), ThreadMBean.class, false); } catch (MalformedObjectNameException moe) { ErrorManager.getDefault().notify(moe); } refresh(); this.treeModel.nodeStructureChanged(root); } public void refresh() { try { // TODO GH: the added set is not being used and right now i'm firing // update events for each insertion or removal. this is probably much // slower than firing a single event with all of the changes. Set deadThreadSet = new HashSet(threadMap.values()); Set addedSet = new HashSet(); long[] threadIds = this.threadMBean.getAllThreadIds(); Arrays.sort(threadIds); ThreadInfo[] threadInfos = this.threadMBean.getThreadInfo(threadIds,Integer.MAX_VALUE); for (int i = 0; i < threadInfos.length; i++) { ThreadInfo threadInfo = threadInfos[i]; DefaultMutableTreeNode threadNode = null; threadNode = (DefaultMutableTreeNode) threadMap.get(new Long(threadInfo.getThreadId())); if (threadNode == null) { threadNode = new DefaultMutableTreeNode(threadInfo); root.add(threadNode); threadMap.put(new Long(threadInfo.getThreadId()),threadNode); addedSet.add(threadNode); this.treeModel.nodesWereInserted(root, new int[] { root.getChildCount() - 1 }); } else { threadNode.setUserObject(threadInfo); threadNode.removeAllChildren(); deadThreadSet.remove(threadNode); } StackTraceElement[] stackElements = threadInfo.getStackTrace(); for (int j = 0; j < stackElements.length; j++) { StackTraceElement stackElement = stackElements[j]; DefaultMutableTreeNode stackNode = new DefaultMutableTreeNode(stackElement); threadNode.add(stackNode); } this.treeModel.nodeStructureChanged(threadNode); } // Remove any threads we didn't remove from the dead thread set... and which are therefore now dead for (Iterator iterator = deadThreadSet.iterator(); iterator.hasNext();) { DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) iterator.next(); int index = root.getIndex(defaultMutableTreeNode); root.remove(defaultMutableTreeNode); this.treeModel.nodesWereRemoved(root, new int[] { index }, new Object[] { defaultMutableTreeNode }); threadMap.remove(new Long(((ThreadInfo)defaultMutableTreeNode.getUserObject()).getThreadId())); } // Fire insertions /* int[] childChanges = new int[addedSet.size()]; int i = 0; for (Iterator iterator = addedSet.iterator(); iterator.hasNext();) { DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) iterator.next(); childChanges[i++] = root.getIndex(defaultMutableTreeNode); } this.treeModel.nodesWereInserted(root, childChanges); */ //this.treeModel.nodeStructureChanged(root); this.threadTree.repaint(); } catch(Exception e) { ErrorManager.getDefault().notify(e); } } /** * Shows the status of a thread in the tree node icon. */ public static class ThreadTreeCellRenderer extends DefaultTreeCellRenderer { public ThreadTreeCellRenderer() { setOpenIcon(threadIcon); setClosedIcon(threadIcon); setLeafIcon(stackElementIcon); } public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { Object userObject = ((DefaultMutableTreeNode)value).getUserObject(); boolean isThread = false; String description = null; Icon icon = null; if (userObject instanceof ThreadInfo) { ThreadInfo threadInfo = (ThreadInfo) userObject; description = threadInfo.getThreadId() + " - " + threadInfo.getThreadName() + " (" + threadInfo.getThreadState() + ")"; isThread = true; if (threadInfo.getThreadState().equals(ThreadState.RUNNABLE) || threadInfo.getThreadState().equals(ThreadState.RUNNABLE_IN_NATIVE)) { icon = threadRunningIcon; } else if (threadInfo.getThreadState().equals(ThreadState.WAITING) || threadInfo.getThreadState().equals(ThreadState.WAITING_IO)) { icon = threadWaitingIcon; } else if (threadInfo.getThreadState().equals(ThreadState.BLOCKED)) { icon = threadBlockedIcon; } else if (threadInfo.getThreadState().equals(ThreadState.TERMINATED)) { icon = threadTerminatedIcon; } else { icon = threadIcon; } } else if (userObject instanceof StackTraceElement) { description = userObject.toString(); isThread = false; icon = stackElementIcon; } Component component = super.getTreeCellRendererComponent(tree, description, sel, expanded, !isThread, row, hasFocus); setIcon(icon); return component; } private static Icon threadIcon = createImageIcon("images/Thread.gif"); private static Icon threadRunningIcon = createImageIcon("images/ThreadRunning.gif"); private static Icon threadWaitingIcon = createImageIcon("images/ThreadWaiting.gif"); private static Icon threadBlockedIcon = createImageIcon("images/ThreadBlocked.gif"); private static Icon threadTerminatedIcon = createImageIcon("images/ThreadTerminated.gif"); private static Icon stackElementIcon = createImageIcon("images/StackElement.gif"); /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path) { java.net.URL imgURL = ConfigurationTreeComponent.class.getClassLoader().getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn't find file: " + path); return null; } } } } |