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

import org.apache.axiom.attachments.Attachments;
import org.apache.axiom.attachments.CachedFileDataSource;
import org.apache.axiom.attachments.lifecycle.LifecycleManager;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPModelBuilder;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.builder.Builder;
import org.apache.axis2.builder.BuilderUtil;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.deployment.DeploymentConstants;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.MessageProcessorSelector;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.activation.DataSource;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.stream.XMLStreamException;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

public class TransportUtils {

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

    public static SOAPEnvelope createSOAPMessage(MessageContext msgContext) throws AxisFault {
        return createSOAPMessage(msgContext, false);
    }

    /**
     * This method will create a SOAPEnvelope based on the InputStream stored on
     * the MessageContext. The 'detach' parameter controls whether or not the
     * underlying DetachableInputStream is detached at the end of the method. Note,
     * detaching the DetachableInputStream closes the underlying InputStream that
     * is stored on the MessageContext.
     */
    public static SOAPEnvelope createSOAPMessage(MessageContext msgContext,
                                                 boolean detach) throws AxisFault {
//        final SOAPEnvelope envelope = msgContext.getEnvelope();
//        if (envelope != null) {
//            if (envelope.isComplete())
//                return envelope;
//        }
        try {
            InputStream inStream = (InputStream) msgContext
                    .getProperty(MessageContext.TRANSPORT_IN);
            msgContext.setProperty(MessageContext.TRANSPORT_IN, null);

            // this inputstram is set by the TransportSender represents a two
            // way transport or a Transport Recevier
            if (inStream == null) {
                throw new AxisFault(Messages.getMessage("inputstreamNull"));
            }

            String contentType = (String) msgContext
                    .getProperty(Constants.Configuration.CONTENT_TYPE);

            // get the type of char encoding
            String charSetEnc = (String) msgContext
                    .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);
            if (charSetEnc == null && contentType != null) {
                charSetEnc = BuilderUtil.getCharSetEncoding(contentType);
            } else if (charSetEnc == null) {
                charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
            }
            msgContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, charSetEnc);

            SOAPEnvelope env = createSOAPMessage(msgContext, inStream, contentType);

            if(detach) {
                detachInputStream(msgContext);
            }
            return env;
        } catch (Exception e) {
            throw AxisFault.makeFault(e);
        }
    }

    /**
     * Objective of this method is to capture the SOAPEnvelope creation logic
     * and make it a common for all the transports and to in/out flows.
     *
     * @param msgContext message context
     * @param inStream input stream
     * @param contentType content type of the message
     * @return the SOAPEnvelope
     * @throws AxisFault if an error occurs
     * @throws OMException if the xml is invalid
     * @throws XMLStreamException if the stream is invalid
     * @throws FactoryConfigurationError
     */
    public static SOAPEnvelope createSOAPMessage(MessageContext msgContext,
                                                 InputStream inStream,
                                                 String contentType)
            throws AxisFault, OMException, XMLStreamException,
            FactoryConfigurationError {
        OMElement documentElement = createDocumentElement(contentType, msgContext, inStream);
        return createSOAPEnvelope(documentElement);
    }

    /**
     * Objective of this method is to capture the SOAPEnvelope creation logic
     * and make it a common for all the transports and to in/out flows.
     *
     * @param msgContext message context
     * @param inStream input stream
     * @param contentType content type of the message
     * @param builder the builder to be used
     * @return the SOAPEnvelope
     * @throws AxisFault if an error occurs
     * @throws OMException if the xml is invalid
     * @throws XMLStreamException if the stream is invalid
     * @throws FactoryConfigurationError
     */
    public static SOAPEnvelope createSOAPMessage(MessageContext msgContext,
                                                 InputStream inStream,
                                                 String contentType,
                                                 Builder builder)
            throws AxisFault, OMException, XMLStreamException, FactoryConfigurationError {
        OMElement documentElement = createDocumentElement(contentType, builder,
                msgContext, inStream);
        return createSOAPEnvelope(documentElement);
    }

    public static SOAPEnvelope createSOAPEnvelope(OMElement documentElement) {
        SOAPEnvelope envelope;
        // Check whether we have received a SOAPEnvelope or not
        if (documentElement instanceof SOAPEnvelope) {
            envelope = (SOAPEnvelope) documentElement;
        } else {
            // If it is not a SOAPEnvelope we wrap that with a fake
            // SOAPEnvelope.
            SOAPFactory soapFactory = OMAbstractFactory.getSOAP11Factory();
            envelope = soapFactory.getDefaultEnvelope();
            if (documentElement != null) {
                envelope.getBody().addChild(documentElement);
            }
        }
        return envelope;
    }

    public static OMElement createDocumentElement(String contentType,
                                                  MessageContext msgContext,
                                                  InputStream inStream)
            throws AxisFault, XMLStreamException {
        OMElement documentElement = null;
        String type = null;
        if (contentType != null) {
            type = getContentType(contentType, msgContext);
            Builder builder = MessageProcessorSelector.getMessageBuilder(type, msgContext);
            if (builder != null) {
                if (log.isDebugEnabled()) {
                    log.debug("createSOAPEnvelope using Builder (" +
                              builder.getClass() + ") selected from type (" + type +")");
                }
                documentElement = builder.processDocument(inStream, contentType, msgContext);
            }
        }
        if (documentElement == null) {
            documentElement = createDefaultDocumentElement(msgContext, inStream, type);
        }
        return documentElement;
    }

    private static OMElement createDefaultDocumentElement(MessageContext msgContext,
                                                          InputStream inStream, String type) {
        OMElement documentElement;
        if (msgContext.isDoingREST()) {
            if (log.isDebugEnabled()) {
                log.debug("Could not find a Builder for type (" + type + ").  Using REST.");
            }
            OMXMLParserWrapper builder = BuilderUtil.createPOXBuilder(inStream, null);
            documentElement = builder.getDocumentElement();
        } else {
            // FIXME making soap defualt for the moment..might effect the
            // performance
            if (log.isDebugEnabled()) {
                log.debug("Could not find a Builder for type (" + type + ").  Using SOAP.");
            }
            String charSetEnc = (String) msgContext
                    .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);
            SOAPModelBuilder builder = BuilderUtil.createSOAPModelBuilder(inStream, charSetEnc);
            documentElement = builder.getDocumentElement();
        }
        return documentElement;
    }

    public static OMElement createDocumentElement(String contentType, Builder builder,
                                                  MessageContext msgContext,
                                                  InputStream inStream)
            throws AxisFault, XMLStreamException {
        OMElement documentElement = null;
        String type = null;
        if (contentType != null) {
            type = getContentType(contentType, msgContext);
            if (builder != null) {
                if (log.isDebugEnabled()) {
                    log.debug("createSOAPEnvelope using Builder (" +
                              builder.getClass() + ") selected from type (" + type +")");
                }
                documentElement = builder.processDocument(inStream, contentType, msgContext);
            }
        }

        if (documentElement == null) {
            documentElement = createDefaultDocumentElement(msgContext, inStream, type);
        }
        return documentElement;
    }

    public static String getContentType(String contentType, MessageContext msgContext) {
        String type;
        int index = contentType.indexOf(';');
        if (index > 0) {
            type = contentType.substring(0, index);
        } else {
            type = contentType;
        }
        // Some services send REST responces as text/xml. We should convert it to
        // application/xml if its a REST response, if not it will try to use the SOAPMessageBuilder.
        // isDoingREST should already be properly set by HTTPTransportUtils.initializeMessageContext
        if (msgContext.isDoingREST() && HTTPConstants.MEDIA_TYPE_TEXT_XML.equals(type)) {
            if (msgContext.isServerSide()) {
                if (msgContext.getSoapAction() == null) {
                    // TODO - remove this logic. 
                    //type = HTTPConstants.MEDIA_TYPE_APPLICATION_XML;
                }
            } else if (!msgContext.isPropertyTrue(Constants.Configuration.SOAP_RESPONSE_MEP)) {
                type = HTTPConstants.MEDIA_TYPE_APPLICATION_XML;
            }
        }
        return type;
    }

    /**
     * Extracts and returns the character set encoding from the
     * Content-type header
     * Example:
     * Content-Type: text/xml; charset=utf-8
     *
     * @param contentType
     */
    public static String getCharSetEncoding(String contentType) {
        if (log.isDebugEnabled()) {
            log.debug("Input contentType (" + contentType + ")");
        }
        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 void writeMessage(MessageContext msgContext, OutputStream out) throws AxisFault {
        SOAPEnvelope envelope = msgContext.getEnvelope();
        OMElement outputMessage = envelope;

        if ((envelope != null) && msgContext.isDoingREST()) {
            outputMessage = envelope.getBody().getFirstElement();
        }

        if (outputMessage != null) {
            try {
                OMOutputFormat format = new OMOutputFormat();

                // Pick the char set encoding from the msgContext
                String charSetEnc =
                        (String) msgContext
                                .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);

                format.setDoOptimize(false);
                format.setDoingSWA(false);
                format.setCharSetEncoding(charSetEnc);
                outputMessage.serializeAndConsume(out, format);
                out.flush();
            } catch (Exception e) {
                throw AxisFault.makeFault(e);
            }
        } else {
            throw new AxisFault(Messages.getMessage("outMessageNull"));
        }
    }




    /**
     * @param contentType          The contentType of the incoming message.  It may be null
     * @param defaultSOAPNamespace Usually set the version that is expected.  This a fallback if the contentType is unavailable or
     *                             does not match our expectations
     * @return null or the soap namespace.  A null indicates that the message will be interpretted as a non-SOAP (i.e. REST) message
     */
    private static String getSOAPNamespaceFromContentType(String contentType,
                                                          String defaultSOAPNamespace) {

        String returnNS = defaultSOAPNamespace;
        // Discriminate using the content Type
        if (contentType != null) {

            /*
            * SOAP11 content-type is "text/xml"
            * SOAP12 content-type is "application/soap+xml"
            *
            * What about other content-types?
            *
            * TODO: I'm not fully convinced this method is complete, given the media types
            * listed in HTTPConstants.  Should we assume all application/* is SOAP12?
            * Should we assume all text/* is SOAP11?
            *
            * So, we'll follow this pattern:
            * 1)  find the content-type main setting
            * 2)  if (1) not understood, find the "type=" param
            * Thilina: I merged (1) & (2)
            */

            if (JavaUtils.indexOfIgnoreCase(contentType, SOAP12Constants.SOAP_12_CONTENT_TYPE) > -1)
            {
                returnNS = SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI;
            }
            // search for "type=text/xml"
            else
            if (JavaUtils.indexOfIgnoreCase(contentType, SOAP11Constants.SOAP_11_CONTENT_TYPE) > -1)
            {
                returnNS = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
            }
        }

        if (returnNS == null) {
            if (log.isDebugEnabled()) {
                log.debug("No content-type or \"type=\" parameter was found in the content-type " +
                        "header and no default was specified, thus defaulting to SOAP 1.1.");
            }
            returnNS = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
        }

        if (log.isDebugEnabled()) {
            log.debug("content-type: " + contentType);
            log.debug("defaultSOAPNamespace: " + defaultSOAPNamespace);
            log.debug("Returned namespace: " + returnNS);
        }
        return returnNS;

    }

    public static void processContentTypeForAction(String contentType, MessageContext msgContext) {
        //Check for action header and set it in as soapAction in MessageContext
        int index = contentType.indexOf("action");
        if (index > -1) {
            String transientString = contentType.substring(index, contentType.length());
            int equal = transientString.indexOf("=");
            int firstSemiColon = transientString.indexOf(";");
            String soapAction; // This will contain "" in the string
            if (firstSemiColon > -1) {
                soapAction = transientString.substring(equal + 1, firstSemiColon);
            } else {
                soapAction = transientString.substring(equal + 1, transientString.length());
            }
            if ((soapAction != null) && soapAction.startsWith("\"")
                    && soapAction.endsWith("\"")) {
                soapAction = soapAction
                        .substring(1, soapAction.length() - 1);
            }
            msgContext.setSoapAction(soapAction);
        }
    }

    /**
     * This is a helper method to get the response written flag from the RequestResponseTransport
     * instance.
     */
    public static boolean isResponseWritten(MessageContext messageContext) {
        RequestResponseTransport reqResTransport = getRequestResponseTransport(messageContext);
        if (reqResTransport != null) {
            if (log.isDebugEnabled()) {
                log.debug("Found RequestResponseTransport returning isResponseWritten()");
            }
            return reqResTransport.isResponseWritten();
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Did not find RequestResponseTransport returning false from get"
                        + "ResponseWritten()");
            }
            return false;
        }
    }

    /**
     * This is a helper method to set the response written flag on the RequestResponseTransport
     * instance.
     */
    public static void setResponseWritten(MessageContext messageContext, boolean responseWritten) {
        RequestResponseTransport reqResTransport = getRequestResponseTransport(messageContext);
        if (reqResTransport != null) {
            if (log.isDebugEnabled()) {
                log.debug("Found RequestResponseTransport setting response written");
            }
            reqResTransport.setResponseWritten(responseWritten);
        } else {
            if (log.isDebugEnabled()) {
               log.debug("Did not find RequestResponseTransport cannot set response written");
            }
        }
    }

    /**
     * This is an internal helper method to retrieve the RequestResponseTransport instance
     * from the MessageContext object. The MessageContext may be the response MessageContext so
     * in that case we will have to retrieve the request MessageContext from the OperationContext.
     */
    private static RequestResponseTransport getRequestResponseTransport(MessageContext messageContext) {
        try {
            // If this is the request MessageContext we should find it directly by the getProperty()
            // method
            RequestResponseTransport transportControl = (RequestResponseTransport)
                    messageContext.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
            
            if (transportControl != null) {
                return transportControl;
            }
            // If this is the response MessageContext we need to look for the request MessageContext
            else if (messageContext.getOperationContext() != null
                    && messageContext.getOperationContext().getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE) != null) {
                return (RequestResponseTransport) messageContext.getOperationContext().getMessageContext(
                        WSDLConstants.MESSAGE_LABEL_IN_VALUE).getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
            }
            else {
                return null;
            }
        }
        catch(AxisFault af) {
            // probably should not be fatal, so just log the message
            String msg = Messages.getMessage("getMessageContextError", af.toString());
            log.debug(msg);
            return null;
        }
    }

    /**
     * Clean up cached attachment file
     * @param msgContext
     */
    public static void deleteAttachments(MessageContext msgContext) {
        if (log.isDebugEnabled()) {
            log.debug("Entering deleteAttachments()");
        }

        Attachments attachments = msgContext.getAttachmentMap();

        if (attachments != null) {
            // Get the list of Content IDs for the attachments...but does not try to pull the stream for new attachments.
            // (Pulling the stream for new attachments will probably fail...the stream is probably closed)
            List keys = attachments.getContentIDList();
            if (keys != null && keys.size() > 0) {
                String key = null;
                File file = null;
                LifecycleManager lcm = (LifecycleManager)msgContext.getRootContext().getAxisConfiguration().getParameterValue(DeploymentConstants.ATTACHMENTS_LIFECYCLE_MANAGER);                       
                DataSource dataSource = null;
                for (int i = 0; i < keys.size(); i++) {
                    try {
                        key = (String) keys.get(i);
                        dataSource = attachments.getDataHandler(key).getDataSource();
                        if(dataSource instanceof CachedFileDataSource){
                            file = ((CachedFileDataSource)dataSource).getFile();
                            if (log.isDebugEnabled()) {
                                log.debug("Delete cache attachment file: "+file.getName());
                            }
                            if(lcm!=null){
                                if(log.isDebugEnabled()){
                                    log.debug("deleting file using lifecyclemanager");
                                }
                                lcm.delete(file);
                            }else{
                                file.delete();
                            }
                        }
                    }
                    catch (Exception e) {
                        if (log.isDebugEnabled()) {
                            log.debug("Delete cache attachment file failed"+ e.getMessage());
                        }

                        if (file != null) {
                            if(lcm!=null){
                                try{
                                    lcm.deleteOnExit(file);
                                }catch(Exception ex){
                                    file.deleteOnExit();
                                }
                            }
                            else{
                                file.deleteOnExit();
                            }
                        }
                    }
                }
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("Exiting deleteAttachments()");
        }
    }

    /**
     * Prepare the message in the given message context so that the underlying input stream can be
     * closed.
     * 
     * @param msgContext
     */
    public static void detachInputStream(MessageContext msgContext) throws AxisFault {
        if (msgContext != null) {
            OMXMLParserWrapper builder = (OMXMLParserWrapper)msgContext.getProperty(Constants.BUILDER);
            if (builder != null) {
                builder.detach();
            } else {
                Attachments attachments = msgContext.getAttachmentMap(false);
                if (attachments != null) {
                    attachments.getAllContentIDs();
                } else {
                    SOAPEnvelope envelope = msgContext.getEnvelope();
                    if (envelope != null) {
                        envelope.build();
                    }
                }
            }
        }
    }

    /**
     * <p>
     * Checks whether MTOM needs to be enabled for the message represented by
     * the msgContext. We check value assigned to the "enableMTOM" property
     * either using the config files (axis2.xml, services.xml) or
     * programatically. Programatic configuration is given priority. If the
     * given value is "optional", MTOM will be enabled only if the incoming
     * message was an MTOM message.
     * </p>
     *
     * @param msgContext the active MessageContext
     * @return true if SwA needs to be enabled
     */
    public static boolean doWriteMTOM(MessageContext msgContext) {
        boolean enableMTOM;
        Object enableMTOMObject = null;
        // First check the whether MTOM is enabled by the configuration
        // (Eg:Axis2.xml, services.xml)
        Parameter parameter = msgContext.getParameter(Constants.Configuration.ENABLE_MTOM);
        if (parameter != null) {
            enableMTOMObject = parameter.getValue();
        }
        // Check whether the configuration is overridden programatically..
        // Priority given to programatically setting of the value
        Object property = msgContext.getProperty(Constants.Configuration.ENABLE_MTOM);
        if (property != null) {
            enableMTOMObject = property;
        }
        enableMTOM = JavaUtils.isTrueExplicitly(enableMTOMObject);
        // Handle the optional value for enableMTOM
        // If the value for 'enableMTOM' is given as optional and if the request
        // message was a MTOM message we sent out MTOM
        if (!enableMTOM && msgContext.isDoingMTOM() && (enableMTOMObject instanceof String)) {
            if (((String) enableMTOMObject).equalsIgnoreCase(Constants.VALUE_OPTIONAL)) {
                //In server side, we check whether request was MTOM
                if (msgContext.isServerSide()) {
                    if (msgContext.isDoingMTOM()) {
                        enableMTOM = true;
                    }
                    // in the client side, we enable MTOM if it is optional
                } else {
                    enableMTOM = true;
                }
            }
        }
        return enableMTOM;
    }

    /**
     * <p>
     * Checks whether SOAP With Attachments (SwA) needs to be enabled for the
     * message represented by the msgContext. We check value assigned to the
     * "enableSwA" property either using the config files (axis2.xml,
     * services.xml) or programatically. Programatic configuration is given
     * priority. If the given value is "optional", SwA will be enabled only if
     * the incoming message was SwA type.
     * </p>
     *
     * @param msgContext the active MessageContext
     * @return true if SwA needs to be enabled
     */
    public static boolean doWriteSwA(MessageContext msgContext) {
        boolean enableSwA;
        Object enableSwAObject = null;
        // First check the whether SwA is enabled by the configuration
        // (Eg:Axis2.xml, services.xml)
        Parameter parameter = msgContext.getParameter(Constants.Configuration.ENABLE_SWA);
        if (parameter != null) {
            enableSwAObject = parameter.getValue();
        }
        // Check whether the configuration is overridden programatically..
        // Priority given to programatically setting of the value
        Object property = msgContext.getProperty(Constants.Configuration.ENABLE_SWA);
        if (property != null) {
            enableSwAObject = property;
        }
        enableSwA = JavaUtils.isTrueExplicitly(enableSwAObject);
        // Handle the optional value for enableSwA
        // If the value for 'enableSwA' is given as optional and if the request
        // message was a SwA message we sent out SwA
        if (!enableSwA && msgContext.isDoingSwA() && (enableSwAObject instanceof String)) {
            if (((String) enableSwAObject).equalsIgnoreCase(Constants.VALUE_OPTIONAL)) {
                enableSwA = true;
            }
        }
        return enableSwA;
    }

    public static boolean isDoingREST(MessageContext msgContext) {
        boolean enableREST = false;

        // check whether isDoingRest is already true in the message context
        if (msgContext.isDoingREST()) {
            return true;
        }

        Object enableRESTProperty = msgContext.getProperty(Constants.Configuration.ENABLE_REST);
        if (enableRESTProperty != null) {
            enableREST = JavaUtils.isTrueExplicitly(enableRESTProperty);
        }

        msgContext.setDoingREST(enableREST);

        return enableREST;
    }

    /**
     * Utility method to query CharSetEncoding. First look in the
     * MessageContext. If it's not there look in the OpContext. Use the defualt,
     * if it's not given in either contexts.
     *
     * @param msgContext the active MessageContext
     * @return String the CharSetEncoding
     */
    public static String getCharSetEncoding(MessageContext msgContext) {
        String charSetEnc = (String) msgContext
            .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);

        if (charSetEnc == null) {
            OperationContext opctx = msgContext.getOperationContext();
            if (opctx != null) {
                charSetEnc = (String) opctx
                    .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING);
            }
            /**
             * If the char set enc is still not found use the default
             */
            if (charSetEnc == null) {
                charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING;
            }
        }
        return charSetEnc;
    }

}
