## jde.debugger
Class EventHandler

    java.lang.Object
      |
      +--jde.debugger.EventHandler

public class EventHandler
extends java.lang.Object
implements java.lang.Runnable, Protocol

EventHandler.java

Each debugee VM has an event handler thread on the jdebug side associated with it that receive all the events from the debugee vm. In turn, the event handler thread passes the events on to the jde, indicating if the vm/current thread was suspended.

Created: Tue Jul 6 14:08:44 1999

Since:
  0.1

Field Summary
`(package private) Application` `app` The application for which we're the event handler
`(package private) boolean` `completed` Keeping track of if the thread is over yet or not
`(package private) boolean` `connected` Are we connected to the VM?
`(package private) java.lang.Integer` `my_id` The ID of the application
`(package private) boolean` `resumeApp` Used by the event handlers to indicate if the app should be resumed after the event occured.
`(package private) java.lang.Thread` `thread` My own thread.

Fields inherited from interface jde.debugger.Protocol

`ATTACH_SHMEM, ATTACH_SOCKET, BR, BREAK, CANCEL_TRACE_CLASSES, CANCEL_TRACE_METHODS, CANCEL_TRACE_THREADS, CLEAR, COMMAND_ERROR, COMMAND_RESULT, CONNECTED_TO_VM, DEBUG, 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
`EventHandler(Application app)`

Method Summary
`private LispForm` `breakpointEvent(com.sun.jdi.event.BreakpointEvent event)` A Breakpoint was hit.
`private LispForm` `classPrepareEvent(com.sun.jdi.event.ClassPrepareEvent event)` A class was prepared.
`private LispForm` `classUnloadEvent(com.sun.jdi.event.ClassUnloadEvent event)` A class was unloaded.
`private LispForm` `exceptionEvent(com.sun.jdi.event.ExceptionEvent event)` An exception event occured.
`private java.lang.String` `expressionSuccess(com.sun.jdi.event.Event event)` For events with corresponding specs (eg.
`private com.sun.jdi.ThreadReference` `getCurrentThread(com.sun.jdi.event.EventSet eventSet)` Get the current thread of this event set.
`private com.sun.jdi.ThreadReference` `getEventThread(com.sun.jdi.event.Event event)` Black magic to divine the ThreadReference of the event.
`private void` `handleDisconnectedException()` What we should do if we get disconnected while we're doing something else.
`private LispForm` `handleEvent(com.sun.jdi.event.Event event)` Handles the events that happened
`private LispForm` `methodEntryEvent(com.sun.jdi.event.MethodEntryEvent event)` A method was entered.
`private LispForm` `methodExitEvent(com.sun.jdi.event.MethodExitEvent event)` A method was exit.
`private java.lang.String` `objectIDMatches(com.sun.jdi.event.WatchpointEvent event)` For watchpoints, when the object-id specified during the command should match the object id of the event.
`private LispForm` `otherEvent(com.sun.jdi.event.Event event)` Duh...
`void` `run()` The thread reads an eventset at a time from the application queue, and processes it.
`void` `shutdown()`
`private LispForm` `stepEvent(com.sun.jdi.event.StepEvent event)` A step event occured.
`private LispForm` `threadDeathEvent(com.sun.jdi.event.ThreadDeathEvent event)` A thread died.
`private java.lang.String` `threadMatch(com.sun.jdi.event.Event event)` For events with corresponding specs (eg.
`private LispForm` `threadStartEvent(com.sun.jdi.event.ThreadStartEvent event)` A thread started
`private LispForm` `vmDeathEvent(com.sun.jdi.event.Event event)`
`private LispForm` `vmDisconnectEvent(com.sun.jdi.event.Event event)`
`private LispForm` `vmStartEvent(com.sun.jdi.event.Event event)`
`private LispForm` `watchpointEvent(com.sun.jdi.event.WatchpointEvent event)` A Watchpoint occured.

Methods inherited from class java.lang.Object
`<clinit>, clone, equals, finalize, getClass, hashCode, notify, notifyAll, registerNatives, toString, wait, wait, wait`

Field Detail

### connected

    boolean connected

  Are we connected to the VM?

### app

    final Application app

  The application for which we're the event handler

### my_id

    final java.lang.Integer my_id

  The ID of the application

### thread

    final java.lang.Thread thread

  My own thread. Used when we want to suspend ourselves or some such weird stuff :-)

### completed

    boolean completed

  Keeping track of if the thread is over yet or not

### resumeApp

    boolean resumeApp

  Used by the event handlers to indicate if the app should be resumed after the event occured.

Constructor Detail

### EventHandler

    public EventHandler(Application app)

Method Detail

### shutdown

    public void shutdown()

### run

    public void run()

  The thread reads an eventset at a time from the application queue, and processes it. Essentially, one by one, each event of the eventset is sent to the corresponding "handler", and if at least one of them returns a non-null value, we pass on the eventset (and the values returned by the handlers) to jde. Otherwise, we just resume the vm (regardless of the suspend policy) and wait for the next eventset.

  This is the syntax of the event set:

       (JDE_BUG_EVENTSET suspend-state thread [event-string]+)

  - suspend-state is one of "all", "none" and "thread"
  - thread is either nil, or the thread corresponding to the event set.
  - event-string is the reply from a handler method. See the individual handler methods.
  - The suspend policy is as follows. Some of the commands (see the `protocol`) allow for specifying the suspend policy for the corresponding event. For example, we might specify that the vm resume automatically after a method entry event is reported.

    Firstly, when multiple events are sent (in an event-set), the suspend policy of the entire event set is the one that would suspend the most threads. So, if a breakpoint-hit is sent with the method-entry event, and the breakpoint-hit wants to suspend the vm, while method-entry wants to resume, overall, the event set suspend policy will be to suspend

    Further, some of the events might occur that haven't been explicitly requested, and hence we haven't set their suspend policy anyway. In these cases, and even otherwise, another decision is made at the time of handling of events regarding the suspension/resumption of the vm.

    So, when an event set is received, each event is handled (via it's handler method). Each event ANDs to a variable resumeApp what it thinks should be done to the app: for example, the vmDeathEvent handler wants to resume, so it does `resumeApp &= true;`. In the same way, when a breakpoint is hit (and matches the constraints), it does a `resumeApp &= false:`.

    After all events have been handled, we check the value of resumeApp. If it's true, we resume the vm. If not, we check the suspend-policy of the event set, and take appropriate action.

    This two-tier suspend-policy handling might be simplified to some extent once all commands support setting of a suspend policy, with that and that alone being used to decide on what to do with the vm.

    A problem with that approach is that since we do a second pass on the events when we get the eventset to determine if the events should be sent to the user (eg. a breakpoint-hit is still not interesting if it doesn't occur on the "right" thread), the latter approach might not work well at all.

  Specified by:
    run in interface java.lang.Runnable

### handleEvent

    private LispForm handleEvent(com.sun.jdi.event.Event event)

  Handles the events that happened
  Parameters:
    `event` - One of the events in the event set.
  Returns:
    A LispForm that indicates what should be sent to jde. This should be of the form "(list jde-dbo-EVENT-event [args])". Each of the functions called herein should return a LispForm of the above form.

### otherEvent

    private LispForm otherEvent(com.sun.jdi.event.Event event)

  Duh... we don't recognize this event... or, we choose not to do anything about it

### handleDisconnectedException

    private void handleDisconnectedException()

  What we should do if we get disconnected while we're doing something else.

### getCurrentThread

    private com.sun.jdi.ThreadReference getCurrentThread(com.sun.jdi.event.EventSet eventSet)

  Get the current thread of this event set. It's not necessary for an event set to have a thread associated with it: in those cases just return null.
  Parameters:
    `eventSet` - The event set that occured
  Returns:
    `null` if there is no thread associated, otherwise the ThreadReference of the Thread

### getEventThread

    private com.sun.jdi.ThreadReference getEventThread(com.sun.jdi.event.Event event)

  Black magic to divine the ThreadReference of the event. Question: can we use "Black magic" and "divine" in the same sentence?
  Parameters:
    `event` - An event from the event set: any event will do
  Returns:
    The ThreadReference of the thread

### threadMatch

    private java.lang.String threadMatch(com.sun.jdi.event.Event event)

  For events with corresponding specs (eg. watchpoints), checks to see if the event thread matches the thread constraint in the spec.

  Syntax:

       nil                              # If no such constraint
                                        #   was found in the spec
       "Error mesg"                     # Constraint found, but error
                                        #   during evaluation
       (list "on_thread_id" threadID)   # Constraint found, satisfied
       (list "on_thread_name" "name")

  Comments:
  - The above are strings: so the '"'s above are actually quoted in the string returned.
  - Note that if the Constraint is found but does not satisfy 'null' is returned: this is tested in the handler routines.

### expressionSuccess

    private java.lang.String expressionSuccess(com.sun.jdi.event.Event event)

  For events with corresponding specs (eg. watchpoints), evaluates the expression stored in the spec, if any, to check if the event is interesting to the user or not. The constraint is thus the expression.

  Syntax:

       nil                              # If no such constraint
                                        #   was found in the spec
       "Error mesg"                     # Constraint found, but error
                                        #   during evaluation
       (list "expression")              # Constraint found, satisfied

  Comments:
  - The above are strings: so the '"'s above are actually quoted in the string returned.
  - Note that if the Constraint is found but does not satisfy 'null' is returned: this is tested in the handler routines.

### objectIDMatches

    private java.lang.String objectIDMatches(com.sun.jdi.event.WatchpointEvent event)

  For watchpoints, when the object-id specified during the command should match the object id of the event.

  Syntax:

       nil                              # if no such constraint was in spec
       "Error mesg"                     # Constraint found, error in eval.
       (list object-id)                 # Constraint found, satisfied.

  Comments:
  - The above are strings: so the '"'s above are actually quoted in the string returned.
  - Note that if the Constraint is found but does not satisfy 'null' is returned: this is tested in the handler routines.
  - object-id is the object id that was specified in the command

### breakpointEvent

    private LispForm breakpointEvent(com.sun.jdi.event.BreakpointEvent event)

  A Breakpoint was hit. We check (based on information in the event request; put in when the spec was resolved; that's sent along with the event) if the user wants to know about this event. If so, we return a lispform, else return null.

  Syntax:

       (list breakpoint-hit-function specID location thread-string expression-string)

  Comments:
  - If one of the constraints returns null instead of a string, it means the constraint isn't satisfied. We return null, indicating that the user is not interested in the event of this event :-)

### stepEvent

    private LispForm stepEvent(com.sun.jdi.event.StepEvent event)

  A step event occured.

  Syntax:

       (list step-function location-string)

### watchpointEvent

    private LispForm watchpointEvent(com.sun.jdi.event.WatchpointEvent event)

  A Watchpoint occured. We check (based on information in the event request; put in when the spec was resolved; that's sent along with the event) if the user wants to know about this event. If so, we return a lispform, else return null.

  Syntax:

       (list watchpoint-hit-function specID object-on-which-hit field-and-value location
             object-id-string thread-string expression-string)

  Comments:
  - If one of the constraints returns null instead of a string, it means the constraint isn't satisfied. We return null, indicating that the user is not interested in the event of this event :-)

### exceptionEvent

    private LispForm exceptionEvent(com.sun.jdi.event.ExceptionEvent event)

  An exception event occured. Depending on the command, it could occur for both caught and uncaught exceptions.

  Syntax:

       (list exception-function specID exception thread-string)

  Comments:
  - If one of the constraints returns null instead of a string, it means the constraint isn't satisfied. We return null, indicating that the user is not interested in the event of this event :-)

### methodEntryEvent

    private LispForm methodEntryEvent(com.sun.jdi.event.MethodEntryEvent event)

  A method was entered.

  Syntax:

       (list method-entry-function method)

### methodExitEvent

    private LispForm methodExitEvent(com.sun.jdi.event.MethodExitEvent event)

  A method was exit.

  Syntax:

       (list method-exit-function method)

### threadStartEvent

    private LispForm threadStartEvent(com.sun.jdi.event.ThreadStartEvent event)

  A thread started

  Syntax:

       (list thread-start-function thread)

### threadDeathEvent

    private LispForm threadDeathEvent(com.sun.jdi.event.ThreadDeathEvent event)

  A thread died.

  Syntax:

       (list thread-death-function thread)

### classPrepareEvent

    private LispForm classPrepareEvent(com.sun.jdi.event.ClassPrepareEvent event)

  A class was prepared. The user might not have even requested for this event: we set it up by default in `Application` because we need it for resolution of specs.

  If a user also requests for this event, a particular property is likely not set, and that is how we know that we're supposed to handle the event for the user.

  Syntax:

       (list class-prepare-function reference-type)

### classUnloadEvent

    private LispForm classUnloadEvent(com.sun.jdi.event.ClassUnloadEvent event)

  A class was unloaded.

  Syntax:

       (list class-unload-function reference-type)

### vmStartEvent

    private LispForm vmStartEvent(com.sun.jdi.event.Event event)

### vmDeathEvent

    private LispForm vmDeathEvent(com.sun.jdi.event.Event event)

### vmDisconnectEvent

    private LispForm vmDisconnectEvent(com.sun.jdi.event.Event event)