// TODO: Note that this RMMessageContext is not really any use - but we need to create it
// so that it can be passed to the fault handling chain. It's really no more than a
// container for the correct addressing and RM spec levels, so we'd be better off passing
// them in directly. Unfortunately that change ripples through the codebase...
RMMsgContext rmMsgCtx = MsgInitializer.initializeMessage(msgCtx);
ConfigurationContext configCtx = msgCtx.getConfigurationContext();
StorageManager storageManager = SandeshaUtil.getSandeshaStorageManager(configCtx, configCtx
.getAxisConfiguration());
SenderBeanMgr senderBeanMgr = storageManager.getSenderBeanMgr();
SequencePropertyBeanMgr seqPropMgr = storageManager.getSequencePropertyBeanMgr();
String outSequenceId = sequenceAck.getIdentifier().getIdentifier();
if (outSequenceId == null || "".equals(outSequenceId)) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.outSeqIDIsNull);
log.debug(message);
throw new SandeshaException(message);
}
String internalSequenceId = SandeshaUtil.getSequenceProperty(outSequenceId,
Sandesha2Constants.SequenceProperties.INTERNAL_SEQUENCE_ID, storageManager);
//here we cannot get the property key using the usual SandeshaUtil.getSequencePropertyKey function,
//because this can be a applicationMessage, which piggybacks the acknowledgement.
String sequencePropertyKey = internalSequenceId;
// Check that the sender of this Ack holds the correct token
SequencePropertyBean tokenBean = seqPropMgr.retrieve(outSequenceId, Sandesha2Constants.SequenceProperties.SECURITY_TOKEN);
if(tokenBean != null) {
SecurityManager secManager = SandeshaUtil.getSecurityManager(configCtx);
SecurityToken token = secManager.recoverSecurityToken(tokenBean.getValue());
secManager.checkProofOfPossession(token, soapHeader, msgCtx);
}
Iterator ackRangeIterator = sequenceAck.getAcknowledgementRanges().iterator();
Iterator nackIterator = sequenceAck.getNackList().iterator();
FaultManager faultManager = new FaultManager();
SandeshaException fault = faultManager
.checkForUnknownSequence(rmMsgCtx, outSequenceId, storageManager);
if(fault == null) {
fault = faultManager.checkForInvalidAcknowledgement(rmMsgCtx, storageManager);
}
if (fault != null) {
throw fault;
}
// updating the last activated time of the sequence.
SequenceManager.updateLastActivatedTime(sequencePropertyKey, storageManager);
SenderBean input = new SenderBean();
input.setSend(true);
input.setReSend(true);
Collection retransmitterEntriesOfSequence = senderBeanMgr.find(input);
ArrayList ackedMessagesList = new ArrayList();
while (ackRangeIterator.hasNext()) {
AcknowledgementRange ackRange = (AcknowledgementRange) ackRangeIterator.next();
long lower = ackRange.getLowerValue();
long upper = ackRange.getUpperValue();
for (long messageNo = lower; messageNo <= upper; messageNo++) {
SenderBean retransmitterBean = getSenderEntry(retransmitterEntriesOfSequence, messageNo);
if (retransmitterBean != null) {
senderBeanMgr.delete(retransmitterBean.getMessageID());
// removing the application message from the storage.
String storageKey = retransmitterBean.getMessageContextRefKey();
storageManager.removeMessageContext(storageKey);
}
ackedMessagesList.add(new Long(messageNo));
}
}
while (nackIterator.hasNext()) {
Nack nack = (Nack) nackIterator.next();
long msgNo = nack.getNackNumber();
// TODO - Process Nack
}
//adding a MakeConnection for the response sequence if needed.
String offeredSequenceId = SandeshaUtil.getSequenceProperty(sequencePropertyKey,
Sandesha2Constants.SequenceProperties.OFFERED_SEQUENCE, storageManager);
if (offeredSequenceId!=null) {
RMDBeanMgr rmdBeanMgr = storageManager.getRMDBeanMgr();
RMDBean rmdBean = rmdBeanMgr.retrieve(outSequenceId);
if (rmdBean!=null && rmdBean.isPollingMode())
SandeshaUtil.shedulePollingRequest(offeredSequenceId, configCtx);
}
// setting acked message date.
// TODO add details specific to each message.
long noOfMsgsAcked = getNoOfMessagesAcked(sequenceAck.getAcknowledgementRanges().iterator());
SequencePropertyBean noOfMsgsAckedBean = seqPropMgr.retrieve(sequencePropertyKey,
Sandesha2Constants.SequenceProperties.NO_OF_OUTGOING_MSGS_ACKED);
boolean added = false;
if (noOfMsgsAckedBean == null) {
added = true;
noOfMsgsAckedBean = new SequencePropertyBean();
noOfMsgsAckedBean.setSequencePropertyKey(sequencePropertyKey);
noOfMsgsAckedBean.setName(Sandesha2Constants.SequenceProperties.NO_OF_OUTGOING_MSGS_ACKED);
}
noOfMsgsAckedBean.setValue(Long.toString(noOfMsgsAcked));
if (added)
seqPropMgr.insert(noOfMsgsAckedBean);
else
seqPropMgr.update(noOfMsgsAckedBean);
// setting the completed_messages list. This gives all the messages of
// the sequence that were acked.
SequencePropertyBean allCompletedMsgsBean = seqPropMgr.retrieve(sequencePropertyKey,
Sandesha2Constants.SequenceProperties.CLIENT_COMPLETED_MESSAGES);
if (allCompletedMsgsBean == null) {
allCompletedMsgsBean = new SequencePropertyBean();
allCompletedMsgsBean.setSequencePropertyKey(sequencePropertyKey);
allCompletedMsgsBean.setName(Sandesha2Constants.SequenceProperties.CLIENT_COMPLETED_MESSAGES);
seqPropMgr.insert(allCompletedMsgsBean);
}
String str = ackedMessagesList.toString();
allCompletedMsgsBean.setValue(str);
seqPropMgr.update(allCompletedMsgsBean);
String lastOutMsgNoStr = SandeshaUtil.getSequenceProperty(sequencePropertyKey,
Sandesha2Constants.SequenceProperties.LAST_OUT_MESSAGE_NO, storageManager);
if (lastOutMsgNoStr != null) {
long highestOutMsgNo = 0;
if (lastOutMsgNoStr != null) {
highestOutMsgNo = Long.parseLong(lastOutMsgNoStr);
}
if (highestOutMsgNo > 0) {
boolean complete = AcknowledgementManager.verifySequenceCompletion(sequenceAck
.getAcknowledgementRanges().iterator(), highestOutMsgNo);
if (complete) {
//using create sequence message as the reference message.
// CreateSeqBeanMgr createSeqBeanMgr = storageManager.getCreateSeqBeanMgr();
// CreateSeqBean createSeqBean = createSeqBeanMgr.retrieve(msgId);
//
TerminateManager.addTerminateSequenceMessage(rmMsgCtx, outSequenceId, sequencePropertyKey,
storageManager);
}
}
}
String action = msgCtx.getOptions().getAction();
if (action!=null && action.equals(SpecSpecificConstants.getAckRequestAction(rmMsgCtx.getRMSpecVersion()))) {
returnValue = true;
rmMsgCtx.pause();
}
if (log.isDebugEnabled())
log.debug("Exit: AcknowledgementProcessor::processAckHeader " + returnValue);
return returnValue;