## jde.debugger
Class JDE

    java.lang.Object
      |
      +--java.lang.Thread
            |
            +--jde.debugger.JDE

public class JDE
extends java.lang.Thread
implements Protocol

JDE.java

This class is the main link between jdebug and jde. It has methods that allow communication between jde and jdebug, as well as a store of all the applications currently active. Commands that have valid app_ids interpret get passed on to the corresponding applications. If not, corresponding errors are sent on the pipe.

Look `here` for the command/response formats, and `here` for information about handling of events, including event set formats

Note that for each command sent by jde, there *has* to be a reply. (either a result or an error) For example, in case we're launching a thread, we should return true, even if the thread might bomb later on.

Handshake Since JDI supports different kinds of connections, (for example, it being possible to "launch" a debugger once an uncaught exception is raised), we should probably have some sort of a handshake mechanism preceding a debugging session, for each new vm.

For example, if the debugee vm is already running, during the handshake we might specify its address. On the other hand, if we want the debugger to *launch* a vm, we can do that during the handshake.

For our purposes, we will only support "launch" in the beginning.

The purpose of the handshake is to establish the debugee_vm_id <-> debugee VM binding. It is guaranteed that no events will be raised from jdebug for a debugee VM for which the handshake is not yet complete.

Created: Wed Jul 7 20:49:16 1999

Since:
  0.1

Field Summary
`(package private) java.util.Map` `applications` All the active applications are kept in a map of `app_id -> app`.
`(package private) java.io.BufferedReader` `in`
`static java.lang.Integer` `my_id` The ID of jdebug.
`(package private) java.io.PrintWriter` `out`
`private java.util.Collection` `pendingCommands` Each command has a command id associated with it, that is used by jde, to match with the corresponding result/error.

Fields inherited from class java.lang.Thread
`contextClassLoader, daemon, eetop, group, inheritedAccessControlContext, MAX_PRIORITY, MIN_PRIORITY, name, NORM_PRIORITY, priority, single_step, stillborn, stopThreadPermission, target, threadInitNumber, threadQ, values`

Fields inherited from interface jde.debugger.Protocol

`ATTACH_SHMEM, ATTACH_SOCKET, BREAK, CANCEL_TRACE_CLASSES, CANCEL_TRACE_METHODS, CANCEL_TRACE_THREADS, CLEAR, COMMAND_ERROR, COMMAND_RESULT, CONNECTED_TO_VM, ERROR, EVALUATE, EVENT_BREAKPOINT_HIT, EVENT_CLASS_PREPARE, EVENT_CLASS_UNLOAD, EVENT_EXCEPTION, EVENT_METHOD_ENTRY, EVENT_METHOD_EXIT, EVENT_OTHER, EVENT_STEP_COMPLETED, EVENT_THREAD_DEATH, EVENT_THREAD_START, EVENT_VM_DEATH, EVENT_VM_DISCONNECT, EVENT_VM_START, EVENT_WATCHPOINT_HIT, EVENTSET, EXIT, FINISH, GET_ARRAY, GET_LOADED_CLASSES, GET_LOCALS, GET_OBJECT, GET_OBJECT_MONITORS, GET_PATH_INFORMATION, GET_STRING, GET_THREAD, GET_THREADS, INTERRUPT, INVALID, JDE_BUG, JDE_INIT_DEBUG_SESSION, KILL_THREAD, LAUNCH, LISTEN_SHMEM, LISTEN_SOCKET, MESSAGE, QUIT, REPORT_IDS_IN_USE, RESUME, RUN, SPEC_RESOLVED, STEP, SUSPEND, TRACE_CLASSES, TRACE_EXCEPTIONS, TRACE_METHODS, TRACE_THREADS, WARNING, WATCH`

Constructor Summary
`JDE()`

Method Summary
`private void` `doAttach(java.lang.String type, java.lang.Integer cmd_id, java.util.List args)` 'attach_socket' and 'attach_shmem' commands.
`private void` `doLaunch(java.lang.Integer cmd_id, java.util.List args)` 'launch' command.
`private void` `doListen(java.lang.String type, java.lang.Integer cmd_id, java.util.List args)` 'listen_socket' and 'listen_shmem' commands.
`private void` `doQuit(java.lang.Integer cmd_id, java.util.List arguments)` 'quit' command.
`private void` `handleAppCommand(java.lang.Integer app_id, java.lang.Integer cmd_id, java.lang.String command, java.util.List arguments)` Commands received from JDE that don't have app_id == -1 get funneled to handleAppCommand.
`private void` `handleGeneralCommand(java.lang.Integer cmd_id, java.lang.String command, java.util.List arguments)` Commands that are not meant for any particular app/vm are funneled to this method.
`private void` `initApplication(java.lang.String category, java.lang.Integer cmd_id, java.util.List args)` This method is actually called by doLaunch, doAttach, and doListen and does all the ugly work.
`void` `removeApplication(java.lang.Integer app_id)` called by `Application.shutdown()` to remove it's own entry from the applications collection here
`void` `run()` JDE is a thread: it reads a line at a time and executes the command therein
`private void` `setSyntax(java.io.StreamTokenizer st)` Sets the syntax of the input stream.
`private void` `shutdown()` Shuts down all the applications prior to exiting
`void` `signal(java.lang.Integer app_id, java.lang.String type, java.lang.Object obj)` Send an arbitrary lisp function across.
`void` `signalCommandError(java.lang.Integer app_id, java.lang.Integer cmd_id, java.lang.Object obj)` reply to a command with an error.
`void` `signalCommandResult(java.lang.Integer app_id, java.lang.Integer cmd_id)` send the result of a command.
`void` `signalCommandResult(java.lang.Integer app_id, java.lang.Integer cmd_id, java.lang.Object obj)` the result of a command.
`private void` `signalReply(java.lang.Integer app_id, java.lang.Integer cmd_id, java.lang.Object obj, java.lang.String type)` Signal a reply: a result or an error
`java.lang.String` `stringRep(java.lang.Object obj)` Returns a string representation of the object.

Methods inherited from class java.lang.Thread

`<clinit>, activeCount, checkAccess, countStackFrames, currentThread, destroy, dumpStack, enumerate, exit, getContextClassLoader, getName, getPriority, getThreadGroup, init, interrupt, interrupt0, interrupted, isAlive, isDaemon, isInterrupted, isInterrupted, join, join, join, nextThreadNum, registerNatives, resume, resume0, setContextClassLoader, setDaemon, setName, setPriority, setPriority0, sleep, sleep, start, stop, stop, stop0, suspend, suspend0, toString, yield`

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

Field Detail

### in

    java.io.BufferedReader in

### out

    java.io.PrintWriter out

### applications

    java.util.Map applications

  All the active applications are kept in a map of `app_id -> app`. The app_id uniquely idenifies the application: it's the duty of the app to nicely remove itself from the map once it's finished

### pendingCommands

    private java.util.Collection pendingCommands

  Each command has a command id associated with it, that is used by jde, to match with the corresponding result/error. jdebug maintains the pending command ids in this collection (as does `Application`, see `Application.pendingCommands`), and removes them once the command processing is over.
  Hence, the command id can actually be reused.

  Note that in case the command is actually meant for one of the apps (ie as ascertained by matching the app_id), the id isn't stored in our Collection, but the applications. This means that, in fact, it is the tuple (app_id, cmd_id) that need be unique (assuming that a "general" command has a app_id of -1

### my_id

    public static final java.lang.Integer my_id

  The ID of jdebug. This is used by jde when issuing commands that are not specific to any particular vm, for instance, 'quit', or the command used to launch new application/vms.
  It is the Integer -1.

Constructor Detail

### JDE

    public JDE()
        throws java.io.IOException

Method Detail

### setSyntax

    private void setSyntax(java.io.StreamTokenizer st)

  Sets the syntax of the input stream. We want the input to be broken into lines, with whitespaces separating tokens

### run

    public void run()

  JDE is a thread: it reads a line at a time and executes the command therein
  Overrides:
    run in class java.lang.Thread

### handleGeneralCommand

    private void handleGeneralCommand(java.lang.Integer cmd_id,
                                      java.lang.String command,
                                      java.util.List arguments)

  Commands that are not meant for any particular app/vm are funneled to this method.
  Parameters:
    `cmd_id` - The ID of the command sent. The app_id was -1
    `command` - The command itself
    `arguments` - And the arguments of the command

### handleAppCommand

    private void handleAppCommand(java.lang.Integer app_id,
                                  java.lang.Integer cmd_id,
                                  java.lang.String command,
                                  java.util.List arguments)

  Commands received from JDE that don't have app_id == -1 get funneled to handleAppCommand. We have to check if the app_id is valid and if it corresponds to a valid app. If not, we send a general error message back to JDE, with my_id=1 and cmd_id=-1 since app_id is not valid anyway
  Parameters:
    `app_id` - The ID of the application for which the command is intended
    `cmd_id` - ID of the command
    `command` - The command
    `arguments` - And a list of the arguments of the command

### initApplication

    private void initApplication(java.lang.String category,
                                 java.lang.Integer cmd_id,
                                 java.util.List args)
                          throws JDEException

  This method is actually called by doLaunch, doAttach, and doListen and does all the ugly work. The 3 above are separated for documentation purposes

  The real reason is that I realised too late that they share the same code :-(

### doLaunch

    private void doLaunch(java.lang.Integer cmd_id,
                          java.util.List args)
                   throws JDEException

  'launch' command. Launches a new application.

  Syntax:

       launch app_id [-use_executable javax] classname [args]

  Comments:
  - this command establishes the existence of a unique "stream" of data between jde and jdebug, indexed by app_id, and referring to a particular vm.
  - other commands might be ... attach app_id [args] ... where args specify the "location" of the running VM. In that case, jdebug might try to connect to the "location", and return an error if unable to do so.

### doAttach

    private void doAttach(java.lang.String type,
                          java.lang.Integer cmd_id,
                          java.util.List args)
                   throws JDEException

  'attach_socket' and 'attach_shmem' commands. Attaches to an already running application through a socket/shared memory.

  Syntax:

       attach_socket app_id -port p_value [-host h_value]
       attach_shmem  app_id name

  Comments:
  - Like launch, except here we're attaching to a debugee vm that has, of course, been launched with the "right" parameters. See the Connection and Invocation details document of JPDA about this.

### doListen

    private void doListen(java.lang.String type,
                          java.lang.Integer cmd_id,
                          java.util.List args)
                   throws JDEException

  'listen_socket' and 'listen_shmem' commands. Listenes for an incoming debuggee connection

  Syntax:

       listen_socket app_id port
       listen_shmem  app_id name

### doQuit

    private void doQuit(java.lang.Integer cmd_id,
                        java.util.List arguments)
                 throws JDEException

  'quit' command.

  Syntax:

       quit

### removeApplication

    public void removeApplication(java.lang.Integer app_id)

  called by `Application.shutdown()` to remove it's own entry from the applications collection here

### shutdown

    private void shutdown()
                   throws JDEException

  Shuts down all the applications prior to exiting

### stringRep

    public java.lang.String stringRep(java.lang.Object obj)

  Returns a string representation of the object. Here is the logic:
  - If the object is null, return an empty string
  - If the object is string, quote it within quotation marks.
  - If the object is a list, recursively call stringRep, appending a space.
  - If it's any other kind of object, return the .toString()

### signal

    public void signal(java.lang.Integer app_id,
                       java.lang.String type,
                       java.lang.Object obj)

  Send an arbitrary lisp function across.
  Parameters:
    `app_id` - The application ID
    `type` - The function name. JDE_BUG gets added to its beginning
    `obj` - An arbitrary object. If a string, it's just printed out, if a list, each of its elements is printed out, with a space after each.

### signalReply

    private void signalReply(java.lang.Integer app_id,
                             java.lang.Integer cmd_id,
                             java.lang.Object obj,
                             java.lang.String type)

  Signal a reply: a result or an error

### signalCommandResult

    public void signalCommandResult(java.lang.Integer app_id,
                                    java.lang.Integer cmd_id)

  send the result of a command. indicates a positive completion of the command. this could of course be provisional: eg. in case of provisional breakpoints

### signalCommandResult

    public void signalCommandResult(java.lang.Integer app_id,
                                    java.lang.Integer cmd_id,
                                    java.lang.Object obj)

  the result of a command. if it's a string, just send it across, else it should be a list. each element is sent across, just doing a toString() -> ie, if you want to send (... 23 "some string" 45), you need to put in the quotes (ie "") yourself: else what will be sent will be (... 23 some string 45), obviously wrong.

### signalCommandError

    public void signalCommandError(java.lang.Integer app_id,
                                   java.lang.Integer cmd_id,
                                   java.lang.Object obj)

  reply to a command with an error.
  Parameters:
    `obj` - Is usually a string explaining what went wrong.