org.apache.axis.attachments.MimeUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.axis.attachments.MimeUtils.java

Source

/*
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed 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.
 */

/**
 * @author Rick Rineholt
 * @author Wouter Cloetens (wouter@mind.be)
 */
package org.apache.axis.attachments;

import org.apache.axis.AxisProperties;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.SessionUtils;
import org.apache.commons.logging.Log;

import java.util.Properties;

/**
 * This class is defines utilities for mime.
 */
public class MimeUtils {

    /** Field log           */
    protected static Log log = LogFactory.getLog(MimeUtils.class.getName());

    /**
     * Determine as efficiently as possible the content length for attachments in a mail Multipart.
     * @param mp is the multipart to be serarched.
     * @return the actual length.
     *
     * @throws javax.mail.MessagingException
     * @throws java.io.IOException
     */
    public static long getContentLength(javax.mail.Multipart mp)
            throws javax.mail.MessagingException, java.io.IOException {

        int totalParts = mp.getCount();
        long totalContentLength = 0;

        for (int i = 0; i < totalParts; ++i) {
            javax.mail.internet.MimeBodyPart bp = (javax.mail.internet.MimeBodyPart) mp.getBodyPart(i);

            totalContentLength += getContentLength(bp);
        }

        String ctype = mp.getContentType();
        javax.mail.internet.ContentType ct = new javax.mail.internet.ContentType(ctype);
        String boundaryStr = ct.getParameter("boundary");
        int boundaryStrLen = boundaryStr.length() + 4; // must add two for -- prefix and another two for crlf

        // there is one more boundary than parts
        // each parts data must have crlf after it.
        // last boundary has an additional --crlf
        return totalContentLength + boundaryStrLen * (totalParts + 1) + 2 * totalParts + +4;
    }

    /**
     * Determine the length for the individual part.
     * @param bp is the part to be searched.
     * @return the length in bytes.
     */
    protected static long getContentLength(javax.mail.internet.MimeBodyPart bp) {

        long headerLength = -1L;
        long dataSize = -1L;

        try {
            headerLength = getHeaderLength(bp);

            javax.activation.DataHandler dh = bp.getDataHandler();
            javax.activation.DataSource ds = dh.getDataSource();

            // Do files our selfs since this is costly to read in. Ask the file system.
            // This is 90% of the use of attachments.
            if (ds instanceof javax.activation.FileDataSource) {
                javax.activation.FileDataSource fdh = (javax.activation.FileDataSource) ds;
                java.io.File df = fdh.getFile();

                if (!df.exists()) {
                    throw new RuntimeException(Messages.getMessage("noFile", df.getAbsolutePath()));
                }

                dataSize = df.length();
            } else {
                dataSize = bp.getSize();

                if (-1 == dataSize) { // Data size is not known so read it the hard way...
                    dataSize = 0;

                    java.io.InputStream in = ds.getInputStream();
                    byte[] readbuf = new byte[64 * 1024];
                    int bytesread;

                    do {
                        bytesread = in.read(readbuf);

                        if (bytesread > 0) {
                            dataSize += bytesread;
                        }
                    } while (bytesread > -1);

                    in.close();
                }
            }
        } catch (Exception e) {
            log.error(Messages.getMessage("exception00"), e);
        }

        return dataSize + headerLength;
    }

    /**
     * Gets the header length for any part.
     * @param bp the part to determine the header length for.
     * @return the length in bytes.
     *
     * @throws javax.mail.MessagingException
     * @throws java.io.IOException
     */
    private static long getHeaderLength(javax.mail.internet.MimeBodyPart bp)
            throws javax.mail.MessagingException, java.io.IOException {

        javax.mail.internet.MimeBodyPart headersOnly = new javax.mail.internet.MimeBodyPart(
                new javax.mail.internet.InternetHeaders(), new byte[0]);

        for (java.util.Enumeration en = bp.getAllHeaders(); en.hasMoreElements();) {
            javax.mail.Header header = (javax.mail.Header) en.nextElement();

            headersOnly.addHeader(header.getName(), header.getValue());
        }

        java.io.ByteArrayOutputStream bas = new java.io.ByteArrayOutputStream(1024 * 16);

        headersOnly.writeTo(bas);
        bas.close();

        return (long) bas.size(); // This has header length plus the crlf part that seperates the data
    }

    // fixme: filter can be replaced as it is not final - is this intended? If
    //  so, document
    // fixme: the fields in filter are not protected - they can be over-written
    /** Field filter           */
    public static String[] filter = new String[] { "Message-ID", "Mime-Version", "Content-Type" };

    /**
     * This routine will the multi part type and write it out to a stream.
     *
     * <p>Note that is does *NOT* pass <code>AxisProperties</code>
     * to <code>javax.mail.Session.getInstance</code>, but instead
     * the System properties.
     * </p>
     * @param os is the output stream to write to.
     * @param mp the multipart that needs to be written to the stream.
     */
    public static void writeToMultiPartStream(java.io.OutputStream os, javax.mail.internet.MimeMultipart mp) {

        try {
            Properties props = AxisProperties.getProperties();

            props.setProperty("mail.smtp.host", "localhost"); // this is a bogus since we will never mail it.

            javax.mail.Session session = javax.mail.Session.getInstance(props, null);
            javax.mail.internet.MimeMessage message = new javax.mail.internet.MimeMessage(session);

            message.setContent(mp);
            message.saveChanges();
            message.writeTo(os, filter);
        } catch (javax.mail.MessagingException e) {
            log.error(Messages.getMessage("javaxMailMessagingException00"), e);
        } catch (java.io.IOException e) {
            log.error(Messages.getMessage("javaIOException00"), e);
        }
    }

    /**
     * This routine will get the content type from a mulit-part mime message.
     *
     * @param mp the MimeMultipart
     * @return the content type
     */
    public static String getContentType(javax.mail.internet.MimeMultipart mp) {
        StringBuffer contentType = new StringBuffer(mp.getContentType());
        // TODO (dims): Commons HttpClient croaks if we don't do this.
        //              Need to get Commons HttpClient fixed.
        for (int i = 0; i < contentType.length();) {
            char ch = contentType.charAt(i);
            if (ch == '\r' || ch == '\n')
                contentType.deleteCharAt(i);
            else
                i++;
        }
        return contentType.toString();
    }

    /**
     * This routine will create a multipart object from the parts and the SOAP content.
     * @param env should be the text for the main root part.
     * @param parts contain a collection of the message parts.
     *
     * @return a new MimeMultipart object
     *
     * @throws org.apache.axis.AxisFault
     */
    public static javax.mail.internet.MimeMultipart createMP(String env, java.util.Collection parts, int sendType)
            throws org.apache.axis.AxisFault {

        javax.mail.internet.MimeMultipart multipart = null;

        try {
            String rootCID = SessionUtils.generateSessionId();

            if (sendType == Attachments.SEND_TYPE_MTOM) {
                multipart = new javax.mail.internet.MimeMultipart("related;type=\"application/xop+xml\"; start=\"<"
                        + rootCID + ">\"; start-info=\"text/xml; charset=utf-8\"");
            } else {
                multipart = new javax.mail.internet.MimeMultipart(
                        "related; type=\"text/xml\"; start=\"<" + rootCID + ">\"");
            }

            javax.mail.internet.MimeBodyPart messageBodyPart = new javax.mail.internet.MimeBodyPart();

            messageBodyPart.setText(env, "UTF-8");
            if (sendType == Attachments.SEND_TYPE_MTOM) {
                messageBodyPart.setHeader("Content-Type",
                        "application/xop+xml; charset=utf-8; type=\"text/xml; charset=utf-8\"");
            } else {
                messageBodyPart.setHeader("Content-Type", "text/xml; charset=UTF-8");
            }
            messageBodyPart.setHeader("Content-Id", "<" + rootCID + ">");
            messageBodyPart.setHeader(HTTPConstants.HEADER_CONTENT_TRANSFER_ENCODING, "binary");
            multipart.addBodyPart(messageBodyPart);

            for (java.util.Iterator it = parts.iterator(); it.hasNext();) {
                org.apache.axis.Part part = (org.apache.axis.Part) it.next();
                javax.activation.DataHandler dh = org.apache.axis.attachments.AttachmentUtils
                        .getActivationDataHandler(part);
                String contentID = part.getContentId();

                messageBodyPart = new javax.mail.internet.MimeBodyPart();

                messageBodyPart.setDataHandler(dh);

                String contentType = part.getContentType();
                if ((contentType == null) || (contentType.trim().length() == 0)) {
                    contentType = dh.getContentType();
                }
                if ((contentType == null) || (contentType.trim().length() == 0)) {
                    contentType = "application/octet-stream";
                }

                messageBodyPart.setHeader(HTTPConstants.HEADER_CONTENT_TYPE, contentType);
                messageBodyPart.setHeader(HTTPConstants.HEADER_CONTENT_ID, "<" + contentID + ">");
                messageBodyPart.setHeader(HTTPConstants.HEADER_CONTENT_TRANSFER_ENCODING, "binary"); // Safe and fastest for anything other than mail;

                for (java.util.Iterator i = part.getNonMatchingMimeHeaders(
                        new String[] { HTTPConstants.HEADER_CONTENT_TYPE, HTTPConstants.HEADER_CONTENT_ID,
                                HTTPConstants.HEADER_CONTENT_TRANSFER_ENCODING }); i.hasNext();) {
                    javax.xml.soap.MimeHeader header = (javax.xml.soap.MimeHeader) i.next();

                    messageBodyPart.setHeader(header.getName(), header.getValue());
                }

                multipart.addBodyPart(messageBodyPart);
            }
        } catch (javax.mail.MessagingException e) {
            log.error(Messages.getMessage("javaxMailMessagingException00"), e);
        }

        return multipart;
    }
}