/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://oss.oracle.com/licenses/CDDL+GPL-1.1
 * or LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package javax.mail;

import java.util.Vector;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import javax.activation.DataSource;

Multipart is a container that holds multiple body parts. Multipart provides methods to retrieve and set its subparts.

Multipart also acts as the base class for the content object returned by most Multipart DataContentHandlers. For example, invoking getContent() on a DataHandler whose source is a "multipart/signed" data source may return an appropriate subclass of Multipart.

Some messaging systems provide different subtypes of Multiparts. For example, MIME specifies a set of subtypes that include "alternative", "mixed", "related", "parallel", "signed", etc.

Multipart is an abstract class. Subclasses provide actual implementations.

Author:John Mani
/** * Multipart is a container that holds multiple body parts. Multipart * provides methods to retrieve and set its subparts. <p> * * Multipart also acts as the base class for the content object returned * by most Multipart DataContentHandlers. For example, invoking getContent() * on a DataHandler whose source is a "multipart/signed" data source may * return an appropriate subclass of Multipart. <p> * * Some messaging systems provide different subtypes of Multiparts. For * example, MIME specifies a set of subtypes that include "alternative", * "mixed", "related", "parallel", "signed", etc. <p> * * Multipart is an abstract class. Subclasses provide actual implementations. * * @author John Mani */
public abstract class Multipart {
Vector of BodyPart objects.
/** * Vector of BodyPart objects. */
protected Vector<BodyPart> parts = new Vector<>(); // Holds BodyParts
This field specifies the content-type of this multipart object. It defaults to "multipart/mixed".
/** * This field specifies the content-type of this multipart * object. It defaults to "multipart/mixed". */
protected String contentType = "multipart/mixed"; // Content-Type
The Part containing this Multipart, if known.
Since: JavaMail 1.1
/** * The <code>Part</code> containing this <code>Multipart</code>, * if known. * @since JavaMail 1.1 */
protected Part parent;
Default constructor. An empty Multipart object is created.
/** * Default constructor. An empty Multipart object is created. */
protected Multipart() { }
Setup this Multipart object from the given MultipartDataSource.

The method adds the MultipartDataSource's BodyPart objects into this Multipart. This Multipart's contentType is set to that of the MultipartDataSource.

This method is typically used in those cases where one has a multipart data source that has already been pre-parsed into the individual body parts (for example, an IMAP datasource), but needs to create an appropriate Multipart subclass that represents a specific multipart subtype.

Params:
  • mp – Multipart datasource
Throws:
/** * Setup this Multipart object from the given MultipartDataSource. <p> * * The method adds the MultipartDataSource's BodyPart * objects into this Multipart. This Multipart's contentType is * set to that of the MultipartDataSource. <p> * * This method is typically used in those cases where one * has a multipart data source that has already been pre-parsed into * the individual body parts (for example, an IMAP datasource), but * needs to create an appropriate Multipart subclass that represents * a specific multipart subtype. * * @param mp Multipart datasource * @exception MessagingException for failures */
protected synchronized void setMultipartDataSource(MultipartDataSource mp) throws MessagingException { contentType = mp.getContentType(); int count = mp.getCount(); for (int i = 0; i < count; i++) addBodyPart(mp.getBodyPart(i)); }
Return the content-type of this Multipart.

This implementation just returns the value of the contentType field.

See Also:
Returns: content-type
/** * Return the content-type of this Multipart. <p> * * This implementation just returns the value of the * <code>contentType</code> field. * * @return content-type * @see #contentType */
public synchronized String getContentType() { return contentType; }
Return the number of enclosed BodyPart objects.

Throws:
See Also:
Returns: number of parts
/** * Return the number of enclosed BodyPart objects. <p> * * @return number of parts * @exception MessagingException for failures * @see #parts */
public synchronized int getCount() throws MessagingException { if (parts == null) return 0; return parts.size(); }
Get the specified Part. Parts are numbered starting at 0.
Params:
  • index – the index of the desired Part
Throws:
Returns: the Part
/** * Get the specified Part. Parts are numbered starting at 0. * * @param index the index of the desired Part * @return the Part * @exception IndexOutOfBoundsException if the given index * is out of range. * @exception MessagingException for other failures */
public synchronized BodyPart getBodyPart(int index) throws MessagingException { if (parts == null) throw new IndexOutOfBoundsException("No such BodyPart"); return parts.elementAt(index); }
Remove the specified part from the multipart message. Shifts all the parts after the removed part down one.
Params:
  • part – The part to remove
Throws:
Returns: true if part removed, false otherwise
/** * Remove the specified part from the multipart message. * Shifts all the parts after the removed part down one. * * @param part The part to remove * @return true if part removed, false otherwise * @exception MessagingException if no such Part exists * @exception IllegalWriteException if the underlying * implementation does not support modification * of existing values */
public synchronized boolean removeBodyPart(BodyPart part) throws MessagingException { if (parts == null) throw new MessagingException("No such body part"); boolean ret = parts.removeElement(part); part.setParent(null); return ret; }
Remove the part at specified location (starting from 0). Shifts all the parts after the removed part down one.
Params:
  • index – Index of the part to remove
Throws:
/** * Remove the part at specified location (starting from 0). * Shifts all the parts after the removed part down one. * * @param index Index of the part to remove * @exception IndexOutOfBoundsException if the given index * is out of range. * @exception IllegalWriteException if the underlying * implementation does not support modification * of existing values * @exception MessagingException for other failures */
public synchronized void removeBodyPart(int index) throws MessagingException { if (parts == null) throw new IndexOutOfBoundsException("No such BodyPart"); BodyPart part = parts.elementAt(index); parts.removeElementAt(index); part.setParent(null); }
Adds a Part to the multipart. The BodyPart is appended to the list of existing Parts.
Params:
  • part – The Part to be appended
Throws:
/** * Adds a Part to the multipart. The BodyPart is appended to * the list of existing Parts. * * @param part The Part to be appended * @exception IllegalWriteException if the underlying * implementation does not support modification * of existing values * @exception MessagingException for other failures */
public synchronized void addBodyPart(BodyPart part) throws MessagingException { if (parts == null) parts = new Vector<>(); parts.addElement(part); part.setParent(this); }
Adds a BodyPart at position index. If index is not the last one in the list, the subsequent parts are shifted up. If index is larger than the number of parts present, the BodyPart is appended to the end.
Params:
  • part – The BodyPart to be inserted
  • index – Location where to insert the part
Throws:
/** * Adds a BodyPart at position <code>index</code>. * If <code>index</code> is not the last one in the list, * the subsequent parts are shifted up. If <code>index</code> * is larger than the number of parts present, the * BodyPart is appended to the end. * * @param part The BodyPart to be inserted * @param index Location where to insert the part * @exception IllegalWriteException if the underlying * implementation does not support modification * of existing values * @exception MessagingException for other failures */
public synchronized void addBodyPart(BodyPart part, int index) throws MessagingException { if (parts == null) parts = new Vector<>(); parts.insertElementAt(part, index); part.setParent(this); }
Output an appropriately encoded bytestream to the given OutputStream. The implementation subclass decides the appropriate encoding algorithm to be used. The bytestream is typically used for sending.
Params:
  • os – the stream to write to
Throws:
/** * Output an appropriately encoded bytestream to the given * OutputStream. The implementation subclass decides the * appropriate encoding algorithm to be used. The bytestream * is typically used for sending. * * @param os the stream to write to * @exception IOException if an IO related exception occurs * @exception MessagingException for other failures */
public abstract void writeTo(OutputStream os) throws IOException, MessagingException;
Return the Part that contains this Multipart object, or null if not known.
Returns: the parent Part
Since: JavaMail 1.1
/** * Return the <code>Part</code> that contains this <code>Multipart</code> * object, or <code>null</code> if not known. * * @return the parent Part * @since JavaMail 1.1 */
public synchronized Part getParent() { return parent; }
Set the parent of this Multipart to be the specified Part. Normally called by the Message or BodyPart setContent(Multipart) method. parent may be null if the Multipart is being removed from its containing Part.
Params:
  • parent – the parent Part
Since: JavaMail 1.1
/** * Set the parent of this <code>Multipart</code> to be the specified * <code>Part</code>. Normally called by the <code>Message</code> * or <code>BodyPart</code> <code>setContent(Multipart)</code> method. * <code>parent</code> may be <code>null</code> if the * <code>Multipart</code> is being removed from its containing * <code>Part</code>. * * @param parent the parent Part * @since JavaMail 1.1 */
public synchronized void setParent(Part parent) { this.parent = parent; } }