1 /* 2 * Copyright (c) 1998, 2011, 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 /* 27 * This source code is provided to illustrate the usage of a given feature 28 * or technique and has been deliberately simplified. Additional steps 29 * required for a production-quality application, such as security checks, 30 * input validation and proper error handling, might not be present in 31 * this sample code. 32 */ 33 34 35 package com.sun.tools.example.debug.gui; 36 37 import java.util.*; 38 39 import javax.swing.*; 40 import javax.swing.tree.*; 41 import java.awt.*; 42 import java.awt.event.*; 43 44 import com.sun.jdi.*; 45 import com.sun.tools.example.debug.event.*; 46 import com.sun.tools.example.debug.bdi.*; 47 48 public class ClassTreeTool extends JPanel { 49 50 private static final long serialVersionUID = 526178912591739259L; 51 52 private Environment env; 53 54 private ExecutionManager runtime; 55 private SourceManager sourceManager; 56 private ClassManager classManager; 57 58 private JTree tree; 59 private DefaultTreeModel treeModel; 60 private ClassTreeNode root; 61 // private SearchPath sourcePath; 62 63 private CommandInterpreter interpreter; 64 65 private static String HEADING = "CLASSES"; 66 67 public ClassTreeTool(Environment env) { 68 69 super(new BorderLayout()); 70 71 this.env = env; 72 this.runtime = env.getExecutionManager(); 73 this.sourceManager = env.getSourceManager(); 74 75 this.interpreter = new CommandInterpreter(env); 76 77 root = createClassTree(HEADING); 78 treeModel = new DefaultTreeModel(root); 79 80 // Create a tree that allows one selection at a time. 81 82 tree = new JTree(treeModel); 83 tree.setSelectionModel(new SingleLeafTreeSelectionModel()); 84 85 /****** 86 // Listen for when the selection changes. 87 tree.addTreeSelectionListener(new TreeSelectionListener() { 88 public void valueChanged(TreeSelectionEvent e) { 89 ClassTreeNode node = (ClassTreeNode) 90 (e.getPath().getLastPathComponent()); 91 if (node != null) { 92 interpreter.executeCommand("view " + node.getReferenceTypeName()); 93 } 94 } 95 }); 96 ******/ 97 98 MouseListener ml = new MouseAdapter() { 99 @Override 100 public void mouseClicked(MouseEvent e) { 101 int selRow = tree.getRowForLocation(e.getX(), e.getY()); 102 TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); 103 if(selRow != -1) { 104 if(e.getClickCount() == 1) { 105 ClassTreeNode node = 106 (ClassTreeNode)selPath.getLastPathComponent(); 107 // If user clicks on leaf, select it, and issue 'view' command. 108 if (node.isLeaf()) { 109 tree.setSelectionPath(selPath); 110 interpreter.executeCommand("view " + node.getReferenceTypeName()); 111 } 112 } 113 } 114 } 115 }; 116 tree.addMouseListener(ml); 117 118 JScrollPane treeView = new JScrollPane(tree); 119 add(treeView); 120 121 // Create listener. 122 ClassTreeToolListener listener = new ClassTreeToolListener(); 123 runtime.addJDIListener(listener); 124 runtime.addSessionListener(listener); 125 126 //### remove listeners on exit! 127 } 128 129 private class ClassTreeToolListener extends JDIAdapter 130 implements JDIListener, SessionListener { 131 132 // SessionListener 133 134 @Override 135 public void sessionStart(EventObject e) { 136 // Get system classes and any others loaded before attaching. 137 try { 138 for (ReferenceType type : runtime.allClasses()) { 139 root.addClass(type); 140 } 141 } catch (VMDisconnectedException ee) { 142 // VM terminated unexpectedly. 143 } catch (NoSessionException ee) { 144 // Ignore. Should not happen. 145 } 146 } 147 148 @Override 149 public void sessionInterrupt(EventObject e) {} 150 @Override 151 public void sessionContinue(EventObject e) {} 152 153 // JDIListener 154 155 @Override 156 public void classPrepare(ClassPrepareEventSet e) { 157 root.addClass(e.getReferenceType()); 158 } 159 160 @Override 161 public void classUnload(ClassUnloadEventSet e) { 162 root.removeClass(e.getClassName()); 163 } 164 165 @Override 166 public void vmDisconnect(VMDisconnectEventSet e) { 167 // Clear contents of this view. 168 root = createClassTree(HEADING); 169 treeModel = new DefaultTreeModel(root); 170 tree.setModel(treeModel); 171 } 172 } 173 174 ClassTreeNode createClassTree(String label) { 175 return new ClassTreeNode(label, null); 176 } 177 178 class ClassTreeNode extends DefaultMutableTreeNode { 179 180 private String name; 181 private ReferenceType refTy; // null for package 182 183 ClassTreeNode(String name, ReferenceType refTy) { 184 this.name = name; 185 this.refTy = refTy; 186 } 187 188 @Override 189 public String toString() { 190 return name; 191 } 192 193 public ReferenceType getReferenceType() { 194 return refTy; 195 } 196 197 public String getReferenceTypeName() { 198 return refTy.name(); 199 } 200 201 private boolean isPackage() { 202 return (refTy == null); 203 } 204 205 @Override 206 public boolean isLeaf() { 207 return !isPackage(); 208 } 209 210 public void addClass(ReferenceType refTy) { 211 addClass(refTy.name(), refTy); 212 } 213 214 private void addClass(String className, ReferenceType refTy) { 215 if (className.equals("")) { 216 return; 217 } 218 int pos = className.indexOf('.'); 219 if (pos < 0) { 220 insertNode(className, refTy); 221 } else { 222 String head = className.substring(0, pos); 223 String tail = className.substring(pos + 1); 224 ClassTreeNode child = insertNode(head, null); 225 child.addClass(tail, refTy); 226 } 227 } 228 229 private ClassTreeNode insertNode(String name, ReferenceType refTy) { 230 for (int i = 0; i < getChildCount(); i++) { 231 ClassTreeNode child = (ClassTreeNode)getChildAt(i); 232 int cmp = name.compareTo(child.toString()); 233 if (cmp == 0) { 234 // like-named node already exists 235 return child; 236 } else if (cmp < 0) { 237 // insert new node before the child 238 ClassTreeNode newChild = new ClassTreeNode(name, refTy); 239 treeModel.insertNodeInto(newChild, this, i); 240 return newChild; 241 } 242 } 243 // insert new node after last child 244 ClassTreeNode newChild = new ClassTreeNode(name, refTy); 245 treeModel.insertNodeInto(newChild, this, getChildCount()); 246 return newChild; 247 } 248 249 public void removeClass(String className) { 250 if (className.equals("")) { 251 return; 252 } 253 int pos = className.indexOf('.'); 254 if (pos < 0) { 255 ClassTreeNode child = findNode(className); 256 if (!isPackage()) { 257 treeModel.removeNodeFromParent(child); 258 } 259 } else { 260 String head = className.substring(0, pos); 261 String tail = className.substring(pos + 1); 262 ClassTreeNode child = findNode(head); 263 child.removeClass(tail); 264 if (isPackage() && child.getChildCount() < 1) { 265 // Prune non-leaf nodes with no children. 266 treeModel.removeNodeFromParent(child); 267 } 268 } 269 } 270 271 private ClassTreeNode findNode(String name) { 272 for (int i = 0; i < getChildCount(); i++) { 273 ClassTreeNode child = (ClassTreeNode)getChildAt(i); 274 int cmp = name.compareTo(child.toString()); 275 if (cmp == 0) { 276 return child; 277 } else if (cmp > 0) { 278 // not found, since children are sorted 279 return null; 280 } 281 } 282 return null; 283 } 284 285 } 286 287 }