boolean piggybackedAck = !(rmMsgCtx.getMessageType()==Sandesha2Constants.MessageTypes.ACK);
MessageContext msgCtx = rmMsgCtx.getMessageContext();
ConfigurationContext configCtx = msgCtx.getConfigurationContext();
StorageManager storageManager = SandeshaUtil.getSandeshaStorageManager(configCtx, configCtx
.getAxisConfiguration());
SenderBeanMgr retransmitterMgr = storageManager.getSenderBeanMgr();
String outSequenceId = sequenceAck.getIdentifier().getIdentifier();
RMSBean rmsBean = SandeshaUtil.getRMSBeanFromSequenceId(storageManager, outSequenceId);
if (outSequenceId == null || "".equals(outSequenceId)) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.outSeqIDIsNull);
log.debug(message);
throw new SandeshaException(message);
}
if (FaultManager.checkForUnknownSequence(rmMsgCtx, outSequenceId, storageManager, piggybackedAck)) {
if (log.isDebugEnabled())
log.debug("Exit: AcknowledgementProcessor::processAckHeader, Unknown sequence");
return;
}
if (FaultManager.checkForSequenceTerminated(rmMsgCtx, outSequenceId, rmsBean, piggybackedAck)) {
if (log.isDebugEnabled())
log.debug("Exit: AcknowledgementProcessor::processAckHeader, Sequence terminated");
return;
}
// Check that the sender of this Ack holds the correct token
String internalSequenceId = rmsBean.getInternalSequenceID();
if(rmsBean.getSecurityTokenData() != null) {
SecurityManager secManager = SandeshaUtil.getSecurityManager(configCtx);
SecurityToken token = secManager.recoverSecurityToken(rmsBean.getSecurityTokenData());
secManager.checkProofOfPossession(token, soapHeader, msgCtx);
}
if(log.isDebugEnabled()) log.debug("Got Ack for RM Sequence: " + outSequenceId + ", internalSeqId: " + internalSequenceId);
Iterator ackRangeIterator = sequenceAck.getAcknowledgementRanges().iterator();
if (FaultManager.checkForUnknownSequence(rmMsgCtx, outSequenceId, storageManager, piggybackedAck)) {
if (log.isDebugEnabled())
log.debug("Exit: AcknowledgementProcessor::processAckHeader, Unknown sequence ");
return;
}
if (FaultManager.checkForInvalidAcknowledgement(rmMsgCtx, sequenceAck, storageManager, rmsBean, piggybackedAck)) {
if (log.isDebugEnabled())
log.debug("Exit: AcknowledgementProcessor::processAckHeader, Invalid Ack range ");
return;
}
String replyToAddress = rmsBean.getReplyToEPR();
EndpointReference replyTo = new EndpointReference (replyToAddress);
boolean anonReplyTo = replyTo.hasAnonymousAddress();
String rmVersion = rmMsgCtx.getRMSpecVersion();
// Compare the clientCompletedMessages with the range we just got, to work out if there
// is any new information in this ack message
RangeString completedMessages = rmsBean.getClientCompletedMessages();
long numberOfNewMessagesAcked = 0;
while(ackRangeIterator.hasNext()) {
AcknowledgementRange ackRange = (AcknowledgementRange) ackRangeIterator.next();
long lower = ackRange.getLowerValue();
long upper = ackRange.getUpperValue();
Range ackedRange = new Range(lower, upper);
// Quick check to see if the whole range is already covered
if(!completedMessages.isRangeCompleted(ackedRange)) {
//we now know that this range is complete so we update it. This should aggregate the
//ranges together and tell us which numbers are newly acked
Range[] newRanges = completedMessages.addRange(ackedRange).getRanges();
// We now take each newly acked message in turn and see if we need to update a sender bean
for (int rangeIndex=0; rangeIndex < newRanges.length; rangeIndex++) {
//now work on each newly acked message in this range
for(long messageNo = newRanges[rangeIndex].lowerValue; messageNo<=newRanges[rangeIndex].upperValue; messageNo++){
numberOfNewMessagesAcked++;
SenderBean matcher = new SenderBean();
matcher.setSequenceID(outSequenceId);
matcher.setMessageNumber(messageNo);
List retransmitterBeans = retransmitterMgr.find(matcher);
if (! retransmitterBeans.isEmpty()){
Iterator retransmitterBeansItr = retransmitterBeans.iterator();
while (retransmitterBeansItr.hasNext()) {
SenderBean retransmitterBean = (SenderBean) retransmitterBeansItr.next();
if (retransmitterBean != null) {
// Check we haven't got an Ack for a message that hasn't been sent yet !
if (retransmitterBean.getSentCount() == 0) {
FaultManager.makeInvalidAcknowledgementFault(rmMsgCtx, sequenceAck, ackRange,
storageManager, piggybackedAck);
if (log.isDebugEnabled())
log.debug("Exit: AcknowledgementProcessor::processAckHeader, Invalid Ack");
return;
}
String storageKey = retransmitterBean.getMessageContextRefKey();
boolean syncResponseNeeded = false;
if (Sandesha2Constants.SPEC_VERSIONS.v1_0.equals(rmVersion) && anonReplyTo) {
MessageContext applicationMessage = storageManager.retrieveMessageContext(storageKey, configCtx);
AxisOperation operation = applicationMessage.getAxisOperation();
if(operation!= null) {
int mep = operation.getAxisSpecificMEPConstant();
syncResponseNeeded = (mep == WSDLConstants.MEP_CONSTANT_OUT_IN);
}
}
if (!syncResponseNeeded) {
// removing the application message from the storage.
retransmitterMgr.delete(retransmitterBean.getMessageID());
storageManager.removeMessageContext(storageKey);
}
}
}
}//end of if (!retransmitterBeans.isEmpty()){
}//end for
}//end for
} //end while
}
// updating the last activated time of the sequence.
rmsBean.setLastActivatedTime(System.currentTimeMillis());
//adding a MakeConnection for the response sequence if needed.
if (rmsBean.getOfferedSequence() != null) {
RMDBeanMgr rMDBeanMgr = storageManager.getRMDBeanMgr();
RMDBean rMDBean = rMDBeanMgr.retrieve(outSequenceId);
if (rMDBean!=null && rMDBean.isPollingMode()) {
PollingManager manager = storageManager.getPollingManager();
if(manager != null) manager.schedulePollingRequest(rMDBean.getSequenceID(), false);
}
}
// We overwrite the previous client completed message ranges with the
// latest view, but only if it is an update i.e. contained a new
// ack range (which is because we do not previous acks arriving late
// to break us)
if (numberOfNewMessagesAcked>0) {
rmsBean.setClientCompletedMessages(completedMessages);
}
// Update the RMSBean
storageManager.getRMSBeanMgr().update(rmsBean);
// Try and terminate the sequence
if (!rmsBean.isAvoidAutoTermination())
TerminateManager.checkAndTerminate(rmMsgCtx.getConfigurationContext(), storageManager, rmsBean);