/*
* 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.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.context.OperationContextFactory;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.context.ServiceGroupContext;
import org.apache.axis2.description.AxisDescription;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.engine.AxisEngine;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sandesha2.RMMsgContext;
import org.apache.sandesha2.Sandesha2Constants;
import org.apache.sandesha2.SandeshaException;
import org.apache.sandesha2.client.SandeshaClientConstants;
import org.apache.sandesha2.context.ContextManager;
import org.apache.sandesha2.i18n.SandeshaMessageHelper;
import org.apache.sandesha2.i18n.SandeshaMessageKeys;
import org.apache.sandesha2.policy.SandeshaPolicyBean;
import org.apache.sandesha2.security.SecurityManager;
import org.apache.sandesha2.storage.StorageManager;
import org.apache.sandesha2.storage.beanmanagers.RMDBeanMgr;
import org.apache.sandesha2.storage.beanmanagers.RMSBeanMgr;
import org.apache.sandesha2.storage.beans.RMDBean;
import org.apache.sandesha2.storage.beans.RMSBean;
import org.apache.sandesha2.storage.beans.RMSequenceBean;
import org.apache.sandesha2.transport.Sandesha2TransportOutDesc;
import org.apache.sandesha2.workers.SandeshaThread;
import org.apache.sandesha2.wsrm.AckRequested;
import org.apache.sandesha2.wsrm.AcknowledgementRange;
import org.apache.sandesha2.wsrm.CloseSequence;
import org.apache.sandesha2.wsrm.CloseSequenceResponse;
import org.apache.sandesha2.wsrm.Sequence;
import org.apache.sandesha2.wsrm.SequenceAcknowledgement;
/**
* Contains utility methods that are used in many plases of Sandesha2.
*/
public class SandeshaUtil {
// private static Hashtable storedMsgContexts = new Hashtable();
private static Log log = LogFactory.getLog(SandeshaUtil.class);
private static AxisModule axisModule = null;
public static AxisModule getAxisModule() {
return axisModule;
}
public static void setAxisModule(AxisModule module) {
axisModule = module;
}
/**
* Create a new UUID.
*
* @return
*/
public static String getUUID() {
// String uuid = "uuid:" + UUIDGenerator.getUUID();
String uuid = org.apache.axiom.om.util.UUIDGenerator.getUUID();
return uuid;
}
/**
* Used to convert a RangeString into a set of AcknowledgementRanges.
*
* @param msgNoStr
* @param factory
* @return
* @throws SandeshaException
*/
public static ArrayList getAckRangeArrayList(RangeString completedMessageRanges, String rmNamespaceValue)
throws SandeshaException {
ArrayList ackRanges = new ArrayList(); //the final ack ranges that we will build up
Range[] ranges = completedMessageRanges.getRanges();
for(int i=0; i<ranges.length; i++){
AcknowledgementRange ackRange = new AcknowledgementRange(rmNamespaceValue);
ackRange.setLowerValue(ranges[i].lowerValue);
ackRange.setUpperValue(ranges[i].upperValue);
ackRanges.add(ackRange);
}
return ackRanges;
}
public static void startWorkersForSequence(ConfigurationContext context, RMSequenceBean sequence)
throws SandeshaException {
if (log.isDebugEnabled())
log.debug("Enter: SandeshaUtil::startWorkersForSequence, sequence " + sequence);
StorageManager mgr = getSandeshaStorageManager(context, context.getAxisConfiguration());
boolean polling = sequence.isPollingMode();
SandeshaThread sender = mgr.getSender();
SandeshaThread invoker = mgr.getInvoker();
SandeshaThread pollMgr = mgr.getPollingManager();
// Only start the polling manager if we are configured to use MakeConnection
if(polling && pollMgr == null) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.makeConnectionDisabled);
throw new SandeshaException(message);
}
if(sequence instanceof RMSBean) {
// We pass in the internal sequence id for internal sequences.
String sequenceId = ((RMSBean)sequence).getInternalSequenceID();
sender.runThreadForSequence(context, sequenceId, true);
if(polling) pollMgr.runThreadForSequence(context, sequenceId, true);
} else {
String sequenceId = sequence.getSequenceID();
sender.runThreadForSequence(context, sequenceId, false);
if(invoker != null) invoker.runThreadForSequence(context, sequenceId, false);
if(polling) pollMgr.runThreadForSequence(context, sequenceId, false);
}
if (log.isDebugEnabled()) log.debug("Exit: SandeshaUtil::startWorkersForSequence");
}
public static String getMessageTypeString(int messageType) {
switch (messageType) {
case Sandesha2Constants.MessageTypes.CREATE_SEQ:
return "CreateSequence";
case Sandesha2Constants.MessageTypes.CREATE_SEQ_RESPONSE:
return "CreateSequenceResponse";
case Sandesha2Constants.MessageTypes.ACK:
return "Acknowledgement";
case Sandesha2Constants.MessageTypes.APPLICATION:
return "Application";
case Sandesha2Constants.MessageTypes.TERMINATE_SEQ:
return "TerminateSequence";
case Sandesha2Constants.MessageTypes.ACK_REQUEST:
return "AckRequest";
case Sandesha2Constants.MessageTypes.CLOSE_SEQUENCE:
return "CloseSequence";
case Sandesha2Constants.MessageTypes.CLOSE_SEQUENCE_RESPONSE:
return "CloseSequenceResponse";
case Sandesha2Constants.MessageTypes.TERMINATE_SEQ_RESPONSE:
return "TerminateSequenceResponse";
case Sandesha2Constants.MessageTypes.FAULT_MSG:
return "Fault";
case Sandesha2Constants.MessageTypes.MAKE_CONNECTION_MSG:
return "MakeConnection";
case Sandesha2Constants.MessageTypes.UNKNOWN:
return "Unknown";
default:
return "Error";
}
}
public static String getServerSideIncomingSeqIdFromInternalSeqId(String internalSequenceId)
throws SandeshaException {
String startStr = Sandesha2Constants.INTERNAL_SEQUENCE_PREFIX + ":";
if (!internalSequenceId.startsWith(startStr)) {
throw new SandeshaException(SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.invalidInternalSequenceID,
internalSequenceId));
}
String incomingSequenceId = internalSequenceId.substring(startStr.length());
return incomingSequenceId;
}
/**
* Used to obtain the storage Manager Implementation.
*
* @param context
* @return
* @throws SandeshaException
*/
public static StorageManager getSandeshaStorageManager(ConfigurationContext context,AxisDescription description) throws SandeshaException {
Parameter parameter = description.getParameter(Sandesha2Constants.STORAGE_MANAGER_PARAMETER);
if (parameter==null) {
parameter = new Parameter (Sandesha2Constants.STORAGE_MANAGER_PARAMETER,Sandesha2Constants.DEFAULT_STORAGE_MANAGER);
}
String value = (String) parameter.getValue();
if (Sandesha2Constants.INMEMORY_STORAGE_MANAGER.equals(value))
return getInMemoryStorageManager(context);
else if (Sandesha2Constants.PERMANENT_STORAGE_MANAGER.equals(value))
return getPermanentStorageManager(context);
else
throw new SandeshaException (SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.cannotGetStorageManager));
}
public static StorageManager getInMemoryStorageManager(ConfigurationContext context) throws SandeshaException {
StorageManager inMemoryStorageManager = null;
AxisConfiguration config = context.getAxisConfiguration();
Parameter parameter = config.getParameter(Sandesha2Constants.INMEMORY_STORAGE_MANAGER);
if(parameter != null) inMemoryStorageManager = (StorageManager) parameter.getValue();
if (inMemoryStorageManager != null) return inMemoryStorageManager;
try {
//Currently module policies (default) are used to find the storage manager. These cant be overriden
//TODO change this so that different services can hv different storage managers.
String storageManagerClassStr = getDefaultPropertyBean(context.getAxisConfiguration()).getInMemoryStorageManagerClass();
inMemoryStorageManager = getStorageManagerInstance(storageManagerClassStr,context);
parameter = new Parameter(Sandesha2Constants.INMEMORY_STORAGE_MANAGER, inMemoryStorageManager);
config.addParameter(parameter);
} catch(AxisFault e) {
String message = SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.cannotInitInMemoryStorageManager,
e.toString());
throw new SandeshaException(message, e);
}
return inMemoryStorageManager;
}
public static StorageManager getPermanentStorageManager(ConfigurationContext context) throws SandeshaException {
StorageManager permanentStorageManager = null;
AxisConfiguration config = context.getAxisConfiguration();
Parameter parameter = config.getParameter(Sandesha2Constants.PERMANENT_STORAGE_MANAGER);
if(parameter != null) permanentStorageManager = (StorageManager) parameter.getValue();
if (permanentStorageManager != null) return permanentStorageManager;
try {
//Currently module policies (default) are used to find the storage manager. These cant be overriden
//TODO change this so that different services can hv different storage managers.
String storageManagerClassStr = getDefaultPropertyBean(context.getAxisConfiguration()).getPermanentStorageManagerClass();
permanentStorageManager = getStorageManagerInstance(storageManagerClassStr,context);
parameter = new Parameter(Sandesha2Constants.PERMANENT_STORAGE_MANAGER, permanentStorageManager);
config.addParameter(parameter);
} catch(AxisFault e) {
String message = SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.cannotInitPersistentStorageManager,
e.toString());
throw new SandeshaException(message, e);
}
return permanentStorageManager;
}
private static StorageManager getStorageManagerInstance (String className,ConfigurationContext context) throws SandeshaException {
StorageManager storageManager = null;
try {
ClassLoader classLoader = null;
AxisConfiguration config = context.getAxisConfiguration();
Parameter classLoaderParam = config.getParameter(Sandesha2Constants.MODULE_CLASS_LOADER);
if(classLoaderParam != null) classLoader = (ClassLoader) classLoaderParam.getValue();
if (classLoader==null)
throw new SandeshaException (SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.classLoaderNotFound));
Class c = classLoader.loadClass(className);
Class configContextClass = context.getClass();
Constructor constructor = c.getConstructor(new Class[] { configContextClass });
Object obj = constructor.newInstance(new Object[] {context});
if (obj == null || !(obj instanceof StorageManager))
throw new SandeshaException(SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.storageManagerMustImplement));
StorageManager mgr = (StorageManager) obj;
storageManager = mgr;
return storageManager;
} catch (Exception e) {
String message = SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.cannotGetStorageManager);
if (log.isErrorEnabled())
log.error(message, e);
throw new SandeshaException(message,e);
}
}
public static int getSOAPVersion(SOAPEnvelope envelope) throws SandeshaException {
String namespaceName = envelope.getNamespace().getNamespaceURI();
if (namespaceName.equals(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI))
return Sandesha2Constants.SOAPVersion.v1_1;
else if (namespaceName.equals(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI))
return Sandesha2Constants.SOAPVersion.v1_2;
else
throw new SandeshaException(SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.unknownSoapVersion,
namespaceName));
}
public static MessageContext createNewRelatedMessageContext(RMMsgContext referenceRMMessage, AxisOperation operation)
throws SandeshaException {
try {
MessageContext referenceMessage = referenceRMMessage.getMessageContext();
ConfigurationContext configContext = referenceMessage.getConfigurationContext();
AxisConfiguration axisConfiguration = configContext.getAxisConfiguration();
MessageContext newMessageContext = new MessageContext();
newMessageContext.setConfigurationContext(configContext);
Options oldOptions = referenceMessage.getOptions();
Options newOptions = new Options ();
newOptions.setProperties(oldOptions.getProperties());
newMessageContext.setOptions(newOptions);
if (referenceMessage.getAxisServiceGroup() != null) {
newMessageContext.setAxisServiceGroup(referenceMessage.getAxisServiceGroup());
if (referenceMessage.getServiceGroupContext()!=null) {
newMessageContext.setServiceGroupContext(referenceMessage.getServiceGroupContext());
newMessageContext.setServiceGroupContextId(referenceMessage.getServiceGroupContextId());
} else {
ServiceGroupContext serviceGroupContext = new ServiceGroupContext (
configContext,referenceMessage.getAxisServiceGroup());
newMessageContext.setServiceGroupContext(serviceGroupContext);
}
} else {
AxisServiceGroup axisServiceGroup = new AxisServiceGroup(axisConfiguration);
ServiceGroupContext serviceGroupContext = new ServiceGroupContext(configContext, axisServiceGroup);
newMessageContext.setAxisServiceGroup(axisServiceGroup);
newMessageContext.setServiceGroupContext(serviceGroupContext);
}
if (referenceMessage.getAxisService() != null) {
newMessageContext.setAxisService(referenceMessage.getAxisService());
if (referenceMessage.getServiceContext()!=null) {
newMessageContext.setServiceContext(referenceMessage.getServiceContext());
newMessageContext.setServiceContextID(referenceMessage.getServiceContextID());
} else {
ServiceGroupContext sgc = newMessageContext.getServiceGroupContext();
ServiceContext serviceContext = sgc.getServiceContext(referenceMessage.getAxisService());
newMessageContext.setServiceContext(serviceContext);
}
}
newMessageContext.setAxisOperation(operation);
//The message created will basically be used as a outMessage, so setting the AxisMessage accordingly
newMessageContext.setAxisMessage(operation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE));
OperationContext operationContext = OperationContextFactory.createOperationContext(operation.getAxisSpecificMEPConstant(), operation, newMessageContext.getServiceContext());
newMessageContext.setOperationContext(operationContext);
operationContext.addMessageContext(newMessageContext);
// adding a blank envelope
SOAPFactory factory = SOAPAbstractFactory.getSOAPFactory(SandeshaUtil.getSOAPVersion(referenceMessage
.getEnvelope()));
newMessageContext.setEnvelope(factory.getDefaultEnvelope());
newMessageContext.setTransportIn(referenceMessage.getTransportIn());
newMessageContext.setTransportOut(referenceMessage.getTransportOut());
// copying transport info.
newMessageContext.setProperty(MessageContext.TRANSPORT_OUT, referenceMessage
.getProperty(MessageContext.TRANSPORT_OUT));
newMessageContext.setProperty(Constants.OUT_TRANSPORT_INFO, referenceMessage
.getProperty(Constants.OUT_TRANSPORT_INFO));
newMessageContext.setProperty(MessageContext.TRANSPORT_HEADERS, referenceMessage
.getProperty(MessageContext.TRANSPORT_HEADERS));
newMessageContext.setProperty(MessageContext.TRANSPORT_IN, referenceMessage
.getProperty(MessageContext.TRANSPORT_IN));
newMessageContext.setProperty(MessageContext.TRANSPORT_OUT, referenceMessage
.getProperty(MessageContext.TRANSPORT_OUT));
newMessageContext.setProperty(AddressingConstants.WS_ADDRESSING_VERSION,
referenceMessage.getProperty(AddressingConstants.WS_ADDRESSING_VERSION));
newMessageContext.setProperty(AddressingConstants.DISABLE_ADDRESSING_FOR_OUT_MESSAGES,
referenceMessage.getProperty(AddressingConstants.DISABLE_ADDRESSING_FOR_OUT_MESSAGES));
copyConfiguredProperties (referenceMessage,newMessageContext);
//copying the serverSide property
newMessageContext.setServerSide(referenceMessage.isServerSide());
//this had to be set here to avoid a double invocation.
if (oldOptions!=null)
newOptions.setUseSeparateListener(oldOptions.isUseSeparateListener());
return newMessageContext;
} catch (AxisFault e) {
log.debug(e.getMessage());
throw new SandeshaException(e.getMessage());
}
}
private static void copyConfiguredProperties (MessageContext fromMessage, MessageContext toMessage) throws AxisFault {
// copying properties as configured in the module.xml properties. Module xml has several
//properties which gives comma seperated lists of property names that have to be copited
//from various places when creating related messages.
if (axisModule==null) {
String message = SandeshaMessageKeys.moduleNotSet;
throw new SandeshaException (message);
}
Parameter propertiesFromRefMsg = axisModule.getParameter(Sandesha2Constants.propertiesToCopyFromReferenceMessage);
if (propertiesFromRefMsg!=null) {
String value = (String) propertiesFromRefMsg.getValue();
if (value!=null) {
value = value.trim();
String[] propertyNames = value.split(",");
for (int i=0;i<propertyNames.length;i++) {
String tmp = propertyNames[i];
String propertyName = null;
String targetPropertyName = null;
if (tmp.indexOf (":")>=0) {
//if the property name is given as two values seperated by a colon, this gives the key of the from msg
//and the key for the To Msg respsctively.
String[] vals = tmp.split(":");
propertyName = vals[0].trim();
targetPropertyName = vals[1].trim();
} else {
propertyName = targetPropertyName = tmp;
}
Object val = fromMessage.getProperty(propertyName);
if (val!=null) {
toMessage.setProperty(targetPropertyName,val);
}
}
}
}
Parameter propertiesFromRefReqMsg = axisModule.getParameter(Sandesha2Constants.propertiesToCopyFromReferenceRequestMessage);
OperationContext referenceOpCtx = fromMessage.getOperationContext();
MessageContext referenceRequestMessage = null;
if (referenceOpCtx!=null)
referenceRequestMessage=referenceOpCtx.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if (propertiesFromRefReqMsg!=null && referenceRequestMessage!=null) {
String value = (String) propertiesFromRefReqMsg.getValue();
if (value!=null) {
value = value.trim();
String[] propertyNames = value.split(",");
for (int i=0;i<propertyNames.length;i++) {
String propertyName = propertyNames[i];
Object val = referenceRequestMessage.getProperty(propertyName);
if (val!=null) {
toMessage.setProperty(propertyName,val);
}
}
}
}
}
public static SandeshaPolicyBean getDefaultPropertyBean (AxisConfiguration axisConfiguration) throws SandeshaException {
Parameter parameter = axisConfiguration.getParameter(Sandesha2Constants.SANDESHA_PROPERTY_BEAN);
if (parameter==null)
throw new SandeshaException (SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.defaultPropertyBeanNotSet));
SandeshaPolicyBean sandeshaPropertyBean = (SandeshaPolicyBean) parameter.getValue();
return sandeshaPropertyBean;
}
//TODO change this method.
public static ArrayList getArrayListFromString(String str) {
if (str == null || "".equals(str))
return new ArrayList();
if (str.length() < 2) {
String message = SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.invalidStringArray,
str);
log.debug(message);
throw new IllegalArgumentException (message);
}
int length = str.length();
if (str.charAt(0) != '[' || str.charAt(length - 1) != ']') {
String message = SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.invalidStringArray, str);
log.debug(message);
throw new IllegalArgumentException(message);
}
ArrayList retArr = new ArrayList();
String subStr = str.substring(1, length - 1);
String[] parts = subStr.split(",");
for (int i = 0; i < parts.length; i++) {
if (!"".equals(parts[i]))
retArr.add(parts[i].trim());
}
return retArr;
}
public static String getInternalSequenceID(String to, String sequenceKey) {
if (to == null && sequenceKey == null)
return null;
else if (to == null)
return sequenceKey;
else if (sequenceKey == null)
return to;
else
return Sandesha2Constants.INTERNAL_SEQUENCE_PREFIX + ":" + to + ":" + sequenceKey;
}
public static String getOutgoingSideInternalSequenceID(String sequenceID) {
return Sandesha2Constants.INTERNAL_SEQUENCE_PREFIX + ":" + sequenceID;
}
public static final RMSBean getRMSBeanFromInternalSequenceId(StorageManager storageManager, String internalSequenceID)
throws SandeshaException {
RMSBeanMgr rmsBeanMgr = storageManager.getRMSBeanMgr();
RMSBean bean = new RMSBean();
bean.setInternalSequenceID(internalSequenceID);
bean = rmsBeanMgr.findUnique(bean);
return bean;
}
public static final RMSBean getRMSBeanFromSequenceId(StorageManager storageManager, String sequenceID)
throws SandeshaException {
RMSBeanMgr rmsBeanMgr = storageManager.getRMSBeanMgr();
RMSBean bean = new RMSBean();
bean.setSequenceID(sequenceID);
bean = rmsBeanMgr.findUnique(bean);
return bean;
}
public static RMDBean getRMDBeanFromSequenceId(StorageManager storageManager, String sequenceID)
throws SandeshaException {
RMDBeanMgr rmdBeanMgr = storageManager.getRMDBeanMgr();
RMDBean bean = new RMDBean();
bean.setSequenceID(sequenceID);
bean = rmdBeanMgr.findUnique(bean);
return bean;
}
public static String getSequenceIDFromInternalSequenceID(String internalSequenceID,
StorageManager storageManager) throws SandeshaException {
RMSBean rMSBean = getRMSBeanFromInternalSequenceId(storageManager, internalSequenceID);
String sequeunceID = null;
if (rMSBean != null &&
rMSBean.getSequenceID() != null &&
!rMSBean.getSequenceID().equals(Sandesha2Constants.TEMP_SEQUENCE_ID))
sequeunceID = rMSBean.getSequenceID();
return sequeunceID;
}
public static String getExecutionChainString(ArrayList executionChain) {
Iterator iter = executionChain.iterator();
String executionChainStr = "";
while (iter.hasNext()) {
Handler handler = (Handler) iter.next();
String name = handler.getName();
executionChainStr = executionChainStr + Sandesha2Constants.EXECUTIN_CHAIN_SEPERATOR + name;
}
return executionChainStr;
}
public static boolean isAllMsgsAckedUpto(long highestInMsgNo, String internalSequenceId,
StorageManager storageManager) throws SandeshaException {
RMSBean rmsBean = SandeshaUtil.getRMSBeanFromInternalSequenceId(storageManager, internalSequenceId);
RangeString ackedMsgRanges = rmsBean.getClientCompletedMessages();
long smallestMsgNo = 1;
Range interestedRange = new Range(smallestMsgNo, highestInMsgNo);
boolean allComplete = false;
if(ackedMsgRanges!=null && ackedMsgRanges.isRangeCompleted(interestedRange)){
allComplete = true;
}
return allComplete;
}
public static SandeshaPolicyBean getPropertyBean (AxisDescription axisDescription) throws SandeshaException {
Parameter parameter = axisDescription.getParameter(Sandesha2Constants.SANDESHA_PROPERTY_BEAN);
if (parameter==null)
throw new SandeshaException (SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.propertyBeanNotSet));
SandeshaPolicyBean propertyBean = (SandeshaPolicyBean) parameter.getValue();
if (propertyBean==null) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.policyBeanNotFound);
throw new SandeshaException (message);
}
return propertyBean;
}
public static String getSequenceIDFromRMMessage(RMMsgContext rmMessageContext) throws SandeshaException {
int messageType = rmMessageContext.getMessageType();
String sequenceID = null;
if (messageType == Sandesha2Constants.MessageTypes.APPLICATION) {
Sequence sequence = (Sequence) rmMessageContext.getMessagePart(Sandesha2Constants.MessageParts.SEQUENCE);
sequenceID = sequence.getIdentifier().getIdentifier();
} else if (messageType == Sandesha2Constants.MessageTypes.ACK) {
Iterator sequenceAckIter = rmMessageContext
.getMessageParts(Sandesha2Constants.MessageParts.SEQ_ACKNOWLEDGEMENT);
//In case of ack messages sequenceId is decided based on the sequenceId of the first
//sequence Ack. In other words Sandesha2 does not expect to receive two SequenceAcknowledgements
//of different RM specifications in the same incoming message.
SequenceAcknowledgement sequenceAcknowledgement = (SequenceAcknowledgement) sequenceAckIter.next();
sequenceID = sequenceAcknowledgement.getIdentifier().getIdentifier();
} else if (messageType == Sandesha2Constants.MessageTypes.ACK_REQUEST) {
Iterator ackRequestIter = rmMessageContext
.getMessageParts(Sandesha2Constants.MessageParts.ACK_REQUEST);
//In case of ack request messages sequenceId is decided based on the sequenceId of the first
//AckRequested.
AckRequested ackReq = (AckRequested) ackRequestIter.next();
sequenceID = ackReq.getIdentifier().getIdentifier();
} else if (messageType == Sandesha2Constants.MessageTypes.CLOSE_SEQUENCE) {
CloseSequence closeSequence = (CloseSequence) rmMessageContext
.getMessagePart(Sandesha2Constants.MessageParts.CLOSE_SEQUENCE);
sequenceID = closeSequence.getIdentifier().getIdentifier();
} else if (messageType == Sandesha2Constants.MessageTypes.CLOSE_SEQUENCE_RESPONSE) {
CloseSequenceResponse closeSequenceResponse = (CloseSequenceResponse) rmMessageContext
.getMessagePart(Sandesha2Constants.MessageParts.CLOSE_SEQUENCE_RESPONSE);
sequenceID = closeSequenceResponse.getIdentifier().getIdentifier();
}
// TODO complete for other message types
return sequenceID;
}
public static String getSequenceKeyFromInternalSequenceID(String internalSequenceID, String to){
if(to==null){
//sequenceKey is just the internalSequenceID
return internalSequenceID;
}
else{
//remove the prefix
int postPrefixStringIndex = internalSequenceID.indexOf(Sandesha2Constants.INTERNAL_SEQUENCE_PREFIX);
if(postPrefixStringIndex>=0){
String postPrefixString = internalSequenceID.substring(postPrefixStringIndex + Sandesha2Constants.INTERNAL_SEQUENCE_PREFIX.length());
//strip of the to epr and trailing and trailing ":"
String toEPRString = ":" + to + ":";
int indexOfToEPR = postPrefixString.indexOf(toEPRString);
if(indexOfToEPR>=0){
return postPrefixString.substring(indexOfToEPR + toEPRString.length());
}
}
}
return null; //could not find the sequenceKey
}
public static SecurityManager getSecurityManager(ConfigurationContext context) throws SandeshaException {
SecurityManager util = null;
AxisConfiguration config = context.getAxisConfiguration();
Parameter p = config.getParameter(Sandesha2Constants.SECURITY_MANAGER);
if(p != null) util = (SecurityManager) p.getValue();
if (util != null) return util;
try {
//Currently module policies are used to find the security impl. These cant be overriden
String securityManagerClassStr = getDefaultPropertyBean(context.getAxisConfiguration()).getSecurityManagerClass();
util = getSecurityManagerInstance(securityManagerClassStr,context);
p = new Parameter(Sandesha2Constants.SECURITY_MANAGER,util);
config.addParameter(p);
} catch(AxisFault e) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.cannotInitSecurityManager, e.toString());
throw new SandeshaException(message,e);
}
return util;
}
private static SecurityManager getSecurityManagerInstance (String className,ConfigurationContext context) throws SandeshaException {
try {
ClassLoader classLoader = null;
AxisConfiguration config = context.getAxisConfiguration();
Parameter classLoaderParam = config.getParameter(Sandesha2Constants.MODULE_CLASS_LOADER);
if(classLoaderParam != null) classLoader = (ClassLoader) classLoaderParam.getValue();
if (classLoader==null)
throw new SandeshaException (SandeshaMessageHelper.getMessage(SandeshaMessageKeys.classLoaderNotFound));
Class c = classLoader.loadClass(className);
Class configContextClass = context.getClass();
Constructor constructor = c.getConstructor(new Class[] { configContextClass });
Object obj = constructor.newInstance(new Object[] {context});
if (!(obj instanceof SecurityManager)) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.securityManagerMustImplement, className);
throw new SandeshaException(message);
}
return (SecurityManager) obj;
} catch (Exception e) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.cannotInitSecurityManager, e.toString());
throw new SandeshaException(message,e);
}
}
public static ContextManager getContextManager(ConfigurationContext context) throws SandeshaException {
ContextManager mgr = null;
AxisConfiguration config = context.getAxisConfiguration();
Parameter p = config.getParameter(Sandesha2Constants.CONTEXT_MANAGER);
if(p != null) mgr = (ContextManager) p.getValue();
if (mgr != null) return mgr;
try {
//Currently module policies are used to find the context impl. These cant be overriden
String securityManagerClassStr = getDefaultPropertyBean(context.getAxisConfiguration()).getContextManagerClass();
mgr = getContextManagerInstance(securityManagerClassStr,context);
p = new Parameter(Sandesha2Constants.CONTEXT_MANAGER,mgr);
config.addParameter(p);
} catch(AxisFault e) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.cannotInitContextManager, e.toString());
throw new SandeshaException(message,e);
}
return mgr;
}
private static ContextManager getContextManagerInstance(String className,ConfigurationContext context) throws SandeshaException {
try {
ClassLoader classLoader = null;
AxisConfiguration config = context.getAxisConfiguration();
Parameter classLoaderParam = config.getParameter(Sandesha2Constants.MODULE_CLASS_LOADER);
if(classLoaderParam != null) classLoader = (ClassLoader) classLoaderParam.getValue();
if (classLoader==null)
throw new SandeshaException (SandeshaMessageHelper.getMessage(SandeshaMessageKeys.classLoaderNotFound));
Class c = classLoader.loadClass(className);
Class configContextClass = context.getClass();
Constructor constructor = c.getConstructor(new Class[] { configContextClass });
Object obj = constructor.newInstance(new Object[] {context});
if (!(obj instanceof ContextManager)) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.contextManagerMustImplement, className);
throw new SandeshaException(message);
}
return (ContextManager) obj;
} catch (Exception e) {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.cannotInitContextManager, e.toString());
throw new SandeshaException(message,e);
}
}
public static boolean isWSRMAnonymous(String address) {
if (address!=null && address.startsWith(Sandesha2Constants.SPEC_2007_02.ANONYMOUS_URI_PREFIX))
return true;
else
return false;
}
public static void executeAndStore (RMMsgContext rmMsgContext, String storageKey) throws AxisFault {
if (log.isDebugEnabled())
log.debug("Enter: SandeshaUtil::executeAndStore, " + storageKey);
MessageContext msgContext = rmMsgContext.getMessageContext();
ConfigurationContext configurationContext = msgContext.getConfigurationContext();
SandeshaPolicyBean policy = getPropertyBean(msgContext.getAxisOperation());
if(policy.isUseMessageSerialization()) {
msgContext.setProperty(Sandesha2Constants.QUALIFIED_FOR_SENDING, Sandesha2Constants.VALUE_TRUE);
StorageManager store = getSandeshaStorageManager(configurationContext, configurationContext.getAxisConfiguration());
store.storeMessageContext(storageKey, msgContext);
} else {
// message will be stored in the Sandesha2TransportSender
msgContext.setProperty(Sandesha2Constants.MESSAGE_STORE_KEY, storageKey);
TransportOutDescription transportOut = msgContext.getTransportOut();
msgContext.setProperty(Sandesha2Constants.ORIGINAL_TRANSPORT_OUT_DESC, transportOut);
msgContext.setProperty(Sandesha2Constants.SET_SEND_TO_TRUE, Sandesha2Constants.VALUE_TRUE);
Sandesha2TransportOutDesc sandesha2TransportOutDesc = new Sandesha2TransportOutDesc();
msgContext.setTransportOut(sandesha2TransportOutDesc);
// sending the message once through Sandesha2TransportSender.
if (msgContext.isPaused())
AxisEngine.resumeSend(msgContext);
else {
//this invocation has to be a blocking one.
Boolean isTransportNonBlocking = (Boolean) msgContext.getProperty(MessageContext.TRANSPORT_NON_BLOCKING);
if (isTransportNonBlocking!=null && isTransportNonBlocking.booleanValue())
msgContext.setProperty(MessageContext.TRANSPORT_NON_BLOCKING, Boolean.FALSE);
AxisEngine.send(msgContext);
msgContext.setProperty(MessageContext.TRANSPORT_NON_BLOCKING, isTransportNonBlocking);
}
}
if (log.isDebugEnabled())
log.debug("Exit: SandeshaUtil::executeAndStore");
}
public static void modifyExecutionChainForStoring (MessageContext message)
throws SandeshaException
{
Object property = message.getProperty(Sandesha2Constants.RETRANSMITTABLE_PHASES);
if (property!=null)
return; //Phases are already set. Dont hv to redo.
SandeshaPolicyBean policy = getPropertyBean(message.getAxisOperation());
if(policy.isUseMessageSerialization())
return; // No need to mess with the transport when we use message serialization
TransportOutDescription transportOutDescription = message.getTransportOut();
if (!(transportOutDescription instanceof Sandesha2TransportOutDesc))
return; //This message is aimed to be stored only if, Sandesha2TransportOutDescription is set.
ArrayList executionChain = message.getExecutionChain();
ArrayList retransmittablePhaseNames = getRetransmittablePhaseNameList();
ArrayList retransmittablePhases = new ArrayList ();
for (Iterator it=executionChain.iterator();it.hasNext();) {
Handler handler = (Handler) it.next();
if (retransmittablePhaseNames.contains(handler.getName())) {
retransmittablePhases.add(handler);
it.remove();
}
}
message.setProperty(Sandesha2Constants.RETRANSMITTABLE_PHASES, retransmittablePhases);
}
private static ArrayList getRetransmittablePhaseNameList () {
//TODO get this phase list from a property
String security = "Security";
ArrayList phases = new ArrayList ();
phases.add(security);
return phases;
}
public static MessageContext cloneMessageContext (MessageContext oldMsg) throws AxisFault {
MessageContext newMsg = new MessageContext ();
newMsg.setOptions(new Options (oldMsg.getOptions()));
//TODO hd to use following hack since a 'clone' method was not available for SOAPEnvelopes.
//Do it the correct way when that becomes available.
OMElement newElement = oldMsg.getEnvelope().cloneOMElement();
String elementString = newElement.toString();
try {
ByteArrayInputStream stream = new ByteArrayInputStream(
elementString.getBytes("UTF8"));
StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(
XMLInputFactory.newInstance().createXMLStreamReader(stream),
null);
SOAPEnvelope envelope = builder.getSOAPEnvelope();
newMsg.setEnvelope(envelope);
} catch (XMLStreamException e) {
throw AxisFault.makeFault(e);
} catch (UnsupportedEncodingException e) {
throw AxisFault.makeFault(e);
}
newMsg.setConfigurationContext(oldMsg.getConfigurationContext());
newMsg.setAxisService(oldMsg.getAxisService());
newMsg.setTransportOut(oldMsg.getTransportOut());
newMsg.setTransportIn(oldMsg.getTransportIn());
//Copy property objects from oldMsg to newMsg
copyConfiguredProperties(oldMsg,newMsg);
return newMsg;
}
/**
* Remove the MustUnderstand header blocks.
* @param envelope
*/
public static SOAPEnvelope removeMustUnderstand(SOAPEnvelope envelope) {
if (log.isDebugEnabled())
log.debug("Enter: SandeshaUtil::removeMustUnderstand");
// you have to explicitely set the 'processed' attribute for header
// blocks, since it get lost in the above read from the stream.
SOAPHeader header = envelope.getHeader();
if (header != null) {
Iterator childrenOfOldEnv = header.getChildElements();
while (childrenOfOldEnv.hasNext()) {
SOAPHeaderBlock oldEnvHeaderBlock = (SOAPHeaderBlock) childrenOfOldEnv.next();
QName oldEnvHeaderBlockQName = oldEnvHeaderBlock.getQName();
if (oldEnvHeaderBlockQName != null) {
// If we've processed the part and it has a must understand, set it as processed
if (oldEnvHeaderBlock.isProcessed() && oldEnvHeaderBlock.getMustUnderstand()) {
// Remove the MustUnderstand part
oldEnvHeaderBlock.setMustUnderstand(false);
}
}
}
}
if (log.isDebugEnabled())
log.debug("Exit: SandeshaUtil::removeMustUnderstand");
return envelope;
}
public static EndpointReference cloneEPR (EndpointReference epr) {
EndpointReference newEPR = new EndpointReference (epr.getAddress());
Map referenceParams = epr.getAllReferenceParameters();
if (referenceParams != null) {
for (Iterator keys = referenceParams.keySet().iterator(); keys
.hasNext();) {
Object key = keys.next();
Object referenceParam = referenceParams.get(key);
if (referenceParam instanceof OMElement) {
OMElement clonedElement = ((OMElement) referenceParam)
.cloneOMElement();
clonedElement.setText("false");
newEPR.addReferenceParameter(clonedElement);
}
}
}
return newEPR;
}
public static boolean isMessageUnreliable(MessageContext mc) {
if(log.isDebugEnabled()) log.debug("Entry: SandeshaUtil::isMessageUnreliable");
boolean result = false;
//look at the msg ctx first
String unreliable = (String) mc.getProperty(SandeshaClientConstants.UNRELIABLE_MESSAGE);
if ("true".equals(unreliable)) {
if (log.isDebugEnabled()) log.debug("Unreliable message context");
result = true;
}
if(!result) {
//look at the operation
if (mc.getAxisOperation() != null) {
Parameter unreliableParam = mc.getAxisOperation().getParameter(SandeshaClientConstants.UNRELIABLE_MESSAGE);
if (null != unreliableParam && "true".equals(unreliableParam.getValue())) {
if (log.isDebugEnabled()) log.debug("Unreliable operation");
result = true;
}
}
}
if(log.isDebugEnabled()) log.debug("Exit: SandeshaUtil::isMessageUnreliable, " + result);
return result;
}
public static boolean isDuplicateInOnlyMessage(MessageContext msgContext)
{
AxisOperation operation = msgContext.getAxisOperation();
String localName = operation.getName().getLocalPart();
if(localName.equals(Sandesha2Constants.RM_DUPLICATE_IN_ONLY_OPERATION.getLocalPart())){
return true;
}
else return false;
}
public static boolean isDuplicateInOutMessage(MessageContext msgContext)
{
AxisOperation operation = msgContext.getAxisOperation();
String localName = operation.getName().getLocalPart();
if(localName.equals(Sandesha2Constants.RM_DUPLICATE_IN_OUT_OPERATION.getLocalPart())){
return true;
}
else return false;
}
public static SOAPEnvelope cloneEnvelope(SOAPEnvelope envelope) throws SandeshaException {
// Now clone the env and set it in the message context
XMLStreamReader streamReader = envelope.cloneOMElement().getXMLStreamReader();
SOAPEnvelope clonedEnvelope = new StAXSOAPModelBuilder(streamReader, null).getSOAPEnvelope();
// you have to explicitely set the 'processed' attribute for header
// blocks, since it get lost in the above read from the stream.
SOAPHeader header = envelope.getHeader();
if (header != null) {
Iterator childrenOfOldEnv = header.getChildElements();
Iterator childrenOfNewEnv = clonedEnvelope.getHeader().getChildElements();
while (childrenOfOldEnv.hasNext()) {
SOAPHeaderBlock oldEnvHeaderBlock = (SOAPHeaderBlock) childrenOfOldEnv.next();
SOAPHeaderBlock newEnvHeaderBlock = (SOAPHeaderBlock) childrenOfNewEnv.next();
QName oldEnvHeaderBlockQName = oldEnvHeaderBlock.getQName();
if (oldEnvHeaderBlockQName != null) {
if (oldEnvHeaderBlockQName.equals(newEnvHeaderBlock.getQName())) {
if (oldEnvHeaderBlock.isProcessed())
newEnvHeaderBlock.setProcessed();
} else {
String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.cloneDoesNotMatchToOriginal);
throw new SandeshaException(message);
}
}
}
}
return clonedEnvelope;
}
public static final String getStackTraceFromException(Exception e) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(baos);
e.printStackTrace(pw);
pw.flush();
String stackTrace = baos.toString();
return stackTrace;
}
public static EndpointReference rewriteEPR(RMSBean sourceBean, EndpointReference epr, ConfigurationContext configContext)
throws SandeshaException
{
if (log.isDebugEnabled())
log.debug("Enter: SandeshaUtil::rewriteEPR " + epr);
SandeshaPolicyBean policy = SandeshaUtil.getPropertyBean(configContext.getAxisConfiguration());
if(!policy.isEnableRMAnonURI()) {
if (log.isDebugEnabled())
log.debug("Exit: SandeshaUtil::rewriteEPR, anon uri is disabled");
return epr;
}
// Handle EPRs that have not yet been set. These are effectively WS-A anon, and therefore
// we can rewrite them.
if(epr == null) epr = new EndpointReference(null);
String address = epr.getAddress();
if(address == null ||
AddressingConstants.Final.WSA_ANONYMOUS_URL.equals(address) ||
AddressingConstants.Submission.WSA_ANONYMOUS_URL.equals(address)) {
// We use the sequence to hold the anonymous uuid, so that messages assigned to the
// sequence will use the same UUID to identify themselves
String uuid = sourceBean.getAnonymousUUID();
if(uuid == null) {
uuid = Sandesha2Constants.SPEC_2007_02.ANONYMOUS_URI_PREFIX + SandeshaUtil.getUUID();
sourceBean.setAnonymousUUID(uuid);
}
if(log.isDebugEnabled()) log.debug("Rewriting EPR with anon URI " + uuid);
epr.setAddress(uuid);
}
if (log.isDebugEnabled())
log.debug("Exit: SandeshaUtil::rewriteEPR " + epr);
return epr;
}
}