* @param e Event
* @throws EngineTraceException To abort the running process
*/
public void observeEvent(ObserverEvent e)
{
EngineTraceEvent event = (EngineTraceEvent) e;
//
// First, check if there is a breakpoint defined for the position
// associated with this event
//
ModelQualifier pos1 = null;
ModelQualifier pos2 = null;
String eventType = event.getEventType();
if (eventType.equals(EngineTraceEvent.NODE_ENTRY))
{
pos1 = event.getNode().getQualifier();
pos2 = event.getNodeSocket().getQualifier();
}
else if (eventType.equals(EngineTraceEvent.NODE_EXIT))
{
pos1 = event.getNodeSocket().getQualifier();
}
else if (eventType.equals(EngineTraceEvent.CONTROL_FLOW))
{
// Nothing to do here
}
else if (eventType.equals(EngineTraceEvent.DATA_FLOW))
{
if (event.getTargetParam() instanceof NodeParam)
pos1 = event.getTargetParam().getQualifier();
else if (event.getSourceParam() instanceof NodeParam)
pos1 = event.getSourceParam().getQualifier();
}
else if (eventType.equals(EngineTraceEvent.PROCESS_EXCEPTION))
{
// Nothing to do here
}
DebuggerClient breakClient = null;
// Check if this token context already runs under control of a debugger client
TokenContext context = event.getTokenContext();
String clientId = context.getDebuggerId();
if (clientId != null)
{
DebuggerClient client = getClient(clientId);
if (client == null)
{
// There is a client id referenced in the token context, but no such client
if (waitForDebugger)
{
client = waitForDebuggerClient(clientId);
}
else
{
// Remove the id from the context and continue the process
context.setDebuggerId(null);
return;
}
}
int mode = client.getDebuggerMode();
if (eventType.equals(EngineTraceEvent.PROCESS_EXCEPTION))
{
// An exeception occurred during process execution
if ((mode & MODE_BREAK_ON_EXCEPTION) != 0)
{
breakClient = client;
}
}
if (breakClient == null)
{
if (stopAtFirstEvent)
{
stopAtFirstEvent = false;
breakClient = client;
}
if (stopAtAnyEvent)
{
breakClient = client;
}
// First, check if we ran onto a breakpoint set by this client
if (pos1 != null)
{
Breakpoint bp = client.getActiveBreakpoint(pos1);
if (bp != null)
{
breakClient = client;
if ((bp.getState() & Breakpoint.STATE_TEMPORARY) != 0)
{
// Clear temporary breakpoint
client.clearBreakpoint(pos1);
}
}
}
if (breakClient == null && pos2 != null)
{
Breakpoint bp = client.getActiveBreakpoint(pos2);
if (bp != null)
{
breakClient = client;
if ((bp.getState() & Breakpoint.STATE_TEMPORARY) != 0)
{
// Clear temporary breakpoint
client.clearBreakpoint(pos2);
}
}
}
// Check if we enter a top-level process
if (breakClient == null && (mode & MODE_BREAK_ON_TOP_LEVEL) != 0 && eventType.equals(EngineTraceEvent.NODE_EXIT)
&& event.getNode() instanceof InitialNode && context.getCallStack().getCallDepth() == 0)
{
// Yes, we are at the exit socket of an initial node of a top level process
// Check if there is a 'break on top level' client
breakClient = client;
}
// Check if we accepted a workflow task
if (breakClient == null && (mode & MODE_BREAK_ON_WORKFLOW) != 0 && eventType.equals(EngineTraceEvent.NODE_EXIT)
&& event.getNode() instanceof WorkflowNode && event.getNodeSocket().isDefaultSocket())
{
// Yes, we are leaving a worklfow node at the default socket
// (meaning we accepted a workflow task)
breakClient = client;
}
if (breakClient == null)
{
// We have no breakpoint set by this client, now check if there is
// a command pending we need to follow
// Check if the current command applies to the current position
int command = client.getNextCommand();
if (command == CMD_STEP_NEXT)
{
// The step next command halts for any events
breakClient = client;
}
else if (command == CMD_STEP_INTO)
{
// The step into command
if (eventType.equals(EngineTraceEvent.NODE_ENTRY))
breakClient = client;
}
else if (command == CMD_STEP_OVER)
{
// The step over command
// Check if the current call level <= call level at time when the command was issued
if (eventType.equals(EngineTraceEvent.NODE_ENTRY))
{
int depth = context.getCallStack().getCallDepth();
int commandDepth = client.getCallDepth();
if (depth <= commandDepth)
{
breakClient = client;
}
}
}
else if (command == CMD_STEP_OUT)
{
// The step out command
// Check if the current call level < call level at time when the command was issued
if (eventType.equals(EngineTraceEvent.NODE_ENTRY))
{
int depth = context.getCallStack().getCallDepth();
int commandDepth = client.getCallDepth();
if (depth <= commandDepth)
{
breakClient = client;
}
}
}
else if (command == CMD_STEP_UNTIL)
{
// The step until command halts at the position specified with the command
String stepUntilPosition = client.getStepUntilPosition();
if (pos1 != null && pos1.equals(stepUntilPosition) || pos2 != null && pos2.equals(stepUntilPosition))
{
breakClient = client;
}
}
if (command != CMD_STEP_UNTIL)
{
// Check if we should skip System model processes
if (breakClient != null && (mode & MODE_SKIP_SYSTEM_MODEL) != 0)
{
if (pos1 != null && CoreConstants.SYSTEM_MODEL_NAME.equals(pos1.getModel()))
{
// Process belongs to the System model, skip
breakClient = null;
}
}
}
}
}
}
else
{
// No client is associated with this context
// check if any client has set a global breakpoint for the current position
if (pos1 != null)
{
breakClient = determineGlobalBreakpointClient(pos1);
}
if (breakClient == null && pos2 != null)
{
breakClient = determineGlobalBreakpointClient(pos2);
}
}
if (breakClient != null)
{
// There is a debugger client associated with this event, stop the process
// Determine current position
ModelQualifier pos = null;
if (event.getTargetParam() instanceof NodeParam)
pos = event.getTargetParam().getQualifier();
else if (event.getSourceParam() instanceof NodeParam)
pos = event.getSourceParam().getQualifier();
else if (event.getNodeSocket() != null)
pos = event.getNodeSocket().getQualifier();
else if (event.getNode() != null)
pos = event.getNode().getQualifier();
if (pos == null)
pos = event.getProcess().getQualifier();
// Save the halt status information in the client object
DebuggerClient.HaltInfo haltInfo = breakClient.addHaltInfo(pos, event, context);
// When stopping a process, reset the step until target