//retrieving the the storage manager
StorageManager storageManager = SandeshaUtil.getSandeshaStorageManager(configContext);
SequencePropertyBeanMgr seqPropMgr = storageManager.getSequencePropretyBeanMgr();
Transaction outHandlerTransaction = storageManager.getTransaction();
boolean serverSide = msgContext.isServerSide();
// setting message Id if null
if (msgContext.getMessageID() == null)
msgContext.setMessageID(SandeshaUtil.getUUID());
// find internal sequence id
String internalSequenceId = null;
String storageKey = SandeshaUtil.getUUID(); //the key which will be used to store this message.
/* Internal sequence id is the one used to refer to the sequence (since
actual sequence id is not available when first msg arrives)
server side - a derivation of the sequenceId of the incoming sequence
client side - a derivation of wsaTo & SeequenceKey */
boolean lastMessage = false;
if (serverSide) {
// getting the request message and rmMessage.
MessageContext reqMsgCtx;
try {
reqMsgCtx = msgContext.getOperationContext().getMessageContext(OperationContextFactory.MESSAGE_LABEL_IN_VALUE);
} catch (AxisFault e) {
throw new SandeshaException (e);
}
RMMsgContext requestRMMsgCtx = MsgInitializer.initializeMessage(reqMsgCtx);
Sequence reqSequence = (Sequence) requestRMMsgCtx.getMessagePart(Sandesha2Constants.MessageParts.SEQUENCE);
if (reqSequence == null) {
String message = "Sequence part is null";
log.debug(message);
throw new SandeshaException(message);
}
String incomingSeqId = reqSequence.getIdentifier().getIdentifier();
if (incomingSeqId == null || incomingSeqId == "") {
String message = "Invalid seqence Id";
log.debug(message);
throw new SandeshaException(message);
}
long requestMsgNo = reqSequence.getMessageNumber().getMessageNumber();
internalSequenceId = SandeshaUtil.getOutgoingSideInternalSequenceID(incomingSeqId);
//deciding weather the last message.
String requestLastMsgNoStr = SandeshaUtil.getSequenceProperty(incomingSeqId,Sandesha2Constants.SequenceProperties.LAST_IN_MESSAGE_NO,configContext);
if (requestLastMsgNoStr!=null) {
long requestLastMsgNo = Long.parseLong(requestLastMsgNoStr);
if (requestLastMsgNo==requestMsgNo)
lastMessage = true;
}
} else {
// set the internal sequence id for the client side.
EndpointReference toEPR = msgContext.getTo();
if (toEPR == null || toEPR.getAddress() == null || "".equals(toEPR.getAddress())) {
String message = "TO End Point Reference is not set correctly. This is a must for the sandesha client side.";
log.debug(message);
throw new SandeshaException(message);
}
String to = toEPR.getAddress();
String sequenceKey = (String) msgContext.getProperty(SandeshaClientConstants.SEQUENCE_KEY);
internalSequenceId = SandeshaUtil.getInternalSequenceID(to,sequenceKey);
String lastAppMessage = (String) msgContext.getProperty(SandeshaClientConstants.LAST_MESSAGE);
if (lastAppMessage!=null && "true".equals(lastAppMessage))
lastMessage = true;
}
/* checking weather the user has given the messageNumber (most of the cases this will not be the case where
the system will generate the message numbers */
//User should set it as a long object.
Long messageNumberLng = (Long) msgContext.getProperty(SandeshaClientConstants.MESSAGE_NUMBER);
long givenMessageNumber = -1;
if (messageNumberLng!=null) {
givenMessageNumber = messageNumberLng.longValue();
if (givenMessageNumber<=0) {
throw new SandeshaException ("The givem message number value is invalid (has to be larger than zero)");
}
}
//the message number that was last used.
long systemMessageNumber = getPreviousMsgNo(configContext, internalSequenceId);
//The number given by the user has to be larger than the last stored number.
if (givenMessageNumber>0 && givenMessageNumber<=systemMessageNumber) {
String message = "The given message number is not larger than value of the last sent message.";
throw new SandeshaException (message);
}
//Finding the correct message number.
long messageNumber = -1;
if (givenMessageNumber>0) // if given message number is valid use it. (this is larger than the last stored due to the last check)
messageNumber = givenMessageNumber;
else if (systemMessageNumber>0) { //if system message number is valid use it.
messageNumber = systemMessageNumber+1;
} else { //This is the fist message (systemMessageNumber = -1)
messageNumber = 1;
}
//A dummy message is a one which will not be processed as a actual application message.
//The RM handlers will simply let these go.
String dummyMessageString = (String) msgContext.getOptions().getProperty(SandeshaClientConstants.DUMMY_MESSAGE);
boolean dummyMessage = false;
if (dummyMessageString!=null && Sandesha2Constants.VALUE_TRUE.equals(dummyMessageString))
dummyMessage = true;
//saving the used message number
if (!dummyMessage)
setNextMsgNo(configContext,internalSequenceId,messageNumber);
//set this as the response highest message.
SequencePropertyBean responseHighestMsgBean = new SequencePropertyBean (
internalSequenceId,
Sandesha2Constants.SequenceProperties.HIGHEST_OUT_MSG_NUMBER,
new Long (messageNumber).toString()
);
seqPropMgr.insert(responseHighestMsgBean);
if (lastMessage) {
SequencePropertyBean responseHighestMsgKeyBean = new SequencePropertyBean (
internalSequenceId,
Sandesha2Constants.SequenceProperties.HIGHEST_OUT_MSG_KEY,
storageKey
);
SequencePropertyBean responseLastMsgKeyBean = new SequencePropertyBean (
internalSequenceId,
Sandesha2Constants.SequenceProperties.LAST_OUT_MESSAGE_NO,
new Long (messageNumber).toString()
);
seqPropMgr.insert(responseHighestMsgKeyBean);
seqPropMgr.insert(responseLastMsgKeyBean);
}
boolean sendCreateSequence = false;
SequencePropertyBean outSeqBean = seqPropMgr.retrieve(
internalSequenceId,
Sandesha2Constants.SequenceProperties.OUT_SEQUENCE_ID);
// setting async ack endpoint for the server side. (if present)
if (serverSide) {
String incomingSequenceID = SandeshaUtil
.getServerSideIncomingSeqIdFromInternalSeqId(internalSequenceId);
SequencePropertyBean incomingToBean = seqPropMgr.retrieve(
incomingSequenceID,
Sandesha2Constants.SequenceProperties.TO_EPR);
if (incomingToBean != null) {
String incomingTo = incomingToBean.getValue();
msgContext.setProperty(SandeshaClientConstants.AcksTo, incomingTo);
}
}
//FINDING THE SPEC VERSION
String specVersion = null;
if (msgContext.isServerSide()) {
//in the server side, get the RM version from the request sequence.
MessageContext requestMessageContext;
try {
requestMessageContext = msgContext.getOperationContext().getMessageContext(AxisOperationFactory.MESSAGE_LABEL_IN_VALUE);
} catch (AxisFault e) {
throw new SandeshaException (e);
}
if (requestMessageContext==null)
throw new SandeshaException ("Request message context is null, cant find out the request side sequenceID");
RMMsgContext requestRMMsgCtx = MsgInitializer.initializeMessage(requestMessageContext);
Sequence sequence = (Sequence) requestRMMsgCtx.getMessagePart(Sandesha2Constants.MessageParts.SEQUENCE);
String requestSequenceID = sequence.getIdentifier().getIdentifier();
SequencePropertyBean specVersionBean = seqPropMgr.retrieve(requestSequenceID,Sandesha2Constants.SequenceProperties.RM_SPEC_VERSION);
if (specVersionBean==null)
throw new SandeshaException ("SpecVersion sequence property bean is not available for the incoming sequence. Cant find the RM version for outgoing side");
specVersion = specVersionBean.getValue();
} else {
//in the client side, user will set the RM version.
specVersion = (String) msgContext.getProperty(SandeshaClientConstants.RM_SPEC_VERSION);
}
if (specVersion==null)
specVersion = SpecSpecificConstants.getDefaultSpecVersion(); //TODO change the default to v1_1.
if (messageNumber == 1) {
if (outSeqBean == null) { // out sequence will be set for the server side, in the case of an offer.
sendCreateSequence = true; // message number being one and not having an out sequence, implies that a create sequence has to be send.
}
// if fist message - setup the sending side sequence - both for the server and the client sides
SequenceManager.setupNewClientSequence(msgContext, internalSequenceId,specVersion);
}
ServiceContext serviceContext = msgContext.getServiceContext();
OperationContext operationContext = msgContext.getOperationContext();
//SENDING THE CREATE SEQUENCE.
if (sendCreateSequence) {
SequencePropertyBean responseCreateSeqAdded = seqPropMgr
.retrieve(internalSequenceId,Sandesha2Constants.SequenceProperties.OUT_CREATE_SEQUENCE_SENT);
String addressingNamespaceURI = SandeshaUtil.getSequenceProperty(internalSequenceId,Sandesha2Constants.SequenceProperties.ADDRESSING_NAMESPACE_VALUE,configContext);
String anonymousURI = SpecSpecificConstants.getAddressingAnonymousURI(addressingNamespaceURI);
if (responseCreateSeqAdded == null) {
responseCreateSeqAdded = new SequencePropertyBean(
internalSequenceId,Sandesha2Constants.SequenceProperties.OUT_CREATE_SEQUENCE_SENT,"true");
seqPropMgr.insert(responseCreateSeqAdded);
String acksTo = null;
if (serviceContext != null)
acksTo = (String) msgContext.getProperty(SandeshaClientConstants.AcksTo);
if (msgContext.isServerSide()) {
// we do not set acksTo value to anonymous when the create
// sequence is send from the server.
MessageContext requestMessage;
try {
requestMessage = operationContext.getMessageContext(OperationContextFactory.MESSAGE_LABEL_IN_VALUE);
} catch (AxisFault e) {
throw new SandeshaException (e);
}
if (requestMessage == null) {
String message = "Request message is not present";
log.debug(message);
throw new SandeshaException(message);
}
acksTo = requestMessage.getTo().getAddress();
} else {
if (acksTo == null)
acksTo = anonymousURI;
}
if (!anonymousURI.equals(acksTo) && !serverSide) {
String transportIn = (String) configContext //TODO verify
.getProperty(MessageContext.TRANSPORT_IN);
if (transportIn == null)
transportIn = org.apache.axis2.Constants.TRANSPORT_HTTP;
} else if (acksTo == null && serverSide) {
String incomingSequencId = SandeshaUtil.getServerSideIncomingSeqIdFromInternalSeqId(internalSequenceId);
SequencePropertyBean bean = seqPropMgr.retrieve(
incomingSequencId,Sandesha2Constants.SequenceProperties.REPLY_TO_EPR);
if (bean != null) {
EndpointReference acksToEPR = new EndpointReference(bean.getValue());
if (acksToEPR != null)
acksTo = (String) acksToEPR.getAddress();
}
} else if (anonymousURI.equals(acksTo)) {
// set transport in.
Object trIn = msgContext.getProperty(MessageContext.TRANSPORT_IN);
if (trIn == null) {
//TODO
}
}
addCreateSequenceMessage(rmMsgCtx, internalSequenceId, acksTo);
}
}
SOAPEnvelope env = rmMsgCtx.getSOAPEnvelope();
if (env == null) {
SOAPEnvelope envelope = SOAPAbstractFactory.getSOAPFactory(
SandeshaUtil.getSOAPVersion(env)).getDefaultEnvelope();
rmMsgCtx.setSOAPEnvelop(envelope);
}
SOAPBody soapBody = rmMsgCtx.getSOAPEnvelope().getBody();
if (soapBody == null) {
String message = "Invalid SOAP message. Body is not present";
log.debug(message);
throw new SandeshaException(message);
}
String messageId1 = SandeshaUtil.getUUID();
if (rmMsgCtx.getMessageId() == null) {
rmMsgCtx.setMessageId(messageId1);
}
if (serverSide) {
// let the request end with 202 if a ack has not been
// written in the incoming thread.
MessageContext reqMsgCtx = null;
try {
reqMsgCtx = msgContext.getOperationContext().getMessageContext(OperationContextFactory.MESSAGE_LABEL_IN_VALUE);
} catch (AxisFault e) {
throw new SandeshaException (e);
}
if (reqMsgCtx.getProperty(Sandesha2Constants.ACK_WRITTEN) == null
|| !"true".equals(reqMsgCtx.getProperty(Sandesha2Constants.ACK_WRITTEN)))
reqMsgCtx.getOperationContext().setProperty(org.apache.axis2.Constants.RESPONSE_WRITTEN, "false");
}
EndpointReference toEPR = msgContext.getTo();
if (toEPR == null) {
String message = "To EPR is not found";
log.debug(message);
throw new SandeshaException(message);
}
//setting default actions.
String to = toEPR.getAddress();
String operationName = msgContext.getOperationContext().getAxisOperation().getName().getLocalPart();
if (msgContext.getWSAAction() == null) {
msgContext.setWSAAction(to + "/" + operationName);
}
if (msgContext.getSoapAction() == null) {
msgContext.setSoapAction("\"" + to + "/" + operationName + "\"");
}
// processing the response if not an dummy.
if (!dummyMessage)
processResponseMessage(rmMsgCtx, internalSequenceId, messageNumber,storageKey);
msgContext.pause(); // the execution will be stopped.
outHandlerTransaction.commit();
}