Example usage for javax.mail.internet ContentType ContentType

List of usage examples for javax.mail.internet ContentType ContentType

Introduction

In this page you can find the example usage for javax.mail.internet ContentType ContentType.

Prototype

public ContentType(String s) throws ParseException 

Source Link

Document

Constructor that takes a Content-Type string.

Usage

From source file:com.cubusmail.mail.MessageHandler.java

/**
 * @param session/*from  ww  w  .  j a  va 2  s .c  om*/
 * @param message
 */
private void init(Session session, MimeMessage message) {

    this.session = session;
    this.message = message;
    try {
        this.readBefore = this.message.isSet(Flag.SEEN);
        String contentType = message.getContentType();
        ContentType type = new ContentType(contentType);
        String charset = type.getParameter("charset");
        if (charset != null) {
            this.charset = charset;
        } else {
            // this.message.setHeader( name, value )
        }
    } catch (MessagingException e) {
        log.warn(e.getMessage());
    }
}

From source file:com.ctriposs.r2.message.rest.QueryTunnelUtil.java

/**
 * Takes a Request object that has been encoded for tunnelling as a POST with an X-HTTP-Override-Method header and
 * creates a new request that represents the intended original request
 *
 * @param request the request to be decoded
 *
 * @return a decoded RestRequest/*from w w w.ja  v a  2 s .c o  m*/
 */
public static RestRequest decode(final RestRequest request)
        throws MessagingException, IOException, URISyntaxException {
    if (request.getHeader(HEADER_METHOD_OVERRIDE) == null) {
        // Not a tunnelled request, just pass thru
        return request;
    }

    String query = null;
    byte[] entity = new byte[0];

    // All encoded requests must have a content type. If the header is missing, ContentType throws an exception
    ContentType contentType = new ContentType(request.getHeader(HEADER_CONTENT_TYPE));

    RestRequestBuilder requestBuilder = request.builder();

    // Get copy of headers and remove the override
    Map<String, String> h = new HashMap<String, String>(request.getHeaders());
    h.remove(HEADER_METHOD_OVERRIDE);

    // Simple case, just extract query params from entity, append to query, and clear entity
    if (contentType.getBaseType().equals(FORM_URL_ENCODED)) {
        query = request.getEntity().asString(Data.UTF_8_CHARSET);
        h.remove(HEADER_CONTENT_TYPE);
        h.remove(CONTENT_LENGTH);
    } else if (contentType.getBaseType().equals(MULTIPART)) {
        // Clear these in case there is no body part
        h.remove(HEADER_CONTENT_TYPE);
        h.remove(CONTENT_LENGTH);

        MimeMultipart multi = new MimeMultipart(new DataSource() {
            @Override
            public InputStream getInputStream() throws IOException {
                return request.getEntity().asInputStream();
            }

            @Override
            public OutputStream getOutputStream() throws IOException {
                return null;
            }

            @Override
            public String getContentType() {
                return request.getHeader(HEADER_CONTENT_TYPE);
            }

            @Override
            public String getName() {
                return null;
            }
        });

        for (int i = 0; i < multi.getCount(); i++) {
            MimeBodyPart part = (MimeBodyPart) multi.getBodyPart(i);

            if (part.isMimeType(FORM_URL_ENCODED) && query == null) {
                // Assume the first segment we come to that is urlencoded is the tunneled query params
                query = IOUtils.toString((InputStream) part.getContent(), UTF8);
            } else if (entity.length <= 0) {
                // Assume the first non-urlencoded content we come to is the intended entity.
                entity = IOUtils.toByteArray((InputStream) part.getContent());
                h.put(CONTENT_LENGTH, Integer.toString(entity.length));
                h.put(HEADER_CONTENT_TYPE, part.getContentType());
            } else {
                // If it's not form-urlencoded and we've already found another section,
                // this has to be be an extra body section, which we have no way to handle.
                // Proceed with the request as if the 1st part we found was the expected body,
                // but log a warning in case some client is constructing a request that doesn't
                // follow the rules.
                String unexpectedContentType = part.getContentType();
                LOG.warn("Unexpected body part in X-HTTP-Method-Override request, type="
                        + unexpectedContentType);
            }
        }
    }

    // Based on what we've found, construct the modified request. It's possible that someone has
    // modified the request URI, adding extra query params for debugging, tracking, etc, so
    // we have to check and append the original query correctly.
    if (query != null && query.length() > 0) {
        String separator = "&";
        String existingQuery = request.getURI().getRawQuery();

        if (existingQuery == null) {
            separator = "?";
        } else if (existingQuery.isEmpty()) {
            // This would mean someone has appended a "?" with no args to the url underneath us
            separator = "";
        }

        requestBuilder.setURI(new URI(request.getURI().toString() + separator + query));
    }
    requestBuilder.setEntity(entity);
    requestBuilder.setHeaders(h);
    requestBuilder.setMethod(request.getHeader(HEADER_METHOD_OVERRIDE));

    return requestBuilder.build();
}

From source file:com.adaptris.core.mail.attachment.MimeMailCreator.java

private String getAttachmentFileName(MimeBodyPart p) throws Exception {
    String filename = null;/*  ww w  . j a  v  a  2  s. c o m*/
    String[] hdr = p.getHeader("Content-Disposition");
    if (hdr != null) {
        ContentDisposition cd = new ContentDisposition(hdr[0]);
        filename = cd.getParameter("filename");
    }
    if (filename == null) {
        hdr = p.getHeader("Content-Type");
        if (hdr != null) {
            ContentType ct = new ContentType(hdr[0]);
            filename = ct.getParameter("name");
        }
    }
    if (filename == null) {
        filename = idGenerator.create(p);
        logR.warn("Could not determine filename for MimeBodyPart, assigning unique filename of {}", filename);

    }
    return filename;
}

From source file:org.trancecode.xproc.step.HttpResponseHandler.java

private ContentType verifyContentType(final ContentType contentMimeType, final String overrideContentType) {
    ContentType overrideMimeType = null;
    try {/*from   w w w.j a  va 2 s .c o m*/
        overrideMimeType = new ContentType(overrideContentType);
    } catch (ParseException e) {
        throw XProcExceptions.xc0030();
    }
    if (StringUtils.equalsIgnoreCase(overrideMimeType.toString(), contentMimeType.toString())) {
        return contentMimeType;
    }
    if (("multipart".equals(contentMimeType.getPrimaryType())
            && !"multipart".equals(overrideMimeType.getPrimaryType()))
            || ("multipart".equals(overrideMimeType.getPrimaryType())
                    && !"multipart".equals(contentMimeType.getPrimaryType()))
            || (contentMimeType.getSubType().contains("xml") || "text".equals(contentMimeType.getPrimaryType())
                    && "image".equals(overrideMimeType.getPrimaryType()))
            || ("image".equals(contentMimeType.getPrimaryType())
                    && (overrideMimeType.getSubType().contains("xml")
                            || "text".equals(overrideMimeType.getPrimaryType())))) {
        throw XProcExceptions.xc0030();
    }
    return overrideMimeType;
}

From source file:crawl.SphinxWrapper.java

private static Document makeDocument(Page page) {
    String url = page.toURL();// w w  w  .j a va 2  s  .co m
    FeatureMap params = Factory.newFeatureMap();

    Document doc = null;

    String docName = shortenUrl(url).replaceAll("[^\\p{ASCII}]", "_") + "_" + Gate.genSym();

    /* Take advantage of the MIME type from the server when
     * constructing the GATE document.      */
    String contentTypeStr = page.getContentType();
    String originalMimeType = null;

    if (contentTypeStr != null) {
        try {
            ContentType contentType = new ContentType(contentTypeStr);
            String mimeType = contentType.getBaseType();
            String encoding = contentType.getParameter("charset");

            // get the content as bytes, and convert it to string using the correct
            // encoding (thanks to Christian Wartena for patch)
            byte[] bContent = page.getContentBytes();
            String sContent = new String(bContent, Charset.forName(encoding));
            params.put(Document.DOCUMENT_STRING_CONTENT_PARAMETER_NAME, sContent);

            if (mimeType != null) {
                if (convertXmlTypes) {
                    originalMimeType = mimeType;
                    mimeType = convertMimeType(mimeType);
                    if (!originalMimeType.equals(mimeType)) {
                        System.out.println("   convert " + originalMimeType + " -> " + mimeType);
                    }
                }
                params.put(Document.DOCUMENT_MIME_TYPE_PARAMETER_NAME, mimeType);
            }

            if (encoding != null) {
                params.put(Document.DOCUMENT_ENCODING_PARAMETER_NAME, encoding);

            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    try {
        doc = (Document) Factory.createResource(DocumentImpl.class.getName(), params, null, docName);
        FeatureMap docFeatures = doc.getFeatures();

        Integer originalLength = page.getLength();
        docFeatures.put("originalLength", originalLength);

        /* Use the Last-Modified HTTP header if available.  */
        long lastModified = page.getLastModified();
        Date date;
        if (lastModified > 0L) {
            date = new Date(lastModified);
        } else {
            date = new Date();
        }
        docFeatures.put("Date", date);

        if (originalMimeType != null) {
            docFeatures.put("originalMimeType", originalMimeType);
        }

        doc.setSourceUrl(page.getURL());
        docFeatures.put("gate.SourceURL", url);
    } catch (ResourceInstantiationException e) {
        System.err.println("WARNING: could not intantiate document " + docName);
        e.printStackTrace();
    }

    return doc;
}

From source file:org.apache.axis2.saaj.SOAPPartImpl.java

/**
 * Construct a SOAP part from the given input stream.
 * The content type (as provided by the MIME headers) must be SOAP 1.1, SOAP 1.2
 * or XOP (MTOM). MIME packages (multipart/related) are not supported and should be
 * parsed using {@link SOAPMessageImpl#SOAPMessageImpl(InputStream, MimeHeaders).
 * <p>/*  w w  w.  j a v  a 2s . c o m*/
 * If the content type is XOP, xop:Include elements will only be replaced if
 * the <code>attachments</code> parameter is not null.
 *
 * @see MessageFactoryImpl#setProcessMTOM(boolean)
 * 
 * @param parentSoapMsg the parent SOAP message
 * @param inputStream the input stream with the content of the SOAP part
 * @param mimeHeaders the MIME headers
 * @param attachments the set of attachments to be used to substitute xop:Include elements
 * @throws SOAPException
 */
public SOAPPartImpl(SOAPMessageImpl parentSoapMsg, InputStream inputStream, MimeHeaders mimeHeaders,
        Attachments attachments) throws SOAPException {
    ContentType contentType = null;
    if (mimeHeaders == null) {
        //TODO : read string from constants
        this.mimeHeaders = new MimeHeaders();
        this.mimeHeaders.addHeader("Content-ID", IDGenerator.generateID());
        this.mimeHeaders.addHeader("content-type", HTTPConstants.MEDIA_TYPE_APPLICATION_SOAP_XML);
    } else {
        String contentTypes[] = mimeHeaders.getHeader(HTTPConstants.CONTENT_TYPE);
        if (contentTypes != null && contentTypes.length > 0) {
            try {
                contentType = new ContentType(contentTypes[0]);
            } catch (ParseException ex) {
                throw new SOAPException("Invalid content type '" + contentTypes[0] + "'");
            }
        }
        this.mimeHeaders = SAAJUtil.copyMimeHeaders(mimeHeaders);
    }

    soapMessage = parentSoapMsg;

    String charset;
    boolean isMTOM;
    String soapEnvelopeNamespaceURI;
    SOAPFactory soapFactory;
    if (contentType == null) {
        charset = null;
        isMTOM = false;
        soapFactory = new SOAP11Factory();
        soapEnvelopeNamespaceURI = null;
    } else {
        String baseType = contentType.getBaseType().toLowerCase();
        String soapContentType;
        if (baseType.equals(MTOMConstants.MTOM_TYPE)) {
            isMTOM = true;
            String typeParam = contentType.getParameter("type");
            if (typeParam == null) {
                throw new SOAPException("Missing 'type' parameter in XOP content type");
            } else {
                soapContentType = typeParam.toLowerCase();
            }
        } else {
            isMTOM = false;
            soapContentType = baseType;
        }

        if (soapContentType.equals(HTTPConstants.MEDIA_TYPE_TEXT_XML)) {
            soapEnvelopeNamespaceURI = SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI;
            soapFactory = new SOAP11Factory();
        } else if (soapContentType.equals(HTTPConstants.MEDIA_TYPE_APPLICATION_SOAP_XML)) {
            soapEnvelopeNamespaceURI = SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI;
            soapFactory = new SOAP12Factory();
        } else {
            throw new SOAPException("Unrecognized content type '" + soapContentType + "'");
        }

        charset = contentType.getParameter("charset");
    }

    XMLStreamReader streamReader;
    try {
        if (charset != null) {
            streamReader = StAXUtils.createXMLStreamReader(inputStream, charset);
        } else {
            streamReader = StAXUtils.createXMLStreamReader(inputStream);
        }
    } catch (XMLStreamException e) {
        throw new SOAPException(e);
    }

    StAXSOAPModelBuilder builder;
    if (isMTOM && attachments != null) {
        builder = new MTOMStAXSOAPModelBuilder(streamReader, soapFactory, attachments,
                soapEnvelopeNamespaceURI);
    } else {
        builder = new StAXSOAPModelBuilder(streamReader, soapFactory, soapEnvelopeNamespaceURI);
    }

    try {
        org.apache.axiom.soap.SOAPEnvelope soapEnvelope = builder.getSOAPEnvelope();
        envelope = new SOAPEnvelopeImpl((org.apache.axiom.soap.impl.dom.SOAPEnvelopeImpl) soapEnvelope);
        envelope.element.build();
        this.document = envelope.getOwnerDocument();
        envelope.setSOAPPartParent(this);
    } catch (Exception e) {
        throw new SOAPException(e);
    }
}

From source file:org.esxx.js.protocol.HTTPHandler.java

@Override
public Object query(Context cx, Scriptable thisObj, Object[] args) throws Exception {
    if (args.length < 1) {
        throw Context.reportRuntimeError("Missing arguments to URI.query().");
    }// ww w .  j av  a 2s.  co m

    final String method = Context.toString(args[0]);
    Scriptable headers = null;
    Object send_obj = null;
    ContentType send_ct = null;
    ContentType recv_ct = null;

    if (args.length >= 2) {
        if (!(args[1] instanceof Scriptable)) {
            throw Context.reportRuntimeError("Second URI.query() argument must be an Object");
        }

        headers = (Scriptable) args[1];
    }

    if (args.length >= 3) {
        send_obj = args[2];
    }

    if (args.length >= 4) {
        send_ct = new ContentType(Context.toString(args[3]));
    }

    if (args.length >= 5) {
        recv_ct = new ContentType(Context.toString(args[4]));
    }

    HttpPost req = new HttpPost(jsuri.getURI()) {
        @Override
        public String getMethod() {
            return method;
        }
    };

    if (headers != null) {
        for (Object p : headers.getIds()) {
            if (p instanceof String) {
                req.addHeader((String) p, Context.toString(headers.get((String) p, headers)));
            }
        }
    }

    if (send_obj != null && send_obj != Context.getUndefinedValue()) {
        attachObject(send_obj, send_ct, req, cx);
    }

    Result result = sendRequest(cx, thisObj, recv_ct, req);

    return makeJSResponse(cx, thisObj, result);
}

From source file:org.apache.axiom.attachments.Attachments.java

/**
* Moves the pointer to the beginning of the first MIME part. Reads
* till first MIME boundary is found or end of stream is reached.
*
* @param inStream// ww  w .j av  a 2  s . c  o  m
* @param contentTypeString
* @param fileCacheEnable
* @param attachmentRepoDir
* @param fileThreshold
* @param contentLength
* @throws OMException
*/
public Attachments(LifecycleManager manager, InputStream inStream, String contentTypeString,
        boolean fileCacheEnable, String attachmentRepoDir, String fileThreshold, int contentLength)
        throws OMException {
    this.manager = manager;
    this.contentLength = contentLength;
    this.attachmentRepoDir = attachmentRepoDir;
    this.fileCacheEnable = fileCacheEnable;
    if (log.isDebugEnabled()) {
        log.debug("Attachments contentLength=" + contentLength + ", contentTypeString=" + contentTypeString);
    }
    if (fileThreshold != null && (!"".equals(fileThreshold))) {
        this.fileStorageThreshold = Integer.parseInt(fileThreshold);
    } else {
        this.fileStorageThreshold = 1;
    }
    attachmentsMap = new TreeMap();
    try {
        contentType = new ContentType(contentTypeString);
    } catch (ParseException e) {
        throw new OMException("Invalid Content Type Field in the Mime Message", e);
    }
    // REVIEW: This conversion is hard-coded to UTF-8.
    // The complete solution is to respect the charset setting of the message.
    // However this may cause problems in BoundaryDelimittedStream and other
    // lower level classes.

    // Boundary always have the prefix "--".
    try {
        String encoding = contentType.getParameter("charset");
        if (encoding == null || encoding.length() == 0) {
            encoding = "UTF-8";
        }
        String boundaryParam = contentType.getParameter("boundary");
        if (boundaryParam == null) {
            throw new OMException("Content-type has no 'boundary' parameter");
        }
        this.boundary = ("--" + boundaryParam).getBytes(encoding);
        if (log.isDebugEnabled()) {
            log.debug("boundary=" + new String(this.boundary));
        }
    } catch (UnsupportedEncodingException e) {
        throw new OMException(e);
    }

    // If the length is not known, install a TeeInputStream
    // so that we can retrieve it later.
    InputStream is = inStream;
    if (contentLength <= 0) {
        filterIS = new DetachableInputStream(inStream);
        is = filterIS;
    }
    pushbackInStream = new PushbackInputStream(is, PUSHBACK_SIZE);

    // Move the read pointer to the beginning of the first part
    // read till the end of first boundary
    while (true) {
        int value;
        try {
            value = pushbackInStream.read();
            if ((byte) value == boundary[0]) {
                int boundaryIndex = 0;
                while ((boundaryIndex < boundary.length) && ((byte) value == boundary[boundaryIndex])) {
                    value = pushbackInStream.read();
                    if (value == -1) {
                        throw new OMException(
                                "Unexpected End of Stream while searching for first Mime Boundary");
                    }
                    boundaryIndex++;
                }
                if (boundaryIndex == boundary.length) { // boundary found
                    pushbackInStream.read();
                    break;
                }
            } else if (value == -1) {
                throw new OMException("Mime parts not found. Stream ended while searching for the boundary");
            }
        } catch (IOException e1) {
            throw new OMException("Stream Error" + e1.toString(), e1);
        }
    }

    // Read the SOAP part and cache it
    getDataHandler(getSOAPPartContentID());

    // Now reset partsRequested. SOAP part is a special case which is always 
    // read beforehand, regardless of request.
    partsRequested = false;
}

From source file:mx.uaq.facturacion.enlace.EmailParserUtils.java

/**
 * Parses any {@link Multipart} instances that contain text or Html attachments,
 * {@link InputStream} instances, additional instances of {@link Multipart}
 * or other attached instances of {@link javax.mail.Message}.
 *
 * Will create the respective {@link EmailFragment}s representing those attachments.
 *
 * Instances of {@link javax.mail.Message} are delegated to
 * {@link #handleMessage(File, javax.mail.Message, List)}. Further instances
 * of {@link Multipart} are delegated to
 * {@link #handleMultipart(File, Multipart, javax.mail.Message, List)}.
 *
 * @param directory Must not be null/*ww w.j a v  a2s .  c om*/
 * @param multipart Must not be null
 * @param mailMessage Must not be null
 * @param emailFragments Must not be null
 */
public static void handleMultipart(File directory, Multipart multipart, javax.mail.Message mailMessage,
        List<EmailFragment> emailFragments) {

    Assert.notNull(directory, "The directory must not be null.");
    Assert.notNull(multipart, "The multipart object to be parsed must not be null.");
    Assert.notNull(mailMessage, "The mail message to be parsed must not be null.");
    Assert.notNull(emailFragments, "The collection of emailfragments must not be null.");

    final int count;

    try {
        count = multipart.getCount();

        if (LOGGER.isInfoEnabled()) {
            LOGGER.info(String.format("Number of enclosed BodyPart objects: %s.", count));
        }

    } catch (MessagingException e) {
        throw new IllegalStateException("Error while retrieving the number of enclosed BodyPart objects.", e);
    }

    for (int i = 0; i < count; i++) {

        final BodyPart bp;

        try {
            bp = multipart.getBodyPart(i);
        } catch (MessagingException e) {
            throw new IllegalStateException("Error while retrieving body part.", e);
        }

        final String contentType;
        String filename;
        final String disposition;
        final String subject;

        try {

            contentType = bp.getContentType();
            filename = bp.getFileName();
            disposition = bp.getDisposition();
            subject = mailMessage.getSubject();

            if (filename == null && bp instanceof MimeBodyPart) {
                filename = ((MimeBodyPart) bp).getContentID();
            }

        } catch (MessagingException e) {
            throw new IllegalStateException("Unable to retrieve body part meta data.", e);
        }

        if (LOGGER.isInfoEnabled()) {
            LOGGER.info(String.format(
                    "BodyPart - Content Type: '%s', filename: '%s', disposition: '%s', subject: '%s'",
                    new Object[] { contentType, filename, disposition, subject }));
        }

        if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
            LOGGER.info(String.format("Handdling attachment '%s', type: '%s'", filename, contentType));
        }

        final Object content;

        try {
            content = bp.getContent();
        } catch (IOException e) {
            throw new IllegalStateException("Error while retrieving the email contents.", e);
        } catch (MessagingException e) {
            throw new IllegalStateException("Error while retrieving the email contents.", e);
        }

        if (content instanceof String) {

            if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
                emailFragments.add(new EmailFragment(directory, i + "-" + filename, content));
                LOGGER.info(String.format("Handdling attachment '%s', type: '%s'", filename, contentType));
            } else {

                final String textFilename;
                final ContentType ct;

                try {
                    ct = new ContentType(contentType);
                } catch (ParseException e) {
                    throw new IllegalStateException("Error while parsing content type '" + contentType + "'.",
                            e);
                }

                if ("text/plain".equalsIgnoreCase(ct.getBaseType())) {
                    textFilename = "message.txt";
                } else if ("text/html".equalsIgnoreCase(ct.getBaseType())) {
                    textFilename = "message.html";
                } else {
                    textFilename = "message.other";
                }

                emailFragments.add(new EmailFragment(directory, textFilename, content));
            }

        } else if (content instanceof InputStream) {

            final InputStream inputStream = (InputStream) content;
            final ByteArrayOutputStream bis = new ByteArrayOutputStream();

            try {
                IOUtils.copy(inputStream, bis);
            } catch (IOException e) {
                throw new IllegalStateException(
                        "Error while copying input stream to the ByteArrayOutputStream.", e);
            }

            emailFragments.add(new EmailFragment(directory, filename, bis.toByteArray()));

        } else if (content instanceof javax.mail.Message) {
            handleMessage(directory, (javax.mail.Message) content, emailFragments);
        } else if (content instanceof Multipart) {
            final Multipart mp2 = (Multipart) content;
            handleMultipart(directory, mp2, mailMessage, emailFragments);
        } else {
            throw new IllegalStateException("Content type not handled: " + content.getClass().getSimpleName());
        }
    }
}

From source file:com.linkedin.r2.message.rest.QueryTunnelUtil.java

/**
 * Takes a Request object that has been encoded for tunnelling as a POST with an X-HTTP-Override-Method header and
 * creates a new request that represents the intended original request
 *
 * @param request the request to be decoded
 * @param requestContext a RequestContext object associated with the request
 *
 * @return a decoded RestRequest//from   w  ww.  j  a  v  a2s  .  c  om
 */
public static RestRequest decode(final RestRequest request, RequestContext requestContext)
        throws MessagingException, IOException, URISyntaxException {
    if (request.getHeader(HEADER_METHOD_OVERRIDE) == null) {
        // Not a tunnelled request, just pass thru
        return request;
    }

    String query = null;
    byte[] entity = new byte[0];

    // All encoded requests must have a content type. If the header is missing, ContentType throws an exception
    ContentType contentType = new ContentType(request.getHeader(HEADER_CONTENT_TYPE));

    RestRequestBuilder requestBuilder = request.builder();

    // Get copy of headers and remove the override
    Map<String, String> h = new HashMap<String, String>(request.getHeaders());
    h.remove(HEADER_METHOD_OVERRIDE);

    // Simple case, just extract query params from entity, append to query, and clear entity
    if (contentType.getBaseType().equals(FORM_URL_ENCODED)) {
        query = request.getEntity().asString(Data.UTF_8_CHARSET);
        h.remove(HEADER_CONTENT_TYPE);
        h.remove(CONTENT_LENGTH);
    } else if (contentType.getBaseType().equals(MULTIPART)) {
        // Clear these in case there is no body part
        h.remove(HEADER_CONTENT_TYPE);
        h.remove(CONTENT_LENGTH);

        MimeMultipart multi = new MimeMultipart(new DataSource() {
            @Override
            public InputStream getInputStream() throws IOException {
                return request.getEntity().asInputStream();
            }

            @Override
            public OutputStream getOutputStream() throws IOException {
                return null;
            }

            @Override
            public String getContentType() {
                return request.getHeader(HEADER_CONTENT_TYPE);
            }

            @Override
            public String getName() {
                return null;
            }
        });

        for (int i = 0; i < multi.getCount(); i++) {
            MimeBodyPart part = (MimeBodyPart) multi.getBodyPart(i);

            if (part.isMimeType(FORM_URL_ENCODED) && query == null) {
                // Assume the first segment we come to that is urlencoded is the tunneled query params
                query = IOUtils.toString((InputStream) part.getContent(), UTF8);
            } else if (entity.length <= 0) {
                // Assume the first non-urlencoded content we come to is the intended entity.
                Object content = part.getContent();
                if (content instanceof MimeMultipart) {
                    ByteArrayOutputStream os = new ByteArrayOutputStream();
                    ((MimeMultipart) content).writeTo(os);
                    entity = os.toByteArray();
                } else {
                    entity = IOUtils.toByteArray((InputStream) content);
                }
                h.put(CONTENT_LENGTH, Integer.toString(entity.length));
                h.put(HEADER_CONTENT_TYPE, part.getContentType());
            } else {
                // If it's not form-urlencoded and we've already found another section,
                // this has to be be an extra body section, which we have no way to handle.
                // Proceed with the request as if the 1st part we found was the expected body,
                // but log a warning in case some client is constructing a request that doesn't
                // follow the rules.
                String unexpectedContentType = part.getContentType();
                LOG.warn("Unexpected body part in X-HTTP-Method-Override request, type="
                        + unexpectedContentType);
            }
        }
    }

    // Based on what we've found, construct the modified request. It's possible that someone has
    // modified the request URI, adding extra query params for debugging, tracking, etc, so
    // we have to check and append the original query correctly.
    if (query != null && query.length() > 0) {
        String separator = "&";
        String existingQuery = request.getURI().getRawQuery();

        if (existingQuery == null) {
            separator = "?";
        } else if (existingQuery.isEmpty()) {
            // This would mean someone has appended a "?" with no args to the url underneath us
            separator = "";
        }

        requestBuilder.setURI(new URI(request.getURI().toString() + separator + query));
    }
    requestBuilder.setEntity(entity);
    requestBuilder.setHeaders(h);
    requestBuilder.setMethod(request.getHeader(HEADER_METHOD_OVERRIDE));

    requestContext.putLocalAttr(R2Constants.IS_QUERY_TUNNELED, true);

    return requestBuilder.build();
}