/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.axis2.util;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.util.UUIDGenerator;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPConstants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPFault;
import org.apache.axiom.soap.SOAPFaultCode;
import org.apache.axiom.soap.SOAPFaultDetail;
import org.apache.axiom.soap.SOAPFaultReason;
import org.apache.axiom.soap.SOAPFaultSubCode;
import org.apache.axiom.soap.SOAPFaultValue;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axiom.soap.SOAPProcessingException;
import org.apache.axiom.soap.SOAPFaultNode;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.AddressingConstants.Final;
import org.apache.axis2.addressing.AddressingHelper;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.addressing.RelatesTo;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.description.*;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.List;

public class MessageContextBuilder {
	
	protected static final Log log = LogFactory.getLog(MessageContextBuilder.class);

    /**
     * Creates a new 'response' message context based on a 'request' message context
     * Only deals with properties/fields that are the same for both 'normal' and fault responses.
     */
    private static MessageContext createResponseMessageContext(MessageContext inMessageContext)
            throws AxisFault {
        MessageContext newmsgCtx =
                inMessageContext.getConfigurationContext().createMessageContext();

        newmsgCtx.setSessionContext(inMessageContext.getSessionContext());
        newmsgCtx.setTransportIn(inMessageContext.getTransportIn());
        newmsgCtx.setTransportOut(inMessageContext.getTransportOut());
        newmsgCtx.setServerSide(inMessageContext.isServerSide());

        // TODO: Should this be specifying (or defaulting to) the "response" relationshipType??
        newmsgCtx.addRelatesTo(new RelatesTo(inMessageContext.getOptions().getMessageId()));

        newmsgCtx.setProperty(AddressingConstants.WS_ADDRESSING_VERSION,
                              inMessageContext.getProperty(
                                      AddressingConstants.WS_ADDRESSING_VERSION));
        newmsgCtx.setProperty(AddressingConstants.DISABLE_ADDRESSING_FOR_OUT_MESSAGES,
                              inMessageContext.getProperty(
                                      AddressingConstants.DISABLE_ADDRESSING_FOR_OUT_MESSAGES));

        newmsgCtx.setProperty(WSDL2Constants.ENDPOINT_LOCAL_NAME,
                              inMessageContext.getProperty(WSDL2Constants.ENDPOINT_LOCAL_NAME));
        newmsgCtx.setProperty(Constants.AXIS_BINDING_OPERATION,
                              inMessageContext.getProperty(Constants.AXIS_BINDING_OPERATION));

        // Setting the charater set encoding
        newmsgCtx.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING,
                              inMessageContext.getProperty(
                                      Constants.Configuration.CHARACTER_SET_ENCODING));
        //Setting the message type property
        newmsgCtx.setProperty(Constants.Configuration.MESSAGE_TYPE,
                              inMessageContext.getProperty(Constants.Configuration.MESSAGE_TYPE));
        newmsgCtx.setDoingREST(inMessageContext.isDoingREST());

        newmsgCtx.setOperationContext(inMessageContext.getOperationContext());

        newmsgCtx.setProperty(MessageContext.TRANSPORT_OUT,
                              inMessageContext.getProperty(MessageContext.TRANSPORT_OUT));
        newmsgCtx.setProperty(Constants.OUT_TRANSPORT_INFO,
                              inMessageContext.getProperty(Constants.OUT_TRANSPORT_INFO));

        handleCorrelationID(inMessageContext,newmsgCtx);
        return newmsgCtx;
    }

    /**
     * Creates a MessageContext for use with a non-fault response based on an request MessageContext
     */
    public static MessageContext createOutMessageContext(MessageContext inMessageContext)
            throws AxisFault {

        // Create a basic response MessageContext with basic fields copied
        MessageContext newmsgCtx = createResponseMessageContext(inMessageContext);

        // Simple response so set To to value of inbound ReplyTo
        newmsgCtx.setTo(inMessageContext.getReplyTo());
        if (newmsgCtx.getTo() == null) {
            newmsgCtx.setTo(new EndpointReference(AddressingConstants.Final.WSA_ANONYMOUS_URL));
        }

        // do Target Resolution
        TargetResolver targetResolver =
                newmsgCtx.getConfigurationContext().getAxisConfiguration().getTargetResolverChain();
        if (targetResolver != null) {
            targetResolver.resolveTarget(newmsgCtx);
        }

        // Determine ReplyTo for response message.
        AxisService axisService = inMessageContext.getAxisService();
        if (axisService != null && Constants.SCOPE_SOAP_SESSION.equals(axisService.getScope())) {
            //If the wsa 2004/08 (submission) spec is in effect use the wsa anonymous URI as the default replyTo value.
            //This is necessary because the wsa none URI is not available in that spec.
            Object version = inMessageContext.getProperty(AddressingConstants.WS_ADDRESSING_VERSION);
            if (AddressingConstants.Submission.WSA_NAMESPACE.equals(version)) {
                newmsgCtx.setReplyTo(
                        new EndpointReference(AddressingConstants.Submission.WSA_ANONYMOUS_URL));
            } else {
                newmsgCtx.setReplyTo(new EndpointReference(AddressingConstants.Final.WSA_NONE_URI));
            }

            newmsgCtx.setMessageID(UUIDGenerator.getUUID());

            // add the service group id as a reference parameter
            String serviceGroupContextId = inMessageContext.getServiceGroupContextId();
            if (serviceGroupContextId != null && !"".equals(serviceGroupContextId)) {
                EndpointReference replyToEPR = newmsgCtx.getReplyTo();
                replyToEPR.addReferenceParameter(new QName(Constants.AXIS2_NAMESPACE_URI,
                                                           Constants.SERVICE_GROUP_ID,
                                                           Constants.AXIS2_NAMESPACE_PREFIX),
                                                 serviceGroupContextId);
            }
        } else {
            EndpointReference outboundToEPR = newmsgCtx.getTo();
            Object version = newmsgCtx.getProperty(AddressingConstants.WS_ADDRESSING_VERSION);
            if (AddressingConstants.Submission.WSA_NAMESPACE.equals(version) ||
                (outboundToEPR != null && !outboundToEPR.hasAnonymousAddress())) {
                newmsgCtx.setMessageID(UUIDGenerator.getUUID());
                newmsgCtx.setReplyTo(new EndpointReference(AddressingConstants.Final.WSA_NONE_URI));
            }
        }

        // Set wsa:Action for response message
        // Use specified value if available
        AxisOperation ao = inMessageContext.getAxisOperation();
        if ((ao != null) && (ao.getOutputAction() != null)) {
            newmsgCtx.setWSAAction(ao.getOutputAction());
        } else { // If not, simply copy the request value. Almost always invalid.
            newmsgCtx.setWSAAction(inMessageContext.getWSAAction());
        }

        if (ao != null){
           newmsgCtx.setAxisMessage(ao.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE));
        }

        // setting the out bound binding message
        AxisBindingMessage inboundAxisBindingMessage
                = (AxisBindingMessage)inMessageContext.getProperty(Constants.AXIS_BINDING_MESSAGE);
        if (inboundAxisBindingMessage != null){
            AxisBindingOperation axisBindingOperation = inboundAxisBindingMessage.getAxisBindingOperation();
            newmsgCtx.setProperty(Constants.AXIS_BINDING_MESSAGE,
                    axisBindingOperation.getChild(WSDLConstants.MESSAGE_LABEL_OUT_VALUE));
        }

        newmsgCtx.setDoingMTOM(inMessageContext.isDoingMTOM());
        newmsgCtx.setDoingSwA(inMessageContext.isDoingSwA());
        newmsgCtx.setServiceGroupContextId(inMessageContext.getServiceGroupContextId());



        // Ensure transport settings match the scheme for the To EPR
        setupCorrectTransportOut(newmsgCtx);
        return newmsgCtx;
    }

    /**
     * Copies the correlation id (jms) from the in message ctx
     * to the out message ctx. Currently this check is for jms 
     * only, but can be expanded to other transports if the need
     * arises.
     */
    private static void handleCorrelationID(MessageContext inMessageContext,MessageContext outMessageContext)    
    {
    	if (inMessageContext.getIncomingTransportName()!= null &&
    	    inMessageContext.getIncomingTransportName().equals(Constants.TRANSPORT_JMS))
    	{
    		log.debug("Incoming Transport is JMS, lets check for JMS correlation id");
    		
	    	String correlationId =
	            (String) inMessageContext.getProperty(Constants.JMS_COORELATION_ID);
	    	log.debug("Correlation id is " + correlationId);
	        if (correlationId != null && correlationId.length() > 0) {
	        	outMessageContext.setProperty(Constants.JMS_COORELATION_ID, correlationId);
	        }
    	}
    }

    /**
     * This method is called to handle any error that occurs at inflow or outflow. But if the
     * method is called twice, it implies that sending the error handling has failed, in which case
     * the method logs the error and exits.
     */
    public static MessageContext createFaultMessageContext(MessageContext processingContext,
                                                           Throwable e)
            throws AxisFault {
        if (processingContext.isProcessingFault()) {
            // We get the error file processing the fault. nothing we can do
            throw new AxisFault(Messages.getMessage("errorwhileProcessingFault"));
        }

        // See if the throwable is an AxisFault and if it already contains the
        // fault MessageContext
        if (e instanceof AxisFault) {
            MessageContext faultMessageContext = ((AxisFault) e).getFaultMessageContext();
            if (faultMessageContext != null) {
                // These may not have been set correctly when the original context
                // was created -- an example of this is with the SimpleHTTPServer.
                // I'm not sure if this is the correct thing to do, or if the
                // code that created this context in the first place should
                // expect that the transport out info was set correctly, as
                // it may need to use that info at some point before we get to
                // this code.
                faultMessageContext.setProperty(MessageContext.TRANSPORT_OUT,
                                                processingContext.getProperty(
                                                        MessageContext.TRANSPORT_OUT));
                faultMessageContext.setProperty(Constants.OUT_TRANSPORT_INFO,
                                                processingContext.getProperty(
                                                        Constants.OUT_TRANSPORT_INFO));
                faultMessageContext.setProcessingFault(true);
                return faultMessageContext;
            }
        }

        // Create a basic response MessageContext with basic fields copied
        MessageContext faultContext = createResponseMessageContext(processingContext);

        // Register the fault message context
        OperationContext operationContext = processingContext.getOperationContext();
        if (operationContext != null) {
            processingContext.getAxisOperation().addFaultMessageContext(faultContext,
                                                                        operationContext);
        }

        faultContext.setProcessingFault(true);

        // Set wsa:Action for response message
        
        // Use specified value if available

        String faultAction = (e instanceof AxisFault) ? ((AxisFault)e).getFaultAction() : null;

        if (faultAction == null) {
            AxisOperation op = processingContext.getAxisOperation();
            if (op != null && op.getFaultAction() != null) {
                // TODO: Should the op be able to pick a fault action based on the fault?
                faultAction = op.getFaultAction();
            } else { //If, for some reason there is no value set, should use a sensible action.
                faultAction = Final.WSA_SOAP_FAULT_ACTION;
            }
        }

        faultContext.setWSAAction(faultAction);

        // there are some information  that the fault thrower wants to pass to the fault path.
        // Means that the fault is a ws-addressing one hence use the ws-addressing fault action.
        Object faultInfoForHeaders =
                processingContext.getLocalProperty(Constants.FAULT_INFORMATION_FOR_HEADERS);
        if (faultInfoForHeaders != null) {
            faultContext.setProperty(Constants.FAULT_INFORMATION_FOR_HEADERS, faultInfoForHeaders);

            // Note that this overrides any action set above
            faultContext.setWSAAction(Final.WSA_FAULT_ACTION);
        }

        // if the exception is due to a problem in the faultTo header itself, we can not use that
        // fault information to send the error. Try to send using replyTo, else leave it to transport
        boolean shouldSendFaultToFaultTo =
                AddressingHelper.shouldSendFaultToFaultTo(processingContext);
        EndpointReference faultTo = processingContext.getFaultTo();
        if (faultTo != null && shouldSendFaultToFaultTo) {
            faultContext.setTo(faultTo);
        } else {
            faultContext.setTo(processingContext.getReplyTo());
        }

        if (faultContext.getTo() == null) {
            faultContext.setTo(new EndpointReference(AddressingConstants.Final.WSA_ANONYMOUS_URL));
        }

        // Not worth setting up the session information on a fault flow
        EndpointReference outboundToEPR = faultContext.getTo();
        Object version = faultContext.getProperty(AddressingConstants.WS_ADDRESSING_VERSION);
        if (AddressingConstants.Submission.WSA_NAMESPACE.equals(version) ||
            (outboundToEPR != null && !outboundToEPR.hasAnonymousAddress())) {
            faultContext.setMessageID(UUIDGenerator.getUUID());
            faultContext.setReplyTo(new EndpointReference(AddressingConstants.Final.WSA_NONE_URI));
        }

        // do Target Resolution
        TargetResolver targetResolver = faultContext.getConfigurationContext()
                .getAxisConfiguration().getTargetResolverChain();
        if (targetResolver != null) {
            targetResolver.resolveTarget(faultContext);
        }

        // Ensure transport settings match the scheme for the To EPR
        setupCorrectTransportOut(faultContext);

        SOAPEnvelope envelope = createFaultEnvelope(processingContext, e);
        faultContext.setEnvelope(envelope);

        //get the SOAP headers, user is trying to send in the fault
        // TODO: Rationalize this mechanism a bit - maybe headers should live in the fault?
        List soapHeadersList =
                (List) processingContext.getProperty(SOAPConstants.HEADER_LOCAL_NAME);
        if (soapHeadersList != null) {
            SOAPHeader soapHeaderElement = envelope.getHeader();
            for (Object aSoapHeadersList : soapHeadersList) {
                OMElement soapHeaderBlock = (OMElement)aSoapHeadersList;
                soapHeaderElement.addChild(soapHeaderBlock);
            }
        }

        // TODO: Transport-specific stuff in here?  Why?  Is there a better way?
        // now add HTTP Headers
        faultContext.setProperty(HTTPConstants.HTTP_HEADERS,
                                 processingContext.getProperty(HTTPConstants.HTTP_HEADERS));

        return faultContext;
    }

    /**
     * Ensure that if the scheme of the To EPR for the response is different than the
     * transport used for the request that the correct TransportOut is available
     */
    private static void setupCorrectTransportOut(MessageContext context) throws AxisFault {
        // Determine that we have the correct transport available.
        TransportOutDescription transportOut = context.getTransportOut();

        try {
            EndpointReference responseEPR = context.getTo();
            if (context.isServerSide() && responseEPR != null) {
                if (!responseEPR.hasAnonymousAddress() && !responseEPR.hasNoneAddress()) {
                    URI uri = new URI(responseEPR.getAddress());
                    String scheme = uri.getScheme();
                    if ((transportOut == null) || !transportOut.getName().equals(scheme)) {
                        ConfigurationContext configurationContext =
                                context.getConfigurationContext();
                        transportOut = configurationContext.getAxisConfiguration()
                                .getTransportOut(scheme);
                        if (transportOut == null) {
                            throw new AxisFault("Can not find the transport sender : " + scheme);
                        }
                        context.setTransportOut(transportOut);
                    }
                    if (context.getOperationContext() != null) {
                        context.getOperationContext().setProperty(
                                Constants.DIFFERENT_EPR, Constants.VALUE_TRUE);
                    }
                }
            }
        } catch (URISyntaxException urise) {
            throw AxisFault.makeFault(urise);
        }
    }

    /**
     * Information to create the SOAPFault can be extracted from different places.
     * 1. Those information may have been put in to the message context by some handler. When someone
     * is putting like that, he must make sure the SOAPElements he is putting must be from the
     * correct SOAP Version.
     * 2. SOAPProcessingException is flexible enough to carry information about the fault. For example
     * it has an attribute to store the fault code. The fault reason can be extracted from the
     * message of the exception. I opted to put the stacktrace under the detail element.
     * eg : <Detail>
     * <Exception> stack trace goes here </Exception>
     * <Detail>
     * <p/>
     * If those information can not be extracted from any of the above places, I default the soap
     * fault values to following.
     * <Fault>
     * <Code>
     * <Value>env:Receiver</Value>
     * </Code>
     * <Reason>
     * <Text>unknown</Text>
     * </Reason>
     * <Role/>
     * <Node/>
     * <Detail/>
     * </Fault>
     * <p/>
     * -- EC
     *
     * @param context
     * @param e
     */
    private static SOAPEnvelope createFaultEnvelope(MessageContext context, Throwable e) {
        SOAPEnvelope envelope;

        if (context.isSOAP11()) {
            envelope = OMAbstractFactory.getSOAP11Factory().getDefaultFaultEnvelope();
        } else {
            // Following will make SOAP 1.2 as the default, too.
            envelope = OMAbstractFactory.getSOAP12Factory().getDefaultFaultEnvelope();
        }
        SOAPFault fault = envelope.getBody().getFault();

        SOAPProcessingException soapException = null;
        AxisFault axisFault = null;

        if (e == null) return envelope;

        if (e instanceof AxisFault) {
            axisFault = (AxisFault) e;
        } else if (e.getCause() instanceof AxisFault) {
            axisFault = (AxisFault) e.getCause();
        }

        if (axisFault != null) {
            Iterator iter = axisFault.headerIterator();
            while (iter.hasNext()) {
                SOAPHeaderBlock header = (SOAPHeaderBlock) iter.next();
                envelope.getHeader().addChild(header);
            }
        }

        if (e instanceof SOAPProcessingException) {
            soapException = (SOAPProcessingException) e;
        } else if (axisFault != null) {
            if (axisFault.getCause() instanceof SOAPProcessingException) {
                soapException = (SOAPProcessingException) axisFault.getCause();
            }
        }

        // user can set the fault information to the message context or to the AxisFault itself.
        // whatever user sets to the message context, supercedes eerything.
        
        Object faultCode = context.getProperty(SOAP12Constants.SOAP_FAULT_CODE_LOCAL_NAME);
        String soapFaultCode = "";

        if (faultCode != null) {
            fault.setCode((SOAPFaultCode) faultCode);
        } else if (soapException != null) {
            soapFaultCode = soapException.getFaultCode();
        } else if (axisFault != null) {
            if (axisFault.getFaultCodeElement() != null) {
                fault.setCode(axisFault.getFaultCodeElement());
            } else {
                QName faultCodeQName = axisFault.getFaultCode();
                if (faultCodeQName != null) {
                    if (faultCodeQName.getLocalPart().indexOf(":") == -1) {
                        String prefix = faultCodeQName.getPrefix();
                        String uri = faultCodeQName.getNamespaceURI();
                        // Get the specified prefix and uri
                        prefix = prefix == null ? "" : prefix;
                        uri = uri == null || "" .equals(uri) ?
                                fault.getNamespace().getNamespaceURI() : uri;
                        // Make sure the prefix and uri are declared on the fault, and 
                        // get the resulting prefix.
                        prefix = fault.declareNamespace(uri, prefix).getPrefix();
                        soapFaultCode = prefix + ":" + faultCodeQName.getLocalPart();
                    } else {
                        soapFaultCode = faultCodeQName.getLocalPart();
                    }
                }
            }
        }

        // defaulting to fault code Receiver, if no message is available
        if (faultCode == null && context.getEnvelope() != null) {
            soapFaultCode = ("".equals(soapFaultCode) || (soapFaultCode == null))
                    ? SOAP12Constants.SOAP_DEFAULT_NAMESPACE_PREFIX + ":" +
                        context.getEnvelope().getVersion().getReceiverFaultCode().getLocalPart()
                    : soapFaultCode;
        }
        
        if (faultCode == null) {
            if (context.isSOAP11()) {
                fault.getCode().setText(soapFaultCode);
            } else {
                fault.getCode().getValue().setText(soapFaultCode);
            }
        }
        
        if (axisFault != null && !context.isSOAP11()) {
            if (axisFault.getFaultSubCodes() != null) {
                
                List faultSubCodes = axisFault.getFaultSubCodes();
                
                QName faultSubCodeQName;

                for (Object faultSubCode : faultSubCodes) {

                    faultSubCodeQName = (QName)faultSubCode;

                    SOAPFactory sf = (SOAPFactory)envelope.getOMFactory();
                    SOAPFaultSubCode soapFaultSubCode = sf.createSOAPFaultSubCode(fault.getCode());
                    SOAPFaultValue saopFaultValue = sf.createSOAPFaultValue(fault.getCode());
                    saopFaultValue.setText(faultSubCodeQName);
                    soapFaultSubCode.setValue(saopFaultValue);
                    fault.getCode().setSubCode(soapFaultSubCode);
                }
                
            } 
        }

        SOAPFaultReason faultReason = (SOAPFaultReason)context.getProperty(
                                            SOAP12Constants.SOAP_FAULT_REASON_LOCAL_NAME);

        if (faultReason == null && axisFault != null) {
            faultReason = axisFault.getFaultReasonElement();
        }
        if (faultReason != null) {
            fault.setReason(faultReason);
        } else {
            String message = "";
            if (soapException != null) {
                message = soapException.getMessage();
            } else if (axisFault != null) {
                // Couldn't find FaultReasonElement, try reason string
                message = axisFault.getReason();
            }

            if (message == null || "".equals(message)) {
                message = getFaultReasonFromException(e, context);
            }

            if (message == null || "".equals(message)) message = "unknown";

            if (context.isSOAP11()) {
                fault.getReason().setText(message);
            } else {
                fault.getReason().getFirstSOAPText().setLang("en-US");
                fault.getReason().getFirstSOAPText().setText(message);
            }
        }

        Object faultRole = context.getProperty(SOAP12Constants.SOAP_FAULT_ROLE_LOCAL_NAME);
        if (faultRole != null) {
            fault.getRole().setText((String) faultRole);
        } else if (axisFault != null) {
            if (axisFault.getFaultRoleElement() != null) {
                fault.setRole(axisFault.getFaultRoleElement());
            }
        }

        Object faultNode = context.getProperty(SOAP12Constants.SOAP_FAULT_NODE_LOCAL_NAME);
        if (faultNode != null) {
            SOAPFaultNode soapFaultNode = fault.getNode();
            if(soapFaultNode != null) {
                soapFaultNode.setText((String) faultNode);
            }
        } else if (axisFault != null) {
            if (axisFault.getFaultNodeElement() != null) {
                fault.setNode(axisFault.getFaultNodeElement());
            }
        }

        // Allow handlers to override the sendStacktraceDetailsWithFaults setting from the Configuration to allow
        // WS-* protocol faults to not include the exception.
        boolean sendStacktraceDetailsWithFaults = false;
        OperationContext oc = context.getOperationContext();
        Object flagFromContext = null;
        if (oc != null) {
            flagFromContext = context.getOperationContext()
                    .getProperty(Constants.Configuration.SEND_STACKTRACE_DETAILS_WITH_FAULTS);
        }
        if (flagFromContext != null) {
            sendStacktraceDetailsWithFaults = JavaUtils.isTrue(flagFromContext);
        } else {
            Parameter param = context.getParameter(
                    Constants.Configuration.SEND_STACKTRACE_DETAILS_WITH_FAULTS);
            if (param != null) {
                sendStacktraceDetailsWithFaults = JavaUtils.isTrue(param.getValue());
            }
        }

        Object faultDetail = context.getProperty(SOAP12Constants.SOAP_FAULT_DETAIL_LOCAL_NAME);
        if (faultDetail != null) {
            fault.setDetail((SOAPFaultDetail) faultDetail);
        } else if (axisFault != null) {
            if (axisFault.getFaultDetailElement() != null) {
                fault.setDetail(axisFault.getFaultDetailElement());
            } else {
                OMElement detail = axisFault.getDetail();
                if (detail != null) {
                    fault.getDetail().addDetailEntry(detail);
                } else if (sendStacktraceDetailsWithFaults) {
                    fault.setException(axisFault);
                }
            }
        } else if (fault.getException() == null && sendStacktraceDetailsWithFaults) {
            if (e instanceof Exception) {
                fault.setException((Exception) e);
            } else {
                fault.setException(new Exception(e));
            }
        }

        return envelope;
    }

    /**
     * By the time the exception comes here it can be wrapped by so many levels. This will crip down
     * to the root cause and get the initial error depending on the property
     *
     * @param e
     */
    private static String getFaultReasonFromException(Throwable e, MessageContext context) {
        Throwable throwable = e;
        Parameter param = context.getParameter(
                Constants.Configuration.DRILL_DOWN_TO_ROOT_CAUSE_FOR_FAULT_REASON);
        boolean drillDownToRootCauseForFaultReason =
                param != null && ((String) param.getValue()).equalsIgnoreCase("true");
        if (drillDownToRootCauseForFaultReason) {
            while (throwable.getCause() != null) {
                throwable = throwable.getCause();
            }
        }
        return throwable.getMessage();
    }

    private static String getSenderFaultCode(OMNamespace soapNamespace) {
        return SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapNamespace.getNamespaceURI())
                ? SOAP12Constants.SOAP_DEFAULT_NAMESPACE_PREFIX + ":"
                + SOAP12Constants.FAULT_CODE_SENDER
                : SOAP12Constants.SOAP_DEFAULT_NAMESPACE_PREFIX + ":"
                + SOAP11Constants.FAULT_CODE_SENDER;
    }
}
