/*
 * 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.om.OMNamespace;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPFault;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.AxisFault;
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.addressing.i18n.AddressingMessages;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisEndpoint;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.axis2.handlers.AbstractTemplatedHandler;
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;
import java.util.List;
import java.util.Map;

public class AddressingOutHandler extends AbstractTemplatedHandler implements AddressingConstants {

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

    // TODO: This is required for MessageContext#getModuleParameter.
    //       Not clear why there is no way to automatically determine this!
    private static final String MODULE_NAME = "addressing";


    public boolean shouldInvoke(MessageContext msgContext) throws AxisFault {
        Parameter param = null;
        boolean disableAddressing = false;
        
        Object o = msgContext.getProperty(DISABLE_ADDRESSING_FOR_OUT_MESSAGES);
        if (o == null || !(o instanceof Boolean)) {
            //determine whether outbound addressing has been disabled or not.
            // Get default value from module.xml or axis2.xml files
            param = msgContext.getModuleParameter(DISABLE_ADDRESSING_FOR_OUT_MESSAGES, MODULE_NAME, handlerDesc);
            disableAddressing =
                msgContext.isPropertyTrue(DISABLE_ADDRESSING_FOR_OUT_MESSAGES,
                    JavaUtils.isTrueExplicitly(Utils.getParameterValue(param)));
        } else {
            disableAddressing = (Boolean) o;
        }

        if (disableAddressing) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(msgContext.getLogIDString() +
                        " Addressing is disabled. Not adding WS-Addressing headers.");
            }
            return false;
        }
        return true;
    }
    
    public InvocationResponse doInvoke(MessageContext msgContext) throws AxisFault {
        

        // Determine the addressin namespace in effect.
        Object addressingVersionFromCurrentMsgCtxt = msgContext.getProperty(WS_ADDRESSING_VERSION);
        if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            log.trace("Addressing version string from messageContext=" +
                    addressingVersionFromCurrentMsgCtxt);
        }
        boolean isSubmissionNamespace =
                Submission.WSA_NAMESPACE.equals(addressingVersionFromCurrentMsgCtxt);

        // Determine whether to include optional addressing headers in the output.
        // Get default value from module.xml or axis2.xml files
        Parameter param = msgContext.getModuleParameter(
                INCLUDE_OPTIONAL_HEADERS, MODULE_NAME, handlerDesc);
        boolean includeOptionalHeaders =
            msgContext.isPropertyTrue(INCLUDE_OPTIONAL_HEADERS,
                    JavaUtils.isTrueExplicitly(Utils.getParameterValue(param)));

        if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
            log.debug("includeOptionalHeaders=" + includeOptionalHeaders);
        }

        // Determine if a MustUnderstand attribute will be added to all headers in the
        // addressing namespace.
        boolean addMustUnderstandAttribute =
                msgContext.isPropertyTrue(ADD_MUST_UNDERSTAND_TO_ADDRESSING_HEADERS);

        // what if there are addressing headers already in the message. Do you replace that or not?
        // Lets have a parameter to control that. The default behavior is you won't replace addressing
        // headers if there are any (this was the case so far).
        boolean replaceHeaders = msgContext.isPropertyTrue(REPLACE_ADDRESSING_HEADERS);
        
        // Allow the user to specify the role these WS-Addressing headers should be targetted at.
        String role = (String) msgContext.getProperty(SOAP_ROLE_FOR_ADDRESSING_HEADERS);

        WSAHeaderWriter writer = new WSAHeaderWriter(msgContext, isSubmissionNamespace,
                                                     addMustUnderstandAttribute, replaceHeaders,
                                                     includeOptionalHeaders, role);
        writer.writeHeaders();

        return InvocationResponse.CONTINUE;
    }

    private class WSAHeaderWriter {

        private MessageContext messageContext;
        private SOAPEnvelope envelope;
        private SOAPHeader header;
        private SOAPFactory factory;
        private Options messageContextOptions;
        private OMNamespace addressingNamespaceObject;
        private String addressingNamespace;
        private String addressingRole;

        private boolean isFinalAddressingNamespace;
        private boolean addMustUnderstandAttribute;
        private boolean replaceHeaders;  // determines whether we replace the existing headers or not, if they present
        private boolean includeOptionalHeaders;

        private ArrayList existingWSAHeaders = null;
        
        public WSAHeaderWriter(MessageContext mc, boolean isSubmissionNamespace, boolean addMU,
                               boolean replace, boolean includeOptional, String role) {
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
                log.debug("WSAHeaderWriter: isFinal=" + !isSubmissionNamespace + " addMU=" + addMU +
                        " replace=" + replace + " includeOptional=" + includeOptional+" role="+role);
            }

            messageContext = mc;
            envelope = mc.getEnvelope();
            factory = (SOAPFactory)envelope.getOMFactory();

            messageContextOptions = messageContext.getOptions();

            addressingNamespace =
                    isSubmissionNamespace ? Submission.WSA_NAMESPACE : Final.WSA_NAMESPACE;

            header = envelope.getHeader();
            // if there is no soap header in the envelope being processed, add one.
            if (header == null) {
            	header = factory.createSOAPHeader(envelope);
            }else{
            	ArrayList addressingHeaders = header.getHeaderBlocksWithNSURI(addressingNamespace);
            	if(addressingHeaders!=null && !addressingHeaders.isEmpty()){
            		existingWSAHeaders = new ArrayList(addressingHeaders.size());
            		for(Iterator iter=addressingHeaders.iterator();iter.hasNext();){
            			SOAPHeaderBlock oe = (SOAPHeaderBlock)iter.next();
            			if(addressingRole == null || addressingRole.length() ==0 || addressingRole.equals(oe.getRole())){
            				existingWSAHeaders.add(oe.getLocalName());
            			}
            		}
            	}
            	if(addressingHeaders != null && addressingHeaders.size() ==0){
            		addressingHeaders = null;
            	}
            }
            
            isFinalAddressingNamespace = !isSubmissionNamespace;
            addMustUnderstandAttribute = addMU;
            replaceHeaders = replace;
            includeOptionalHeaders = includeOptional;
            addressingRole = role;
            
            if(!isFinalAddressingNamespace && mc.getTo() == null){
            	mc.setTo(new EndpointReference(AddressingConstants.Submission.WSA_ANONYMOUS_URL));
            }
        }

        public void writeHeaders() throws AxisFault {

            // by this time, we definitely have some addressing information to be sent. This is because,
            // we have tested at the start of this whether messageInformationHeaders are null or not.
            // So rather than declaring addressing namespace in each and every addressing header, lets
            // define that in the Header itself.
        	addressingNamespaceObject = header.declareNamespace(addressingNamespace, WSA_DEFAULT_PREFIX);

            // processing WSA To
            processToEPR();

            // processing WSA replyTo
            processReplyTo();

            // processing WSA From
            processFromEPR();

            // processing WSA FaultTo
            processFaultToEPR();

            // processing WSA MessageID
            processMessageID();

            // processing WSA Action
            processWSAAction();

            // processing WSA RelatesTo
            processRelatesTo();

            // process fault headers, if present
            processFaultsInfoIfPresent();

            // process mustUnderstand attribute, if required.
            processMustUnderstandProperty();
        }


        private void processMessageID() {
            String messageID = messageContextOptions.getMessageId();
            
            //Check whether we want to force a message id to be sent.
            if (messageID == null && includeOptionalHeaders) {
                messageID = UIDGenerator.generateURNString();
                messageContextOptions.setMessageId(messageID);
            }
            
            if (messageID != null && !isAddressingHeaderAlreadyAvailable(WSA_MESSAGE_ID, false))
            {//optional
            	ArrayList attributes = (ArrayList)messageContext.getLocalProperty(
                        AddressingConstants.MESSAGEID_ATTRIBUTES);
                createSOAPHeaderBlock(messageID, WSA_MESSAGE_ID, attributes);
            }
        }

        private void processWSAAction() throws AxisFault {
            String action = messageContextOptions.getAction();

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace(messageContext.getLogIDString() +
                        " processWSAAction: action from messageContext: " + action);
            }
            if (action == null || action.length()==0) {
                if (messageContext.getAxisOperation() != null) {
                    action = messageContext.getAxisOperation().getOutputAction();
                    if(action!=null){
                    	// Set this action back to obviate possible action mismatch problems
                    	messageContext.setWSAAction(action);
                    }
                    if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                        log.trace(messageContext.getLogIDString() +
                                " processWSAAction: action from AxisOperation: " + action);
                    }
                }
            }else{
	            // Use the correct fault action for the selected namespace
	            if(isFinalAddressingNamespace){
	            	if(Submission.WSA_FAULT_ACTION.equals(action)){
	            		action = Final.WSA_FAULT_ACTION;
	            		messageContextOptions.setAction(action);
	            	}
	            }else{
	            	if(Final.WSA_FAULT_ACTION.equals(action)){
	            		action = Submission.WSA_FAULT_ACTION;
	            		messageContextOptions.setAction(action);
	            	}else if(Final.WSA_SOAP_FAULT_ACTION.equals(action)){
	                    action = Submission.WSA_FAULT_ACTION;
	                    messageContextOptions.setAction(action);
	            	}
	            }
            }

            // If we need to add a wsa:Action header
            if (!isAddressingHeaderAlreadyAvailable(WSA_ACTION, false)) {
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace(messageContext.getLogIDString() +
                            " processWSAAction: No existing wsa:Action header found");
                }
                // If we don't have an action to add,
                if (action == null || action.length()==0) {
                    if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                        log.trace(messageContext.getLogIDString() +
                                " processWSAAction: No action to add to header");
                    }
                    // Fault unless validation has been explictily turned off
                    if (!messageContext.isPropertyTrue(
                            AddressingConstants.DISABLE_OUTBOUND_ADDRESSING_VALIDATION))
                    {
                        throw new AxisFault(AddressingMessages.getMessage("outboundNoAction"));
                    }
                } else {
                    if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                        log.trace(messageContext.getLogIDString() +
                                " processWSAAction: Adding action to header: " + action);
                    }
                    // Otherwise just add the header
                    ArrayList attributes = (ArrayList)messageContext.getLocalProperty(
                            AddressingConstants.ACTION_ATTRIBUTES);
                    createSOAPHeaderBlock(action, WSA_ACTION, attributes);
                }
            }
        }

        private void processFaultsInfoIfPresent() {
            OMElement detailElement = AddressingFaultsHelper
                    .getDetailElementForAddressingFault(messageContext, addressingNamespaceObject);
            if (detailElement != null) {
                //The difference between SOAP 1.1 and SOAP 1.2 fault messages is explained in the WS-Addressing Specs.
                if (isFinalAddressingNamespace && messageContext.isSOAP11()) {
                    // Add detail as a wsa:FaultDetail header
                    if (!isAddressingHeaderAlreadyAvailable(Final.FAULT_HEADER_DETAIL, false)) {
                        SOAPHeaderBlock faultDetail = header.addHeaderBlock(
                                Final.FAULT_HEADER_DETAIL, addressingNamespaceObject);
                        faultDetail.addChild((OMElement)factory.importInformationItem(detailElement));
                    }
                } else if (!messageContext.isSOAP11()) {
                    // Add detail to the Fault in the SOAP Body
                    SOAPFault fault = envelope.getBody().getFault();
                    if (fault != null && fault.getDetail() != null) {
                        fault.getDetail().addDetailEntry(
                                (OMElement)factory.importInformationItem(detailElement));
                    }
                }
            }
        }

        private void processRelatesTo() {
            if (!isAddressingHeaderAlreadyAvailable(WSA_RELATES_TO, true)) {
                RelatesTo[] relatesTo = messageContextOptions.getRelationships();

                if (relatesTo != null) {
                    for (int i = 0, length = relatesTo.length; i < length; i++) {
                        OMElement relatesToHeader = createSOAPHeaderBlock(relatesTo[i].getValue(),
                        		WSA_RELATES_TO, relatesTo[i].getExtensibilityAttributes());
                        String relationshipType = relatesTo[i].getRelationshipType();
                        if (relatesToHeader != null) {
                        	
                        	if(!includeOptionalHeaders){
                        		if (Final.WSA_DEFAULT_RELATIONSHIP_TYPE.equals(relationshipType) ||
                                        Submission.WSA_DEFAULT_RELATIONSHIP_TYPE
                                                .equals(relationshipType)) {
                        			relationshipType = null; //Omit the attribute.
                        		}
                        	}
                        	
                            if(relationshipType != null){
	                            relatesToHeader.addAttribute(WSA_RELATES_TO_RELATIONSHIP_TYPE,
	                                                         relationshipType,
	                                                         null);
                            }
                        }
                    }
                }
            }
        }

        private void processFaultToEPR() throws AxisFault {
            EndpointReference epr = messageContextOptions.getFaultTo();
            String headerName = AddressingConstants.WSA_FAULT_TO;

            //Omit the header if the epr is null.
            if (epr != null && !isAddressingHeaderAlreadyAvailable(headerName, false)) {
                addToSOAPHeader(epr, headerName);
            }
        }

        private void processFromEPR() throws AxisFault {
            EndpointReference epr = messageContextOptions.getFrom();
            String headerName = AddressingConstants.WSA_FROM;

            //Omit the header if the epr is null.
            if (epr != null && !isAddressingHeaderAlreadyAvailable(headerName, false)) {
                addToSOAPHeader(epr, headerName);
            }
        }

        private void processReplyTo() throws AxisFault {
            EndpointReference epr = messageContextOptions.getReplyTo();
            String headerName = AddressingConstants.WSA_REPLY_TO;

            //Don't check epr for null here as addToSOAPHeader() will provide an appropriate default.
            //This default is especially useful for client side outbound processing.
            if (!isAddressingHeaderAlreadyAvailable(headerName, false)) {
                addToSOAPHeader(epr, headerName);
            }
        }

        private void processToEPR() throws AxisFault {
            EndpointReference epr = messageContextOptions.getTo();
            if (epr != null && !isAddressingHeaderAlreadyAvailable(WSA_TO, false)) {
                try {
                    processToEPRReferenceInformation(epr.getAllReferenceParameters());
                }
                catch (Exception e) {
                    throw new AxisFault(AddressingMessages.getMessage("referenceParameterError"), e);
                }
                String address = epr.getAddress();
                if (address != null && address.length()!=0) {
                    if (!includeOptionalHeaders && isFinalAddressingNamespace &&
                            epr.isWSAddressingAnonymous())
                    {
                        return; //Omit the header.
                    }
                    createSOAPHeaderBlock(address, WSA_TO, epr.getAddressAttributes());
                }
            }
        }

        private OMElement createSOAPHeaderBlock(String value, String headerName, ArrayList<OMAttribute> attributes) {
            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace("createSOAPHeaderBlock: value=" + value + " headerName=" + headerName);
            }
            if (value != null && value.length()!=0) {
                SOAPHeaderBlock soapHeaderBlock =
                        header.addHeaderBlock(headerName, addressingNamespaceObject);
                soapHeaderBlock.addChild(factory.createOMText(value));
                if (attributes != null && !attributes.isEmpty()) {
                    Iterator<OMAttribute> attrIterator = attributes.iterator();
                    while (attrIterator.hasNext()) {
                        soapHeaderBlock.addAttribute(
                                (OMAttribute)soapHeaderBlock.getOMFactory().importInformationItem(attrIterator.next()));
                    }
                }
                addRoleToHeader(soapHeaderBlock);
                return soapHeaderBlock;
            }
            return null;
        }

        private void addToSOAPHeader(EndpointReference epr, String headerName) throws AxisFault {
            String prefix = addressingNamespaceObject.getPrefix();
            String anonymous = isFinalAddressingNamespace ?
                    Final.WSA_ANONYMOUS_URL : Submission.WSA_ANONYMOUS_URL;

            if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                log.trace("addToSOAPHeader: epr=" + epr + " headerName=" + headerName);
            }

            if (epr == null) {
                if (!includeOptionalHeaders && isFinalAddressingNamespace &&
                        AddressingConstants.WSA_REPLY_TO.equals(headerName)) {
                    return; //Omit the header.
                } else {
                    epr = new EndpointReference(anonymous);
                }
            }
            else if (!isFinalAddressingNamespace && epr.hasNoneAddress()) {
                return; //Omit the header.
            }
            else if (epr.isWSAddressingAnonymous())
            {
                if (!includeOptionalHeaders && isFinalAddressingNamespace &&
                        AddressingConstants.WSA_REPLY_TO.equals(headerName)) {
                    return; //Omit the header.
                } else {
                    epr.setAddress(anonymous);
                }
            }

            OMElement soapHeaderBlock = EndpointReferenceHelper.toOM(factory,
                                                                     epr,
                                                                     new QName(addressingNamespace,
                                                                               headerName, prefix),
                                                                     addressingNamespace);
            addRoleToHeader((SOAPHeaderBlock) soapHeaderBlock);
            header.addChild(soapHeaderBlock);
        }

        /**
         * This will add reference parameters and/or reference properties in to the message
         *
         * @param referenceInformation a Map from QName -> OMElement
         * @param parent               is the element to which the referenceparameters should be
         *                             attached
         */
        private void processToEPRReferenceInformation(Map referenceInformation) throws Exception {
            if (referenceInformation != null) {
                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                    log.trace("processToEPRReferenceInformation: " + referenceInformation);
                }
                Iterator iterator = referenceInformation.values().iterator();
                while (iterator.hasNext()) {
                    OMElement omElement = (OMElement)iterator.next();
                    SOAPHeaderBlock newElement = factory.createSOAPHeaderBlock(omElement);
                    if (isFinalAddressingNamespace) {
                        newElement.addAttribute(Final.WSA_IS_REFERENCE_PARAMETER_ATTRIBUTE,
                                               Final.WSA_TYPE_ATTRIBUTE_VALUE,
                                               addressingNamespaceObject);
                    }
                    addRoleToHeader(newElement);
                    header.addChild(newElement);
                }
            }
            // Now add reference parameters we found in the WSDL (if any)
            AxisService service = messageContext.getAxisService();
            if(service != null){
            	AxisEndpoint endpoint = service.getEndpoint(service.getEndpointName());
            	if(endpoint != null){
            		ArrayList referenceparameters = (ArrayList) endpoint.getParameterValue(REFERENCE_PARAMETER_PARAMETER);
            		if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
            			log.trace("processToEPRReferenceInformation: Reference Parameters from WSDL:" + referenceparameters);
            		}
            		if(referenceparameters!=null){
            			Iterator iterator = referenceparameters.iterator();
            			while (iterator.hasNext()) {
            				OMElement omElement = (OMElement)iterator.next();
                            // Only add the reference parameter from the WSDL if it does not already exist.
                            // This allows clients to override the values before invoking the service.
                            if (referenceInformation == null || !referenceInformation.containsKey(omElement.getQName())) {
                                SOAPHeaderBlock newElement = factory.createSOAPHeaderBlock(omElement);
                                if (isFinalAddressingNamespace) {
                                    newElement.addAttribute(Final.WSA_IS_REFERENCE_PARAMETER_ATTRIBUTE,
                                                            Final.WSA_TYPE_ATTRIBUTE_VALUE,
                                                            addressingNamespaceObject);
                                }
                                addRoleToHeader(newElement);
                                header.addChild(newElement);
                            } else {
                                if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                                    log.trace("processToEPRReferenceInformation: Reference parameter already exists so ignoring value from WSDL: " + omElement);
                                }
                            }
            			}
            		}
            	}
            }
            
            if (log.isTraceEnabled()) {
                log.trace("processToEPRReferenceInformation: Header after adding reference parameters: "+header);
            }
        }

        /**
         * This will check for the existence of message information headers already in the message.
         * If there are already headers, then replacing them or not depends on the replaceHeaders
         * property.
         *
         * @param name            - Name of the message information header
         * @param multipleHeaders - determines whether to search for multiple headers, or not.
         * @return false - if one can add new headers (always the case if multipleHeaders is true),
         *         true - if new headers can't be added.
         */
        private boolean isAddressingHeaderAlreadyAvailable(String name, boolean multipleHeaders) {
        	boolean status = false;

        	if (multipleHeaders) {
        		if (replaceHeaders) {
        			QName qname = new QName(addressingNamespace, name, WSA_DEFAULT_PREFIX);
        			Iterator<OMElement> iterator = header.getChildrenWithName(qname);
        			while (iterator.hasNext()) {
        				iterator.next();
        				iterator.remove();
        			}
        		}
        	} else {
        		boolean exists = didAddressingHeaderExist(name);
        		if (exists && replaceHeaders) {
        			QName qname = new QName(addressingNamespace, name, WSA_DEFAULT_PREFIX);
        			OMElement addressingHeader = header.getFirstChildWithName(qname);
        			if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
        				log.trace("isAddressingHeaderAlreadyAvailable: Removing existing header:" +
        						addressingHeader.getLocalName());
        			}
        			addressingHeader.detach();
        		} else {
        			status = exists;
        		}
        	}

        	if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
        		log.trace("isAddressingHeaderAlreadyAvailable: name=" + name + " status=" + status);
        	}
        	return status;
        }

        private boolean didAddressingHeaderExist(String headerName){
        	if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
        		log.trace("didAddressingHeaderExist: headerName=" + headerName);
        	}
        	boolean result = false;
        	if(existingWSAHeaders != null){
        		result = existingWSAHeaders.contains(headerName);
        		if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
        			log.trace("didAddressingHeaderExist: existingWSAHeaders=" + existingWSAHeaders+" result="+result);
        		}
        	}
        	return result;
        }

        /**
         * Sets a mustUnderstand attribute on all headers that are found with the appropriate
         * addressing namespace.
         */
        private void processMustUnderstandProperty() {
            if (addMustUnderstandAttribute) {
                List headers = header.getHeaderBlocksWithNSURI(addressingNamespace);

                for (int i = 0, size = headers.size(); i < size; i++) {
                    SOAPHeaderBlock soapHeaderBlock = (SOAPHeaderBlock)headers.get(i);
                    soapHeaderBlock.setMustUnderstand(true);
                    if (LoggingControl.debugLoggingAllowed && log.isTraceEnabled()) {
                        log.trace(
                                "processMustUnderstandProperty: Setting mustUnderstand=true on: " +
                                        soapHeaderBlock.getLocalName());
                    }
                }
            }
        }
        
        private void addRoleToHeader(SOAPHeaderBlock header){
        	if(addressingRole == null || addressingRole.length()==0){
        		return;
        	}
        	header.setRole(addressingRole);
        }
    }
}

