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

import org.apache.axiom.attachments.Attachments;
import org.apache.axiom.attachments.lifecycle.LifecycleManager;
import org.apache.axiom.attachments.lifecycle.impl.LifecycleManagerImpl;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.om.util.StAXParserConfiguration;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPConstants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPModelBuilder;
import org.apache.axiom.soap.SOAPProcessingException;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.deployment.DeploymentConstants;
import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.java.security.AccessController;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.MessageProcessorSelector;
import org.apache.axis2.util.MultipleEntryHashMap;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.*;

import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PushbackInputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Map;

public class BuilderUtil {
    private static final Log log = LogFactory.getLog(BuilderUtil.class);

    /**
     * @deprecated
     */
    public static final int BOM_SIZE = 4;

    public static SOAPEnvelope buildsoapMessage(MessageContext messageContext,
                                                MultipleEntryHashMap requestParameterMap,
                                                SOAPFactory soapFactory) throws AxisFault {

        SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope();
        SOAPBody body = soapEnvelope.getBody();
        XmlSchemaElement xmlSchemaElement;
        AxisOperation axisOperation = messageContext.getAxisOperation();
        if (axisOperation != null) {
            AxisMessage axisMessage =
                    axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
            xmlSchemaElement = axisMessage.getSchemaElement();

            if (xmlSchemaElement == null) {
                OMElement bodyFirstChild =
                        soapFactory
                                .createOMElement(messageContext.getAxisOperation().getName(), body);

                // if there is no schema its piece of cake !! add these to the soap body in any order you like.
                // Note : if there are parameters in the path of the URL, there is no way this can add them
                // to the message.
                createSOAPMessageWithoutSchema(soapFactory, bodyFirstChild, requestParameterMap);
            } else {

                // first get the target namespace from the schema and the wrapping element.
                // create an OMElement out of those information. We are going to extract parameters from
                // url, create OMElements and add them as children to this wrapping element.
                String targetNamespace = xmlSchemaElement.getQName().getNamespaceURI();
                QName bodyFirstChildQName;
                if (targetNamespace != null && !"".equals(targetNamespace)) {
                    bodyFirstChildQName = new QName(targetNamespace, xmlSchemaElement.getName());
                } else {
                    bodyFirstChildQName = new QName(xmlSchemaElement.getName());
                }
                OMElement bodyFirstChild = soapFactory.createOMElement(bodyFirstChildQName, body);

                // Schema should adhere to the IRI style in this. So assume IRI style and dive in to
                // schema
                XmlSchemaType schemaType = xmlSchemaElement.getSchemaType();
                if (schemaType instanceof XmlSchemaComplexType) {
                    XmlSchemaComplexType complexType = ((XmlSchemaComplexType)schemaType);
                    XmlSchemaParticle particle = complexType.getParticle();
                    if (particle instanceof XmlSchemaSequence || particle instanceof XmlSchemaAll) {

                        if (particle instanceof XmlSchemaSequence) {
                            XmlSchemaSequence sequence = (XmlSchemaSequence) particle;
                            // now we need to know some information from the binding operation.

                            for (XmlSchemaSequenceMember sequenceMember : sequence.getItems()) {

                                XmlSchemaElement innerElement = (XmlSchemaElement) sequenceMember;
                                QName qName = innerElement.getQName();
                                // ignoring the elements without proper type and minoccurs zero
                                if ((innerElement.getSchemaTypeName() == null) &&
                                    (innerElement.getMinOccurs() == 0)) {
                                    continue;
                                }
                                if (qName == null && innerElement.getSchemaTypeName()
                                        .equals(org.apache.ws.commons.schema.constants.Constants.XSD_ANYTYPE)) {
                                    createSOAPMessageWithoutSchema(soapFactory, bodyFirstChild,
                                                                   requestParameterMap);
                                    break;
                                }
                                checkMinOccurs(innerElement, qName, soapFactory, requestParameterMap,
                                               bodyFirstChild);
                            }
                        } else {
                            XmlSchemaAll sequence = (XmlSchemaAll) particle;
                            // now we need to know some information from the binding operation.

                            for (XmlSchemaAllMember sequenceMember : sequence.getItems()) {

                                XmlSchemaElement innerElement = (XmlSchemaElement) sequenceMember;
                                QName qName = innerElement.getQName();
                                // ignoring the elements without proper type and minoccurs zero
                                if ((innerElement.getSchemaTypeName() == null) &&
                                    (innerElement.getMinOccurs() == 0)) {
                                    continue;
                                }
                                if (qName == null && innerElement.getSchemaTypeName()
                                        .equals(org.apache.ws.commons.schema.constants.Constants.XSD_ANYTYPE)) {
                                    createSOAPMessageWithoutSchema(soapFactory, bodyFirstChild,
                                                                   requestParameterMap);
                                    break;
                                }
                                checkMinOccurs(innerElement, qName, soapFactory, requestParameterMap,
                                               bodyFirstChild);
                            }
                        }
                    }
                }else {
                    throw new AxisFault(xmlSchemaElement.getName() + " message element in schema should follow the " +
                            "(Internationalized Resource Identifier)IRI ) style to process request in REST style");
                }
            }
        }
        return soapEnvelope;
    }

    private static void checkMinOccurs(XmlSchemaElement innerElement, QName qName,
                                       SOAPFactory soapFactory,
                                       MultipleEntryHashMap requestParameterMap,
                                       OMElement bodyFirstChild)
            throws AxisFault {
        long minOccurs = innerElement.getMinOccurs();
        boolean nillable = innerElement.isNillable();
        String name =
                qName != null ? qName.getLocalPart() : innerElement.getName();
        Object value;
        OMNamespace ns = (qName == null ||
                          qName.getNamespaceURI() == null
                          || qName.getNamespaceURI().length() == 0) ?
                         null : soapFactory.createOMNamespace(
                qName.getNamespaceURI(), null);

        // FIXME changed
        while ((value = requestParameterMap.get(name)) != null) {
            addRequestParameter(soapFactory,
                                bodyFirstChild, ns, name, value);
            minOccurs--;
        }
        if (minOccurs > 0) {
            if (nillable) {

                OMNamespace xsi = soapFactory.createOMNamespace(
                        Constants.URI_DEFAULT_SCHEMA_XSI,
                        Constants.NS_PREFIX_SCHEMA_XSI);
                OMAttribute omAttribute =
                        soapFactory.createOMAttribute("nil", xsi, "true");
                soapFactory.createOMElement(name, ns,
                                            bodyFirstChild)
                        .addAttribute(omAttribute);

            } else {
                throw new AxisFault("Required element " + qName +
                                    " defined in the schema can not be" +
                                    " found in the request");
            }
        }
    }

    public static void createSOAPMessageWithoutSchema(SOAPFactory soapFactory,
                                                       OMElement bodyFirstChild,
                                                       MultipleEntryHashMap requestParameterMap) {

        // first add the parameters in the URL
        if (requestParameterMap != null) {
            for (Object o : requestParameterMap.keySet()) {
                String key = (String) o;
                Object value;
                while ((value = requestParameterMap.get(key)) != null) {
                    addRequestParameter(soapFactory, bodyFirstChild, null, key, value);
                }
            }
        }
    }

    private static void addRequestParameter(SOAPFactory soapFactory,
                                            OMElement bodyFirstChild,
                                            OMNamespace ns,
                                            String key,
                                            Object parameter) {
        if (parameter instanceof DataHandler) {
            DataHandler dataHandler = (DataHandler)parameter;
            OMText dataText = bodyFirstChild.getOMFactory().createOMText(
                    dataHandler, true);
            soapFactory.createOMElement(key, ns, bodyFirstChild).addChild(
                    dataText);
        } else {
            String textValue = parameter.toString();
            soapFactory.createOMElement(key, ns, bodyFirstChild).setText(
                    textValue);
        }
    }

    /**
     * Create a builder suitable for an XML message. This method uses
     * {@link StAXParserConfiguration#SOAP} to disallow document type declarations (that potentially
     * reference external entities).
     * 
     * @param in
     *            the input stream containing the plain XML message
     * @param encoding
     *            the charset encoding of the message or <code>null</code> if the parser should
     *            determine the charset encoding
     * @return the builder
     */
    public static OMXMLParserWrapper createPOXBuilder(InputStream in, String encoding) {
        return OMXMLBuilderFactory.createOMBuilder(StAXParserConfiguration.SOAP, in, encoding);
    }

    /**
     * @deprecated Instead of using this method, you should probably pass the {@link InputStream}
     *             directly to the XML parser. If the stream is not XML, you shouldn't be using this
     *             method anyway.
     */
    public static Reader getReader(final InputStream is, final String charSetEncoding)
            throws IOException {
        final PushbackInputStream is2 = getPushbackInputStream(is);
        final String encoding = getCharSetEncoding(is2, charSetEncoding);
        InputStreamReader inputStreamReader;
        try {
            inputStreamReader = (InputStreamReader)AccessController.doPrivileged(
                    new PrivilegedExceptionAction() {
                        public Object run() throws UnsupportedEncodingException {
                            return new InputStreamReader(is2, encoding);
                        }
                    }
            );
        } catch (PrivilegedActionException e) {
            throw (UnsupportedEncodingException)e.getException();
        }
        return new BufferedReader(inputStreamReader);
    }

    /**
     * @deprecated If you need a {@link PushbackInputStream} just construct one (with the
     *             appropriate size).
     */
    public static PushbackInputStream getPushbackInputStream(InputStream is) {
        return new PushbackInputStream(is, BOM_SIZE);
    }

    /**
     * @deprecated It's the role of the XML parser to determine the charset encoding and/or byte
     *             order using the algorithm described in the "Autodetection of Character Encodings"
     *             appendix of the XML spec. If you need this method, then something is wrong:
     *             probably you are using a {@link Reader} where you should use an
     *             {@link InputStream}.
     */
    public static String getCharSetEncoding(PushbackInputStream is2, String defaultEncoding)
            throws IOException {
        String encoding;
        byte bom[] = new byte[BOM_SIZE];
        int n, unread;

        n = is2.read(bom, 0, bom.length);

        if ((bom[0] == (byte)0xEF) && (bom[1] == (byte)0xBB) && (bom[2] == (byte)0xBF)) {
            encoding = "UTF-8";
            if (log.isDebugEnabled()) {
                log.debug("char set encoding set from BOM =" + encoding);
            }
            unread = n - 3;
        } else if ((bom[0] == (byte)0xFE) && (bom[1] == (byte)0xFF)) {
            encoding = "UTF-16BE";
            if (log.isDebugEnabled()) {
                log.debug("char set encoding set from BOM =" + encoding);
            }
            unread = n - 2;
        } else if ((bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE)) {
            encoding = "UTF-16LE";
            if (log.isDebugEnabled()) {
                log.debug("char set encoding set from BOM =" + encoding);
            }
            unread = n - 2;
        } else if ((bom[0] == (byte)0x00) && (bom[1] == (byte)0x00) && (bom[2] == (byte)0xFE)
                   && (bom[3] == (byte)0xFF)) {
            encoding = "UTF-32BE";
            if (log.isDebugEnabled()) {
                log.debug("char set encoding set from BOM =" + encoding);
            }
            unread = n - 4;
        } else if ((bom[0] == (byte)0xFF) && (bom[1] == (byte)0xFE) && (bom[2] == (byte)0x00)
                   && (bom[3] == (byte)0x00)) {
            encoding = "UTF-32LE";
            if (log.isDebugEnabled()) {
                log.debug("char set encoding set from BOM =" + encoding);
            }
            unread = n - 4;
        } else {

            // Unicode BOM mark not found, unread all bytes
            encoding = defaultEncoding;
            if (log.isDebugEnabled()) {
                log.debug("char set encoding set from default =" + encoding);
            }
            unread = n;
        }

        if (unread > 0) {
            is2.unread(bom, (n - unread), unread);
        }
        return encoding;
    }


    public static String getEnvelopeNamespace(String contentType) {
        String soapNS = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
        if (contentType != null) {
            if (contentType.indexOf(SOAP12Constants.SOAP_12_CONTENT_TYPE) > -1) {
                // it is SOAP 1.2
                soapNS = SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI;
            } else if (contentType.indexOf(SOAP11Constants.SOAP_11_CONTENT_TYPE) > -1) {
                // SOAP 1.1
                soapNS = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
            }
        }
        return soapNS;
    }

    /**
     * Extracts and returns the character set encoding from the Content-type header
     * <p/>
     * Example: "Content-Type: text/xml; charset=utf-8" would return "utf-8"
     *
     * @param contentType a content-type (from HTTP or MIME, for instance)
     * @return the character set encoding if found, or MessageContext.DEFAULT_CHAR_SET_ENCODING
     */
    public static String getCharSetEncoding(String contentType) {
        if (log.isDebugEnabled()) {
            log.debug("Input contentType (" + contentType + ")");
        }
        if (contentType == null) {
            // Using the default UTF-8
            if (log.isDebugEnabled()) {
                log.debug("CharSetEncoding defaulted (" + MessageContext.DEFAULT_CHAR_SET_ENCODING +
                          ")");
            }
            return MessageContext.DEFAULT_CHAR_SET_ENCODING;
        }

        int index = contentType.indexOf(HTTPConstants.CHAR_SET_ENCODING);

        if (index == -1) {    // Charset encoding not found in the content-type header
            // Using the default UTF-8
            if (log.isDebugEnabled()) {
                log.debug("CharSetEncoding defaulted (" + MessageContext.DEFAULT_CHAR_SET_ENCODING +
                          ")");
            }
            return MessageContext.DEFAULT_CHAR_SET_ENCODING;
        }

        // If there are spaces around the '=' sign
        int indexOfEq = contentType.indexOf("=", index);

        // There can be situations where "charset" is not the last parameter of the Content-Type header
        int indexOfSemiColon = contentType.indexOf(";", indexOfEq);
        String value;

        if (indexOfSemiColon > 0) {
            value = (contentType.substring(indexOfEq + 1, indexOfSemiColon));
        } else {
            value = (contentType.substring(indexOfEq + 1, contentType.length())).trim();
        }

        // There might be "" around the value - if so remove them
        if (value.indexOf('\"') != -1) {
            value = value.replaceAll("\"", "");
        }
        value = value.trim();
        if (log.isDebugEnabled()) {
            log.debug("CharSetEncoding from content-type (" + value + ")");
        }
        return value;
    }

    public static Attachments createAttachmentsMap(MessageContext msgContext,
                                                      InputStream inStream,
                                                      String contentTypeString) {
        boolean fileCacheForAttachments = isAttachmentsCacheEnabled(msgContext);

        String attachmentRepoDir = null;
        String attachmentSizeThreshold = null;

        if (fileCacheForAttachments) {
            Object attachmentRepoDirProperty = msgContext
                    .getProperty(Constants.Configuration.ATTACHMENT_TEMP_DIR);

            if (attachmentRepoDirProperty != null) {
                attachmentRepoDir = (String)attachmentRepoDirProperty;
            } else {
                Parameter attachmentRepoDirParameter = msgContext
                        .getParameter(Constants.Configuration.ATTACHMENT_TEMP_DIR);
                attachmentRepoDir =
                        (attachmentRepoDirParameter != null) ? (String)attachmentRepoDirParameter
                                .getValue()
                                : null;
            }

            Object attachmentSizeThresholdProperty = msgContext
                    .getProperty(Constants.Configuration.FILE_SIZE_THRESHOLD);
            if (attachmentSizeThresholdProperty != null
                && attachmentSizeThresholdProperty instanceof String) {
                attachmentSizeThreshold = (String)attachmentSizeThresholdProperty;
            } else {
                Parameter attachmentSizeThresholdParameter = msgContext
                        .getParameter(Constants.Configuration.FILE_SIZE_THRESHOLD);
                attachmentSizeThreshold = attachmentSizeThresholdParameter != null ?
                        attachmentSizeThresholdParameter.getValue().toString() : null;
            }
        }

        // Get the content-length if it is available
        int contentLength = 0;
        Map headers = (Map)msgContext.getProperty(MessageContext.TRANSPORT_HEADERS);
        if (headers != null) {
            String contentLengthValue = (String)headers.get(HTTPConstants.HEADER_CONTENT_LENGTH);
            if (contentLengthValue != null) {
                try {
                    contentLength = new Integer(contentLengthValue);
                } catch (NumberFormatException e) {
                    if (log.isDebugEnabled()) {
                        log.debug(
                                "Content-Length is not a valid number.  Will assume it is not set:" +
                                e);
                    }
                }
            }
        }
        if (log.isDebugEnabled()) {
            if (contentLength > 0) {
                log.debug("Creating an Attachments map.  The content-length is" + contentLength);
            } else {
                log.debug("Creating an Attachments map.");
            }
        }
        return createAttachments(msgContext,
                                 inStream,
                                 contentTypeString,
                                 fileCacheForAttachments,
                                 attachmentRepoDir,
                                 attachmentSizeThreshold,
                                 contentLength);
    }

    public static boolean isAttachmentsCacheEnabled(MessageContext msgContext) {
        Object cacheAttachmentProperty = msgContext
                .getProperty(Constants.Configuration.CACHE_ATTACHMENTS);
        String cacheAttachmentString;
        boolean fileCacheForAttachments;

        if (cacheAttachmentProperty != null && cacheAttachmentProperty instanceof String) {
            cacheAttachmentString = (String)cacheAttachmentProperty;
        } else {
            Parameter parameter_cache_attachment =
                    msgContext.getParameter(Constants.Configuration.CACHE_ATTACHMENTS);
            cacheAttachmentString = (parameter_cache_attachment != null) ?
                    (String)parameter_cache_attachment.getValue() : null;
        }
        fileCacheForAttachments = (Constants.VALUE_TRUE.equals(cacheAttachmentString));
        return fileCacheForAttachments;
    }

    public static Attachments createAttachments(MessageContext msgContext,
                                                InputStream inStream,
                                                String contentTypeString,
                                                boolean fileCacheForAttachments,
                                                String attachmentRepoDir,
                                                String attachmentSizeThreshold,
                                                int contentLength) {
        LifecycleManager manager = null;
        try {
            AxisConfiguration configuration = msgContext.getRootContext().getAxisConfiguration();
            manager = (LifecycleManager)configuration
                    .getParameterValue(DeploymentConstants.ATTACHMENTS_LIFECYCLE_MANAGER);
            if (manager == null) {
                manager = new LifecycleManagerImpl();
                configuration.addParameter(DeploymentConstants.ATTACHMENTS_LIFECYCLE_MANAGER,
                                           manager);
            }
        } catch (Exception e) {
            if (log.isDebugEnabled()) {
                log.debug("Exception getting Attachments LifecycleManager", e);
            }
        }
        return new Attachments(manager,
                               inStream,
                               contentTypeString,
                               fileCacheForAttachments,
                               attachmentRepoDir,
                               attachmentSizeThreshold,
                               contentLength);
    }

    /**
     * Create a SOAP model builder. This method delegates to
     * {@link OMXMLBuilderFactory#createSOAPModelBuilder(InputStream, String)} but generates
     * additional logging if an error occurs.
     * 
     * @param in
     *            the input stream containing the SOAP message
     * @param encoding
     *            the charset encoding of the SOAP message or <code>null</code> if the parser should
     *            determine the charset encoding
     * @return the builder
     */
    public static SOAPModelBuilder createSOAPModelBuilder(InputStream in, String encoding) {
        try {
            return OMXMLBuilderFactory.createSOAPModelBuilder(in, encoding);
        } catch (OMException e) {
            log.info("OMException in getSOAPBuilder", e);
            try {
                log.info("Remaining input stream :[" +
                         new String(IOUtils.toByteArray(in), encoding) + "]");
            } catch (IOException e1) {
                // Nothing here?
            }
            throw e;
        }
    }

    /**
     * @deprecated Use {@link MessageProcessorSelector#getMessageBuilder(String, MessageContext)}.
     */
    public static Builder getBuilderFromSelector(String type, MessageContext msgContext)
            throws AxisFault {
        return MessageProcessorSelector.getMessageBuilder(type, msgContext);
    }

    public static void validateSOAPVersion(String soapNamespaceURIFromTransport,
                                           SOAPEnvelope envelope) {
        if (soapNamespaceURIFromTransport != null) {
            OMNamespace envelopeNamespace = envelope.getNamespace();
            String namespaceName = envelopeNamespace.getNamespaceURI();
            if (!(soapNamespaceURIFromTransport.equals(namespaceName))) {
                throw new SOAPProcessingException(
                        "Transport level information does not match with SOAP" +
                        " Message namespace URI", envelopeNamespace.getPrefix() + ":" +
                                                  SOAPConstants.FAULT_CODE_VERSION_MISMATCH);
            }
        }
    }

    public static void validateCharSetEncoding(String charsetEncodingFromTransport,
                                               String charsetEncodingFromXML,
                                               String soapNamespaceURI) throws AxisFault {
        if ((charsetEncodingFromXML != null)
            && !"".equals(charsetEncodingFromXML)
            && (charsetEncodingFromTransport != null)
            && !charsetEncodingFromXML.equalsIgnoreCase(charsetEncodingFromTransport)
            && !compatibleEncodings(charsetEncodingFromXML, charsetEncodingFromTransport)) {
            /**
             * WS-BP Rule 1019 requires toleration if the character sets mismatch
             * I am changing this to simply a debug statement.
            String faultCode;

            if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapNamespaceURI)) {
                faultCode = SOAP12Constants.FAULT_CODE_SENDER;
            } else {
                faultCode = SOAP11Constants.FAULT_CODE_SENDER;
            }

            throw new AxisFault("Character Set Encoding from "
                    + "transport information [" + charsetEncodingFromTransport + "] does not match with "
                    + "character set encoding in the received SOAP message [" + charsetEncodingFromXML + "]", faultCode);
            **/
            if (log.isDebugEnabled()) {
                log.debug("Character Set Encoding from "
                        + "transport information [" + charsetEncodingFromTransport + "] does not match with "
                        + "character set encoding in the received SOAP message [" + charsetEncodingFromXML + "]");
            }
        }
    }

    /**
     * check if the pair is [UTF-16,UTF-16LE] [UTF-32, UTF-32LE],[UTF-16,UTF-16BE] [UTF-32,
     * UTF-32BE] etc.
     *
     * @param enc1 encoding style
     * @param enc2 encoding style
     * @return true if the encoding styles are compatible, or false otherwise
     */
    private static boolean compatibleEncodings(String enc1, String enc2) {
        enc1 = enc1.toLowerCase();
        enc2 = enc2.toLowerCase();
        if (enc1.endsWith("be") || enc1.endsWith("le")) {
            enc1 = enc1.substring(0, enc1.length() - 2);
        }
        if (enc2.endsWith("be") || enc2.endsWith("le")) {
            enc2 = enc2.substring(0, enc2.length() - 2);
        }
        return enc1.equals(enc2);
    }
}
