KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > tools > example > debug > tty > TTY


1 /*
2  * @(#)TTY.java 1.66 06/04/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.tty;
36
37 import com.sun.jdi.*;
38 import com.sun.jdi.event.*;
39 import com.sun.jdi.request.*;
40 import com.sun.jdi.connect.*;
41
42 import java.util.*;
43 import java.io.*;
44
45 public class TTY implements EventNotifier {
46     EventHandler handler = null;
47
48     /**
49      * List of Strings to execute at each stop.
50      */

51     private List monitorCommands = new ArrayList();
52     private int monitorCount = 0;
53
54     /**
55      * The name of this tool.
56      */

57     private static final String JavaDoc progname = "jdb";
58
59     public void vmStartEvent(VMStartEvent se) {
60         Thread.yield(); // fetch output
61
MessageOutput.lnprint("VM Started:");
62     }
63
64     public void vmDeathEvent(VMDeathEvent e) {
65     }
66
67     public void vmDisconnectEvent(VMDisconnectEvent e) {
68     }
69
70     public void threadStartEvent(ThreadStartEvent e) {
71     }
72
73     public void threadDeathEvent(ThreadDeathEvent e) {
74     }
75
76     public void classPrepareEvent(ClassPrepareEvent e) {
77     }
78
79     public void classUnloadEvent(ClassUnloadEvent e) {
80     }
81
82     public void breakpointEvent(BreakpointEvent be) {
83         Thread.yield(); // fetch output
84
MessageOutput.lnprint("Breakpoint hit:");
85     }
86
87     public void fieldWatchEvent(WatchpointEvent fwe) {
88         Field field = fwe.field();
89         ObjectReference obj = fwe.object();
90         Thread.yield(); // fetch output
91

92         if (fwe instanceof ModificationWatchpointEvent) {
93             MessageOutput.lnprint("Field access encountered before after",
94                                   new Object JavaDoc [] {field,
95                                                  fwe.valueCurrent(),
96                                                  ((ModificationWatchpointEvent)fwe).valueToBe()});
97         } else {
98             MessageOutput.lnprint("Field access encountered", field.toString());
99         }
100     }
101
102     public void stepEvent(StepEvent se) {
103         Thread.yield(); // fetch output
104
MessageOutput.lnprint("Step completed:");
105     }
106
107     public void exceptionEvent(ExceptionEvent ee) {
108         Thread.yield(); // fetch output
109
Location catchLocation = ee.catchLocation();
110         if (catchLocation == null) {
111             MessageOutput.lnprint("Exception occurred uncaught",
112                                   ee.exception().referenceType().name());
113         } else {
114             MessageOutput.lnprint("Exception occurred caught",
115                                   new Object JavaDoc [] {ee.exception().referenceType().name(),
116                                                  Commands.locationString(catchLocation)});
117         }
118     }
119
120     public void methodEntryEvent(MethodEntryEvent me) {
121         Thread.yield(); // fetch output
122
/*
123          * These can be very numerous, so be as efficient as possible.
124          * If we are stopping here, then we will see the normal location
125          * info printed.
126          */

127         if (me.request().suspendPolicy() != EventRequest.SUSPEND_NONE) {
128             // We are stopping; the name will be shown by the normal mechanism
129
MessageOutput.lnprint("Method entered:");
130         } else {
131             // We aren't stopping, show the name
132
MessageOutput.print("Method entered:");
133             printLocationOfEvent(me);
134         }
135     }
136
137     public boolean methodExitEvent(MethodExitEvent me) {
138         Thread.yield(); // fetch output
139
/*
140          * These can be very numerous, so be as efficient as possible.
141          */

142         Method mmm = Env.atExitMethod();
143         Method meMethod = me.method();
144
145         if (mmm == null || mmm.equals(meMethod)) {
146             // Either we are not tracing a specific method, or we are
147
// and we are exitting that method.
148

149             if (me.request().suspendPolicy() != EventRequest.SUSPEND_NONE) {
150                 // We will be stopping here, so do a newline
151
MessageOutput.println();
152             }
153             if (Env.vm().canGetMethodReturnValues()) {
154                 MessageOutput.print("Method exitedValue:", me.returnValue() + "");
155             } else {
156                 MessageOutput.print("Method exited:");
157             }
158
159             if (me.request().suspendPolicy() == EventRequest.SUSPEND_NONE) {
160                 // We won't be stopping here, so show the method name
161
printLocationOfEvent(me);
162                 
163             }
164
165             // In case we want to have a one shot trace exit some day, this
166
// code disables the request so we don't hit it again.
167
if (false) {
168                 // This is a one shot deal; we don't want to stop
169
// here the next time.
170
Env.setAtExitMethod(null);
171                 EventRequestManager erm = Env.vm().eventRequestManager();
172                 Iterator it = erm.methodExitRequests().iterator();
173                 while (it.hasNext()) {
174                     EventRequest eReq = (EventRequest)it.next();
175                     if (eReq.equals(me.request())) {
176                         eReq.disable();
177                     }
178                 }
179             }
180             return true;
181         }
182
183         // We are tracing a specific method, and this isn't it. Keep going.
184
return false;
185     }
186
187     public void vmInterrupted() {
188         Thread.yield(); // fetch output
189
printCurrentLocation();
190         Iterator it = monitorCommands.iterator();
191         while (it.hasNext()) {
192             StringTokenizer t = new StringTokenizer((String JavaDoc)it.next());
193             t.nextToken(); // get rid of monitor number
194
executeCommand(t);
195         }
196         MessageOutput.printPrompt();
197     }
198
199     public void receivedEvent(Event event) {
200     }
201
202     private void printBaseLocation(String JavaDoc threadName, Location loc) {
203         MessageOutput.println("location",
204                               new Object JavaDoc [] {threadName,
205                                              Commands.locationString(loc)});
206     }
207
208     private void printCurrentLocation() {
209         ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
210         StackFrame frame;
211         try {
212             frame = threadInfo.getCurrentFrame();
213         } catch (IncompatibleThreadStateException exc) {
214             MessageOutput.println("<location unavailable>");
215             return;
216         }
217         if (frame == null) {
218             MessageOutput.println("No frames on the current call stack");
219         } else {
220             Location loc = frame.location();
221             printBaseLocation(threadInfo.getThread().name(), loc);
222             // Output the current source line, if possible
223
if (loc.lineNumber() != -1) {
224                 String JavaDoc line;
225                 try {
226                     line = Env.sourceLine(loc, loc.lineNumber());
227                 } catch (java.io.IOException JavaDoc e) {
228                     line = null;
229                 }
230                 if (line != null) {
231                     MessageOutput.println("source line number and line",
232                                           new Object JavaDoc [] {new Integer JavaDoc(loc.lineNumber()),
233                                                          line});
234                 }
235             }
236         }
237         MessageOutput.println();
238     }
239
240     private void printLocationOfEvent(LocatableEvent theEvent) {
241         printBaseLocation(theEvent.thread().name(), theEvent.location());
242     }
243
244     void help() {
245         MessageOutput.println("zz help text");
246     }
247
248     private static final String JavaDoc[][] commandList = {
249         /*
250          * NOTE: this list must be kept sorted in ascending ASCII
251          * order by element [0]. Ref: isCommand() below.
252          *
253          *Command OK when OK when
254          * name disconnected? readonly?
255          *------------------------------------
256          */

257         {"!!", "n", "y"},
258         {"?", "y", "y"},
259         {"bytecodes", "n", "y"},
260         {"catch", "y", "n"},
261         {"class", "n", "y"},
262         {"classes", "n", "y"},
263         {"classpath", "n", "y"},
264         {"clear", "y", "n"},
265         {"connectors", "y", "y"},
266         {"cont", "n", "n"},
267         {"disablegc", "n", "n"},
268         {"down", "n", "y"},
269         {"dump", "n", "y"},
270         {"enablegc", "n", "n"},
271         {"eval", "n", "y"},
272         {"exclude", "y", "n"},
273         {"exit", "y", "y"},
274         {"extension", "n", "y"},
275         {"fields", "n", "y"},
276         {"gc", "n", "n"},
277         {"help", "y", "y"},
278         {"ignore", "y", "n"},
279         {"interrupt", "n", "n"},
280         {"kill", "n", "n"},
281         {"lines", "n", "y"},
282         {"list", "n", "y"},
283         {"load", "n", "y"},
284         {"locals", "n", "y"},
285         {"lock", "n", "n"},
286         {"memory", "n", "y"},
287         {"methods", "n", "y"},
288         {"monitor", "n", "n"},
289         {"next", "n", "n"},
290         {"pop", "n", "n"},
291         {"print", "n", "y"},
292         {"quit", "y", "y"},
293         {"read", "y", "y"},
294         {"redefine", "n", "n"},
295         {"reenter", "n", "n"},
296         {"resume", "n", "n"},
297         {"run", "y", "n"},
298         {"save", "n", "n"},
299         {"set", "n", "n"},
300         {"sourcepath", "y", "y"},
301         {"step", "n", "n"},
302         {"stepi", "n", "n"},
303         {"stop", "y", "n"},
304         {"suspend", "n", "n"},
305         {"thread", "n", "y"},
306         {"threadgroup", "n", "y"},
307         {"threadgroups", "n", "y"},
308         {"threadlocks", "n", "y"},
309         {"threads", "n", "y"},
310         {"trace", "n", "n"},
311         {"unmonitor", "n", "n"},
312         {"untrace", "n", "n"},
313         {"unwatch", "y", "n"},
314         {"up", "n", "y"},
315         {"use", "y", "y"},
316         {"version", "y", "y"},
317         {"watch", "y", "n"},
318         {"where", "n", "y"},
319         {"wherei", "n", "y"},
320     };
321
322     /*
323      * Look up the command string in commandList.
324      * If found, return the index.
325      * If not found, return index < 0
326      */

327     private int isCommand(String JavaDoc key) {
328         //Reference: binarySearch() in java/util/Arrays.java
329
// Adapted for use with String[][0].
330
int low = 0;
331     int high = commandList.length - 1;
332         long i = 0;
333     while (low <= high) {
334         int mid = (low + high) >>> 1;
335         String JavaDoc midVal = commandList[mid][0];
336             int compare = midVal.compareTo(key);
337         if (compare < 0)
338         low = mid + 1;
339         else if (compare > 0)
340         high = mid - 1;
341         else
342         return mid; // key found
343
}
344     return -(low + 1); // key not found.
345
};
346
347     /*
348      * Return true if the command is OK when disconnected.
349      */

350     private boolean isDisconnectCmd(int ii) {
351         if (ii < 0 || ii >= commandList.length) return false;
352         return (commandList[ii][1].equals("y"));
353     }
354
355     /*
356      * Return true if the command is OK when readonly.
357      */

358     private boolean isReadOnlyCmd(int ii) {
359         if (ii < 0 || ii >= commandList.length) return false;
360         return (commandList[ii][2].equals("y"));
361     };
362
363
364     void executeCommand(StringTokenizer t) {
365         String JavaDoc cmd = t.nextToken().toLowerCase();
366         // Normally, prompt for the next command after this one is done
367
boolean showPrompt = true;
368
369
370         /*
371          * Anything starting with # is discarded as a no-op or 'comment'.
372          */

373         if (!cmd.startsWith("#")) {
374             /*
375              * Next check for an integer repetition prefix. If found,
376              * recursively execute cmd that number of times.
377              */

378             if (Character.isDigit(cmd.charAt(0)) && t.hasMoreTokens()) {
379                 try {
380                     int repeat = Integer.parseInt(cmd);
381                     String JavaDoc subcom = t.nextToken("");
382                     while (repeat-- > 0) {
383                         executeCommand(new StringTokenizer(subcom));
384                         showPrompt = false; // Bypass the printPrompt() below.
385
}
386                 } catch (NumberFormatException JavaDoc exc) {
387                     MessageOutput.println("Unrecognized command. Try help...", cmd);
388                 }
389             } else {
390                 int commandNumber = isCommand(cmd);
391                 /*
392                  * Check for an unknown command
393                  */

394                 if (commandNumber < 0) {
395                     MessageOutput.println("Unrecognized command. Try help...", cmd);
396                 } else if (!Env.connection().isOpen() && !isDisconnectCmd(commandNumber)) {
397                     MessageOutput.println("Command not valid until the VM is started with the run command",
398                                           cmd);
399                 } else if (Env.connection().isOpen() && !Env.vm().canBeModified() &&
400                            !isReadOnlyCmd(commandNumber)) {
401                     MessageOutput.println("Command is not supported on a read-only VM connection",
402                                           cmd);
403                 } else {
404
405                     Commands evaluator = new Commands();
406                     try {
407                         if (cmd.equals("print")) {
408                             evaluator.commandPrint(t, false);
409                             showPrompt = false; // asynchronous command
410
} else if (cmd.equals("eval")) {
411                             evaluator.commandPrint(t, false);
412                             showPrompt = false; // asynchronous command
413
} else if (cmd.equals("set")) {
414                             evaluator.commandSet(t);
415                             showPrompt = false; // asynchronous command
416
} else if (cmd.equals("dump")) {
417                             evaluator.commandPrint(t, true);
418                             showPrompt = false; // asynchronous command
419
} else if (cmd.equals("locals")) {
420                             evaluator.commandLocals();
421                         } else if (cmd.equals("classes")) {
422                             evaluator.commandClasses();
423                         } else if (cmd.equals("class")) {
424                             evaluator.commandClass(t);
425                         } else if (cmd.equals("connectors")) {
426                             evaluator.commandConnectors(Bootstrap.virtualMachineManager());
427                         } else if (cmd.equals("methods")) {
428                             evaluator.commandMethods(t);
429                         } else if (cmd.equals("fields")) {
430                             evaluator.commandFields(t);
431                         } else if (cmd.equals("threads")) {
432                             evaluator.commandThreads(t);
433                         } else if (cmd.equals("thread")) {
434                             evaluator.commandThread(t);
435                         } else if (cmd.equals("suspend")) {
436                             evaluator.commandSuspend(t);
437                         } else if (cmd.equals("resume")) {
438                             evaluator.commandResume(t);
439                         } else if (cmd.equals("cont")) {
440                             evaluator.commandCont();
441                         } else if (cmd.equals("threadgroups")) {
442                             evaluator.commandThreadGroups();
443                         } else if (cmd.equals("threadgroup")) {
444                             evaluator.commandThreadGroup(t);
445                         } else if (cmd.equals("catch")) {
446                             evaluator.commandCatchException(t);
447                         } else if (cmd.equals("ignore")) {
448                             evaluator.commandIgnoreException(t);
449                         } else if (cmd.equals("step")) {
450                             evaluator.commandStep(t);
451                         } else if (cmd.equals("stepi")) {
452                             evaluator.commandStepi();
453                         } else if (cmd.equals("next")) {
454                             evaluator.commandNext();
455                         } else if (cmd.equals("kill")) {
456                             evaluator.commandKill(t);
457                         } else if (cmd.equals("interrupt")) {
458                             evaluator.commandInterrupt(t);
459                         } else if (cmd.equals("trace")) {
460                             evaluator.commandTrace(t);
461                         } else if (cmd.equals("untrace")) {
462                             evaluator.commandUntrace(t);
463                         } else if (cmd.equals("where")) {
464                             evaluator.commandWhere(t, false);
465                         } else if (cmd.equals("wherei")) {
466                             evaluator.commandWhere(t, true);
467                         } else if (cmd.equals("up")) {
468                             evaluator.commandUp(t);
469                         } else if (cmd.equals("down")) {
470                             evaluator.commandDown(t);
471                         } else if (cmd.equals("load")) {
472                             evaluator.commandLoad(t);
473                         } else if (cmd.equals("run")) {
474                             evaluator.commandRun(t);
475                             /*
476                              * Fire up an event handler, if the connection was just
477                              * opened. Since this was done from the run command
478                              * we don't stop the VM on its VM start event (so
479                              * arg 2 is false).
480                              */

481                             if ((handler == null) && Env.connection().isOpen()) {
482                                 handler = new EventHandler(this, false);
483                             }
484                         } else if (cmd.equals("memory")) {
485                             evaluator.commandMemory();
486                         } else if (cmd.equals("gc")) {
487                             evaluator.commandGC();
488                         } else if (cmd.equals("stop")) {
489                             evaluator.commandStop(t);
490                         } else if (cmd.equals("clear")) {
491                             evaluator.commandClear(t);
492                         } else if (cmd.equals("watch")) {
493                             evaluator.commandWatch(t);
494                         } else if (cmd.equals("unwatch")) {
495                             evaluator.commandUnwatch(t);
496                         } else if (cmd.equals("list")) {
497                             evaluator.commandList(t);
498                         } else if (cmd.equals("lines")) { // Undocumented command: useful for testing.
499
evaluator.commandLines(t);
500                         } else if (cmd.equals("classpath")) {
501                             evaluator.commandClasspath(t);
502                         } else if (cmd.equals("use") || cmd.equals("sourcepath")) {
503                             evaluator.commandUse(t);
504                         } else if (cmd.equals("monitor")) {
505                             monitorCommand(t);
506                         } else if (cmd.equals("unmonitor")) {
507                             unmonitorCommand(t);
508                         } else if (cmd.equals("lock")) {
509                             evaluator.commandLock(t);
510                             showPrompt = false; // asynchronous command
511
} else if (cmd.equals("threadlocks")) {
512                             evaluator.commandThreadlocks(t);
513                         } else if (cmd.equals("disablegc")) {
514                             evaluator.commandDisableGC(t);
515                             showPrompt = false; // asynchronous command
516
} else if (cmd.equals("enablegc")) {
517                             evaluator.commandEnableGC(t);
518                             showPrompt = false; // asynchronous command
519
} else if (cmd.equals("save")) { // Undocumented command: useful for testing.
520
evaluator.commandSave(t);
521                             showPrompt = false; // asynchronous command
522
} else if (cmd.equals("bytecodes")) { // Undocumented command: useful for testing.
523
evaluator.commandBytecodes(t);
524                         } else if (cmd.equals("redefine")) {
525                             evaluator.commandRedefine(t);
526                         } else if (cmd.equals("pop")) {
527                             evaluator.commandPopFrames(t, false);
528                         } else if (cmd.equals("reenter")) {
529                             evaluator.commandPopFrames(t, true);
530                         } else if (cmd.equals("extension")) {
531                             evaluator.commandExtension(t);
532                         } else if (cmd.equals("exclude")) {
533                             evaluator.commandExclude(t);
534                         } else if (cmd.equals("read")) {
535                             readCommand(t);
536                         } else if (cmd.equals("help") || cmd.equals("?")) {
537                             help();
538                         } else if (cmd.equals("version")) {
539                             evaluator.commandVersion(progname,
540                                                      Bootstrap.virtualMachineManager());
541                         } else if (cmd.equals("quit") || cmd.equals("exit")) {
542                             if (handler != null) {
543                                 handler.shutdown();
544                             }
545                             Env.shutdown();
546                         } else {
547                             MessageOutput.println("Unrecognized command. Try help...", cmd);
548                         }
549                     } catch (VMCannotBeModifiedException rovm) {
550                         MessageOutput.println("Command is not supported on a read-only VM connection", cmd);
551                     } catch (UnsupportedOperationException JavaDoc uoe) {
552                         MessageOutput.println("Command is not supported on the target VM", cmd);
553                     } catch (VMNotConnectedException vmnse) {
554                         MessageOutput.println("Command not valid until the VM is started with the run command",
555                                               cmd);
556                     } catch (Exception JavaDoc e) {
557                         MessageOutput.printException("Internal exception:", e);
558                     }
559                 }
560             }
561         }
562         if (showPrompt) {
563             MessageOutput.printPrompt();
564         }
565     }
566
567     /*
568      * Maintain a list of commands to execute each time the VM is suspended.
569      */

570     void monitorCommand(StringTokenizer t) {
571         if (t.hasMoreTokens()) {
572             ++monitorCount;
573             monitorCommands.add(monitorCount + ": " + t.nextToken(""));
574         } else {
575             Iterator it = monitorCommands.iterator();
576             while (it.hasNext()) {
577                 MessageOutput.printDirectln((String JavaDoc)it.next());// Special case: use printDirectln()
578
}
579         }
580     }
581
582     void unmonitorCommand(StringTokenizer t) {
583         if (t.hasMoreTokens()) {
584             String JavaDoc monTok = t.nextToken();
585             int monNum;
586             try {
587                 monNum = Integer.parseInt(monTok);
588             } catch (NumberFormatException JavaDoc exc) {
589                 MessageOutput.println("Not a monitor number:", monTok);
590                 return;
591             }
592             String JavaDoc monStr = monTok + ":";
593             Iterator it = monitorCommands.iterator();
594             while (it.hasNext()) {
595                 String JavaDoc cmd = (String JavaDoc)it.next();
596                 StringTokenizer ct = new StringTokenizer(cmd);
597                 if (ct.nextToken().equals(monStr)) {
598                     monitorCommands.remove(cmd);
599                     MessageOutput.println("Unmonitoring", cmd);
600                     return;
601                 }
602             }
603             MessageOutput.println("No monitor numbered:", monTok);
604         } else {
605             MessageOutput.println("Usage: unmonitor <monitor#>");
606         }
607     }
608
609
610     void readCommand(StringTokenizer t) {
611         if (t.hasMoreTokens()) {
612             String JavaDoc cmdfname = t.nextToken();
613             if (!readCommandFile(cmdfname)) {
614                 MessageOutput.println("Could not open:", cmdfname);
615             }
616         } else {
617             MessageOutput.println("Usage: read <command-filename>");
618         }
619     }
620
621     /**
622      * Read and execute a command file. Return true if the
623      * file could be opened.
624      */

625     boolean readCommandFile(String JavaDoc filename) {
626         File f = new File(filename);
627         BufferedReader inFile = null;
628         try {
629             if (f.canRead()) {
630                 MessageOutput.println("*** Reading commands from", f.getCanonicalPath());
631                 // Process initial commands.
632
inFile = new BufferedReader(new FileReader(f));
633                 String JavaDoc ln;
634                 while ((ln = inFile.readLine()) != null) {
635                     StringTokenizer t = new StringTokenizer(ln);
636                     if (t.hasMoreTokens()) {
637                         executeCommand(t);
638                     }
639                 }
640             }
641         } catch (IOException e) {
642         } finally {
643             if (inFile != null) {
644                 try {
645                     inFile.close();
646                 } catch (Exception JavaDoc exc) {
647                 }
648             }
649         }
650         return inFile != null;
651     }
652
653     public TTY() throws Exception JavaDoc {
654
655         MessageOutput.println("Initializing progname", progname);
656        
657         if (Env.connection().isOpen() && Env.vm().canBeModified()) {
658             /*
659              * Connection opened on startup. Start event handler
660              * immediately, telling it (through arg 2) to stop on the
661              * VM start event.
662              */

663             this.handler = new EventHandler(this, true);
664         }
665         try {
666             BufferedReader in =
667                     new BufferedReader(new InputStreamReader(System.in));
668     
669             String JavaDoc lastLine = null;
670     
671             Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
672     
673             /*
674              * Try reading user's home startup file. Handle Unix and
675              * and Win32 conventions for the names of these files.
676              */

677             if (!readCommandFile(System.getProperty("user.home") +
678                                  File.separator + "jdb.ini")) {
679                 readCommandFile(System.getProperty("user.home") +
680                                 File.separator + ".jdbrc");
681             }
682     
683             // Try startup file in local directory
684
if (!readCommandFile(System.getProperty("user.dir") +
685                                  File.separator + "jdb.ini")) {
686                 readCommandFile(System.getProperty("user.dir") +
687                                 File.separator + ".jdbrc");
688             }
689     
690             // Process interactive commands.
691
MessageOutput.printPrompt();
692             while (true) {
693                 String JavaDoc ln = in.readLine();
694                 if (ln == null) {
695                     MessageOutput.println("Input stream closed.");
696                     return;
697                 }
698     
699                 if (ln.startsWith("!!") && lastLine != null) {
700                     ln = lastLine + ln.substring(2);
701                     MessageOutput.printDirectln(ln);// Special case: use printDirectln()
702
}
703     
704                 StringTokenizer t = new StringTokenizer(ln);
705                 if (t.hasMoreTokens()) {
706                     lastLine = ln;
707                     executeCommand(t);
708                 } else {
709                     MessageOutput.printPrompt();
710                 }
711             }
712         } catch (VMDisconnectedException e) {
713             handler.handleDisconnectedException();
714         }
715     }
716
717     private static void usage() {
718         MessageOutput.println("zz usage text", new Object JavaDoc [] {progname,
719                                                      File.pathSeparator});
720         System.exit(1);
721     }
722
723     static void usageError(String JavaDoc messageKey) {
724         MessageOutput.println(messageKey);
725         MessageOutput.println();
726         usage();
727     }
728
729     static void usageError(String JavaDoc messageKey, String JavaDoc argument) {
730         MessageOutput.println(messageKey, argument);
731         MessageOutput.println();
732         usage();
733     }
734
735     private static boolean supportsSharedMemory() {
736         List connectors = Bootstrap.virtualMachineManager().allConnectors();
737         Iterator iter = connectors.iterator();
738         while (iter.hasNext()) {
739             Connector connector = (Connector)iter.next();
740             if (connector.transport() == null) {
741                 continue;
742             }
743             if ("dt_shmem".equals(connector.transport().name())) {
744                 return true;
745             }
746         }
747         return false;
748     }
749
750     private static String JavaDoc addressToSocketArgs(String JavaDoc address) {
751         int index = address.indexOf(':');
752         if (index != -1) {
753             String JavaDoc hostString = address.substring(0, index);
754             String JavaDoc portString = address.substring(index + 1);
755             return "hostname=" + hostString + ",port=" + portString;
756         } else {
757             return "port=" + address;
758         }
759     }
760
761     private static boolean hasWhitespace(String JavaDoc string) {
762         int length = string.length();
763         for (int i = 0; i < length; i++) {
764             if (Character.isWhitespace(string.charAt(i))) {
765                 return true;
766             }
767         }
768         return false;
769     }
770
771     private static String JavaDoc addArgument(String JavaDoc string, String JavaDoc argument) {
772         if (hasWhitespace(argument) || argument.indexOf(',') != -1) {
773             // Quotes were stripped out for this argument, add 'em back.
774
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(string);
775             buffer.append('"');
776             for (int i = 0; i < argument.length(); i++) {
777                 char c = argument.charAt(i);
778                 if (c == '"') {
779                     buffer.append('\\');
780                 }
781                 buffer.append(c);
782             }
783             buffer.append("\" ");
784             return buffer.toString();
785         } else {
786             return string + argument + ' ';
787         }
788     }
789
790     public static void main(String JavaDoc argv[]) throws MissingResourceException {
791         String JavaDoc cmdLine = "";
792         String JavaDoc javaArgs = "";
793         int traceFlags = VirtualMachine.TRACE_NONE;
794         boolean launchImmediately = false;
795         String JavaDoc connectSpec = null;
796         
797         MessageOutput.textResources = ResourceBundle.getBundle
798             ("com.sun.tools.example.debug.tty.TTYResources",
799              Locale.getDefault());
800
801         for (int i = 0; i < argv.length; i++) {
802             String JavaDoc token = argv[i];
803             if (token.equals("-dbgtrace")) {
804                 if ((i == argv.length - 1) ||
805                     ! Character.isDigit(argv[i+1].charAt(0))) {
806                     traceFlags = VirtualMachine.TRACE_ALL;
807                 } else {
808                     String JavaDoc flagStr = "";
809                     try {
810                         flagStr = argv[++i];
811                         traceFlags = Integer.decode(flagStr).intValue();
812                     } catch (NumberFormatException JavaDoc nfe) {
813                         usageError("dbgtrace flag value must be an integer:",
814                                    flagStr);
815                         return;
816                     }
817                 }
818             } else if (token.equals("-X")) {
819                 usageError("Use java minus X to see");
820                 return;
821             } else if (
822                    // Standard VM options passed on
823
token.equals("-v") || token.startsWith("-v:") || // -v[:...]
824
token.startsWith("-verbose") || // -verbose[:...]
825
token.startsWith("-D") ||
826                    // -classpath handled below
827
// NonStandard options passed on
828
token.startsWith("-X") ||
829                    // Old-style options (These should remain in place as long as
830
// the standard VM accepts them)
831
token.equals("-noasyncgc") || token.equals("-prof") ||
832                    token.equals("-verify") || token.equals("-noverify") ||
833                    token.equals("-verifyremote") ||
834                    token.equals("-verbosegc") ||
835                    token.startsWith("-ms") || token.startsWith("-mx") ||
836                    token.startsWith("-ss") || token.startsWith("-oss") ) {
837
838                 javaArgs = addArgument(javaArgs, token);
839             } else if (token.equals("-tclassic")) {
840                 usageError("Classic VM no longer supported.");
841                 return;
842             } else if (token.equals("-tclient")) {
843                 // -client must be the first one
844
javaArgs = "-client " + javaArgs;
845             } else if (token.equals("-tserver")) {
846                 // -server must be the first one
847
javaArgs = "-server " + javaArgs;
848             } else if (token.equals("-sourcepath")) {
849                 if (i == (argv.length - 1)) {
850                     usageError("No sourcepath specified.");
851                     return;
852                 }
853                 Env.setSourcePath(argv[++i]);
854             } else if (token.equals("-classpath")) {
855                 if (i == (argv.length - 1)) {
856                     usageError("No classpath specified.");
857                     return;
858                 }
859                 javaArgs = addArgument(javaArgs, token);
860                 javaArgs = addArgument(javaArgs, argv[++i]);
861             } else if (token.equals("-attach")) {
862                 if (connectSpec != null) {
863                     usageError("cannot redefine existing connection", token);
864                     return;
865                 }
866                 if (i == (argv.length - 1)) {
867                     usageError("No attach address specified.");
868                     return;
869                 }
870                 String JavaDoc address = argv[++i];
871
872                 /*
873                  * -attach is shorthand for one of the reference implementation's
874                  * attaching connectors. Use the shared memory attach if it's
875                  * available; otherwise, use sockets. Build a connect
876                  * specification string based on this decision.
877                  */

878                 if (supportsSharedMemory()) {
879                     connectSpec = "com.sun.jdi.SharedMemoryAttach:name=" +
880                                    address;
881                 } else {
882                     String JavaDoc suboptions = addressToSocketArgs(address);
883                     connectSpec = "com.sun.jdi.SocketAttach:" + suboptions;
884                 }
885             } else if (token.equals("-listen") || token.equals("-listenany")) {
886                 if (connectSpec != null) {
887                     usageError("cannot redefine existing connection", token);
888                     return;
889                 }
890                 String JavaDoc address = null;
891                 if (token.equals("-listen")) {
892                     if (i == (argv.length - 1)) {
893                         usageError("No attach address specified.");
894                         return;
895                     }
896                     address = argv[++i];
897                 }
898
899                 /*
900                  * -listen[any] is shorthand for one of the reference implementation's
901                  * listening connectors. Use the shared memory listen if it's
902                  * available; otherwise, use sockets. Build a connect
903                  * specification string based on this decision.
904                  */

905                 if (supportsSharedMemory()) {
906                     connectSpec = "com.sun.jdi.SharedMemoryListen:";
907                     if (address != null) {
908                         connectSpec += ("name=" + address);
909                     }
910                 } else {
911                     connectSpec = "com.sun.jdi.SocketListen:";
912                     if (address != null) {
913                         connectSpec += addressToSocketArgs(address);
914                     }
915                 }
916             } else if (token.equals("-launch")) {
917                 launchImmediately = true;
918             } else if (token.equals("-listconnectors")) {
919                 Commands evaluator = new Commands();
920                 evaluator.commandConnectors(Bootstrap.virtualMachineManager());
921                 return;
922             } else if (token.equals("-connect")) {
923                 /*
924                  * -connect allows the user to pick the connector
925                  * used in bringing up the target VM. This allows
926                  * use of connectors other than those in the reference
927                  * implementation.
928                  */

929                 if (connectSpec != null) {
930                     usageError("cannot redefine existing connection", token);
931                     return;
932                 }
933                 if (i == (argv.length - 1)) {
934                     usageError("No connect specification.");
935                     return;
936                 }
937                 connectSpec = argv[++i];
938             } else if (token.equals("-help")) {
939                 usage();
940             } else if (token.equals("-version")) {
941                 Commands evaluator = new Commands();
942                 evaluator.commandVersion(progname,
943                                          Bootstrap.virtualMachineManager());
944                 System.exit(0);
945             } else if (token.startsWith("-")) {
946                 usageError("invalid option", token);
947                 return;
948             } else {
949                 // Everything from here is part of the command line
950
cmdLine = addArgument("", token);
951                 for (i++; i < argv.length; i++) {
952                     cmdLine = addArgument(cmdLine, argv[i]);
953                 }
954                 break;
955             }
956         }
957
958         /*
959          * Unless otherwise specified, set the default connect spec.
960      */

961
962         /*
963          * Here are examples of jdb command lines and how the options
964      * are interpreted as arguments to the program being debugged.
965      * arg1 arg2
966      * ---- ----
967      * jdb hello a b a b
968      * jdb hello "a b" a b
969      * jdb hello a,b a,b
970      * jdb hello a, b a, b
971      * jdb hello "a, b" a, b
972      * jdb -connect "com.sun.jdi.CommandLineLaunch:main=hello a,b" illegal
973      * jdb -connect com.sun.jdi.CommandLineLaunch:main=hello "a,b" illegal
974      * jdb -connect 'com.sun.jdi.CommandLineLaunch:main=hello "a,b"' arg1 = a,b
975      * jdb -connect 'com.sun.jdi.CommandLineLaunch:main=hello "a b"' arg1 = a b
976      * jdb -connect 'com.sun.jdi.CommandLineLaunch:main=hello a b' arg1 = a arg2 = b
977      * jdb -connect 'com.sun.jdi.CommandLineLaunch:main=hello "a," b' arg1 = a, arg2 = b
978      */

979         if (connectSpec == null) {
980             connectSpec = "com.sun.jdi.CommandLineLaunch:";
981         } else if (!connectSpec.endsWith(",") && !connectSpec.endsWith(":")) {
982             connectSpec += ","; // (Bug ID 4285874)
983
}
984
985         cmdLine = cmdLine.trim();
986         javaArgs = javaArgs.trim();
987
988         if (cmdLine.length() > 0) {
989             if (!connectSpec.startsWith("com.sun.jdi.CommandLineLaunch:")) {
990                 usageError("Cannot specify command line with connector:",
991                            connectSpec);
992                 return;
993             }
994             connectSpec += "main=" + cmdLine + ",";
995         }
996
997         if (javaArgs.length() > 0) {
998             if (!connectSpec.startsWith("com.sun.jdi.CommandLineLaunch:")) {
999                 usageError("Cannot specify target vm arguments with connector:",
1000                           connectSpec);
1001                return;
1002            }
1003            connectSpec += "options=" + javaArgs + ",";
1004        }
1005
1006        try {
1007            if (! connectSpec.endsWith(",")) {
1008                connectSpec += ","; // (Bug ID 4285874)
1009
}
1010            Env.init(connectSpec, launchImmediately, traceFlags);
1011            new TTY();
1012        } catch(Exception JavaDoc e) {
1013            MessageOutput.printException("Internal exception:", e);
1014        }
1015    }
1016}
1017
1018
Popular Tags