/*
 * Copyright (c) 1998, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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<String> args = method.argumentTypeNames();
        int lastParam = args.size() - 1;
        // output param types except for the last
        for (int ii = 0; ii < lastParam; ii++) {
            buf.append(args.get(ii));
            buf.append(", ");
        }
        if (lastParam >= 0) {
            // output the last param
            String lastStr = 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) {
        Collection<Connector> ccs = vmm.allConnectors();
        if (ccs.isEmpty()) {
            MessageOutput.println("Connectors available");
        }
        for (Connector cc : ccs) {
            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());

            for (Connector.Argument aa : cc.defaultArguments().values()) {
                    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() {
        StringBuffer classList = new StringBuffer();
        for (ReferenceType refType : Env.vm().allClasses()) {
            classList.append(refType.name());
            classList.append("\n");
        }
        MessageOutput.print("** classes list **", classList.toString());
    }

    void commandClass(StringTokenizer t) {
        List<ReferenceType> 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<InterfaceType> interfaces =
                showAll ? clazz.allInterfaces() : clazz.interfaces();
            for (InterfaceType interfaze : interfaces) {
                MessageOutput.println("implements:", interfaze.name());
            }

            for (ClassType sub : clazz.subclasses()) {
                MessageOutput.println("subclass:", sub.name());
            }
            for (ReferenceType nest : clazz.nestedTypes()) {
                MessageOutput.println("nested:", nest.name());
            }
        } else if (type instanceof InterfaceType) {
            InterfaceType interfaze = (InterfaceType)type;
            MessageOutput.println("Interface:", interfaze.name());
            for (InterfaceType superinterface : interfaze.superinterfaces()) {
                MessageOutput.println("extends:", superinterface.name());
            }
            for (InterfaceType sub : interfaze.subinterfaces()) {
                MessageOutput.println("subinterface:", sub.name());
            }
            for (ClassType implementor : interfaze.implementors()) {
                MessageOutput.println("implementor:", implementor.name());
            }
            for (ReferenceType nest : interfaze.nestedTypes()) {
                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) {
            StringBuffer methodsList = new StringBuffer();
            for (Method method : cls.allMethods()) {
                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<Field> fields = cls.allFields();
            List<Field> visible = cls.visibleFields();
            StringBuffer fieldsList = new StringBuffer();
            for (Field field : fields) {
                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 = 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 = 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());
        for (ThreadGroupReference child : group.threadGroups()) {
            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();
         for (StepRequest request : mgr.stepRequests()) {
             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
        for (EventRequestSpec spec : Env.specList.eventRequestSpecs()) {
            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<StackFrame> 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 = 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.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")) {
                for (ThreadInfo threadInfo : ThreadInfo.threads()) {
                    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
        for (EventRequestSpec spec : Env.specList.eventRequestSpecs()) {
            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) {
        BreakpointSpec 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 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<WatchpointSpec> parseWatchpointSpec(StringTokenizer t) {
        List<WatchpointSpec> list = new ArrayList<WatchpointSpec>();
        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 {
            WatchpointSpec 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;
        }

        for (WatchpointSpec spec : parseWatchpointSpec(t)) {
            resolveNow(spec);
        }
    }

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

        for (WatchpointSpec spec : parseWatchpointSpec(t)) {
            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<Method> 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 = 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<Location> lines = null;
                    if (idMethod == null) {
                        lines = refType.allLineLocations();
                    } else {
                        for (Method method : refType.allMethods()) {
                            if (method.name().equals(idMethod)) {
                                lines = method.allLineLocations();
                            }
                        }
                        if (lines == null) {
                            MessageOutput.println("is not a valid method name", idMethod);
                        }
                    }
                    for (Location line : lines) {
                        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<LocalVariable, Value> values = frame.getValues(vars);

            MessageOutput.println("Method arguments:");
            for (LocalVariable var : vars) {
                if (var.isArgument()) {
                    Value val = values.get(var);
                    printVar(var, val);
                }
            }
            MessageOutput.println("Local variables:");
            for (LocalVariable var : vars) {
                if (!var.isArgument()) {
                    Value val = 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 (Field field : refType.fields()) {
            StringBuffer o = new StringBuffer();
            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) {
            for (InterfaceType sup : ((InterfaceType)refType).superinterfaces()) {
                dump(obj, sup, refTypeBase);
            }
        } else {
            /* else refType is an instanceof ArrayType */
            if (obj instanceof ArrayReference) {
                for (Iterator<Value> 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<ThreadReference> waiters = object.waitingThreads();
                if (waiters.size() == 0) {
                    MessageOutput.println("No waiters");
                } else {
                    for (ThreadReference waiter : waiters) {
                        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<ObjectReference> owned = thread.ownedMonitors();
            if (owned.size() == 0) {
                MessageOutput.println("No monitors owned");
            } else {
                for (ObjectReference monitor : owned) {
                    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")) {
            for (ThreadInfo threadInfo : ThreadInfo.threads()) {
                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<String> keys = Env.getSaveKeys();
            if (keys.isEmpty()) {
                MessageOutput.println("No saved values");
                return;
            }
            for (String key : keys) {
                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<ReferenceType> 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 = classes.get(0);
        if (!(rt instanceof ClassType)) {
            MessageOutput.println("not a class", className);
            return;
        }

        byte[] bytecodes = null;
        for (Method method : rt.methodsByName(methodName)) {
            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<ReferenceType> 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 = 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");
            }
        }
    }
}
