blob: 3f49a3ba1cc023eaf91eae91db79c5ba6a43b7ad [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.sandesha2.util;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisOperationFactory;
import org.apache.axis2.om.OMElement;
import org.apache.axis2.soap.SOAP11Constants;
import org.apache.axis2.soap.SOAP12Constants;
import org.apache.axis2.soap.SOAPEnvelope;
import org.apache.axis2.soap.SOAPFactory;
import org.apache.axis2.soap.SOAPHeader;
import org.apache.axis2.util.Utils;
import org.apache.sandesha2.Sandesha2Constants;
import org.apache.sandesha2.FaultData;
import org.apache.sandesha2.RMMsgContext;
import org.apache.sandesha2.SOAPFaultEnvelopeCreator;
import org.apache.sandesha2.SandeshaException;
import org.apache.sandesha2.storage.StorageManager;
import org.apache.sandesha2.storage.beanmanagers.NextMsgBeanMgr;
import org.apache.sandesha2.storage.beanmanagers.SequencePropertyBeanMgr;
import org.apache.sandesha2.storage.beans.NextMsgBean;
import org.apache.sandesha2.storage.beans.SequencePropertyBean;
import org.apache.sandesha2.wsrm.AcknowledgementRange;
import org.apache.sandesha2.wsrm.CreateSequence;
import org.apache.sandesha2.wsrm.Identifier;
import org.apache.sandesha2.wsrm.Sequence;
import org.apache.sandesha2.wsrm.SequenceAcknowledgement;
import org.apache.sandesha2.wsrm.SequenceOffer;
import org.apache.sandesha2.wsrm.TerminateSequence;
/**
* Has logic to check for possible RM related faults and create it.
*
* @author Chamikara Jayalath <chamikaramj@gmail.com>
* @author Sanka Samaranayaka <ssanka@gmail.com>
*/
public class FaultManager {
public FaultManager() {
}
public RMMsgContext checkForPossibleFaults(MessageContext msgCtx)
throws SandeshaException {
//Cannot initialize message before checking for MsgNoRoleover - since
// initialization will give an exception
//for rolled over messages.
SOAPEnvelope envelope = msgCtx.getEnvelope();
if (envelope == null)
throw new SandeshaException("SOAP Envelope is null");
RMMsgContext faultMessageContext = null;
SOAPHeader header = envelope.getHeader();
if (header != null) {
OMElement sequenceHeaderBlock = header
.getFirstChildWithName(new QName(Sandesha2Constants.WSRM.NS_URI_RM,
Sandesha2Constants.WSRM.SEQUENCE));
if (sequenceHeaderBlock != null) {
faultMessageContext = checkForMessageNumberRoleover(msgCtx);
if (faultMessageContext != null)
return faultMessageContext;
}
}
RMMsgContext rmMsgCtx = MsgInitializer.initializeMessage(msgCtx);
int msgType = rmMsgCtx.getMessageType();
if (msgType == Sandesha2Constants.MessageTypes.APPLICATION
|| msgType == Sandesha2Constants.MessageTypes.TERMINATE_SEQ) {
faultMessageContext = checkForUnknownSequence(msgCtx);
if (faultMessageContext != null)
return faultMessageContext;
}
if (msgType == Sandesha2Constants.MessageTypes.CREATE_SEQ) {
faultMessageContext = checkForCreateSequenceRefused(msgCtx);
if (faultMessageContext != null)
return faultMessageContext;
}
if (msgType == Sandesha2Constants.MessageTypes.ACK) {
faultMessageContext = checkForInvalidAcknowledgement(msgCtx);
if (faultMessageContext != null)
return faultMessageContext;
}
if (msgType == Sandesha2Constants.MessageTypes.APPLICATION) {
faultMessageContext = checkForLastMsgNumberExceeded(msgCtx);
if (faultMessageContext != null)
return faultMessageContext;
}
return faultMessageContext;
}
/**
* Check weather the CreateSequence should be refused and generate the fault if it should.
*
* @param messageContext
* @return
* @throws SandeshaException
*/
private RMMsgContext checkForCreateSequenceRefused(
MessageContext messageContext) throws SandeshaException {
RMMsgContext rmMsgCtx = MsgInitializer
.initializeMessage(messageContext);
CreateSequence createSequence = (CreateSequence) rmMsgCtx
.getMessagePart(Sandesha2Constants.MessageParts.CREATE_SEQ);
if (createSequence == null)
throw new SandeshaException(
"CreateSequence message does not have a CreateSequence part");
ConfigurationContext context = messageContext.getConfigurationContext();
StorageManager storageManager = (StorageManager) SandeshaUtil
.getSandeshaStorageManager(context);
if (storageManager == null)
throw new SandeshaException("Storage Manager is null");
boolean refuseSequence = false;
String reason = "";
SequenceOffer offer = createSequence.getSequenceOffer();
if (offer != null) {
String offeredSequenceId = offer.getIdentifer().getIdentifier();
if (offeredSequenceId == null || "".equals(offeredSequenceId)) {
refuseSequence = true;
reason = "Offered sequenceId is invalid";
} else {
NextMsgBeanMgr nextMsgBeanMgr = storageManager
.getNextMsgBeanMgr();
Collection collection = nextMsgBeanMgr.retrieveAll();
Iterator it = collection.iterator();
while (it.hasNext()) {
//checking weather a incoming sequence with the given id
// exists.
NextMsgBean nextMsgBean = (NextMsgBean) it.next();
String sequenceId = nextMsgBean.getSequenceId();
if (sequenceId.equals(offeredSequenceId)) {
refuseSequence = true;
reason = "A sequence with offered sequenceId, already axists";
}
//checking weather an outgoing sequence with the given id
// exists.
SequencePropertyBeanMgr sequencePropertyBeanMgr = storageManager
.getSequencePropretyBeanMgr();
SequencePropertyBean sequencePropertyBean = sequencePropertyBeanMgr
.retrieve(
sequenceId,
Sandesha2Constants.SequenceProperties.OUT_SEQUENCE_ID);
if (sequencePropertyBean != null) {
String outSequenceId = (String) sequencePropertyBean
.getValue();
if (outSequenceId != null
&& outSequenceId.equals(offeredSequenceId)) {
refuseSequence = true;
reason = "A sequence with offered sequenceId, already axists";
}
}
}
}
}
//TODO - if (securityTokenReference is present RefuseCreateSequence)
if (refuseSequence) {
FaultData data = new FaultData();
data
.setType(Sandesha2Constants.SOAPFaults.FaultType.CREATE_SEQUENCE_REFUSED);
int SOAPVersion = SandeshaUtil.getSOAPVersion(rmMsgCtx
.getSOAPEnvelope());
if (SOAPVersion == Sandesha2Constants.SOAPVersion.v1_1)
data.setCode(SOAP11Constants.FAULT_CODE_SENDER);
else
data.setCode(SOAP12Constants.FAULT_CODE_SENDER);
data
.setSubcode(Sandesha2Constants.SOAPFaults.Subcodes.CREATE_SEQUENCE_REFUSED);
data.setReason(reason);
return getFault(rmMsgCtx, data);
}
return null;
}
/**
* Check weather the LastMessage number has been exceeded and generate the fault if it is.
*
* @param msgCtx
* @return
*/
private RMMsgContext checkForLastMsgNumberExceeded(MessageContext msgCtx) {
return null;
}
private RMMsgContext checkForMessageNumberRoleover(
MessageContext messageContext) {
return null;
}
/**
* Check whether a Sequence message (a) belongs to a unknown sequence
* (generates an UnknownSequence fault) (b) message number exceeds a
* predifined limit ( genenrates a Message Number Rollover fault)
*
* @param msgCtx
* @return @throws
* SandeshaException
*/
public RMMsgContext checkForUnknownSequence(MessageContext messageContext)
throws SandeshaException {
RMMsgContext rmMsgCtx = MsgInitializer
.initializeMessage(messageContext);
String sequenceId = null;
if (rmMsgCtx.getMessageType() == Sandesha2Constants.MessageTypes.APPLICATION) {
Sequence sequence = (Sequence) rmMsgCtx
.getMessagePart(Sandesha2Constants.MessageParts.SEQUENCE);
if (sequence == null)
throw new SandeshaException(
"Sequence part not found in the application message");
sequenceId = sequence.getIdentifier().getIdentifier();
} else if (rmMsgCtx.getMessageType() == Sandesha2Constants.MessageTypes.ACK) {
SequenceAcknowledgement sequenceAcknowledgement = (SequenceAcknowledgement) rmMsgCtx
.getMessagePart(Sandesha2Constants.MessageParts.SEQ_ACKNOWLEDGEMENT);
sequenceId = sequenceAcknowledgement.getIdentifier()
.getIdentifier();
} else if (rmMsgCtx.getMessageType() == Sandesha2Constants.MessageTypes.TERMINATE_SEQ) {
TerminateSequence terminateSequence = (TerminateSequence) rmMsgCtx
.getMessagePart(Sandesha2Constants.MessageParts.TERMINATE_SEQ);
sequenceId = terminateSequence.getIdentifier().getIdentifier();
} else {
//sequenceId not found.
return null;
}
StorageManager storageManager = SandeshaUtil
.getSandeshaStorageManager(messageContext.getConfigurationContext());
NextMsgBeanMgr mgr = storageManager.getNextMsgBeanMgr();
SOAPEnvelope envelope = messageContext.getEnvelope();
Collection coll = mgr.retrieveAll();
Iterator it = coll.iterator();
boolean validSequence = false;
while (it.hasNext()) {
NextMsgBean nextMsgBean = (NextMsgBean) it.next();
String tempId = nextMsgBean.getSequenceId();
if (tempId.equals(sequenceId)) {
validSequence = true;
break;
}
}
if (!validSequence) {
//Return an UnknownSequence error
int SOAPVersion = SandeshaUtil.getSOAPVersion(envelope);
FaultData data = new FaultData();
if (SOAPVersion == Sandesha2Constants.SOAPVersion.v1_1)
data.setCode(SOAP11Constants.FAULT_CODE_SENDER);
else
data.setCode(SOAP12Constants.FAULT_CODE_SENDER);
data.setSubcode(Sandesha2Constants.SOAPFaults.Subcodes.UNKNOWN_SEQUENCE);
SOAPFactory factory = SOAPAbstractFactory
.getSOAPFactory(SOAPVersion);
Identifier identifier = new Identifier(factory);
identifier.setIndentifer(sequenceId);
OMElement identifierOMElem = identifier.getOMElement();
data.setDetail(identifierOMElem);
data
.setReason("The value of wsrm:Identifier is not a known Sequence identifier");
return getFault(rmMsgCtx, data);
}
return null;
}
/**
* Check weather the Acknowledgement is invalid and generate a fault if it is.
*
* @param msgCtx
* @return @throws
* SandeshaException
*/
public RMMsgContext checkForInvalidAcknowledgement(MessageContext msgCtx)
throws SandeshaException {
//check lower<=upper
//TODO acked for not-send message
RMMsgContext rmMsgContext = new RMMsgContext();
if (rmMsgContext.getMessageType() != Sandesha2Constants.MessageTypes.ACK)
return null;
SequenceAcknowledgement sequenceAcknowledgement = (SequenceAcknowledgement) rmMsgContext
.getMessagePart(Sandesha2Constants.MessageParts.SEQ_ACKNOWLEDGEMENT);
List sequenceAckList = sequenceAcknowledgement
.getAcknowledgementRanges();
Iterator it = sequenceAckList.iterator();
while (it.hasNext()) {
AcknowledgementRange acknowledgementRange = (AcknowledgementRange) it
.next();
long upper = acknowledgementRange.getUpperValue();
long lower = acknowledgementRange.getLowerValue();
if (lower > upper) {
//Invalid ack
FaultData data = new FaultData();
int SOAPVersion = SandeshaUtil.getSOAPVersion(msgCtx
.getEnvelope());
if (SOAPVersion == Sandesha2Constants.SOAPVersion.v1_1)
data.setCode(SOAP11Constants.FAULT_CODE_SENDER);
else
data.setCode(SOAP12Constants.FAULT_CODE_SENDER);
data.setSubcode(Sandesha2Constants.SOAPFaults.Subcodes.INVALID_ACKNOWLEDGEMENT);
data.setSubcode("The SequenceAcknowledgement is invalid. Lower value is larger than upper value");
data.setDetail(sequenceAcknowledgement.getOMElement());
return getFault(rmMsgContext, data);
}
}
return null;
}
/**
* Returns a RMMessageContext for the fault message. Data for generating the fault is given in the data parameter.
*
* @param referenceRMMsgContext
* @param data
* @return
* @throws SandeshaException
*/
public RMMsgContext getFault(RMMsgContext referenceRMMsgContext,
FaultData data) throws SandeshaException {
try {
MessageContext referenceMessage = referenceRMMsgContext
.getMessageContext();
MessageContext faultMsgContext = Utils
.createOutMessageContext(referenceMessage);
StorageManager storageManager = SandeshaUtil
.getSandeshaStorageManager(referenceMessage
.getConfigurationContext());
//setting contexts.
faultMsgContext.setAxisServiceGroup(referenceMessage
.getAxisServiceGroup());
faultMsgContext.setAxisService(referenceMessage.getAxisService());
faultMsgContext.setAxisServiceGroup(referenceMessage
.getAxisServiceGroup());
faultMsgContext.setServiceGroupContext(referenceMessage
.getServiceGroupContext());
faultMsgContext.setServiceGroupContextId(referenceMessage
.getServiceGroupContextId());
faultMsgContext.setServiceContext(referenceMessage
.getServiceContext());
faultMsgContext.setServiceContextID(referenceMessage
.getServiceContextID());
AxisOperation operation = AxisOperationFactory
.getAxisOperation(AxisOperationFactory.MEP_CONSTANT_OUT_ONLY);
OperationContext operationContext = new OperationContext(operation);
faultMsgContext.setAxisOperation(operation);
faultMsgContext.setOperationContext(operationContext);
String acksToStr = null;
if (referenceRMMsgContext.getMessageType() == Sandesha2Constants.MessageTypes.CREATE_SEQ) {
CreateSequence createSequence = (CreateSequence) referenceRMMsgContext
.getMessagePart(Sandesha2Constants.MessageParts.CREATE_SEQ);
acksToStr = createSequence.getAcksTo().getAddress().getEpr()
.getAddress();
} else {
SequencePropertyBeanMgr seqPropMgr = storageManager
.getSequencePropretyBeanMgr();
String sequenceId = data.getSequenceId();
SequencePropertyBean acksToBean = seqPropMgr.retrieve(
sequenceId, Sandesha2Constants.SequenceProperties.ACKS_TO_EPR);
if (acksToBean != null) {
EndpointReference epr = (EndpointReference) acksToBean
.getValue();
if (epr != null)
acksToStr = epr.getAddress();
}
}
if (acksToStr != null
&& !acksToStr.equals(Sandesha2Constants.WSA.NS_URI_ANONYMOUS)) {
faultMsgContext.setTo(new EndpointReference(acksToStr));
}
int SOAPVersion = SandeshaUtil.getSOAPVersion(referenceMessage
.getEnvelope());
SOAPFaultEnvelopeCreator.addSOAPFaultEnvelope(faultMsgContext,
SOAPVersion, data);
RMMsgContext faultRMMsgCtx = MsgInitializer
.initializeMessage(faultMsgContext);
return faultRMMsgCtx;
} catch (AxisFault e) {
throw new SandeshaException(e.getMessage());
}
}
}