KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > tools > example > debug > gui > CommandInterpreter


1 /*
2  * @(#)CommandInterpreter.java 1.24 05/11/17
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 /*
8  * Copyright (c) 1997-1999 by Sun Microsystems, Inc. All Rights Reserved.
9  *
10  * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
11  * modify and redistribute this software in source and binary code form,
12  * provided that i) this copyright notice and license appear on all copies of
13  * the software; and ii) Licensee does not utilize the software in a manner
14  * which is disparaging to Sun.
15  *
16  * This software is provided "AS IS," without a warranty of any kind. ALL
17  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
18  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
19  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
20  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
21  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
22  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
23  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
24  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
25  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGES.
27  *
28  * This software is not designed or intended for use in on-line control of
29  * aircraft, air traffic, aircraft navigation or aircraft communications; or in
30  * the design, construction, operation or maintenance of any nuclear
31  * facility. Licensee represents and warrants that it will not use or
32  * redistribute the Software for such purposes.
33  */

34
35 package com.sun.tools.example.debug.gui;
36
37 import java.io.*;
38 import java.util.*;
39
40 import com.sun.jdi.*;
41 import com.sun.jdi.request.*;
42
43 import com.sun.tools.example.debug.bdi.*;
44
45 public class CommandInterpreter {
46
47     boolean echo;
48
49     Environment env;
50
51     private ContextManager context;
52     private ExecutionManager runtime;
53     private ClassManager classManager;
54     private SourceManager sourceManager;
55
56     private OutputSink out; //### Hack! Should be local in each method used.
57
private String JavaDoc lastCommand = "help";
58
59     public CommandInterpreter(Environment env) {
60     this(env, true);
61     }
62
63     public CommandInterpreter(Environment env, boolean echo) {
64     this.env = env;
65     this.echo = echo;
66     this.runtime = env.getExecutionManager();
67     this.context = env.getContextManager();
68     this.classManager = env.getClassManager();
69     this.sourceManager = env.getSourceManager();
70     }
71
72     private ThreadReference[] threads = null;
73
74     /*
75      * The numbering of threads is relative to the current set of threads,
76      * and may be affected by the creation and termination of new threads.
77      * Commands issued using such thread ids will only give reliable behavior
78      * relative to what was shown earlier in 'list' commands if the VM is interrupted.
79      * We need a better scheme.
80      */

81
82     private ThreadReference[] threads() throws NoSessionException {
83         if (threads == null) {
84             ThreadIterator ti = new ThreadIterator(getDefaultThreadGroup());
85             List tlist = new ArrayList();
86             while (ti.hasNext()) {
87                 tlist.add(ti.nextThread());
88             }
89             threads = (ThreadReference[])tlist.toArray(new ThreadReference[tlist.size()]);
90         }
91         return threads;
92     }
93
94     private ThreadReference findThread(String JavaDoc idToken) throws NoSessionException {
95     String JavaDoc id;
96         ThreadReference thread = null;
97         if (idToken.startsWith("t@")) {
98             id = idToken.substring(2);
99         } else {
100         id = idToken;
101     }
102         try {
103         ThreadReference[] threads = threads();
104             long threadID = Long.parseLong(id, 16);
105         for (int i = 0; i < threads.length; i++) {
106         if (threads[i].uniqueID() == threadID) {
107             thread = threads[i];
108             break;
109         }
110         }
111         if (thread == null) {
112         //env.failure("No thread for id \"" + idToken + "\"");
113
env.failure("\"" + idToken + "\" is not a valid thread id.");
114         }
115         } catch (NumberFormatException JavaDoc e) {
116             env.error("Thread id \"" + idToken + "\" is ill-formed.");
117             thread = null;
118         }
119         return thread;
120     }
121
122     private ThreadIterator allThreads() throws NoSessionException {
123     threads = null;
124     //### Why not use runtime.allThreads().iterator() ?
125
return new ThreadIterator(runtime.topLevelThreadGroups());
126     }
127
128     private ThreadIterator currentThreadGroupThreads() throws NoSessionException {
129     threads = null;
130         return new ThreadIterator(getDefaultThreadGroup());
131     }
132
133     private ThreadGroupIterator allThreadGroups() throws NoSessionException {
134     threads = null;
135         return new ThreadGroupIterator(runtime.topLevelThreadGroups());
136     }
137
138     private ThreadGroupReference defaultThreadGroup;
139
140     private ThreadGroupReference getDefaultThreadGroup() throws NoSessionException {
141     if (defaultThreadGroup == null) {
142         defaultThreadGroup = runtime.systemThreadGroup();
143     }
144     return defaultThreadGroup;
145     }
146
147     private void setDefaultThreadGroup(ThreadGroupReference tg) {
148     defaultThreadGroup = tg;
149     }
150
151     /*
152      * Command handlers.
153      */

154
155     // Command: classes
156

157     private void commandClasses() throws NoSessionException {
158         List list = runtime.allClasses();
159     OutputSink out = env.getOutputSink();
160         //out.println("** classes list **");
161
for (int i = 0 ; i < list.size() ; i++) {
162             ReferenceType refType = (ReferenceType)list.get(i);
163             out.println(refType.name());
164         }
165     out.show();
166     }
167
168
169     // Command: methods
170

171     private void commandMethods(StringTokenizer t) throws NoSessionException {
172         if (!t.hasMoreTokens()) {
173             env.error("No class specified.");
174             return;
175         }
176         String JavaDoc idClass = t.nextToken();
177     ReferenceType cls = findClass(idClass);
178     if (cls != null) {
179             List methods = cls.allMethods();
180         OutputSink out = env.getOutputSink();
181             for (int i = 0; i < methods.size(); i++) {
182                 Method method = (Method)methods.get(i);
183                 out.print(method.declaringType().name() + " " +
184                             method.name() + "(");
185                 Iterator it = method.argumentTypeNames().iterator();
186                 if (it.hasNext()) {
187                     while (true) {
188                         out.print((String JavaDoc)it.next());
189                         if (!it.hasNext()) {
190                             break;
191                         }
192                         out.print(", ");
193                     }
194                 }
195                 out.println(")");
196             }
197         out.show();
198     } else {
199         //### Should validate class name syntax.
200
env.failure("\"" + idClass + "\" is not a valid id or class name.");
201     }
202     }
203
204     private ReferenceType findClass(String JavaDoc pattern) throws NoSessionException {
205     List results = runtime.findClassesMatchingPattern(pattern);
206     if (results.size() > 0) {
207         //### Should handle multiple results sensibly.
208
return (ReferenceType)results.get(0);
209     }
210     return null;
211     }
212
213     // Command: threads
214

215     private void commandThreads(StringTokenizer t) throws NoSessionException {
216         if (!t.hasMoreTokens()) {
217         OutputSink out = env.getOutputSink();
218             printThreadGroup(out, getDefaultThreadGroup(), 0);
219         out.show();
220             return;
221         }
222         String JavaDoc name = t.nextToken();
223         ThreadGroupReference tg = findThreadGroup(name);
224         if (tg == null) {
225             env.failure(name + " is not a valid threadgroup name.");
226         } else {
227         OutputSink out = env.getOutputSink();
228             printThreadGroup(out, tg, 0);
229         out.show();
230         }
231     }
232
233     private ThreadGroupReference findThreadGroup(String JavaDoc name) throws NoSessionException {
234     //### Issue: Uniqueness of thread group names is not enforced.
235
ThreadGroupIterator tgi = allThreadGroups();
236         while (tgi.hasNext()) {
237             ThreadGroupReference tg = tgi.nextThreadGroup();
238             if (tg.name().equals(name)) {
239                 return tg;
240             }
241         }
242         return null;
243     }
244
245     private int printThreadGroup(OutputSink out, ThreadGroupReference tg, int iThread) {
246         out.println("Group " + tg.name() + ":");
247         List tlist = tg.threads();
248         int maxId = 0;
249         int maxName = 0;
250         for (int i = 0 ; i < tlist.size() ; i++) {
251             ThreadReference thr = (ThreadReference)tlist.get(i);
252             int len = Utils.description(thr).length();
253             if (len > maxId)
254                 maxId = len;
255             String JavaDoc name = thr.name();
256             int iDot = name.lastIndexOf('.');
257             if (iDot >= 0 && name.length() > iDot) {
258                 name = name.substring(iDot + 1);
259             }
260             if (name.length() > maxName)
261                 maxName = name.length();
262         }
263         String JavaDoc maxNumString = String.valueOf(iThread + tlist.size());
264         int maxNumDigits = maxNumString.length();
265         for (int i = 0 ; i < tlist.size() ; i++) {
266             ThreadReference thr = (ThreadReference)tlist.get(i);
267             char buf[] = new char[80];
268             for (int j = 0; j < 79; j++) {
269                 buf[j] = ' ';
270             }
271             buf[79] = '\0';
272             StringBuffer JavaDoc sbOut = new StringBuffer JavaDoc();
273             sbOut.append(buf);
274
275             // Right-justify the thread number at start of output string
276
String JavaDoc numString = String.valueOf(iThread + i + 1);
277             sbOut.insert(maxNumDigits - numString.length(),
278                          numString);
279             sbOut.insert(maxNumDigits, ".");
280
281             int iBuf = maxNumDigits + 2;
282             sbOut.insert(iBuf, Utils.description(thr));
283             iBuf += maxId + 1;
284             String JavaDoc name = thr.name();
285             int iDot = name.lastIndexOf('.');
286             if (iDot >= 0 && name.length() > iDot) {
287                 name = name.substring(iDot + 1);
288             }
289             sbOut.insert(iBuf, name);
290             iBuf += maxName + 1;
291             sbOut.insert(iBuf, Utils.getStatus(thr));
292             sbOut.setLength(79);
293             out.println(sbOut.toString());
294         }
295         List tglist = tg.threadGroups();
296         for (int ig = 0; ig < tglist.size(); ig++) {
297             ThreadGroupReference tg0 = (ThreadGroupReference)tglist.get(ig);
298             if (!tg.equals(tg0)) { // TODO ref mgt
299
iThread += printThreadGroup(out, tg0, iThread + tlist.size());
300             }
301         }
302         return tlist.size();
303     }
304
305     // Command: threadgroups
306

307     private void commandThreadGroups() throws NoSessionException {
308     ThreadGroupIterator it = allThreadGroups();
309         int cnt = 0;
310     OutputSink out = env.getOutputSink();
311         while (it.hasNext()) {
312             ThreadGroupReference tg = it.nextThreadGroup();
313             ++cnt;
314             out.println("" + cnt + ". " + Utils.description(tg) + " " + tg.name());
315     }
316     out.show();
317     }
318
319     // Command: thread
320

321     private void commandThread(StringTokenizer t) throws NoSessionException {
322         if (!t.hasMoreTokens()) {
323             env.error("Thread number not specified.");
324             return;
325         }
326         ThreadReference thread = findThread(t.nextToken());
327         if (thread != null) {
328         //### Should notify user.
329
context.setCurrentThread(thread);
330         }
331     }
332
333     // Command: threadgroup
334

335     private void commandThreadGroup(StringTokenizer t) throws NoSessionException {
336         if (!t.hasMoreTokens()) {
337             env.error("Threadgroup name not specified.");
338             return;
339         }
340         String JavaDoc name = t.nextToken();
341         ThreadGroupReference tg = findThreadGroup(name);
342         if (tg == null) {
343             env.failure(name + " is not a valid threadgroup name.");
344         } else {
345         //### Should notify user.
346
setDefaultThreadGroup(tg);
347         }
348     }
349
350     // Command: run
351

352     private void commandRun(StringTokenizer t) throws NoSessionException {
353     if (doLoad(false, t)) {
354         env.notice("Running ...");
355     }
356     }
357
358     // Command: load
359

360     private void commandLoad(StringTokenizer t) throws NoSessionException {
361     if (doLoad(true, t)) {}
362     }
363     
364     private boolean doLoad(boolean suspended,
365                StringTokenizer t) throws NoSessionException {
366
367         String JavaDoc clname;
368     
369         if (!t.hasMoreTokens()) {
370         clname = context.getMainClassName();
371         if (!clname.equals("")) {
372         // Run from prevously-set class name.
373
try {
374             String JavaDoc vmArgs = context.getVmArguments();
375             runtime.run(suspended,
376                 vmArgs,
377                 clname,
378                 context.getProgramArguments());
379             return true;
380         } catch (VMLaunchFailureException e) {
381             env.failure("Attempt to launch main class \"" + clname + "\" failed.");
382         }
383         } else {
384         env.failure("No main class specifed and no current default defined.");
385         }
386         } else {
387         clname = t.nextToken();
388         StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
389         // Allow VM arguments to be specified here?
390
while (t.hasMoreTokens()) {
391         String JavaDoc tok = t.nextToken();
392         sbuf.append(tok);
393         if (t.hasMoreTokens()) {
394             sbuf.append(' ');
395         }
396         }
397         String JavaDoc args = sbuf.toString();
398         try {
399         String JavaDoc vmArgs = context.getVmArguments();
400         runtime.run(suspended, vmArgs, clname, args);
401         context.setMainClassName(clname);
402         //context.setVmArguments(vmArgs);
403
context.setProgramArguments(args);
404         return true;
405         } catch (VMLaunchFailureException e) {
406                 env.failure("Attempt to launch main class \"" + clname + "\" failed.");
407             }
408     }
409     return false;
410     }
411
412     // Command: connect
413

414     private void commandConnect(StringTokenizer t) {
415         try {
416             LaunchTool.queryAndLaunchVM(runtime);
417         } catch (VMLaunchFailureException e) {
418             env.failure("Attempt to connect failed.");
419         }
420     }
421
422     // Command: attach
423

424     private void commandAttach(StringTokenizer t) {
425     String JavaDoc portName;
426     if (!t.hasMoreTokens()) {
427         portName = context.getRemotePort();
428         if (!portName.equals("")) {
429         try {
430             runtime.attach(portName);
431         } catch (VMLaunchFailureException e) {
432             env.failure("Attempt to attach to port \"" + portName + "\" failed.");
433         }
434         } else {
435         env.failure("No port specifed and no current default defined.");
436         }
437     } else {
438         portName = t.nextToken();
439         try {
440         runtime.attach(portName);
441         } catch (VMLaunchFailureException e) {
442         env.failure("Attempt to attach to port \"" + portName + "\" failed.");
443         }
444         context.setRemotePort(portName);
445     }
446     }
447
448     // Command: detach
449

450     private void commandDetach(StringTokenizer t) throws NoSessionException {
451     runtime.detach();
452     }
453
454     // Command: interrupt
455

456     private void commandInterrupt(StringTokenizer t) throws NoSessionException {
457     runtime.interrupt();
458     }
459
460     // Command: suspend
461

462     private void commandSuspend(StringTokenizer t) throws NoSessionException {
463         if (!t.hasMoreTokens()) {
464         // Suspend all threads in the current thread group.
465
//### Issue: help message says default is all threads.
466
//### Behavior here agrees with 'jdb', however.
467
ThreadIterator ti = currentThreadGroupThreads();
468             while (ti.hasNext()) {
469                 // TODO - don't suspend debugger threads
470
ti.nextThread().suspend();
471             }
472             env.notice("All (non-system) threads suspended.");
473         } else {
474             while (t.hasMoreTokens()) {
475                 ThreadReference thread = findThread(t.nextToken());
476                 if (thread != null) {
477                     //thread.suspend();
478
runtime.suspendThread(thread);
479                 }
480             }
481         }
482     }
483
484     // Command: resume
485

486     private void commandResume(StringTokenizer t) throws NoSessionException {
487          if (!t.hasMoreTokens()) {
488         // Suspend all threads in the current thread group.
489
//### Issue: help message says default is all threads.
490
//### Behavior here agrees with 'jdb', however.
491
ThreadIterator ti = currentThreadGroupThreads();
492             while (ti.hasNext()) {
493                 // TODO - don't suspend debugger threads
494
ti.nextThread().resume();
495             }
496         env.notice("All threads resumed.");
497          } else {
498              while (t.hasMoreTokens()) {
499                 ThreadReference thread = findThread(t.nextToken());
500                 if (thread != null) {
501                     //thread.resume();
502
runtime.resumeThread(thread);
503         }
504          }
505      }
506     }
507
508     // Command: cont
509

510     private void commandCont() throws NoSessionException {
511     try {
512         runtime.go();
513     } catch (VMNotInterruptedException e) {
514         //### failure?
515
env.notice("Target VM is already running.");
516     }
517     }
518
519     // Command: step
520

521     private void commandStep(StringTokenizer t) throws NoSessionException{
522     ThreadReference current = context.getCurrentThread();
523         if (current == null) {
524             env.failure("No current thread.");
525             return;
526         }
527         try {
528             if (t.hasMoreTokens() &&
529         t.nextToken().toLowerCase().equals("up")) {
530         runtime.stepOut(current);
531             } else {
532                 runtime.stepIntoLine(current);
533             }
534         } catch (AbsentInformationException e) {
535             env.failure("No linenumber information available -- " +
536                 "Try \"stepi\" to step by instructions.");
537         }
538     }
539
540     // Command: stepi
541

542     private void commandStepi() throws NoSessionException {
543     ThreadReference current = context.getCurrentThread();
544     if (current == null) {
545             env.failure("No current thread.");
546             return;
547         }
548         runtime.stepIntoInstruction(current);
549     }
550
551     // Command: next
552

553     private void commandNext() throws NoSessionException {
554     ThreadReference current = context.getCurrentThread();
555         if (current == null) {
556             env.failure("No current thread.");
557             return;
558         }
559         try {
560         runtime.stepOverLine(current);
561         } catch (AbsentInformationException e) {
562             env.failure("No linenumber information available -- " +
563                             "Try \"nexti\" to step by instructions.");
564         }
565     }
566
567     // Command: nexti (NEW)
568

569     private void commandNexti() throws NoSessionException {
570     ThreadReference current = context.getCurrentThread();
571         if (current == null) {
572             env.failure("No current thread.");
573             return;
574         }
575     runtime.stepOverInstruction(current);
576     }
577
578     // Command: kill
579

580     private void commandKill(StringTokenizer t) throws NoSessionException {
581     //### Should change the way in which thread ids and threadgroup names
582
//### are distinguished.
583
if (!t.hasMoreTokens()) {
584             env.error("Usage: kill <threadgroup name> or <thread id>");
585             return;
586         }
587         while (t.hasMoreTokens()) {
588             String JavaDoc idToken = t.nextToken();
589             ThreadReference thread = findThread(idToken);
590             if (thread != null) {
591         runtime.stopThread(thread);
592                 env.notice("Thread " + thread.name() + " killed.");
593                 return;
594             } else {
595                 /* Check for threadgroup name, NOT skipping "system". */
596         //### Should skip "system"? Classic 'jdb' does this.
597
//### Should deal with possible non-uniqueness of threadgroup names.
598
ThreadGroupIterator itg = allThreadGroups();
599                 while (itg.hasNext()) {
600                     ThreadGroupReference tg = itg.nextThreadGroup();
601                     if (tg.name().equals(idToken)) {
602                         ThreadIterator it = new ThreadIterator(tg);
603                         while (it.hasNext()) {
604                             runtime.stopThread(it.nextThread());
605             }
606             env.notice("Threadgroup " + tg.name() + "killed.");
607                         return;
608                     }
609                 }
610                 env.failure("\"" + idToken +
611                 "\" is not a valid threadgroup or id.");
612             }
613         }
614     }
615
616
617     /*************
618     // TODO
619     private void commandCatchException(StringTokenizer t) throws NoSessionException {}
620     // TODO
621     private void commandIgnoreException(StringTokenizer t) throws NoSessionException {}
622     *************/

623
624     // Command: up
625

626     //### Print current frame after command?
627

628     int readCount(StringTokenizer t) {
629         int cnt = 1;
630         if (t.hasMoreTokens()) {
631             String JavaDoc idToken = t.nextToken();
632             int n;
633             try {
634                 cnt = Integer.valueOf(idToken).intValue();
635             } catch (NumberFormatException JavaDoc e) {
636                 cnt = -1;
637             }
638         }
639         return cnt;
640     }
641     
642     void commandUp(StringTokenizer t) throws NoSessionException {
643     ThreadReference current = context.getCurrentThread();
644         if (current == null) {
645             env.failure("No current thread.");
646             return;
647         }
648         int nLevels = readCount(t);
649         if (nLevels <= 0) {
650             env.error("usage: up [n frames]");
651             return;
652         }
653     try {
654         int delta = context.moveCurrentFrameIndex(current, -nLevels);
655         if (delta == 0) {
656         env.notice("Already at top of stack.");
657         } else if (-delta < nLevels) {
658         env.notice("Moved up " + delta + " frames to top of stack.");
659         }
660     } catch (VMNotInterruptedException e) {
661         env.failure("Target VM must be in interrupted state.");
662     }
663     }
664     
665     private void commandDown(StringTokenizer t) throws NoSessionException {
666     ThreadReference current = context.getCurrentThread();
667         if (current == null) {
668             env.failure("No current thread.");
669             return;
670         }
671         int nLevels = readCount(t);
672         if (nLevels <= 0) {
673             env.error("usage: down [n frames]");
674             return;
675         }
676     try {
677         int delta = context.moveCurrentFrameIndex(current, nLevels);
678         if (delta == 0) {
679         env.notice("Already at bottom of stack.");
680         } else if (delta < nLevels) {
681         env.notice("Moved down " + delta + " frames to bottom of stack.");
682         }
683     } catch (VMNotInterruptedException e) {
684         env.failure("Target VM must be in interrupted state.");
685     }
686     }
687     
688     // Command: frame
689

690     private void commandFrame(StringTokenizer t) throws NoSessionException {
691     ThreadReference current = context.getCurrentThread();
692         if (current == null) {
693             env.failure("No current thread.");
694             return;
695         }
696         if (!t.hasMoreTokens()) {
697             env.error("usage: frame <frame-index>");
698             return;
699         }
700         String JavaDoc idToken = t.nextToken();
701         int n;
702         try {
703             n = Integer.valueOf(idToken).intValue();
704         } catch (NumberFormatException JavaDoc e) {
705             n = 0;
706         }
707         if (n <= 0) {
708             env.error("use positive frame index");
709             return;
710         }
711     try {
712         int delta = context.setCurrentFrameIndex(current, n);
713         if (delta == 0) {
714         env.notice("Frame unchanged.");
715         } else if (delta < 0) {
716         env.notice("Moved up " + -delta + " frames.");
717         } else {
718         env.notice("Moved down " + delta + " frames.");
719         }
720     } catch (VMNotInterruptedException e) {
721         env.failure("Target VM must be in interrupted state.");
722     }
723     }
724
725     // Command: where
726

727     //### Should we insist that VM be interrupted here?
728
//### There is an inconsistency between the 'where' command
729
//### and 'up' and 'down' in this respect.
730

731     private void commandWhere(StringTokenizer t, boolean showPC)
732                         throws NoSessionException {
733     ThreadReference current = context.getCurrentThread();
734         if (!t.hasMoreTokens()) {
735             if (current == null) {
736                 env.error("No thread specified.");
737                 return;
738             }
739             dumpStack(current, showPC);
740         } else {
741             String JavaDoc token = t.nextToken();
742             if (token.toLowerCase().equals("all")) {
743         ThreadIterator it = allThreads();
744         while (it.hasNext()) {
745             ThreadReference thread = (ThreadReference)it.next();
746                     out.println(thread.name() + ": ");
747                     dumpStack(thread, showPC);
748                 }
749             } else {
750                 ThreadReference thread = findThread(t.nextToken());
751         //### Do we want to set current thread here?
752
//### Should notify user of change.
753
if (thread != null) {
754             context.setCurrentThread(thread);
755                 }
756                 dumpStack(thread, showPC);
757             }
758         }
759     }
760
761     private void dumpStack(ThreadReference thread, boolean showPC) {
762     //### Check for these.
763
//env.failure("Thread no longer exists.");
764
//env.failure("Target VM must be in interrupted state.");
765
//env.failure("Current thread isn't suspended.");
766
//### Should handle extremely long stack traces sensibly for user.
767
List stack = null;
768     try {
769         stack = thread.frames();
770     } catch (IncompatibleThreadStateException e) {
771             env.failure("Thread is not suspended.");
772     }
773     //### Fix this!
774
//### Previously mishandled cases where thread was not current.
775
//### Now, prints all of the stack regardless of current frame.
776
int frameIndex = 0;
777     //int frameIndex = context.getCurrentFrameIndex();
778
if (stack == null) {
779             env.failure("Thread is not running (no stack).");
780         } else {
781         OutputSink out = env.getOutputSink();
782             int nFrames = stack.size();
783             for (int i = frameIndex; i < nFrames; i++) {
784                 StackFrame frame = (StackFrame)stack.get(i);
785                 Location loc = frame.location();
786                 Method meth = loc.method();
787                 out.print(" [" + (i + 1) + "] ");
788                 out.print(meth.declaringType().name());
789                 out.print('.');
790                 out.print(meth.name());
791                 out.print(" (");
792                 if (meth instanceof Method && ((Method)meth).isNative()) {
793                     out.print("native method");
794                 } else if (loc.lineNumber() != -1) {
795                     try {
796                         out.print(loc.sourceName());
797                     } catch (AbsentInformationException e) {
798                         out.print("<unknown>");
799                     }
800                     out.print(':');
801                     out.print(loc.lineNumber());
802                 }
803                 out.print(')');
804                 if (showPC) {
805                     long pc = loc.codeIndex();
806                     if (pc != -1) {
807                         out.print(", pc = " + pc);
808                     }
809                 }
810                 out.println();
811             }
812         out.show();
813         }
814     }
815     
816     private void listEventRequests() throws NoSessionException {
817         // Print set breakpoints
818
Iterator iter = runtime.eventRequestSpecs().iterator();
819         if (!iter.hasNext()) {
820             env.notice("No breakpoints/watchpoints/exceptions set.");
821     } else {
822         OutputSink out = env.getOutputSink();
823             out.println("Current breakpoints/watchpoints/exceptions set:");
824         while (iter.hasNext()) {
825         EventRequestSpec bp = (EventRequestSpec)iter.next();
826         out.println("\t" + bp);
827         }
828         out.show();
829     }
830     }
831
832     private BreakpointSpec parseBreakpointSpec(String JavaDoc bptSpec) {
833     StringTokenizer t = new StringTokenizer(bptSpec);
834         BreakpointSpec bpSpec = null;
835 // try {
836
String JavaDoc token = t.nextToken("@:( \t\n\r");
837             // We can't use hasMoreTokens here because it will cause any leading
838
// paren to be lost.
839
String JavaDoc rest;
840             try {
841                 rest = t.nextToken("").trim();
842             } catch (NoSuchElementException e) {
843                 rest = null;
844             }
845         if ((rest != null) && rest.startsWith("@")) {
846                 t = new StringTokenizer(rest.substring(1));
847                 String JavaDoc sourceName = token;
848                 String JavaDoc lineToken = t.nextToken();
849                 int lineNumber = Integer.valueOf(lineToken).intValue();
850                 if (t.hasMoreTokens()) {
851                     return null;
852                 }
853                 bpSpec = runtime.createSourceLineBreakpoint(sourceName,
854                                                             lineNumber);
855             } else if ((rest != null) && rest.startsWith(":")) {
856                 t = new StringTokenizer(rest.substring(1));
857                 String JavaDoc classId = token;
858                 String JavaDoc lineToken = t.nextToken();
859                 int lineNumber = Integer.valueOf(lineToken).intValue();
860                 if (t.hasMoreTokens()) {
861                     return null;
862                 }
863                 bpSpec = runtime.createClassLineBreakpoint(classId, lineNumber);
864             } else {
865                 // Try stripping method from class.method token.
866
int idot = token.lastIndexOf(".");
867                 if ( (idot <= 0) || /* No dot or dot in first char */
868                      (idot >= token.length() - 1) ) { /* dot in last char */
869                     return null;
870                 }
871                 String JavaDoc methodName = token.substring(idot + 1);
872                 String JavaDoc classId = token.substring(0, idot);
873                 List argumentList = null;
874                 if (rest != null) {
875                     if (!rest.startsWith("(") || !rest.endsWith(")")) {
876             //### Should throw exception with error message
877
//out.println("Invalid method specification: "
878
// + methodName + rest);
879
return null;
880                     }
881                     // Trim the parens
882
//### What about spaces in arglist?
883
rest = rest.substring(1, rest.length() - 1);
884                     argumentList = new ArrayList();
885                     t = new StringTokenizer(rest, ",");
886                     while (t.hasMoreTokens()) {
887                         argumentList.add(t.nextToken());
888                     }
889                 }
890                 bpSpec = runtime.createMethodBreakpoint(classId,
891                                                        methodName,
892                                                        argumentList);
893             }
894 // } catch (Exception e) {
895
// env.error("Exception attempting to create breakpoint: " + e);
896
// return null;
897
// }
898
return bpSpec;
899     }
900
901     private void commandStop(StringTokenizer t) throws NoSessionException {
902         Location bploc;
903         String JavaDoc token;
904
905         if (!t.hasMoreTokens()) {
906             listEventRequests();
907     } else {
908         token = t.nextToken();
909         // Ignore optional "at" or "in" token.
910
// Allowed for backward compatibility.
911
if (token.equals("at") || token.equals("in")) {
912         if (t.hasMoreTokens()) {
913             token = t.nextToken();
914         } else {
915             env.error("Missing breakpoint specification.");
916             return;
917         }
918         }
919             BreakpointSpec bpSpec = parseBreakpointSpec(token);
920         if (bpSpec != null) {
921         //### Add sanity-checks for deferred breakpoint.
922
runtime.install(bpSpec);
923         } else {
924         env.error("Ill-formed breakpoint specification.");
925         }
926     }
927     }
928
929     private void commandClear(StringTokenizer t) throws NoSessionException {
930         if (!t.hasMoreTokens()) {
931             // Print set breakpoints
932
listEventRequests();
933             return;
934         }
935     //### need 'clear all'
936
BreakpointSpec bpSpec = parseBreakpointSpec(t.nextToken());
937         if (bpSpec != null) {
938             Iterator iter = runtime.eventRequestSpecs().iterator();
939             if (!iter.hasNext()) {
940                 env.notice("No breakpoints set.");
941             } else {
942                 List toDelete = new ArrayList();
943                 while (iter.hasNext()) {
944                     BreakpointSpec spec = (BreakpointSpec)iter.next();
945                     if (spec.equals(bpSpec)) {
946                         toDelete.add(spec);
947                     }
948                 }
949                 // The request used for matching should be found
950
if (toDelete.size() <= 1) {
951                     env.notice("No matching breakpoint set.");
952                 }
953                 for (Iterator it = toDelete.iterator(); it.hasNext();) {
954                     BreakpointSpec spec = (BreakpointSpec)it.next();
955                     runtime.delete(spec);
956                 }
957             }
958         } else {
959         env.error("Ill-formed breakpoint specification.");
960     }
961     }
962
963     // Command: list
964

965     private void commandList(StringTokenizer t) throws NoSessionException {
966     ThreadReference current = context.getCurrentThread();
967         if (current == null) {
968             env.error("No thread specified.");
969             return;
970         }
971     Location loc;
972     try {
973         StackFrame frame = context.getCurrentFrame(current);
974         if (frame == null) {
975         env.failure("Thread has not yet begun execution.");
976         return;
977         }
978         loc = frame.location();
979     } catch (VMNotInterruptedException e) {
980         env.failure("Target VM must be in interrupted state.");
981         return;
982     }
983     SourceModel source = sourceManager.sourceForLocation(loc);
984     if (source == null) {
985         if (loc.method().isNative()) {
986         env.failure("Current method is native.");
987         return;
988         }
989         env.failure("No source available for " + Utils.locationString(loc) + ".");
990         return;
991     }
992         ReferenceType refType = loc.declaringType();
993         int lineno = loc.lineNumber();
994         if (t.hasMoreTokens()) {
995             String JavaDoc id = t.nextToken();
996             // See if token is a line number.
997
try {
998                 lineno = Integer.valueOf(id).intValue();
999             } catch (NumberFormatException JavaDoc nfe) {
1000                // It isn't -- see if it's a method name.
1001
List meths = refType.methodsByName(id);
1002        if (meths == null || meths.size() == 0) {
1003            env.failure(id +
1004                " is not a valid line number or " +
1005                "method name for class " +
1006                refType.name());
1007            return;
1008        } else if (meths.size() > 1) {
1009            env.failure(id +
1010                " is an ambiguous method name in" +
1011                refType.name());
1012            return;
1013        }
1014        loc = ((Method)meths.get(0)).location();
1015        lineno = loc.lineNumber();
1016            }
1017        }
1018    int startLine = (lineno > 4) ? lineno - 4 : 1;
1019    int endLine = startLine + 9;
1020    String JavaDoc sourceLine = source.sourceLine(lineno);
1021    if (sourceLine == null) {
1022        env.failure("" +
1023            lineno +
1024            " is an invalid line number for " +
1025            refType.name());
1026    } else {
1027        OutputSink out = env.getOutputSink();
1028        for (int i = startLine; i <= endLine; i++) {
1029                sourceLine = source.sourceLine(i);
1030        if (sourceLine == null) {
1031            break;
1032        }
1033        out.print(i);
1034        out.print("\t");
1035        if (i == lineno) {
1036            out.print("=> ");
1037        } else {
1038            out.print(" ");
1039        }
1040        out.println(sourceLine);
1041        }
1042        out.show();
1043    }
1044    }
1045
1046    // Command: use
1047
// Get or set the source file path list.
1048

1049    private void commandUse(StringTokenizer t) {
1050        if (!t.hasMoreTokens()) {
1051            out.println(sourceManager.getSourcePath().asString());
1052        } else {
1053        //### Should throw exception for invalid path.
1054
//### E.g., vetoable property change.
1055
sourceManager.setSourcePath(new SearchPath(t.nextToken()));
1056        }
1057    }
1058
1059    // Command: sourcepath
1060
// Get or set the source file path list. (Alternate to 'use'.)
1061

1062    private void commandSourcepath(StringTokenizer t) {
1063        if (!t.hasMoreTokens()) {
1064            out.println(sourceManager.getSourcePath().asString());
1065        } else {
1066        //### Should throw exception for invalid path.
1067
//### E.g., vetoable property change.
1068
sourceManager.setSourcePath(new SearchPath(t.nextToken()));
1069        }
1070    }
1071
1072    // Command: classpath
1073
// Get or set the class file path list.
1074

1075    private void commandClasspath(StringTokenizer t) {
1076        if (!t.hasMoreTokens()) {
1077            out.println(classManager.getClassPath().asString());
1078        } else {
1079        //### Should throw exception for invalid path.
1080
//### E.g., vetoable property change.
1081
classManager.setClassPath(new SearchPath(t.nextToken()));
1082        }
1083    }
1084
1085    // Command: view
1086
// Display source for source file or class.
1087

1088    private void commandView(StringTokenizer t) throws NoSessionException {
1089        if (!t.hasMoreTokens()) {
1090        env.error("Argument required");
1091        } else {
1092        String JavaDoc name = t.nextToken();
1093        if (name.endsWith(".java") ||
1094        name.indexOf(File.separatorChar) >= 0) {
1095        env.viewSource(name);
1096        } else {
1097        //### JDI crashes taking line number for class.
1098
/*****
1099        ReferenceType cls = findClass(name);
1100        if (cls != null) {
1101            env.viewLocation(cls.location());
1102        } else {
1103            env.failure("No such class");
1104        }
1105        *****/

1106        String JavaDoc fileName = name.replace('.', File.separatorChar) + ".java";
1107        env.viewSource(fileName);
1108        }
1109    }
1110    }
1111
1112    // Command: locals
1113
// Print all local variables in current stack frame.
1114

1115    private void commandLocals() throws NoSessionException {
1116    ThreadReference current = context.getCurrentThread();
1117        if (current == null) {
1118            env.failure("No default thread specified: " +
1119            "use the \"thread\" command first.");
1120            return;
1121        }
1122    StackFrame frame;
1123    try {
1124        frame = context.getCurrentFrame(current);
1125        if (frame == null) {
1126        env.failure("Thread has not yet created any stack frames.");
1127        return;
1128        }
1129    } catch (VMNotInterruptedException e) {
1130        env.failure("Target VM must be in interrupted state.");
1131        return;
1132    }
1133
1134        List vars;
1135        try {
1136            vars = frame.visibleVariables();
1137            if (vars == null || vars.size() == 0) {
1138                env.failure("No local variables");
1139                return;
1140            }
1141        } catch (AbsentInformationException e) {
1142            env.failure("Local variable information not available." +
1143                        " Compile with -g to generate variable information");
1144            return;
1145        }
1146
1147    OutputSink out = env.getOutputSink();
1148        out.println("Method arguments:");
1149        for (Iterator it = vars.iterator(); it.hasNext(); ) {
1150            LocalVariable var = (LocalVariable)it.next();
1151            if (var.isArgument()) {
1152                printVar(out, var, frame);
1153            }
1154        }
1155        out.println("Local variables:");
1156        for (Iterator it = vars.iterator(); it.hasNext(); ) {
1157            LocalVariable var = (LocalVariable)it.next();
1158            if (!var.isArgument()) {
1159                printVar(out, var, frame);
1160            }
1161        }
1162    out.show();
1163        return;
1164    }
1165
1166    /**
1167     * Command: monitor
1168     * Monitor an expression
1169     */

1170    private void commandMonitor(StringTokenizer t) throws NoSessionException {
1171        if (!t.hasMoreTokens()) {
1172        env.error("Argument required");
1173        } else {
1174        env.getMonitorListModel().add(t.nextToken(""));
1175        }
1176    }
1177
1178    /**
1179     * Command: unmonitor
1180     * Unmonitor an expression
1181     */

1182    private void commandUnmonitor(StringTokenizer t) throws NoSessionException {
1183        if (!t.hasMoreTokens()) {
1184        env.error("Argument required");
1185        } else {
1186        env.getMonitorListModel().remove(t.nextToken(""));
1187        }
1188    }
1189
1190    // Print a stack variable.
1191

1192    private void printVar(OutputSink out, LocalVariable var, StackFrame frame) {
1193        out.print(" " + var.name());
1194        if (var.isVisible(frame)) {
1195            Value val = frame.getValue(var);
1196            out.println(" = " + val.toString());
1197        } else {
1198            out.println(" is not in scope");
1199        }
1200    }
1201
1202    // Command: print
1203
// Evaluate an expression.
1204

1205    private void commandPrint(StringTokenizer t, boolean dumpObject) throws NoSessionException {
1206        if (!t.hasMoreTokens()) {
1207        //### Probably confused if expresion contains whitespace.
1208
env.error("No expression specified.");
1209            return;
1210        }
1211    ThreadReference current = context.getCurrentThread();
1212        if (current == null) {
1213            env.failure("No default thread specified: " +
1214            "use the \"thread\" command first.");
1215            return;
1216        }
1217    StackFrame frame;
1218    try {
1219        frame = context.getCurrentFrame(current);
1220        if (frame == null) {
1221        env.failure("Thread has not yet created any stack frames.");
1222        return;
1223        }
1224    } catch (VMNotInterruptedException e) {
1225        env.failure("Target VM must be in interrupted state.");
1226        return;
1227    }
1228        while (t.hasMoreTokens()) {
1229            String JavaDoc expr = t.nextToken("");
1230        Value val = null;
1231        try {
1232        val = runtime.evaluate(frame, expr);
1233        } catch(Exception JavaDoc e) {
1234                env.error("Exception: " + e);
1235        //### Fix this!
1236
}
1237            if (val == null) {
1238                return; // Error message already printed
1239
}
1240        OutputSink out = env.getOutputSink();
1241            if (dumpObject && (val instanceof ObjectReference) &&
1242                                 !(val instanceof StringReference)) {
1243                ObjectReference obj = (ObjectReference)val;
1244                ReferenceType refType = obj.referenceType();
1245                out.println(expr + " = " + val.toString() + " {");
1246                dump(out, obj, refType, refType);
1247                out.println("}");
1248            } else {
1249                out.println(expr + " = " + val.toString());
1250            }
1251        out.show();
1252        }
1253    }
1254
1255    private void dump(OutputSink out,
1256              ObjectReference obj, ReferenceType refType,
1257                      ReferenceType refTypeBase) {
1258        for (Iterator it = refType.fields().iterator(); it.hasNext(); ) {
1259            Field field = (Field)it.next();
1260            out.print(" ");
1261            if (!refType.equals(refTypeBase)) {
1262                out.print(refType.name() + ".");
1263            }
1264            out.print(field.name() + ": ");
1265            Object JavaDoc o = obj.getValue(field);
1266            out.println((o == null) ? "null" : o.toString()); // Bug ID 4374471
1267
}
1268        if (refType instanceof ClassType) {
1269            ClassType sup = ((ClassType)refType).superclass();
1270            if (sup != null) {
1271                dump(out, obj, sup, refTypeBase);
1272            }
1273        } else if (refType instanceof InterfaceType) {
1274            List sups = ((InterfaceType)refType).superinterfaces();
1275            for (Iterator it = sups.iterator(); it.hasNext(); ) {
1276                dump(out, obj, (ReferenceType)it.next(), refTypeBase);
1277            }
1278        }
1279    }
1280
1281    /*
1282     * Display help message.
1283     */

1284    
1285    private void help() {
1286    out.println("** command list **");
1287    out.println("threads [threadgroup] -- list threads");
1288    out.println("thread <thread id> -- set default thread");
1289    out.println("suspend [thread id(s)] -- suspend threads (default: all)");
1290        out.println("resume [thread id(s)] -- resume threads (default: all)");
1291        out.println("where [thread id] | all -- dump a thread's stack");
1292        out.println("wherei [thread id] | all -- dump a thread's stack, with pc info");
1293        out.println("threadgroups -- list threadgroups");
1294        out.println("threadgroup <name> -- set current threadgroup\n");
1295// out.println("print <expression> -- print value of expression");
1296
out.println("dump <expression> -- print all object information\n");
1297// out.println("eval <expression> -- evaluate expression (same as print)");
1298
out.println("locals -- print all local variables in current stack frame\n");
1299        out.println("classes -- list currently known classes");
1300    out.println("methods <class id> -- list a class's methods\n");
1301        out.println("stop [in] <class id>.<method>[(argument_type,...)] -- set a breakpoint in a method");
1302        out.println("stop [at] <class id>:<line> -- set a breakpoint at a line");
1303        out.println("up [n frames] -- move up a thread's stack");
1304        out.println("down [n frames] -- move down a thread's stack");
1305        out.println("frame <frame-id> -- to a frame");
1306        out.println("clear <class id>.<method>[(argument_type,...)] -- clear a breakpoint in a method");
1307        out.println("clear <class id>:<line> -- clear a breakpoint at a line");
1308        out.println("clear -- list breakpoints");
1309        out.println("step -- execute current line");
1310        out.println("step up -- execute until the current method returns to its caller");
1311        out.println("stepi -- execute current instruction");
1312        out.println("next -- step one line (step OVER calls)");
1313        out.println("nexti -- step one instruction (step OVER calls)");
1314        out.println("cont -- continue execution from breakpoint\n");
1315// out.println("catch <class id> -- break for the specified exception");
1316
// out.println("ignore <class id> -- ignore when the specified exception\n");
1317
out.println("view classname|filename -- display source file");
1318        out.println("list [line number|method] -- print source code context at line or method");
1319        out.println("use <source file path> -- display or change the source path\n");
1320//### new
1321
out.println("sourcepath <source file path> -- display or change the source path\n");
1322//### new
1323
out.println("classpath <class file path> -- display or change the class path\n");
1324    out.println("monitor <expression> -- evaluate an expression each time the program stops\n");
1325    out.println("unmonitor <monitor#> -- delete a monitor\n");
1326        out.println("read <filename> -- read and execute a command file\n");
1327// out.println("memory -- report memory usage");
1328
// out.println("gc -- free unused objects\n");
1329
out.println("run <class> [args] -- start execution of a Java class");
1330        out.println("run -- re-execute last class run");
1331        out.println("load <class> [args] -- start execution of a Java class, initially suspended");
1332        out.println("load -- re-execute last class run, initially suspended");
1333        out.println("attach <portname> -- debug existing process\n");
1334        out.println("detach -- detach from debuggee process\n");
1335        out.println("kill <thread(group)> -- kill a thread or threadgroup\n");
1336        out.println("!! -- repeat last command");
1337        out.println("help (or ?) -- list commands");
1338        out.println("exit (or quit) -- exit debugger");
1339    }
1340    
1341    /*
1342     * Execute a command.
1343     */

1344    
1345    public void executeCommand(String JavaDoc command) {
1346    //### Treatment of 'out' here is dirty...
1347
out = env.getOutputSink();
1348    if (echo) {
1349        out.println(">>> " + command);
1350    }
1351    StringTokenizer t = new StringTokenizer(command);
1352    try {
1353        String JavaDoc cmd;
1354            if (t.hasMoreTokens()) {
1355                cmd = t.nextToken().toLowerCase();
1356                lastCommand = cmd;
1357            } else {
1358                cmd = lastCommand;
1359            }
1360        if (cmd.equals("print")) {
1361        commandPrint(t, false);
1362        } else if (cmd.equals("eval")) {
1363        commandPrint(t, false);
1364        } else if (cmd.equals("dump")) {
1365        commandPrint(t, true);
1366        } else if (cmd.equals("locals")) {
1367        commandLocals();
1368        } else if (cmd.equals("classes")) {
1369        commandClasses();
1370        } else if (cmd.equals("methods")) {
1371        commandMethods(t);
1372        } else if (cmd.equals("threads")) {
1373        commandThreads(t);
1374        } else if (cmd.equals("thread")) {
1375        commandThread(t);
1376        } else if (cmd.equals("suspend")) {
1377        commandSuspend(t);
1378        } else if (cmd.equals("resume")) {
1379        commandResume(t);
1380        } else if (cmd.equals("cont")) {
1381        commandCont();
1382        } else if (cmd.equals("threadgroups")) {
1383        commandThreadGroups();
1384        } else if (cmd.equals("threadgroup")) {
1385        commandThreadGroup(t);
1386        } else if (cmd.equals("run")) {
1387        commandRun(t);
1388        } else if (cmd.equals("load")) {
1389        commandLoad(t);
1390        } else if (cmd.equals("connect")) {
1391        commandConnect(t);
1392        } else if (cmd.equals("attach")) {
1393        commandAttach(t);
1394        } else if (cmd.equals("detach")) {
1395        commandDetach(t);
1396        } else if (cmd.equals("interrupt")) {
1397        commandInterrupt(t);
1398//### Not implemented.
1399
// } else if (cmd.equals("catch")) {
1400
// commandCatchException(t);
1401
//### Not implemented.
1402
// } else if (cmd.equals("ignore")) {
1403
// commandIgnoreException(t);
1404
} else if (cmd.equals("step")) {
1405        commandStep(t);
1406        } else if (cmd.equals("stepi")) {
1407        commandStepi();
1408        } else if (cmd.equals("next")) {
1409        commandNext();
1410        } else if (cmd.equals("nexti")) {
1411        commandNexti();
1412            } else if (cmd.equals("kill")) {
1413                commandKill(t);
1414        } else if (cmd.equals("where")) {
1415        commandWhere(t, false);
1416        } else if (cmd.equals("wherei")) {
1417        commandWhere(t, true);
1418        } else if (cmd.equals("up")) {
1419        commandUp(t);
1420        } else if (cmd.equals("down")) {
1421        commandDown(t);
1422        } else if (cmd.equals("frame")) {
1423        commandFrame(t);
1424        } else if (cmd.equals("stop")) {
1425        commandStop(t);
1426        } else if (cmd.equals("clear")) {
1427        commandClear(t);
1428        } else if (cmd.equals("list")) {
1429        commandList(t);
1430        } else if (cmd.equals("use")) {
1431        commandUse(t);
1432        } else if (cmd.equals("sourcepath")) {
1433        commandSourcepath(t);
1434        } else if (cmd.equals("classpath")) {
1435        commandClasspath(t);
1436        } else if (cmd.equals("monitor")) {
1437        commandMonitor(t);
1438        } else if (cmd.equals("unmonitor")) {
1439        commandUnmonitor(t);
1440        } else if (cmd.equals("view")) {
1441        commandView(t);
1442// } else if (cmd.equals("read")) {
1443
// readCommand(t);
1444
} else if (cmd.equals("help") || cmd.equals("?")) {
1445        help();
1446        } else if (cmd.equals("quit") || cmd.equals("exit")) {
1447        try {
1448            runtime.detach();
1449        } catch (NoSessionException e) {
1450            // ignore
1451
}
1452        env.terminate();
1453        } else {
1454        //### Dubious repeat-count feature inherited from 'jdb'
1455
if (t.hasMoreTokens()) {
1456                    try {
1457                        int repeat = Integer.parseInt(cmd);
1458                        String JavaDoc subcom = t.nextToken("");
1459                        while (repeat-- > 0) {
1460                            executeCommand(subcom);
1461                        }
1462                        return;
1463                    } catch (NumberFormatException JavaDoc exc) {
1464                    }
1465                }
1466        out.println("huh? Try help...");
1467        out.flush();
1468        }
1469    } catch (NoSessionException e) {
1470        out.println("There is no currently attached VM session.");
1471        out.flush();
1472    } catch (Exception JavaDoc e) {
1473        out.println("Internal exception: " + e.toString());
1474        out.flush();
1475        System.out.println("JDB internal exception: " + e.toString());
1476        e.printStackTrace();
1477    }
1478    out.show();
1479    }
1480}
1481
1482
1483
1484
1485
1486
1487
1488
Popular Tags