/*
 * 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.handlers.addressing;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.RolePlayer;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.AddressingFaultsHelper;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.addressing.EndpointReferenceHelper;
import org.apache.axis2.addressing.RelatesTo;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.HandlerDescription;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.LoggingControl;
import org.apache.axis2.util.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Iterator;

public class AddressingInHandler extends AbstractHandler implements AddressingConstants {

    private static final int TO_FLAG = 1, FROM_FLAG = 2, REPLYTO_FLAG = 3,
            FAULTO_FLAG = 4, MESSAGEID_FLAG = 6, ACTION_FLAG = 0;

    private static final Log log = LogFactory.getLog(AddressingInHandler.class);

    private boolean disableRefparamExtract = false;
    private AxisConfiguration configuration = null;
    private RolePlayer rolePlayer = null;
    
    public void init(HandlerDescription handlerdesc){
    	super.init(handlerdesc);
    	// check whether to process reference parameters.
        Parameter param = handlerdesc.getParameter(DISABLE_REF_PARAMETER_EXTRACT);
        String value = Utils.getParameterValue(param);
        disableRefparamExtract = JavaUtils.isTrueExplicitly(value);

        if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
            log.debug("disableRefparamExtract=" + disableRefparamExtract);
        }
    }
    
    public InvocationResponse invoke(MessageContext msgContext) throws AxisFault {
        //Set the defaults on the message context.
        msgContext.setProperty(DISABLE_ADDRESSING_FOR_OUT_MESSAGES, Boolean.TRUE);
        msgContext.setProperty(IS_ADDR_INFO_ALREADY_PROCESSED, Boolean.FALSE);

        //Determine if we want to ignore addressing headers. This parameter must
        //be retrieved from the message context because it's value can vary on a
        //per service basis.
        Parameter disableParam = msgContext.getParameter(DISABLE_ADDRESSING_FOR_IN_MESSAGES);
        String value = Utils.getParameterValue(disableParam);
        if (JavaUtils.isTrueExplicitly(value)) {
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
                log.debug(
                        "The AddressingInHandler has been disabled. No further processing will take place.");
            }
            return InvocationResponse.CONTINUE;         
        }

        // if there are not headers put a flag to disable addressing temporary
        SOAPHeader header = msgContext.getEnvelope().getHeader();
        if (header == null) {
            return InvocationResponse.CONTINUE;
        }

        if(configuration == null){
        	AxisConfiguration conf = msgContext.getConfigurationContext().getAxisConfiguration();
        	rolePlayer = (RolePlayer)conf.getParameterValue(Constants.SOAP_ROLE_PLAYER_PARAMETER);
        	configuration = conf;
        }
        
        // check whether another handler has explicitly set which addressing namespace to expect.
        Iterator iterator = null;
        String namespace = (String) msgContext.getProperty(WS_ADDRESSING_VERSION);
        
        // check whether the service is configured to use a particular version of WS-Addressing,
        // e.g. via JAX-WS annotations.
        if (namespace == null) {
            Parameter namespaceParam = msgContext.getParameter(WS_ADDRESSING_VERSION);
            namespace = Utils.getParameterValue(namespaceParam);
        }
        
        if (namespace == null) {
            namespace = Final.WSA_NAMESPACE;
            iterator = header.getHeadersToProcess(rolePlayer, namespace);

            if (!iterator.hasNext()) {
                if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
                    log.debug("No headers present corresponding to " + namespace);
                }

                namespace = Submission.WSA_NAMESPACE;
                iterator = header.getHeadersToProcess(rolePlayer, namespace);
            }
        }
        else if (Final.WSA_NAMESPACE.equals(namespace) || Submission.WSA_NAMESPACE.equals(namespace)) {
            iterator = header.getHeadersToProcess(rolePlayer, namespace);
            
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
                log.debug("The preconfigured namespace is, , " + namespace);
            }            
        }
        else {
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
                log.debug("The specified namespace is not supported by this handler, " + namespace);
            }            

            return InvocationResponse.CONTINUE;
        }

        if (iterator.hasNext()) {
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
                log.debug(namespace +
                          " headers present in the SOAP message. Starting to process ...");
            }

            //Need to set these properties here, before we extract the WS-Addressing
            //information, in case we throw a fault.
            msgContext.setProperty(WS_ADDRESSING_VERSION, namespace);
            msgContext.setProperty(DISABLE_ADDRESSING_FOR_OUT_MESSAGES, Boolean.FALSE);
            
            extractAddressingInformation(msgContext, iterator, namespace);
            
            // check for reference parameters
            if (!disableRefparamExtract) {
                extractToEprReferenceParameters(msgContext.getTo(), header, namespace);
            }
            
            //We should only get to this point if we haven't thrown a fault.
            msgContext.setProperty(IS_ADDR_INFO_ALREADY_PROCESSED, Boolean.TRUE);
        }
        else {
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
                log.debug("No headers present corresponding to " + namespace);
            }
        }

        return InvocationResponse.CONTINUE;
    }

    /**
     * Pull addressing headers out from the SOAP message.
     *
     * @param messageContext the active MessageContext
     * @param headers an Iterator over the addressing headers targeted to me
     * @param namespace the addressing namespace
     * @throws AxisFault if an error occurs
     */
    private void extractAddressingInformation(MessageContext messageContext, Iterator headers,
                                         String namespace)
            throws AxisFault {
        Options messageContextOptions = messageContext.getOptions();

        ArrayList duplicateHeaderNames = new ArrayList(1); // Normally will not be used for more than 1 header

        ArrayList relatesToHeaders = null;
        SOAPHeaderBlock actionBlock = null, toBlock = null, messageIDBlock = null, replyToBlock =
                null, faultToBlock = null, fromBlock = null;

        // Per the SOAP Binding spec "headers with an incorrect cardinality MUST NOT be used" So these variables
        // are used to keep track of invalid cardinality headers so they are not deserialised.
        boolean[] ignoreHeaders = new boolean[7];
        boolean[] checkedHeaderNames = new boolean[7];

        // First pass just check for duplicates
        while (headers.hasNext()) {
            SOAPHeaderBlock soapHeaderBlock = (SOAPHeaderBlock)headers.next();
            String localName = soapHeaderBlock.getLocalName();
            if (WSA_ACTION.equals(localName)) {
                actionBlock = soapHeaderBlock;
                checkDuplicateHeaders(WSA_ACTION, ACTION_FLAG,
                                      checkedHeaderNames, ignoreHeaders,
                                      duplicateHeaderNames);
            } else if (WSA_TO.equals(localName)) {
                toBlock = soapHeaderBlock;
                checkDuplicateHeaders(WSA_TO, TO_FLAG, checkedHeaderNames, ignoreHeaders,
                                      duplicateHeaderNames);
            } else if (WSA_MESSAGE_ID.equals(localName)) {
                messageIDBlock = soapHeaderBlock;
                checkDuplicateHeaders(WSA_MESSAGE_ID, MESSAGEID_FLAG,
                                      checkedHeaderNames, ignoreHeaders,
                                      duplicateHeaderNames);
            } else if (WSA_REPLY_TO.equals(localName)) {
                replyToBlock = soapHeaderBlock;
                checkDuplicateHeaders(WSA_REPLY_TO, REPLYTO_FLAG,
                                      checkedHeaderNames, ignoreHeaders,
                                      duplicateHeaderNames);
            } else if (WSA_FAULT_TO.equals(localName)) {
                faultToBlock = soapHeaderBlock;
                checkDuplicateHeaders(WSA_FAULT_TO, FAULTO_FLAG,
                                      checkedHeaderNames, ignoreHeaders,
                                      duplicateHeaderNames);
            } else if (WSA_FROM.equals(localName)) {
                fromBlock = soapHeaderBlock;
                checkDuplicateHeaders(WSA_FROM, FROM_FLAG,
                                      checkedHeaderNames, ignoreHeaders,
                                      duplicateHeaderNames);
            } else if (WSA_RELATES_TO.equals(localName)) {
                if (relatesToHeaders == null) {
                    relatesToHeaders = new ArrayList(1);
                }
                relatesToHeaders.add(soapHeaderBlock);
            }
        }

        if (actionBlock != null && !ignoreHeaders[ACTION_FLAG]) {
            extractActionInformation(actionBlock, messageContext);
        }
        if (toBlock != null && !ignoreHeaders[TO_FLAG]) {
            extractToEPRInformation(toBlock,
                                    messageContextOptions,
                                    namespace);
        }
        if (messageIDBlock != null && !ignoreHeaders[MESSAGEID_FLAG]) {
            extractMessageIDInformation(messageIDBlock, messageContext);
        }
        if (relatesToHeaders != null) {
            for (int i = 0; i < relatesToHeaders.size(); i++) {
                extractRelatesToInformation((SOAPHeaderBlock) relatesToHeaders.get(i),
                                            messageContextOptions);
            }
        }
        if (replyToBlock != null && !ignoreHeaders[REPLYTO_FLAG]) {
            extractReplyToEPRInformation(replyToBlock, namespace, messageContext);
        }
        if (faultToBlock != null && !ignoreHeaders[FAULTO_FLAG]) {
            extractFaultToEPRInformation(faultToBlock, namespace, messageContext);
        }
        if (fromBlock != null && !ignoreHeaders[FROM_FLAG]) {
            extractFromEPRInformation(fromBlock, namespace, messageContext);
        }

        // Now that all the valid wsa headers have been read, throw an exception if there was an invalid cardinality
        // This means that if for example there are multiple MessageIDs and a FaultTo, the FaultTo will be respected.
        if (!duplicateHeaderNames.isEmpty()) {
            // Simply choose the first problem header we came across as we can only fault for one of them.
            AddressingFaultsHelper.triggerInvalidCardinalityFault(messageContext,
                                                                  (String) duplicateHeaderNames
                                                                          .get(0));
        }

        // check for the presence of madatory addressing headers
        checkForMandatoryHeaders(checkedHeaderNames, messageContext, namespace);

        // provide default values for headers that have not been found.
        setDefaults(checkedHeaderNames, messageContext, namespace);
    }

    private void checkForMandatoryHeaders(boolean[] alreadyFoundAddrHeader,
                                            MessageContext messageContext,
                                            String namespace) throws AxisFault {
        if (Final.WSA_NAMESPACE.equals(namespace)) {
            //Unable to validate the wsa:MessageID header here as we do not yet know which MEP
            //is in effect.
            // @see AddressingValidationHandler#checkMessageIDHeader
            
            if (!alreadyFoundAddrHeader[ACTION_FLAG]) {
                AddressingFaultsHelper
                .triggerMessageAddressingRequiredFault(messageContext, WSA_ACTION);
            }
        }
        else {
            if (!alreadyFoundAddrHeader[TO_FLAG]) {
                AddressingFaultsHelper.triggerMessageAddressingRequiredFault(messageContext, WSA_TO);
            }

            if (!alreadyFoundAddrHeader[ACTION_FLAG]) {
                AddressingFaultsHelper
                        .triggerMessageAddressingRequiredFault(messageContext, WSA_ACTION);
            }

            if (alreadyFoundAddrHeader[REPLYTO_FLAG] ||
                    alreadyFoundAddrHeader[FAULTO_FLAG]) {

                if (!alreadyFoundAddrHeader[MESSAGEID_FLAG]) {
                    AddressingFaultsHelper
                            .triggerMessageAddressingRequiredFault(messageContext, WSA_MESSAGE_ID);
                }
            }            
        }
    }

    private void setDefaults(boolean[] alreadyFoundAddrHeader, MessageContext messageContext, String namespace) {
        if (Final.WSA_NAMESPACE.equals(namespace)) {
            //According to the WS-Addressing spec, we should default the wsa:To header to the
            //anonymous URI. Doing that, however, might prevent a different value from being
            //used instead, such as the transport URL. Therefore, we only apply the default
            //on the inbound response side of a synchronous request-response exchange.
            if (!alreadyFoundAddrHeader[TO_FLAG] && !messageContext.isServerSide()) {
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(messageContext.getLogIDString() +
                    " setDefaults: Setting WS-Addressing default value for the To property.");
                }
                messageContext.setTo(new EndpointReference(Final.WSA_ANONYMOUS_URL));
            }
            
            if (!alreadyFoundAddrHeader[REPLYTO_FLAG]) {
                messageContext.setReplyTo(new EndpointReference(Final.WSA_ANONYMOUS_URL));
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(messageContext.getLogIDString() +
                    " setDefaults: Setting WS-Addressing default value for the ReplyTo property.");
                }
            }
        }
        else {
            //The none URI is not defined in the 2004/08 spec, but it is used here anyway
            //as a flag to indicate the correct semantics to apply, i.e. in the 2004/08 spec
            //the absence of a ReplyTo header indicates that a response is NOT required.
            if (!alreadyFoundAddrHeader[REPLYTO_FLAG]) {
                messageContext.setReplyTo(new EndpointReference(Final.WSA_NONE_URI));
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(
                            "setDefaults: Setting WS-Addressing default value for the ReplyTo property.");
                }
            }            
        }
    }

    private void checkDuplicateHeaders(String addressingHeaderName, int headerFlag,
                                       boolean[] checkedHeaderNames, boolean[] ignoreHeaders,
                                       ArrayList duplicateHeaderNames) {//throws AxisFault {
        // If the header name has been seen before then we should return true and add it to the list
        // of duplicate header names. Otherwise it is the first time we've seen the header so add it
        // to the checked liat and return false.
        ignoreHeaders[headerFlag] = checkedHeaderNames[headerFlag];
        if (ignoreHeaders[headerFlag]) {
            duplicateHeaderNames.add(addressingHeaderName);
        } else {
            checkedHeaderNames[headerFlag] = true;
        }

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace("checkDuplicateHeaders: addressingHeaderName=" + addressingHeaderName
                      + " isDuplicate=" + ignoreHeaders[headerFlag]);
        }
    }

    private void extractRelatesToInformation(SOAPHeaderBlock soapHeaderBlock,
                                             Options messageContextOptions) {
        String address = soapHeaderBlock.getText();

        // Extract the RelationshipType attribute if it exists
        OMAttribute relationshipType =
                soapHeaderBlock.getAttribute(
                        new QName(AddressingConstants.WSA_RELATES_TO_RELATIONSHIP_TYPE));

        String relationshipTypeString =
                relationshipType == null ? null : relationshipType.getAttributeValue();

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace("extractRelatesToInformation: Extracted Relationship. Value=" + address +
                      " RelationshipType=" + relationshipTypeString);
        }

        RelatesTo relatesTo = new RelatesTo(address, relationshipTypeString);

        ArrayList attributes = extractAttributesFromSOAPHeaderBlock(soapHeaderBlock);
        relatesTo.setExtensibilityAttributes(attributes);

        messageContextOptions.addRelatesTo(relatesTo);

        // Completed processing of this header
        soapHeaderBlock.setProcessed();
    }

    private void extractFaultToEPRInformation(SOAPHeaderBlock soapHeaderBlock,
                                              String addressingNamespace,
                                              MessageContext messageContext) throws AxisFault {
        Options messageContextOptions = messageContext.getOptions();
        EndpointReference epr = messageContextOptions.getFaultTo();
        if (epr == null) {
            epr = new EndpointReference("");
            messageContextOptions.setFaultTo(epr);
        }
        extractEPRInformation(soapHeaderBlock, epr, addressingNamespace, messageContext);
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace("extractFaultToEPRInformation: Extracted FaultTo EPR: " + epr);
        }
        soapHeaderBlock.setProcessed();
    }

    private void extractReplyToEPRInformation(SOAPHeaderBlock soapHeaderBlock,
                                              String addressingNamespace,
                                              MessageContext messageContext) throws AxisFault {
        Options messageContextOptions = messageContext.getOptions();
        EndpointReference epr = messageContextOptions.getReplyTo();
        if (epr == null) {
            epr = new EndpointReference("");
            messageContextOptions.setReplyTo(epr);
        }
        extractEPRInformation(soapHeaderBlock, epr, addressingNamespace, messageContext);
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace("extractReplyToEPRInformation: Extracted ReplyTo EPR: " + epr);
        }
        soapHeaderBlock.setProcessed();
    }

    private void extractFromEPRInformation(SOAPHeaderBlock soapHeaderBlock,
                                           String addressingNamespace,
                                           MessageContext messageContext) throws AxisFault {
        Options messageContextOptions = messageContext.getOptions();
        EndpointReference epr = messageContextOptions.getFrom();
        if (epr == null) {
            epr = new EndpointReference(
                    "");  // I don't know the address now. Let me pass the empty string now and fill this
            // once I process the Elements under this.
            messageContextOptions.setFrom(epr);
        }
        extractEPRInformation(soapHeaderBlock, epr, addressingNamespace, messageContext);
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace("extractFromEPRInformation: Extracted From EPR: " + epr);
        }
        soapHeaderBlock.setProcessed();
    }

    private void extractToEPRInformation(SOAPHeaderBlock soapHeaderBlock,
                                         Options messageContextOptions, String namespace) {

        EndpointReference epr;
        //here the addressing epr overidde what ever already there in the message context
        epr = new EndpointReference(soapHeaderBlock.getText());
        messageContextOptions.setTo(epr);

        // check for address attributes
        Iterator addressAttributes = soapHeaderBlock.getAllAttributes();
        if (addressAttributes != null && addressAttributes.hasNext()) {
            ArrayList attributes = new ArrayList();
            while (addressAttributes.hasNext()) {
                OMAttribute attr = (OMAttribute) addressAttributes.next();
                attributes.add(attr);
            }
            epr.setAddressAttributes(attributes);
        }

        soapHeaderBlock.setProcessed();

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace("extractToEPRInformation: Extracted To EPR: " + epr);
        }
    }

    private void extractToEprReferenceParameters(EndpointReference toEPR, SOAPHeader header,
                                                   String namespace) {
        if (Final.WSA_NAMESPACE.equals(namespace)) {
            Iterator headerBlocks = header.getChildElements();
            while (headerBlocks.hasNext()) {
                OMElement headerElement = (OMElement)headerBlocks.next();
                OMAttribute isRefParamAttr =
                    headerElement.getAttribute(new QName(namespace, "IsReferenceParameter"));
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace("extractToEprReferenceParameters: Checking header: " +
                            headerElement.getQName());
                }
                if (isRefParamAttr != null && "true".equals(isRefParamAttr.getAttributeValue())) {
                    toEPR.addReferenceParameter(headerElement);
                    if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                        log.trace("extractToEprReferenceParameters: Header: " +
                                headerElement.getQName() +
                        " has IsReferenceParameter attribute. Adding to toEPR.");
                    }
                }
            }
        }
        else {
            // there is no exact way to identify ref parameters for Submission version. So let's have a handler
            // at the end of the flow, which puts all the handlers (which are of course mustUnderstand=false)
            // as reference parameters

            // TODO : Chinthaka
        }
    }

    //We assume that any action that already exists in the message context must be the
    //soapaction. We compare that action to the WS-Addressing action, and if they are
    //different we throw a fault.
    private void extractActionInformation(SOAPHeaderBlock soapHeaderBlock,
                                          MessageContext messageContext)
            throws AxisFault {
        Options messageContextOptions = messageContext.getOptions();
        String soapAction = messageContextOptions.getAction();
        String wsaAction = soapHeaderBlock.getText();

        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace("extractActionInformation: soapAction='" + soapAction + "' wsa:Action='" +
                      wsaAction + "'");
        }

        // Need to validate that the content of the wsa:Action header is not null or whitespace
        if ((wsaAction == null) || "".equals(wsaAction.trim())) {
            AddressingFaultsHelper.triggerActionNotSupportedFault(messageContext, wsaAction);
        }

        // The isServerSide check is because the underlying Options object is
        // shared between request and response MessageContexts for Sync
        // invocations. If the soapAction is set outbound and a wsa:Action is
        // received on the response they will differ (because there is no
        // SOAPAction header on an HTTP response). In this case we should not
        // check that soapAction==wsa:Action
        if (soapAction != null && !"".equals(soapAction) && messageContext.isServerSide()) {
            if (!soapAction.equals(wsaAction)) {
                AddressingFaultsHelper.triggerActionMismatchFault(messageContext, soapAction, wsaAction);
            }
        } else {
            messageContextOptions.setAction(wsaAction);
        }

        ArrayList attributes = extractAttributesFromSOAPHeaderBlock(soapHeaderBlock);
        if (attributes != null) {
            messageContext.setProperty(AddressingConstants.ACTION_ATTRIBUTES, attributes);
        }

        soapHeaderBlock.setProcessed();
    }

    private void extractMessageIDInformation(SOAPHeaderBlock soapHeaderBlock,
                                             MessageContext messageContext) throws AxisFault {
        messageContext.getOptions().setMessageId(soapHeaderBlock.getText());

        ArrayList attributes = extractAttributesFromSOAPHeaderBlock(soapHeaderBlock);
        if (attributes != null) {
            messageContext.setProperty(AddressingConstants.MESSAGEID_ATTRIBUTES, attributes);
        }

        soapHeaderBlock.setProcessed();
    }

    /**
     * Given the soap header block, this should extract the information within EPR.
     *
     * @param headerBlock         a SOAP header which is of type EndpointReference
     * @param epr                 the EndpointReference to fill in with the extracted data
     * @param addressingNamespace the WSA namespace URI
     * @param messageContext      the active MessageContext
     * @throws AxisFault if there is a problem
     */
    private void extractEPRInformation(SOAPHeaderBlock headerBlock, EndpointReference epr,
                                       String addressingNamespace, MessageContext messageContext)
            throws AxisFault {
        String namespace = null;
        
        try {
            namespace = EndpointReferenceHelper.fromOM(epr, headerBlock);            
        } catch (AxisFault af) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(
                        "extractEPRInformation: Exception occurred deserialising an EndpointReference.",
                        af);
            }
            AddressingFaultsHelper
                    .triggerMissingAddressInEPRFault(messageContext, headerBlock.getLocalName());
        }
        
        //Check that the EPR has the correct namespace.
        if (!namespace.equals(addressingNamespace)) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(
                        "extractEPRInformation: Addressing namespace = " + addressingNamespace +
                        ", EPR namespace = " + namespace);
            }
            AddressingFaultsHelper
                    .triggerInvalidEPRFault(messageContext, headerBlock.getLocalName());
        }
    }

    private ArrayList extractAttributesFromSOAPHeaderBlock(SOAPHeaderBlock soapHeaderBlock) {
        Iterator actionAttributes = soapHeaderBlock.getAllAttributes();
        if (actionAttributes != null && actionAttributes.hasNext()) {
            ArrayList attributes = new ArrayList();
            while (actionAttributes.hasNext()) {
                OMAttribute attr = (OMAttribute) actionAttributes.next();
                attributes.add(attr);
            }
            return attributes;
        }
        return null;
    }
}
