/*
 * 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.ContentType;
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.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPVersion;
import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.saaj.util.SAAJUtil;
import org.apache.axis2.kernel.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);
            ContentType.Builder contentType;
            if (isEmptyString(contentTypeValue)) {
                contentType = ContentType.builder().setMediaType(attachmentParts.size() > 0 ? MediaType.MULTIPART_RELATED : getMediaType());
            } else {
                contentType = new ContentType(contentTypeValue).toBuilder();
                //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));
                ContentType.Builder soapPartContentType;
                if (isEmptyString(soapPartContentTypeValue)) {
                    soapPartContentType = new ContentType(soapPartContentTypeValue).toBuilder();
                } else {
                    soapPartContentType = ContentType.builder().setMediaType(getMediaType());
                }                
                setCharsetParameter(soapPartContentType);
            } else {
                //Configure charset
                setCharsetParameter(contentType);
            }
            
            mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentType.build().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 {
                ContentType.Builder contentType = new ContentType(getSingleHeaderValue(HTTPConstants.HEADER_CONTENT_TYPE)).toBuilder();
                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() == SOAPVersion.SOAP11);
                
                //Double save the content-type in case anything is updated
                mimeHeaders.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentType.build().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(ContentType.Builder 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");
            }
        }
    }
}
