/* * 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. * *
Note that is does *NOT* pass AxisProperties
* to javax.mail.Session.getInstance
, but instead
* the System properties.
*