_startTime = System.currentTimeMillis();
}
public void run() {
if (_child != null || !_eventHandlers.isEmpty()) {
CompositeProcess mlSet = ProcessUtil.compose(new ReceiveProcess() {
private static final long serialVersionUID = 1913414844895865116L;
}.setChannel(_self.self).setReceiver(new Termination() {
public void terminate() {
_terminated = true;
// Forward the termination request to the nested activity.
if (_child != null && !_childTermRequested) {
replication(_child.self).terminate();
_childTermRequested = true;
}
// Forward the termination request to our event handlers.
terminateEventHandlers();
instance(ACTIVE.this);
}
}));
// Handle messages from the child if it is still alive
if (_child != null) {
mlSet.or(new ReceiveProcess() {
private static final long serialVersionUID = -6934246487304813033L;
}.setChannel(_child.parent).setReceiver(new ParentScope() {
public void compensate(OScope scope, Synch ret) {
// If this scope does not have available compensations, defer to
// parent scope, otherwise do compensation.
if (_scopeFrame.availableCompensations == null)
_self.parent.compensate(scope, ret);
else {
// TODO: Check if we are doing duplicate compensation
List<CompensationHandler> compensations = findCompensationData(scope);
_scopeFrame.availableCompensations.removeAll(compensations);
instance(new ORDEREDCOMPENSATOR(compensations, ret));
}
instance(ACTIVE.this);
}
public void completed(FaultData flt, Set<CompensationHandler> compensations) {
// Set the fault to the activity's choice, if and only if no previous fault
// has been detected (first fault wins).
if (flt != null && _fault == null)
_fault = flt;
_child = null;
_compensations.addAll(compensations);
if (flt == null)
stopEventHandlers();
else
terminateEventHandlers();
instance(ACTIVE.this);
}
public void cancelled() {
// Implicit scope holds links of the enclosed activity,
// they only get cancelled when we propagate upwards.
if (_oscope.implicitScope)
_self.parent.cancelled();
else
completed(null, CompensationHandler.emptySet());
}
public void failure(String reason, Element data) {
completed(createFault(OFailureHandling.FAILURE_FAULT_NAME, _self.o, null),
CompensationHandler.emptySet());
}
}) );
}
// Similarly, handle messages from the event handler, if one exists
// and if it has not completed.
for (Iterator<EventHandlerInfo> i = _eventHandlers.iterator();i.hasNext();) {
final EventHandlerInfo ehi = i.next();
mlSet.or(new ReceiveProcess() {
private static final long serialVersionUID = -4694721357537858221L;
}.setChannel(ehi.psc).setReceiver(new ParentScope() {
public void compensate(OScope scope, Synch ret) {
// ACTIVE scopes do not compensate, send request up to parent.
_self.parent.compensate(scope, ret);
instance(ACTIVE.this);
}
public void completed(FaultData flt, Set<CompensationHandler> compenstations) {
// Set the fault to the activity's choice, if and only if no previous fault
// has been detected (first fault wins).
if (flt != null && _fault == null)
_fault = flt;
_eventHandlers.remove(ehi);
_compensations.addAll(compenstations);
if (flt != null) {
// Terminate child if we get a fault from the event handler.
if (_child != null && !_childTermRequested) {
replication(_child.self).terminate();
_childTermRequested = true;
}
terminateEventHandlers();
} else
stopEventHandlers();
instance(ACTIVE.this);
}
public void cancelled() { completed(null, CompensationHandler.emptySet()); }
public void failure(String reason, Element data) { completed(null, CompensationHandler.emptySet()); }
}));
}
object(false, mlSet);
} else /* nothing to wait for... */ {
// Any compensation handlers that were available but not activated will be forgotten.
Set<CompensationHandler> unreachableCompensationHandlers = _scopeFrame.availableCompensations;
if (unreachableCompensationHandlers != null)
for (Iterator<CompensationHandler> i = unreachableCompensationHandlers.iterator(); i.hasNext(); ) {
CompensationHandler ch = i.next();
ch.compChannel.forget();
}
_scopeFrame.availableCompensations = null;
// Maintain a set of links needing dead-path elimination.
Set<OLink> linksNeedingDPE = new HashSet<OLink>();
if (_oscope.faultHandler != null)
for (Iterator<OCatch> i = _oscope.faultHandler.catchBlocks.iterator(); i.hasNext(); )
linksNeedingDPE.addAll(i.next().outgoingLinks);
// We're done with the main work, if we were terminated, we will
// need to load the termination handler:
if (_terminated) {
if (__log.isDebugEnabled()) {
__log.debug("Scope: " + _oscope + " was terminated. (fault="+_fault+")");
}
// ??? Should we forward
// If termination handler defined, and the scope has not faulted
if (_oscope.terminationHandler != null && _fault == null) {
// We have to create a scope for the catch block.
BpelRuntimeContext ntive = getBpelRuntimeContext();
ActivityInfo terminationHandlerActivity = new ActivityInfo(genMonotonic(), _oscope.terminationHandler,
newChannel(Termination.class,"TH"), newChannel(ParentScope.class,"TH"));
ScopeFrame terminationHandlerScopeFrame = new ScopeFrame(_oscope.terminationHandler,
ntive.createScopeInstance(_scopeFrame.scopeInstanceId, _oscope.terminationHandler),
_scopeFrame, CompensationHandler.emptySet(), (FaultData)null);
// Create the temination handler scope.
instance(new SCOPE(terminationHandlerActivity,terminationHandlerScopeFrame, SCOPE.this._linkFrame));
object(new ReceiveProcess() {
private static final long serialVersionUID = -6009078124717125270L;
}.setChannel(terminationHandlerActivity.parent).setReceiver(new ParentScope() {
public void compensate(OScope scope, Synch ret) {
// This should never happen.
throw new AssertionError("received compensate request!");
}
public void completed(FaultData fault, Set<CompensationHandler> compensations) {
// The compensations that have been registered here, will never be activated,
// so we'll forget them as soon as possible.
for (CompensationHandler compensation : compensations)
compensation.compChannel.forget();
// When a fault occurs within a termination handler, it is not propagated
_self.parent.completed(null, CompensationHandler.emptySet());
}
public void cancelled() { completed(null, CompensationHandler.emptySet()); }
public void failure(String reason, Element data) { completed(null, CompensationHandler.emptySet()); }
}));
} else {
_self.parent.completed(null,_compensations);
}
} else if (_fault != null) {
sendEvent(new ScopeFaultEvent(_fault.getFaultName(), _fault.getFaultLineNo(),_fault.getExplanation()));
// Find a fault handler for our fault.
OCatch catchBlock = _oscope.faultHandler == null ? null : findCatch(_oscope.faultHandler, _fault.getFaultName(), _fault.getFaultType());
// Collect all the compensation data for completed child scopes.
assert !!_eventHandlers.isEmpty();
assert _child == null;
if (catchBlock == null) {
// If we cannot find a catch block for this fault, then we simply propagate the fault
// to the parent. NOTE: the "default" fault handler as described in the BPEL spec
// must be generated by the compiler.
__log.warn(_self + ": has no fault handler for "
+ _fault.getFaultName() + "; scope will propagate FAULT! , " + _fault.toString());
_self.parent.completed(_fault, _compensations);
} else /* catchBlock != null */ {
__log.warn(_self + ": has a fault handler for "
+ _fault.getFaultName() + ": "+ catchBlock + " , " + _fault.toString());
linksNeedingDPE.removeAll(catchBlock.outgoingLinks);
// We have to create a scope for the catch block.
BpelRuntimeContext ntive = getBpelRuntimeContext();
ActivityInfo faultHandlerActivity = new ActivityInfo(genMonotonic(), catchBlock,
newChannel(Termination.class,"FH"), newChannel(ParentScope.class,"FH"));
ScopeFrame faultHandlerScopeFrame = new ScopeFrame(catchBlock,
ntive.createScopeInstance(_scopeFrame.scopeInstanceId, catchBlock),
_scopeFrame, _compensations, _fault);
if (catchBlock.faultVariable != null) {
try {
VariableInstance vinst = faultHandlerScopeFrame.resolve(catchBlock.faultVariable);
initializeVariable(vinst, _fault.getFaultMessage().cloneNode(true));
// Generating event
VariableModificationEvent se = new VariableModificationEvent(vinst.declaration.name);
se.setNewValue(_fault.getFaultMessage());
if (_oscope.debugInfo != null)
se.setLineNo(_oscope.debugInfo.startLine);
sendEvent(se);
} catch (Exception ex) {
__log.fatal(ex);
throw new InvalidProcessException(ex);
}
}
// Create the fault handler scope.
instance(new SCOPE(faultHandlerActivity,faultHandlerScopeFrame, SCOPE.this._linkFrame));
object(new ReceiveProcess() {
private static final long serialVersionUID = -6009078124717125270L;
}.setChannel(faultHandlerActivity.parent).setReceiver(new ParentScope() {
public void compensate(OScope scope, Synch ret) {
// This should never happen.
throw new AssertionError("received compensate request!");