/*
 * Copyright 1998-2004 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.tools.example.debug.tty;

import com.sun.jdi.*;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.request.*;
import com.sun.tools.example.debug.expr.ExpressionParser;
import com.sun.tools.example.debug.expr.ParseException;

import java.text.*;
import java.util.*;
import java.io.*;

class Commands {

    abstract class AsyncExecution {
        abstract void action();

        AsyncExecution() {
            execute();
        }

        void execute() {
            /*
             * Save current thread and stack frame. (BugId 4296031)
             */
            final ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
            final int stackFrame = threadInfo == null? 0 : threadInfo.getCurrentFrameIndex();
            Thread thread = new Thread("asynchronous jdb command") {
                    public void run() {
                        try {
                            action();
                        } catch (UnsupportedOperationException uoe) {
                            //(BugId 4453329)
                            MessageOutput.println("Operation is not supported on the target VM");
                        } catch (Exception e) {
                            MessageOutput.println("Internal exception during operation:",
                                                  e.getMessage());
                        } finally {
                            /*
                             * This was an asynchronous command.  Events may have been
                             * processed while it was running.  Restore the thread and
                             * stack frame the user was looking at.  (BugId 4296031)
                             */
                            if (threadInfo != null) {
                                ThreadInfo.setCurrentThreadInfo(threadInfo);
                                try {
                                    threadInfo.setCurrentFrameIndex(stackFrame);
                                } catch (IncompatibleThreadStateException e) {
                                    MessageOutput.println("Current thread isnt suspended.");
                                } catch (ArrayIndexOutOfBoundsException e) {
                                    MessageOutput.println("Requested stack frame is no longer active:",
                                                          new Object []{new Integer(stackFrame)});
                                }
                            }
                            MessageOutput.printPrompt();
                        }
                    }
                };
            thread.start();
        }
    }

    Commands() {
    }

    private Value evaluate(String expr) {
        Value result = null;
        ExpressionParser.GetFrame frameGetter = null;
        try {
            final ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
            if ((threadInfo != null) && (threadInfo.getCurrentFrame() != null)) {
                frameGetter = new ExpressionParser.GetFrame() {
                        public StackFrame get() throws IncompatibleThreadStateException {
                            return threadInfo.getCurrentFrame();
                        }
                    };
            }
            result = ExpressionParser.evaluate(expr, Env.vm(), frameGetter);
        } catch (InvocationException ie) {
            MessageOutput.println("Exception in expression:",
                                  ie.exception().referenceType().name());
        } catch (Exception ex) {
            String exMessage = ex.getMessage();
            if (exMessage == null) {
                MessageOutput.printException(exMessage, ex);
            } else {
                String s;
                try {
                    s = MessageOutput.format(exMessage);
                } catch (MissingResourceException mex) {
                    s = ex.toString();
                }
                MessageOutput.printDirectln(s);// Special case: use printDirectln()
            }
        }
        return result;
    }

    private String getStringValue() {
         Value val = null;
         String valStr = null;
         try {
              val = ExpressionParser.getMassagedValue();
              valStr = val.toString();
         } catch (ParseException e) {
              String msg = e.getMessage();
              if (msg == null) {
                  MessageOutput.printException(msg, e);
              } else {
                  String s;
                  try {
                      s = MessageOutput.format(msg);
                  } catch (MissingResourceException mex) {
                      s = e.toString();
                  }
                  MessageOutput.printDirectln(s);
              }
         }
         return valStr;
    }

    private ThreadInfo doGetThread(String idToken) {
        ThreadInfo threadInfo = ThreadInfo.getThreadInfo(idToken);
        if (threadInfo == null) {
            MessageOutput.println("is not a valid thread id", idToken);
        }
        return threadInfo;
    }

    String typedName(Method method) {
        StringBuffer buf = new StringBuffer();
        buf.append(method.name());
        buf.append("(");

        List args = method.argumentTypeNames();
        int lastParam = args.size() - 1;
        // output param types except for the last
        for (int ii = 0; ii < lastParam; ii++) {
            buf.append((String)args.get(ii));
            buf.append(", ");
        }
        if (lastParam >= 0) {
            // output the last param
            String lastStr = (String)args.get(lastParam);
            if (method.isVarArgs()) {
                // lastParam is an array.  Replace the [] with ...
                buf.append(lastStr.substring(0, lastStr.length() - 2));
                buf.append("...");
            } else {
                buf.append(lastStr);
            }
        }
        buf.append(")");
        return buf.toString();
    }

    void commandConnectors(VirtualMachineManager vmm) {
        Iterator iter = vmm.allConnectors().iterator();
        if (iter.hasNext()) {
            MessageOutput.println("Connectors available");
        }
        while (iter.hasNext()) {
            Connector cc = (Connector)iter.next();
            String transportName =
                cc.transport() == null ? "null" : cc.transport().name();
            MessageOutput.println();
            MessageOutput.println("Connector and Transport name",
                                  new Object [] {cc.name(), transportName});
            MessageOutput.println("Connector description", cc.description());

            Iterator argIter = cc.defaultArguments().values().iterator();
            if (argIter.hasNext()) {
                while (argIter.hasNext()) {
                    Connector.Argument aa = (Connector.Argument)argIter.next();
                    MessageOutput.println();

                    boolean requiredArgument = aa.mustSpecify();
                    if (aa.value() == null || aa.value() == "") {
                        //no current value and no default.
                        MessageOutput.println(requiredArgument ?
                                              "Connector required argument nodefault" :
                                              "Connector argument nodefault", aa.name());
                    } else {
                        MessageOutput.println(requiredArgument ?
                                              "Connector required argument default" :
                                              "Connector argument default",
                                              new Object [] {aa.name(), aa.value()});
                    }
                    MessageOutput.println("Connector description", aa.description());

                }
            }
        }

    }

    void commandClasses() {
        List list = Env.vm().allClasses();

        StringBuffer classList = new StringBuffer();
        for (int i = 0 ; i < list.size() ; i++) {
            ReferenceType refType = (ReferenceType)list.get(i);
            classList.append(refType.name());
            classList.append("\n");
        }
        MessageOutput.print("** classes list **", classList.toString());
    }

    void commandClass(StringTokenizer t) {
        List list = Env.vm().allClasses();

        if (!t.hasMoreTokens()) {
            MessageOutput.println("No class specified.");
            return;
        }

        String idClass = t.nextToken();
        boolean showAll = false;

        if (t.hasMoreTokens()) {
            if (t.nextToken().toLowerCase().equals("all")) {
                showAll = true;
            } else {
                MessageOutput.println("Invalid option on class command");
                return;
            }
        }
        ReferenceType type = Env.getReferenceTypeFromToken(idClass);
        if (type == null) {
            MessageOutput.println("is not a valid id or class name", idClass);
            return;
        }
        if (type instanceof ClassType) {
            ClassType clazz = (ClassType)type;
            MessageOutput.println("Class:", clazz.name());

            ClassType superclass = clazz.superclass();
            while (superclass != null) {
                MessageOutput.println("extends:", superclass.name());
                superclass = showAll ? superclass.superclass() : null;
            }

            List interfaces = showAll ? clazz.allInterfaces()
                                      : clazz.interfaces();
            Iterator iter = interfaces.iterator();
            while (iter.hasNext()) {
                InterfaceType interfaze = (InterfaceType)iter.next();
                MessageOutput.println("implements:", interfaze.name());
            }

            List subs = clazz.subclasses();
            iter = subs.iterator();
            while (iter.hasNext()) {
                ClassType sub = (ClassType)iter.next();
                MessageOutput.println("subclass:", sub.name());
            }
            List nested = clazz.nestedTypes();
            iter = nested.iterator();
            while (iter.hasNext()) {
                ReferenceType nest = (ReferenceType)iter.next();
                MessageOutput.println("nested:", nest.name());
            }
        } else if (type instanceof InterfaceType) {
            InterfaceType interfaze = (InterfaceType)type;
            MessageOutput.println("Interface:", interfaze.name());
            List supers = interfaze.superinterfaces();
            Iterator iter = supers.iterator();
            while (iter.hasNext()) {
                InterfaceType superinterface = (InterfaceType)iter.next();
                MessageOutput.println("extends:", superinterface.name());
            }
            List subs = interfaze.subinterfaces();
            iter = subs.iterator();
            while (iter.hasNext()) {
                InterfaceType sub = (InterfaceType)iter.next();
                MessageOutput.println("subinterface:", sub.name());
            }
            List implementors = interfaze.implementors();
            iter = implementors.iterator();
            while (iter.hasNext()) {
                ClassType implementor = (ClassType)iter.next();
                MessageOutput.println("implementor:", implementor.name());
            }
            List nested = interfaze.nestedTypes();
            iter = nested.iterator();
            while (iter.hasNext()) {
                ReferenceType nest = (ReferenceType)iter.next();
                MessageOutput.println("nested:", nest.name());
            }
        } else {  // array type
            ArrayType array = (ArrayType)type;
            MessageOutput.println("Array:", array.name());
        }
    }

    void commandMethods(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No class specified.");
            return;
        }

        String idClass = t.nextToken();
        ReferenceType cls = Env.getReferenceTypeFromToken(idClass);
        if (cls != null) {
            List methods = cls.allMethods();
            StringBuffer methodsList = new StringBuffer();
            for (int i = 0; i < methods.size(); i++) {
                Method method = (Method)methods.get(i);
                methodsList.append(method.declaringType().name());
                methodsList.append(" ");
                methodsList.append(typedName(method));
                methodsList.append('\n');
            }
            MessageOutput.print("** methods list **", methodsList.toString());
        } else {
            MessageOutput.println("is not a valid id or class name", idClass);
        }
    }

    void commandFields(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No class specified.");
            return;
        }

        String idClass = t.nextToken();
        ReferenceType cls = Env.getReferenceTypeFromToken(idClass);
        if (cls != null) {
            List fields = cls.allFields();
            List visible = cls.visibleFields();
            StringBuffer fieldsList = new StringBuffer();
            for (int i = 0; i < fields.size(); i++) {
                Field field = (Field)fields.get(i);
                String s;
                if (!visible.contains(field)) {
                    s = MessageOutput.format("list field typename and name hidden",
                                             new Object [] {field.typeName(),
                                                            field.name()});
                } else if (!field.declaringType().equals(cls)) {
                    s = MessageOutput.format("list field typename and name inherited",
                                             new Object [] {field.typeName(),
                                                            field.name(),
                                                            field.declaringType().name()});
                } else {
                    s = MessageOutput.format("list field typename and name",
                                             new Object [] {field.typeName(),
                                                            field.name()});
                }
                fieldsList.append(s);
            }
            MessageOutput.print("** fields list **", fieldsList.toString());
        } else {
            MessageOutput.println("is not a valid id or class name", idClass);
        }
    }

    private void printThreadGroup(ThreadGroupReference tg) {
        ThreadIterator threadIter = new ThreadIterator(tg);

        MessageOutput.println("Thread Group:", tg.name());
        int maxIdLength = 0;
        int maxNameLength = 0;
        while (threadIter.hasNext()) {
            ThreadReference thr = (ThreadReference)threadIter.next();
            maxIdLength = Math.max(maxIdLength,
                                   Env.description(thr).length());
            maxNameLength = Math.max(maxNameLength,
                                     thr.name().length());
        }

        threadIter = new ThreadIterator(tg);
        while (threadIter.hasNext()) {
            ThreadReference thr = (ThreadReference)threadIter.next();
            if (thr.threadGroup() == null) {
                continue;
            }
            // Note any thread group changes
            if (!thr.threadGroup().equals(tg)) {
                tg = thr.threadGroup();
                MessageOutput.println("Thread Group:", tg.name());
            }

            /*
             * Do a bit of filling with whitespace to get thread ID
             * and thread names to line up in the listing, and also
             * allow for proper localization.  This also works for
             * very long thread names, at the possible cost of lines
             * being wrapped by the display device.
             */
            StringBuffer idBuffer = new StringBuffer(Env.description(thr));
            for (int i = idBuffer.length(); i < maxIdLength; i++) {
                idBuffer.append(" ");
            }
            StringBuffer nameBuffer = new StringBuffer(thr.name());
            for (int i = nameBuffer.length(); i < maxNameLength; i++) {
                nameBuffer.append(" ");
            }

            /*
             * Select the output format to use based on thread status
             * and breakpoint.
             */
            String statusFormat;
            switch (thr.status()) {
            case ThreadReference.THREAD_STATUS_UNKNOWN:
                if (thr.isAtBreakpoint()) {
                    statusFormat = "Thread description name unknownStatus BP";
                } else {
                    statusFormat = "Thread description name unknownStatus";
                }
                break;
            case ThreadReference.THREAD_STATUS_ZOMBIE:
                if (thr.isAtBreakpoint()) {
                    statusFormat = "Thread description name zombieStatus BP";
                } else {
                    statusFormat = "Thread description name zombieStatus";
                }
                break;
            case ThreadReference.THREAD_STATUS_RUNNING:
                if (thr.isAtBreakpoint()) {
                    statusFormat = "Thread description name runningStatus BP";
                } else {
                    statusFormat = "Thread description name runningStatus";
                }
                break;
            case ThreadReference.THREAD_STATUS_SLEEPING:
                if (thr.isAtBreakpoint()) {
                    statusFormat = "Thread description name sleepingStatus BP";
                } else {
                    statusFormat = "Thread description name sleepingStatus";
                }
                break;
            case ThreadReference.THREAD_STATUS_MONITOR:
                if (thr.isAtBreakpoint()) {
                    statusFormat = "Thread description name waitingStatus BP";
                } else {
                    statusFormat = "Thread description name waitingStatus";
                }
                break;
            case ThreadReference.THREAD_STATUS_WAIT:
                if (thr.isAtBreakpoint()) {
                    statusFormat = "Thread description name condWaitstatus BP";
                } else {
                    statusFormat = "Thread description name condWaitstatus";
                }
                break;
            default:
                throw new InternalError(MessageOutput.format("Invalid thread status."));
            }
            MessageOutput.println(statusFormat,
                                  new Object [] {idBuffer.toString(),
                                                 nameBuffer.toString()});
        }
    }

    void commandThreads(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            printThreadGroup(ThreadInfo.group());
            return;
        }
        String name = t.nextToken();
        ThreadGroupReference tg = ThreadGroupIterator.find(name);
        if (tg == null) {
            MessageOutput.println("is not a valid threadgroup name", name);
        } else {
            printThreadGroup(tg);
        }
    }

    void commandThreadGroups() {
        ThreadGroupIterator it = new ThreadGroupIterator();
        int cnt = 0;
        while (it.hasNext()) {
            ThreadGroupReference tg = it.nextThreadGroup();
            ++cnt;
            MessageOutput.println("thread group number description name",
                                  new Object [] { new Integer (cnt),
                                                  Env.description(tg),
                                                  tg.name()});
        }
    }

    void commandThread(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("Thread number not specified.");
            return;
        }
        ThreadInfo threadInfo = doGetThread(t.nextToken());
        if (threadInfo != null) {
            ThreadInfo.setCurrentThreadInfo(threadInfo);
        }
    }

    void commandThreadGroup(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("Threadgroup name not specified.");
            return;
        }
        String name = t.nextToken();
        ThreadGroupReference tg = ThreadGroupIterator.find(name);
        if (tg == null) {
            MessageOutput.println("is not a valid threadgroup name", name);
        } else {
            ThreadInfo.setThreadGroup(tg);
        }
    }

    void commandRun(StringTokenizer t) {
        /*
         * The 'run' command makes little sense in a
         * that doesn't support restarts or multiple VMs. However,
         * this is an attempt to emulate the behavior of the old
         * JDB as much as possible. For new users and implementations
         * it is much more straightforward to launch immedidately
         * with the -launch option.
         */
        VMConnection connection = Env.connection();
        if (!connection.isLaunch()) {
            if (!t.hasMoreTokens()) {
                commandCont();
            } else {
                MessageOutput.println("run <args> command is valid only with launched VMs");
            }
            return;
        }
        if (connection.isOpen()) {
            MessageOutput.println("VM already running. use cont to continue after events.");
            return;
        }

        /*
         * Set the main class and any arguments. Note that this will work
         * only with the standard launcher, "com.sun.jdi.CommandLineLauncher"
         */
        String args;
        if (t.hasMoreTokens()) {
            args = t.nextToken("");
            boolean argsSet = connection.setConnectorArg("main", args);
            if (!argsSet) {
                MessageOutput.println("Unable to set main class and arguments");
                return;
            }
        } else {
            args = connection.connectorArg("main");
            if (args.length() == 0) {
                MessageOutput.println("Main class and arguments must be specified");
                return;
            }
        }
        MessageOutput.println("run", args);

        /*
         * Launch the VM.
         */
        connection.open();

    }

    void commandLoad(StringTokenizer t) {
        MessageOutput.println("The load command is no longer supported.");
    }

    private List<ThreadReference> allThreads(ThreadGroupReference group) {
        List<ThreadReference> list = new ArrayList<ThreadReference>();
        list.addAll(group.threads());
        Iterator iter = group.threadGroups().iterator();
        while (iter.hasNext()) {
            ThreadGroupReference child = (ThreadGroupReference)iter.next();
            list.addAll(allThreads(child));
        }
        return list;
    }

    void commandSuspend(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            Env.vm().suspend();
            MessageOutput.println("All threads suspended.");
        } else {
            while (t.hasMoreTokens()) {
                ThreadInfo threadInfo = doGetThread(t.nextToken());
                if (threadInfo != null) {
                    threadInfo.getThread().suspend();
                }
            }
        }
    }

    void commandResume(StringTokenizer t) {
         if (!t.hasMoreTokens()) {
             ThreadInfo.invalidateAll();
             Env.vm().resume();
             MessageOutput.println("All threads resumed.");
         } else {
             while (t.hasMoreTokens()) {
                ThreadInfo threadInfo = doGetThread(t.nextToken());
                if (threadInfo != null) {
                    threadInfo.invalidate();
                    threadInfo.getThread().resume();
                }
            }
        }
    }

    void commandCont() {
        if (ThreadInfo.getCurrentThreadInfo() == null) {
            MessageOutput.println("Nothing suspended.");
            return;
        }
        ThreadInfo.invalidateAll();
        Env.vm().resume();
    }

    void clearPreviousStep(ThreadReference thread) {
        /*
         * A previous step may not have completed on this thread;
         * if so, it gets removed here.
         */
         EventRequestManager mgr = Env.vm().eventRequestManager();
         List requests = mgr.stepRequests();
         Iterator iter = requests.iterator();
         while (iter.hasNext()) {
             StepRequest request = (StepRequest)iter.next();
             if (request.thread().equals(thread)) {
                 mgr.deleteEventRequest(request);
                 break;
             }
         }
    }
    /* step
     *
     */
    void commandStep(StringTokenizer t) {
        ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
        if (threadInfo == null) {
            MessageOutput.println("Nothing suspended.");
            return;
        }
        int depth;
        if (t.hasMoreTokens() &&
                  t.nextToken().toLowerCase().equals("up")) {
            depth = StepRequest.STEP_OUT;
        } else {
            depth = StepRequest.STEP_INTO;
        }

        clearPreviousStep(threadInfo.getThread());
        EventRequestManager reqMgr = Env.vm().eventRequestManager();
        StepRequest request = reqMgr.createStepRequest(threadInfo.getThread(),
                                                       StepRequest.STEP_LINE, depth);
        if (depth == StepRequest.STEP_INTO) {
            Env.addExcludes(request);
        }
        // We want just the next step event and no others
        request.addCountFilter(1);
        request.enable();
        ThreadInfo.invalidateAll();
        Env.vm().resume();
    }

    /* stepi
     * step instruction.
     */
    void commandStepi() {
        ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
        if (threadInfo == null) {
            MessageOutput.println("Nothing suspended.");
            return;
        }
        clearPreviousStep(threadInfo.getThread());
        EventRequestManager reqMgr = Env.vm().eventRequestManager();
        StepRequest request = reqMgr.createStepRequest(threadInfo.getThread(),
                                                       StepRequest.STEP_MIN,
                                                       StepRequest.STEP_INTO);
        Env.addExcludes(request);
        // We want just the next step event and no others
        request.addCountFilter(1);
        request.enable();
        ThreadInfo.invalidateAll();
        Env.vm().resume();
    }

    void commandNext() {
        ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
        if (threadInfo == null) {
            MessageOutput.println("Nothing suspended.");
            return;
        }
        clearPreviousStep(threadInfo.getThread());
        EventRequestManager reqMgr = Env.vm().eventRequestManager();
        StepRequest request = reqMgr.createStepRequest(threadInfo.getThread(),
                                                       StepRequest.STEP_LINE,
                                                       StepRequest.STEP_OVER);
        Env.addExcludes(request);
        // We want just the next step event and no others
        request.addCountFilter(1);
        request.enable();
        ThreadInfo.invalidateAll();
        Env.vm().resume();
    }

    void doKill(ThreadReference thread, StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No exception object specified.");
            return;
        }
        String expr = t.nextToken("");
        Value val = evaluate(expr);
        if ((val != null) && (val instanceof ObjectReference)) {
            try {
                thread.stop((ObjectReference)val);
                MessageOutput.println("killed", thread.toString());
            } catch (InvalidTypeException e) {
                MessageOutput.println("Invalid exception object");
            }
        } else {
            MessageOutput.println("Expression must evaluate to an object");
        }
    }

    void doKillThread(final ThreadReference threadToKill,
                      final StringTokenizer tokenizer) {
        new AsyncExecution() {
                void action() {
                    doKill(threadToKill, tokenizer);
                }
            };
    }

    void commandKill(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("Usage: kill <thread id> <throwable>");
            return;
        }
        ThreadInfo threadInfo = doGetThread(t.nextToken());
        if (threadInfo != null) {
            MessageOutput.println("killing thread:", threadInfo.getThread().name());
            doKillThread(threadInfo.getThread(), t);
            return;
        }
    }

    void listCaughtExceptions() {
        boolean noExceptions = true;

        // Print a listing of the catch patterns currently in place
        Iterator iter = Env.specList.eventRequestSpecs().iterator();
        while (iter.hasNext()) {
            EventRequestSpec spec = (EventRequestSpec)iter.next();
            if (spec instanceof ExceptionSpec) {
                if (noExceptions) {
                    noExceptions = false;
                    MessageOutput.println("Exceptions caught:");
                }
                MessageOutput.println("tab", spec.toString());
            }
        }
        if (noExceptions) {
            MessageOutput.println("No exceptions caught.");
        }
    }

    private EventRequestSpec parseExceptionSpec(StringTokenizer t) {
        String notification = t.nextToken();
        boolean notifyCaught = false;
        boolean notifyUncaught = false;
        EventRequestSpec spec = null;
        String classPattern = null;

        if (notification.equals("uncaught")) {
            notifyCaught = false;
            notifyUncaught = true;
        } else if (notification.equals("caught")) {
            notifyCaught = true;
            notifyUncaught = false;
        } else if (notification.equals("all")) {
            notifyCaught = true;
            notifyUncaught = true;
        } else {
            /*
             * Handle the same as "all" for backward
             * compatibility with existing .jdbrc files.
             *
             * Insert an "all" and take the current token as the
             * intended classPattern
             *
             */
            notifyCaught = true;
            notifyUncaught = true;
            classPattern = notification;
        }
        if (classPattern == null && t.hasMoreTokens()) {
            classPattern = t.nextToken();
        }
        if ((classPattern != null) && (notifyCaught || notifyUncaught)) {
            try {
                spec = Env.specList.createExceptionCatch(classPattern,
                                                         notifyCaught,
                                                         notifyUncaught);
            } catch (ClassNotFoundException exc) {
                MessageOutput.println("is not a valid class name", classPattern);
            }
        }
        return spec;
    }

    void commandCatchException(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            listCaughtExceptions();
        } else {
            EventRequestSpec spec = parseExceptionSpec(t);
            if (spec != null) {
                resolveNow(spec);
            } else {
                MessageOutput.println("Usage: catch exception");
            }
        }
    }

    void commandIgnoreException(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            listCaughtExceptions();
        } else {
            EventRequestSpec spec = parseExceptionSpec(t);
            if (Env.specList.delete(spec)) {
                MessageOutput.println("Removed:", spec.toString());
            } else {
                if (spec != null) {
                    MessageOutput.println("Not found:", spec.toString());
                }
                MessageOutput.println("Usage: ignore exception");
            }
        }
    }

    void commandUp(StringTokenizer t) {
        ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
        if (threadInfo == null) {
            MessageOutput.println("Current thread not set.");
            return;
        }

        int nLevels = 1;
        if (t.hasMoreTokens()) {
            String idToken = t.nextToken();
            int i;
            try {
                NumberFormat nf = NumberFormat.getNumberInstance();
                nf.setParseIntegerOnly(true);
                Number n = nf.parse(idToken);
                i = n.intValue();
            } catch (java.text.ParseException jtpe) {
                i = 0;
            }
            if (i <= 0) {
                MessageOutput.println("Usage: up [n frames]");
                return;
            }
            nLevels = i;
        }

        try {
            threadInfo.up(nLevels);
        } catch (IncompatibleThreadStateException e) {
            MessageOutput.println("Current thread isnt suspended.");
        } catch (ArrayIndexOutOfBoundsException e) {
            MessageOutput.println("End of stack.");
        }
    }

    void commandDown(StringTokenizer t) {
        ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
        if (threadInfo == null) {
            MessageOutput.println("Current thread not set.");
            return;
        }

        int nLevels = 1;
        if (t.hasMoreTokens()) {
            String idToken = t.nextToken();
            int i;
            try {
                NumberFormat nf = NumberFormat.getNumberInstance();
                nf.setParseIntegerOnly(true);
                Number n = nf.parse(idToken);
                i = n.intValue();
            } catch (java.text.ParseException jtpe) {
                i = 0;
            }
            if (i <= 0) {
                MessageOutput.println("Usage: down [n frames]");
                return;
            }
            nLevels = i;
        }

        try {
            threadInfo.down(nLevels);
        } catch (IncompatibleThreadStateException e) {
            MessageOutput.println("Current thread isnt suspended.");
        } catch (ArrayIndexOutOfBoundsException e) {
            MessageOutput.println("End of stack.");
        }
    }

    private void dumpStack(ThreadInfo threadInfo, boolean showPC) {
        List stack = null;
        try {
            stack = threadInfo.getStack();
        } catch (IncompatibleThreadStateException e) {
            MessageOutput.println("Current thread isnt suspended.");
            return;
        }
        if (stack == null) {
            MessageOutput.println("Thread is not running (no stack).");
        } else {
            int nFrames = stack.size();
            for (int i = threadInfo.getCurrentFrameIndex(); i < nFrames; i++) {
                StackFrame frame = (StackFrame)stack.get(i);
                dumpFrame (i, showPC, frame);
            }
        }
    }

    private void dumpFrame (int frameNumber, boolean showPC, StackFrame frame) {
        Location loc = frame.location();
        long pc = -1;
        if (showPC) {
            pc = loc.codeIndex();
        }
        Method meth = loc.method();

        long lineNumber = loc.lineNumber();
        String methodInfo = null;
        if (meth instanceof Method && ((Method)meth).isNative()) {
            methodInfo = MessageOutput.format("native method");
        } else if (lineNumber != -1) {
            try {
                methodInfo = loc.sourceName() +
                    MessageOutput.format("line number",
                                         new Object [] {new Long(lineNumber)});
            } catch (AbsentInformationException e) {
                methodInfo = MessageOutput.format("unknown");
            }
        }
        if (pc != -1) {
            MessageOutput.println("stack frame dump with pc",
                                  new Object [] {new Integer(frameNumber + 1),
                                                 meth.declaringType().name(),
                                                 meth.name(),
                                                 methodInfo,
                                                 new Long(pc)});
        } else {
            MessageOutput.println("stack frame dump",
                                  new Object [] {new Integer(frameNumber + 1),
                                                 meth.declaringType().name(),
                                                 meth.name(),
                                                 methodInfo});
        }
    }

    void commandWhere(StringTokenizer t, boolean showPC) {
        if (!t.hasMoreTokens()) {
            ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
            if (threadInfo == null) {
                MessageOutput.println("No thread specified.");
                return;
            }
            dumpStack(threadInfo, showPC);
        } else {
            String token = t.nextToken();
            if (token.toLowerCase().equals("all")) {
                Iterator iter = ThreadInfo.threads().iterator();
                while (iter.hasNext()) {
                    ThreadInfo threadInfo = (ThreadInfo)iter.next();
                    MessageOutput.println("Thread:",
                                          threadInfo.getThread().name());
                    dumpStack(threadInfo, showPC);
                }
            } else {
                ThreadInfo threadInfo = doGetThread(token);
                if (threadInfo != null) {
                    ThreadInfo.setCurrentThreadInfo(threadInfo);
                    dumpStack(threadInfo, showPC);
                }
            }
        }
    }

    void commandInterrupt(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
            if (threadInfo == null) {
                MessageOutput.println("No thread specified.");
                return;
            }
            threadInfo.getThread().interrupt();
        } else {
            ThreadInfo threadInfo = doGetThread(t.nextToken());
            if (threadInfo != null) {
                threadInfo.getThread().interrupt();
            }
        }
    }

    void commandMemory() {
        MessageOutput.println("The memory command is no longer supported.");
    }

    void commandGC() {
        MessageOutput.println("The gc command is no longer necessary.");
    }

    /*
     * The next two methods are used by this class and by EventHandler
     * to print consistent locations and error messages.
     */
    static String locationString(Location loc) {
        return MessageOutput.format("locationString",
                                    new Object [] {loc.declaringType().name(),
                                                   loc.method().name(),
                                                   new Integer (loc.lineNumber()),
                                                   new Long (loc.codeIndex())});
    }

    void listBreakpoints() {
        boolean noBreakpoints = true;

        // Print set breakpoints
        Iterator iter = Env.specList.eventRequestSpecs().iterator();
        while (iter.hasNext()) {
            EventRequestSpec spec = (EventRequestSpec)iter.next();
            if (spec instanceof BreakpointSpec) {
                if (noBreakpoints) {
                    noBreakpoints = false;
                    MessageOutput.println("Breakpoints set:");
                }
                MessageOutput.println("tab", spec.toString());
            }
        }
        if (noBreakpoints) {
            MessageOutput.println("No breakpoints set.");
        }
    }


    private void printBreakpointCommandUsage(String atForm, String inForm) {
        MessageOutput.println("printbreakpointcommandusage",
                              new Object [] {atForm, inForm});
    }

    protected BreakpointSpec parseBreakpointSpec(StringTokenizer t,
                                             String atForm, String inForm) {
        EventRequestSpec breakpoint = null;
        try {
            String token = t.nextToken(":( \t\n\r");

            // We can't use hasMoreTokens here because it will cause any leading
            // paren to be lost.
            String rest;
            try {
                rest = t.nextToken("").trim();
            } catch (NoSuchElementException e) {
                rest = null;
            }

            if ((rest != null) && rest.startsWith(":")) {
                t = new StringTokenizer(rest.substring(1));
                String classId = token;
                String lineToken = t.nextToken();

                NumberFormat nf = NumberFormat.getNumberInstance();
                nf.setParseIntegerOnly(true);
                Number n = nf.parse(lineToken);
                int lineNumber = n.intValue();

                if (t.hasMoreTokens()) {
                    printBreakpointCommandUsage(atForm, inForm);
                    return null;
                }
                try {
                    breakpoint = Env.specList.createBreakpoint(classId,
                                                               lineNumber);
                } catch (ClassNotFoundException exc) {
                    MessageOutput.println("is not a valid class name", classId);
                }
            } else {
                // Try stripping method from class.method token.
                int idot = token.lastIndexOf(".");
                if ( (idot <= 0) ||                     /* No dot or dot in first char */
                     (idot >= token.length() - 1) ) { /* dot in last char */
                    printBreakpointCommandUsage(atForm, inForm);
                    return null;
                }
                String methodName = token.substring(idot + 1);
                String classId = token.substring(0, idot);
                List<String> argumentList = null;
                if (rest != null) {
                    if (!rest.startsWith("(") || !rest.endsWith(")")) {
                        MessageOutput.println("Invalid method specification:",
                                              methodName + rest);
                        printBreakpointCommandUsage(atForm, inForm);
                        return null;
                    }
                    // Trim the parens
                    rest = rest.substring(1, rest.length() - 1);

                    argumentList = new ArrayList<String>();
                    t = new StringTokenizer(rest, ",");
                    while (t.hasMoreTokens()) {
                        argumentList.add(t.nextToken());
                    }
                }
                try {
                    breakpoint = Env.specList.createBreakpoint(classId,
                                                               methodName,
                                                               argumentList);
                } catch (MalformedMemberNameException exc) {
                    MessageOutput.println("is not a valid method name", methodName);
                } catch (ClassNotFoundException exc) {
                    MessageOutput.println("is not a valid class name", classId);
                }
            }
        } catch (Exception e) {
            printBreakpointCommandUsage(atForm, inForm);
            return null;
        }
        return (BreakpointSpec)breakpoint;
    }

    private void resolveNow(EventRequestSpec spec) {
        boolean success = Env.specList.addEagerlyResolve(spec);
        if (success && !spec.isResolved()) {
            MessageOutput.println("Deferring.", spec.toString());
        }
    }

    void commandStop(StringTokenizer t) {
        Location bploc;
        String atIn;
        byte suspendPolicy = EventRequest.SUSPEND_ALL;

        if (t.hasMoreTokens()) {
            atIn = t.nextToken();
            if (atIn.equals("go") && t.hasMoreTokens()) {
                suspendPolicy = EventRequest.SUSPEND_NONE;
                atIn = t.nextToken();
            } else if (atIn.equals("thread") && t.hasMoreTokens()) {
                suspendPolicy = EventRequest.SUSPEND_EVENT_THREAD;
                atIn = t.nextToken();
            }
        } else {
            listBreakpoints();
            return;
        }

        BreakpointSpec spec = parseBreakpointSpec(t, "stop at", "stop in");
        if (spec != null) {
            // Enforcement of "at" vs. "in". The distinction is really
            // unnecessary and we should consider not checking for this
            // (and making "at" and "in" optional).
            if (atIn.equals("at") && spec.isMethodBreakpoint()) {
                MessageOutput.println("Use stop at to set a breakpoint at a line number");
                printBreakpointCommandUsage("stop at", "stop in");
                return;
            }
            spec.suspendPolicy = suspendPolicy;
            resolveNow(spec);
        }
    }

    void commandClear(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            listBreakpoints();
            return;
        }

        BreakpointSpec spec = parseBreakpointSpec(t, "clear", "clear");
        if (spec != null) {
            if (Env.specList.delete(spec)) {
                MessageOutput.println("Removed:", spec.toString());
            } else {
                MessageOutput.println("Not found:", spec.toString());
            }
        }
    }

    private List<EventRequestSpec> parseWatchpointSpec(StringTokenizer t) {
        List<EventRequestSpec> list = new ArrayList<EventRequestSpec>();
        boolean access = false;
        boolean modification = false;
        int suspendPolicy = EventRequest.SUSPEND_ALL;

        String fieldName = t.nextToken();
        if (fieldName.equals("go")) {
            suspendPolicy = EventRequest.SUSPEND_NONE;
            fieldName = t.nextToken();
        } else if (fieldName.equals("thread")) {
            suspendPolicy = EventRequest.SUSPEND_EVENT_THREAD;
            fieldName = t.nextToken();
        }
        if (fieldName.equals("access")) {
            access = true;
            fieldName = t.nextToken();
        } else if (fieldName.equals("all")) {
            access = true;
            modification = true;
            fieldName = t.nextToken();
        } else {
            modification = true;
        }
        int dot = fieldName.lastIndexOf('.');
        if (dot < 0) {
            MessageOutput.println("Class containing field must be specified.");
            return list;
        }
        String className = fieldName.substring(0, dot);
        fieldName = fieldName.substring(dot+1);

        try {
            EventRequestSpec spec;
            if (access) {
                spec = Env.specList.createAccessWatchpoint(className,
                                                           fieldName);
                spec.suspendPolicy = suspendPolicy;
                list.add(spec);
            }
            if (modification) {
                spec = Env.specList.createModificationWatchpoint(className,
                                                                 fieldName);
                spec.suspendPolicy = suspendPolicy;
                list.add(spec);
            }
        } catch (MalformedMemberNameException exc) {
            MessageOutput.println("is not a valid field name", fieldName);
        } catch (ClassNotFoundException exc) {
            MessageOutput.println("is not a valid class name", className);
        }
        return list;
    }

    void commandWatch(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("Field to watch not specified");
            return;
        }

        Iterator iter = parseWatchpointSpec(t).iterator();
        while (iter.hasNext()) {
            resolveNow((WatchpointSpec)iter.next());
        }
    }

    void commandUnwatch(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("Field to unwatch not specified");
            return;
        }

        Iterator iter = parseWatchpointSpec(t).iterator();
        while (iter.hasNext()) {
            WatchpointSpec spec = (WatchpointSpec)iter.next();
            if (Env.specList.delete(spec)) {
                MessageOutput.println("Removed:", spec.toString());
            } else {
                MessageOutput.println("Not found:", spec.toString());
            }
        }
    }

    void turnOnExitTrace(ThreadInfo threadInfo, int suspendPolicy) {
        EventRequestManager erm = Env.vm().eventRequestManager();
        MethodExitRequest exit = erm.createMethodExitRequest();
        if (threadInfo != null) {
            exit.addThreadFilter(threadInfo.getThread());
        }
        Env.addExcludes(exit);
        exit.setSuspendPolicy(suspendPolicy);
        exit.enable();

    }

    static String methodTraceCommand = null;

    void commandTrace(StringTokenizer t) {
        String modif;
        int suspendPolicy = EventRequest.SUSPEND_ALL;
        ThreadInfo threadInfo = null;
        String goStr = " ";

        /*
         * trace [go] methods [thread]
         * trace [go] method exit | exits [thread]
         */
        if (t.hasMoreTokens()) {
            modif = t.nextToken();
            if (modif.equals("go")) {
                suspendPolicy = EventRequest.SUSPEND_NONE;
                goStr = " go ";
                if (t.hasMoreTokens()) {
                    modif = t.nextToken();
                }
            } else if (modif.equals("thread")) {
                // this is undocumented as it doesn't work right.
                suspendPolicy = EventRequest.SUSPEND_EVENT_THREAD;
                if (t.hasMoreTokens()) {
                    modif = t.nextToken();
                }
            }

            if  (modif.equals("method")) {
                String traceCmd = null;

                if (t.hasMoreTokens()) {
                    String modif1 = t.nextToken();
                    if (modif1.equals("exits") || modif1.equals("exit")) {
                        if (t.hasMoreTokens()) {
                            threadInfo = doGetThread(t.nextToken());
                        }
                        if (modif1.equals("exit")) {
                            StackFrame frame;
                            try {
                                frame = ThreadInfo.getCurrentThreadInfo().getCurrentFrame();
                            } catch (IncompatibleThreadStateException ee) {
                                MessageOutput.println("Current thread isnt suspended.");
                                return;
                            }
                            Env.setAtExitMethod(frame.location().method());
                            traceCmd = MessageOutput.format("trace" +
                                                    goStr + "method exit " +
                                                    "in effect for",
                                                    Env.atExitMethod().toString());
                        } else {
                            traceCmd = MessageOutput.format("trace" +
                                                   goStr + "method exits " +
                                                   "in effect");
                        }
                        commandUntrace(new StringTokenizer("methods"));
                        turnOnExitTrace(threadInfo, suspendPolicy);
                        methodTraceCommand = traceCmd;
                        return;
                    }
                } else {
                   MessageOutput.println("Can only trace");
                   return;
                }
            }
            if (modif.equals("methods")) {
                // Turn on method entry trace
                MethodEntryRequest entry;
                EventRequestManager erm = Env.vm().eventRequestManager();
                if (t.hasMoreTokens()) {
                    threadInfo = doGetThread(t.nextToken());
                }
                if (threadInfo != null) {
                    /*
                     * To keep things simple we want each 'trace' to cancel
                     * previous traces.  However in this case, we don't do that
                     * to preserve backward compatibility with pre JDK 6.0.
                     * IE, you can currently do
                     *   trace   methods 0x21
                     *   trace   methods 0x22
                     * and you will get xxx traced just on those two threads
                     * But this feature is kind of broken because if you then do
                     *   untrace  0x21
                     * it turns off both traces instead of just the one.
                     * Another bogosity is that if you do
                     *   trace methods
                     *   trace methods
                     * and you will get two traces.
                     */

                    entry = erm.createMethodEntryRequest();
                    entry.addThreadFilter(threadInfo.getThread());
                } else {
                    commandUntrace(new StringTokenizer("methods"));
                    entry = erm.createMethodEntryRequest();
                }
                Env.addExcludes(entry);
                entry.setSuspendPolicy(suspendPolicy);
                entry.enable();
                turnOnExitTrace(threadInfo, suspendPolicy);
                methodTraceCommand = MessageOutput.format("trace" + goStr +
                                                          "methods in effect");

                return;
            }

            MessageOutput.println("Can only trace");
            return;
        }

        // trace all by itself.
        if (methodTraceCommand != null) {
            MessageOutput.printDirectln(methodTraceCommand);
        }

        // More trace lines can be added here.
    }

    void commandUntrace(StringTokenizer t) {
        // untrace
        // untrace methods

        String modif = null;
        EventRequestManager erm = Env.vm().eventRequestManager();
        if (t.hasMoreTokens()) {
            modif = t.nextToken();
        }
        if (modif == null || modif.equals("methods")) {
            erm.deleteEventRequests(erm.methodEntryRequests());
            erm.deleteEventRequests(erm.methodExitRequests());
            Env.setAtExitMethod(null);
            methodTraceCommand = null;
        }
    }

    void commandList(StringTokenizer t) {
        StackFrame frame = null;
        ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
        if (threadInfo == null) {
            MessageOutput.println("No thread specified.");
            return;
        }
        try {
            frame = threadInfo.getCurrentFrame();
        } catch (IncompatibleThreadStateException e) {
            MessageOutput.println("Current thread isnt suspended.");
            return;
        }

        if (frame == null) {
            MessageOutput.println("No frames on the current call stack");
            return;
        }

        Location loc = frame.location();
        if (loc.method().isNative()) {
            MessageOutput.println("Current method is native");
            return;
        }

        String sourceFileName = null;
        try {
            sourceFileName = loc.sourceName();

            ReferenceType refType = loc.declaringType();
            int lineno = loc.lineNumber();

            if (t.hasMoreTokens()) {
                String id = t.nextToken();

                // See if token is a line number.
                try {
                    NumberFormat nf = NumberFormat.getNumberInstance();
                    nf.setParseIntegerOnly(true);
                    Number n = nf.parse(id);
                    lineno = n.intValue();
                } catch (java.text.ParseException jtpe) {
                    // It isn't -- see if it's a method name.
                        List meths = refType.methodsByName(id);
                        if (meths == null || meths.size() == 0) {
                            MessageOutput.println("is not a valid line number or method name for",
                                                  new Object [] {id, refType.name()});
                            return;
                        } else if (meths.size() > 1) {
                            MessageOutput.println("is an ambiguous method name in",
                                                  new Object [] {id, refType.name()});
                            return;
                        }
                        loc = ((Method)meths.get(0)).location();
                        lineno = loc.lineNumber();
                }
            }
            int startLine = Math.max(lineno - 4, 1);
            int endLine = startLine + 9;
            if (lineno < 0) {
                MessageOutput.println("Line number information not available for");
            } else if (Env.sourceLine(loc, lineno) == null) {
                MessageOutput.println("is an invalid line number for",
                                      new Object [] {new Integer (lineno),
                                                     refType.name()});
            } else {
                for (int i = startLine; i <= endLine; i++) {
                    String sourceLine = Env.sourceLine(loc, i);
                    if (sourceLine == null) {
                        break;
                    }
                    if (i == lineno) {
                        MessageOutput.println("source line number current line and line",
                                              new Object [] {new Integer (i),
                                                             sourceLine});
                    } else {
                        MessageOutput.println("source line number and line",
                                              new Object [] {new Integer (i),
                                                             sourceLine});
                    }
                }
            }
        } catch (AbsentInformationException e) {
            MessageOutput.println("No source information available for:", loc.toString());
        } catch(FileNotFoundException exc) {
            MessageOutput.println("Source file not found:", sourceFileName);
        } catch(IOException exc) {
            MessageOutput.println("I/O exception occurred:", exc.toString());
        }
    }

    void commandLines(StringTokenizer t) { // Undocumented command: useful for testing
        if (!t.hasMoreTokens()) {
            MessageOutput.println("Specify class and method");
        } else {
            String idClass = t.nextToken();
            String idMethod = t.hasMoreTokens() ? t.nextToken() : null;
            try {
                ReferenceType refType = Env.getReferenceTypeFromToken(idClass);
                if (refType != null) {
                    List lines = null;
                    if (idMethod == null) {
                        lines = refType.allLineLocations();
                    } else {
                        List methods = refType.allMethods();
                        Iterator iter = methods.iterator();
                        while (iter.hasNext()) {
                            Method method = (Method)iter.next();
                            if (method.name().equals(idMethod)) {
                                lines = method.allLineLocations();
                            }
                        }
                        if (lines == null) {
                            MessageOutput.println("is not a valid method name", idMethod);
                        }
                    }
                    Iterator iter = lines.iterator();
                    while (iter.hasNext()) {
                        Location line = (Location)iter.next();
                        MessageOutput.printDirectln(line.toString());// Special case: use printDirectln()
                    }
                } else {
                    MessageOutput.println("is not a valid id or class name", idClass);
                }
            } catch (AbsentInformationException e) {
                MessageOutput.println("Line number information not available for", idClass);
            }
        }
    }

    void commandClasspath(StringTokenizer t) {
        if (Env.vm() instanceof PathSearchingVirtualMachine) {
            PathSearchingVirtualMachine vm = (PathSearchingVirtualMachine)Env.vm();
            MessageOutput.println("base directory:", vm.baseDirectory());
            MessageOutput.println("classpath:", vm.classPath().toString());
            MessageOutput.println("bootclasspath:", vm.bootClassPath().toString());
        } else {
            MessageOutput.println("The VM does not use paths");
        }
    }

    /* Get or set the source file path list. */
    void commandUse(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.printDirectln(Env.getSourcePath());// Special case: use printDirectln()
        } else {
            /*
             * Take the remainder of the command line, minus
             * leading or trailing whitespace.  Embedded
             * whitespace is fine.
             */
            Env.setSourcePath(t.nextToken("").trim());
        }
    }

    /* Print a stack variable */
    private void printVar(LocalVariable var, Value value) {
        MessageOutput.println("expr is value",
                              new Object [] {var.name(),
                                             value == null ? "null" : value.toString()});
    }

    /* Print all local variables in current stack frame. */
    void commandLocals() {
        StackFrame frame;
        ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
        if (threadInfo == null) {
            MessageOutput.println("No default thread specified:");
            return;
        }
        try {
            frame = threadInfo.getCurrentFrame();
            if (frame == null) {
                throw new AbsentInformationException();
            }
            List<LocalVariable> vars = frame.visibleVariables();

            if (vars.size() == 0) {
                MessageOutput.println("No local variables");
                return;
            }
            Map values = frame.getValues(vars);

            MessageOutput.println("Method arguments:");
            for (Iterator it = vars.iterator(); it.hasNext(); ) {
                LocalVariable var = (LocalVariable)it.next();
                if (var.isArgument()) {
                    Value val = (Value)values.get(var);
                    printVar(var, val);
                }
            }
            MessageOutput.println("Local variables:");
            for (Iterator it = vars.iterator(); it.hasNext(); ) {
                LocalVariable var = (LocalVariable)it.next();
                if (!var.isArgument()) {
                    Value val = (Value)values.get(var);
                    printVar(var, val);
                }
            }
        } catch (AbsentInformationException aie) {
            MessageOutput.println("Local variable information not available.");
        } catch (IncompatibleThreadStateException exc) {
            MessageOutput.println("Current thread isnt suspended.");
        }
    }

    private void dump(ObjectReference obj, ReferenceType refType,
                      ReferenceType refTypeBase) {
        for (Iterator it = refType.fields().iterator(); it.hasNext(); ) {
            StringBuffer o = new StringBuffer();
            Field field = (Field)it.next();
            o.append("    ");
            if (!refType.equals(refTypeBase)) {
                o.append(refType.name());
                o.append(".");
            }
            o.append(field.name());
            o.append(MessageOutput.format("colon space"));
            o.append(obj.getValue(field));
            MessageOutput.printDirectln(o.toString()); // Special case: use printDirectln()
        }
        if (refType instanceof ClassType) {
            ClassType sup = ((ClassType)refType).superclass();
            if (sup != null) {
                dump(obj, sup, refTypeBase);
            }
        } else if (refType instanceof InterfaceType) {
            List sups = ((InterfaceType)refType).superinterfaces();
            for (Iterator it = sups.iterator(); it.hasNext(); ) {
                dump(obj, (ReferenceType)it.next(), refTypeBase);
            }
        } else {
            /* else refType is an instanceof ArrayType */
            if (obj instanceof ArrayReference) {
                for (Iterator it = ((ArrayReference)obj).getValues().iterator();
                     it.hasNext(); ) {
                    MessageOutput.printDirect(it.next().toString());// Special case: use printDirect()
                    if (it.hasNext()) {
                        MessageOutput.printDirect(", ");// Special case: use printDirect()
                    }
                }
                MessageOutput.println();
            }
        }
    }

    /* Print a specified reference.
     */
    void doPrint(StringTokenizer t, boolean dumpObject) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No objects specified.");
            return;
        }

        while (t.hasMoreTokens()) {
            String expr = t.nextToken("");
            Value val = evaluate(expr);
            if (val == null) {
                MessageOutput.println("expr is null", expr.toString());
            } else if (dumpObject && (val instanceof ObjectReference) &&
                       !(val instanceof StringReference)) {
                ObjectReference obj = (ObjectReference)val;
                ReferenceType refType = obj.referenceType();
                MessageOutput.println("expr is value",
                                      new Object [] {expr.toString(),
                                                     MessageOutput.format("grouping begin character")});
                dump(obj, refType, refType);
                MessageOutput.println("grouping end character");
            } else {
                  String strVal = getStringValue();
                  if (strVal != null) {
                     MessageOutput.println("expr is value", new Object [] {expr.toString(),
                                                                      strVal});
                   }
            }
        }
    }

    void commandPrint(final StringTokenizer t, final boolean dumpObject) {
        new AsyncExecution() {
                void action() {
                    doPrint(t, dumpObject);
                }
            };
    }

    void commandSet(final StringTokenizer t) {
        String all = t.nextToken("");

        /*
         * Bare bones error checking.
         */
        if (all.indexOf('=') == -1) {
            MessageOutput.println("Invalid assignment syntax");
            MessageOutput.printPrompt();
            return;
        }

        /*
         * The set command is really just syntactic sugar. Pass it on to the
         * print command.
         */
        commandPrint(new StringTokenizer(all), false);
    }

    void doLock(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No object specified.");
            return;
        }

        String expr = t.nextToken("");
        Value val = evaluate(expr);

        try {
            if ((val != null) && (val instanceof ObjectReference)) {
                ObjectReference object = (ObjectReference)val;
                String strVal = getStringValue();
                if (strVal != null) {
                    MessageOutput.println("Monitor information for expr",
                                      new Object [] {expr.trim(),
                                                     strVal});
                }
                ThreadReference owner = object.owningThread();
                if (owner == null) {
                    MessageOutput.println("Not owned");
                } else {
                    MessageOutput.println("Owned by:",
                                          new Object [] {owner.name(),
                                                         new Integer (object.entryCount())});
                }
                List waiters = object.waitingThreads();
                if (waiters.size() == 0) {
                    MessageOutput.println("No waiters");
                } else {
                    Iterator iter = waiters.iterator();
                    while (iter.hasNext()) {
                        ThreadReference waiter = (ThreadReference)iter.next();
                        MessageOutput.println("Waiting thread:", waiter.name());
                    }
                }
            } else {
                MessageOutput.println("Expression must evaluate to an object");
            }
        } catch (IncompatibleThreadStateException e) {
            MessageOutput.println("Threads must be suspended");
        }
    }

    void commandLock(final StringTokenizer t) {
        new AsyncExecution() {
                void action() {
                    doLock(t);
                }
            };
    }

    private void printThreadLockInfo(ThreadInfo threadInfo) {
        ThreadReference thread = threadInfo.getThread();
        try {
            MessageOutput.println("Monitor information for thread", thread.name());
            List owned = thread.ownedMonitors();
            if (owned.size() == 0) {
                MessageOutput.println("No monitors owned");
            } else {
                Iterator iter = owned.iterator();
                while (iter.hasNext()) {
                    ObjectReference monitor = (ObjectReference)iter.next();
                    MessageOutput.println("Owned monitor:", monitor.toString());
                }
            }
            ObjectReference waiting = thread.currentContendedMonitor();
            if (waiting == null) {
                MessageOutput.println("Not waiting for a monitor");
            } else {
                MessageOutput.println("Waiting for monitor:", waiting.toString());
            }
        } catch (IncompatibleThreadStateException e) {
            MessageOutput.println("Threads must be suspended");
        }
    }

    void commandThreadlocks(final StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
            if (threadInfo == null) {
                MessageOutput.println("Current thread not set.");
            } else {
                printThreadLockInfo(threadInfo);
            }
            return;
        }
        String token = t.nextToken();
        if (token.toLowerCase().equals("all")) {
            Iterator iter = ThreadInfo.threads().iterator();
            while (iter.hasNext()) {
                ThreadInfo threadInfo = (ThreadInfo)iter.next();
                printThreadLockInfo(threadInfo);
            }
        } else {
            ThreadInfo threadInfo = doGetThread(token);
            if (threadInfo != null) {
                ThreadInfo.setCurrentThreadInfo(threadInfo);
                printThreadLockInfo(threadInfo);
            }
        }
    }

    void doDisableGC(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No object specified.");
            return;
        }

        String expr = t.nextToken("");
        Value val = evaluate(expr);
        if ((val != null) && (val instanceof ObjectReference)) {
            ObjectReference object = (ObjectReference)val;
            object.disableCollection();
            String strVal = getStringValue();
            if (strVal != null) {
                 MessageOutput.println("GC Disabled for", strVal);
            }
        } else {
            MessageOutput.println("Expression must evaluate to an object");
        }
    }

    void commandDisableGC(final StringTokenizer t) {
        new AsyncExecution() {
                void action() {
                    doDisableGC(t);
                }
            };
    }

    void doEnableGC(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No object specified.");
            return;
        }

        String expr = t.nextToken("");
        Value val = evaluate(expr);
        if ((val != null) && (val instanceof ObjectReference)) {
            ObjectReference object = (ObjectReference)val;
            object.enableCollection();
            String strVal = getStringValue();
            if (strVal != null) {
                 MessageOutput.println("GC Enabled for", strVal);
            }
        } else {
            MessageOutput.println("Expression must evaluate to an object");
        }
    }

    void commandEnableGC(final StringTokenizer t) {
        new AsyncExecution() {
                void action() {
                    doEnableGC(t);
                }
            };
    }

    void doSave(StringTokenizer t) {// Undocumented command: useful for testing.
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No save index specified.");
            return;
        }

        String key = t.nextToken();

        if (!t.hasMoreTokens()) {
            MessageOutput.println("No expression specified.");
            return;
        }
        String expr = t.nextToken("");
        Value val = evaluate(expr);
        if (val != null) {
            Env.setSavedValue(key, val);
            String strVal = getStringValue();
            if (strVal != null) {
                 MessageOutput.println("saved", strVal);
            }
        } else {
            MessageOutput.println("Expression cannot be void");
        }
    }

    void commandSave(final StringTokenizer t) { // Undocumented command: useful for testing.
        if (!t.hasMoreTokens()) {
            Set keys = Env.getSaveKeys();
            Iterator iter = keys.iterator();
            if (!iter.hasNext()) {
                MessageOutput.println("No saved values");
                return;
            }
            while (iter.hasNext()) {
                String key = (String)iter.next();
                Value value = Env.getSavedValue(key);
                if ((value instanceof ObjectReference) &&
                    ((ObjectReference)value).isCollected()) {
                    MessageOutput.println("expr is value <collected>",
                                          new Object [] {key, value.toString()});
                } else {
                    if (value == null){
                        MessageOutput.println("expr is null", key);
                    } else {
                        MessageOutput.println("expr is value",
                                              new Object [] {key, value.toString()});
                    }
                }
            }
        } else {
            new AsyncExecution() {
                    void action() {
                        doSave(t);
                    }
                };
        }

    }

   void commandBytecodes(final StringTokenizer t) { // Undocumented command: useful for testing.
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No class specified.");
            return;
        }
        String className = t.nextToken();

        if (!t.hasMoreTokens()) {
            MessageOutput.println("No method specified.");
            return;
        }
        // Overloading is not handled here.
        String methodName = t.nextToken();

        List classes = Env.vm().classesByName(className);
        // TO DO: handle multiple classes found
        if (classes.size() == 0) {
            if (className.indexOf('.') < 0) {
                MessageOutput.println("not found (try the full name)", className);
            } else {
                MessageOutput.println("not found", className);
            }
            return;
        }

        ReferenceType rt = (ReferenceType)classes.get(0);
        if (!(rt instanceof ClassType)) {
            MessageOutput.println("not a class", className);
            return;
        }

        byte[] bytecodes = null;
        List list = rt.methodsByName(methodName);
        Iterator iter = list.iterator();
        while (iter.hasNext()) {
            Method method = (Method)iter.next();
            if (!method.isAbstract()) {
                bytecodes = method.bytecodes();
                break;
            }
        }

        StringBuffer line = new StringBuffer(80);
        line.append("0000: ");
        for (int i = 0; i < bytecodes.length; i++) {
            if ((i > 0) && (i % 16 == 0)) {
                MessageOutput.printDirectln(line.toString());// Special case: use printDirectln()
                line.setLength(0);
                line.append(String.valueOf(i));
                line.append(": ");
                int len = line.length();
                for (int j = 0; j < 6 - len; j++) {
                    line.insert(0, '0');
                }
            }
            int val = 0xff & bytecodes[i];
            String str = Integer.toHexString(val);
            if (str.length() == 1) {
                line.append('0');
            }
            line.append(str);
            line.append(' ');
        }
        if (line.length() > 6) {
            MessageOutput.printDirectln(line.toString());// Special case: use printDirectln()
        }
    }

    void commandExclude(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.printDirectln(Env.excludesString());// Special case: use printDirectln()
        } else {
            String rest = t.nextToken("");
            if (rest.equals("none")) {
                rest = "";
            }
            Env.setExcludes(rest);
        }
    }

    void commandRedefine(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("Specify classes to redefine");
        } else {
            String className = t.nextToken();
            List classes = Env.vm().classesByName(className);
            if (classes.size() == 0) {
                MessageOutput.println("No class named", className);
                return;
            }
            if (classes.size() > 1) {
                MessageOutput.println("More than one class named", className);
                return;
            }
            Env.setSourcePath(Env.getSourcePath());
            ReferenceType refType = (ReferenceType)classes.get(0);
            if (!t.hasMoreTokens()) {
                MessageOutput.println("Specify file name for class", className);
                return;
            }
            String fileName = t.nextToken();
            File phyl = new File(fileName);
            byte[] bytes = new byte[(int)phyl.length()];
            try {
                InputStream in = new FileInputStream(phyl);
                in.read(bytes);
                in.close();
            } catch (Exception exc) {
                MessageOutput.println("Error reading file",
                             new Object [] {fileName, exc.toString()});
                return;
            }
            Map<ReferenceType, byte[]> map = new HashMap<ReferenceType, byte[]>();
            map.put(refType, bytes);
            try {
                Env.vm().redefineClasses(map);
            } catch (Throwable exc) {
                MessageOutput.println("Error redefining class to file",
                             new Object [] {className,
                                            fileName,
                                            exc});
            }
        }
    }

    void commandPopFrames(StringTokenizer t, boolean reenter) {
        ThreadInfo threadInfo;

        if (t.hasMoreTokens()) {
            String token = t.nextToken();
            threadInfo = doGetThread(token);
            if (threadInfo == null) {
                return;
            }
        } else {
            threadInfo = ThreadInfo.getCurrentThreadInfo();
            if (threadInfo == null) {
                MessageOutput.println("No thread specified.");
                return;
            }
        }

        try {
            StackFrame frame = threadInfo.getCurrentFrame();
            threadInfo.getThread().popFrames(frame);
            threadInfo = ThreadInfo.getCurrentThreadInfo();
            ThreadInfo.setCurrentThreadInfo(threadInfo);
            if (reenter) {
                commandStepi();
            }
        } catch (Throwable exc) {
            MessageOutput.println("Error popping frame", exc.toString());
        }
    }

    void commandExtension(StringTokenizer t) {
        if (!t.hasMoreTokens()) {
            MessageOutput.println("No class specified.");
            return;
        }

        String idClass = t.nextToken();
        ReferenceType cls = Env.getReferenceTypeFromToken(idClass);
        String extension = null;
        if (cls != null) {
            try {
                extension = cls.sourceDebugExtension();
                MessageOutput.println("sourcedebugextension", extension);
            } catch (AbsentInformationException e) {
                MessageOutput.println("No sourcedebugextension specified");
            }
        } else {
            MessageOutput.println("is not a valid id or class name", idClass);
        }
    }

    void commandVersion(String debuggerName,
                        VirtualMachineManager vmm) {
        MessageOutput.println("minus version",
                              new Object [] { debuggerName,
                                              new Integer(vmm.majorInterfaceVersion()),
                                              new Integer(vmm.minorInterfaceVersion()),
                                                  System.getProperty("java.version")});
        if (Env.connection() != null) {
            try {
                MessageOutput.printDirectln(Env.vm().description());// Special case: use printDirectln()
            } catch (VMNotConnectedException e) {
                MessageOutput.println("No VM connected");
            }
        }
    }
}
