Showing the changes to java/pkg/com/sun/tools/example/debug/gui (32 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,74 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import javax.swing.*; | ||
| 29 | import java.awt.*; | ||
| 30 | import java.awt.event.*; | ||
| 31 | |||
| 32 | import com.sun.tools.example.debug.bdi.*; | ||
| 33 | |||
| 34 | public class ApplicationTool extends JPanel { | ||
| 35 | |||
| 36 | private static final long serialVersionUID = 310966063293205714L; | ||
| 37 | |||
| 38 | private ExecutionManager runtime; | ||
| 39 | |||
| 40 | private TypeScript script; | ||
| 41 | |||
| 42 | private static final String PROMPT = "Input:"; | ||
| 43 | |||
| 44 | public ApplicationTool(Environment env) { | ||
| 45 | |||
| 46 | super(new BorderLayout()); | ||
| 47 | |||
| 48 | this.runtime = env.getExecutionManager(); | ||
| 49 | |||
| 50 | this.script = new TypeScript(PROMPT, false); // No implicit echo. | ||
| 51 | this.add(script); | ||
| 52 | |||
| 53 | script.addActionListener(new ActionListener() { | ||
| 54 | @Override | ||
| 55 | public void actionPerformed(ActionEvent e) { | ||
| 56 | runtime.sendLineToApplication(script.readln()); | ||
| 57 | } | ||
| 58 | }); | ||
| 59 | |||
| 60 | runtime.addApplicationEchoListener(new TypeScriptOutputListener(script)); | ||
| 61 | runtime.addApplicationOutputListener(new TypeScriptOutputListener(script)); | ||
| 62 | runtime.addApplicationErrorListener(new TypeScriptOutputListener(script)); | ||
| 63 | |||
| 64 | //### should clean up on exit! | ||
| 65 | |||
| 66 | } | ||
| 67 | |||
| 68 | /****** | ||
| 69 | public void setFont(Font f) { | ||
| 70 | script.setFont(f); | ||
| 71 | } | ||
| 72 | ******/ | ||
| 73 | |||
| 74 | } | ||
| @@ -0,0 +1,64 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | public class ClassManager { | ||
| 29 | |||
| 30 | // This class is provided primarily for symmetry with | ||
| 31 | // SourceManager. Currently, it does very little. | ||
| 32 | // If we add facilities in the future that require that | ||
| 33 | // class files be read outside of the VM, for example, to | ||
| 34 | // provide a disassembled view of a class for bytecode-level | ||
| 35 | // debugging, the required class file management will be done | ||
| 36 | // here. | ||
| 37 | |||
| 38 | private SearchPath classPath; | ||
| 39 | |||
| 40 | public ClassManager(Environment env) { | ||
| 41 | this.classPath = new SearchPath(""); | ||
| 42 | } | ||
| 43 | |||
| 44 | public ClassManager(SearchPath classPath) { | ||
| 45 | this.classPath = classPath; | ||
| 46 | } | ||
| 47 | |||
| 48 | /* | ||
| 49 | * Set path for access to class files. | ||
| 50 | */ | ||
| 51 | |||
| 52 | public void setClassPath(SearchPath sp) { | ||
| 53 | classPath = sp; | ||
| 54 | } | ||
| 55 | |||
| 56 | /* | ||
| 57 | * Get path for access to class files. | ||
| 58 | */ | ||
| 59 | |||
| 60 | public SearchPath getClassPath() { | ||
| 61 | return classPath; | ||
| 62 | } | ||
| 63 | |||
| 64 | } | ||
| @@ -0,0 +1,278 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.util.*; | ||
| 29 | |||
| 30 | import javax.swing.*; | ||
| 31 | import javax.swing.tree.*; | ||
| 32 | import java.awt.*; | ||
| 33 | import java.awt.event.*; | ||
| 34 | |||
| 35 | import com.sun.jdi.*; | ||
| 36 | import com.sun.tools.example.debug.event.*; | ||
| 37 | import com.sun.tools.example.debug.bdi.*; | ||
| 38 | |||
| 39 | public class ClassTreeTool extends JPanel { | ||
| 40 | |||
| 41 | private static final long serialVersionUID = 526178912591739259L; | ||
| 42 | |||
| 43 | private Environment env; | ||
| 44 | |||
| 45 | private ExecutionManager runtime; | ||
| 46 | private SourceManager sourceManager; | ||
| 47 | private ClassManager classManager; | ||
| 48 | |||
| 49 | private JTree tree; | ||
| 50 | private DefaultTreeModel treeModel; | ||
| 51 | private ClassTreeNode root; | ||
| 52 | // private SearchPath sourcePath; | ||
| 53 | |||
| 54 | private CommandInterpreter interpreter; | ||
| 55 | |||
| 56 | private static String HEADING = "CLASSES"; | ||
| 57 | |||
| 58 | public ClassTreeTool(Environment env) { | ||
| 59 | |||
| 60 | super(new BorderLayout()); | ||
| 61 | |||
| 62 | this.env = env; | ||
| 63 | this.runtime = env.getExecutionManager(); | ||
| 64 | this.sourceManager = env.getSourceManager(); | ||
| 65 | |||
| 66 | this.interpreter = new CommandInterpreter(env); | ||
| 67 | |||
| 68 | root = createClassTree(HEADING); | ||
| 69 | treeModel = new DefaultTreeModel(root); | ||
| 70 | |||
| 71 | // Create a tree that allows one selection at a time. | ||
| 72 | |||
| 73 | tree = new JTree(treeModel); | ||
| 74 | tree.setSelectionModel(new SingleLeafTreeSelectionModel()); | ||
| 75 | |||
| 76 | /****** | ||
| 77 | // Listen for when the selection changes. | ||
| 78 | tree.addTreeSelectionListener(new TreeSelectionListener() { | ||
| 79 | public void valueChanged(TreeSelectionEvent e) { | ||
| 80 | ClassTreeNode node = (ClassTreeNode) | ||
| 81 | (e.getPath().getLastPathComponent()); | ||
| 82 | if (node != null) { | ||
| 83 | interpreter.executeCommand("view " + node.getReferenceTypeName()); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | }); | ||
| 87 | ******/ | ||
| 88 | |||
| 89 | MouseListener ml = new MouseAdapter() { | ||
| 90 | @Override | ||
| 91 | public void mouseClicked(MouseEvent e) { | ||
| 92 | int selRow = tree.getRowForLocation(e.getX(), e.getY()); | ||
| 93 | TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); | ||
| 94 | if(selRow != -1) { | ||
| 95 | if(e.getClickCount() == 1) { | ||
| 96 | ClassTreeNode node = | ||
| 97 | (ClassTreeNode)selPath.getLastPathComponent(); | ||
| 98 | // If user clicks on leaf, select it, and issue 'view' command. | ||
| 99 | if (node.isLeaf()) { | ||
| 100 | tree.setSelectionPath(selPath); | ||
| 101 | interpreter.executeCommand("view " + node.getReferenceTypeName()); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
| 106 | }; | ||
| 107 | tree.addMouseListener(ml); | ||
| 108 | |||
| 109 | JScrollPane treeView = new JScrollPane(tree); | ||
| 110 | add(treeView); | ||
| 111 | |||
| 112 | // Create listener. | ||
| 113 | ClassTreeToolListener listener = new ClassTreeToolListener(); | ||
| 114 | runtime.addJDIListener(listener); | ||
| 115 | runtime.addSessionListener(listener); | ||
| 116 | |||
| 117 | //### remove listeners on exit! | ||
| 118 | } | ||
| 119 | |||
| 120 | private class ClassTreeToolListener extends JDIAdapter | ||
| 121 | implements JDIListener, SessionListener { | ||
| 122 | |||
| 123 | // SessionListener | ||
| 124 | |||
| 125 | @Override | ||
| 126 | public void sessionStart(EventObject e) { | ||
| 127 | // Get system classes and any others loaded before attaching. | ||
| 128 | try { | ||
| 129 | for (ReferenceType type : runtime.allClasses()) { | ||
| 130 | root.addClass(type); | ||
| 131 | } | ||
| 132 | } catch (VMDisconnectedException ee) { | ||
| 133 | // VM terminated unexpectedly. | ||
| 134 | } catch (NoSessionException ee) { | ||
| 135 | // Ignore. Should not happen. | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | @Override | ||
| 140 | public void sessionInterrupt(EventObject e) {} | ||
| 141 | @Override | ||
| 142 | public void sessionContinue(EventObject e) {} | ||
| 143 | |||
| 144 | // JDIListener | ||
| 145 | |||
| 146 | @Override | ||
| 147 | public void classPrepare(ClassPrepareEventSet e) { | ||
| 148 | root.addClass(e.getReferenceType()); | ||
| 149 | } | ||
| 150 | |||
| 151 | @Override | ||
| 152 | public void classUnload(ClassUnloadEventSet e) { | ||
| 153 | root.removeClass(e.getClassName()); | ||
| 154 | } | ||
| 155 | |||
| 156 | @Override | ||
| 157 | public void vmDisconnect(VMDisconnectEventSet e) { | ||
| 158 | // Clear contents of this view. | ||
| 159 | root = createClassTree(HEADING); | ||
| 160 | treeModel = new DefaultTreeModel(root); | ||
| 161 | tree.setModel(treeModel); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | ClassTreeNode createClassTree(String label) { | ||
| 166 | return new ClassTreeNode(label, null); | ||
| 167 | } | ||
| 168 | |||
| 169 | class ClassTreeNode extends DefaultMutableTreeNode { | ||
| 170 | |||
| 171 | private String name; | ||
| 172 | private ReferenceType refTy; // null for package | ||
| 173 | |||
| 174 | ClassTreeNode(String name, ReferenceType refTy) { | ||
| 175 | this.name = name; | ||
| 176 | this.refTy = refTy; | ||
| 177 | } | ||
| 178 | |||
| 179 | @Override | ||
| 180 | public String toString() { | ||
| 181 | return name; | ||
| 182 | } | ||
| 183 | |||
| 184 | public ReferenceType getReferenceType() { | ||
| 185 | return refTy; | ||
| 186 | } | ||
| 187 | |||
| 188 | public String getReferenceTypeName() { | ||
| 189 | return refTy.name(); | ||
| 190 | } | ||
| 191 | |||
| 192 | private boolean isPackage() { | ||
| 193 | return (refTy == null); | ||
| 194 | } | ||
| 195 | |||
| 196 | @Override | ||
| 197 | public boolean isLeaf() { | ||
| 198 | return !isPackage(); | ||
| 199 | } | ||
| 200 | |||
| 201 | public void addClass(ReferenceType refTy) { | ||
| 202 | addClass(refTy.name(), refTy); | ||
| 203 | } | ||
| 204 | |||
| 205 | private void addClass(String className, ReferenceType refTy) { | ||
| 206 | if (className.equals("")) { | ||
| 207 | return; | ||
| 208 | } | ||
| 209 | int pos = className.indexOf('.'); | ||
| 210 | if (pos < 0) { | ||
| 211 | insertNode(className, refTy); | ||
| 212 | } else { | ||
| 213 | String head = className.substring(0, pos); | ||
| 214 | String tail = className.substring(pos + 1); | ||
| 215 | ClassTreeNode child = insertNode(head, null); | ||
| 216 | child.addClass(tail, refTy); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | private ClassTreeNode insertNode(String name, ReferenceType refTy) { | ||
| 221 | for (int i = 0; i < getChildCount(); i++) { | ||
| 222 | ClassTreeNode child = (ClassTreeNode)getChildAt(i); | ||
| 223 | int cmp = name.compareTo(child.toString()); | ||
| 224 | if (cmp == 0) { | ||
| 225 | // like-named node already exists | ||
| 226 | return child; | ||
| 227 | } else if (cmp < 0) { | ||
| 228 | // insert new node before the child | ||
| 229 | ClassTreeNode newChild = new ClassTreeNode(name, refTy); | ||
| 230 | treeModel.insertNodeInto(newChild, this, i); | ||
| 231 | return newChild; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | // insert new node after last child | ||
| 235 | ClassTreeNode newChild = new ClassTreeNode(name, refTy); | ||
| 236 | treeModel.insertNodeInto(newChild, this, getChildCount()); | ||
| 237 | return newChild; | ||
| 238 | } | ||
| 239 | |||
| 240 | public void removeClass(String className) { | ||
| 241 | if (className.equals("")) { | ||
| 242 | return; | ||
| 243 | } | ||
| 244 | int pos = className.indexOf('.'); | ||
| 245 | if (pos < 0) { | ||
| 246 | ClassTreeNode child = findNode(className); | ||
| 247 | if (!isPackage()) { | ||
| 248 | treeModel.removeNodeFromParent(child); | ||
| 249 | } | ||
| 250 | } else { | ||
| 251 | String head = className.substring(0, pos); | ||
| 252 | String tail = className.substring(pos + 1); | ||
| 253 | ClassTreeNode child = findNode(head); | ||
| 254 | child.removeClass(tail); | ||
| 255 | if (isPackage() && child.getChildCount() < 1) { | ||
| 256 | // Prune non-leaf nodes with no children. | ||
| 257 | treeModel.removeNodeFromParent(child); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | private ClassTreeNode findNode(String name) { | ||
| 263 | for (int i = 0; i < getChildCount(); i++) { | ||
| 264 | ClassTreeNode child = (ClassTreeNode)getChildAt(i); | ||
| 265 | int cmp = name.compareTo(child.toString()); | ||
| 266 | if (cmp == 0) { | ||
| 267 | return child; | ||
| 268 | } else if (cmp > 0) { | ||
| 269 | // not found, since children are sorted | ||
| 270 | return null; | ||
| 271 | } | ||
| 272 | } | ||
| 273 | return null; | ||
| 274 | } | ||
| 275 | |||
| 276 | } | ||
| 277 | |||
| 278 | } | ||
| @@ -0,0 +1,1459 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.util.*; | ||
| 30 | |||
| 31 | import com.sun.jdi.*; | ||
| 32 | import com.sun.tools.example.debug.bdi.*; | ||
| 33 | |||
| 34 | public class CommandInterpreter { | ||
| 35 | |||
| 36 | boolean echo; | ||
| 37 | |||
| 38 | Environment env; | ||
| 39 | |||
| 40 | private ContextManager context; | ||
| 41 | private ExecutionManager runtime; | ||
| 42 | private ClassManager classManager; | ||
| 43 | private SourceManager sourceManager; | ||
| 44 | |||
| 45 | private OutputSink out; //### Hack! Should be local in each method used. | ||
| 46 | private String lastCommand = "help"; | ||
| 47 | |||
| 48 | public CommandInterpreter(Environment env) { | ||
| 49 | this(env, true); | ||
| 50 | } | ||
| 51 | |||
| 52 | public CommandInterpreter(Environment env, boolean echo) { | ||
| 53 | this.env = env; | ||
| 54 | this.echo = echo; | ||
| 55 | this.runtime = env.getExecutionManager(); | ||
| 56 | this.context = env.getContextManager(); | ||
| 57 | this.classManager = env.getClassManager(); | ||
| 58 | this.sourceManager = env.getSourceManager(); | ||
| 59 | } | ||
| 60 | |||
| 61 | private ThreadReference[] threads = null; | ||
| 62 | |||
| 63 | /* | ||
| 64 | * The numbering of threads is relative to the current set of threads, | ||
| 65 | * and may be affected by the creation and termination of new threads. | ||
| 66 | * Commands issued using such thread ids will only give reliable behavior | ||
| 67 | * relative to what was shown earlier in 'list' commands if the VM is interrupted. | ||
| 68 | * We need a better scheme. | ||
| 69 | */ | ||
| 70 | |||
| 71 | private ThreadReference[] threads() throws NoSessionException { | ||
| 72 | if (threads == null) { | ||
| 73 | ThreadIterator ti = new ThreadIterator(getDefaultThreadGroup()); | ||
| 74 | List<ThreadReference> tlist = new ArrayList<ThreadReference>(); | ||
| 75 | while (ti.hasNext()) { | ||
| 76 | tlist.add(ti.nextThread()); | ||
| 77 | } | ||
| 78 | threads = tlist.toArray(new ThreadReference[tlist.size()]); | ||
| 79 | } | ||
| 80 | return threads; | ||
| 81 | } | ||
| 82 | |||
| 83 | private ThreadReference findThread(String idToken) throws NoSessionException { | ||
| 84 | String id; | ||
| 85 | ThreadReference thread = null; | ||
| 86 | if (idToken.startsWith("t@")) { | ||
| 87 | id = idToken.substring(2); | ||
| 88 | } else { | ||
| 89 | id = idToken; | ||
| 90 | } | ||
| 91 | try { | ||
| 92 | ThreadReference[] threads = threads(); | ||
| 93 | long threadID = Long.parseLong(id, 16); | ||
| 94 | for (ThreadReference thread2 : threads) { | ||
| 95 | if (thread2.uniqueID() == threadID) { | ||
| 96 | thread = thread2; | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | if (thread == null) { | ||
| 101 | //env.failure("No thread for id \"" + idToken + "\""); | ||
| 102 | env.failure("\"" + idToken + "\" is not a valid thread id."); | ||
| 103 | } | ||
| 104 | } catch (NumberFormatException e) { | ||
| 105 | env.error("Thread id \"" + idToken + "\" is ill-formed."); | ||
| 106 | thread = null; | ||
| 107 | } | ||
| 108 | return thread; | ||
| 109 | } | ||
| 110 | |||
| 111 | private ThreadIterator allThreads() throws NoSessionException { | ||
| 112 | threads = null; | ||
| 113 | //### Why not use runtime.allThreads().iterator() ? | ||
| 114 | return new ThreadIterator(runtime.topLevelThreadGroups()); | ||
| 115 | } | ||
| 116 | |||
| 117 | private ThreadIterator currentThreadGroupThreads() throws NoSessionException { | ||
| 118 | threads = null; | ||
| 119 | return new ThreadIterator(getDefaultThreadGroup()); | ||
| 120 | } | ||
| 121 | |||
| 122 | private ThreadGroupIterator allThreadGroups() throws NoSessionException { | ||
| 123 | threads = null; | ||
| 124 | return new ThreadGroupIterator(runtime.topLevelThreadGroups()); | ||
| 125 | } | ||
| 126 | |||
| 127 | private ThreadGroupReference defaultThreadGroup; | ||
| 128 | |||
| 129 | private ThreadGroupReference getDefaultThreadGroup() throws NoSessionException { | ||
| 130 | if (defaultThreadGroup == null) { | ||
| 131 | defaultThreadGroup = runtime.systemThreadGroup(); | ||
| 132 | } | ||
| 133 | return defaultThreadGroup; | ||
| 134 | } | ||
| 135 | |||
| 136 | private void setDefaultThreadGroup(ThreadGroupReference tg) { | ||
| 137 | defaultThreadGroup = tg; | ||
| 138 | } | ||
| 139 | |||
| 140 | /* | ||
| 141 | * Command handlers. | ||
| 142 | */ | ||
| 143 | |||
| 144 | // Command: classes | ||
| 145 | |||
| 146 | private void commandClasses() throws NoSessionException { | ||
| 147 | OutputSink out = env.getOutputSink(); | ||
| 148 | //out.println("** classes list **"); | ||
| 149 | for (ReferenceType refType : runtime.allClasses()) { | ||
| 150 | out.println(refType.name()); | ||
| 151 | } | ||
| 152 | out.show(); | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | // Command: methods | ||
| 157 | |||
| 158 | private void commandMethods(StringTokenizer t) throws NoSessionException { | ||
| 159 | if (!t.hasMoreTokens()) { | ||
| 160 | env.error("No class specified."); | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | String idClass = t.nextToken(); | ||
| 164 | ReferenceType cls = findClass(idClass); | ||
| 165 | if (cls != null) { | ||
| 166 | List<Method> methods = cls.allMethods(); | ||
| 167 | OutputSink out = env.getOutputSink(); | ||
| 168 | for (int i = 0; i < methods.size(); i++) { | ||
| 169 | Method method = methods.get(i); | ||
| 170 | out.print(method.declaringType().name() + " " + | ||
| 171 | method.name() + "("); | ||
| 172 | Iterator<String> it = method.argumentTypeNames().iterator(); | ||
| 173 | if (it.hasNext()) { | ||
| 174 | while (true) { | ||
| 175 | out.print(it.next()); | ||
| 176 | if (!it.hasNext()) { | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | out.print(", "); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | out.println(")"); | ||
| 183 | } | ||
| 184 | out.show(); | ||
| 185 | } else { | ||
| 186 | //### Should validate class name syntax. | ||
| 187 | env.failure("\"" + idClass + "\" is not a valid id or class name."); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | private ReferenceType findClass(String pattern) throws NoSessionException { | ||
| 192 | List<ReferenceType> results = runtime.findClassesMatchingPattern(pattern); | ||
| 193 | if (results.size() > 0) { | ||
| 194 | //### Should handle multiple results sensibly. | ||
| 195 | return results.get(0); | ||
| 196 | } | ||
| 197 | return null; | ||
| 198 | } | ||
| 199 | |||
| 200 | // Command: threads | ||
| 201 | |||
| 202 | private void commandThreads(StringTokenizer t) throws NoSessionException { | ||
| 203 | if (!t.hasMoreTokens()) { | ||
| 204 | OutputSink out = env.getOutputSink(); | ||
| 205 | printThreadGroup(out, getDefaultThreadGroup(), 0); | ||
| 206 | out.show(); | ||
| 207 | return; | ||
| 208 | } | ||
| 209 | String name = t.nextToken(); | ||
| 210 | ThreadGroupReference tg = findThreadGroup(name); | ||
| 211 | if (tg == null) { | ||
| 212 | env.failure(name + " is not a valid threadgroup name."); | ||
| 213 | } else { | ||
| 214 | OutputSink out = env.getOutputSink(); | ||
| 215 | printThreadGroup(out, tg, 0); | ||
| 216 | out.show(); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | private ThreadGroupReference findThreadGroup(String name) throws NoSessionException { | ||
| 221 | //### Issue: Uniqueness of thread group names is not enforced. | ||
| 222 | ThreadGroupIterator tgi = allThreadGroups(); | ||
| 223 | while (tgi.hasNext()) { | ||
| 224 | ThreadGroupReference tg = tgi.nextThreadGroup(); | ||
| 225 | if (tg.name().equals(name)) { | ||
| 226 | return tg; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | return null; | ||
| 230 | } | ||
| 231 | |||
| 232 | private int printThreadGroup(OutputSink out, ThreadGroupReference tg, int iThread) { | ||
| 233 | out.println("Group " + tg.name() + ":"); | ||
| 234 | List<ThreadReference> tlist = tg.threads(); | ||
| 235 | int maxId = 0; | ||
| 236 | int maxName = 0; | ||
| 237 | for (int i = 0 ; i < tlist.size() ; i++) { | ||
| 238 | ThreadReference thr = tlist.get(i); | ||
| 239 | int len = Utils.description(thr).length(); | ||
| 240 | if (len > maxId) { | ||
| 241 | maxId = len; | ||
| 242 | } | ||
| 243 | String name = thr.name(); | ||
| 244 | int iDot = name.lastIndexOf('.'); | ||
| 245 | if (iDot >= 0 && name.length() > iDot) { | ||
| 246 | name = name.substring(iDot + 1); | ||
| 247 | } | ||
| 248 | if (name.length() > maxName) { | ||
| 249 | maxName = name.length(); | ||
| 250 | } | ||
| 251 | } | ||
| 252 | String maxNumString = String.valueOf(iThread + tlist.size()); | ||
| 253 | int maxNumDigits = maxNumString.length(); | ||
| 254 | for (int i = 0 ; i < tlist.size() ; i++) { | ||
| 255 | ThreadReference thr = tlist.get(i); | ||
| 256 | char buf[] = new char[80]; | ||
| 257 | for (int j = 0; j < 79; j++) { | ||
| 258 | buf[j] = ' '; | ||
| 259 | } | ||
| 260 | buf[79] = '\0'; | ||
| 261 | StringBuffer sbOut = new StringBuffer(); | ||
| 262 | sbOut.append(buf); | ||
| 263 | |||
| 264 | // Right-justify the thread number at start of output string | ||
| 265 | String numString = String.valueOf(iThread + i + 1); | ||
| 266 | sbOut.insert(maxNumDigits - numString.length(), | ||
| 267 | numString); | ||
| 268 | sbOut.insert(maxNumDigits, "."); | ||
| 269 | |||
| 270 | int iBuf = maxNumDigits + 2; | ||
| 271 | sbOut.insert(iBuf, Utils.description(thr)); | ||
| 272 | iBuf += maxId + 1; | ||
| 273 | String name = thr.name(); | ||
| 274 | int iDot = name.lastIndexOf('.'); | ||
| 275 | if (iDot >= 0 && name.length() > iDot) { | ||
| 276 | name = name.substring(iDot + 1); | ||
| 277 | } | ||
| 278 | sbOut.insert(iBuf, name); | ||
| 279 | iBuf += maxName + 1; | ||
| 280 | sbOut.insert(iBuf, Utils.getStatus(thr)); | ||
| 281 | sbOut.setLength(79); | ||
| 282 | out.println(sbOut.toString()); | ||
| 283 | } | ||
| 284 | for (ThreadGroupReference tg0 : tg.threadGroups()) { | ||
| 285 | if (!tg.equals(tg0)) { // TODO ref mgt | ||
| 286 | iThread += printThreadGroup(out, tg0, iThread + tlist.size()); | ||
| 287 | } | ||
| 288 | } | ||
| 289 | return tlist.size(); | ||
| 290 | } | ||
| 291 | |||
| 292 | // Command: threadgroups | ||
| 293 | |||
| 294 | private void commandThreadGroups() throws NoSessionException { | ||
| 295 | ThreadGroupIterator it = allThreadGroups(); | ||
| 296 | int cnt = 0; | ||
| 297 | OutputSink out = env.getOutputSink(); | ||
| 298 | while (it.hasNext()) { | ||
| 299 | ThreadGroupReference tg = it.nextThreadGroup(); | ||
| 300 | ++cnt; | ||
| 301 | out.println("" + cnt + ". " + Utils.description(tg) + " " + tg.name()); | ||
| 302 | } | ||
| 303 | out.show(); | ||
| 304 | } | ||
| 305 | |||
| 306 | // Command: thread | ||
| 307 | |||
| 308 | private void commandThread(StringTokenizer t) throws NoSessionException { | ||
| 309 | if (!t.hasMoreTokens()) { | ||
| 310 | env.error("Thread number not specified."); | ||
| 311 | return; | ||
| 312 | } | ||
| 313 | ThreadReference thread = findThread(t.nextToken()); | ||
| 314 | if (thread != null) { | ||
| 315 | //### Should notify user. | ||
| 316 | context.setCurrentThread(thread); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | // Command: threadgroup | ||
| 321 | |||
| 322 | private void commandThreadGroup(StringTokenizer t) throws NoSessionException { | ||
| 323 | if (!t.hasMoreTokens()) { | ||
| 324 | env.error("Threadgroup name not specified."); | ||
| 325 | return; | ||
| 326 | } | ||
| 327 | String name = t.nextToken(); | ||
| 328 | ThreadGroupReference tg = findThreadGroup(name); | ||
| 329 | if (tg == null) { | ||
| 330 | env.failure(name + " is not a valid threadgroup name."); | ||
| 331 | } else { | ||
| 332 | //### Should notify user. | ||
| 333 | setDefaultThreadGroup(tg); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | // Command: run | ||
| 338 | |||
| 339 | private void commandRun(StringTokenizer t) throws NoSessionException { | ||
| 340 | if (doLoad(false, t)) { | ||
| 341 | env.notice("Running ..."); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | // Command: load | ||
| 346 | |||
| 347 | private void commandLoad(StringTokenizer t) throws NoSessionException { | ||
| 348 | if (doLoad(true, t)) {} | ||
| 349 | } | ||
| 350 | |||
| 351 | private boolean doLoad(boolean suspended, | ||
| 352 | StringTokenizer t) throws NoSessionException { | ||
| 353 | |||
| 354 | String clname; | ||
| 355 | |||
| 356 | if (!t.hasMoreTokens()) { | ||
| 357 | clname = context.getMainClassName(); | ||
| 358 | if (!clname.equals("")) { | ||
| 359 | // Run from prevously-set class name. | ||
| 360 | try { | ||
| 361 | String vmArgs = context.getVmArguments(); | ||
| 362 | runtime.run(suspended, | ||
| 363 | vmArgs, | ||
| 364 | clname, | ||
| 365 | context.getProgramArguments()); | ||
| 366 | return true; | ||
| 367 | } catch (VMLaunchFailureException e) { | ||
| 368 | env.failure("Attempt to launch main class \"" + clname + "\" failed."); | ||
| 369 | } | ||
| 370 | } else { | ||
| 371 | env.failure("No main class specifed and no current default defined."); | ||
| 372 | } | ||
| 373 | } else { | ||
| 374 | clname = t.nextToken(); | ||
| 375 | StringBuffer sbuf = new StringBuffer(); | ||
| 376 | // Allow VM arguments to be specified here? | ||
| 377 | while (t.hasMoreTokens()) { | ||
| 378 | String tok = t.nextToken(); | ||
| 379 | sbuf.append(tok); | ||
| 380 | if (t.hasMoreTokens()) { | ||
| 381 | sbuf.append(' '); | ||
| 382 | } | ||
| 383 | } | ||
| 384 | String args = sbuf.toString(); | ||
| 385 | try { | ||
| 386 | String vmArgs = context.getVmArguments(); | ||
| 387 | runtime.run(suspended, vmArgs, clname, args); | ||
| 388 | context.setMainClassName(clname); | ||
| 389 | //context.setVmArguments(vmArgs); | ||
| 390 | context.setProgramArguments(args); | ||
| 391 | return true; | ||
| 392 | } catch (VMLaunchFailureException e) { | ||
| 393 | env.failure("Attempt to launch main class \"" + clname + "\" failed."); | ||
| 394 | } | ||
| 395 | } | ||
| 396 | return false; | ||
| 397 | } | ||
| 398 | |||
| 399 | // Command: connect | ||
| 400 | |||
| 401 | private void commandConnect(StringTokenizer t) { | ||
| 402 | try { | ||
| 403 | LaunchTool.queryAndLaunchVM(runtime); | ||
| 404 | } catch (VMLaunchFailureException e) { | ||
| 405 | env.failure("Attempt to connect failed."); | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | // Command: attach | ||
| 410 | |||
| 411 | private void commandAttach(StringTokenizer t) { | ||
| 412 | String portName; | ||
| 413 | if (!t.hasMoreTokens()) { | ||
| 414 | portName = context.getRemotePort(); | ||
| 415 | if (!portName.equals("")) { | ||
| 416 | try { | ||
| 417 | runtime.attach(portName); | ||
| 418 | } catch (VMLaunchFailureException e) { | ||
| 419 | env.failure("Attempt to attach to port \"" + portName + "\" failed."); | ||
| 420 | } | ||
| 421 | } else { | ||
| 422 | env.failure("No port specifed and no current default defined."); | ||
| 423 | } | ||
| 424 | } else { | ||
| 425 | portName = t.nextToken(); | ||
| 426 | try { | ||
| 427 | runtime.attach(portName); | ||
| 428 | } catch (VMLaunchFailureException e) { | ||
| 429 | env.failure("Attempt to attach to port \"" + portName + "\" failed."); | ||
| 430 | } | ||
| 431 | context.setRemotePort(portName); | ||
| 432 | } | ||
| 433 | } | ||
| 434 | |||
| 435 | // Command: detach | ||
| 436 | |||
| 437 | private void commandDetach(StringTokenizer t) throws NoSessionException { | ||
| 438 | runtime.detach(); | ||
| 439 | } | ||
| 440 | |||
| 441 | // Command: interrupt | ||
| 442 | |||
| 443 | private void commandInterrupt(StringTokenizer t) throws NoSessionException { | ||
| 444 | runtime.interrupt(); | ||
| 445 | } | ||
| 446 | |||
| 447 | // Command: suspend | ||
| 448 | |||
| 449 | private void commandSuspend(StringTokenizer t) throws NoSessionException { | ||
| 450 | if (!t.hasMoreTokens()) { | ||
| 451 | // Suspend all threads in the current thread group. | ||
| 452 | //### Issue: help message says default is all threads. | ||
| 453 | //### Behavior here agrees with 'jdb', however. | ||
| 454 | ThreadIterator ti = currentThreadGroupThreads(); | ||
| 455 | while (ti.hasNext()) { | ||
| 456 | // TODO - don't suspend debugger threads | ||
| 457 | ti.nextThread().suspend(); | ||
| 458 | } | ||
| 459 | env.notice("All (non-system) threads suspended."); | ||
| 460 | } else { | ||
| 461 | while (t.hasMoreTokens()) { | ||
| 462 | ThreadReference thread = findThread(t.nextToken()); | ||
| 463 | if (thread != null) { | ||
| 464 | //thread.suspend(); | ||
| 465 | runtime.suspendThread(thread); | ||
| 466 | } | ||
| 467 | } | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | // Command: resume | ||
| 472 | |||
| 473 | private void commandResume(StringTokenizer t) throws NoSessionException { | ||
| 474 | if (!t.hasMoreTokens()) { | ||
| 475 | // Suspend all threads in the current thread group. | ||
| 476 | //### Issue: help message says default is all threads. | ||
| 477 | //### Behavior here agrees with 'jdb', however. | ||
| 478 | ThreadIterator ti = currentThreadGroupThreads(); | ||
| 479 | while (ti.hasNext()) { | ||
| 480 | // TODO - don't suspend debugger threads | ||
| 481 | ti.nextThread().resume(); | ||
| 482 | } | ||
| 483 | env.notice("All threads resumed."); | ||
| 484 | } else { | ||
| 485 | while (t.hasMoreTokens()) { | ||
| 486 | ThreadReference thread = findThread(t.nextToken()); | ||
| 487 | if (thread != null) { | ||
| 488 | //thread.resume(); | ||
| 489 | runtime.resumeThread(thread); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | } | ||
| 493 | } | ||
| 494 | |||
| 495 | // Command: cont | ||
| 496 | |||
| 497 | private void commandCont() throws NoSessionException { | ||
| 498 | try { | ||
| 499 | runtime.go(); | ||
| 500 | } catch (VMNotInterruptedException e) { | ||
| 501 | //### failure? | ||
| 502 | env.notice("Target VM is already running."); | ||
| 503 | } | ||
| 504 | } | ||
| 505 | |||
| 506 | // Command: step | ||
| 507 | |||
| 508 | private void commandStep(StringTokenizer t) throws NoSessionException{ | ||
| 509 | ThreadReference current = context.getCurrentThread(); | ||
| 510 | if (current == null) { | ||
| 511 | env.failure("No current thread."); | ||
| 512 | return; | ||
| 513 | } | ||
| 514 | try { | ||
| 515 | if (t.hasMoreTokens() && | ||
| 516 | t.nextToken().toLowerCase().equals("up")) { | ||
| 517 | runtime.stepOut(current); | ||
| 518 | } else { | ||
| 519 | runtime.stepIntoLine(current); | ||
| 520 | } | ||
| 521 | } catch (AbsentInformationException e) { | ||
| 522 | env.failure("No linenumber information available -- " + | ||
| 523 | "Try \"stepi\" to step by instructions."); | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 527 | // Command: stepi | ||
| 528 | |||
| 529 | private void commandStepi() throws NoSessionException { | ||
| 530 | ThreadReference current = context.getCurrentThread(); | ||
| 531 | if (current == null) { | ||
| 532 | env.failure("No current thread."); | ||
| 533 | return; | ||
| 534 | } | ||
| 535 | runtime.stepIntoInstruction(current); | ||
| 536 | } | ||
| 537 | |||
| 538 | // Command: next | ||
| 539 | |||
| 540 | private void commandNext() throws NoSessionException { | ||
| 541 | ThreadReference current = context.getCurrentThread(); | ||
| 542 | if (current == null) { | ||
| 543 | env.failure("No current thread."); | ||
| 544 | return; | ||
| 545 | } | ||
| 546 | try { | ||
| 547 | runtime.stepOverLine(current); | ||
| 548 | } catch (AbsentInformationException e) { | ||
| 549 | env.failure("No linenumber information available -- " + | ||
| 550 | "Try \"nexti\" to step by instructions."); | ||
| 551 | } | ||
| 552 | } | ||
| 553 | |||
| 554 | // Command: nexti (NEW) | ||
| 555 | |||
| 556 | private void commandNexti() throws NoSessionException { | ||
| 557 | ThreadReference current = context.getCurrentThread(); | ||
| 558 | if (current == null) { | ||
| 559 | env.failure("No current thread."); | ||
| 560 | return; | ||
| 561 | } | ||
| 562 | runtime.stepOverInstruction(current); | ||
| 563 | } | ||
| 564 | |||
| 565 | // Command: kill | ||
| 566 | |||
| 567 | private void commandKill(StringTokenizer t) throws NoSessionException { | ||
| 568 | //### Should change the way in which thread ids and threadgroup names | ||
| 569 | //### are distinguished. | ||
| 570 | if (!t.hasMoreTokens()) { | ||
| 571 | env.error("Usage: kill <threadgroup name> or <thread id>"); | ||
| 572 | return; | ||
| 573 | } | ||
| 574 | while (t.hasMoreTokens()) { | ||
| 575 | String idToken = t.nextToken(); | ||
| 576 | ThreadReference thread = findThread(idToken); | ||
| 577 | if (thread != null) { | ||
| 578 | runtime.stopThread(thread); | ||
| 579 | env.notice("Thread " + thread.name() + " killed."); | ||
| 580 | return; | ||
| 581 | } else { | ||
| 582 | /* Check for threadgroup name, NOT skipping "system". */ | ||
| 583 | //### Should skip "system"? Classic 'jdb' does this. | ||
| 584 | //### Should deal with possible non-uniqueness of threadgroup names. | ||
| 585 | ThreadGroupIterator itg = allThreadGroups(); | ||
| 586 | while (itg.hasNext()) { | ||
| 587 | ThreadGroupReference tg = itg.nextThreadGroup(); | ||
| 588 | if (tg.name().equals(idToken)) { | ||
| 589 | ThreadIterator it = new ThreadIterator(tg); | ||
| 590 | while (it.hasNext()) { | ||
| 591 | runtime.stopThread(it.nextThread()); | ||
| 592 | } | ||
| 593 | env.notice("Threadgroup " + tg.name() + "killed."); | ||
| 594 | return; | ||
| 595 | } | ||
| 596 | } | ||
| 597 | env.failure("\"" + idToken + | ||
| 598 | "\" is not a valid threadgroup or id."); | ||
| 599 | } | ||
| 600 | } | ||
| 601 | } | ||
| 602 | |||
| 603 | |||
| 604 | /************* | ||
| 605 | // TODO | ||
| 606 | private void commandCatchException(StringTokenizer t) throws NoSessionException {} | ||
| 607 | // TODO | ||
| 608 | private void commandIgnoreException(StringTokenizer t) throws NoSessionException {} | ||
| 609 | *************/ | ||
| 610 | |||
| 611 | // Command: up | ||
| 612 | |||
| 613 | //### Print current frame after command? | ||
| 614 | |||
| 615 | int readCount(StringTokenizer t) { | ||
| 616 | int cnt = 1; | ||
| 617 | if (t.hasMoreTokens()) { | ||
| 618 | String idToken = t.nextToken(); | ||
| 619 | try { | ||
| 620 | cnt = Integer.valueOf(idToken).intValue(); | ||
| 621 | } catch (NumberFormatException e) { | ||
| 622 | cnt = -1; | ||
| 623 | } | ||
| 624 | } | ||
| 625 | return cnt; | ||
| 626 | } | ||
| 627 | |||
| 628 | void commandUp(StringTokenizer t) throws NoSessionException { | ||
| 629 | ThreadReference current = context.getCurrentThread(); | ||
| 630 | if (current == null) { | ||
| 631 | env.failure("No current thread."); | ||
| 632 | return; | ||
| 633 | } | ||
| 634 | int nLevels = readCount(t); | ||
| 635 | if (nLevels <= 0) { | ||
| 636 | env.error("usage: up [n frames]"); | ||
| 637 | return; | ||
| 638 | } | ||
| 639 | try { | ||
| 640 | int delta = context.moveCurrentFrameIndex(current, -nLevels); | ||
| 641 | if (delta == 0) { | ||
| 642 | env.notice("Already at top of stack."); | ||
| 643 | } else if (-delta < nLevels) { | ||
| 644 | env.notice("Moved up " + delta + " frames to top of stack."); | ||
| 645 | } | ||
| 646 | } catch (VMNotInterruptedException e) { | ||
| 647 | env.failure("Target VM must be in interrupted state."); | ||
| 648 | } | ||
| 649 | } | ||
| 650 | |||
| 651 | private void commandDown(StringTokenizer t) throws NoSessionException { | ||
| 652 | ThreadReference current = context.getCurrentThread(); | ||
| 653 | if (current == null) { | ||
| 654 | env.failure("No current thread."); | ||
| 655 | return; | ||
| 656 | } | ||
| 657 | int nLevels = readCount(t); | ||
| 658 | if (nLevels <= 0) { | ||
| 659 | env.error("usage: down [n frames]"); | ||
| 660 | return; | ||
| 661 | } | ||
| 662 | try { | ||
| 663 | int delta = context.moveCurrentFrameIndex(current, nLevels); | ||
| 664 | if (delta == 0) { | ||
| 665 | env.notice("Already at bottom of stack."); | ||
| 666 | } else if (delta < nLevels) { | ||
| 667 | env.notice("Moved down " + delta + " frames to bottom of stack."); | ||
| 668 | } | ||
| 669 | } catch (VMNotInterruptedException e) { | ||
| 670 | env.failure("Target VM must be in interrupted state."); | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | // Command: frame | ||
| 675 | |||
| 676 | private void commandFrame(StringTokenizer t) throws NoSessionException { | ||
| 677 | ThreadReference current = context.getCurrentThread(); | ||
| 678 | if (current == null) { | ||
| 679 | env.failure("No current thread."); | ||
| 680 | return; | ||
| 681 | } | ||
| 682 | if (!t.hasMoreTokens()) { | ||
| 683 | env.error("usage: frame <frame-index>"); | ||
| 684 | return; | ||
| 685 | } | ||
| 686 | String idToken = t.nextToken(); | ||
| 687 | int n; | ||
| 688 | try { | ||
| 689 | n = Integer.valueOf(idToken).intValue(); | ||
| 690 | } catch (NumberFormatException e) { | ||
| 691 | n = 0; | ||
| 692 | } | ||
| 693 | if (n <= 0) { | ||
| 694 | env.error("use positive frame index"); | ||
| 695 | return; | ||
| 696 | } | ||
| 697 | try { | ||
| 698 | int delta = context.setCurrentFrameIndex(current, n); | ||
| 699 | if (delta == 0) { | ||
| 700 | env.notice("Frame unchanged."); | ||
| 701 | } else if (delta < 0) { | ||
| 702 | env.notice("Moved up " + -delta + " frames."); | ||
| 703 | } else { | ||
| 704 | env.notice("Moved down " + delta + " frames."); | ||
| 705 | } | ||
| 706 | } catch (VMNotInterruptedException e) { | ||
| 707 | env.failure("Target VM must be in interrupted state."); | ||
| 708 | } | ||
| 709 | } | ||
| 710 | |||
| 711 | // Command: where | ||
| 712 | |||
| 713 | //### Should we insist that VM be interrupted here? | ||
| 714 | //### There is an inconsistency between the 'where' command | ||
| 715 | //### and 'up' and 'down' in this respect. | ||
| 716 | |||
| 717 | private void commandWhere(StringTokenizer t, boolean showPC) | ||
| 718 | throws NoSessionException { | ||
| 719 | ThreadReference current = context.getCurrentThread(); | ||
| 720 | if (!t.hasMoreTokens()) { | ||
| 721 | if (current == null) { | ||
| 722 | env.error("No thread specified."); | ||
| 723 | return; | ||
| 724 | } | ||
| 725 | dumpStack(current, showPC); | ||
| 726 | } else { | ||
| 727 | String token = t.nextToken(); | ||
| 728 | if (token.toLowerCase().equals("all")) { | ||
| 729 | ThreadIterator it = allThreads(); | ||
| 730 | while (it.hasNext()) { | ||
| 731 | ThreadReference thread = it.next(); | ||
| 732 | out.println(thread.name() + ": "); | ||
| 733 | dumpStack(thread, showPC); | ||
| 734 | } | ||
| 735 | } else { | ||
| 736 | ThreadReference thread = findThread(t.nextToken()); | ||
| 737 | //### Do we want to set current thread here? | ||
| 738 | //### Should notify user of change. | ||
| 739 | if (thread != null) { | ||
| 740 | context.setCurrentThread(thread); | ||
| 741 | } | ||
| 742 | dumpStack(thread, showPC); | ||
| 743 | } | ||
| 744 | } | ||
| 745 | } | ||
| 746 | |||
| 747 | private void dumpStack(ThreadReference thread, boolean showPC) { | ||
| 748 | //### Check for these. | ||
| 749 | //env.failure("Thread no longer exists."); | ||
| 750 | //env.failure("Target VM must be in interrupted state."); | ||
| 751 | //env.failure("Current thread isn't suspended."); | ||
| 752 | //### Should handle extremely long stack traces sensibly for user. | ||
| 753 | List<StackFrame> stack = null; | ||
| 754 | try { | ||
| 755 | stack = thread.frames(); | ||
| 756 | } catch (IncompatibleThreadStateException e) { | ||
| 757 | env.failure("Thread is not suspended."); | ||
| 758 | } | ||
| 759 | //### Fix this! | ||
| 760 | //### Previously mishandled cases where thread was not current. | ||
| 761 | //### Now, prints all of the stack regardless of current frame. | ||
| 762 | int frameIndex = 0; | ||
| 763 | //int frameIndex = context.getCurrentFrameIndex(); | ||
| 764 | if (stack == null) { | ||
| 765 | env.failure("Thread is not running (no stack)."); | ||
| 766 | } else { | ||
| 767 | OutputSink out = env.getOutputSink(); | ||
| 768 | int nFrames = stack.size(); | ||
| 769 | for (int i = frameIndex; i < nFrames; i++) { | ||
| 770 | StackFrame frame = stack.get(i); | ||
| 771 | Location loc = frame.location(); | ||
| 772 | Method meth = loc.method(); | ||
| 773 | out.print(" [" + (i + 1) + "] "); | ||
| 774 | out.print(meth.declaringType().name()); | ||
| 775 | out.print('.'); | ||
| 776 | out.print(meth.name()); | ||
| 777 | out.print(" ("); | ||
| 778 | if (meth.isNative()) { | ||
| 779 | out.print("native method"); | ||
| 780 | } else if (loc.lineNumber() != -1) { | ||
| 781 | try { | ||
| 782 | out.print(loc.sourceName()); | ||
| 783 | } catch (AbsentInformationException e) { | ||
| 784 | out.print("<unknown>"); | ||
| 785 | } | ||
| 786 | out.print(':'); | ||
| 787 | out.print(loc.lineNumber()); | ||
| 788 | } | ||
| 789 | out.print(')'); | ||
| 790 | if (showPC) { | ||
| 791 | long pc = loc.codeIndex(); | ||
| 792 | if (pc != -1) { | ||
| 793 | out.print(", pc = " + pc); | ||
| 794 | } | ||
| 795 | } | ||
| 796 | out.println(); | ||
| 797 | } | ||
| 798 | out.show(); | ||
| 799 | } | ||
| 800 | } | ||
| 801 | |||
| 802 | private void listEventRequests() throws NoSessionException { | ||
| 803 | // Print set breakpoints | ||
| 804 | List<EventRequestSpec> specs = runtime.eventRequestSpecs(); | ||
| 805 | if (specs.isEmpty()) { | ||
| 806 | env.notice("No breakpoints/watchpoints/exceptions set."); | ||
| 807 | } else { | ||
| 808 | OutputSink out = env.getOutputSink(); | ||
| 809 | out.println("Current breakpoints/watchpoints/exceptions set:"); | ||
| 810 | for (EventRequestSpec bp : specs) { | ||
| 811 | out.println("\t" + bp); | ||
| 812 | } | ||
| 813 | out.show(); | ||
| 814 | } | ||
| 815 | } | ||
| 816 | |||
| 817 | private BreakpointSpec parseBreakpointSpec(String bptSpec) { | ||
| 818 | StringTokenizer t = new StringTokenizer(bptSpec); | ||
| 819 | BreakpointSpec bpSpec = null; | ||
| 820 | // try { | ||
| 821 | String token = t.nextToken("@:( \t\n\r"); | ||
| 822 | // We can't use hasMoreTokens here because it will cause any leading | ||
| 823 | // paren to be lost. | ||
| 824 | String rest; | ||
| 825 | try { | ||
| 826 | rest = t.nextToken("").trim(); | ||
| 827 | } catch (NoSuchElementException e) { | ||
| 828 | rest = null; | ||
| 829 | } | ||
| 830 | if ((rest != null) && rest.startsWith("@")) { | ||
| 831 | t = new StringTokenizer(rest.substring(1)); | ||
| 832 | String sourceName = token; | ||
| 833 | String lineToken = t.nextToken(); | ||
| 834 | int lineNumber = Integer.valueOf(lineToken).intValue(); | ||
| 835 | if (t.hasMoreTokens()) { | ||
| 836 | return null; | ||
| 837 | } | ||
| 838 | bpSpec = runtime.createSourceLineBreakpoint(sourceName, | ||
| 839 | lineNumber); | ||
| 840 | } else if ((rest != null) && rest.startsWith(":")) { | ||
| 841 | t = new StringTokenizer(rest.substring(1)); | ||
| 842 | String classId = token; | ||
| 843 | String lineToken = t.nextToken(); | ||
| 844 | int lineNumber = Integer.valueOf(lineToken).intValue(); | ||
| 845 | if (t.hasMoreTokens()) { | ||
| 846 | return null; | ||
| 847 | } | ||
| 848 | bpSpec = runtime.createClassLineBreakpoint(classId, lineNumber); | ||
| 849 | } else { | ||
| 850 | // Try stripping method from class.method token. | ||
| 851 | int idot = token.lastIndexOf("."); | ||
| 852 | if ( (idot <= 0) || /* No dot or dot in first char */ | ||
| 853 | (idot >= token.length() - 1) ) { /* dot in last char */ | ||
| 854 | return null; | ||
| 855 | } | ||
| 856 | String methodName = token.substring(idot + 1); | ||
| 857 | String classId = token.substring(0, idot); | ||
| 858 | List<String> argumentList = null; | ||
| 859 | if (rest != null) { | ||
| 860 | if (!rest.startsWith("(") || !rest.endsWith(")")) { | ||
| 861 | //### Should throw exception with error message | ||
| 862 | //out.println("Invalid method specification: " | ||
| 863 | // + methodName + rest); | ||
| 864 | return null; | ||
| 865 | } | ||
| 866 | // Trim the parens | ||
| 867 | //### What about spaces in arglist? | ||
| 868 | rest = rest.substring(1, rest.length() - 1); | ||
| 869 | argumentList = new ArrayList<String>(); | ||
| 870 | t = new StringTokenizer(rest, ","); | ||
| 871 | while (t.hasMoreTokens()) { | ||
| 872 | argumentList.add(t.nextToken()); | ||
| 873 | } | ||
| 874 | } | ||
| 875 | bpSpec = runtime.createMethodBreakpoint(classId, | ||
| 876 | methodName, | ||
| 877 | argumentList); | ||
| 878 | } | ||
| 879 | // } catch (Exception e) { | ||
| 880 | // env.error("Exception attempting to create breakpoint: " + e); | ||
| 881 | // return null; | ||
| 882 | // } | ||
| 883 | return bpSpec; | ||
| 884 | } | ||
| 885 | |||
| 886 | private void commandStop(StringTokenizer t) throws NoSessionException { | ||
| 887 | String token; | ||
| 888 | |||
| 889 | if (!t.hasMoreTokens()) { | ||
| 890 | listEventRequests(); | ||
| 891 | } else { | ||
| 892 | token = t.nextToken(); | ||
| 893 | // Ignore optional "at" or "in" token. | ||
| 894 | // Allowed for backward compatibility. | ||
| 895 | if (token.equals("at") || token.equals("in")) { | ||
| 896 | if (t.hasMoreTokens()) { | ||
| 897 | token = t.nextToken(); | ||
| 898 | } else { | ||
| 899 | env.error("Missing breakpoint specification."); | ||
| 900 | return; | ||
| 901 | } | ||
| 902 | } | ||
| 903 | BreakpointSpec bpSpec = parseBreakpointSpec(token); | ||
| 904 | if (bpSpec != null) { | ||
| 905 | //### Add sanity-checks for deferred breakpoint. | ||
| 906 | runtime.install(bpSpec); | ||
| 907 | } else { | ||
| 908 | env.error("Ill-formed breakpoint specification."); | ||
| 909 | } | ||
| 910 | } | ||
| 911 | } | ||
| 912 | |||
| 913 | private void commandClear(StringTokenizer t) throws NoSessionException { | ||
| 914 | if (!t.hasMoreTokens()) { | ||
| 915 | // Print set breakpoints | ||
| 916 | listEventRequests(); | ||
| 917 | return; | ||
| 918 | } | ||
| 919 | //### need 'clear all' | ||
| 920 | BreakpointSpec bpSpec = parseBreakpointSpec(t.nextToken()); | ||
| 921 | if (bpSpec != null) { | ||
| 922 | List<EventRequestSpec> specs = runtime.eventRequestSpecs(); | ||
| 923 | |||
| 924 | if (specs.isEmpty()) { | ||
| 925 | env.notice("No breakpoints set."); | ||
| 926 | } else { | ||
| 927 | List<EventRequestSpec> toDelete = new ArrayList<EventRequestSpec>(); | ||
| 928 | for (EventRequestSpec spec : specs) { | ||
| 929 | if (spec.equals(bpSpec)) { | ||
| 930 | toDelete.add(spec); | ||
| 931 | } | ||
| 932 | } | ||
| 933 | // The request used for matching should be found | ||
| 934 | if (toDelete.size() <= 1) { | ||
| 935 | env.notice("No matching breakpoint set."); | ||
| 936 | } | ||
| 937 | for (EventRequestSpec spec : toDelete) { | ||
| 938 | runtime.delete(spec); | ||
| 939 | } | ||
| 940 | } | ||
| 941 | } else { | ||
| 942 | env.error("Ill-formed breakpoint specification."); | ||
| 943 | } | ||
| 944 | } | ||
| 945 | |||
| 946 | // Command: list | ||
| 947 | |||
| 948 | private void commandList(StringTokenizer t) throws NoSessionException { | ||
| 949 | ThreadReference current = context.getCurrentThread(); | ||
| 950 | if (current == null) { | ||
| 951 | env.error("No thread specified."); | ||
| 952 | return; | ||
| 953 | } | ||
| 954 | Location loc; | ||
| 955 | try { | ||
| 956 | StackFrame frame = context.getCurrentFrame(current); | ||
| 957 | if (frame == null) { | ||
| 958 | env.failure("Thread has not yet begun execution."); | ||
| 959 | return; | ||
| 960 | } | ||
| 961 | loc = frame.location(); | ||
| 962 | } catch (VMNotInterruptedException e) { | ||
| 963 | env.failure("Target VM must be in interrupted state."); | ||
| 964 | return; | ||
| 965 | } | ||
| 966 | SourceModel source = sourceManager.sourceForLocation(loc); | ||
| 967 | if (source == null) { | ||
| 968 | if (loc.method().isNative()) { | ||
| 969 | env.failure("Current method is native."); | ||
| 970 | return; | ||
| 971 | } | ||
| 972 | env.failure("No source available for " + Utils.locationString(loc) + "."); | ||
| 973 | return; | ||
| 974 | } | ||
| 975 | ReferenceType refType = loc.declaringType(); | ||
| 976 | int lineno = loc.lineNumber(); | ||
| 977 | if (t.hasMoreTokens()) { | ||
| 978 | String id = t.nextToken(); | ||
| 979 | // See if token is a line number. | ||
| 980 | try { | ||
| 981 | lineno = Integer.valueOf(id).intValue(); | ||
| 982 | } catch (NumberFormatException nfe) { | ||
| 983 | // It isn't -- see if it's a method name. | ||
| 984 | List<Method> meths = refType.methodsByName(id); | ||
| 985 | if (meths == null || meths.size() == 0) { | ||
| 986 | env.failure(id + | ||
| 987 | " is not a valid line number or " + | ||
| 988 | "method name for class " + | ||
| 989 | refType.name()); | ||
| 990 | return; | ||
| 991 | } else if (meths.size() > 1) { | ||
| 992 | env.failure(id + | ||
| 993 | " is an ambiguous method name in" + | ||
| 994 | refType.name()); | ||
| 995 | return; | ||
| 996 | } | ||
| 997 | loc = meths.get(0).location(); | ||
| 998 | lineno = loc.lineNumber(); | ||
| 999 | } | ||
| 1000 | } | ||
| 1001 | int startLine = (lineno > 4) ? lineno - 4 : 1; | ||
| 1002 | int endLine = startLine + 9; | ||
| 1003 | String sourceLine = source.sourceLine(lineno); | ||
| 1004 | if (sourceLine == null) { | ||
| 1005 | env.failure("" + | ||
| 1006 | lineno + | ||
| 1007 | " is an invalid line number for " + | ||
| 1008 | refType.name()); | ||
| 1009 | } else { | ||
| 1010 | OutputSink out = env.getOutputSink(); | ||
| 1011 | for (int i = startLine; i <= endLine; i++) { | ||
| 1012 | sourceLine = source.sourceLine(i); | ||
| 1013 | if (sourceLine == null) { | ||
| 1014 | break; | ||
| 1015 | } | ||
| 1016 | out.print(i); | ||
| 1017 | out.print("\t"); | ||
| 1018 | if (i == lineno) { | ||
| 1019 | out.print("=> "); | ||
| 1020 | } else { | ||
| 1021 | out.print(" "); | ||
| 1022 | } | ||
| 1023 | out.println(sourceLine); | ||
| 1024 | } | ||
| 1025 | out.show(); | ||
| 1026 | } | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | // Command: use | ||
| 1030 | // Get or set the source file path list. | ||
| 1031 | |||
| 1032 | private void commandUse(StringTokenizer t) { | ||
| 1033 | if (!t.hasMoreTokens()) { | ||
| 1034 | out.println(sourceManager.getSourcePath().asString()); | ||
| 1035 | } else { | ||
| 1036 | //### Should throw exception for invalid path. | ||
| 1037 | //### E.g., vetoable property change. | ||
| 1038 | sourceManager.setSourcePath(new SearchPath(t.nextToken())); | ||
| 1039 | } | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | // Command: sourcepath | ||
| 1043 | // Get or set the source file path list. (Alternate to 'use'.) | ||
| 1044 | |||
| 1045 | private void commandSourcepath(StringTokenizer t) { | ||
| 1046 | if (!t.hasMoreTokens()) { | ||
| 1047 | out.println(sourceManager.getSourcePath().asString()); | ||
| 1048 | } else { | ||
| 1049 | //### Should throw exception for invalid path. | ||
| 1050 | //### E.g., vetoable property change. | ||
| 1051 | sourceManager.setSourcePath(new SearchPath(t.nextToken())); | ||
| 1052 | } | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | // Command: classpath | ||
| 1056 | // Get or set the class file path list. | ||
| 1057 | |||
| 1058 | private void commandClasspath(StringTokenizer t) { | ||
| 1059 | if (!t.hasMoreTokens()) { | ||
| 1060 | out.println(classManager.getClassPath().asString()); | ||
| 1061 | } else { | ||
| 1062 | //### Should throw exception for invalid path. | ||
| 1063 | //### E.g., vetoable property change. | ||
| 1064 | classManager.setClassPath(new SearchPath(t.nextToken())); | ||
| 1065 | } | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | // Command: view | ||
| 1069 | // Display source for source file or class. | ||
| 1070 | |||
| 1071 | private void commandView(StringTokenizer t) throws NoSessionException { | ||
| 1072 | if (!t.hasMoreTokens()) { | ||
| 1073 | env.error("Argument required"); | ||
| 1074 | } else { | ||
| 1075 | String name = t.nextToken(); | ||
| 1076 | if (name.endsWith(".java") || | ||
| 1077 | name.indexOf(File.separatorChar) >= 0) { | ||
| 1078 | env.viewSource(name); | ||
| 1079 | } else { | ||
| 1080 | //### JDI crashes taking line number for class. | ||
| 1081 | /***** | ||
| 1082 | ReferenceType cls = findClass(name); | ||
| 1083 | if (cls != null) { | ||
| 1084 | env.viewLocation(cls.location()); | ||
| 1085 | } else { | ||
| 1086 | env.failure("No such class"); | ||
| 1087 | } | ||
| 1088 | *****/ | ||
| 1089 | String fileName = name.replace('.', File.separatorChar) + ".java"; | ||
| 1090 | env.viewSource(fileName); | ||
| 1091 | } | ||
| 1092 | } | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | // Command: locals | ||
| 1096 | // Print all local variables in current stack frame. | ||
| 1097 | |||
| 1098 | private void commandLocals() throws NoSessionException { | ||
| 1099 | ThreadReference current = context.getCurrentThread(); | ||
| 1100 | if (current == null) { | ||
| 1101 | env.failure("No default thread specified: " + | ||
| 1102 | "use the \"thread\" command first."); | ||
| 1103 | return; | ||
| 1104 | } | ||
| 1105 | StackFrame frame; | ||
| 1106 | try { | ||
| 1107 | frame = context.getCurrentFrame(current); | ||
| 1108 | if (frame == null) { | ||
| 1109 | env.failure("Thread has not yet created any stack frames."); | ||
| 1110 | return; | ||
| 1111 | } | ||
| 1112 | } catch (VMNotInterruptedException e) { | ||
| 1113 | env.failure("Target VM must be in interrupted state."); | ||
| 1114 | return; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | List<LocalVariable> vars; | ||
| 1118 | try { | ||
| 1119 | vars = frame.visibleVariables(); | ||
| 1120 | if (vars == null || vars.size() == 0) { | ||
| 1121 | env.failure("No local variables"); | ||
| 1122 | return; | ||
| 1123 | } | ||
| 1124 | } catch (AbsentInformationException e) { | ||
| 1125 | env.failure("Local variable information not available." + | ||
| 1126 | " Compile with -g to generate variable information"); | ||
| 1127 | return; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | OutputSink out = env.getOutputSink(); | ||
| 1131 | out.println("Method arguments:"); | ||
| 1132 | for (LocalVariable var : vars) { | ||
| 1133 | if (var.isArgument()) { | ||
| 1134 | printVar(out, var, frame); | ||
| 1135 | } | ||
| 1136 | } | ||
| 1137 | out.println("Local variables:"); | ||
| 1138 | for (LocalVariable var : vars) { | ||
| 1139 | if (!var.isArgument()) { | ||
| 1140 | printVar(out, var, frame); | ||
| 1141 | } | ||
| 1142 | } | ||
| 1143 | out.show(); | ||
| 1144 | return; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | /** | ||
| 1148 | * Command: monitor | ||
| 1149 | * Monitor an expression | ||
| 1150 | */ | ||
| 1151 | private void commandMonitor(StringTokenizer t) throws NoSessionException { | ||
| 1152 | if (!t.hasMoreTokens()) { | ||
| 1153 | env.error("Argument required"); | ||
| 1154 | } else { | ||
| 1155 | env.getMonitorListModel().add(t.nextToken("")); | ||
| 1156 | } | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | /** | ||
| 1160 | * Command: unmonitor | ||
| 1161 | * Unmonitor an expression | ||
| 1162 | */ | ||
| 1163 | private void commandUnmonitor(StringTokenizer t) throws NoSessionException { | ||
| 1164 | if (!t.hasMoreTokens()) { | ||
| 1165 | env.error("Argument required"); | ||
| 1166 | } else { | ||
| 1167 | env.getMonitorListModel().remove(t.nextToken("")); | ||
| 1168 | } | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | // Print a stack variable. | ||
| 1172 | |||
| 1173 | private void printVar(OutputSink out, LocalVariable var, StackFrame frame) { | ||
| 1174 | out.print(" " + var.name()); | ||
| 1175 | if (var.isVisible(frame)) { | ||
| 1176 | Value val = frame.getValue(var); | ||
| 1177 | out.println(" = " + val.toString()); | ||
| 1178 | } else { | ||
| 1179 | out.println(" is not in scope"); | ||
| 1180 | } | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | // Command: print | ||
| 1184 | // Evaluate an expression. | ||
| 1185 | |||
| 1186 | private void commandPrint(StringTokenizer t, boolean dumpObject) throws NoSessionException { | ||
| 1187 | if (!t.hasMoreTokens()) { | ||
| 1188 | //### Probably confused if expresion contains whitespace. | ||
| 1189 | env.error("No expression specified."); | ||
| 1190 | return; | ||
| 1191 | } | ||
| 1192 | ThreadReference current = context.getCurrentThread(); | ||
| 1193 | if (current == null) { | ||
| 1194 | env.failure("No default thread specified: " + | ||
| 1195 | "use the \"thread\" command first."); | ||
| 1196 | return; | ||
| 1197 | } | ||
| 1198 | StackFrame frame; | ||
| 1199 | try { | ||
| 1200 | frame = context.getCurrentFrame(current); | ||
| 1201 | if (frame == null) { | ||
| 1202 | env.failure("Thread has not yet created any stack frames."); | ||
| 1203 | return; | ||
| 1204 | } | ||
| 1205 | } catch (VMNotInterruptedException e) { | ||
| 1206 | env.failure("Target VM must be in interrupted state."); | ||
| 1207 | return; | ||
| 1208 | } | ||
| 1209 | while (t.hasMoreTokens()) { | ||
| 1210 | String expr = t.nextToken(""); | ||
| 1211 | Value val = null; | ||
| 1212 | try { | ||
| 1213 | val = runtime.evaluate(frame, expr); | ||
| 1214 | } catch(Exception e) { | ||
| 1215 | env.error("Exception: " + e); | ||
| 1216 | //### Fix this! | ||
| 1217 | } | ||
| 1218 | if (val == null) { | ||
| 1219 | return; // Error message already printed | ||
| 1220 | } | ||
| 1221 | OutputSink out = env.getOutputSink(); | ||
| 1222 | if (dumpObject && (val instanceof ObjectReference) && | ||
| 1223 | !(val instanceof StringReference)) { | ||
| 1224 | ObjectReference obj = (ObjectReference)val; | ||
| 1225 | ReferenceType refType = obj.referenceType(); | ||
| 1226 | out.println(expr + " = " + val.toString() + " {"); | ||
| 1227 | dump(out, obj, refType, refType); | ||
| 1228 | out.println("}"); | ||
| 1229 | } else { | ||
| 1230 | out.println(expr + " = " + val.toString()); | ||
| 1231 | } | ||
| 1232 | out.show(); | ||
| 1233 | } | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | private void dump(OutputSink out, | ||
| 1237 | ObjectReference obj, ReferenceType refType, | ||
| 1238 | ReferenceType refTypeBase) { | ||
| 1239 | for (Field field : refType.fields()) { | ||
| 1240 | out.print(" "); | ||
| 1241 | if (!refType.equals(refTypeBase)) { | ||
| 1242 | out.print(refType.name() + "."); | ||
| 1243 | } | ||
| 1244 | out.print(field.name() + ": "); | ||
| 1245 | Object o = obj.getValue(field); | ||
| 1246 | out.println((o == null) ? "null" : o.toString()); // Bug ID 4374471 | ||
| 1247 | } | ||
| 1248 | if (refType instanceof ClassType) { | ||
| 1249 | ClassType sup = ((ClassType)refType).superclass(); | ||
| 1250 | if (sup != null) { | ||
| 1251 | dump(out, obj, sup, refTypeBase); | ||
| 1252 | } | ||
| 1253 | } else if (refType instanceof InterfaceType) { | ||
| 1254 | for (InterfaceType sup : ((InterfaceType)refType).superinterfaces()) { | ||
| 1255 | dump(out, obj, sup, refTypeBase); | ||
| 1256 | } | ||
| 1257 | } | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | /* | ||
| 1261 | * Display help message. | ||
| 1262 | */ | ||
| 1263 | |||
| 1264 | private void help() { | ||
| 1265 | out.println("** command list **"); | ||
| 1266 | out.println("threads [threadgroup] -- list threads"); | ||
| 1267 | out.println("thread <thread id> -- set default thread"); | ||
| 1268 | out.println("suspend [thread id(s)] -- suspend threads (default: all)"); | ||
| 1269 | out.println("resume [thread id(s)] -- resume threads (default: all)"); | ||
| 1270 | out.println("where [thread id] | all -- dump a thread's stack"); | ||
| 1271 | out.println("wherei [thread id] | all -- dump a thread's stack, with pc info"); | ||
| 1272 | out.println("threadgroups -- list threadgroups"); | ||
| 1273 | out.println("threadgroup <name> -- set current threadgroup\n"); | ||
| 1274 | // out.println("print <expression> -- print value of expression"); | ||
| 1275 | out.println("dump <expression> -- print all object information\n"); | ||
| 1276 | // out.println("eval <expression> -- evaluate expression (same as print)"); | ||
| 1277 | out.println("locals -- print all local variables in current stack frame\n"); | ||
| 1278 | out.println("classes -- list currently known classes"); | ||
| 1279 | out.println("methods <class id> -- list a class's methods\n"); | ||
| 1280 | out.println("stop [in] <class id>.<method>[(argument_type,...)] -- set a breakpoint in a method"); | ||
| 1281 | out.println("stop [at] <class id>:<line> -- set a breakpoint at a line"); | ||
| 1282 | out.println("up [n frames] -- move up a thread's stack"); | ||
| 1283 | out.println("down [n frames] -- move down a thread's stack"); | ||
| 1284 | out.println("frame <frame-id> -- to a frame"); | ||
| 1285 | out.println("clear <class id>.<method>[(argument_type,...)] -- clear a breakpoint in a method"); | ||
| 1286 | out.println("clear <class id>:<line> -- clear a breakpoint at a line"); | ||
| 1287 | out.println("clear -- list breakpoints"); | ||
| 1288 | out.println("step -- execute current line"); | ||
| 1289 | out.println("step up -- execute until the current method returns to its caller"); | ||
| 1290 | out.println("stepi -- execute current instruction"); | ||
| 1291 | out.println("next -- step one line (step OVER calls)"); | ||
| 1292 | out.println("nexti -- step one instruction (step OVER calls)"); | ||
| 1293 | out.println("cont -- continue execution from breakpoint\n"); | ||
| 1294 | // out.println("catch <class id> -- break for the specified exception"); | ||
| 1295 | // out.println("ignore <class id> -- ignore when the specified exception\n"); | ||
| 1296 | out.println("view classname|filename -- display source file"); | ||
| 1297 | out.println("list [line number|method] -- print source code context at line or method"); | ||
| 1298 | out.println("use <source file path> -- display or change the source path\n"); | ||
| 1299 | //### new | ||
| 1300 | out.println("sourcepath <source file path> -- display or change the source path\n"); | ||
| 1301 | //### new | ||
| 1302 | out.println("classpath <class file path> -- display or change the class path\n"); | ||
| 1303 | out.println("monitor <expression> -- evaluate an expression each time the program stops\n"); | ||
| 1304 | out.println("unmonitor <monitor#> -- delete a monitor\n"); | ||
| 1305 | out.println("read <filename> -- read and execute a command file\n"); | ||
| 1306 | // out.println("memory -- report memory usage"); | ||
| 1307 | // out.println("gc -- free unused objects\n"); | ||
| 1308 | out.println("run <class> [args] -- start execution of a Java class"); | ||
| 1309 | out.println("run -- re-execute last class run"); | ||
| 1310 | out.println("load <class> [args] -- start execution of a Java class, initially suspended"); | ||
| 1311 | out.println("load -- re-execute last class run, initially suspended"); | ||
| 1312 | out.println("attach <portname> -- debug existing process\n"); | ||
| 1313 | out.println("detach -- detach from debuggee process\n"); | ||
| 1314 | out.println("kill <thread(group)> -- kill a thread or threadgroup\n"); | ||
| 1315 | out.println("!! -- repeat last command"); | ||
| 1316 | out.println("help (or ?) -- list commands"); | ||
| 1317 | out.println("exit (or quit) -- exit debugger"); | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | /* | ||
| 1321 | * Execute a command. | ||
| 1322 | */ | ||
| 1323 | |||
| 1324 | public void executeCommand(String command) { | ||
| 1325 | //### Treatment of 'out' here is dirty... | ||
| 1326 | out = env.getOutputSink(); | ||
| 1327 | if (echo) { | ||
| 1328 | out.println(">>> " + command); | ||
| 1329 | } | ||
| 1330 | StringTokenizer t = new StringTokenizer(command); | ||
| 1331 | try { | ||
| 1332 | String cmd; | ||
| 1333 | if (t.hasMoreTokens()) { | ||
| 1334 | cmd = t.nextToken().toLowerCase(); | ||
| 1335 | lastCommand = cmd; | ||
| 1336 | } else { | ||
| 1337 | cmd = lastCommand; | ||
| 1338 | } | ||
| 1339 | if (cmd.equals("print")) { | ||
| 1340 | commandPrint(t, false); | ||
| 1341 | } else if (cmd.equals("eval")) { | ||
| 1342 | commandPrint(t, false); | ||
| 1343 | } else if (cmd.equals("dump")) { | ||
| 1344 | commandPrint(t, true); | ||
| 1345 | } else if (cmd.equals("locals")) { | ||
| 1346 | commandLocals(); | ||
| 1347 | } else if (cmd.equals("classes")) { | ||
| 1348 | commandClasses(); | ||
| 1349 | } else if (cmd.equals("methods")) { | ||
| 1350 | commandMethods(t); | ||
| 1351 | } else if (cmd.equals("threads")) { | ||
| 1352 | commandThreads(t); | ||
| 1353 | } else if (cmd.equals("thread")) { | ||
| 1354 | commandThread(t); | ||
| 1355 | } else if (cmd.equals("suspend")) { | ||
| 1356 | commandSuspend(t); | ||
| 1357 | } else if (cmd.equals("resume")) { | ||
| 1358 | commandResume(t); | ||
| 1359 | } else if (cmd.equals("cont")) { | ||
| 1360 | commandCont(); | ||
| 1361 | } else if (cmd.equals("threadgroups")) { | ||
| 1362 | commandThreadGroups(); | ||
| 1363 | } else if (cmd.equals("threadgroup")) { | ||
| 1364 | commandThreadGroup(t); | ||
| 1365 | } else if (cmd.equals("run")) { | ||
| 1366 | commandRun(t); | ||
| 1367 | } else if (cmd.equals("load")) { | ||
| 1368 | commandLoad(t); | ||
| 1369 | } else if (cmd.equals("connect")) { | ||
| 1370 | commandConnect(t); | ||
| 1371 | } else if (cmd.equals("attach")) { | ||
| 1372 | commandAttach(t); | ||
| 1373 | } else if (cmd.equals("detach")) { | ||
| 1374 | commandDetach(t); | ||
| 1375 | } else if (cmd.equals("interrupt")) { | ||
| 1376 | commandInterrupt(t); | ||
| 1377 | //### Not implemented. | ||
| 1378 | // } else if (cmd.equals("catch")) { | ||
| 1379 | // commandCatchException(t); | ||
| 1380 | //### Not implemented. | ||
| 1381 | // } else if (cmd.equals("ignore")) { | ||
| 1382 | // commandIgnoreException(t); | ||
| 1383 | } else if (cmd.equals("step")) { | ||
| 1384 | commandStep(t); | ||
| 1385 | } else if (cmd.equals("stepi")) { | ||
| 1386 | commandStepi(); | ||
| 1387 | } else if (cmd.equals("next")) { | ||
| 1388 | commandNext(); | ||
| 1389 | } else if (cmd.equals("nexti")) { | ||
| 1390 | commandNexti(); | ||
| 1391 | } else if (cmd.equals("kill")) { | ||
| 1392 | commandKill(t); | ||
| 1393 | } else if (cmd.equals("where")) { | ||
| 1394 | commandWhere(t, false); | ||
| 1395 | } else if (cmd.equals("wherei")) { | ||
| 1396 | commandWhere(t, true); | ||
| 1397 | } else if (cmd.equals("up")) { | ||
| 1398 | commandUp(t); | ||
| 1399 | } else if (cmd.equals("down")) { | ||
| 1400 | commandDown(t); | ||
| 1401 | } else if (cmd.equals("frame")) { | ||
| 1402 | commandFrame(t); | ||
| 1403 | } else if (cmd.equals("stop")) { | ||
| 1404 | commandStop(t); | ||
| 1405 | } else if (cmd.equals("clear")) { | ||
| 1406 | commandClear(t); | ||
| 1407 | } else if (cmd.equals("list")) { | ||
| 1408 | commandList(t); | ||
| 1409 | } else if (cmd.equals("use")) { | ||
| 1410 | commandUse(t); | ||
| 1411 | } else if (cmd.equals("sourcepath")) { | ||
| 1412 | commandSourcepath(t); | ||
| 1413 | } else if (cmd.equals("classpath")) { | ||
| 1414 | commandClasspath(t); | ||
| 1415 | } else if (cmd.equals("monitor")) { | ||
| 1416 | commandMonitor(t); | ||
| 1417 | } else if (cmd.equals("unmonitor")) { | ||
| 1418 | commandUnmonitor(t); | ||
| 1419 | } else if (cmd.equals("view")) { | ||
| 1420 | commandView(t); | ||
| 1421 | // } else if (cmd.equals("read")) { | ||
| 1422 | // readCommand(t); | ||
| 1423 | } else if (cmd.equals("help") || cmd.equals("?")) { | ||
| 1424 | help(); | ||
| 1425 | } else if (cmd.equals("quit") || cmd.equals("exit")) { | ||
| 1426 | try { | ||
| 1427 | runtime.detach(); | ||
| 1428 | } catch (NoSessionException e) { | ||
| 1429 | // ignore | ||
| 1430 | } | ||
| 1431 | env.terminate(); | ||
| 1432 | } else { | ||
| 1433 | //### Dubious repeat-count feature inherited from 'jdb' | ||
| 1434 | if (t.hasMoreTokens()) { | ||
| 1435 | try { | ||
| 1436 | int repeat = Integer.parseInt(cmd); | ||
| 1437 | String subcom = t.nextToken(""); | ||
| 1438 | while (repeat-- > 0) { | ||
| 1439 | executeCommand(subcom); | ||
| 1440 | } | ||
| 1441 | return; | ||
| 1442 | } catch (NumberFormatException exc) { | ||
| 1443 | } | ||
| 1444 | } | ||
| 1445 | out.println("huh? Try help..."); | ||
| 1446 | out.flush(); | ||
| 1447 | } | ||
| 1448 | } catch (NoSessionException e) { | ||
| 1449 | out.println("There is no currently attached VM session."); | ||
| 1450 | out.flush(); | ||
| 1451 | } catch (Exception e) { | ||
| 1452 | out.println("Internal exception: " + e.toString()); | ||
| 1453 | out.flush(); | ||
| 1454 | System.out.println("JDB internal exception: " + e.toString()); | ||
| 1455 | e.printStackTrace(); | ||
| 1456 | } | ||
| 1457 | out.show(); | ||
| 1458 | } | ||
| 1459 | } | ||
| @@ -0,0 +1,333 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.util.*; | ||
| 30 | |||
| 31 | import javax.swing.*; | ||
| 32 | import java.awt.BorderLayout; | ||
| 33 | import java.awt.event.*; | ||
| 34 | |||
| 35 | import com.sun.jdi.*; | ||
| 36 | import com.sun.jdi.event.*; | ||
| 37 | |||
| 38 | import com.sun.tools.example.debug.bdi.*; | ||
| 39 | import com.sun.tools.example.debug.event.*; | ||
| 40 | |||
| 41 | public class CommandTool extends JPanel { | ||
| 42 | |||
| 43 | private static final long serialVersionUID = 8613516856378346415L; | ||
| 44 | |||
| 45 | private Environment env; | ||
| 46 | |||
| 47 | private ContextManager context; | ||
| 48 | private ExecutionManager runtime; | ||
| 49 | private SourceManager sourceManager; | ||
| 50 | |||
| 51 | private TypeScript script; | ||
| 52 | |||
| 53 | private static final String DEFAULT_CMD_PROMPT = "Command:"; | ||
| 54 | |||
| 55 | public CommandTool(Environment env) { | ||
| 56 | |||
| 57 | super(new BorderLayout()); | ||
| 58 | |||
| 59 | this.env = env; | ||
| 60 | this.context = env.getContextManager(); | ||
| 61 | this.runtime = env.getExecutionManager(); | ||
| 62 | this.sourceManager = env.getSourceManager(); | ||
| 63 | |||
| 64 | script = new TypeScript(DEFAULT_CMD_PROMPT, false); //no echo | ||
| 65 | this.add(script); | ||
| 66 | |||
| 67 | final CommandInterpreter interpreter = | ||
| 68 | new CommandInterpreter(env); | ||
| 69 | |||
| 70 | // Establish handler for incoming commands. | ||
| 71 | |||
| 72 | script.addActionListener(new ActionListener() { | ||
| 73 | @Override | ||
| 74 | public void actionPerformed(ActionEvent e) { | ||
| 75 | interpreter.executeCommand(script.readln()); | ||
| 76 | } | ||
| 77 | }); | ||
| 78 | |||
| 79 | // Establish ourselves as the listener for VM diagnostics. | ||
| 80 | |||
| 81 | OutputListener diagnosticsListener = | ||
| 82 | new TypeScriptOutputListener(script, true); | ||
| 83 | runtime.addDiagnosticsListener(diagnosticsListener); | ||
| 84 | |||
| 85 | // Establish ourselves as the shared debugger typescript. | ||
| 86 | |||
| 87 | env.setTypeScript(new PrintWriter(new TypeScriptWriter(script))); | ||
| 88 | |||
| 89 | // Handle VM events. | ||
| 90 | |||
| 91 | TTYDebugListener listener = new TTYDebugListener(diagnosticsListener); | ||
| 92 | |||
| 93 | runtime.addJDIListener(listener); | ||
| 94 | runtime.addSessionListener(listener); | ||
| 95 | runtime.addSpecListener(listener); | ||
| 96 | context.addContextListener(listener); | ||
| 97 | |||
| 98 | //### remove listeners on exit! | ||
| 99 | |||
| 100 | } | ||
| 101 | |||
| 102 | private class TTYDebugListener implements | ||
| 103 | JDIListener, SessionListener, SpecListener, ContextListener { | ||
| 104 | |||
| 105 | private OutputListener diagnostics; | ||
| 106 | |||
| 107 | TTYDebugListener(OutputListener diagnostics) { | ||
| 108 | this.diagnostics = diagnostics; | ||
| 109 | } | ||
| 110 | |||
| 111 | // JDIListener | ||
| 112 | |||
| 113 | @Override | ||
| 114 | public void accessWatchpoint(AccessWatchpointEventSet e) { | ||
| 115 | setThread(e); | ||
| 116 | for (EventIterator it = e.eventIterator(); it.hasNext(); ) { | ||
| 117 | it.nextEvent(); | ||
| 118 | diagnostics.putString("Watchpoint hit: " + | ||
| 119 | locationString(e)); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | @Override | ||
| 124 | public void classPrepare(ClassPrepareEventSet e) { | ||
| 125 | if (context.getVerboseFlag()) { | ||
| 126 | String name = e.getReferenceType().name(); | ||
| 127 | diagnostics.putString("Class " + name + " loaded"); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | @Override | ||
| 132 | public void classUnload(ClassUnloadEventSet e) { | ||
| 133 | if (context.getVerboseFlag()) { | ||
| 134 | diagnostics.putString("Class " + e.getClassName() + | ||
| 135 | " unloaded."); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | @Override | ||
| 140 | public void exception(ExceptionEventSet e) { | ||
| 141 | setThread(e); | ||
| 142 | String name = e.getException().referenceType().name(); | ||
| 143 | diagnostics.putString("Exception: " + name); | ||
| 144 | } | ||
| 145 | |||
| 146 | @Override | ||
| 147 | public void locationTrigger(LocationTriggerEventSet e) { | ||
| 148 | String locString = locationString(e); | ||
| 149 | setThread(e); | ||
| 150 | for (EventIterator it = e.eventIterator(); it.hasNext(); ) { | ||
| 151 | Event evt = it.nextEvent(); | ||
| 152 | if (evt instanceof BreakpointEvent) { | ||
| 153 | diagnostics.putString("Breakpoint hit: " + locString); | ||
| 154 | } else if (evt instanceof StepEvent) { | ||
| 155 | diagnostics.putString("Step completed: " + locString); | ||
| 156 | } else if (evt instanceof MethodEntryEvent) { | ||
| 157 | diagnostics.putString("Method entered: " + locString); | ||
| 158 | } else if (evt instanceof MethodExitEvent) { | ||
| 159 | diagnostics.putString("Method exited: " + locString); | ||
| 160 | } else { | ||
| 161 | diagnostics.putString("UNKNOWN event: " + e); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | @Override | ||
| 167 | public void modificationWatchpoint(ModificationWatchpointEventSet e) { | ||
| 168 | setThread(e); | ||
| 169 | for (EventIterator it = e.eventIterator(); it.hasNext(); ) { | ||
| 170 | it.nextEvent(); | ||
| 171 | diagnostics.putString("Watchpoint hit: " + | ||
| 172 | locationString(e)); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | @Override | ||
| 177 | public void threadDeath(ThreadDeathEventSet e) { | ||
| 178 | if (context.getVerboseFlag()) { | ||
| 179 | diagnostics.putString("Thread " + e.getThread() + | ||
| 180 | " ended."); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | @Override | ||
| 185 | public void threadStart(ThreadStartEventSet e) { | ||
| 186 | if (context.getVerboseFlag()) { | ||
| 187 | diagnostics.putString("Thread " + e.getThread() + | ||
| 188 | " started."); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | @Override | ||
| 193 | public void vmDeath(VMDeathEventSet e) { | ||
| 194 | script.setPrompt(DEFAULT_CMD_PROMPT); | ||
| 195 | diagnostics.putString("VM exited"); | ||
| 196 | } | ||
| 197 | |||
| 198 | @Override | ||
| 199 | public void vmDisconnect(VMDisconnectEventSet e) { | ||
| 200 | script.setPrompt(DEFAULT_CMD_PROMPT); | ||
| 201 | diagnostics.putString("Disconnected from VM"); | ||
| 202 | } | ||
| 203 | |||
| 204 | @Override | ||
| 205 | public void vmStart(VMStartEventSet e) { | ||
| 206 | script.setPrompt(DEFAULT_CMD_PROMPT); | ||
| 207 | diagnostics.putString("VM started"); | ||
| 208 | } | ||
| 209 | |||
| 210 | // SessionListener | ||
| 211 | |||
| 212 | @Override | ||
| 213 | public void sessionStart(EventObject e) {} | ||
| 214 | |||
| 215 | @Override | ||
| 216 | public void sessionInterrupt(EventObject e) { | ||
| 217 | Thread.yield(); // fetch output | ||
| 218 | diagnostics.putString("VM interrupted by user."); | ||
| 219 | script.setPrompt(DEFAULT_CMD_PROMPT); | ||
| 220 | } | ||
| 221 | |||
| 222 | @Override | ||
| 223 | public void sessionContinue(EventObject e) { | ||
| 224 | diagnostics.putString("Execution resumed."); | ||
| 225 | script.setPrompt(DEFAULT_CMD_PROMPT); | ||
| 226 | } | ||
| 227 | |||
| 228 | // SpecListener | ||
| 229 | |||
| 230 | @Override | ||
| 231 | public void breakpointSet(SpecEvent e) { | ||
| 232 | EventRequestSpec spec = e.getEventRequestSpec(); | ||
| 233 | diagnostics.putString("Breakpoint set at " + spec + "."); | ||
| 234 | } | ||
| 235 | @Override | ||
| 236 | public void breakpointDeferred(SpecEvent e) { | ||
| 237 | EventRequestSpec spec = e.getEventRequestSpec(); | ||
| 238 | diagnostics.putString("Breakpoint will be set at " + | ||
| 239 | spec + " when its class is loaded."); | ||
| 240 | } | ||
| 241 | @Override | ||
| 242 | public void breakpointDeleted(SpecEvent e) { | ||
| 243 | EventRequestSpec spec = e.getEventRequestSpec(); | ||
| 244 | diagnostics.putString("Breakpoint at " + spec.toString() + " deleted."); | ||
| 245 | } | ||
| 246 | @Override | ||
| 247 | public void breakpointResolved(SpecEvent e) { | ||
| 248 | EventRequestSpec spec = e.getEventRequestSpec(); | ||
| 249 | diagnostics.putString("Breakpoint resolved to " + spec.toString() + "."); | ||
| 250 | } | ||
| 251 | @Override | ||
| 252 | public void breakpointError(SpecErrorEvent e) { | ||
| 253 | EventRequestSpec spec = e.getEventRequestSpec(); | ||
| 254 | diagnostics.putString("Deferred breakpoint at " + | ||
| 255 | spec + " could not be resolved:" + | ||
| 256 | e.getReason()); | ||
| 257 | } | ||
| 258 | |||
| 259 | //### Add info for watchpoints and exceptions | ||
| 260 | |||
| 261 | @Override | ||
| 262 | public void watchpointSet(SpecEvent e) { | ||
| 263 | } | ||
| 264 | @Override | ||
| 265 | public void watchpointDeferred(SpecEvent e) { | ||
| 266 | } | ||
| 267 | @Override | ||
| 268 | public void watchpointDeleted(SpecEvent e) { | ||
| 269 | } | ||
| 270 | @Override | ||
| 271 | public void watchpointResolved(SpecEvent e) { | ||
| 272 | } | ||
| 273 | @Override | ||
| 274 | public void watchpointError(SpecErrorEvent e) { | ||
| 275 | } | ||
| 276 | |||
| 277 | @Override | ||
| 278 | public void exceptionInterceptSet(SpecEvent e) { | ||
| 279 | } | ||
| 280 | @Override | ||
| 281 | public void exceptionInterceptDeferred(SpecEvent e) { | ||
| 282 | } | ||
| 283 | @Override | ||
| 284 | public void exceptionInterceptDeleted(SpecEvent e) { | ||
| 285 | } | ||
| 286 | @Override | ||
| 287 | public void exceptionInterceptResolved(SpecEvent e) { | ||
| 288 | } | ||
| 289 | @Override | ||
| 290 | public void exceptionInterceptError(SpecErrorEvent e) { | ||
| 291 | } | ||
| 292 | |||
| 293 | |||
| 294 | // ContextListener. | ||
| 295 | |||
| 296 | // If the user selects a new current thread or frame, update prompt. | ||
| 297 | |||
| 298 | @Override | ||
| 299 | public void currentFrameChanged(CurrentFrameChangedEvent e) { | ||
| 300 | // Update prompt only if affect thread is current. | ||
| 301 | ThreadReference thread = e.getThread(); | ||
| 302 | if (thread == context.getCurrentThread()) { | ||
| 303 | script.setPrompt(promptString(thread, e.getIndex())); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | } | ||
| 308 | |||
| 309 | private String locationString(LocatableEventSet e) { | ||
| 310 | Location loc = e.getLocation(); | ||
| 311 | return "thread=\"" + e.getThread().name() + | ||
| 312 | "\", " + Utils.locationString(loc); | ||
| 313 | } | ||
| 314 | |||
| 315 | private void setThread(LocatableEventSet e) { | ||
| 316 | if (!e.suspendedNone()) { | ||
| 317 | Thread.yield(); // fetch output | ||
| 318 | script.setPrompt(promptString(e.getThread(), 0)); | ||
| 319 | //### Current thread should be set elsewhere, e.g., | ||
| 320 | //### in ContextManager | ||
| 321 | //### context.setCurrentThread(thread); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | private String promptString(ThreadReference thread, int frameIndex) { | ||
| 326 | if (thread == null) { | ||
| 327 | return DEFAULT_CMD_PROMPT; | ||
| 328 | } else { | ||
| 329 | // Frame indices are presented to user as indexed from 1. | ||
| 330 | return (thread.name() + "[" + (frameIndex + 1) + "]:"); | ||
| 331 | } | ||
| 332 | } | ||
| 333 | } | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | public interface ContextListener { | ||
| 29 | void currentFrameChanged(CurrentFrameChangedEvent e); | ||
| 30 | } | ||
| @@ -0,0 +1,353 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.util.*; | ||
| 30 | |||
| 31 | import com.sun.jdi.*; | ||
| 32 | import com.sun.tools.example.debug.event.*; | ||
| 33 | import com.sun.tools.example.debug.bdi.*; | ||
| 34 | |||
| 35 | public class ContextManager { | ||
| 36 | |||
| 37 | private ClassManager classManager; | ||
| 38 | private ExecutionManager runtime; | ||
| 39 | |||
| 40 | private String mainClassName; | ||
| 41 | private String vmArguments; | ||
| 42 | private String commandArguments; | ||
| 43 | private String remotePort; | ||
| 44 | |||
| 45 | private ThreadReference currentThread; | ||
| 46 | |||
| 47 | private boolean verbose; | ||
| 48 | |||
| 49 | private ArrayList<ContextListener> contextListeners = new ArrayList<ContextListener>(); | ||
| 50 | |||
| 51 | public ContextManager(Environment env) { | ||
| 52 | classManager = env.getClassManager(); | ||
| 53 | runtime = env.getExecutionManager(); | ||
| 54 | mainClassName = ""; | ||
| 55 | vmArguments = ""; | ||
| 56 | commandArguments = ""; | ||
| 57 | currentThread = null; | ||
| 58 | |||
| 59 | ContextManagerListener listener = new ContextManagerListener(); | ||
| 60 | runtime.addJDIListener(listener); | ||
| 61 | runtime.addSessionListener(listener); | ||
| 62 | } | ||
| 63 | |||
| 64 | // Program execution defaults. | ||
| 65 | |||
| 66 | //### Should there be change listeners for these? | ||
| 67 | //### They would be needed if we expected a dialog to be | ||
| 68 | //### synchronized with command input while it was open. | ||
| 69 | |||
| 70 | public String getMainClassName() { | ||
| 71 | return mainClassName; | ||
| 72 | } | ||
| 73 | |||
| 74 | public void setMainClassName(String mainClassName) { | ||
| 75 | this.mainClassName = mainClassName; | ||
| 76 | } | ||
| 77 | |||
| 78 | public String getVmArguments() { | ||
| 79 | return processClasspathDefaults(vmArguments); | ||
| 80 | } | ||
| 81 | |||
| 82 | public void setVmArguments(String vmArguments) { | ||
| 83 | this.vmArguments = vmArguments; | ||
| 84 | } | ||
| 85 | |||
| 86 | public String getProgramArguments() { | ||
| 87 | return commandArguments; | ||
| 88 | } | ||
| 89 | |||
| 90 | public void setProgramArguments(String commandArguments) { | ||
| 91 | this.commandArguments = commandArguments; | ||
| 92 | } | ||
| 93 | |||
| 94 | public String getRemotePort() { | ||
| 95 | return remotePort; | ||
| 96 | } | ||
| 97 | |||
| 98 | public void setRemotePort(String remotePort) { | ||
| 99 | this.remotePort = remotePort; | ||
| 100 | |||
| 101 | } | ||
| 102 | |||
| 103 | |||
| 104 | // Miscellaneous debugger session preferences. | ||
| 105 | |||
| 106 | public boolean getVerboseFlag() { | ||
| 107 | return verbose; | ||
| 108 | } | ||
| 109 | |||
| 110 | public void setVerboseFlag(boolean verbose) { | ||
| 111 | this.verbose = verbose; | ||
| 112 | } | ||
| 113 | |||
| 114 | |||
| 115 | // Thread focus. | ||
| 116 | |||
| 117 | public ThreadReference getCurrentThread() { | ||
| 118 | return currentThread; | ||
| 119 | } | ||
| 120 | |||
| 121 | public void setCurrentThread(ThreadReference t) { | ||
| 122 | if (t != currentThread) { | ||
| 123 | currentThread = t; | ||
| 124 | notifyCurrentThreadChanged(t); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | public void setCurrentThreadInvalidate(ThreadReference t) { | ||
| 129 | currentThread = t; | ||
| 130 | notifyCurrentFrameChanged(runtime.threadInfo(t), | ||
| 131 | 0, true); | ||
| 132 | } | ||
| 133 | |||
| 134 | public void invalidateCurrentThread() { | ||
| 135 | notifyCurrentFrameChanged(null, 0, true); | ||
| 136 | } | ||
| 137 | |||
| 138 | |||
| 139 | // If a view is displaying the current thread, it may | ||
| 140 | // choose to indicate which frame is current in the | ||
| 141 | // sense of the command-line UI. It may also "warp" the | ||
| 142 | // selection to that frame when changed by an 'up' or 'down' | ||
| 143 | // command. Hence, a notifier is provided. | ||
| 144 | |||
| 145 | /****** | ||
| 146 | public int getCurrentFrameIndex() { | ||
| 147 | return getCurrentFrameIndex(currentThreadInfo); | ||
| 148 | } | ||
| 149 | ******/ | ||
| 150 | |||
| 151 | public int getCurrentFrameIndex(ThreadReference t) { | ||
| 152 | return getCurrentFrameIndex(runtime.threadInfo(t)); | ||
| 153 | } | ||
| 154 | |||
| 155 | //### Used in StackTraceTool. | ||
| 156 | public int getCurrentFrameIndex(ThreadInfo tinfo) { | ||
| 157 | if (tinfo == null) { | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | Integer currentFrame = (Integer)tinfo.getUserObject(); | ||
| 161 | if (currentFrame == null) { | ||
| 162 | return 0; | ||
| 163 | } else { | ||
| 164 | return currentFrame.intValue(); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | public int moveCurrentFrameIndex(ThreadReference t, int count) throws VMNotInterruptedException { | ||
| 169 | return setCurrentFrameIndex(t,count, true); | ||
| 170 | } | ||
| 171 | |||
| 172 | public int setCurrentFrameIndex(ThreadReference t, int newIndex) throws VMNotInterruptedException { | ||
| 173 | return setCurrentFrameIndex(t, newIndex, false); | ||
| 174 | } | ||
| 175 | |||
| 176 | public int setCurrentFrameIndex(int newIndex) throws VMNotInterruptedException { | ||
| 177 | if (currentThread == null) { | ||
| 178 | return 0; | ||
| 179 | } else { | ||
| 180 | return setCurrentFrameIndex(currentThread, newIndex, false); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | private int setCurrentFrameIndex(ThreadReference t, int x, boolean relative) throws VMNotInterruptedException { | ||
| 185 | boolean sameThread = t.equals(currentThread); | ||
| 186 | ThreadInfo tinfo = runtime.threadInfo(t); | ||
| 187 | if (tinfo == null) { | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | int maxIndex = tinfo.getFrameCount()-1; | ||
| 191 | int oldIndex = getCurrentFrameIndex(tinfo); | ||
| 192 | int newIndex = relative? oldIndex + x : x; | ||
| 193 | if (newIndex > maxIndex) { | ||
| 194 | newIndex = maxIndex; | ||
| 195 | } else if (newIndex < 0) { | ||
| 196 | newIndex = 0; | ||
| 197 | } | ||
| 198 | if (!sameThread || newIndex != oldIndex) { // don't recurse | ||
| 199 | setCurrentFrameIndex(tinfo, newIndex); | ||
| 200 | } | ||
| 201 | return newIndex - oldIndex; | ||
| 202 | } | ||
| 203 | |||
| 204 | private void setCurrentFrameIndex(ThreadInfo tinfo, int index) { | ||
| 205 | tinfo.setUserObject(new Integer(index)); | ||
| 206 | //### In fact, the value may not have changed at this point. | ||
| 207 | //### We need to signal that the user attempted to change it, | ||
| 208 | //### however, so that the selection can be "warped" to the | ||
| 209 | //### current location. | ||
| 210 | notifyCurrentFrameChanged(tinfo.thread(), index); | ||
| 211 | } | ||
| 212 | |||
| 213 | public StackFrame getCurrentFrame() throws VMNotInterruptedException { | ||
| 214 | return getCurrentFrame(runtime.threadInfo(currentThread)); | ||
| 215 | } | ||
| 216 | |||
| 217 | public StackFrame getCurrentFrame(ThreadReference t) throws VMNotInterruptedException { | ||
| 218 | return getCurrentFrame(runtime.threadInfo(t)); | ||
| 219 | } | ||
| 220 | |||
| 221 | public StackFrame getCurrentFrame(ThreadInfo tinfo) throws VMNotInterruptedException { | ||
| 222 | int index = getCurrentFrameIndex(tinfo); | ||
| 223 | try { | ||
| 224 | // It is possible, though unlikely, that the VM was interrupted | ||
| 225 | // before the thread created its Java stack. | ||
| 226 | return tinfo.getFrame(index); | ||
| 227 | } catch (FrameIndexOutOfBoundsException e) { | ||
| 228 | return null; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | public void addContextListener(ContextListener cl) { | ||
| 233 | contextListeners.add(cl); | ||
| 234 | } | ||
| 235 | |||
| 236 | public void removeContextListener(ContextListener cl) { | ||
| 237 | contextListeners.remove(cl); | ||
| 238 | } | ||
| 239 | |||
| 240 | //### These notifiers are fired only in response to USER-INITIATED changes | ||
| 241 | //### to the current thread and current frame. When the current thread is set automatically | ||
| 242 | //### after a breakpoint hit or step completion, no event is generated. Instead, | ||
| 243 | //### interested parties are expected to listen for the BreakpointHit and StepCompleted | ||
| 244 | //### events. This convention is unclean, and I believe that it reflects a defect in | ||
| 245 | //### in the current architecture. Unfortunately, however, we cannot guarantee the | ||
| 246 | //### order in which various listeners receive a given event, and the handlers for | ||
| 247 | //### the very same events that cause automatic changes to the current thread may also | ||
| 248 | //### need to know the current thread. | ||
| 249 | |||
| 250 | private void notifyCurrentThreadChanged(ThreadReference t) { | ||
| 251 | ThreadInfo tinfo = null; | ||
| 252 | int index = 0; | ||
| 253 | if (t != null) { | ||
| 254 | tinfo = runtime.threadInfo(t); | ||
| 255 | index = getCurrentFrameIndex(tinfo); | ||
| 256 | } | ||
| 257 | notifyCurrentFrameChanged(tinfo, index, false); | ||
| 258 | } | ||
| 259 | |||
| 260 | private void notifyCurrentFrameChanged(ThreadReference t, int index) { | ||
| 261 | notifyCurrentFrameChanged(runtime.threadInfo(t), | ||
| 262 | index, false); | ||
| 263 | } | ||
| 264 | |||
| 265 | private void notifyCurrentFrameChanged(ThreadInfo tinfo, int index, | ||
| 266 | boolean invalidate) { | ||
| 267 | ArrayList<ContextListener> l = new ArrayList<ContextListener>(contextListeners); | ||
| 268 | CurrentFrameChangedEvent evt = | ||
| 269 | new CurrentFrameChangedEvent(this, tinfo, index, invalidate); | ||
| 270 | for (int i = 0; i < l.size(); i++) { | ||
| 271 | l.get(i).currentFrameChanged(evt); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | private class ContextManagerListener extends JDIAdapter | ||
| 276 | implements SessionListener, JDIListener { | ||
| 277 | |||
| 278 | // SessionListener | ||
| 279 | |||
| 280 | @Override | ||
| 281 | public void sessionStart(EventObject e) { | ||
| 282 | invalidateCurrentThread(); | ||
| 283 | } | ||
| 284 | |||
| 285 | @Override | ||
| 286 | public void sessionInterrupt(EventObject e) { | ||
| 287 | setCurrentThreadInvalidate(currentThread); | ||
| 288 | } | ||
| 289 | |||
| 290 | @Override | ||
| 291 | public void sessionContinue(EventObject e) { | ||
| 292 | invalidateCurrentThread(); | ||
| 293 | } | ||
| 294 | |||
| 295 | // JDIListener | ||
| 296 | |||
| 297 | @Override | ||
| 298 | public void locationTrigger(LocationTriggerEventSet e) { | ||
| 299 | setCurrentThreadInvalidate(e.getThread()); | ||
| 300 | } | ||
| 301 | |||
| 302 | @Override | ||
| 303 | public void exception(ExceptionEventSet e) { | ||
| 304 | setCurrentThreadInvalidate(e.getThread()); | ||
| 305 | } | ||
| 306 | |||
| 307 | @Override | ||
| 308 | public void vmDisconnect(VMDisconnectEventSet e) { | ||
| 309 | invalidateCurrentThread(); | ||
| 310 | } | ||
| 311 | |||
| 312 | } | ||
| 313 | |||
| 314 | |||
| 315 | /** | ||
| 316 | * Add a -classpath argument to the arguments passed to the exec'ed | ||
| 317 | * VM with the contents of CLASSPATH environment variable, | ||
| 318 | * if -classpath was not already specified. | ||
| 319 | * | ||
| 320 | * @param javaArgs the arguments to the VM being exec'd that | ||
| 321 | * potentially has a user specified -classpath argument. | ||
| 322 | * @return a javaArgs whose -classpath option has been added | ||
| 323 | */ | ||
| 324 | |||
| 325 | private String processClasspathDefaults(String javaArgs) { | ||
| 326 | if (javaArgs.indexOf("-classpath ") == -1) { | ||
| 327 | StringBuffer munged = new StringBuffer(javaArgs); | ||
| 328 | SearchPath classpath = classManager.getClassPath(); | ||
| 329 | if (classpath.isEmpty()) { | ||
| 330 | String envcp = System.getProperty("env.class.path"); | ||
| 331 | if ((envcp != null) && (envcp.length() > 0)) { | ||
| 332 | munged.append(" -classpath " + envcp); | ||
| 333 | } | ||
| 334 | } else { | ||
| 335 | munged.append(" -classpath " + classpath.asString()); | ||
| 336 | } | ||
| 337 | return munged.toString(); | ||
| 338 | } else { | ||
| 339 | return javaArgs; | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | private String appendPath(String path1, String path2) { | ||
| 344 | if (path1 == null || path1.length() == 0) { | ||
| 345 | return path2 == null ? "." : path2; | ||
| 346 | } else if (path2 == null || path2.length() == 0) { | ||
| 347 | return path1; | ||
| 348 | } else { | ||
| 349 | return path1 + File.pathSeparator + path2; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | |||
| 353 | } | ||
| @@ -0,0 +1,62 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import com.sun.jdi.*; | ||
| 29 | import com.sun.tools.example.debug.bdi.*; | ||
| 30 | import java.util.EventObject; | ||
| 31 | |||
| 32 | public class CurrentFrameChangedEvent extends EventObject { | ||
| 33 | |||
| 34 | private static final long serialVersionUID = 4214479486546762179L; | ||
| 35 | private ThreadInfo tinfo; | ||
| 36 | private int index; | ||
| 37 | private boolean invalidate; | ||
| 38 | |||
| 39 | public CurrentFrameChangedEvent(Object source, ThreadInfo tinfo, | ||
| 40 | int index, boolean invalidate) { | ||
| 41 | super(source); | ||
| 42 | this.tinfo = tinfo; | ||
| 43 | this.index = index; | ||
| 44 | this.invalidate = invalidate; | ||
| 45 | } | ||
| 46 | |||
| 47 | public ThreadReference getThread() { | ||
| 48 | return tinfo == null? null : tinfo.thread(); | ||
| 49 | } | ||
| 50 | |||
| 51 | public ThreadInfo getThreadInfo() { | ||
| 52 | return tinfo; | ||
| 53 | } | ||
| 54 | |||
| 55 | public int getIndex() { | ||
| 56 | return index; | ||
| 57 | } | ||
| 58 | |||
| 59 | public boolean getInvalidate() { | ||
| 60 | return invalidate; | ||
| 61 | } | ||
| 62 | } | ||
| @@ -0,0 +1,156 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import com.sun.jdi.*; | ||
| 30 | import com.sun.tools.example.debug.bdi.*; | ||
| 31 | |||
| 32 | public class Environment { | ||
| 33 | |||
| 34 | private SourceManager sourceManager; | ||
| 35 | private ClassManager classManager; | ||
| 36 | private ContextManager contextManager; | ||
| 37 | private MonitorListModel monitorListModel; | ||
| 38 | private ExecutionManager runtime; | ||
| 39 | |||
| 40 | private PrintWriter typeScript; | ||
| 41 | |||
| 42 | private boolean verbose; | ||
| 43 | |||
| 44 | public Environment() { | ||
| 45 | this.classManager = new ClassManager(this); | ||
| 46 | //### Order of the next three lines is important! (FIX THIS) | ||
| 47 | this.runtime = new ExecutionManager(); | ||
| 48 | this.sourceManager = new SourceManager(this); | ||
| 49 | this.contextManager = new ContextManager(this); | ||
| 50 | this.monitorListModel = new MonitorListModel(this); | ||
| 51 | } | ||
| 52 | |||
| 53 | // Services used by debugging tools. | ||
| 54 | |||
| 55 | public SourceManager getSourceManager() { | ||
| 56 | return sourceManager; | ||
| 57 | } | ||
| 58 | |||
| 59 | public ClassManager getClassManager() { | ||
| 60 | return classManager; | ||
| 61 | } | ||
| 62 | |||
| 63 | public ContextManager getContextManager() { | ||
| 64 | return contextManager; | ||
| 65 | } | ||
| 66 | |||
| 67 | public MonitorListModel getMonitorListModel() { | ||
| 68 | return monitorListModel; | ||
| 69 | } | ||
| 70 | |||
| 71 | public ExecutionManager getExecutionManager() { | ||
| 72 | return runtime; | ||
| 73 | } | ||
| 74 | |||
| 75 | //### TODO: | ||
| 76 | //### Tools should attach/detach from environment | ||
| 77 | //### via a property, which should call an 'addTool' | ||
| 78 | //### method when set to maintain a registry of | ||
| 79 | //### tools for exit-time cleanup, etc. Tool | ||
| 80 | //### class constructors should be argument-free, so | ||
| 81 | //### that they may be instantiated by bean builders. | ||
| 82 | //### Will also need 'removeTool' in case property | ||
| 83 | //### value is changed. | ||
| 84 | // | ||
| 85 | // public void addTool(Tool t); | ||
| 86 | // public void removeTool(Tool t); | ||
| 87 | |||
| 88 | public void terminate() { | ||
| 89 | System.exit(0); | ||
| 90 | } | ||
| 91 | |||
| 92 | // public void refresh(); // notify all tools to refresh their views | ||
| 93 | |||
| 94 | |||
| 95 | // public void addStatusListener(StatusListener l); | ||
| 96 | // public void removeStatusListener(StatusListener l); | ||
| 97 | |||
| 98 | // public void addOutputListener(OutputListener l); | ||
| 99 | // public void removeOutputListener(OutputListener l); | ||
| 100 | |||
| 101 | public void setTypeScript(PrintWriter writer) { | ||
| 102 | typeScript = writer; | ||
| 103 | } | ||
| 104 | |||
| 105 | public void error(String message) { | ||
| 106 | if (typeScript != null) { | ||
| 107 | typeScript.println(message); | ||
| 108 | } else { | ||
| 109 | System.out.println(message); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | public void failure(String message) { | ||
| 114 | if (typeScript != null) { | ||
| 115 | typeScript.println(message); | ||
| 116 | } else { | ||
| 117 | System.out.println(message); | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | public void notice(String message) { | ||
| 122 | if (typeScript != null) { | ||
| 123 | typeScript.println(message); | ||
| 124 | } else { | ||
| 125 | System.out.println(message); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | public OutputSink getOutputSink() { | ||
| 130 | return new OutputSink(typeScript); | ||
| 131 | } | ||
| 132 | |||
| 133 | public void viewSource(String fileName) { | ||
| 134 | //### HACK ### | ||
| 135 | //### Should use listener here. | ||
| 136 | com.sun.tools.example.debug.gui.GUI.srcTool.showSourceFile(fileName); | ||
| 137 | } | ||
| 138 | |||
| 139 | public void viewLocation(Location locn) { | ||
| 140 | //### HACK ### | ||
| 141 | //### Should use listener here. | ||
| 142 | //### Should we use sourceForLocation here? | ||
| 143 | com.sun.tools.example.debug.gui.GUI.srcTool.showSourceForLocation(locn); | ||
| 144 | } | ||
| 145 | |||
| 146 | //### Also in 'ContextManager'. Do we need both? | ||
| 147 | |||
| 148 | public boolean getVerboseFlag() { | ||
| 149 | return verbose; | ||
| 150 | } | ||
| 151 | |||
| 152 | public void setVerboseFlag(boolean verbose) { | ||
| 153 | this.verbose = verbose; | ||
| 154 | } | ||
| 155 | |||
| 156 | } | ||
| @@ -0,0 +1,256 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import javax.swing.*; | ||
| 30 | import javax.swing.border.*; | ||
| 31 | import java.awt.*; | ||
| 32 | import java.awt.event.*; | ||
| 33 | |||
| 34 | import com.sun.jdi.*; | ||
| 35 | import com.sun.tools.example.debug.bdi.*; | ||
| 36 | |||
| 37 | public class GUI extends JPanel { | ||
| 38 | |||
| 39 | private static final long serialVersionUID = 3292463234530679091L; | ||
| 40 | private CommandTool cmdTool; | ||
| 41 | private ApplicationTool appTool; | ||
| 42 | //###HACK## | ||
| 43 | //### There is currently dirty code in Environment that | ||
| 44 | //### accesses this directly. | ||
| 45 | //private SourceTool srcTool; | ||
| 46 | public static SourceTool srcTool; | ||
| 47 | |||
| 48 | private SourceTreeTool sourceTreeTool; | ||
| 49 | private ClassTreeTool classTreeTool; | ||
| 50 | private ThreadTreeTool threadTreeTool; | ||
| 51 | private StackTraceTool stackTool; | ||
| 52 | private MonitorTool monitorTool; | ||
| 53 | |||
| 54 | public static final String progname = "javadt"; | ||
| 55 | public static final String version = "1.0Beta"; //### FIX ME. | ||
| 56 | public static final String windowBanner = "Java(tm) platform Debug Tool"; | ||
| 57 | |||
| 58 | private Font fixedFont = new Font("monospaced", Font.PLAIN, 10); | ||
| 59 | |||
| 60 | private GUI(Environment env) { | ||
| 61 | setLayout(new BorderLayout()); | ||
| 62 | |||
| 63 | setBorder(new EmptyBorder(5, 5, 5, 5)); | ||
| 64 | |||
| 65 | add(new JDBToolBar(env), BorderLayout.NORTH); | ||
| 66 | |||
| 67 | srcTool = new SourceTool(env); | ||
| 68 | srcTool.setPreferredSize(new java.awt.Dimension(500, 300)); | ||
| 69 | srcTool.setTextFont(fixedFont); | ||
| 70 | |||
| 71 | stackTool = new StackTraceTool(env); | ||
| 72 | stackTool.setPreferredSize(new java.awt.Dimension(500, 100)); | ||
| 73 | |||
| 74 | monitorTool = new MonitorTool(env); | ||
| 75 | monitorTool.setPreferredSize(new java.awt.Dimension(500, 50)); | ||
| 76 | |||
| 77 | JSplitPane right = new JSplitPane(JSplitPane.VERTICAL_SPLIT, srcTool, | ||
| 78 | new JSplitPane(JSplitPane.VERTICAL_SPLIT, stackTool, monitorTool)); | ||
| 79 | |||
| 80 | sourceTreeTool = new SourceTreeTool(env); | ||
| 81 | sourceTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); | ||
| 82 | |||
| 83 | classTreeTool = new ClassTreeTool(env); | ||
| 84 | classTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); | ||
| 85 | |||
| 86 | threadTreeTool = new ThreadTreeTool(env); | ||
| 87 | threadTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); | ||
| 88 | |||
| 89 | JTabbedPane treePane = new JTabbedPane(SwingConstants.BOTTOM); | ||
| 90 | treePane.addTab("Source", null, sourceTreeTool); | ||
| 91 | treePane.addTab("Classes", null, classTreeTool); | ||
| 92 | treePane.addTab("Threads", null, threadTreeTool); | ||
| 93 | |||
| 94 | JSplitPane centerTop = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treePane, right); | ||
| 95 | |||
| 96 | cmdTool = new CommandTool(env); | ||
| 97 | cmdTool.setPreferredSize(new java.awt.Dimension(700, 150)); | ||
| 98 | |||
| 99 | appTool = new ApplicationTool(env); | ||
| 100 | appTool.setPreferredSize(new java.awt.Dimension(700, 200)); | ||
| 101 | |||
| 102 | JSplitPane centerBottom = new JSplitPane(JSplitPane.VERTICAL_SPLIT, cmdTool, appTool); | ||
| 103 | // centerBottom.setPreferredSize(new java.awt.Dimension(700, 350)); | ||
| 104 | |||
| 105 | JSplitPane center = new JSplitPane(JSplitPane.VERTICAL_SPLIT, centerTop, centerBottom); | ||
| 106 | |||
| 107 | add(center, BorderLayout.CENTER); | ||
| 108 | |||
| 109 | |||
| 110 | } | ||
| 111 | |||
| 112 | private static void usage() { | ||
| 113 | String separator = File.pathSeparator; | ||
| 114 | System.out.println("Usage: " + progname + " <options> <class> <arguments>"); | ||
| 115 | System.out.println(); | ||
| 116 | System.out.println("where options include:"); | ||
| 117 | System.out.println(" -help print out this message and exit"); | ||
| 118 | System.out.println(" -sourcepath <directories separated by \"" + | ||
| 119 | separator + "\">"); | ||
| 120 | System.out.println(" list directories in which to look for source files"); | ||
| 121 | System.out.println(" -remote <hostname>:<port-number>"); | ||
| 122 | System.out.println(" host machine and port number of interpreter to attach to"); | ||
| 123 | System.out.println(" -dbgtrace [flags] print info for debugging " + progname); | ||
| 124 | System.out.println(); | ||
| 125 | System.out.println("options forwarded to debuggee process:"); | ||
| 126 | System.out.println(" -v -verbose[:class|gc|jni]"); | ||
| 127 | System.out.println(" turn on verbose mode"); | ||
| 128 | System.out.println(" -D<name>=<value> set a system property"); | ||
| 129 | System.out.println(" -classpath <directories separated by \"" + | ||
| 130 | separator + "\">"); | ||
| 131 | System.out.println(" list directories in which to look for classes"); | ||
| 132 | System.out.println(" -X<option> non-standard debuggee VM option"); | ||
| 133 | System.out.println(); | ||
| 134 | System.out.println("<class> is the name of the class to begin debugging"); | ||
| 135 | System.out.println("<arguments> are the arguments passed to the main() method of <class>"); | ||
| 136 | System.out.println(); | ||
| 137 | System.out.println("For command help type 'help' at " + progname + " prompt"); | ||
| 138 | } | ||
| 139 | |||
| 140 | public static void main(String argv[]) { | ||
| 141 | String clsName = ""; | ||
| 142 | String progArgs = ""; | ||
| 143 | String javaArgs = ""; | ||
| 144 | final Environment env = new Environment(); | ||
| 145 | |||
| 146 | JPanel mainPanel = new GUI(env); | ||
| 147 | |||
| 148 | ContextManager context = env.getContextManager(); | ||
| 149 | ExecutionManager runtime = env.getExecutionManager(); | ||
| 150 | |||
| 151 | for (int i = 0; i < argv.length; i++) { | ||
| 152 | String token = argv[i]; | ||
| 153 | if (token.equals("-dbgtrace")) { | ||
| 154 | if ((i == argv.length - 1) || | ||
| 155 | ! Character.isDigit(argv[i+1].charAt(0))) { | ||
| 156 | runtime.setTraceMode(VirtualMachine.TRACE_ALL); | ||
| 157 | } else { | ||
| 158 | String flagStr = argv[++i]; | ||
| 159 | runtime.setTraceMode(Integer.decode(flagStr).intValue()); | ||
| 160 | } | ||
| 161 | } else if (token.equals("-X")) { | ||
| 162 | System.out.println( | ||
| 163 | "Use 'java -X' to see the available non-standard options"); | ||
| 164 | System.out.println(); | ||
| 165 | usage(); | ||
| 166 | System.exit(1); | ||
| 167 | } else if ( | ||
| 168 | // Standard VM options passed on | ||
| 169 | token.equals("-v") || token.startsWith("-v:") || // -v[:...] | ||
| 170 | token.startsWith("-verbose") || // -verbose[:...] | ||
| 171 | token.startsWith("-D") || | ||
| 172 | // NonStandard options passed on | ||
| 173 | token.startsWith("-X") || | ||
| 174 | // Old-style options | ||
| 175 | // (These should remain in place as long as the standard VM accepts them) | ||
| 176 | token.equals("-noasyncgc") || token.equals("-prof") || | ||
| 177 | token.equals("-verify") || token.equals("-noverify") || | ||
| 178 | token.equals("-verifyremote") || | ||
| 179 | token.equals("-verbosegc") || | ||
| 180 | token.startsWith("-ms") || token.startsWith("-mx") || | ||
| 181 | token.startsWith("-ss") || token.startsWith("-oss") ) { | ||
| 182 | javaArgs += token + " "; | ||
| 183 | } else if (token.equals("-sourcepath")) { | ||
| 184 | if (i == (argv.length - 1)) { | ||
| 185 | System.out.println("No sourcepath specified."); | ||
| 186 | usage(); | ||
| 187 | System.exit(1); | ||
| 188 | } | ||
| 189 | env.getSourceManager().setSourcePath(new SearchPath(argv[++i])); | ||
| 190 | } else if (token.equals("-classpath")) { | ||
| 191 | if (i == (argv.length - 1)) { | ||
| 192 | System.out.println("No classpath specified."); | ||
| 193 | usage(); | ||
| 194 | System.exit(1); | ||
| 195 | } | ||
| 196 | env.getClassManager().setClassPath(new SearchPath(argv[++i])); | ||
| 197 | } else if (token.equals("-remote")) { | ||
| 198 | if (i == (argv.length - 1)) { | ||
| 199 | System.out.println("No remote specified."); | ||
| 200 | usage(); | ||
| 201 | System.exit(1); | ||
| 202 | } | ||
| 203 | env.getContextManager().setRemotePort(argv[++i]); | ||
| 204 | } else if (token.equals("-help")) { | ||
| 205 | usage(); | ||
| 206 | System.exit(0); | ||
| 207 | } else if (token.equals("-version")) { | ||
| 208 | System.out.println(progname + " version " + version); | ||
| 209 | System.exit(0); | ||
| 210 | } else if (token.startsWith("-")) { | ||
| 211 | System.out.println("invalid option: " + token); | ||
| 212 | usage(); | ||
| 213 | System.exit(1); | ||
| 214 | } else { | ||
| 215 | // Everything from here is part of the command line | ||
| 216 | clsName = token; | ||
| 217 | for (i++; i < argv.length; i++) { | ||
| 218 | progArgs += argv[i] + " "; | ||
| 219 | } | ||
| 220 | break; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | context.setMainClassName(clsName); | ||
| 225 | context.setProgramArguments(progArgs); | ||
| 226 | context.setVmArguments(javaArgs); | ||
| 227 | |||
| 228 | // Force Cross Platform L&F | ||
| 229 | try { | ||
| 230 | UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); | ||
| 231 | // If you want the System L&F instead, comment out the above line and | ||
| 232 | // uncomment the following: | ||
| 233 | // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | ||
| 234 | } catch (Exception exc) { | ||
| 235 | System.err.println("Error loading L&F: " + exc); | ||
| 236 | } | ||
| 237 | |||
| 238 | JFrame frame = new JFrame(); | ||
| 239 | frame.setBackground(Color.lightGray); | ||
| 240 | frame.setTitle(windowBanner); | ||
| 241 | frame.setJMenuBar(new JDBMenuBar(env)); | ||
| 242 | frame.setContentPane(mainPanel); | ||
| 243 | |||
| 244 | frame.addWindowListener(new WindowAdapter() { | ||
| 245 | @Override | ||
| 246 | public void windowClosing(WindowEvent e) { | ||
| 247 | env.terminate(); | ||
| 248 | } | ||
| 249 | }); | ||
| 250 | |||
| 251 | frame.pack(); | ||
| 252 | frame.setVisible(true); | ||
| 253 | |||
| 254 | } | ||
| 255 | |||
| 256 | } | ||
| @@ -0,0 +1,209 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import javax.swing.Icon; | ||
| 29 | import javax.swing.ImageIcon; | ||
| 30 | |||
| 31 | class Icons { | ||
| 32 | |||
| 33 | private static int[] exec = { | ||
| 34 | 0xffd8ffe0, 0x00104a46, 0x49460001, 0x01020000 | ||
| 35 | , 0x00000000, 0xffdb0043, 0x00020101, 0x01010102 | ||
| 36 | , 0x01010102, 0x02020202, 0x04030202, 0x02020504 | ||
| 37 | , 0x04030406, 0x05060606, 0x05060606, 0x07090806 | ||
| 38 | , 0x07090706, 0x06080b08, 0x090a0a0a, 0x0a0a0608 | ||
| 39 | , 0x0b0c0b0a, 0x0c090a0a, 0x0affdb00, 0x43010202 | ||
| 40 | , 0x02020202, 0x05030305, 0x0a070607, 0x0a0a0a0a | ||
| 41 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a | ||
| 42 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a | ||
| 43 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0affc0 | ||
| 44 | , 0x00110800, 0x0c000c03, 0x01220002, 0x11010311 | ||
| 45 | , 0x01ffc400, 0x1f000001, 0x05010101, 0x01010100 | ||
| 46 | , 0x00000000, 0x00000001, 0x02030405, 0x06070809 | ||
| 47 | , 0x0a0bffc4, 0x00b51000, 0x02010303, 0x02040305 | ||
| 48 | , 0x05040400, 0x00017d01, 0x02030004, 0x11051221 | ||
| 49 | , 0x31410613, 0x51610722, 0x71143281, 0x91a10823 | ||
| 50 | , 0x42b1c115, 0x52d1f024, 0x33627282, 0x090a1617 | ||
| 51 | , 0x18191a25, 0x26272829, 0x2a343536, 0x3738393a | ||
| 52 | , 0x43444546, 0x4748494a, 0x53545556, 0x5758595a | ||
| 53 | , 0x63646566, 0x6768696a, 0x73747576, 0x7778797a | ||
| 54 | , 0x83848586, 0x8788898a, 0x92939495, 0x96979899 | ||
| 55 | , 0x9aa2a3a4, 0xa5a6a7a8, 0xa9aab2b3, 0xb4b5b6b7 | ||
| 56 | , 0xb8b9bac2, 0xc3c4c5c6, 0xc7c8c9ca, 0xd2d3d4d5 | ||
| 57 | , 0xd6d7d8d9, 0xdae1e2e3, 0xe4e5e6e7, 0xe8e9eaf1 | ||
| 58 | , 0xf2f3f4f5, 0xf6f7f8f9, 0xfaffc400, 0x1f010003 | ||
| 59 | , 0x01010101, 0x01010101, 0x01000000, 0x00000001 | ||
| 60 | , 0x02030405, 0x06070809, 0x0a0bffc4, 0x00b51100 | ||
| 61 | , 0x02010204, 0x04030407, 0x05040400, 0x01027700 | ||
| 62 | , 0x01020311, 0x04052131, 0x06124151, 0x07617113 | ||
| 63 | , 0x22328108, 0x144291a1, 0xb1c10923, 0x3352f015 | ||
| 64 | , 0x6272d10a, 0x162434e1, 0x25f11718, 0x191a2627 | ||
| 65 | , 0x28292a35, 0x36373839, 0x3a434445, 0x46474849 | ||
| 66 | , 0x4a535455, 0x56575859, 0x5a636465, 0x66676869 | ||
| 67 | , 0x6a737475, 0x76777879, 0x7a828384, 0x85868788 | ||
| 68 | , 0x898a9293, 0x94959697, 0x98999aa2, 0xa3a4a5a6 | ||
| 69 | , 0xa7a8a9aa, 0xb2b3b4b5, 0xb6b7b8b9, 0xbac2c3c4 | ||
| 70 | , 0xc5c6c7c8, 0xc9cad2d3, 0xd4d5d6d7, 0xd8d9dae2 | ||
| 71 | , 0xe3e4e5e6, 0xe7e8e9ea, 0xf2f3f4f5, 0xf6f7f8f9 | ||
| 72 | , 0xfaffda00, 0x0c030100, 0x02110311, 0x003f00fd | ||
| 73 | , 0xbafda27e, 0x35ea1f03, 0x346f0ef8, 0x86cfc2d3 | ||
| 74 | , 0x6b31ea9e, 0x2ab7d2ee, 0xf4fb38cb, 0x5cc91cb0 | ||
| 75 | , 0xce4790a0, 0xfcd2ef44, 0xc29e1f95, 0xf94b065f | ||
| 76 | , 0x42a86eb4, 0xed3ef67b, 0x7b9bcb18, 0x6692ce63 | ||
| 77 | , 0x35a492c4, 0x19a090a3, 0x465d09fb, 0xadb1dd72 | ||
| 78 | , 0x39daec3a, 0x13535706, 0x1f0f8ca7, 0x8dad56a5 | ||
| 79 | , 0x5e6a72e5, 0xe485be0b, 0x2b49df77, 0xcceda6ca | ||
| 80 | , 0xda6ece3a, 0x147150c5, 0xd5a93a97, 0x84b97963 | ||
| 81 | , 0x6f86cbde, 0x77ddf33b, 0x69b2b69b, 0xb3ffd900 | ||
| 82 | |||
| 83 | }; | ||
| 84 | private static int[] blank = { | ||
| 85 | 0xffd8ffe0, 0x00104a46, 0x49460001, 0x01020000 | ||
| 86 | , 0x00000000, 0xffdb0043, 0x00020101, 0x01010102 | ||
| 87 | , 0x01010102, 0x02020202, 0x04030202, 0x02020504 | ||
| 88 | , 0x04030406, 0x05060606, 0x05060606, 0x07090806 | ||
| 89 | , 0x07090706, 0x06080b08, 0x090a0a0a, 0x0a0a0608 | ||
| 90 | , 0x0b0c0b0a, 0x0c090a0a, 0x0affdb00, 0x43010202 | ||
| 91 | , 0x02020202, 0x05030305, 0x0a070607, 0x0a0a0a0a | ||
| 92 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a | ||
| 93 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a | ||
| 94 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0affc0 | ||
| 95 | , 0x00110800, 0x0c000c03, 0x01220002, 0x11010311 | ||
| 96 | , 0x01ffc400, 0x1f000001, 0x05010101, 0x01010100 | ||
| 97 | , 0x00000000, 0x00000001, 0x02030405, 0x06070809 | ||
| 98 | , 0x0a0bffc4, 0x00b51000, 0x02010303, 0x02040305 | ||
| 99 | , 0x05040400, 0x00017d01, 0x02030004, 0x11051221 | ||
| 100 | , 0x31410613, 0x51610722, 0x71143281, 0x91a10823 | ||
| 101 | , 0x42b1c115, 0x52d1f024, 0x33627282, 0x090a1617 | ||
| 102 | , 0x18191a25, 0x26272829, 0x2a343536, 0x3738393a | ||
| 103 | , 0x43444546, 0x4748494a, 0x53545556, 0x5758595a | ||
| 104 | , 0x63646566, 0x6768696a, 0x73747576, 0x7778797a | ||
| 105 | , 0x83848586, 0x8788898a, 0x92939495, 0x96979899 | ||
| 106 | , 0x9aa2a3a4, 0xa5a6a7a8, 0xa9aab2b3, 0xb4b5b6b7 | ||
| 107 | , 0xb8b9bac2, 0xc3c4c5c6, 0xc7c8c9ca, 0xd2d3d4d5 | ||
| 108 | , 0xd6d7d8d9, 0xdae1e2e3, 0xe4e5e6e7, 0xe8e9eaf1 | ||
| 109 | , 0xf2f3f4f5, 0xf6f7f8f9, 0xfaffc400, 0x1f010003 | ||
| 110 | , 0x01010101, 0x01010101, 0x01000000, 0x00000001 | ||
| 111 | , 0x02030405, 0x06070809, 0x0a0bffc4, 0x00b51100 | ||
| 112 | , 0x02010204, 0x04030407, 0x05040400, 0x01027700 | ||
| 113 | , 0x01020311, 0x04052131, 0x06124151, 0x07617113 | ||
| 114 | , 0x22328108, 0x144291a1, 0xb1c10923, 0x3352f015 | ||
| 115 | , 0x6272d10a, 0x162434e1, 0x25f11718, 0x191a2627 | ||
| 116 | , 0x28292a35, 0x36373839, 0x3a434445, 0x46474849 | ||
| 117 | , 0x4a535455, 0x56575859, 0x5a636465, 0x66676869 | ||
| 118 | , 0x6a737475, 0x76777879, 0x7a828384, 0x85868788 | ||
| 119 | , 0x898a9293, 0x94959697, 0x98999aa2, 0xa3a4a5a6 | ||
| 120 | , 0xa7a8a9aa, 0xb2b3b4b5, 0xb6b7b8b9, 0xbac2c3c4 | ||
| 121 | , 0xc5c6c7c8, 0xc9cad2d3, 0xd4d5d6d7, 0xd8d9dae2 | ||
| 122 | , 0xe3e4e5e6, 0xe7e8e9ea, 0xf2f3f4f5, 0xf6f7f8f9 | ||
| 123 | , 0xfaffda00, 0x0c030100, 0x02110311, 0x003f00fd | ||
| 124 | , 0xfca28a28, 0x03ffd900 | ||
| 125 | |||
| 126 | }; | ||
| 127 | |||
| 128 | private static int[] stopSignWords = { | ||
| 129 | 0xffd8ffe0, 0x00104a46, 0x49460001, 0x01020000 | ||
| 130 | , 0x00000000, 0xffdb0043, 0x00020101, 0x01010102 | ||
| 131 | , 0x01010102, 0x02020202, 0x04030202, 0x02020504 | ||
| 132 | , 0x04030406, 0x05060606, 0x05060606, 0x07090806 | ||
| 133 | , 0x07090706, 0x06080b08, 0x090a0a0a, 0x0a0a0608 | ||
| 134 | , 0x0b0c0b0a, 0x0c090a0a, 0x0affdb00, 0x43010202 | ||
| 135 | , 0x02020202, 0x05030305, 0x0a070607, 0x0a0a0a0a | ||
| 136 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a | ||
| 137 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a | ||
| 138 | , 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0a0a0a, 0x0a0affc0 | ||
| 139 | , 0x00110800, 0x0c000c03, 0x01220002, 0x11010311 | ||
| 140 | , 0x01ffc400, 0x1f000001, 0x05010101, 0x01010100 | ||
| 141 | , 0x00000000, 0x00000001, 0x02030405, 0x06070809 | ||
| 142 | , 0x0a0bffc4, 0x00b51000, 0x02010303, 0x02040305 | ||
| 143 | , 0x05040400, 0x00017d01, 0x02030004, 0x11051221 | ||
| 144 | , 0x31410613, 0x51610722, 0x71143281, 0x91a10823 | ||
| 145 | , 0x42b1c115, 0x52d1f024, 0x33627282, 0x090a1617 | ||
| 146 | , 0x18191a25, 0x26272829, 0x2a343536, 0x3738393a | ||
| 147 | , 0x43444546, 0x4748494a, 0x53545556, 0x5758595a | ||
| 148 | , 0x63646566, 0x6768696a, 0x73747576, 0x7778797a | ||
| 149 | , 0x83848586, 0x8788898a, 0x92939495, 0x96979899 | ||
| 150 | , 0x9aa2a3a4, 0xa5a6a7a8, 0xa9aab2b3, 0xb4b5b6b7 | ||
| 151 | , 0xb8b9bac2, 0xc3c4c5c6, 0xc7c8c9ca, 0xd2d3d4d5 | ||
| 152 | , 0xd6d7d8d9, 0xdae1e2e3, 0xe4e5e6e7, 0xe8e9eaf1 | ||
| 153 | , 0xf2f3f4f5, 0xf6f7f8f9, 0xfaffc400, 0x1f010003 | ||
| 154 | , 0x01010101, 0x01010101, 0x01000000, 0x00000001 | ||
| 155 | , 0x02030405, 0x06070809, 0x0a0bffc4, 0x00b51100 | ||
| 156 | , 0x02010204, 0x04030407, 0x05040400, 0x01027700 | ||
| 157 | , 0x01020311, 0x04052131, 0x06124151, 0x07617113 | ||
| 158 | , 0x22328108, 0x144291a1, 0xb1c10923, 0x3352f015 | ||
| 159 | , 0x6272d10a, 0x162434e1, 0x25f11718, 0x191a2627 | ||
| 160 | , 0x28292a35, 0x36373839, 0x3a434445, 0x46474849 | ||
| 161 | , 0x4a535455, 0x56575859, 0x5a636465, 0x66676869 | ||
| 162 | , 0x6a737475, 0x76777879, 0x7a828384, 0x85868788 | ||
| 163 | , 0x898a9293, 0x94959697, 0x98999aa2, 0xa3a4a5a6 | ||
| 164 | , 0xa7a8a9aa, 0xb2b3b4b5, 0xb6b7b8b9, 0xbac2c3c4 | ||
| 165 | , 0xc5c6c7c8, 0xc9cad2d3, 0xd4d5d6d7, 0xd8d9dae2 | ||
| 166 | , 0xe3e4e5e6, 0xe7e8e9ea, 0xf2f3f4f5, 0xf6f7f8f9 | ||
| 167 | , 0xfaffda00, 0x0c030100, 0x02110311, 0x003f00f8 | ||
| 168 | , 0xe7e37fc6, 0xff00197f, 0xc142fc65, 0x17ed5bfb | ||
| 169 | , 0x56db699e, 0x27f14f89, 0xf4cb7b85, 0x5bcd3924 | ||
| 170 | , 0xb5d1ed5d, 0x3cc8b4db, 0x08a4ddf6, 0x6b387cc6 | ||
| 171 | , 0x09182599, 0x99e595e5, 0x9e69a693, 0xbaf0dffc | ||
| 172 | , 0x1c9dff00, 0x050aff00, 0x82637837, 0x44fd94be | ||
| 173 | , 0x11e89f0f, 0xfc61e16d, 0x334c5b8f, 0x0f37c45d | ||
| 174 | , 0x26fef2eb, 0x46b56778, 0xd34db796, 0xd6fadbfd | ||
| 175 | , 0x0e2f2898, 0xa3903b42, 0xb21891d6, 0x08e08623 | ||
| 176 | , 0xfe0e4ef0, 0xdf837fe0, 0x98dff050, 0xbb2f847f | ||
| 177 | , 0xb2978274, 0xcd33c2de, 0x30f87f69, 0xe2e6f0f5 | ||
| 178 | , 0xe44ef6ba, 0x35d5c5fe, 0xa16b2dad, 0x8246d1f9 | ||
| 179 | , 0x167fe84b, 0x2a40772c, 0x2d33c717, 0x9702c304 | ||
| 180 | , 0x5fb0dff0, 0x4abff825, 0x5ffc13d7, 0xc55ff04f | ||
| 181 | , 0x5f845f17, 0x3e2e7ec8, 0xbf0ffe21, 0xf8a7e21f | ||
| 182 | , 0xc3fd1fc5, 0xde21f10f, 0xc45f0758, 0x6b774b75 | ||
| 183 | , 0xa9584174, 0xf6b6ef75, 0x0b7d9ace, 0x1f304514 | ||
| 184 | , 0x11ed50a8, 0x647f3279, 0x679e5fcf, 0x720cbb37 | ||
| 185 | , 0xc3f1257a, 0x95eb7343, 0xdebabc9d, 0xeef4d1ab | ||
| 186 | , 0x2b7e1b2d, 0x0fec0f16, 0xb8c7c3cc, 0xdbc15caf | ||
| 187 | , 0x0795e59e, 0xc710fd97, 0x2cfd9d38, 0xf2f241aa | ||
| 188 | , 0x9efc64e5, 0x2e67dd7b, 0xdf14acd1, 0xffd90000 | ||
| 189 | |||
| 190 | }; | ||
| 191 | |||
| 192 | static private byte[] wordsToBytes(int[] wordArray) { | ||
| 193 | byte[] bytes = new byte[wordArray.length * 4]; | ||
| 194 | int inx = bytes.length; | ||
| 195 | for (int i = wordArray.length-1; i >= 0; --i) { | ||
| 196 | int word = wordArray[i]; | ||
| 197 | for (int j = 0; j < 4; ++j) { | ||
| 198 | bytes[--inx] = (byte)(word & 0xff); | ||
| 199 | word = word >>> 8; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | return bytes; | ||
| 203 | } | ||
| 204 | |||
| 205 | static Icon stopSignIcon = new ImageIcon(wordsToBytes(stopSignWords)); | ||
| 206 | static Icon blankIcon = new ImageIcon(wordsToBytes(blank)); | ||
| 207 | |||
| 208 | static Icon execIcon = new ImageIcon(wordsToBytes(exec)); | ||
| 209 | } | ||
| @@ -0,0 +1,269 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.File; | ||
| 29 | import java.util.Hashtable; | ||
| 30 | import java.util.Enumeration; | ||
| 31 | import javax.swing.filechooser.*; | ||
| 32 | |||
| 33 | //### Renamed from 'ExampleFileFilter.java' provided with Swing demos. | ||
| 34 | |||
| 35 | /** | ||
| 36 | * A convenience implementation of FileFilter that filters out | ||
| 37 | * all files except for those type extensions that it knows about. | ||
| 38 | * | ||
| 39 | * Extensions are of the type ".foo", which is typically found on | ||
| 40 | * Windows and Unix boxes, but not on Macinthosh. Case is ignored. | ||
| 41 | * | ||
| 42 | * Example - create a new filter that filerts out all files | ||
| 43 | * but gif and jpg image files: | ||
| 44 | * | ||
| 45 | * JFileChooser chooser = new JFileChooser(); | ||
| 46 | * ExampleFileFilter filter = new ExampleFileFilter( | ||
| 47 | * new String{"gif", "jpg"}, "JPEG & GIF Images") | ||
| 48 | * chooser.addChoosableFileFilter(filter); | ||
| 49 | * chooser.showOpenDialog(this); | ||
| 50 | * | ||
| 51 | * @author Jeff Dinkins | ||
| 52 | */ | ||
| 53 | |||
| 54 | public class JDBFileFilter extends FileFilter { | ||
| 55 | |||
| 56 | private static String TYPE_UNKNOWN = "Type Unknown"; | ||
| 57 | private static String HIDDEN_FILE = "Hidden File"; | ||
| 58 | |||
| 59 | private Hashtable<String, JDBFileFilter> filters = null; | ||
| 60 | private String description = null; | ||
| 61 | private String fullDescription = null; | ||
| 62 | private boolean useExtensionsInDescription = true; | ||
| 63 | |||
| 64 | /** | ||
| 65 | * Creates a file filter. If no filters are added, then all | ||
| 66 | * files are accepted. | ||
| 67 | * | ||
| 68 | * @see #addExtension | ||
| 69 | */ | ||
| 70 | public JDBFileFilter() { | ||
| 71 | this.filters = new Hashtable<String, JDBFileFilter>(); | ||
| 72 | } | ||
| 73 | |||
| 74 | /** | ||
| 75 | * Creates a file filter that accepts files with the given extension. | ||
| 76 | * Example: new JDBFileFilter("jpg"); | ||
| 77 | * | ||
| 78 | * @see #addExtension | ||
| 79 | */ | ||
| 80 | public JDBFileFilter(String extension) { | ||
| 81 | this(extension,null); | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Creates a file filter that accepts the given file type. | ||
| 86 | * Example: new JDBFileFilter("jpg", "JPEG Image Images"); | ||
| 87 | * | ||
| 88 | * Note that the "." before the extension is not needed. If | ||
| 89 | * provided, it will be ignored. | ||
| 90 | * | ||
| 91 | * @see #addExtension | ||
| 92 | */ | ||
| 93 | public JDBFileFilter(String extension, String description) { | ||
| 94 | this(); | ||
| 95 | if(extension!=null) { | ||
| 96 | addExtension(extension); | ||
| 97 | } | ||
| 98 | if(description!=null) { | ||
| 99 | setDescription(description); | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | /** | ||
| 104 | * Creates a file filter from the given string array. | ||
| 105 | * Example: new JDBFileFilter(String {"gif", "jpg"}); | ||
| 106 | * | ||
| 107 | * Note that the "." before the extension is not needed adn | ||
| 108 | * will be ignored. | ||
| 109 | * | ||
| 110 | * @see #addExtension | ||
| 111 | */ | ||
| 112 | public JDBFileFilter(String[] filters) { | ||
| 113 | this(filters, null); | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 | * Creates a file filter from the given string array and description. | ||
| 118 | * Example: new JDBFileFilter(String {"gif", "jpg"}, "Gif and JPG Images"); | ||
| 119 | * | ||
| 120 | * Note that the "." before the extension is not needed and will be ignored. | ||
| 121 | * | ||
| 122 | * @see #addExtension | ||
| 123 | */ | ||
| 124 | public JDBFileFilter(String[] filters, String description) { | ||
| 125 | this(); | ||
| 126 | for (String filter : filters) { | ||
| 127 | // add filters one by one | ||
| 128 | addExtension(filter); | ||
| 129 | } | ||
| 130 | if(description!=null) { | ||
| 131 | setDescription(description); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * Return true if this file should be shown in the directory pane, | ||
| 137 | * false if it shouldn't. | ||
| 138 | * | ||
| 139 | * Files that begin with "." are ignored. | ||
| 140 | * | ||
| 141 | * @see #getExtension | ||
| 142 | * @see FileFilter#accepts | ||
| 143 | */ | ||
| 144 | @Override | ||
| 145 | public boolean accept(File f) { | ||
| 146 | if(f != null) { | ||
| 147 | if(f.isDirectory()) { | ||
| 148 | return true; | ||
| 149 | } | ||
| 150 | String extension = getExtension(f); | ||
| 151 | if(extension != null && filters.get(getExtension(f)) != null) { | ||
| 152 | return true; | ||
| 153 | }; | ||
| 154 | } | ||
| 155 | return false; | ||
| 156 | } | ||
| 157 | |||
| 158 | /** | ||
| 159 | * Return the extension portion of the file's name . | ||
| 160 | * | ||
| 161 | * @see #getExtension | ||
| 162 | * @see FileFilter#accept | ||
| 163 | */ | ||
| 164 | public String getExtension(File f) { | ||
| 165 | if(f != null) { | ||
| 166 | String filename = f.getName(); | ||
| 167 | int i = filename.lastIndexOf('.'); | ||
| 168 | if(i>0 && i<filename.length()-1) { | ||
| 169 | return filename.substring(i+1).toLowerCase(); | ||
| 170 | }; | ||
| 171 | } | ||
| 172 | return null; | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * Adds a filetype "dot" extension to filter against. | ||
| 177 | * | ||
| 178 | * For example: the following code will create a filter that filters | ||
| 179 | * out all files except those that end in ".jpg" and ".tif": | ||
| 180 | * | ||
| 181 | * JDBFileFilter filter = new JDBFileFilter(); | ||
| 182 | * filter.addExtension("jpg"); | ||
| 183 | * filter.addExtension("tif"); | ||
| 184 | * | ||
| 185 | * Note that the "." before the extension is not needed and will be ignored. | ||
| 186 | */ | ||
| 187 | public void addExtension(String extension) { | ||
| 188 | if(filters == null) { | ||
| 189 | filters = new Hashtable<String, JDBFileFilter>(5); | ||
| 190 | } | ||
| 191 | filters.put(extension.toLowerCase(), this); | ||
| 192 | fullDescription = null; | ||
| 193 | } | ||
| 194 | |||
| 195 | |||
| 196 | /** | ||
| 197 | * Returns the human readable description of this filter. For | ||
| 198 | * example: "JPEG and GIF Image Files (*.jpg, *.gif)" | ||
| 199 | * | ||
| 200 | * @see setDescription | ||
| 201 | * @see setExtensionListInDescription | ||
| 202 | * @see isExtensionListInDescription | ||
| 203 | * @see FileFilter#getDescription | ||
| 204 | */ | ||
| 205 | @Override | ||
| 206 | public String getDescription() { | ||
| 207 | if(fullDescription == null) { | ||
| 208 | if(description == null || isExtensionListInDescription()) { | ||
| 209 | fullDescription = description==null ? "(" : description + " ("; | ||
| 210 | // build the description from the extension list | ||
| 211 | Enumeration<String> extensions = filters.keys(); | ||
| 212 | if(extensions != null) { | ||
| 213 | fullDescription += "." + extensions.nextElement(); | ||
| 214 | while (extensions.hasMoreElements()) { | ||
| 215 | fullDescription += ", " + extensions.nextElement(); | ||
| 216 | } | ||
| 217 | } | ||
| 218 | fullDescription += ")"; | ||
| 219 | } else { | ||
| 220 | fullDescription = description; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | return fullDescription; | ||
| 224 | } | ||
| 225 | |||
| 226 | /** | ||
| 227 | * Sets the human readable description of this filter. For | ||
| 228 | * example: filter.setDescription("Gif and JPG Images"); | ||
| 229 | * | ||
| 230 | * @see setDescription | ||
| 231 | * @see setExtensionListInDescription | ||
| 232 | * @see isExtensionListInDescription | ||
| 233 | */ | ||
| 234 | public void setDescription(String description) { | ||
| 235 | this.description = description; | ||
| 236 | fullDescription = null; | ||
| 237 | } | ||
| 238 | |||
| 239 | /** | ||
| 240 | * Determines whether the extension list (.jpg, .gif, etc) should | ||
| 241 | * show up in the human readable description. | ||
| 242 | * | ||
| 243 | * Only relevent if a description was provided in the constructor | ||
| 244 | * or using setDescription(); | ||
| 245 | * | ||
| 246 | * @see getDescription | ||
| 247 | * @see setDescription | ||
| 248 | * @see isExtensionListInDescription | ||
| 249 | */ | ||
| 250 | public void setExtensionListInDescription(boolean b) { | ||
| 251 | useExtensionsInDescription = b; | ||
| 252 | fullDescription = null; | ||
| 253 | } | ||
| 254 | |||
| 255 | /** | ||
| 256 | * Returns whether the extension list (.jpg, .gif, etc) should | ||
| 257 | * show up in the human readable description. | ||
| 258 | * | ||
| 259 | * Only relevent if a description was provided in the constructor | ||
| 260 | * or using setDescription(); | ||
| 261 | * | ||
| 262 | * @see getDescription | ||
| 263 | * @see setDescription | ||
| 264 | * @see setExtensionListInDescription | ||
| 265 | */ | ||
| 266 | public boolean isExtensionListInDescription() { | ||
| 267 | return useExtensionsInDescription; | ||
| 268 | } | ||
| 269 | } | ||
| @@ -0,0 +1,190 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import javax.swing.*; | ||
| 29 | import java.awt.*; | ||
| 30 | import java.awt.event.*; | ||
| 31 | import java.util.Vector; | ||
| 32 | import java.util.List; | ||
| 33 | |||
| 34 | import com.sun.tools.example.debug.bdi.*; | ||
| 35 | |||
| 36 | //### This is currently just a placeholder! | ||
| 37 | |||
| 38 | class JDBMenuBar extends JMenuBar { | ||
| 39 | |||
| 40 | Environment env; | ||
| 41 | |||
| 42 | ExecutionManager runtime; | ||
| 43 | ClassManager classManager; | ||
| 44 | SourceManager sourceManager; | ||
| 45 | |||
| 46 | CommandInterpreter interpreter; | ||
| 47 | |||
| 48 | JDBMenuBar(Environment env) { | ||
| 49 | this.env = env; | ||
| 50 | this.runtime = env.getExecutionManager(); | ||
| 51 | this.classManager = env.getClassManager(); | ||
| 52 | this.sourceManager = env.getSourceManager(); | ||
| 53 | this.interpreter = new CommandInterpreter(env, true); | ||
| 54 | |||
| 55 | JMenu fileMenu = new JMenu("File"); | ||
| 56 | |||
| 57 | JMenuItem openItem = new JMenuItem("Open...", 'O'); | ||
| 58 | openItem.addActionListener(new ActionListener() { | ||
| 59 | @Override | ||
| 60 | public void actionPerformed(ActionEvent e) { | ||
| 61 | openCommand(); | ||
| 62 | } | ||
| 63 | }); | ||
| 64 | fileMenu.add(openItem); | ||
| 65 | addTool(fileMenu, "Exit debugger", "Exit", "exit"); | ||
| 66 | |||
| 67 | JMenu cmdMenu = new JMenu("Commands"); | ||
| 68 | |||
| 69 | addTool(cmdMenu, "Step into next line", "Step", "step"); | ||
| 70 | addTool(cmdMenu, "Step over next line", "Next", "next"); | ||
| 71 | cmdMenu.addSeparator(); | ||
| 72 | |||
| 73 | addTool(cmdMenu, "Step into next instruction", | ||
| 74 | "Step Instruction", "stepi"); | ||
| 75 | addTool(cmdMenu, "Step over next instruction", | ||
| 76 | "Next Instruction", "nexti"); | ||
| 77 | cmdMenu.addSeparator(); | ||
| 78 | |||
| 79 | addTool(cmdMenu, "Step out of current method call", | ||
| 80 | "Step Up", "step up"); | ||
| 81 | cmdMenu.addSeparator(); | ||
| 82 | |||
| 83 | addTool(cmdMenu, "Suspend execution", "Interrupt", "interrupt"); | ||
| 84 | addTool(cmdMenu, "Continue execution", "Continue", "cont"); | ||
| 85 | cmdMenu.addSeparator(); | ||
| 86 | |||
| 87 | addTool(cmdMenu, "Display current stack", "Where", "where"); | ||
| 88 | cmdMenu.addSeparator(); | ||
| 89 | |||
| 90 | addTool(cmdMenu, "Move up one stack frame", "Up", "up"); | ||
| 91 | addTool(cmdMenu, "Move down one stack frame", "Down", "down"); | ||
| 92 | cmdMenu.addSeparator(); | ||
| 93 | |||
| 94 | JMenuItem monitorItem = new JMenuItem("Monitor Expression...", 'M'); | ||
| 95 | monitorItem.addActionListener(new ActionListener() { | ||
| 96 | @Override | ||
| 97 | public void actionPerformed(ActionEvent e) { | ||
| 98 | monitorCommand(); | ||
| 99 | } | ||
| 100 | }); | ||
| 101 | cmdMenu.add(monitorItem); | ||
| 102 | |||
| 103 | JMenuItem unmonitorItem = new JMenuItem("Unmonitor Expression..."); | ||
| 104 | unmonitorItem.addActionListener(new ActionListener() { | ||
| 105 | @Override | ||
| 106 | public void actionPerformed(ActionEvent e) { | ||
| 107 | unmonitorCommand(); | ||
| 108 | } | ||
| 109 | }); | ||
| 110 | cmdMenu.add(unmonitorItem); | ||
| 111 | |||
| 112 | JMenu breakpointMenu = new JMenu("Breakpoint"); | ||
| 113 | JMenuItem stopItem = new JMenuItem("Stop in...", 'S'); | ||
| 114 | stopItem.addActionListener(new ActionListener() { | ||
| 115 | @Override | ||
| 116 | public void actionPerformed(ActionEvent e) { | ||
| 117 | buildBreakpoint(); | ||
| 118 | } | ||
| 119 | }); | ||
| 120 | breakpointMenu.add(stopItem); | ||
| 121 | |||
| 122 | JMenu helpMenu = new JMenu("Help"); | ||
| 123 | addTool(helpMenu, "Display command list", "Help", "help"); | ||
| 124 | |||
| 125 | this.add(fileMenu); | ||
| 126 | this.add(cmdMenu); | ||
| 127 | // this.add(breakpointMenu); | ||
| 128 | this.add(helpMenu); | ||
| 129 | } | ||
| 130 | |||
| 131 | private void buildBreakpoint() { | ||
| 132 | Frame frame = JOptionPane.getRootFrame(); | ||
| 133 | JDialog dialog = new JDialog(frame, "Specify Breakpoint"); | ||
| 134 | Container contents = dialog.getContentPane(); | ||
| 135 | Vector<String> classes = new Vector<String>(); | ||
| 136 | classes.add("Foo"); | ||
| 137 | classes.add("Bar"); | ||
| 138 | JList list = new JList(classes); | ||
| 139 | JScrollPane scrollPane = new JScrollPane(list); | ||
| 140 | contents.add(scrollPane); | ||
| 141 | dialog.show(); | ||
| 142 | |||
| 143 | } | ||
| 144 | |||
| 145 | private void monitorCommand() { | ||
| 146 | String expr = (String)JOptionPane.showInputDialog(null, | ||
| 147 | "Expression to monitor:", "Add Monitor", | ||
| 148 | JOptionPane.QUESTION_MESSAGE, null, null, null); | ||
| 149 | if (expr != null) { | ||
| 150 | interpreter.executeCommand("monitor " + expr); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | private void unmonitorCommand() { | ||
| 155 | List monitors = env.getMonitorListModel().monitors(); | ||
| 156 | String expr = (String)JOptionPane.showInputDialog(null, | ||
| 157 | "Expression to unmonitor:", "Remove Monitor", | ||
| 158 | JOptionPane.QUESTION_MESSAGE, null, | ||
| 159 | monitors.toArray(), | ||
| 160 | monitors.get(monitors.size()-1)); | ||
| 161 | if (expr != null) { | ||
| 162 | interpreter.executeCommand("unmonitor " + expr); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | private void openCommand() { | ||
| 167 | JFileChooser chooser = new JFileChooser(); | ||
| 168 | JDBFileFilter filter = new JDBFileFilter("java", "Java source code"); | ||
| 169 | chooser.setFileFilter(filter); | ||
| 170 | int result = chooser.showOpenDialog(this); | ||
| 171 | if (result == JFileChooser.APPROVE_OPTION) { | ||
| 172 | System.out.println("Chose file: " + chooser.getSelectedFile().getName()); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | private void addTool(JMenu menu, String toolTip, String labelText, | ||
| 177 | String command) { | ||
| 178 | JMenuItem mi = new JMenuItem(labelText); | ||
| 179 | mi.setToolTipText(toolTip); | ||
| 180 | final String cmd = command; | ||
| 181 | mi.addActionListener(new ActionListener() { | ||
| 182 | @Override | ||
| 183 | public void actionPerformed(ActionEvent e) { | ||
| 184 | interpreter.executeCommand(cmd); | ||
| 185 | } | ||
| 186 | }); | ||
| 187 | menu.add(mi); | ||
| 188 | } | ||
| 189 | |||
| 190 | } | ||
| @@ -0,0 +1,101 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import javax.swing.*; | ||
| 29 | import java.awt.event.*; | ||
| 30 | |||
| 31 | import com.sun.tools.example.debug.bdi.*; | ||
| 32 | |||
| 33 | class JDBToolBar extends JToolBar { | ||
| 34 | |||
| 35 | Environment env; | ||
| 36 | |||
| 37 | ExecutionManager runtime; | ||
| 38 | ClassManager classManager; | ||
| 39 | SourceManager sourceManager; | ||
| 40 | |||
| 41 | CommandInterpreter interpreter; | ||
| 42 | |||
| 43 | JDBToolBar(Environment env) { | ||
| 44 | |||
| 45 | this.env = env; | ||
| 46 | this.runtime = env.getExecutionManager(); | ||
| 47 | this.classManager = env.getClassManager(); | ||
| 48 | this.sourceManager = env.getSourceManager(); | ||
| 49 | this.interpreter = new CommandInterpreter(env, true); | ||
| 50 | |||
| 51 | //===== Configure toolbar here ===== | ||
| 52 | |||
| 53 | addTool("Run application", "run", "run"); | ||
| 54 | addTool("Connect to application", "connect", "connect"); | ||
| 55 | addSeparator(); | ||
| 56 | |||
| 57 | addTool("Step into next line", "step", "step"); | ||
| 58 | addTool("Step over next line", "next", "next"); | ||
| 59 | // addSeparator(); | ||
| 60 | |||
| 61 | // addTool("Step into next instruction", "stepi", "stepi"); | ||
| 62 | // addTool("Step over next instruction", "nexti", "nexti"); | ||
| 63 | // addSeparator(); | ||
| 64 | |||
| 65 | addTool("Step out of current method call", "step up", "step up"); | ||
| 66 | addSeparator(); | ||
| 67 | |||
| 68 | addTool("Suspend execution", "interrupt", "interrupt"); | ||
| 69 | addTool("Continue execution", "cont", "cont"); | ||
| 70 | addSeparator(); | ||
| 71 | |||
| 72 | // addTool("Display current stack", "where", "where"); | ||
| 73 | // addSeparator(); | ||
| 74 | |||
| 75 | addTool("Move up one stack frame", "up", "up"); | ||
| 76 | addTool("Move down one stack frame", "down", "down"); | ||
| 77 | // addSeparator(); | ||
| 78 | |||
| 79 | // addTool("Display command list", "help", "help"); | ||
| 80 | // addSeparator(); | ||
| 81 | |||
| 82 | // addTool("Exit debugger", "exit", "exit"); | ||
| 83 | |||
| 84 | //================================== | ||
| 85 | |||
| 86 | } | ||
| 87 | |||
| 88 | private void addTool(String toolTip, String labelText, String command) { | ||
| 89 | JButton button = new JButton(labelText); | ||
| 90 | button.setToolTipText(toolTip); | ||
| 91 | final String cmd = command; | ||
| 92 | button.addActionListener(new ActionListener() { | ||
| 93 | @Override | ||
| 94 | public void actionPerformed(ActionEvent e) { | ||
| 95 | interpreter.executeCommand(cmd); | ||
| 96 | } | ||
| 97 | }); | ||
| 98 | this.add(button); | ||
| 99 | } | ||
| 100 | |||
| 101 | } | ||
| @@ -0,0 +1,263 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1999, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.util.List; | ||
| 29 | import java.util.ArrayList; | ||
| 30 | import java.util.Map; | ||
| 31 | import java.util.HashMap; | ||
| 32 | import java.awt.BorderLayout; | ||
| 33 | import java.awt.Container; | ||
| 34 | import java.awt.event.ActionEvent; | ||
| 35 | import java.awt.event.ActionListener; | ||
| 36 | import javax.swing.*; | ||
| 37 | import javax.swing.border.Border; | ||
| 38 | import javax.swing.border.TitledBorder; | ||
| 39 | |||
| 40 | import com.sun.jdi.*; | ||
| 41 | import com.sun.jdi.connect.*; | ||
| 42 | |||
| 43 | import com.sun.tools.example.debug.bdi.*; | ||
| 44 | |||
| 45 | class LaunchTool { | ||
| 46 | |||
| 47 | private final ExecutionManager runtime; | ||
| 48 | |||
| 49 | private abstract class ArgRep { | ||
| 50 | final Connector.Argument arg; | ||
| 51 | final JPanel panel; | ||
| 52 | |||
| 53 | ArgRep(Connector.Argument arg) { | ||
| 54 | this.arg = arg; | ||
| 55 | panel = new JPanel(); | ||
| 56 | Border etched = BorderFactory.createEtchedBorder(); | ||
| 57 | Border titled = BorderFactory.createTitledBorder(etched, | ||
| 58 | arg.description(), | ||
| 59 | TitledBorder.LEFT, TitledBorder.TOP); | ||
| 60 | panel.setBorder(titled); | ||
| 61 | } | ||
| 62 | |||
| 63 | abstract String getText(); | ||
| 64 | |||
| 65 | boolean isValid() { | ||
| 66 | return arg.isValid(getText()); | ||
| 67 | } | ||
| 68 | |||
| 69 | boolean isSpecified() { | ||
| 70 | String value = getText(); | ||
| 71 | return (value != null && value.length() > 0) || | ||
| 72 | !arg.mustSpecify(); | ||
| 73 | } | ||
| 74 | |||
| 75 | void install() { | ||
| 76 | arg.setValue(getText()); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | private class StringArgRep extends ArgRep { | ||
| 81 | final JTextField textField; | ||
| 82 | |||
| 83 | StringArgRep(Connector.Argument arg, JPanel comp) { | ||
| 84 | super(arg); | ||
| 85 | textField = new JTextField(arg.value(), 50 ); | ||
| 86 | textField.setBorder(BorderFactory.createLoweredBevelBorder()); | ||
| 87 | |||
| 88 | panel.add(new JLabel(arg.label(), SwingConstants.RIGHT)); | ||
| 89 | panel.add(textField); // , BorderLayout.CENTER); | ||
| 90 | comp.add(panel); | ||
| 91 | } | ||
| 92 | |||
| 93 | @Override | ||
| 94 | String getText() { | ||
| 95 | return textField.getText(); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | private class BooleanArgRep extends ArgRep { | ||
| 100 | final JCheckBox check; | ||
| 101 | |||
| 102 | BooleanArgRep(Connector.BooleanArgument barg, JPanel comp) { | ||
| 103 | super(barg); | ||
| 104 | check = new JCheckBox(barg.label()); | ||
| 105 | check.setSelected(barg.booleanValue()); | ||
| 106 | panel.add(check); | ||
| 107 | comp.add(panel); | ||
| 108 | } | ||
| 109 | |||
| 110 | @Override | ||
| 111 | String getText() { | ||
| 112 | return ((Connector.BooleanArgument)arg) | ||
| 113 | .stringValueOf(check.getModel().isSelected()); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | |||
| 118 | private LaunchTool(ExecutionManager runtime) { | ||
| 119 | this.runtime = runtime; | ||
| 120 | } | ||
| 121 | |||
| 122 | private Connector selectConnector() { | ||
| 123 | final JDialog dialog = new JDialog(); | ||
| 124 | Container content = dialog.getContentPane(); | ||
| 125 | final JPanel radioPanel = new JPanel(); | ||
| 126 | final ButtonGroup radioGroup = new ButtonGroup(); | ||
| 127 | VirtualMachineManager manager = Bootstrap.virtualMachineManager(); | ||
| 128 | List<Connector> all = manager.allConnectors(); | ||
| 129 | Map<ButtonModel, Connector> modelToConnector = new HashMap<ButtonModel, Connector>(all.size(), 0.5f); | ||
| 130 | |||
| 131 | dialog.setModal(true); | ||
| 132 | dialog.setTitle("Select Connector Type"); | ||
| 133 | radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.Y_AXIS)); | ||
| 134 | for (Connector connector : all) { | ||
| 135 | JRadioButton radio = new JRadioButton(connector.description()); | ||
| 136 | modelToConnector.put(radio.getModel(), connector); | ||
| 137 | radioPanel.add(radio); | ||
| 138 | radioGroup.add(radio); | ||
| 139 | } | ||
| 140 | content.add(radioPanel); | ||
| 141 | |||
| 142 | final boolean[] oked = {false}; | ||
| 143 | JPanel buttonPanel = okCancel( dialog, new ActionListener() { | ||
| 144 | @Override | ||
| 145 | public void actionPerformed(ActionEvent event) { | ||
| 146 | if (radioGroup.getSelection() == null) { | ||
| 147 | JOptionPane.showMessageDialog(dialog, | ||
| 148 | "Please select a connector type", | ||
| 149 | "No Selection", | ||
| 150 | JOptionPane.ERROR_MESSAGE); | ||
| 151 | } else { | ||
| 152 | oked[0] = true; | ||
| 153 | dialog.setVisible(false); | ||
| 154 | dialog.dispose(); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | } ); | ||
| 158 | content.add(BorderLayout.SOUTH, buttonPanel); | ||
| 159 | dialog.pack(); | ||
| 160 | dialog.setVisible(true); | ||
| 161 | |||
| 162 | return oked[0] ? | ||
| 163 | modelToConnector.get(radioGroup.getSelection()) : | ||
| 164 | null; | ||
| 165 | } | ||
| 166 | |||
| 167 | private void configureAndConnect(final Connector connector) { | ||
| 168 | final JDialog dialog = new JDialog(); | ||
| 169 | final Map<String, Connector.Argument> args = connector.defaultArguments(); | ||
| 170 | |||
| 171 | dialog.setModal(true); | ||
| 172 | dialog.setTitle("Connector Arguments"); | ||
| 173 | Container content = dialog.getContentPane(); | ||
| 174 | JPanel guts = new JPanel(); | ||
| 175 | Border etched = BorderFactory.createEtchedBorder(); | ||
| 176 | BorderFactory.createTitledBorder(etched, | ||
| 177 | connector.description(), | ||
| 178 | TitledBorder.LEFT, TitledBorder.TOP); | ||
| 179 | guts.setBorder(etched); | ||
| 180 | guts.setLayout(new BoxLayout(guts, BoxLayout.Y_AXIS)); | ||
| 181 | |||
| 182 | // guts.add(new JLabel(connector.description())); | ||
| 183 | |||
| 184 | final List<ArgRep> argReps = new ArrayList<ArgRep>(args.size()); | ||
| 185 | for (Connector.Argument arg : args.values()) { | ||
| 186 | ArgRep ar; | ||
| 187 | if (arg instanceof Connector.BooleanArgument) { | ||
| 188 | ar = new BooleanArgRep((Connector.BooleanArgument)arg, guts); | ||
| 189 | } else { | ||
| 190 | ar = new StringArgRep(arg, guts); | ||
| 191 | } | ||
| 192 | argReps.add(ar); | ||
| 193 | } | ||
| 194 | content.add(guts); | ||
| 195 | |||
| 196 | JPanel buttonPanel = okCancel( dialog, new ActionListener() { | ||
| 197 | @Override | ||
| 198 | public void actionPerformed(ActionEvent event) { | ||
| 199 | for (ArgRep ar : argReps) { | ||
| 200 | if (!ar.isSpecified()) { | ||
| 201 | JOptionPane.showMessageDialog(dialog, | ||
| 202 | ar.arg.label() + | ||
| 203 | ": Argument must be specified", | ||
| 204 | "No argument", JOptionPane.ERROR_MESSAGE); | ||
| 205 | return; | ||
| 206 | } | ||
| 207 | if (!ar.isValid()) { | ||
| 208 | JOptionPane.showMessageDialog(dialog, | ||
| 209 | ar.arg.label() + | ||
| 210 | ": Bad argument value: " + | ||
| 211 | ar.getText(), | ||
| 212 | "Bad argument", JOptionPane.ERROR_MESSAGE); | ||
| 213 | return; | ||
| 214 | } | ||
| 215 | ar.install(); | ||
| 216 | } | ||
| 217 | try { | ||
| 218 | if (runtime.explictStart(connector, args)) { | ||
| 219 | dialog.setVisible(false); | ||
| 220 | dialog.dispose(); | ||
| 221 | } else { | ||
| 222 | JOptionPane.showMessageDialog(dialog, | ||
| 223 | "Bad arguments values: See diagnostics window.", | ||
| 224 | "Bad arguments", JOptionPane.ERROR_MESSAGE); | ||
| 225 | } | ||
| 226 | } catch (VMLaunchFailureException exc) { | ||
| 227 | JOptionPane.showMessageDialog(dialog, | ||
| 228 | "Launch Failure: " + exc, | ||
| 229 | "Launch Failed",JOptionPane.ERROR_MESSAGE); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | } ); | ||
| 233 | content.add(BorderLayout.SOUTH, buttonPanel); | ||
| 234 | dialog.pack(); | ||
| 235 | dialog.setVisible(true); | ||
| 236 | } | ||
| 237 | |||
| 238 | private JPanel okCancel(final JDialog dialog, ActionListener okListener) { | ||
| 239 | JPanel buttonPanel = new JPanel(); | ||
| 240 | JButton ok = new JButton("OK"); | ||
| 241 | JButton cancel = new JButton("Cancel"); | ||
| 242 | buttonPanel.add(ok); | ||
| 243 | buttonPanel.add(cancel); | ||
| 244 | ok.addActionListener(okListener); | ||
| 245 | cancel.addActionListener( new ActionListener() { | ||
| 246 | @Override | ||
| 247 | public void actionPerformed(ActionEvent event) { | ||
| 248 | dialog.setVisible(false); | ||
| 249 | dialog.dispose(); | ||
| 250 | } | ||
| 251 | } ); | ||
| 252 | return buttonPanel; | ||
| 253 | } | ||
| 254 | |||
| 255 | static void queryAndLaunchVM(ExecutionManager runtime) | ||
| 256 | throws VMLaunchFailureException { | ||
| 257 | LaunchTool lt = new LaunchTool(runtime); | ||
| 258 | Connector connector = lt.selectConnector(); | ||
| 259 | if (connector != null) { | ||
| 260 | lt.configureAndConnect(connector); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | } | ||
| @@ -0,0 +1,90 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.util.*; | ||
| 29 | |||
| 30 | import javax.swing.AbstractListModel; | ||
| 31 | |||
| 32 | public class MonitorListModel extends AbstractListModel { | ||
| 33 | |||
| 34 | private final List<String> monitors = new ArrayList<String>(); | ||
| 35 | |||
| 36 | MonitorListModel(Environment env) { | ||
| 37 | |||
| 38 | // Create listener. | ||
| 39 | MonitorListListener listener = new MonitorListListener(); | ||
| 40 | env.getContextManager().addContextListener(listener); | ||
| 41 | |||
| 42 | //### remove listeners on exit! | ||
| 43 | } | ||
| 44 | |||
| 45 | @Override | ||
| 46 | public Object getElementAt(int index) { | ||
| 47 | return monitors.get(index); | ||
| 48 | } | ||
| 49 | |||
| 50 | @Override | ||
| 51 | public int getSize() { | ||
| 52 | return monitors.size(); | ||
| 53 | } | ||
| 54 | |||
| 55 | public void add(String expr) { | ||
| 56 | monitors.add(expr); | ||
| 57 | int newIndex = monitors.size()-1; // order important | ||
| 58 | fireIntervalAdded(this, newIndex, newIndex); | ||
| 59 | } | ||
| 60 | |||
| 61 | public void remove(String expr) { | ||
| 62 | int index = monitors.indexOf(expr); | ||
| 63 | remove(index); | ||
| 64 | } | ||
| 65 | |||
| 66 | public void remove(int index) { | ||
| 67 | monitors.remove(index); | ||
| 68 | fireIntervalRemoved(this, index, index); | ||
| 69 | } | ||
| 70 | |||
| 71 | public List<String> monitors() { | ||
| 72 | return Collections.unmodifiableList(monitors); | ||
| 73 | } | ||
| 74 | |||
| 75 | public Iterator<?> iterator() { | ||
| 76 | return monitors().iterator(); | ||
| 77 | } | ||
| 78 | |||
| 79 | private void invalidate() { | ||
| 80 | fireContentsChanged(this, 0, monitors.size()-1); | ||
| 81 | } | ||
| 82 | |||
| 83 | private class MonitorListListener implements ContextListener { | ||
| 84 | |||
| 85 | @Override | ||
| 86 | public void currentFrameChanged(final CurrentFrameChangedEvent e) { | ||
| 87 | invalidate(); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| @@ -0,0 +1,125 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import javax.swing.*; | ||
| 29 | import javax.swing.event.*; | ||
| 30 | import java.awt.*; | ||
| 31 | import com.sun.jdi.*; | ||
| 32 | import com.sun.tools.example.debug.bdi.*; | ||
| 33 | import com.sun.tools.example.debug.expr.ExpressionParser; | ||
| 34 | import com.sun.tools.example.debug.expr.ParseException; | ||
| 35 | |||
| 36 | public class MonitorTool extends JPanel { | ||
| 37 | |||
| 38 | private static final long serialVersionUID = -645235951031726647L; | ||
| 39 | private ExecutionManager runtime; | ||
| 40 | private ContextManager context; | ||
| 41 | |||
| 42 | private JList list; | ||
| 43 | |||
| 44 | public MonitorTool(Environment env) { | ||
| 45 | super(new BorderLayout()); | ||
| 46 | this.runtime = env.getExecutionManager(); | ||
| 47 | this.context = env.getContextManager(); | ||
| 48 | |||
| 49 | list = new JList(env.getMonitorListModel()); | ||
| 50 | list.setCellRenderer(new MonitorRenderer()); | ||
| 51 | |||
| 52 | JScrollPane listView = new JScrollPane(list); | ||
| 53 | add(listView); | ||
| 54 | |||
| 55 | // Create listener. | ||
| 56 | MonitorToolListener listener = new MonitorToolListener(); | ||
| 57 | list.addListSelectionListener(listener); | ||
| 58 | //### remove listeners on exit! | ||
| 59 | } | ||
| 60 | |||
| 61 | private class MonitorToolListener implements ListSelectionListener { | ||
| 62 | @Override | ||
| 63 | public void valueChanged(ListSelectionEvent e) { | ||
| 64 | int index = list.getSelectedIndex(); | ||
| 65 | if (index != -1) { | ||
| 66 | } | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | private Value evaluate(String expr) throws ParseException, | ||
| 71 | InvocationException, | ||
| 72 | InvalidTypeException, | ||
| 73 | ClassNotLoadedException, | ||
| 74 | IncompatibleThreadStateException { | ||
| 75 | ExpressionParser.GetFrame frameGetter = | ||
| 76 | new ExpressionParser.GetFrame() { | ||
| 77 | @Override | ||
| 78 | public StackFrame get() | ||
| 79 | throws IncompatibleThreadStateException | ||
| 80 | { | ||
| 81 | try { | ||
| 82 | return context.getCurrentFrame(); | ||
| 83 | } catch (VMNotInterruptedException exc) { | ||
| 84 | throw new IncompatibleThreadStateException(); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | }; | ||
| 88 | return ExpressionParser.evaluate(expr, runtime.vm(), frameGetter); | ||
| 89 | } | ||
| 90 | |||
| 91 | private class MonitorRenderer extends DefaultListCellRenderer { | ||
| 92 | |||
| 93 | @Override | ||
| 94 | public Component getListCellRendererComponent(JList list, | ||
| 95 | Object value, | ||
| 96 | int index, | ||
| 97 | boolean isSelected, | ||
| 98 | boolean cellHasFocus) { | ||
| 99 | |||
| 100 | //### We should indicate the current thread independently of the | ||
| 101 | //### selection, e.g., with an icon, because the user may change | ||
| 102 | //### the selection graphically without affecting the current | ||
| 103 | //### thread. | ||
| 104 | |||
| 105 | super.getListCellRendererComponent(list, value, index, | ||
| 106 | isSelected, cellHasFocus); | ||
| 107 | if (value == null) { | ||
| 108 | this.setText("<unavailable>"); | ||
| 109 | } else { | ||
| 110 | String expr = (String)value; | ||
| 111 | try { | ||
| 112 | Value result = evaluate(expr); | ||
| 113 | this.setText(expr + " = " + result); | ||
| 114 | } catch (ParseException exc) { | ||
| 115 | this.setText(expr + " ? " + exc.getMessage()); | ||
| 116 | } catch (IncompatibleThreadStateException exc) { | ||
| 117 | this.setText(expr + " ..."); | ||
| 118 | } catch (Exception exc) { | ||
| 119 | this.setText(expr + " ? " + exc); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | return this; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | |||
| 30 | // This class is used in 'CommandInterpreter' as a hook to | ||
| 31 | // allow messagebox style command output as an alternative | ||
| 32 | // to a typescript. It should be an interface, not a class. | ||
| 33 | |||
| 34 | public class OutputSink extends PrintWriter { | ||
| 35 | |||
| 36 | // Currently, we do no buffering, | ||
| 37 | // so 'show' is a no-op. | ||
| 38 | |||
| 39 | OutputSink(Writer writer) { | ||
| 40 | super(writer); | ||
| 41 | } | ||
| 42 | |||
| 43 | public void show() { | ||
| 44 | // ignore | ||
| 45 | } | ||
| 46 | } | ||
| @@ -0,0 +1,95 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.util.*; | ||
| 30 | |||
| 31 | public class SearchPath { | ||
| 32 | |||
| 33 | private String pathString; | ||
| 34 | |||
| 35 | private String[] pathArray; | ||
| 36 | |||
| 37 | public SearchPath(String searchPath) { | ||
| 38 | //### Should check searchpath for well-formedness. | ||
| 39 | StringTokenizer st = new StringTokenizer(searchPath, File.pathSeparator); | ||
| 40 | List<String> dlist = new ArrayList<String>(); | ||
| 41 | while (st.hasMoreTokens()) { | ||
| 42 | dlist.add(st.nextToken()); | ||
| 43 | } | ||
| 44 | pathString = searchPath; | ||
| 45 | pathArray = dlist.toArray(new String[dlist.size()]); | ||
| 46 | } | ||
| 47 | |||
| 48 | public boolean isEmpty() { | ||
| 49 | return (pathArray.length == 0); | ||
| 50 | } | ||
| 51 | |||
| 52 | public String asString() { | ||
| 53 | return pathString; | ||
| 54 | } | ||
| 55 | |||
| 56 | public String[] asArray() { | ||
| 57 | return pathArray.clone(); | ||
| 58 | } | ||
| 59 | |||
| 60 | public File resolve(String relativeFileName) { | ||
| 61 | for (String element : pathArray) { | ||
| 62 | File path = new File(element, relativeFileName); | ||
| 63 | if (path.exists()) { | ||
| 64 | return path; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | return null; | ||
| 68 | } | ||
| 69 | |||
| 70 | //### return List? | ||
| 71 | |||
| 72 | public String[] children(String relativeDirName, FilenameFilter filter) { | ||
| 73 | // If a file appears at the same relative path | ||
| 74 | // with respect to multiple entries on the classpath, | ||
| 75 | // the one corresponding to the earliest entry on the | ||
| 76 | // classpath is retained. This is the one that will be | ||
| 77 | // found if we later do a 'resolve'. | ||
| 78 | SortedSet<String> s = new TreeSet<String>(); // sorted, no duplicates | ||
| 79 | for (String element : pathArray) { | ||
| 80 | File path = new File(element, relativeDirName); | ||
| 81 | if (path.exists()) { | ||
| 82 | String[] childArray = path.list(filter); | ||
| 83 | if (childArray != null) { | ||
| 84 | for (int j = 0; j < childArray.length; j++) { | ||
| 85 | if (!s.contains(childArray[j])) { | ||
| 86 | s.add(childArray[j]); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| 91 | } | ||
| 92 | return s.toArray(new String[s.size()]); | ||
| 93 | } | ||
| 94 | |||
| 95 | } | ||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import javax.swing.tree.*; | ||
| 29 | |||
| 30 | public class SingleLeafTreeSelectionModel extends DefaultTreeSelectionModel { | ||
| 31 | |||
| 32 | private static final long serialVersionUID = -7849105107888117679L; | ||
| 33 | |||
| 34 | SingleLeafTreeSelectionModel() { | ||
| 35 | super(); | ||
| 36 | selectionMode = SINGLE_TREE_SELECTION; | ||
| 37 | } | ||
| 38 | |||
| 39 | @Override | ||
| 40 | public void setSelectionPath(TreePath path) { | ||
| 41 | if(((TreeNode)(path.getLastPathComponent())).isLeaf()) { | ||
| 42 | super.setSelectionPath(path); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | @Override | ||
| 47 | public void setSelectionPaths(TreePath[] paths) { | ||
| 48 | // Only look at first path, as all others will be | ||
| 49 | // ignored anyway in single tree selection mode. | ||
| 50 | if(((TreeNode)(paths[0].getLastPathComponent())).isLeaf()) { | ||
| 51 | super.setSelectionPaths(paths); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | @Override | ||
| 56 | public void addSelectionPath(TreePath path) { | ||
| 57 | if(((TreeNode)(path.getLastPathComponent())).isLeaf()) { | ||
| 58 | super.setSelectionPath(path); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | @Override | ||
| 63 | public void addSelectionPaths(TreePath[] paths) { | ||
| 64 | // Only look at first path, as all others will be | ||
| 65 | // ignored anyway in single tree selection mode. | ||
| 66 | if(((TreeNode)(paths[0].getLastPathComponent())).isLeaf()) { | ||
| 67 | super.addSelectionPaths(paths); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | public interface SourceListener { | ||
| 29 | void sourcepathChanged(SourcepathChangedEvent e); | ||
| 30 | } | ||
| @@ -0,0 +1,180 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.util.*; | ||
| 30 | |||
| 31 | import com.sun.jdi.*; | ||
| 32 | |||
| 33 | import com.sun.tools.example.debug.event.*; | ||
| 34 | |||
| 35 | /** | ||
| 36 | * Manage the list of source files. | ||
| 37 | * Origin of SourceListener events. | ||
| 38 | */ | ||
| 39 | public class SourceManager { | ||
| 40 | |||
| 41 | //### TODO: The source cache should be aged, and some cap | ||
| 42 | //### put on memory consumption by source files loaded into core. | ||
| 43 | |||
| 44 | private List<SourceModel> sourceList; | ||
| 45 | private SearchPath sourcePath; | ||
| 46 | |||
| 47 | private ArrayList<SourceListener> sourceListeners = new ArrayList<SourceListener>(); | ||
| 48 | |||
| 49 | private Map<ReferenceType, SourceModel> classToSource = new HashMap<ReferenceType, SourceModel>(); | ||
| 50 | |||
| 51 | private Environment env; | ||
| 52 | |||
| 53 | /** | ||
| 54 | * Hold on to it so it can be removed. | ||
| 55 | */ | ||
| 56 | private SMClassListener classListener = new SMClassListener(); | ||
| 57 | |||
| 58 | public SourceManager(Environment env) { | ||
| 59 | this(env, new SearchPath("")); | ||
| 60 | } | ||
| 61 | |||
| 62 | public SourceManager(Environment env, SearchPath sourcePath) { | ||
| 63 | this.env = env; | ||
| 64 | this.sourceList = new LinkedList<SourceModel>(); | ||
| 65 | this.sourcePath = sourcePath; | ||
| 66 | env.getExecutionManager().addJDIListener(classListener); | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Set path for access to source code. | ||
| 71 | */ | ||
| 72 | public void setSourcePath(SearchPath sp) { | ||
| 73 | sourcePath = sp; | ||
| 74 | // Old cached sources are now invalid. | ||
| 75 | sourceList = new LinkedList<SourceModel>(); | ||
| 76 | notifySourcepathChanged(); | ||
| 77 | classToSource = new HashMap<ReferenceType, SourceModel>(); | ||
| 78 | } | ||
| 79 | |||
| 80 | public void addSourceListener(SourceListener l) { | ||
| 81 | sourceListeners.add(l); | ||
| 82 | } | ||
| 83 | |||
| 84 | public void removeSourceListener(SourceListener l) { | ||
| 85 | sourceListeners.remove(l); | ||
| 86 | } | ||
| 87 | |||
| 88 | private void notifySourcepathChanged() { | ||
| 89 | ArrayList<SourceListener> l = new ArrayList<SourceListener>(sourceListeners); | ||
| 90 | SourcepathChangedEvent evt = new SourcepathChangedEvent(this); | ||
| 91 | for (int i = 0; i < l.size(); i++) { | ||
| 92 | l.get(i).sourcepathChanged(evt); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | /** | ||
| 97 | * Get path for access to source code. | ||
| 98 | */ | ||
| 99 | public SearchPath getSourcePath() { | ||
| 100 | return sourcePath; | ||
| 101 | } | ||
| 102 | |||
| 103 | /** | ||
| 104 | * Get source object associated with a Location. | ||
| 105 | */ | ||
| 106 | public SourceModel sourceForLocation(Location loc) { | ||
| 107 | return sourceForClass(loc.declaringType()); | ||
| 108 | } | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Get source object associated with a class or interface. | ||
| 112 | * Returns null if not available. | ||
| 113 | */ | ||
| 114 | public SourceModel sourceForClass(ReferenceType refType) { | ||
| 115 | SourceModel sm = classToSource.get(refType); | ||
| 116 | if (sm != null) { | ||
| 117 | return sm; | ||
| 118 | } | ||
| 119 | try { | ||
| 120 | String filename = refType.sourceName(); | ||
| 121 | String refName = refType.name(); | ||
| 122 | int iDot = refName.lastIndexOf('.'); | ||
| 123 | String pkgName = (iDot >= 0)? refName.substring(0, iDot+1) : ""; | ||
| 124 | String full = pkgName.replace('.', File.separatorChar) + filename; | ||
| 125 | File path = sourcePath.resolve(full); | ||
| 126 | if (path != null) { | ||
| 127 | sm = sourceForFile(path); | ||
| 128 | classToSource.put(refType, sm); | ||
| 129 | return sm; | ||
| 130 | } | ||
| 131 | return null; | ||
| 132 | } catch (AbsentInformationException e) { | ||
| 133 | return null; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | /** | ||
| 138 | * Get source object associated with an absolute file path. | ||
| 139 | */ | ||
| 140 | //### Use hash table for this? | ||
| 141 | public SourceModel sourceForFile(File path) { | ||
| 142 | Iterator<SourceModel> iter = sourceList.iterator(); | ||
| 143 | SourceModel sm = null; | ||
| 144 | while (iter.hasNext()) { | ||
| 145 | SourceModel candidate = iter.next(); | ||
| 146 | if (candidate.fileName().equals(path)) { | ||
| 147 | sm = candidate; | ||
| 148 | iter.remove(); // Will move to start of list. | ||
| 149 | break; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | if (sm == null && path.exists()) { | ||
| 153 | sm = new SourceModel(env, path); | ||
| 154 | } | ||
| 155 | if (sm != null) { | ||
| 156 | // At start of list for faster access | ||
| 157 | sourceList.add(0, sm); | ||
| 158 | } | ||
| 159 | return sm; | ||
| 160 | } | ||
| 161 | |||
| 162 | private class SMClassListener extends JDIAdapter | ||
| 163 | implements JDIListener { | ||
| 164 | |||
| 165 | @Override | ||
| 166 | public void classPrepare(ClassPrepareEventSet e) { | ||
| 167 | ReferenceType refType = e.getReferenceType(); | ||
| 168 | SourceModel sm = sourceForClass(refType); | ||
| 169 | if (sm != null) { | ||
| 170 | sm.addClass(refType); | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | @Override | ||
| 175 | public void classUnload(ClassUnloadEventSet e) { | ||
| 176 | //### iterate through looking for (e.getTypeName()). | ||
| 177 | //### then remove it. | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| @@ -0,0 +1,247 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.util.*; | ||
| 30 | |||
| 31 | import com.sun.jdi.*; | ||
| 32 | import com.sun.jdi.request.*; | ||
| 33 | |||
| 34 | import javax.swing.*; | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Represents and manages one source file. | ||
| 38 | * Caches source lines. Holds other source file info. | ||
| 39 | */ | ||
| 40 | public class SourceModel extends AbstractListModel { | ||
| 41 | |||
| 42 | private File path; | ||
| 43 | |||
| 44 | boolean isActuallySource = true; | ||
| 45 | |||
| 46 | private List<ReferenceType> classes = new ArrayList<ReferenceType>(); | ||
| 47 | |||
| 48 | private Environment env; | ||
| 49 | |||
| 50 | // Cached line-by-line access. | ||
| 51 | |||
| 52 | //### Unify this with source model used in source view? | ||
| 53 | //### What is our cache-management policy for these? | ||
| 54 | //### Even with weak refs, we won't discard any part of the | ||
| 55 | //### source if the SourceModel object is reachable. | ||
| 56 | /** | ||
| 57 | * List of Line. | ||
| 58 | */ | ||
| 59 | private List<Line> sourceLines = null; | ||
| 60 | |||
| 61 | public static class Line { | ||
| 62 | public String text; | ||
| 63 | public boolean hasBreakpoint = false; | ||
| 64 | public ReferenceType refType = null; | ||
| 65 | Line(String text) { | ||
| 66 | this.text = text; | ||
| 67 | } | ||
| 68 | public boolean isExecutable() { | ||
| 69 | return refType != null; | ||
| 70 | } | ||
| 71 | public boolean hasBreakpoint() { | ||
| 72 | return hasBreakpoint; | ||
| 73 | } | ||
| 74 | }; | ||
| 75 | |||
| 76 | // 132 characters long, all printable characters. | ||
| 77 | public static final Line prototypeCellValue = new Line( | ||
| 78 | "abcdefghijklmnopqrstuvwxyz" + | ||
| 79 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + | ||
| 80 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + | ||
| 81 | "1234567890~!@#$%^&*()_+{}|" + | ||
| 82 | ":<>?`-=[];',.XXXXXXXXXXXX/\\\""); | ||
| 83 | |||
| 84 | SourceModel(Environment env, File path) { | ||
| 85 | this.env = env; | ||
| 86 | this.path = path; | ||
| 87 | } | ||
| 88 | |||
| 89 | public SourceModel(String message) { | ||
| 90 | this.path = null; | ||
| 91 | setMessage(message); | ||
| 92 | } | ||
| 93 | |||
| 94 | private void setMessage(String message) { | ||
| 95 | isActuallySource = false; | ||
| 96 | sourceLines = new ArrayList<Line>(); | ||
| 97 | sourceLines.add(new Line(message)); | ||
| 98 | } | ||
| 99 | |||
| 100 | // **** Implement ListModel ***** | ||
| 101 | |||
| 102 | @Override | ||
| 103 | public Object getElementAt(int index) { | ||
| 104 | if (sourceLines == null) { | ||
| 105 | initialize(); | ||
| 106 | } | ||
| 107 | return sourceLines.get(index); | ||
| 108 | } | ||
| 109 | |||
| 110 | @Override | ||
| 111 | public int getSize() { | ||
| 112 | if (sourceLines == null) { | ||
| 113 | initialize(); | ||
| 114 | } | ||
| 115 | return sourceLines.size(); | ||
| 116 | } | ||
| 117 | |||
| 118 | // ***** Other functionality ***** | ||
| 119 | |||
| 120 | public File fileName() { | ||
| 121 | return path; | ||
| 122 | } | ||
| 123 | |||
| 124 | public BufferedReader sourceReader() throws IOException { | ||
| 125 | return new BufferedReader(new FileReader(path)); | ||
| 126 | } | ||
| 127 | |||
| 128 | public Line line(int lineNo) { | ||
| 129 | if (sourceLines == null) { | ||
| 130 | initialize(); | ||
| 131 | } | ||
| 132 | int index = lineNo - 1; // list is 0-indexed | ||
| 133 | if (index >= sourceLines.size() || index < 0) { | ||
| 134 | return null; | ||
| 135 | } else { | ||
| 136 | return sourceLines.get(index); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | public String sourceLine(int lineNo) { | ||
| 141 | Line line = line(lineNo); | ||
| 142 | if (line == null) { | ||
| 143 | return null; | ||
| 144 | } else { | ||
| 145 | return line.text; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | void addClass(ReferenceType refType) { | ||
| 150 | // Logically is Set | ||
| 151 | if (classes.indexOf(refType) == -1) { | ||
| 152 | classes.add(refType); | ||
| 153 | if (sourceLines != null) { | ||
| 154 | markClassLines(refType); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | /** | ||
| 160 | * @return List of currently known {@link com.sun.jdi.ReferenceType} | ||
| 161 | * in this source file. | ||
| 162 | */ | ||
| 163 | public List<ReferenceType> referenceTypes() { | ||
| 164 | return Collections.unmodifiableList(classes); | ||
| 165 | } | ||
| 166 | |||
| 167 | private void initialize() { | ||
| 168 | try { | ||
| 169 | rawInit(); | ||
| 170 | } catch (IOException exc) { | ||
| 171 | setMessage("[Error reading source code]"); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | public void showBreakpoint(int ln, boolean hasBreakpoint) { | ||
| 176 | line(ln).hasBreakpoint = hasBreakpoint; | ||
| 177 | fireContentsChanged(this, ln, ln); | ||
| 178 | } | ||
| 179 | |||
| 180 | public void showExecutable(int ln, ReferenceType refType) { | ||
| 181 | line(ln).refType = refType; | ||
| 182 | fireContentsChanged(this, ln, ln); | ||
| 183 | } | ||
| 184 | |||
| 185 | /** | ||
| 186 | * Mark executable lines and breakpoints, but only | ||
| 187 | * when sourceLines is set. | ||
| 188 | */ | ||
| 189 | private void markClassLines(ReferenceType refType) { | ||
| 190 | for (Method meth : refType.methods()) { | ||
| 191 | try { | ||
| 192 | for (Location loc : meth.allLineLocations()) { | ||
| 193 | showExecutable(loc.lineNumber(), refType); | ||
| 194 | } | ||
| 195 | } catch (AbsentInformationException exc) { | ||
| 196 | // do nothing | ||
| 197 | } | ||
| 198 | } | ||
| 199 | for (BreakpointRequest bp : | ||
| 200 | env.getExecutionManager().eventRequestManager().breakpointRequests()) { | ||
| 201 | if (bp.location() != null) { | ||
| 202 | Location loc = bp.location(); | ||
| 203 | if (loc.declaringType().equals(refType)) { | ||
| 204 | showBreakpoint(loc.lineNumber(),true); | ||
| 205 | } | ||
| 206 | } | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | private void rawInit() throws IOException { | ||
| 211 | sourceLines = new ArrayList<Line>(); | ||
| 212 | BufferedReader reader = sourceReader(); | ||
| 213 | try { | ||
| 214 | String line = reader.readLine(); | ||
| 215 | while (line != null) { | ||
| 216 | sourceLines.add(new Line(expandTabs(line))); | ||
| 217 | line = reader.readLine(); | ||
| 218 | } | ||
| 219 | } finally { | ||
| 220 | reader.close(); | ||
| 221 | } | ||
| 222 | for (ReferenceType refType : classes) { | ||
| 223 | markClassLines(refType); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | private String expandTabs(String s) { | ||
| 228 | int col = 0; | ||
| 229 | int len = s.length(); | ||
| 230 | StringBuffer sb = new StringBuffer(132); | ||
| 231 | for (int i = 0; i < len; i++) { | ||
| 232 | char c = s.charAt(i); | ||
| 233 | sb.append(c); | ||
| 234 | if (c == '\t') { | ||
| 235 | int pad = (8 - (col % 8)); | ||
| 236 | for (int j = 0; j < pad; j++) { | ||
| 237 | sb.append(' '); | ||
| 238 | } | ||
| 239 | col += pad; | ||
| 240 | } else { | ||
| 241 | col++; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | return sb.toString(); | ||
| 245 | } | ||
| 246 | |||
| 247 | } | ||
| @@ -0,0 +1,383 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.awt.*; | ||
| 30 | import java.awt.event.*; | ||
| 31 | import javax.swing.*; | ||
| 32 | |||
| 33 | import com.sun.jdi.*; | ||
| 34 | import com.sun.jdi.request.*; | ||
| 35 | |||
| 36 | import com.sun.tools.example.debug.bdi.*; | ||
| 37 | |||
| 38 | public class SourceTool extends JPanel { | ||
| 39 | |||
| 40 | private static final long serialVersionUID = -5461299294186395257L; | ||
| 41 | |||
| 42 | private Environment env; | ||
| 43 | |||
| 44 | private ExecutionManager runtime; | ||
| 45 | private ContextManager context; | ||
| 46 | private SourceManager sourceManager; | ||
| 47 | |||
| 48 | private JList list; | ||
| 49 | private ListModel sourceModel; | ||
| 50 | |||
| 51 | // Information on source file that is on display, or failed to be | ||
| 52 | // displayed due to inaccessible source. Used to update display | ||
| 53 | // when sourcepath is changed. | ||
| 54 | |||
| 55 | private String sourceName; // relative path name, if showSourceFile | ||
| 56 | private Location sourceLocn; // location, if showSourceForLocation | ||
| 57 | private CommandInterpreter interpreter; | ||
| 58 | |||
| 59 | public SourceTool(Environment env) { | ||
| 60 | |||
| 61 | super(new BorderLayout()); | ||
| 62 | |||
| 63 | this.env = env; | ||
| 64 | |||
| 65 | runtime = env.getExecutionManager(); | ||
| 66 | sourceManager = env.getSourceManager(); | ||
| 67 | this.context = env.getContextManager(); | ||
| 68 | this.interpreter = new CommandInterpreter(env, true); | ||
| 69 | |||
| 70 | sourceModel = new DefaultListModel(); // empty | ||
| 71 | |||
| 72 | list = new JList(sourceModel); | ||
| 73 | list.setCellRenderer(new SourceLineRenderer()); | ||
| 74 | |||
| 75 | list.setPrototypeCellValue(SourceModel.prototypeCellValue); | ||
| 76 | |||
| 77 | SourceToolListener listener = new SourceToolListener(); | ||
| 78 | context.addContextListener(listener); | ||
| 79 | runtime.addSpecListener(listener); | ||
| 80 | sourceManager.addSourceListener(listener); | ||
| 81 | |||
| 82 | MouseListener squeek = new STMouseListener(); | ||
| 83 | list.addMouseListener(squeek); | ||
| 84 | |||
| 85 | add(new JScrollPane(list)); | ||
| 86 | } | ||
| 87 | |||
| 88 | public void setTextFont(Font f) { | ||
| 89 | list.setFont(f); | ||
| 90 | list.setPrototypeCellValue(SourceModel.prototypeCellValue); | ||
| 91 | } | ||
| 92 | |||
| 93 | private class SourceToolListener | ||
| 94 | implements ContextListener, SourceListener, SpecListener | ||
| 95 | { | ||
| 96 | |||
| 97 | // ContextListener | ||
| 98 | |||
| 99 | @Override | ||
| 100 | public void currentFrameChanged(CurrentFrameChangedEvent e) { | ||
| 101 | showSourceContext(e.getThread(), e.getIndex()); | ||
| 102 | } | ||
| 103 | |||
| 104 | // Clear source view. | ||
| 105 | // sourceModel = new DefaultListModel(); // empty | ||
| 106 | |||
| 107 | // SourceListener | ||
| 108 | |||
| 109 | @Override | ||
| 110 | public void sourcepathChanged(SourcepathChangedEvent e) { | ||
| 111 | // Reload source view if its contents depend | ||
| 112 | // on the source path. | ||
| 113 | if (sourceName != null) { | ||
| 114 | showSourceFile(sourceName); | ||
| 115 | } else if (sourceLocn != null) { | ||
| 116 | showSourceForLocation(sourceLocn); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | // SpecListener | ||
| 121 | |||
| 122 | @Override | ||
| 123 | public void breakpointSet(SpecEvent e) { | ||
| 124 | breakpointResolved(e); | ||
| 125 | } | ||
| 126 | |||
| 127 | @Override | ||
| 128 | public void breakpointDeferred(SpecEvent e) { } | ||
| 129 | |||
| 130 | @Override | ||
| 131 | public void breakpointDeleted(SpecEvent e) { | ||
| 132 | BreakpointRequest req = (BreakpointRequest)e.getEventRequest(); | ||
| 133 | Location loc = req.location(); | ||
| 134 | if (loc != null) { | ||
| 135 | try { | ||
| 136 | SourceModel sm = sourceManager.sourceForLocation(loc); | ||
| 137 | sm.showBreakpoint(loc.lineNumber(), false); | ||
| 138 | showSourceForLocation(loc); | ||
| 139 | } catch (Exception exc) { | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | @Override | ||
| 145 | public void breakpointResolved(SpecEvent e) { | ||
| 146 | BreakpointRequest req = (BreakpointRequest)e.getEventRequest(); | ||
| 147 | Location loc = req.location(); | ||
| 148 | try { | ||
| 149 | SourceModel sm = sourceManager.sourceForLocation(loc); | ||
| 150 | sm.showBreakpoint(loc.lineNumber(), true); | ||
| 151 | showSourceForLocation(loc); | ||
| 152 | } catch (Exception exc) { | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | @Override | ||
| 157 | public void breakpointError(SpecErrorEvent e) { | ||
| 158 | breakpointDeleted(e); | ||
| 159 | } | ||
| 160 | |||
| 161 | @Override | ||
| 162 | public void watchpointSet(SpecEvent e) { | ||
| 163 | } | ||
| 164 | @Override | ||
| 165 | public void watchpointDeferred(SpecEvent e) { | ||
| 166 | } | ||
| 167 | @Override | ||
| 168 | public void watchpointDeleted(SpecEvent e) { | ||
| 169 | } | ||
| 170 | @Override | ||
| 171 | public void watchpointResolved(SpecEvent e) { | ||
| 172 | } | ||
| 173 | @Override | ||
| 174 | public void watchpointError(SpecErrorEvent e) { | ||
| 175 | } | ||
| 176 | |||
| 177 | @Override | ||
| 178 | public void exceptionInterceptSet(SpecEvent e) { | ||
| 179 | } | ||
| 180 | @Override | ||
| 181 | public void exceptionInterceptDeferred(SpecEvent e) { | ||
| 182 | } | ||
| 183 | @Override | ||
| 184 | public void exceptionInterceptDeleted(SpecEvent e) { | ||
| 185 | } | ||
| 186 | @Override | ||
| 187 | public void exceptionInterceptResolved(SpecEvent e) { | ||
| 188 | } | ||
| 189 | @Override | ||
| 190 | public void exceptionInterceptError(SpecErrorEvent e) { | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | private void showSourceContext(ThreadReference thread, int index) { | ||
| 195 | //### Should use ThreadInfo here. | ||
| 196 | StackFrame frame = null; | ||
| 197 | if (thread != null) { | ||
| 198 | try { | ||
| 199 | frame = thread.frame(index); | ||
| 200 | } catch (IncompatibleThreadStateException e) {} | ||
| 201 | } | ||
| 202 | if (frame == null) { | ||
| 203 | return; | ||
| 204 | } | ||
| 205 | Location locn = frame.location(); | ||
| 206 | /***** | ||
| 207 | if (!showSourceForLocation(locn)) { | ||
| 208 | env.notice("Could not display source for " | ||
| 209 | + Utils.locationString(locn)); | ||
| 210 | } | ||
| 211 | *****/ | ||
| 212 | showSourceForLocation(locn); | ||
| 213 | } | ||
| 214 | |||
| 215 | public boolean showSourceForLocation(Location locn) { | ||
| 216 | sourceName = null; | ||
| 217 | sourceLocn = locn; | ||
| 218 | int lineNo = locn.lineNumber(); | ||
| 219 | if (lineNo != -1) { | ||
| 220 | SourceModel source = sourceManager.sourceForLocation(locn); | ||
| 221 | if (source != null) { | ||
| 222 | showSourceAtLine(source, lineNo-1); | ||
| 223 | return true; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | // Here if we could not display source. | ||
| 227 | showSourceUnavailable(); | ||
| 228 | return false; | ||
| 229 | } | ||
| 230 | |||
| 231 | public boolean showSourceFile(String fileName) { | ||
| 232 | sourceLocn = null; | ||
| 233 | File file; | ||
| 234 | if (!fileName.startsWith(File.separator)) { | ||
| 235 | sourceName = fileName; | ||
| 236 | SearchPath sourcePath = sourceManager.getSourcePath(); | ||
| 237 | file = sourcePath.resolve(fileName); | ||
| 238 | if (file == null) { | ||
| 239 | //env.failure("Source not found on current source path."); | ||
| 240 | showSourceUnavailable(); | ||
| 241 | return false; | ||
| 242 | } | ||
| 243 | } else { | ||
| 244 | sourceName = null; // Absolute pathname does not depend on sourcepath. | ||
| 245 | file = new File(fileName); | ||
| 246 | } | ||
| 247 | SourceModel source = sourceManager.sourceForFile(file); | ||
| 248 | if (source != null) { | ||
| 249 | showSource(source); | ||
| 250 | return true; | ||
| 251 | } | ||
| 252 | showSourceUnavailable(); | ||
| 253 | return false; | ||
| 254 | } | ||
| 255 | |||
| 256 | private void showSource(SourceModel model) { | ||
| 257 | setViewModel(model); | ||
| 258 | } | ||
| 259 | |||
| 260 | private void showSourceAtLine(SourceModel model, int lineNo) { | ||
| 261 | setViewModel(model); | ||
| 262 | if (model.isActuallySource && (lineNo < model.getSize())) { | ||
| 263 | list.setSelectedIndex(lineNo); | ||
| 264 | if (lineNo+4 < model.getSize()) { | ||
| 265 | list.ensureIndexIsVisible(lineNo+4); // give some context | ||
| 266 | } | ||
| 267 | list.ensureIndexIsVisible(lineNo); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | private void showSourceUnavailable() { | ||
| 272 | SourceModel model = new SourceModel("[Source code is not available]"); | ||
| 273 | setViewModel(model); | ||
| 274 | } | ||
| 275 | |||
| 276 | private void setViewModel(SourceModel model) { | ||
| 277 | if (model != sourceModel) { | ||
| 278 | // install new model | ||
| 279 | list.setModel(model); | ||
| 280 | sourceModel = model; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | private class SourceLineRenderer extends DefaultListCellRenderer { | ||
| 285 | |||
| 286 | @Override | ||
| 287 | public Component getListCellRendererComponent(JList list, | ||
| 288 | Object value, | ||
| 289 | int index, | ||
| 290 | boolean isSelected, | ||
| 291 | boolean cellHasFocus) { | ||
| 292 | |||
| 293 | //### Should set background highlight and/or icon if breakpoint on this line. | ||
| 294 | // Configures "this" | ||
| 295 | super.getListCellRendererComponent(list, value, index, | ||
| 296 | isSelected, cellHasFocus); | ||
| 297 | |||
| 298 | SourceModel.Line line = (SourceModel.Line)value; | ||
| 299 | |||
| 300 | //### Tab expansion is now done when source file is read in, | ||
| 301 | //### to speed up display. This costs a lot of space, slows | ||
| 302 | //### down source file loading, and has not been demonstrated | ||
| 303 | //### to yield an observable improvement in display performance. | ||
| 304 | //### Measurements may be appropriate here. | ||
| 305 | //String sourceLine = expandTabs((String)value); | ||
| 306 | setText(line.text); | ||
| 307 | if (line.hasBreakpoint) { | ||
| 308 | setIcon(Icons.stopSignIcon); | ||
| 309 | } else if (line.isExecutable()) { | ||
| 310 | setIcon(Icons.execIcon); | ||
| 311 | } else { | ||
| 312 | setIcon(Icons.blankIcon); | ||
| 313 | } | ||
| 314 | |||
| 315 | |||
| 316 | return this; | ||
| 317 | } | ||
| 318 | |||
| 319 | @Override | ||
| 320 | public Dimension getPreferredSize() { | ||
| 321 | Dimension dim = super.getPreferredSize(); | ||
| 322 | return new Dimension(dim.width, dim.height-5); | ||
| 323 | } | ||
| 324 | |||
| 325 | } | ||
| 326 | |||
| 327 | private class STMouseListener extends MouseAdapter implements MouseListener { | ||
| 328 | @Override | ||
| 329 | public void mousePressed(MouseEvent e) { | ||
| 330 | if (e.isPopupTrigger()) { | ||
| 331 | showPopupMenu((Component)e.getSource(), | ||
| 332 | e.getX(), e.getY()); | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | @Override | ||
| 337 | public void mouseReleased(MouseEvent e) { | ||
| 338 | if (e.isPopupTrigger()) { | ||
| 339 | showPopupMenu((Component)e.getSource(), | ||
| 340 | e.getX(), e.getY()); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | private void showPopupMenu(Component invoker, int x, int y) { | ||
| 345 | JList list = (JList)invoker; | ||
| 346 | int ln = list.getSelectedIndex() + 1; | ||
| 347 | SourceModel.Line line = | ||
| 348 | (SourceModel.Line)list.getSelectedValue(); | ||
| 349 | JPopupMenu popup = new JPopupMenu(); | ||
| 350 | |||
| 351 | if (line == null) { | ||
| 352 | popup.add(new JMenuItem("please select a line")); | ||
| 353 | } else if (line.isExecutable()) { | ||
| 354 | String className = line.refType.name(); | ||
| 355 | if (line.hasBreakpoint()) { | ||
| 356 | popup.add(commandItem("Clear Breakpoint", | ||
| 357 | "clear " + className + | ||
| 358 | ":" + ln)); | ||
| 359 | } else { | ||
| 360 | popup.add(commandItem("Set Breakpoint", | ||
| 361 | "stop at " + className + | ||
| 362 | ":" + ln)); | ||
| 363 | } | ||
| 364 | } else { | ||
| 365 | popup.add(new JMenuItem("not an executable line")); | ||
| 366 | } | ||
| 367 | |||
| 368 | popup.show(invoker, | ||
| 369 | x + popup.getWidth()/2, y + popup.getHeight()/2); | ||
| 370 | } | ||
| 371 | |||
| 372 | private JMenuItem commandItem(String label, final String cmd) { | ||
| 373 | JMenuItem item = new JMenuItem(label); | ||
| 374 | item.addActionListener(new ActionListener() { | ||
| 375 | @Override | ||
| 376 | public void actionPerformed(ActionEvent e) { | ||
| 377 | interpreter.executeCommand(cmd); | ||
| 378 | } | ||
| 379 | }); | ||
| 380 | return item; | ||
| 381 | } | ||
| 382 | } | ||
| 383 | } | ||
| @@ -0,0 +1,283 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | import java.util.*; | ||
| 30 | |||
| 31 | import javax.swing.*; | ||
| 32 | import javax.swing.tree.*; | ||
| 33 | import java.awt.*; | ||
| 34 | import java.awt.event.*; | ||
| 35 | |||
| 36 | import com.sun.tools.example.debug.bdi.*; | ||
| 37 | |||
| 38 | public class SourceTreeTool extends JPanel { | ||
| 39 | |||
| 40 | private static final long serialVersionUID = 3336680912107956419L; | ||
| 41 | |||
| 42 | private Environment env; | ||
| 43 | |||
| 44 | private ExecutionManager runtime; | ||
| 45 | private SourceManager sourceManager; | ||
| 46 | private ClassManager classManager; | ||
| 47 | |||
| 48 | private JTree tree; | ||
| 49 | private SourceTreeNode root; | ||
| 50 | private SearchPath sourcePath; | ||
| 51 | private CommandInterpreter interpreter; | ||
| 52 | |||
| 53 | private static String HEADING = "SOURCES"; | ||
| 54 | |||
| 55 | public SourceTreeTool(Environment env) { | ||
| 56 | |||
| 57 | super(new BorderLayout()); | ||
| 58 | |||
| 59 | this.env = env; | ||
| 60 | this.runtime = env.getExecutionManager(); | ||
| 61 | this.sourceManager = env.getSourceManager(); | ||
| 62 | |||
| 63 | this.interpreter = new CommandInterpreter(env); | ||
| 64 | |||
| 65 | sourcePath = sourceManager.getSourcePath(); | ||
| 66 | root = createDirectoryTree(HEADING); | ||
| 67 | |||
| 68 | // Create a tree that allows one selection at a time. | ||
| 69 | tree = new JTree(new DefaultTreeModel(root)); | ||
| 70 | tree.setSelectionModel(new SingleLeafTreeSelectionModel()); | ||
| 71 | |||
| 72 | /****** | ||
| 73 | // Listen for when the selection changes. | ||
| 74 | tree.addTreeSelectionListener(new TreeSelectionListener() { | ||
| 75 | public void valueChanged(TreeSelectionEvent e) { | ||
| 76 | SourceTreeNode node = (SourceTreeNode) | ||
| 77 | (e.getPath().getLastPathComponent()); | ||
| 78 | interpreter.executeCommand("view " + node.getRelativePath()); | ||
| 79 | } | ||
| 80 | }); | ||
| 81 | ******/ | ||
| 82 | |||
| 83 | MouseListener ml = new MouseAdapter() { | ||
| 84 | @Override | ||
| 85 | public void mouseClicked(MouseEvent e) { | ||
| 86 | int selRow = tree.getRowForLocation(e.getX(), e.getY()); | ||
| 87 | TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); | ||
| 88 | if(selRow != -1) { | ||
| 89 | if(e.getClickCount() == 1) { | ||
| 90 | SourceTreeNode node = | ||
| 91 | (SourceTreeNode)selPath.getLastPathComponent(); | ||
| 92 | // If user clicks on leaf, select it, and issue 'view' command. | ||
| 93 | if (node.isLeaf()) { | ||
| 94 | tree.setSelectionPath(selPath); | ||
| 95 | interpreter.executeCommand("view " + node.getRelativePath()); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | }; | ||
| 101 | tree.addMouseListener(ml); | ||
| 102 | |||
| 103 | JScrollPane treeView = new JScrollPane(tree); | ||
| 104 | add(treeView); | ||
| 105 | |||
| 106 | // Create listener for source path changes. | ||
| 107 | |||
| 108 | SourceTreeToolListener listener = new SourceTreeToolListener(); | ||
| 109 | sourceManager.addSourceListener(listener); | ||
| 110 | |||
| 111 | //### remove listeners on exit! | ||
| 112 | } | ||
| 113 | |||
| 114 | private class SourceTreeToolListener implements SourceListener { | ||
| 115 | |||
| 116 | @Override | ||
| 117 | public void sourcepathChanged(SourcepathChangedEvent e) { | ||
| 118 | sourcePath = sourceManager.getSourcePath(); | ||
| 119 | root = createDirectoryTree(HEADING); | ||
| 120 | tree.setModel(new DefaultTreeModel(root)); | ||
| 121 | } | ||
| 122 | |||
| 123 | } | ||
| 124 | |||
| 125 | private static class SourceOrDirectoryFilter implements FilenameFilter { | ||
| 126 | @Override | ||
| 127 | public boolean accept(File dir, String name) { | ||
| 128 | return (name.endsWith(".java") || | ||
| 129 | new File(dir, name).isDirectory()); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | private static FilenameFilter filter = new SourceOrDirectoryFilter(); | ||
| 134 | |||
| 135 | SourceTreeNode createDirectoryTree(String label) { | ||
| 136 | try { | ||
| 137 | return new SourceTreeNode(label, null, "", true); | ||
| 138 | } catch (SecurityException e) { | ||
| 139 | env.failure("Cannot access source file or directory"); | ||
| 140 | return null; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | class SourceTreeNode implements TreeNode { | ||
| 146 | |||
| 147 | private String name; | ||
| 148 | private boolean isDirectory; | ||
| 149 | private SourceTreeNode parent; | ||
| 150 | private SourceTreeNode[] children; | ||
| 151 | private String relativePath; | ||
| 152 | private boolean isExpanded; | ||
| 153 | |||
| 154 | private SourceTreeNode(String label, | ||
| 155 | SourceTreeNode parent, | ||
| 156 | String relativePath, | ||
| 157 | boolean isDirectory) { | ||
| 158 | this.name = label; | ||
| 159 | this.relativePath = relativePath; | ||
| 160 | this.parent = parent; | ||
| 161 | this.isDirectory = isDirectory; | ||
| 162 | } | ||
| 163 | |||
| 164 | @Override | ||
| 165 | public String toString() { | ||
| 166 | return name; | ||
| 167 | } | ||
| 168 | |||
| 169 | public String getRelativePath() { | ||
| 170 | return relativePath; | ||
| 171 | } | ||
| 172 | |||
| 173 | private void expandIfNeeded() { | ||
| 174 | try { | ||
| 175 | if (!isExpanded && isDirectory) { | ||
| 176 | String[] files = sourcePath.children(relativePath, filter); | ||
| 177 | children = new SourceTreeNode[files.length]; | ||
| 178 | for (int i = 0; i < files.length; i++) { | ||
| 179 | String childName = | ||
| 180 | (relativePath.equals("")) | ||
| 181 | ? files[i] | ||
| 182 | : relativePath + File.separator + files[i]; | ||
| 183 | File file = sourcePath.resolve(childName); | ||
| 184 | boolean isDir = (file != null && file.isDirectory()); | ||
| 185 | children[i] = | ||
| 186 | new SourceTreeNode(files[i], this, childName, isDir); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | isExpanded = true; | ||
| 190 | } catch (SecurityException e) { | ||
| 191 | children = null; | ||
| 192 | env.failure("Cannot access source file or directory"); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | // -- interface TreeNode -- | ||
| 197 | |||
| 198 | /* | ||
| 199 | * Returns the child <code>TreeNode</code> at index | ||
| 200 | * <code>childIndex</code>. | ||
| 201 | */ | ||
| 202 | @Override | ||
| 203 | public TreeNode getChildAt(int childIndex) { | ||
| 204 | expandIfNeeded(); | ||
| 205 | return children[childIndex]; | ||
| 206 | } | ||
| 207 | |||
| 208 | /** | ||
| 209 | * Returns the number of children <code>TreeNode</code>s the receiver | ||
| 210 | * contains. | ||
| 211 | */ | ||
| 212 | @Override | ||
| 213 | public int getChildCount() { | ||
| 214 | expandIfNeeded(); | ||
| 215 | return children.length; | ||
| 216 | } | ||
| 217 | |||
| 218 | /** | ||
| 219 | * Returns the parent <code>TreeNode</code> of the receiver. | ||
| 220 | */ | ||
| 221 | @Override | ||
| 222 | public TreeNode getParent() { | ||
| 223 | return parent; | ||
| 224 | } | ||
| 225 | |||
| 226 | /** | ||
| 227 | * Returns the index of <code>node</code> in the receivers children. | ||
| 228 | * If the receiver does not contain <code>node</code>, -1 will be | ||
| 229 | * returned. | ||
| 230 | */ | ||
| 231 | @Override | ||
| 232 | public int getIndex(TreeNode node) { | ||
| 233 | expandIfNeeded(); | ||
| 234 | for (int i = 0; i < children.length; i++) { | ||
| 235 | if (children[i] == node) { | ||
| 236 | return i; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | return -1; | ||
| 240 | } | ||
| 241 | |||
| 242 | /** | ||
| 243 | * Returns true if the receiver allows children. | ||
| 244 | */ | ||
| 245 | @Override | ||
| 246 | public boolean getAllowsChildren() { | ||
| 247 | return isDirectory; | ||
| 248 | } | ||
| 249 | |||
| 250 | /** | ||
| 251 | * Returns true if the receiver is a leaf. | ||
| 252 | */ | ||
| 253 | @Override | ||
| 254 | public boolean isLeaf() { | ||
| 255 | expandIfNeeded(); | ||
| 256 | return !isDirectory; | ||
| 257 | } | ||
| 258 | |||
| 259 | /** | ||
| 260 | * Returns the children of the receiver as an Enumeration. | ||
| 261 | */ | ||
| 262 | @Override | ||
| 263 | public Enumeration children() { | ||
| 264 | expandIfNeeded(); | ||
| 265 | return new Enumeration() { | ||
| 266 | int i = 0; | ||
| 267 | @Override | ||
| 268 | public boolean hasMoreElements() { | ||
| 269 | return (i < children.length); | ||
| 270 | } | ||
| 271 | @Override | ||
| 272 | public Object nextElement() throws NoSuchElementException { | ||
| 273 | if (i >= children.length) { | ||
| 274 | throw new NoSuchElementException(); | ||
| 275 | } | ||
| 276 | return children[i++]; | ||
| 277 | } | ||
| 278 | }; | ||
| 279 | } | ||
| 280 | |||
| 281 | } | ||
| 282 | |||
| 283 | } | ||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.util.EventObject; | ||
| 29 | |||
| 30 | public class SourcepathChangedEvent extends EventObject { | ||
| 31 | |||
| 32 | private static final long serialVersionUID = 8762169481005804121L; | ||
| 33 | |||
| 34 | public SourcepathChangedEvent(Object source) { | ||
| 35 | super(source); | ||
| 36 | } | ||
| 37 | } | ||
| @@ -0,0 +1,198 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import javax.swing.*; | ||
| 29 | import javax.swing.event.*; | ||
| 30 | import java.awt.*; | ||
| 31 | import com.sun.jdi.*; | ||
| 32 | import com.sun.tools.example.debug.bdi.*; | ||
| 33 | |||
| 34 | public class StackTraceTool extends JPanel { | ||
| 35 | |||
| 36 | private static final long serialVersionUID = 9140041989427965718L; | ||
| 37 | |||
| 38 | private Environment env; | ||
| 39 | |||
| 40 | private ExecutionManager runtime; | ||
| 41 | private ContextManager context; | ||
| 42 | |||
| 43 | private ThreadInfo tinfo; | ||
| 44 | |||
| 45 | private JList list; | ||
| 46 | private ListModel stackModel; | ||
| 47 | |||
| 48 | public StackTraceTool(Environment env) { | ||
| 49 | |||
| 50 | super(new BorderLayout()); | ||
| 51 | |||
| 52 | this.env = env; | ||
| 53 | this.runtime = env.getExecutionManager(); | ||
| 54 | this.context = env.getContextManager(); | ||
| 55 | |||
| 56 | stackModel = new DefaultListModel(); // empty | ||
| 57 | |||
| 58 | list = new JList(stackModel); | ||
| 59 | list.setCellRenderer(new StackFrameRenderer()); | ||
| 60 | |||
| 61 | JScrollPane listView = new JScrollPane(list); | ||
| 62 | add(listView); | ||
| 63 | |||
| 64 | // Create listener. | ||
| 65 | StackTraceToolListener listener = new StackTraceToolListener(); | ||
| 66 | context.addContextListener(listener); | ||
| 67 | list.addListSelectionListener(listener); | ||
| 68 | |||
| 69 | //### remove listeners on exit! | ||
| 70 | } | ||
| 71 | |||
| 72 | private class StackTraceToolListener | ||
| 73 | implements ContextListener, ListSelectionListener | ||
| 74 | { | ||
| 75 | |||
| 76 | // ContextListener | ||
| 77 | |||
| 78 | // If the user selects a new current frame, display it in | ||
| 79 | // this view. | ||
| 80 | |||
| 81 | //### I suspect we handle the case badly that the VM is not interrupted. | ||
| 82 | |||
| 83 | @Override | ||
| 84 | public void currentFrameChanged(CurrentFrameChangedEvent e) { | ||
| 85 | // If the current frame of the thread appearing in this | ||
| 86 | // view is changed, move the selection to track it. | ||
| 87 | int frameIndex = e.getIndex(); | ||
| 88 | ThreadInfo ti = e.getThreadInfo(); | ||
| 89 | if (e.getInvalidate() || tinfo != ti) { | ||
| 90 | tinfo = ti; | ||
| 91 | showStack(ti, frameIndex); | ||
| 92 | } else { | ||
| 93 | if (frameIndex < stackModel.getSize()) { | ||
| 94 | list.setSelectedIndex(frameIndex); | ||
| 95 | list.ensureIndexIsVisible(frameIndex); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | // ListSelectionListener | ||
| 101 | |||
| 102 | @Override | ||
| 103 | public void valueChanged(ListSelectionEvent e) { | ||
| 104 | int index = list.getSelectedIndex(); | ||
| 105 | if (index != -1) { | ||
| 106 | //### should use listener? | ||
| 107 | try { | ||
| 108 | context.setCurrentFrameIndex(index); | ||
| 109 | } catch (VMNotInterruptedException exc) { | ||
| 110 | } | ||
| 111 | } | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | private class StackFrameRenderer extends DefaultListCellRenderer { | ||
| 116 | |||
| 117 | @Override | ||
| 118 | public Component getListCellRendererComponent(JList list, | ||
| 119 | Object value, | ||
| 120 | int index, | ||
| 121 | boolean isSelected, | ||
| 122 | boolean cellHasFocus) { | ||
| 123 | |||
| 124 | //### We should indicate the current thread independently of the | ||
| 125 | //### selection, e.g., with an icon, because the user may change | ||
| 126 | //### the selection graphically without affecting the current | ||
| 127 | //### thread. | ||
| 128 | |||
| 129 | super.getListCellRendererComponent(list, value, index, | ||
| 130 | isSelected, cellHasFocus); | ||
| 131 | if (value == null) { | ||
| 132 | this.setText("<unavailable>"); | ||
| 133 | } else { | ||
| 134 | StackFrame frame = (StackFrame)value; | ||
| 135 | Location loc = frame.location(); | ||
| 136 | Method meth = loc.method(); | ||
| 137 | String methName = | ||
| 138 | meth.declaringType().name() + '.' + meth.name(); | ||
| 139 | String position = ""; | ||
| 140 | if (meth.isNative()) { | ||
| 141 | position = " (native method)"; | ||
| 142 | } else if (loc.lineNumber() != -1) { | ||
| 143 | position = ":" + loc.lineNumber(); | ||
| 144 | } else { | ||
| 145 | long pc = loc.codeIndex(); | ||
| 146 | if (pc != -1) { | ||
| 147 | position = ", pc = " + pc; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | // Indices are presented to the user starting from 1, not 0. | ||
| 151 | this.setText("[" + (index+1) +"] " + methName + position); | ||
| 152 | } | ||
| 153 | return this; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | // Point this view at the given thread and frame. | ||
| 158 | |||
| 159 | private void showStack(ThreadInfo tinfo, int selectFrame) { | ||
| 160 | StackTraceListModel model = new StackTraceListModel(tinfo); | ||
| 161 | stackModel = model; | ||
| 162 | list.setModel(stackModel); | ||
| 163 | list.setSelectedIndex(selectFrame); | ||
| 164 | list.ensureIndexIsVisible(selectFrame); | ||
| 165 | } | ||
| 166 | |||
| 167 | private static class StackTraceListModel extends AbstractListModel { | ||
| 168 | |||
| 169 | private final ThreadInfo tinfo; | ||
| 170 | |||
| 171 | public StackTraceListModel(ThreadInfo tinfo) { | ||
| 172 | this.tinfo = tinfo; | ||
| 173 | } | ||
| 174 | |||
| 175 | @Override | ||
| 176 | public Object getElementAt(int index) { | ||
| 177 | try { | ||
| 178 | return tinfo == null? null : tinfo.getFrame(index); | ||
| 179 | } catch (VMNotInterruptedException e) { | ||
| 180 | //### Is this the right way to handle this? | ||
| 181 | //### Would happen if user scrolled stack trace | ||
| 182 | //### while not interrupted -- should probably | ||
| 183 | //### block user interaction in this case. | ||
| 184 | return null; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | @Override | ||
| 189 | public int getSize() { | ||
| 190 | try { | ||
| 191 | return tinfo == null? 1 : tinfo.getFrameCount(); | ||
| 192 | } catch (VMNotInterruptedException e) { | ||
| 193 | //### Is this the right way to handle this? | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| @@ -0,0 +1,346 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 2008, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.util.*; | ||
| 29 | import java.util.List; // Must import explicitly due to conflict with javax.awt.List | ||
| 30 | |||
| 31 | import javax.swing.*; | ||
| 32 | import javax.swing.tree.*; | ||
| 33 | import java.awt.*; | ||
| 34 | import java.awt.event.*; | ||
| 35 | |||
| 36 | import com.sun.jdi.*; | ||
| 37 | import com.sun.tools.example.debug.event.*; | ||
| 38 | import com.sun.tools.example.debug.bdi.*; | ||
| 39 | |||
| 40 | //### Bug: If the name of a thread is changed via Thread.setName(), the | ||
| 41 | //### thread tree view does not reflect this. The name of the thread at | ||
| 42 | //### the time it is created is used throughout its lifetime. | ||
| 43 | |||
| 44 | public class ThreadTreeTool extends JPanel { | ||
| 45 | |||
| 46 | private static final long serialVersionUID = 4168599992853038878L; | ||
| 47 | |||
| 48 | private Environment env; | ||
| 49 | |||
| 50 | private ExecutionManager runtime; | ||
| 51 | private SourceManager sourceManager; | ||
| 52 | private ClassManager classManager; | ||
| 53 | |||
| 54 | private JTree tree; | ||
| 55 | private DefaultTreeModel treeModel; | ||
| 56 | private ThreadTreeNode root; | ||
| 57 | private SearchPath sourcePath; | ||
| 58 | |||
| 59 | private CommandInterpreter interpreter; | ||
| 60 | |||
| 61 | private static String HEADING = "THREADS"; | ||
| 62 | |||
| 63 | public ThreadTreeTool(Environment env) { | ||
| 64 | |||
| 65 | super(new BorderLayout()); | ||
| 66 | |||
| 67 | this.env = env; | ||
| 68 | this.runtime = env.getExecutionManager(); | ||
| 69 | this.sourceManager = env.getSourceManager(); | ||
| 70 | |||
| 71 | this.interpreter = new CommandInterpreter(env); | ||
| 72 | |||
| 73 | root = createThreadTree(HEADING); | ||
| 74 | treeModel = new DefaultTreeModel(root); | ||
| 75 | |||
| 76 | // Create a tree that allows one selection at a time. | ||
| 77 | |||
| 78 | tree = new JTree(treeModel); | ||
| 79 | tree.setSelectionModel(new SingleLeafTreeSelectionModel()); | ||
| 80 | |||
| 81 | MouseListener ml = new MouseAdapter() { | ||
| 82 | @Override | ||
| 83 | public void mouseClicked(MouseEvent e) { | ||
| 84 | int selRow = tree.getRowForLocation(e.getX(), e.getY()); | ||
| 85 | TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); | ||
| 86 | if(selRow != -1) { | ||
| 87 | if(e.getClickCount() == 1) { | ||
| 88 | ThreadTreeNode node = | ||
| 89 | (ThreadTreeNode)selPath.getLastPathComponent(); | ||
| 90 | // If user clicks on leaf, select it, and issue 'thread' command. | ||
| 91 | if (node.isLeaf()) { | ||
| 92 | tree.setSelectionPath(selPath); | ||
| 93 | interpreter.executeCommand("thread " + | ||
| 94 | node.getThreadId() + | ||
| 95 | " (\"" + | ||
| 96 | node.getName() + "\")"); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
| 101 | }; | ||
| 102 | |||
| 103 | tree.addMouseListener(ml); | ||
| 104 | |||
| 105 | JScrollPane treeView = new JScrollPane(tree); | ||
| 106 | add(treeView); | ||
| 107 | |||
| 108 | // Create listener. | ||
| 109 | ThreadTreeToolListener listener = new ThreadTreeToolListener(); | ||
| 110 | runtime.addJDIListener(listener); | ||
| 111 | runtime.addSessionListener(listener); | ||
| 112 | |||
| 113 | //### remove listeners on exit! | ||
| 114 | } | ||
| 115 | |||
| 116 | HashMap<ThreadReference, List<String>> threadTable = new HashMap<ThreadReference, List<String>>(); | ||
| 117 | |||
| 118 | private List<String> threadPath(ThreadReference thread) { | ||
| 119 | // May exit abnormally if VM disconnects. | ||
| 120 | List<String> l = new ArrayList<String>(); | ||
| 121 | l.add(0, thread.name()); | ||
| 122 | ThreadGroupReference group = thread.threadGroup(); | ||
| 123 | while (group != null) { | ||
| 124 | l.add(0, group.name()); | ||
| 125 | group = group.parent(); | ||
| 126 | } | ||
| 127 | return l; | ||
| 128 | } | ||
| 129 | |||
| 130 | private class ThreadTreeToolListener extends JDIAdapter | ||
| 131 | implements JDIListener, SessionListener { | ||
| 132 | |||
| 133 | // SessionListener | ||
| 134 | |||
| 135 | @Override | ||
| 136 | public void sessionStart(EventObject e) { | ||
| 137 | try { | ||
| 138 | for (ThreadReference thread : runtime.allThreads()) { | ||
| 139 | root.addThread(thread); | ||
| 140 | } | ||
| 141 | } catch (VMDisconnectedException ee) { | ||
| 142 | // VM went away 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 | |||
| 154 | // JDIListener | ||
| 155 | |||
| 156 | @Override | ||
| 157 | public void threadStart(ThreadStartEventSet e) { | ||
| 158 | root.addThread(e.getThread()); | ||
| 159 | } | ||
| 160 | |||
| 161 | @Override | ||
| 162 | public void threadDeath(ThreadDeathEventSet e) { | ||
| 163 | root.removeThread(e.getThread()); | ||
| 164 | } | ||
| 165 | |||
| 166 | @Override | ||
| 167 | public void vmDisconnect(VMDisconnectEventSet e) { | ||
| 168 | // Clear the contents of this view. | ||
| 169 | root = createThreadTree(HEADING); | ||
| 170 | treeModel = new DefaultTreeModel(root); | ||
| 171 | tree.setModel(treeModel); | ||
| 172 | threadTable = new HashMap<ThreadReference, List<String>>(); | ||
| 173 | } | ||
| 174 | |||
| 175 | } | ||
| 176 | |||
| 177 | ThreadTreeNode createThreadTree(String label) { | ||
| 178 | return new ThreadTreeNode(label, null); | ||
| 179 | } | ||
| 180 | |||
| 181 | class ThreadTreeNode extends DefaultMutableTreeNode { | ||
| 182 | |||
| 183 | String name; | ||
| 184 | ThreadReference thread; // null if thread group | ||
| 185 | long uid; | ||
| 186 | String description; | ||
| 187 | |||
| 188 | ThreadTreeNode(String name, ThreadReference thread) { | ||
| 189 | if (name == null) { | ||
| 190 | name = "<unnamed>"; | ||
| 191 | } | ||
| 192 | this.name = name; | ||
| 193 | this.thread = thread; | ||
| 194 | if (thread == null) { | ||
| 195 | this.uid = -1; | ||
| 196 | this.description = name; | ||
| 197 | } else { | ||
| 198 | this.uid = thread.uniqueID(); | ||
| 199 | this.description = name + " (t@" + Long.toHexString(uid) + ")"; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | @Override | ||
| 204 | public String toString() { | ||
| 205 | return description; | ||
| 206 | } | ||
| 207 | |||
| 208 | public String getName() { | ||
| 209 | return name; | ||
| 210 | } | ||
| 211 | |||
| 212 | public ThreadReference getThread() { | ||
| 213 | return thread; | ||
| 214 | } | ||
| 215 | |||
| 216 | public String getThreadId() { | ||
| 217 | return "t@" + Long.toHexString(uid); | ||
| 218 | } | ||
| 219 | |||
| 220 | private boolean isThreadGroup() { | ||
| 221 | return (thread == null); | ||
| 222 | } | ||
| 223 | |||
| 224 | @Override | ||
| 225 | public boolean isLeaf() { | ||
| 226 | return !isThreadGroup(); | ||
| 227 | } | ||
| 228 | |||
| 229 | public void addThread(ThreadReference thread) { | ||
| 230 | // This can fail if the VM disconnects. | ||
| 231 | // It is important to do all necessary JDI calls | ||
| 232 | // before modifying the tree, so we don't abort | ||
| 233 | // midway through! | ||
| 234 | if (threadTable.get(thread) == null) { | ||
| 235 | // Add thread only if not already present. | ||
| 236 | try { | ||
| 237 | List<String> path = threadPath(thread); | ||
| 238 | // May not get here due to exception. | ||
| 239 | // If we get here, we are committed. | ||
| 240 | // We must not leave the tree partially updated. | ||
| 241 | try { | ||
| 242 | threadTable.put(thread, path); | ||
| 243 | addThread(path, thread); | ||
| 244 | } catch (Throwable tt) { | ||
| 245 | //### Assertion failure. | ||
| 246 | throw new RuntimeException("ThreadTree corrupted"); | ||
| 247 | } | ||
| 248 | } catch (VMDisconnectedException ee) { | ||
| 249 | // Ignore. Thread will not be added. | ||
| 250 | } | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | private void addThread(List<String> threadPath, ThreadReference thread) { | ||
| 255 | int size = threadPath.size(); | ||
| 256 | if (size == 0) { | ||
| 257 | return; | ||
| 258 | } else if (size == 1) { | ||
| 259 | String name = threadPath.get(0); | ||
| 260 | insertNode(name, thread); | ||
| 261 | } else { | ||
| 262 | String head = threadPath.get(0); | ||
| 263 | List<String> tail = threadPath.subList(1, size); | ||
| 264 | ThreadTreeNode child = insertNode(head, null); | ||
| 265 | child.addThread(tail, thread); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | private ThreadTreeNode insertNode(String name, ThreadReference thread) { | ||
| 270 | for (int i = 0; i < getChildCount(); i++) { | ||
| 271 | ThreadTreeNode child = (ThreadTreeNode)getChildAt(i); | ||
| 272 | int cmp = name.compareTo(child.getName()); | ||
| 273 | if (cmp == 0 && thread == null) { | ||
| 274 | // A like-named interior node already exists. | ||
| 275 | return child; | ||
| 276 | } else if (cmp < 0) { | ||
| 277 | // Insert new node before the child. | ||
| 278 | ThreadTreeNode newChild = new ThreadTreeNode(name, thread); | ||
| 279 | treeModel.insertNodeInto(newChild, this, i); | ||
| 280 | return newChild; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | // Insert new node after last child. | ||
| 284 | ThreadTreeNode newChild = new ThreadTreeNode(name, thread); | ||
| 285 | treeModel.insertNodeInto(newChild, this, getChildCount()); | ||
| 286 | return newChild; | ||
| 287 | } | ||
| 288 | |||
| 289 | public void removeThread(ThreadReference thread) { | ||
| 290 | List<String> threadPath = threadTable.get(thread); | ||
| 291 | // Only remove thread if we recorded it in table. | ||
| 292 | // Original add may have failed due to VM disconnect. | ||
| 293 | if (threadPath != null) { | ||
| 294 | removeThread(threadPath, thread); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | private void removeThread(List<String> threadPath, ThreadReference thread) { | ||
| 299 | int size = threadPath.size(); | ||
| 300 | if (size == 0) { | ||
| 301 | return; | ||
| 302 | } else if (size == 1) { | ||
| 303 | String name = threadPath.get(0); | ||
| 304 | ThreadTreeNode child = findLeafNode(thread, name); | ||
| 305 | treeModel.removeNodeFromParent(child); | ||
| 306 | } else { | ||
| 307 | String head = threadPath.get(0); | ||
| 308 | List<String> tail = threadPath.subList(1, size); | ||
| 309 | ThreadTreeNode child = findInternalNode(head); | ||
| 310 | child.removeThread(tail, thread); | ||
| 311 | if (child.isThreadGroup() && child.getChildCount() < 1) { | ||
| 312 | // Prune non-leaf nodes with no children. | ||
| 313 | treeModel.removeNodeFromParent(child); | ||
| 314 | } | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | private ThreadTreeNode findLeafNode(ThreadReference thread, String name) { | ||
| 319 | for (int i = 0; i < getChildCount(); i++) { | ||
| 320 | ThreadTreeNode child = (ThreadTreeNode)getChildAt(i); | ||
| 321 | if (child.getThread() == thread) { | ||
| 322 | if (!name.equals(child.getName())) { | ||
| 323 | //### Assertion failure. | ||
| 324 | throw new RuntimeException("name mismatch"); | ||
| 325 | } | ||
| 326 | return child; | ||
| 327 | } | ||
| 328 | } | ||
| 329 | //### Assertion failure. | ||
| 330 | throw new RuntimeException("not found"); | ||
| 331 | } | ||
| 332 | |||
| 333 | private ThreadTreeNode findInternalNode(String name) { | ||
| 334 | for (int i = 0; i < getChildCount(); i++) { | ||
| 335 | ThreadTreeNode child = (ThreadTreeNode)getChildAt(i); | ||
| 336 | if (name.equals(child.getName())) { | ||
| 337 | return child; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | //### Assertion failure. | ||
| 341 | throw new RuntimeException("not found"); | ||
| 342 | } | ||
| 343 | |||
| 344 | } | ||
| 345 | |||
| 346 | } | ||
| @@ -0,0 +1,123 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.awt.*; | ||
| 29 | import java.awt.event.*; | ||
| 30 | import javax.swing.*; | ||
| 31 | |||
| 32 | public class TypeScript extends JPanel { | ||
| 33 | |||
| 34 | private static final long serialVersionUID = -983704841363534885L; | ||
| 35 | private JTextArea history; | ||
| 36 | private JTextField entry; | ||
| 37 | |||
| 38 | private JLabel promptLabel; | ||
| 39 | |||
| 40 | private JScrollBar historyVScrollBar; | ||
| 41 | private JScrollBar historyHScrollBar; | ||
| 42 | |||
| 43 | private boolean echoInput = false; | ||
| 44 | |||
| 45 | private static String newline = System.getProperty("line.separator"); | ||
| 46 | |||
| 47 | public TypeScript(String prompt) { | ||
| 48 | this(prompt, true); | ||
| 49 | } | ||
| 50 | |||
| 51 | public TypeScript(String prompt, boolean echoInput) { | ||
| 52 | this.echoInput = echoInput; | ||
| 53 | |||
| 54 | setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); | ||
| 55 | //setBorder(new EmptyBorder(5, 5, 5, 5)); | ||
| 56 | |||
| 57 | history = new JTextArea(0, 0); | ||
| 58 | history.setEditable(false); | ||
| 59 | JScrollPane scroller = new JScrollPane(history); | ||
| 60 | historyVScrollBar = scroller.getVerticalScrollBar(); | ||
| 61 | historyHScrollBar = scroller.getHorizontalScrollBar(); | ||
| 62 | |||
| 63 | add(scroller); | ||
| 64 | |||
| 65 | JPanel cmdLine = new JPanel(); | ||
| 66 | cmdLine.setLayout(new BoxLayout(cmdLine, BoxLayout.X_AXIS)); | ||
| 67 | //cmdLine.setBorder(new EmptyBorder(5, 5, 0, 0)); | ||
| 68 | |||
| 69 | promptLabel = new JLabel(prompt + " "); | ||
| 70 | cmdLine.add(promptLabel); | ||
| 71 | entry = new JTextField(); | ||
| 72 | //### Swing bug workaround. | ||
| 73 | entry.setMaximumSize(new Dimension(1000, 20)); | ||
| 74 | cmdLine.add(entry); | ||
| 75 | add(cmdLine); | ||
| 76 | } | ||
| 77 | |||
| 78 | /****** | ||
| 79 | public void setFont(Font f) { | ||
| 80 | entry.setFont(f); | ||
| 81 | history.setFont(f); | ||
| 82 | } | ||
| 83 | ******/ | ||
| 84 | |||
| 85 | public void setPrompt(String prompt) { | ||
| 86 | promptLabel.setText(prompt + " "); | ||
| 87 | } | ||
| 88 | |||
| 89 | public void append(String text) { | ||
| 90 | history.append(text); | ||
| 91 | historyVScrollBar.setValue(historyVScrollBar.getMaximum()); | ||
| 92 | historyHScrollBar.setValue(historyHScrollBar.getMinimum()); | ||
| 93 | } | ||
| 94 | |||
| 95 | public void newline() { | ||
| 96 | history.append(newline); | ||
| 97 | historyVScrollBar.setValue(historyVScrollBar.getMaximum()); | ||
| 98 | historyHScrollBar.setValue(historyHScrollBar.getMinimum()); | ||
| 99 | } | ||
| 100 | |||
| 101 | public void flush() {} | ||
| 102 | |||
| 103 | public void addActionListener(ActionListener a) { | ||
| 104 | entry.addActionListener(a); | ||
| 105 | } | ||
| 106 | |||
| 107 | public void removeActionListener(ActionListener a) { | ||
| 108 | entry.removeActionListener(a); | ||
| 109 | } | ||
| 110 | |||
| 111 | public String readln() { | ||
| 112 | String text = entry.getText(); | ||
| 113 | entry.setText(""); | ||
| 114 | if (echoInput) { | ||
| 115 | history.append(">>>"); | ||
| 116 | history.append(text); | ||
| 117 | history.append(newline); | ||
| 118 | historyVScrollBar.setValue(historyVScrollBar.getMaximum()); | ||
| 119 | historyHScrollBar.setValue(historyHScrollBar.getMinimum()); | ||
| 120 | } | ||
| 121 | return text; | ||
| 122 | } | ||
| 123 | } | ||
| @@ -0,0 +1,52 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import com.sun.tools.example.debug.bdi.OutputListener; | ||
| 29 | |||
| 30 | public class TypeScriptOutputListener implements OutputListener { | ||
| 31 | |||
| 32 | private TypeScript script; | ||
| 33 | private boolean appendNewline; | ||
| 34 | |||
| 35 | public TypeScriptOutputListener(TypeScript script) { | ||
| 36 | this(script, false); | ||
| 37 | } | ||
| 38 | |||
| 39 | public TypeScriptOutputListener(TypeScript script, boolean appendNewline) { | ||
| 40 | this.script = script; | ||
| 41 | this.appendNewline = appendNewline; | ||
| 42 | } | ||
| 43 | |||
| 44 | @Override | ||
| 45 | public void putString(String s) { | ||
| 46 | script.append(s); | ||
| 47 | if (appendNewline) { | ||
| 48 | script.newline(); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | } | ||
| @@ -0,0 +1,52 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1998, 1999, 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 com.sun.tools.example.debug.gui; | ||
| 27 | |||
| 28 | import java.io.*; | ||
| 29 | |||
| 30 | public class TypeScriptWriter extends Writer { | ||
| 31 | |||
| 32 | TypeScript script; | ||
| 33 | |||
| 34 | public TypeScriptWriter(TypeScript script) { | ||
| 35 | this.script = script; | ||
| 36 | } | ||
| 37 | |||
| 38 | @Override | ||
| 39 | public void write(char[] cbuf, int off, int len) throws IOException { | ||
| 40 | script.append(String.valueOf(cbuf, off, len)); | ||
| 41 | } | ||
| 42 | |||
| 43 | @Override | ||
| 44 | public void flush() { | ||
| 45 | script.flush(); | ||
| 46 | } | ||
| 47 | |||
| 48 | @Override | ||
| 49 | public void close() { | ||
| 50 | script.flush(); | ||
| 51 | } | ||
| 52 | } | ||
| @@ -0,0 +1,38 @@ | |||
| 1 | <../../../../../../../../mkconfig | ||
| 2 | |||
| 3 | TARG=\ | ||
| 4 | ApplicationTool.dis\ | ||
| 5 | ClassManager.dis\ | ||
| 6 | ClassTreeTool.dis\ | ||
| 7 | CommandInterpreter.dis\ | ||
| 8 | CommandTool.dis\ | ||
| 9 | ContextListener.dis\ | ||
| 10 | ContextManager.dis\ | ||
| 11 | CurrentFrameChangedEvent.dis\ | ||
| 12 | Environment.dis\ | ||
| 13 | GUI.dis\ | ||
| 14 | Icons.dis\ | ||
| 15 | JDBFileFilter.dis\ | ||
| 16 | JDBMenuBar.dis\ | ||
| 17 | JDBToolBar.dis\ | ||
| 18 | LaunchTool.dis\ | ||
| 19 | MonitorListModel.dis\ | ||
| 20 | MonitorTool.dis\ | ||
| 21 | OutputSink.dis\ | ||
| 22 | SearchPath.dis\ | ||
| 23 | SingleLeafTreeSelectionModel.dis\ | ||
| 24 | SourceListener.dis\ | ||
| 25 | SourceManager.dis\ | ||
| 26 | SourceModel.dis\ | ||
| 27 | SourcepathChangedEvent.dis\ | ||
| 28 | SourceTool.dis\ | ||
| 29 | SourceTreeTool.dis\ | ||
| 30 | StackTraceTool.dis\ | ||
| 31 | ThreadTreeTool.dis\ | ||
| 32 | TypeScript.dis\ | ||
| 33 | TypeScriptOutputListener.dis\ | ||
| 34 | TypeScriptWriter.dis\ | ||
| 35 | |||
| 36 | DISBIN=$ROOT/java/dis/java/java/com/sun/tools/example/debug/gui | ||
| 37 | |||
| 38 | <$ROOT/mkfiles/mkjava | ||