blob: f4f5cf33ff381ae7c5833bbe2da2982d28c56e9e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.core;
import java.util.EventObject;
import org.eclipse.debug.internal.core.DebugCoreMessages;
/**
* A debug event describes an event in a program being debugged or
* in a running process. Debug models and process implementations
* are required to generate debug events as specified by this class.
* <p>
* The following list defines the events generated for each debug
* model element.
* The <code>getSource()</code> method of a debug event
* returns the element associated with the event.
* Creation events are guaranteed to occur in a top
* down order - that is, parents are created before children.
* Termination events are guaranteed to occur in a bottom up order -
* that is, children before parents. However, termination events are not guaranteed
* for all elements that are created. That is, terminate events can be coalesced - a
* terminate event for a parent signals that all children have been terminated.
* </p>
* <p>
* A debug model may define model specific events by specifying a debug event
* kind of <code>MODEL_SPECIFIC</code>. A model specific event is identified by the
* event source (i.e. by the debug model that generated the event). The detail of
* a model specific event is client defined. Note that model specific events are
* not understood by the debug platform, and are thus ignored.
* </p>
* <p>
* The generic <code>CHANGE</code> event can be fired at any time by any element.
* Generally, a client of a debug model, such as as a UI, can get sufficient
* information to update by listening/responding to the other event kinds. However,
* if a debug model needs to inform clients of a change that is not specified
* by create/terminate/suspend/resume, the <code>CHANGE</code> event may be used.
* For example, generally, the only way a thread or any of its children can change
* state between a suspend and resume operation, is if the thread or owning debug
* target is terminated. However, if a debug model supports some other operation
* that would allow a debug element to change state while suspended, the debug model
* would fire a change event for that element. The valid detail codes for a
* change event are:<ul>
* <li><code>STATE</code> - indicates the state of an element has changed, but its
* children are not affected. A client would use a state change event to update
* a label of the affected element, but would not update any children.</li>
* <li><code>CONTENT</code> - indicates that a debug element's value or contents have
* changed in some way. For example, when the value of a variable is changed
* explicitly, the variable should fire a content change event.</li>
* </ul>
* </p>
* <ul>
* <li><code>IProcess</code>
* <ul>
* <li><code>CREATE</code> - a process has been created and is executing.</li>
* <li><code>TERMINATE</code> - a process has terminated.</li>
* </ul>
* <li><code>IDebugTarget</code>
* <ul>
* <li><code>CREATE</code> - a debug target has been created and is ready
* to begin a debug session.</li>
* <li><code>TERMINATE</code> - a debug target has terminated and the debug
* session has ended.</li>
* <li><code>SUSPEND</code> - a debug target has suspended. Event detail provides
* the reason for the suspension:<ul>
* <li><code>STEP_END</code> - a request to step has completed</li>
* <li><code>BREAKPOINT</code> - a breakpoint has been hit</li>
* <li><code>CLIENT_REQUEST</code> - a client request has caused the target to suspend
* (i.e. an explicit call to <code>suspend()</code>)</li>
* <li><code>UNSPECIFIED</code> - the reason for the suspend is not specified</li>
* </ul>
* </li>
* <li><code>RESUME</code> - a debug target has resumed. Event detail provides
* the reason for the resume:<ul>
* <li><code>STEP_INTO</code> - a target is being resumed because of a request to step into</li>
* <li><code>STEP_OVER</code> - a target is being resumed because of a request to step over</li>
* <li><code>STEP_RETURN</code> - a target is being resumed because of a request to step return</li>
* <li><code>CLIENT_REQUEST</code> - a client request has caused the target to be resumed
* (i.e. an explicit call to <code>resume()</code>)</li>
* <li><code>UNSPECIFIED</code> - The reason for the resume is not specified</li>
* </ul>
* </li>
* </ul>
* </li>
* <li><code>IThread</code>
* <ul>
* <li><code>CREATE</code> - a thread has been created in a debug target.</li>
* <li><code>TERMINATE</code> - a thread has terminated.</li>
* <li><code>SUSPEND</code> - a thread has suspended execution. Event detail provides
* the reason for the suspension:<ul>
* <li><code>STEP_END</code> - a request to step has completed</li>
* <li><code>BREAKPOINT</code> - a breakpoint has been hit</li>
* <li><code>CLIENT_REQUEST</code> - a client request has caused the thread to suspend
* (i.e. an explicit call to <code>suspend()</code>)</li>
* <li><code>EVALUATION</code> - an expression evaluation has ended that may
* have had side effects in the debug target.</li>
* <li><code>EVALUATION_IMPLICIT</code> - an expression evaluation has ended that
* had no side effects in the debug target.</li>
* <li><code>UNSPECIFIED</code> - the reason for the suspend is not specified</li>
* </ul>
* </li>
* <li><code>RESUME</code> - a thread has resumed execution. Event detail provides
* the reason for the resume:<ul>
* <li><code>STEP_INTO</code> - a thread is being resumed because of a request to step into</li>
* <li><code>STEP_OVER</code> - a thread is being resumed because of a request to step over</li>
* <li><code>STEP_RETURN</code> - a thread is being resumed because of a request to step return</li>
* <li><code>CLIENT_REQUEST</code> - a client request has caused the thread to be resumed
* (i.e. an explicit call to <code>resume()</code>)</li>
* <li><code>EVALUATION</code> - an expression evaluation has started that may
* have side effects in the debug target.</li>
* <li><code>EVALUATION_IMPLICIT</code> - an expression evaluation has started that
* will have no side effects in the debug target.</li>
* <li><code>UNSPECIFIED</code> - The reason for the resume is not specified</li>
* </ul>
* </li>
* </ul>
* </li>
* <li><code>IStackFrame</code> - no events are specified for stack frames.
* When a thread is suspended, it has stack frames. When a thread resumes,
* stack frames are unavailable.
* </li>
* <li><code>IVariable</code> - no events are specified for variables.
* When a thread is suspended, stack frames have variables. When a thread resumes,
* variables are unavailable.
* </li>
* <li><code>IValue</code> - no events are specified for values.
* </li>
* </ul>
* <p>
* Clients may instantiate this class. Clients are not intended to subclass this class.
* </p>
*
*/
public final class DebugEvent extends EventObject {
/**
* All objects that can be serialized should have a stable serialVersionUID
*/
private static final long serialVersionUID = 1L;
/**
* Resume event kind.
*/
public static final int RESUME= 0x0001;
/**
* Suspend event kind.
*/
public static final int SUSPEND= 0x0002;
/**
* Create event kind.
*/
public static final int CREATE= 0x0004;
/**
* Terminate event kind.
*/
public static final int TERMINATE= 0x0008;
/**
* Change event kind.
*/
public static final int CHANGE= 0x0010;
/**
* Model specific event kind. The detail codes
* for a model specific event are client defined.
*
* @since 2.1.2
*/
public static final int MODEL_SPECIFIC= 0x0020;
/**
* Step start detail. Indicates a thread was resumed by a step
* into action.
* @since 2.0
*/
public static final int STEP_INTO= 0x0001;
/**
* Step start detail. Indicates a thread was resumed by a step
* over action.
* @since 2.0
*/
public static final int STEP_OVER= 0x0002;
/**
* Step start detail. Indicates a thread was resumed by a step
* return action.
* @since 2.0
*/
public static final int STEP_RETURN= 0x0004;
/**
* Step end detail. Indicates a thread was suspended due
* to the completion of a step action.
*/
public static final int STEP_END= 0x0008;
/**
* Breakpoint detail. Indicates a thread was suspended by
* a breakpoint.
*/
public static final int BREAKPOINT= 0x0010;
/**
* Client request detail. Indicates a thread was suspended due
* to a client request.
*/
public static final int CLIENT_REQUEST= 0x0020;
/**
* Evaluation detail. Indicates that a thread was resumed or
* suspended to perform an expression evaluation.
*
* @since 2.0
*/
public static final int EVALUATION = 0x0040;
/**
* Evaluation detail. Indicates that a thread was resumed or
* suspended to perform an implicit expression evaluation.
* An implicit evaluation is an evaluation that is performed
* as an indirect result of a user action.
* Clients may use this detail event to decide whether or not
* to alert the user that an evaluation is taking place..
*
* @since 2.0
*/
public static final int EVALUATION_IMPLICIT = 0x0080;
/**
* State change detail. Indicates the state of a single
* debug element has changed. Only valid for <code>CHANGE</code>
* events.
*
* @since 2.0
*/
public static final int STATE = 0x0100;
/**
* Content change detail. Indicates the content of a debug element
* (and potentially its children) has changed. Only valid for
* <code>CHANGE</code> events.
*
* @since 2.0
*/
public static final int CONTENT = 0x0200;
/**
* Constant indicating that the kind or detail of a debug
* event is unspecified.
*/
public static final int UNSPECIFIED = 0;
/**
* The kind of event - one of the kind constants defined by
* this class.
*/
private int fKind= UNSPECIFIED;
/**
* The detail of the event - one of the detail constants defined by
* this class.
*/
private int fDetail= UNSPECIFIED;
/**
* Client defined data field.
*
* @since 2.1.2
*/
private Object fData = null;
/**
* Constructs a new debug event of the given kind with a detail code of
* <code>UNSPECIFIED</code>.
*
* @param eventSource the object associated with the event
* @param kind the kind of debug event (one of the
* kind constants defined by this class)
*/
public DebugEvent(Object eventSource, int kind) {
this(eventSource, kind, UNSPECIFIED);
}
/**
* Constructs a new debug event of the given kind with the given detail.
*
* @param eventSource the object associated with the event
* @param kind the kind of debug event (one of the
* kind constants defined by this class)
* @param detail extra information about the event (one of the
* detail constants defined by this class or a client defined detail if this is a model specific event)
*/
public DebugEvent(Object eventSource, int kind, int detail) {
super(eventSource);
if ((kind & (RESUME | SUSPEND | CREATE | TERMINATE | CHANGE | MODEL_SPECIFIC)) == 0)
throw new IllegalArgumentException(DebugCoreMessages.DebugEvent_illegal_kind);
if (kind != MODEL_SPECIFIC && detail != UNSPECIFIED && (detail & (STEP_END | STEP_INTO | STEP_OVER | STEP_RETURN | BREAKPOINT | CLIENT_REQUEST |EVALUATION | EVALUATION_IMPLICIT | STATE | CONTENT)) == 0)
throw new IllegalArgumentException(DebugCoreMessages.DebugEvent_illegal_detail);
fKind= kind;
fDetail= detail;
}
/**
* Returns a constant describing extra detail about the event - either one
* of the detail constants defined by this class, possibly
* <code>UNSPECIFIED</code>, or a client defined detail if this is a model specific event.
*
* @return the detail code
*/
public int getDetail() {
return fDetail;
}
/**
* Returns this event's kind - one of the kind constants defined by this class.
*
* @return the kind code
*/
public int getKind() {
return fKind;
}
/**
* Returns whether this event's detail indicates the
* beginning of a step event. This event's detail is one
* of <code>STEP_INTO</code>, <code>STEP_OVER</code>, or
* <code>STEP_RETURN</code>.
*
* @return whether this event's detail indicates the beginning
* of a step event.
* @since 2.0
*/
public boolean isStepStart() {
return (getDetail() & (STEP_INTO | STEP_OVER | STEP_RETURN)) > 0;
}
/**
* Returns whether this event's detail indicates an
* evaluation. This event's detail is one
* of <code>EVALUATION</code>, or <code>EVALUATION_IMPLICIT</code>.
*
* @return whether this event's detail indicates an evaluation.
* @since 2.0
*/
public boolean isEvaluation() {
return (getDetail() & (EVALUATION | EVALUATION_IMPLICIT)) > 0;
}
/**
* Sets this event's application defined data.
*
* @param data application defined data
* @since 2.1.2
*/
public void setData(Object data) {
fData = data;
}
/**
* Returns this event's application defined data, or <code>null</code> if none
*
* @return application defined data, or <code>null</code> if none
* @since 2.1.2
*/
public Object getData() {
return fData;
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer buf = new StringBuffer("DebugEvent["); //$NON-NLS-1$
if (getSource() != null) {
buf.append(getSource().toString());
} else {
buf.append("null"); //$NON-NLS-1$
}
buf.append(", "); //$NON-NLS-1$
switch (getKind()) {
case CREATE:
buf.append("CREATE"); //$NON-NLS-1$
break;
case TERMINATE:
buf.append("TERMINATE"); //$NON-NLS-1$
break;
case RESUME:
buf.append("RESUME"); //$NON-NLS-1$
break;
case SUSPEND:
buf.append("SUSPEND"); //$NON-NLS-1$
break;
case CHANGE:
buf.append("CHANGE"); //$NON-NLS-1$
break;
case UNSPECIFIED:
buf.append("UNSPECIFIED"); //$NON-NLS-1$
break;
case MODEL_SPECIFIC:
buf.append("MODEL_SPECIFIC"); //$NON-NLS-1$
break;
}
buf.append(", "); //$NON-NLS-1$
switch (getDetail()) {
case BREAKPOINT:
buf.append("BREAKPOINT"); //$NON-NLS-1$
break;
case CLIENT_REQUEST:
buf.append("CLIENT_REQUEST"); //$NON-NLS-1$
break;
case STEP_END:
buf.append("STEP_END"); //$NON-NLS-1$
break;
case STEP_INTO:
buf.append("STEP_INTO"); //$NON-NLS-1$
break;
case STEP_OVER:
buf.append("STEP_OVER"); //$NON-NLS-1$
break;
case STEP_RETURN:
buf.append("STEP_RETURN"); //$NON-NLS-1$
break;
case EVALUATION:
buf.append("EVALUATION"); //$NON-NLS-1$
break;
case EVALUATION_IMPLICIT:
buf.append("EVALUATION_IMPLICIT"); //$NON-NLS-1$
break;
case STATE:
buf.append("STATE"); //$NON-NLS-1$
break;
case CONTENT:
buf.append("CONTENT"); //$NON-NLS-1$
break;
case UNSPECIFIED:
buf.append("UNSPECIFIED"); //$NON-NLS-1$
break;
default:
// model specific
buf.append(getDetail());
break;
}
buf.append("]"); //$NON-NLS-1$
return buf.toString();
}
}