1 /**************************************************************** 2 * Licensed to the Apache Software Foundation (ASF) under one * 3 * or more contributor license agreements. See the NOTICE file * 4 * distributed with this work for additional information * 5 * regarding copyright ownership. The ASF licenses this file * 6 * to you under the Apache License, Version 2.0 (the * 7 * "License"); you may not use this file except in compliance * 8 * with the License. You may obtain a copy of the License at * 9 * * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, * 13 * software distributed under the License is distributed on an * 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 15 * KIND, either express or implied. See the License for the * 16 * specific language governing permissions and limitations * 17 * under the License. * 18 ****************************************************************/ 19 20 package org.apache.james.mime4j.message; 21 22 import java.io.BufferedWriter; 23 import java.io.IOException; 24 import java.io.OutputStream; 25 import java.io.OutputStreamWriter; 26 import java.util.Collections; 27 import java.util.Iterator; 28 import java.util.LinkedList; 29 import java.util.List; 30 31 import org.apache.james.mime4j.field.ContentTypeField; 32 import org.apache.james.mime4j.field.Field; 33 import org.apache.james.mime4j.util.CharsetUtil; 34 35 /** 36 * Represents a MIME multipart body (see RFC 2045).A multipart body has a 37 * ordered list of body parts. The multipart body also has a preamble and 38 * epilogue. The preamble consists of whatever characters appear before the 39 * first body part while the epilogue consists of whatever characters come 40 * after the last body part. 41 * 42 * 43 * @version $Id: Multipart.java,v 1.3 2004/10/02 12:41:11 ntherning Exp $ 44 */ 45 public class Multipart implements Body { 46 private String preamble = ""; 47 private String epilogue = ""; 48 private List<BodyPart> bodyParts = new LinkedList<BodyPart>(); 49 private Entity parent = null; 50 private String subType = "alternative"; 51 52 /** 53 * Creates a new empty <code>Multipart</code> instance. 54 */ Multipart()55 public Multipart() { 56 } 57 58 /** 59 * Gets the multipart sub-type. E.g. <code>alternative</code> (the default) 60 * or <code>parallel</code>. See RFC 2045 for common sub-types and their 61 * meaning. 62 * 63 * @return the multipart sub-type. 64 */ getSubType()65 public String getSubType() { 66 return subType; 67 } 68 69 /** 70 * Sets the multipart sub-type. E.g. <code>alternative</code> 71 * or <code>parallel</code>. See RFC 2045 for common sub-types and their 72 * meaning. 73 * 74 * @param subType the sub-type. 75 */ setSubType(String subType)76 public void setSubType(String subType) { 77 this.subType = subType; 78 } 79 80 /** 81 * @see org.apache.james.mime4j.message.Body#getParent() 82 */ getParent()83 public Entity getParent() { 84 return parent; 85 } 86 87 /** 88 * @see org.apache.james.mime4j.message.Body#setParent(org.apache.james.mime4j.message.Entity) 89 */ setParent(Entity parent)90 public void setParent(Entity parent) { 91 this.parent = parent; 92 for (Iterator<BodyPart> it = bodyParts.iterator(); it.hasNext();) { 93 it.next().setParent(parent); 94 } 95 } 96 97 /** 98 * Gets the epilogue. 99 * 100 * @return the epilogue. 101 */ getEpilogue()102 public String getEpilogue() { 103 return epilogue; 104 } 105 106 /** 107 * Sets the epilogue. 108 * 109 * @param epilogue the epilogue. 110 */ setEpilogue(String epilogue)111 public void setEpilogue(String epilogue) { 112 this.epilogue = epilogue; 113 } 114 115 /** 116 * Gets the list of body parts. The list is immutable. 117 * 118 * @return the list of <code>BodyPart</code> objects. 119 */ getBodyParts()120 public List<BodyPart> getBodyParts() { 121 return Collections.unmodifiableList(bodyParts); 122 } 123 124 /** 125 * Sets the list of body parts. 126 * 127 * @param bodyParts the new list of <code>BodyPart</code> objects. 128 */ setBodyParts(List<BodyPart> bodyParts)129 public void setBodyParts(List<BodyPart> bodyParts) { 130 this.bodyParts = bodyParts; 131 for (Iterator<BodyPart> it = bodyParts.iterator(); it.hasNext();) { 132 it.next().setParent(parent); 133 } 134 } 135 136 /** 137 * Adds a body part to the end of the list of body parts. 138 * 139 * @param bodyPart the body part. 140 */ addBodyPart(BodyPart bodyPart)141 public void addBodyPart(BodyPart bodyPart) { 142 bodyParts.add(bodyPart); 143 bodyPart.setParent(parent); 144 } 145 146 /** 147 * Gets the preamble. 148 * 149 * @return the preamble. 150 */ getPreamble()151 public String getPreamble() { 152 return preamble; 153 } 154 155 /** 156 * Sets the preamble. 157 * 158 * @param preamble the preamble. 159 */ setPreamble(String preamble)160 public void setPreamble(String preamble) { 161 this.preamble = preamble; 162 } 163 164 /** 165 * 166 * @see org.apache.james.mime4j.message.Body#writeTo(java.io.OutputStream) 167 */ writeTo(OutputStream out)168 public void writeTo(OutputStream out) throws IOException { 169 String boundary = getBoundary(); 170 List<BodyPart> bodyParts = getBodyParts(); 171 172 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, CharsetUtil.getCharset(getCharset())),8192); 173 174 writer.write(getPreamble() + "\r\n"); 175 176 for (int i = 0; i < bodyParts.size(); i++) { 177 writer.write(boundary + "\r\n"); 178 bodyParts.get(i).writeTo(out); 179 } 180 181 writer.write(getEpilogue() + "\r\n"); 182 writer.write(boundary + "--" + "\r\n"); 183 184 } 185 186 /** 187 * Return the boundory of the parent Entity 188 * 189 * @return boundery 190 */ getBoundary()191 private String getBoundary() { 192 Entity e = getParent(); 193 ContentTypeField cField = (ContentTypeField) e.getHeader().getField( 194 Field.CONTENT_TYPE); 195 return cField.getBoundary(); 196 } 197 getCharset()198 private String getCharset() { 199 Entity e = getParent(); 200 String charString = ((ContentTypeField) e.getHeader().getField(Field.CONTENT_TYPE)).getCharset(); 201 return charString; 202 } 203 } 204