History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/example/debug/gui (32 of 18352 files). Show all

Unified · Split

32 files
  1. java/pkg/com/sun/tools/example/debug/gui/ApplicationTool.java +74 −0
  2. java/pkg/com/sun/tools/example/debug/gui/ClassManager.java +64 −0
  3. java/pkg/com/sun/tools/example/debug/gui/ClassTreeTool.java +278 −0
  4. java/pkg/com/sun/tools/example/debug/gui/CommandInterpreter.java +1459 −0
  5. java/pkg/com/sun/tools/example/debug/gui/CommandTool.java +333 −0
  6. java/pkg/com/sun/tools/example/debug/gui/ContextListener.java +30 −0
  7. java/pkg/com/sun/tools/example/debug/gui/ContextManager.java +353 −0
  8. java/pkg/com/sun/tools/example/debug/gui/CurrentFrameChangedEvent.java +62 −0
  9. java/pkg/com/sun/tools/example/debug/gui/Environment.java +156 −0
  10. java/pkg/com/sun/tools/example/debug/gui/GUI.java +256 −0
  11. java/pkg/com/sun/tools/example/debug/gui/Icons.java +209 −0
  12. java/pkg/com/sun/tools/example/debug/gui/JDBFileFilter.java +269 −0
  13. java/pkg/com/sun/tools/example/debug/gui/JDBMenuBar.java +190 −0
  14. java/pkg/com/sun/tools/example/debug/gui/JDBToolBar.java +101 −0
  15. java/pkg/com/sun/tools/example/debug/gui/LaunchTool.java +263 −0
  16. java/pkg/com/sun/tools/example/debug/gui/MonitorListModel.java +90 −0
  17. java/pkg/com/sun/tools/example/debug/gui/MonitorTool.java +125 −0
  18. java/pkg/com/sun/tools/example/debug/gui/OutputSink.java +46 −0
  19. java/pkg/com/sun/tools/example/debug/gui/SearchPath.java +95 −0
  20. java/pkg/com/sun/tools/example/debug/gui/SingleLeafTreeSelectionModel.java +70 −0
  21. java/pkg/com/sun/tools/example/debug/gui/SourceListener.java +30 −0
  22. java/pkg/com/sun/tools/example/debug/gui/SourceManager.java +180 −0
  23. java/pkg/com/sun/tools/example/debug/gui/SourceModel.java +247 −0
  24. java/pkg/com/sun/tools/example/debug/gui/SourceTool.java +383 −0
  25. java/pkg/com/sun/tools/example/debug/gui/SourceTreeTool.java +283 −0
  26. java/pkg/com/sun/tools/example/debug/gui/SourcepathChangedEvent.java +37 −0
  27. java/pkg/com/sun/tools/example/debug/gui/StackTraceTool.java +198 −0
  28. java/pkg/com/sun/tools/example/debug/gui/ThreadTreeTool.java +346 −0
  29. java/pkg/com/sun/tools/example/debug/gui/TypeScript.java +123 −0
  30. java/pkg/com/sun/tools/example/debug/gui/TypeScriptOutputListener.java +52 −0
  31. java/pkg/com/sun/tools/example/debug/gui/TypeScriptWriter.java +52 −0
  32. java/pkg/com/sun/tools/example/debug/gui/mkfile +38 −0
java/pkg/com/sun/tools/example/debug/gui/ApplicationTool.java+74−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/ClassManager.java+64−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/ClassTreeTool.java+278−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/CommandInterpreter.java+1459−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/CommandTool.java+333−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/ContextListener.java+30−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/ContextManager.java+353−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/CurrentFrameChangedEvent.java+62−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/Environment.java+156−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/GUI.java+256−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/Icons.java+209−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/JDBFileFilter.java+269−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/JDBMenuBar.java+190−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/JDBToolBar.java+101−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/LaunchTool.java+263−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/MonitorListModel.java+90−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/MonitorTool.java+125−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/OutputSink.java+46−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/SearchPath.java+95−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/SingleLeafTreeSelectionModel.java+70−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/SourceListener.java+30−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/SourceManager.java+180−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/SourceModel.java+247−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/SourceTool.java+383−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/SourceTreeTool.java+283−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/SourcepathChangedEvent.java+37−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/StackTraceTool.java+198−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/ThreadTreeTool.java+346−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/TypeScript.java+123−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/TypeScriptOutputListener.java+52−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/TypeScriptWriter.java+52−0
@@ -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+}
java/pkg/com/sun/tools/example/debug/gui/mkfile+38−0
@@ -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