String sequenceId = sequence.getIdentifier().getIdentifier();
long msgNo = sequence.getMessageNumber().getMessageNumber();
boolean lastMessage = sequence.getLastMessage() != null;
// Check that both the Sequence header and message body have been secured properly
RMDBeanMgr mgr = storageManager.getRMDBeanMgr();
RMDBean bean = mgr.retrieve(sequenceId);
if(bean != null && bean.getSecurityTokenData() != null) {
SecurityManager secManager = SandeshaUtil.getSecurityManager(msgCtx.getConfigurationContext());
QName seqName = new QName(rmMsgCtx.getRMNamespaceValue(), Sandesha2Constants.WSRM_COMMON.SEQUENCE);
SOAPEnvelope envelope = msgCtx.getEnvelope();
OMElement body = envelope.getBody();
OMElement seqHeader = envelope.getHeader().getFirstChildWithName(seqName);
SecurityToken token = secManager.recoverSecurityToken(bean.getSecurityTokenData());
secManager.checkProofOfPossession(token, seqHeader, msgCtx);
secManager.checkProofOfPossession(token, body, msgCtx);
}
// Store the inbound sequence id, number and lastMessage onto the operation context
OperationContext opCtx = msgCtx.getOperationContext();
if(opCtx != null) {
opCtx.setProperty(Sandesha2Constants.MessageContextProperties.INBOUND_SEQUENCE_ID, sequenceId);
opCtx.setProperty(Sandesha2Constants.MessageContextProperties.INBOUND_MESSAGE_NUMBER, new Long(msgNo));
if(lastMessage) opCtx.setProperty(Sandesha2Constants.MessageContextProperties.INBOUND_LAST_MESSAGE, Boolean.TRUE);
}
// setting acked msg no range
ConfigurationContext configCtx = rmMsgCtx.getMessageContext().getConfigurationContext();
if (configCtx == null) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.configContextNotSet);
log.debug(message);
throw new SandeshaException(message);
}
if (FaultManager.checkForUnknownSequence(rmMsgCtx, sequenceId, storageManager, false)) {
if (log.isDebugEnabled())
log.debug("Exit: SequenceProcessor::processReliableMessage, Unknown sequence");
return InvocationResponse.ABORT;
}
// throwing a fault if the sequence is terminated
if (FaultManager.checkForSequenceTerminated(rmMsgCtx, sequenceId, bean, false)) {
if (log.isDebugEnabled())
log.debug("Exit: SequenceProcessor::processReliableMessage, Sequence terminated");
return InvocationResponse.ABORT;
}
// throwing a fault if the sequence is closed.
if (FaultManager.checkForSequenceClosed(rmMsgCtx, sequenceId, bean, false)) {
if (log.isDebugEnabled())
log.debug("Exit: SequenceProcessor::processReliableMessage, Sequence closed");
return InvocationResponse.ABORT;
}
FaultManager.checkForLastMsgNumberExceeded(rmMsgCtx, storageManager);
if (FaultManager.checkForMessageRolledOver(rmMsgCtx, sequenceId, msgNo)) {
if (log.isDebugEnabled())
log.debug("Exit: SequenceProcessor::processReliableMessage, Message rolled over " + msgNo);
return InvocationResponse.ABORT;
}
// Pause the messages bean if not the right message to invoke.
// updating the last activated time of the sequence.
bean.setLastActivatedTime(System.currentTimeMillis());
if (lastMessage) {
//setting this as the LastMessage number
bean.setLastInMessageId(msgCtx.getMessageID());
}
EndpointReference replyTo = rmMsgCtx.getReplyTo();
String key = SandeshaUtil.getUUID(); // key to store the message.
// updating the Highest_In_Msg_No property which gives the highest
// message number retrieved from this sequence.
long highestInMsgNo = bean.getHighestInMessageNumber();
if (msgNo > highestInMsgNo) {
// If WS-Addressing is turned off there may not be a message id written into the SOAP
// headers, but we can still fake one up to help us match up requests and replies within
// this end of the connection.
String messageId = msgCtx.getMessageID();
if(messageId == null) {
messageId = SandeshaUtil.getUUID();
msgCtx.setMessageID(messageId);
}
bean.setHighestInMessageId(messageId);
bean.setHighestInMessageNumber(msgNo);
}
String specVersion = rmMsgCtx.getRMSpecVersion();
if (rmMsgCtx.getMessageContext().getAxisOperation().getName().getLocalPart().equals(Sandesha2Constants.RM_DUPLICATE_OPERATION.getLocalPart())
&& (Sandesha2Constants.QOS.InvocationType.DEFAULT_INVOCATION_TYPE == Sandesha2Constants.QOS.InvocationType.EXACTLY_ONCE)) {
// this is a duplicate message and the invocation type is EXACTLY_ONCE. We try to return
// ack messages at this point, as if someone is sending duplicates then they may have
// missed earlier acks. We also have special processing for sync 2-way with RM 1.0
if((replyTo==null || replyTo.hasAnonymousAddress()) &&
(specVersion!=null && specVersion.equals(Sandesha2Constants.SPEC_VERSIONS.v1_0))) {
SenderBeanMgr senderBeanMgr = storageManager.getSenderBeanMgr();
SenderBean findSenderBean = new SenderBean ();
if (rmMsgCtx.getMessageType()==Sandesha2Constants.MessageTypes.LAST_MESSAGE)
findSenderBean.setMessageType(Sandesha2Constants.MessageTypes.LAST_MESSAGE);
else
findSenderBean.setMessageType(Sandesha2Constants.MessageTypes.APPLICATION);
findSenderBean.setInboundSequenceId(sequence.getIdentifier().getIdentifier());
findSenderBean.setInboundMessageNumber(sequence.getMessageNumber().getMessageNumber());
findSenderBean.setSend(true);
SenderBean replyMessageBean = senderBeanMgr.findUnique(findSenderBean);
// this is effectively a poll for the replyMessage, so re-use the logic in the MakeConnection
// processor. This will use this thread to re-send the reply, writing it into the transport.
// As the reply is now written we do not want to continue processing, or suspend, so we abort.
if(replyMessageBean != null) {
if(log.isDebugEnabled()) log.debug("Found matching reply for replayed message");
MakeConnectionProcessor.replyToPoll(rmMsgCtx, replyMessageBean, storageManager, false, null, transaction);
result = InvocationResponse.ABORT;
if (log.isDebugEnabled())
log.debug("Exit: SequenceProcessor::processReliableMessage, replayed message: " + result);
return result;
}
}
EndpointReference acksTo = new EndpointReference (bean.getAcksToEPR());
// Send an Ack if needed.
//We are not sending acks for duplicate messages in the RM 1.0 anon InOut case.
//If a standalone ack get sent before the actualy message (I.e. before the original msg get
//replied), the client may take this as a InOnly message and may avoid looking for the application
//response.
if (!(Sandesha2Constants.SPEC_VERSIONS.v1_0.equals(rmMsgCtx.getRMSpecVersion()) &&
rmMsgCtx.getReplyTo().hasAnonymousAddress())) {
sendAckIfNeeded(bean, sequenceId, rmMsgCtx, storageManager, true, acksTo.hasAnonymousAddress());
}
result = InvocationResponse.ABORT;
if (log.isDebugEnabled())
log.debug("Exit: SequenceProcessor::processReliableMessage, dropping duplicate: " + result);
return result;
}
// If the message is a reply to an outbound message then we can update the RMSBean that
// matches.
EndpointReference toEPR = msgCtx.getTo();
if(toEPR == null || toEPR.hasAnonymousAddress()) {
RMSBean outBean = null;
// Look for the correct outbound sequence by checking the anon uuid (if there is one)
String toAddress = (toEPR == null) ? null : toEPR.getAddress();
if(SandeshaUtil.isWSRMAnonymous(toAddress)) {
RMSBean finderBean = new RMSBean();
finderBean.setAnonymousUUID(toAddress);
outBean = storageManager.getRMSBeanMgr().findUnique(finderBean);
}
// Fall back to the sequence that may have been offered at sequence creation time
if(outBean == null) {
String outboundSequence = bean.getOutboundInternalSequence();
if(outboundSequence != null) {
outBean = SandeshaUtil.getRMSBeanFromInternalSequenceId(storageManager, outboundSequence);
}
}
// Update the reply count
if(outBean != null && outBean.getExpectedReplies() > 0 ) {
outBean.setExpectedReplies(outBean.getExpectedReplies() - 1);
RMSBeanMgr outMgr = storageManager.getRMSBeanMgr();
outMgr.update(outBean);
}
}
// Set the last activated time
bean.setLastActivatedTime(System.currentTimeMillis());
// Update the RMD bean
mgr.update(bean);
// If we are doing sync 2-way over WSRM 1.0, then we may just have received one of
// the reply messages that we were looking for. If so we can remove the matching sender bean.
int mep = msgCtx.getAxisOperation().getAxisSpecifMEPConstant();
if(specVersion!=null && specVersion.equals(Sandesha2Constants.SPEC_VERSIONS.v1_0) &&