1459 lines · 53.1 KB · Java
RawDownload
/* * 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.gui; import java.io.*;import java.util.*; import com.sun.jdi.*;import com.sun.tools.example.debug.bdi.*; public class CommandInterpreter {     boolean echo;     Environment env;     private ContextManager context;    private ExecutionManager runtime;    private ClassManager classManager;    private SourceManager sourceManager;     private OutputSink out; //### Hack!  Should be local in each method used.    private String lastCommand = "help";     public CommandInterpreter(Environment env) {        this(env, true);    }     public CommandInterpreter(Environment env, boolean echo) {        this.env = env;        this.echo = echo;        this.runtime = env.getExecutionManager();        this.context = env.getContextManager();        this.classManager = env.getClassManager();        this.sourceManager = env.getSourceManager();    }     private ThreadReference[] threads = null;     /*     * The numbering of threads is relative to the current set of threads,     * and may be affected by the creation and termination of new threads.     * Commands issued using such thread ids will only give reliable behavior     * relative to what was shown earlier in 'list' commands if the VM is interrupted.     * We need a better scheme.     */     private ThreadReference[] threads() throws NoSessionException {        if (threads == null) {            ThreadIterator ti = new ThreadIterator(getDefaultThreadGroup());            List<ThreadReference> tlist = new ArrayList<ThreadReference>();            while (ti.hasNext()) {                tlist.add(ti.nextThread());            }            threads = tlist.toArray(new ThreadReference[tlist.size()]);        }        return threads;    }     private ThreadReference findThread(String idToken) throws NoSessionException {        String id;        ThreadReference thread = null;        if (idToken.startsWith("t@")) {            id = idToken.substring(2);        } else {            id = idToken;        }        try {            ThreadReference[] threads = threads();            long threadID = Long.parseLong(id, 16);            for (ThreadReference thread2 : threads) {                if (thread2.uniqueID() == threadID) {                    thread = thread2;                    break;                }            }            if (thread == null) {                //env.failure("No thread for id \"" + idToken + "\"");                env.failure("\"" + idToken + "\" is not a valid thread id.");            }        } catch (NumberFormatException e) {            env.error("Thread id \"" + idToken + "\" is ill-formed.");            thread = null;        }        return thread;    }     private ThreadIterator allThreads() throws NoSessionException {        threads = null;        //### Why not use runtime.allThreads().iterator() ?        return new ThreadIterator(runtime.topLevelThreadGroups());    }     private ThreadIterator currentThreadGroupThreads() throws NoSessionException {        threads = null;        return new ThreadIterator(getDefaultThreadGroup());    }     private ThreadGroupIterator allThreadGroups() throws NoSessionException {        threads = null;        return new ThreadGroupIterator(runtime.topLevelThreadGroups());    }     private ThreadGroupReference defaultThreadGroup;     private ThreadGroupReference getDefaultThreadGroup() throws NoSessionException {        if (defaultThreadGroup == null) {            defaultThreadGroup = runtime.systemThreadGroup();        }        return defaultThreadGroup;    }     private void setDefaultThreadGroup(ThreadGroupReference tg) {        defaultThreadGroup = tg;    }     /*     * Command handlers.     */     // Command: classes     private void commandClasses() throws NoSessionException {        OutputSink out = env.getOutputSink();        //out.println("** classes list **");        for (ReferenceType refType : runtime.allClasses()) {            out.println(refType.name());        }        out.show();    }      // Command: methods     private void commandMethods(StringTokenizer t) throws NoSessionException {        if (!t.hasMoreTokens()) {            env.error("No class specified.");            return;        }        String idClass = t.nextToken();        ReferenceType cls = findClass(idClass);        if (cls != null) {            List<Method> methods = cls.allMethods();            OutputSink out = env.getOutputSink();            for (int i = 0; i < methods.size(); i++) {                Method method = methods.get(i);                out.print(method.declaringType().name() + " " +                            method.name() + "(");                Iterator<String> it = method.argumentTypeNames().iterator();                if (it.hasNext()) {                    while (true) {                        out.print(it.next());                        if (!it.hasNext()) {                            break;                        }                        out.print(", ");                    }                }                out.println(")");            }            out.show();        } else {            //### Should validate class name syntax.            env.failure("\"" + idClass + "\" is not a valid id or class name.");        }    }     private ReferenceType findClass(String pattern) throws NoSessionException {        List<ReferenceType> results = runtime.findClassesMatchingPattern(pattern);        if (results.size() > 0) {            //### Should handle multiple results sensibly.            return results.get(0);        }        return null;    }     // Command: threads     private void commandThreads(StringTokenizer t) throws NoSessionException {        if (!t.hasMoreTokens()) {            OutputSink out = env.getOutputSink();            printThreadGroup(out, getDefaultThreadGroup(), 0);            out.show();            return;        }        String name = t.nextToken();        ThreadGroupReference tg = findThreadGroup(name);        if (tg == null) {            env.failure(name + " is not a valid threadgroup name.");        } else {            OutputSink out = env.getOutputSink();            printThreadGroup(out, tg, 0);            out.show();        }    }     private ThreadGroupReference findThreadGroup(String name) throws NoSessionException {        //### Issue: Uniqueness of thread group names is not enforced.        ThreadGroupIterator tgi = allThreadGroups();        while (tgi.hasNext()) {            ThreadGroupReference tg = tgi.nextThreadGroup();            if (tg.name().equals(name)) {                return tg;            }        }        return null;    }     private int printThreadGroup(OutputSink out, ThreadGroupReference tg, int iThread) {        out.println("Group " + tg.name() + ":");        List<ThreadReference> tlist = tg.threads();        int maxId = 0;        int maxName = 0;        for (int i = 0 ; i < tlist.size() ; i++) {            ThreadReference thr = tlist.get(i);            int len = Utils.description(thr).length();            if (len > maxId) {                maxId = len;            }            String name = thr.name();            int iDot = name.lastIndexOf('.');            if (iDot >= 0 && name.length() > iDot) {                name = name.substring(iDot + 1);            }            if (name.length() > maxName) {                maxName = name.length();        }        }        String maxNumString = String.valueOf(iThread + tlist.size());        int maxNumDigits = maxNumString.length();        for (int i = 0 ; i < tlist.size() ; i++) {            ThreadReference thr = tlist.get(i);            char buf[] = new char[80];            for (int j = 0; j < 79; j++) {                buf[j] = ' ';            }            buf[79] = '\0';            StringBuffer sbOut = new StringBuffer();            sbOut.append(buf);             // Right-justify the thread number at start of output string            String numString = String.valueOf(iThread + i + 1);            sbOut.insert(maxNumDigits - numString.length(),                         numString);            sbOut.insert(maxNumDigits, ".");             int iBuf = maxNumDigits + 2;            sbOut.insert(iBuf, Utils.description(thr));            iBuf += maxId + 1;            String name = thr.name();            int iDot = name.lastIndexOf('.');            if (iDot >= 0 && name.length() > iDot) {                name = name.substring(iDot + 1);            }            sbOut.insert(iBuf, name);            iBuf += maxName + 1;            sbOut.insert(iBuf, Utils.getStatus(thr));            sbOut.setLength(79);            out.println(sbOut.toString());        }        for (ThreadGroupReference tg0 : tg.threadGroups()) {            if (!tg.equals(tg0)) {  // TODO ref mgt                iThread += printThreadGroup(out, tg0, iThread + tlist.size());            }        }        return tlist.size();    }     // Command: threadgroups     private void commandThreadGroups() throws NoSessionException {        ThreadGroupIterator it = allThreadGroups();        int cnt = 0;        OutputSink out = env.getOutputSink();        while (it.hasNext()) {            ThreadGroupReference tg = it.nextThreadGroup();            ++cnt;            out.println("" + cnt + ". " + Utils.description(tg) + " " + tg.name());        }        out.show();    }     // Command: thread     private void commandThread(StringTokenizer t) throws NoSessionException {        if (!t.hasMoreTokens()) {            env.error("Thread number not specified.");            return;        }        ThreadReference thread = findThread(t.nextToken());        if (thread != null) {            //### Should notify user.            context.setCurrentThread(thread);        }    }     // Command: threadgroup     private void commandThreadGroup(StringTokenizer t) throws NoSessionException {        if (!t.hasMoreTokens()) {            env.error("Threadgroup name not specified.");            return;        }        String name = t.nextToken();        ThreadGroupReference tg = findThreadGroup(name);        if (tg == null) {            env.failure(name + " is not a valid threadgroup name.");        } else {            //### Should notify user.            setDefaultThreadGroup(tg);        }    }     // Command: run     private void commandRun(StringTokenizer t) throws NoSessionException {        if (doLoad(false, t)) {            env.notice("Running ...");        }    }     // Command: load     private void commandLoad(StringTokenizer t) throws NoSessionException {        if (doLoad(true, t)) {}    }     private boolean doLoad(boolean suspended,                           StringTokenizer t) throws NoSessionException {         String clname;         if (!t.hasMoreTokens()) {            clname = context.getMainClassName();            if (!clname.equals("")) {                // Run from prevously-set class name.                try {                    String vmArgs = context.getVmArguments();                    runtime.run(suspended,                                vmArgs,                                clname,                                context.getProgramArguments());                    return true;                } catch (VMLaunchFailureException e) {                    env.failure("Attempt to launch main class \"" + clname + "\" failed.");                }            } else {                env.failure("No main class specifed and no current default defined.");            }        } else {            clname = t.nextToken();            StringBuffer sbuf = new StringBuffer();            // Allow VM arguments to be specified here?            while (t.hasMoreTokens()) {                String tok = t.nextToken();                sbuf.append(tok);                if (t.hasMoreTokens()) {                    sbuf.append(' ');                }            }            String args = sbuf.toString();            try {                String vmArgs = context.getVmArguments();                runtime.run(suspended, vmArgs, clname, args);                context.setMainClassName(clname);                //context.setVmArguments(vmArgs);                context.setProgramArguments(args);                return true;            } catch (VMLaunchFailureException e) {                env.failure("Attempt to launch main class \"" + clname + "\" failed.");            }        }        return false;    }     // Command: connect     private void commandConnect(StringTokenizer t) {        try {            LaunchTool.queryAndLaunchVM(runtime);        } catch (VMLaunchFailureException e) {            env.failure("Attempt to connect failed.");        }    }     // Command: attach     private void commandAttach(StringTokenizer t) {        String portName;        if (!t.hasMoreTokens()) {            portName = context.getRemotePort();            if (!portName.equals("")) {                try {                    runtime.attach(portName);                } catch (VMLaunchFailureException e) {                    env.failure("Attempt to attach to port \"" + portName + "\" failed.");                }            } else {                env.failure("No port specifed and no current default defined.");            }        } else {            portName = t.nextToken();            try {                runtime.attach(portName);            } catch (VMLaunchFailureException e) {                env.failure("Attempt to attach to port \"" + portName + "\" failed.");            }            context.setRemotePort(portName);        }    }     // Command: detach     private void commandDetach(StringTokenizer t) throws NoSessionException {        runtime.detach();    }     // Command: interrupt     private void commandInterrupt(StringTokenizer t) throws NoSessionException {        runtime.interrupt();    }     // Command: suspend     private void commandSuspend(StringTokenizer t) throws NoSessionException {        if (!t.hasMoreTokens()) {            // Suspend all threads in the current thread group.            //### Issue: help message says default is all threads.            //### Behavior here agrees with 'jdb', however.            ThreadIterator ti = currentThreadGroupThreads();            while (ti.hasNext()) {                // TODO - don't suspend debugger threads                ti.nextThread().suspend();            }            env.notice("All (non-system) threads suspended.");        } else {            while (t.hasMoreTokens()) {                ThreadReference thread = findThread(t.nextToken());                if (thread != null) {                    //thread.suspend();                    runtime.suspendThread(thread);                }            }        }    }     // Command: resume     private void commandResume(StringTokenizer t) throws NoSessionException {         if (!t.hasMoreTokens()) {            // Suspend all threads in the current thread group.            //### Issue: help message says default is all threads.            //### Behavior here agrees with 'jdb', however.            ThreadIterator ti = currentThreadGroupThreads();            while (ti.hasNext()) {                // TODO - don't suspend debugger threads                ti.nextThread().resume();            }            env.notice("All threads resumed.");         } else {             while (t.hasMoreTokens()) {                ThreadReference thread = findThread(t.nextToken());                if (thread != null) {                    //thread.resume();                    runtime.resumeThread(thread);                }             }         }    }     // Command: cont     private void commandCont() throws NoSessionException {        try {            runtime.go();        } catch (VMNotInterruptedException e) {

Lines 1–500 of 1459.