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

import org.apache.axiom.attachments.Attachments;
import org.apache.axiom.mime.ContentTypeBuilder;
import org.apache.axiom.mime.MediaType;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.impl.OMMultipartWriter;
import org.apache.axiom.soap.SOAP11Version;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.saaj.util.SAAJUtil;
import org.apache.axis2.transport.http.HTTPConstants;

import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

public class SOAPMessageImpl extends SOAPMessage {

    private SOAPPart soapPart;
    private Collection<AttachmentPart> attachmentParts = new ArrayList<AttachmentPart>();
    private MimeHeaders mimeHeaders;

    private Map<String,Object> props = new Hashtable<String,Object>();
    private boolean saveRequired;

    public SOAPMessageImpl(SOAPEnvelopeImpl soapEnvelope) {
        this.mimeHeaders = new MimeHeaders();
        this.mimeHeaders.addHeader("content-type", ((SOAPFactory)soapEnvelope.omTarget.getOMFactory()).getSOAPVersion().getMediaType().toString());
        soapPart = new SOAPPartImpl(this, soapEnvelope);
    }

    public SOAPMessageImpl(InputStream inputstream, MimeHeaders mimeHeaders, boolean processMTOM)
            throws SOAPException {
        String contentType = null;
        String tmpContentType = "";
        if (mimeHeaders != null) {
            String contentTypes[] = mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE);
            if (contentTypes != null && contentTypes.length > 0) {
                tmpContentType = contentTypes[0];
                contentType = SAAJUtil.normalizeContentType(tmpContentType);
            }
        }
        if (HTTPConstants.MEDIA_TYPE_MULTIPART_RELATED.equals(contentType)) {
            try {
                Attachments attachments =
                        new Attachments(inputstream, tmpContentType, false, "", "");
                
                // Axiom doesn't give us access to the MIME headers of the individual
                // parts of the SOAP message package. We need to reconstruct them from
                // the available information.
                MimeHeaders soapPartHeaders = new MimeHeaders();
                soapPartHeaders.addHeader(HTTPConstants.HEADER_CONTENT_TYPE,
                        attachments.getRootPartContentType());
                String soapPartContentId = attachments.getRootPartContentID();
                soapPartHeaders.addHeader("Content-ID", "<" + soapPartContentId + ">");
                
                soapPart = new SOAPPartImpl(this, attachments.getRootPartInputStream(),
                        soapPartHeaders, processMTOM ? attachments : null);
                
                for (String contentId : attachments.getAllContentIDs()) {
                    if (!contentId.equals(soapPartContentId)) {
                        AttachmentPart ap =
                                createAttachmentPart(attachments.getDataHandler(contentId));
                        ap.setContentId("<" + contentId + ">");
                        attachmentParts.add(ap);
                    }
                }
            } catch (OMException e) {
                throw new SOAPException(e);
            }
        } else {
            initCharsetEncodingFromContentType(tmpContentType);
            soapPart = new SOAPPartImpl(this, inputstream, mimeHeaders, null);
        }

        this.mimeHeaders = (mimeHeaders == null) ?
                new MimeHeaders() :
                SAAJUtil.copyMimeHeaders(mimeHeaders);
    }

    /**
     * Retrieves a description of this <CODE>SOAPMessage</CODE> object's content.
     *
     * @return a <CODE>String</CODE> describing the content of this message or <CODE>null</CODE> if
     *         no description has been set
     * @see #setContentDescription(String) setContentDescription(java.lang.String)
     */
    public String getContentDescription() {
        String values[] = mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION);
        if (values != null && values.length > 0) {
            return values[0];
        }
        return null;
    }

    /**
     * Sets the description of this <CODE>SOAPMessage</CODE> object's content with the given
     * description.
     *
     * @param description a <CODE>String</CODE> describing the content of this message
     * @see #getContentDescription() getContentDescription()
     */
    public void setContentDescription(String description) {
        mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_DESCRIPTION, description);
    }

    /**
     * Gets the SOAP part of this <CODE>SOAPMessage</CODE> object.
     * <p/>
     * <p/>
     * <P>If a <CODE>SOAPMessage</CODE> object contains one or more attachments, the SOAP Part must
     * be the first MIME body part in the message.</P>
     *
     * @return the <CODE>SOAPPart</CODE> object for this <CODE> SOAPMessage</CODE> object
     */
    public SOAPPart getSOAPPart() {
        return soapPart;
    }

    /**
     * Removes all <CODE>AttachmentPart</CODE> objects that have been added to this
     * <CODE>SOAPMessage</CODE> object.
     * <p/>
     * <P>This method does not touch the SOAP part.</P>
     */
    public void removeAllAttachments() {
        attachmentParts.clear();
        saveRequired = true;
    }

    /**
     * Gets a count of the number of attachments in this message. This count does not include the
     * SOAP part.
     *
     * @return the number of <CODE>AttachmentPart</CODE> objects that are part of this
     *         <CODE>SOAPMessage</CODE> object
     */
    public int countAttachments() {
        return attachmentParts.size();
    }

    /**
     * Retrieves all the <CODE>AttachmentPart</CODE> objects that are part of this
     * <CODE>SOAPMessage</CODE> object.
     *
     * @return an iterator over all the attachments in this message
     */
    public Iterator getAttachments() {
        return attachmentParts.iterator();
    }

    /**
     * Retrieves all the AttachmentPart objects that have header entries that match the specified
     * headers. Note that a returned attachment could have headers in addition to those specified.
     *
     * @param headers a {@link javax.xml.soap.MimeHeaders} object containing the MIME headers for
     *                which to search
     * @return an iterator over all attachments({@link javax.xml.soap.AttachmentPart}) that have a
     *         header that matches one of the given headers
     */
    public Iterator getAttachments(javax.xml.soap.MimeHeaders headers) {
        Collection<AttachmentPart> matchingAttachmentParts = new ArrayList<AttachmentPart>();
        Iterator iterator = getAttachments();
        {
            AttachmentPartImpl part;
            while (iterator.hasNext()) {
                part = (AttachmentPartImpl)iterator.next();
                if (part.matches(headers)) {
                    matchingAttachmentParts.add(part);
                }
            }
        }
        return matchingAttachmentParts.iterator();
    }

    /**
     * Adds the given <CODE>AttachmentPart</CODE> object to this <CODE>SOAPMessage</CODE> object. An
     * <CODE> AttachmentPart</CODE> object must be created before it can be added to a message.
     *
     * @param attachmentPart an <CODE> AttachmentPart</CODE> object that is to become part of this
     *                       <CODE>SOAPMessage</CODE> object
     * @throws IllegalArgumentException
     *
     */
    public void addAttachmentPart(AttachmentPart attachmentPart) {
        if (attachmentPart != null) {
            attachmentParts.add(attachmentPart);
            mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, "multipart/related");
            saveRequired = true;
        }
    }

    /**
     * Creates a new empty <CODE>AttachmentPart</CODE> object. Note that the method
     * <CODE>addAttachmentPart</CODE> must be called with this new <CODE>AttachmentPart</CODE>
     * object as the parameter in order for it to become an attachment to this
     * <CODE>SOAPMessage</CODE> object.
     *
     * @return a new <CODE>AttachmentPart</CODE> object that can be populated and added to this
     *         <CODE>SOAPMessage</CODE> object
     */
    public AttachmentPart createAttachmentPart() {
        return new AttachmentPartImpl();
    }

    /**
     * Returns all the transport-specific MIME headers for this <CODE>SOAPMessage</CODE> object in a
     * transport-independent fashion.
     *
     * @return a <CODE>MimeHeaders</CODE> object containing the <CODE>MimeHeader</CODE> objects
     */
    public javax.xml.soap.MimeHeaders getMimeHeaders() {
        return mimeHeaders;
    }

    /**
     * Updates this <CODE>SOAPMessage</CODE> object with all the changes that have been made to it.
     * This method is called automatically when a message is sent or written to by the methods
     * <CODE>ProviderConnection.send</CODE>, <CODE> SOAPConnection.call</CODE>, or <CODE>
     * SOAPMessage.writeTo</CODE>. However, if changes are made to a message that was received or to
     * one that has already been sent, the method <CODE>saveChanges</CODE> needs to be called
     * explicitly in order to save the changes. The method <CODE>saveChanges</CODE> also generates
     * any changes that can be read back (for example, a MessageId in profiles that support a
     * message id). All MIME headers in a message that is created for sending purposes are
     * guaranteed to have valid values only after <CODE>saveChanges</CODE> has been called.
     * <p/>
     * <P>In addition, this method marks the point at which the data from all constituent
     * <CODE>AttachmentPart</CODE> objects are pulled into the message.</P>
     *
     * @throws SOAPException if there was a problem saving changes to this message.
     */
    public void saveChanges() throws SOAPException {
        try {
            String contentTypeValue = getSingleHeaderValue(HTTPConstants.HEADER_CONTENT_TYPE);
            ContentTypeBuilder contentType;
            if (isEmptyString(contentTypeValue)) {
                contentType = new ContentTypeBuilder(attachmentParts.size() > 0 ? MediaType.MULTIPART_RELATED : getMediaType());
            } else {
                contentType = new ContentTypeBuilder(contentTypeValue);
                //Use configures the baseType with multipart/related while no attachment exists or all the attachments are removed
                if (contentType.getMediaType().equals(MediaType.MULTIPART_RELATED) && attachmentParts.size() == 0) {
                    contentType.setMediaType(getMediaType());
                    contentType.clearParameters();
                }
            }
           
            //If it is of multipart/related, initialize those required values in the content-type, including boundary etc.
            if (contentType.getMediaType().equals(MediaType.MULTIPART_RELATED)) {
                
                //Configure boundary
                String boundaryParam = contentType.getParameter("boundary");
                if (isEmptyString(boundaryParam)) {
                    contentType.setParameter("boundary", UIDGenerator.generateMimeBoundary());
                }

                //Configure start content id, always get it from soapPart in case it is changed
                String soapPartContentId = soapPart.getContentId();
                if (isEmptyString(soapPartContentId)) {
                    soapPartContentId = "<" + UIDGenerator.generateContentId() + ">";
                    soapPart.setContentId(soapPartContentId);
                }
                contentType.setParameter("start", soapPartContentId);
                
                //Configure contentId for each attachments
                for(AttachmentPart attachmentPart : attachmentParts) {
                    if(isEmptyString(attachmentPart.getContentId())) {
                        attachmentPart.setContentId("<" + UIDGenerator.generateContentId() + ">");
                    }
                }
                
                //Configure type                
                contentType.setParameter("type", getMediaType().toString());
                
                //Configure charset
                String soapPartContentTypeValue = getSingleHeaderValue(soapPart.getMimeHeader(HTTPConstants.HEADER_CONTENT_TYPE));
                ContentTypeBuilder soapPartContentType = null;
                if (isEmptyString(soapPartContentTypeValue)) {
                    soapPartContentType = new ContentTypeBuilder(soapPartContentTypeValue);
                } else {
                    soapPartContentType = new ContentTypeBuilder(getMediaType());
                }                
                setCharsetParameter(soapPartContentType);
            } else {
                //Configure charset
                setCharsetParameter(contentType);
            }
            
            mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentType.toString());
        } catch (ParseException e) {
            throw new SOAPException("Invalid Content Type Field in the Mime Message", e);
        }

        saveRequired = false;
    }

    public void setSaveRequired() {
        this.saveRequired = true;
    }

    /**
     * Indicates whether this <CODE>SOAPMessage</CODE> object has had the method {@link
     * #saveChanges()} called on it.
     *
     * @return <CODE>true</CODE> if <CODE>saveChanges</CODE> has been called on this message at
     *         least once; <CODE> false</CODE> otherwise.
     */
    public boolean saveRequired() {
        return saveRequired;
    }

    /**
     * Writes this <CODE>SOAPMessage</CODE> object to the given output stream. The externalization
     * format is as defined by the SOAP 1.1 with Attachments specification.
     * <p/>
     * <P>If there are no attachments, just an XML stream is written out. For those messages that
     * have attachments, <CODE>writeTo</CODE> writes a MIME-encoded byte stream.</P>
     *
     * @param out the <CODE>OutputStream</CODE> object to which this <CODE>SOAPMessage</CODE> object
     *            will be written
     * @throws SOAPException if there was a problem in externalizing this SOAP message
     * @throws IOException   if an I/O error occurs
     */
    public void writeTo(OutputStream out) throws SOAPException, IOException {
        try {           
            saveChanges();
            OMOutputFormat format = new OMOutputFormat();
            String enc = (String)getProperty(CHARACTER_SET_ENCODING);
            format.setCharSetEncoding(enc != null ? enc : OMOutputFormat.DEFAULT_CHAR_SET_ENCODING);
            String writeXmlDecl = (String)getProperty(WRITE_XML_DECLARATION);
            if (writeXmlDecl == null || writeXmlDecl.equals("false")) {
                //SAAJ default case doesn't send XML decl
                format.setIgnoreXMLDeclaration(true);
            }
            
            SOAPEnvelope envelope = ((SOAPEnvelopeImpl) soapPart.getEnvelope()).getOMTarget();
            if (attachmentParts.isEmpty()) {
                envelope.serialize(out, format);
            } else {
                ContentTypeBuilder contentType = new ContentTypeBuilder(getSingleHeaderValue(HTTPConstants.HEADER_CONTENT_TYPE));
                String boundary = contentType.getParameter("boundary");
                if(isEmptyString(boundary)) {
                    boundary = UIDGenerator.generateMimeBoundary();
                    contentType.setParameter("boundary", boundary);
                }
                format.setMimeBoundary(boundary);

                String rootContentId = soapPart.getContentId();
                if(isEmptyString(rootContentId)) {
                    rootContentId = "<" + UIDGenerator.generateContentId() + ">";
                    soapPart.setContentId(rootContentId);
                }                
                contentType.setParameter("start", rootContentId);
                if ((rootContentId.indexOf("<") > -1) & (rootContentId.indexOf(">") > -1)) {
                    rootContentId = rootContentId.substring(1, (rootContentId.length() - 1));
                }
                format.setRootContentId(rootContentId);

                format.setSOAP11(((SOAPFactory)((SOAPEnvelopeImpl) soapPart.getEnvelope()).omTarget.getOMFactory()).getSOAPVersion() == SOAP11Version.getSingleton());
                
                //Double save the content-type in case anything is updated
                mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentType.toString());

                OMMultipartWriter mpw = new OMMultipartWriter(out, format);
                OutputStream rootPartOutputStream = mpw.writeRootPart();
                envelope.serialize(rootPartOutputStream);
                rootPartOutputStream.close();
                for (AttachmentPart ap : attachmentParts) {
                    mpw.writePart(ap.getDataHandler(), ap.getContentId());
                }
                mpw.complete();
            }

            saveRequired = true;
        } catch (Exception e) {
            throw new SOAPException(e);
        }
    }

    /**
     * Associates the specified value with the specified property. If there was already a value
     * associated with this property, the old value is replaced.
     * <p/>
     * The valid property names include <code>WRITE_XML_DECLARATION</code> and
     * <code>CHARACTER_SET_ENCODING</code>. All of these standard SAAJ properties are prefixed by
     * "javax.xml.soap". Vendors may also add implementation specific properties. These properties
     * must be prefixed with package names that are unique to the vendor.
     * <p/>
     * Setting the property <code>WRITE_XML_DECLARATION</code> to <code>"true"</code> will cause an
     * XML Declaration to be written out at the start of the SOAP message. The default value of
     * "false" suppresses this declaration.
     * <p/>
     * The property <code>CHARACTER_SET_ENCODING</code> defaults to the value <code>"utf-8"</code>
     * which causes the SOAP message to be encoded using UTF-8. Setting
     * <code>CHARACTER_SET_ENCODING</code> to <code>"utf-16"</code> causes the SOAP message to be
     * encoded using UTF-16.
     * <p/>
     * Some implementations may allow encodings in addition to UTF-8 and UTF-16. Refer to your
     * vendor's documentation for details.
     *
     * @param property the property with which the specified value is to be associated
     * @param value    the value to be associated with the specified property
     */
    public void setProperty(String property, Object value) {
        props.put(property, value);
    }

    /**
     * Retrieves value of the specified property.
     *
     * @param property the name of the property to retrieve
     * @return the value of the property or <code>null</code> if no such property exists
     * @throws SOAPException if the property name is not recognized
     */
    public Object getProperty(String property) throws SOAPException {
        return props.get(property);
    }

    /**
     * Returns an AttachmentPart object that is associated with an attachment that is referenced by
     * this SOAPElement or null if no such attachment exists. References can be made via an href
     * attribute as described in SOAP Messages with Attachments (http://www.w3.org/TR/SOAPattachments#SOAPReferenceToAttachements)
     * , or via a single Text child node containing a URI as described in the WS-I Attachments
     * Profile 1.0 for elements of schema type ref:swaRef(ref:swaRef (http://www.wsi.org/Profiles/AttachmentsProfile-1.0-2004-08-24.html")
     * ). These two mechanisms must be supported. The support for references via href attribute also
     * implies that this method should also be supported on an element that is an xop:Include
     * element (XOP (http://www.w3.org/2000/xp/Group/3/06/Attachments/XOP.html) ). other reference
     * mechanisms may be supported by individual implementations of this standard. Contact your
     * vendor for details.
     *
     * @param element - The SOAPElement containing the reference to an Attachment
     * @return the referenced AttachmentPart or null if no such AttachmentPart exists or no
     *         reference can be found in this SOAPElement.
     * @throws SOAPException - if there is an error in the attempt to access the attachment
     */
    public AttachmentPart getAttachment(SOAPElement soapelement) throws SOAPException {
        //TODO read strings from constants
        Iterator iterator = getAttachments();
        {
            AttachmentPartImpl attachmentPart;
            while (iterator.hasNext()) {
                attachmentPart = (AttachmentPartImpl)iterator.next();
                String[] contentIds = attachmentPart.getMimeHeader("Content-Id");

                //References can be made via an href attribute as described in SOAP Messages
                //with Attachments or via a single Text child node containing a URI
                String reference = soapelement.getAttribute("href");
                if (reference == null || reference.trim().length() == 0) {
                    reference = soapelement.getValue();
                    if (reference == null || reference.trim().length() == 0) {
                        return null;
                    }
                }

                for (int a = 0; a < contentIds.length; a++) {
                    //eg: cid:gifImage scenario
                    String idPart = reference.substring(reference.indexOf(":") + 1);
                    idPart = "<" + idPart + ">";
                    if (idPart.equals(contentIds[a])) {
                        return attachmentPart;
                    }
                }

                String[] contentLocations = attachmentPart.getMimeHeader("Content-Location");
                if (!(contentLocations == null)) {
                    //uri scenario
                    for (int b = 0; b < contentLocations.length; b++) {
                        if (reference.equals(contentLocations[b])) {
                            return attachmentPart;
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * Removes all the AttachmentPart objects that have header entries that match the specified
     * headers. Note that the removed attachment could have headers in addition to those specified.
     *
     * @param headers - a MimeHeaders object containing the MIME headers for which to search
     * @since SAAJ 1.3
     */
    public void removeAttachments(MimeHeaders headers) {
        Collection<AttachmentPart> newAttachmentParts = new ArrayList<AttachmentPart>();
        for (AttachmentPart attachmentPart : attachmentParts) {
            //Get all the headers
            for (Iterator iterator = headers.getAllHeaders(); iterator.hasNext();) {
                MimeHeader mimeHeader = (MimeHeader)iterator.next();
                String[] headerValues = attachmentPart.getMimeHeader(mimeHeader.getName());
                //if values for this header name, do not remove it
                if (headerValues.length != 0) {
                    if (!(headerValues[0].equals(mimeHeader.getValue()))) {
                        newAttachmentParts.add(attachmentPart);
                    }
                }
            }
        }
        attachmentParts.clear();
        this.attachmentParts = newAttachmentParts;
        saveRequired = true;
    }

    /**
     * Gets the SOAP Header contained in this <code>SOAPMessage</code> object.
     *
     * @return the <code>SOAPHeader</code> object contained by this <code>SOAPMessage</code> object
     * @throws javax.xml.soap.SOAPException if the SOAP Header does not exist or cannot be
     *                                      retrieved
     */
    public SOAPHeader getSOAPHeader() throws SOAPException {
        return this.soapPart.getEnvelope().getHeader();
    }

    /**
     * Gets the SOAP Body contained in this <code>SOAPMessage</code> object.
     *
     * @return the <code>SOAPBody</code> object contained by this <code>SOAPMessage</code> object
     * @throws javax.xml.soap.SOAPException if the SOAP Body does not exist or cannot be retrieved
     */
    public SOAPBody getSOAPBody() throws SOAPException {
        return this.soapPart.getEnvelope().getBody();
    }

    /**
     * Set the character encoding based on the <code>contentType</code> parameter
     *
     * @param contentType
     */
    private void initCharsetEncodingFromContentType(final String contentType) {
        if (contentType != null) {
            int delimiterIndex = contentType.lastIndexOf("charset");
            if (delimiterIndex > 0) {
                String charsetPart = contentType.substring(delimiterIndex);
                int charsetIndex = charsetPart.indexOf('=');
                String charset = charsetPart.substring(charsetIndex + 1).trim();
                if ((charset.startsWith("\"") || charset.startsWith("\'"))) {
                    charset = charset.substring(1, charset.length());
                }
                if ((charset.endsWith("\"") || charset.endsWith("\'"))) {
                    charset = charset.substring(0, charset.length() - 1);
                }
                int index = charset.indexOf(';');
                if (index != -1) {
                    charset = charset.substring(0, index);
                }
                setProperty(SOAPMessage.CHARACTER_SET_ENCODING, charset);
            }
        }
    }
    
    private boolean isEmptyString(String value) {
        return value == null || value.length() == 0;
    }
    
    private String getSingleHeaderValue(String[] values) {
        return values != null && values.length > 0 ? values[0] : null;
    }

    private String getSingleHeaderValue(String name) {
        String[] values = mimeHeaders.getHeader(name);
        if (values == null || values.length == 0) {
            return null;
        } else {
            return values[0];
        }
    }
    
    private MediaType getMediaType() throws SOAPException {
        return ((SOAPFactory)((SOAPEnvelopeImpl) soapPart.getEnvelope()).omTarget.getOMFactory()).getSOAPVersion().getMediaType();
    }
    
    /**
     * If the charset is configured by CHARACTER_SET_ENCODING, set it in the contentPart always. 
     * If it has already been configured in the contentType, leave it there.
     * UTF-8 is used as the default value. 
     * @param contentType
     * @throws SOAPException
     */
    private void setCharsetParameter(ContentTypeBuilder contentType) throws SOAPException{
        String charset = (String)getProperty(CHARACTER_SET_ENCODING); 
        if (!isEmptyString(charset)) {
            contentType.setParameter("charset", charset);
        } else {
            charset = contentType.getParameter("charset");
            if(isEmptyString(charset)) {
                contentType.setParameter("charset", "UTF-8");
            }
        }
    }
}
