1 |
/* |
2 |
* Multipart.java |
3 |
* Copyright(C) 2002 The Free Software Foundation |
4 |
* |
5 |
* This file is part of GNU JavaMail, a library. |
6 |
* |
7 |
* GNU JavaMail is free software; you can redistribute it and/or modify |
8 |
* it under the terms of the GNU General Public License as published by |
9 |
* the Free Software Foundation; either version 2 of the License, or |
10 |
*(at your option) any later version. |
11 |
* |
12 |
* GNU JavaMail is distributed in the hope that it will be useful, |
13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
* GNU General Public License for more details. |
16 |
* |
17 |
* You should have received a copy of the GNU General Public License |
18 |
* along with this library; if not, write to the Free Software |
19 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 |
* |
21 |
* As a special exception, if you link this library with other files to |
22 |
* produce an executable, this library does not by itself cause the |
23 |
* resulting executable to be covered by the GNU General Public License. |
24 |
* This exception does not however invalidate any other reasons why the |
25 |
* executable file might be covered by the GNU General Public License. |
26 |
*/ |
27 |
|
28 |
package javax.mail; |
29 |
|
30 |
import java.io.IOException; |
31 |
import java.io.OutputStream; |
32 |
import java.util.ArrayList; |
33 |
import java.util.List; |
34 |
import javax.activation.DataSource; |
35 |
|
36 |
/** |
37 |
* Multipart is a container that holds multiple body parts. |
38 |
* Multipart provides methods to retrieve and set its subparts. |
39 |
* <p> |
40 |
* Multipart also acts as the base class for the content object returned by |
41 |
* most Multipart DataContentHandlers. For example, invoking |
42 |
* <code>getContent()</code> on a DataHandler whose source is a |
43 |
* "multipart/signed" data source may return an appropriate subclass |
44 |
* of Multipart. |
45 |
* <p> |
46 |
* Some messaging systems provide different subtypes of Multiparts. |
47 |
* For example, MIME specifies a set of subtypes that include |
48 |
* "alternative", "mixed", "related", "parallel", "signed", etc. |
49 |
* <p> |
50 |
* Multipart is an abstract class. Subclasses provide actual implementations. |
51 |
* |
52 |
* @author <a href="mailto:dog@gnu.org">Chris Burdess</a> |
53 |
*/ |
54 |
public abstract class Multipart |
55 |
{ |
56 |
|
57 |
/** |
58 |
* List of BodyPart objects. |
59 |
*/ |
60 |
protected List parts; |
61 |
|
62 |
/** |
63 |
* This field specifies the content-type of this multipart object. |
64 |
* It defaults to "multipart/mixed". |
65 |
*/ |
66 |
protected String contentType; |
67 |
|
68 |
/** |
69 |
* The Part containing this Multipart, if known. |
70 |
*/ |
71 |
protected Part parent; |
72 |
|
73 |
/** |
74 |
* Default constructor. An empty Multipart object is created. |
75 |
*/ |
76 |
protected Multipart() |
77 |
{ |
78 |
parts = new ArrayList(); |
79 |
contentType = "multipart/mixed"; |
80 |
parent = null; |
81 |
} |
82 |
|
83 |
/** |
84 |
* Setup this Multipart object from the given MultipartDataSource. |
85 |
* <p> |
86 |
* The method adds the MultipartDataSource's BodyPart objects into this |
87 |
* Multipart. This Multipart's <code>contentType</code> is set to that of |
88 |
* the MultipartDataSource. |
89 |
* <p> |
90 |
* This method is typically used in those cases where one has a multipart |
91 |
* data source that has already been pre-parsed into the individual body |
92 |
* parts(for example, an IMAP datasource), but needs to create an |
93 |
* appropriate Multipart subclass that represents a specific multipart |
94 |
* subtype. |
95 |
* @param mp Multipart datasource |
96 |
*/ |
97 |
protected void setMultipartDataSource(MultipartDataSource mp) |
98 |
throws MessagingException |
99 |
{ |
100 |
contentType = mp.getContentType(); |
101 |
int count = mp.getCount(); |
102 |
for (int i = 0; i < count; i++) |
103 |
{ |
104 |
addBodyPart(mp.getBodyPart(i)); |
105 |
} |
106 |
} |
107 |
|
108 |
/** |
109 |
* Return the content-type of this Multipart. |
110 |
* <p> |
111 |
* This implementation just returns the value of the |
112 |
* <code>contentType</code> field. |
113 |
*/ |
114 |
public String getContentType() |
115 |
{ |
116 |
return contentType; |
117 |
} |
118 |
|
119 |
/** |
120 |
* Return the number of enclosed BodyPart objects. |
121 |
*/ |
122 |
public int getCount() |
123 |
throws MessagingException |
124 |
{ |
125 |
return (parts == null) ? 0 : parts.size(); |
126 |
} |
127 |
|
128 |
/** |
129 |
* Get the specified Part. |
130 |
* Parts are numbered starting at 0. |
131 |
* @param index the index of the desired Part |
132 |
* @exception IndexOutOfBoundsException if the given index is out of range. |
133 |
*/ |
134 |
public BodyPart getBodyPart(int index) |
135 |
throws MessagingException |
136 |
{ |
137 |
if (parts == null) |
138 |
{ |
139 |
throw new IndexOutOfBoundsException(); |
140 |
} |
141 |
return (BodyPart) parts.get(index); |
142 |
} |
143 |
|
144 |
/** |
145 |
* Remove the specified part from the multipart message. |
146 |
* Shifts all the parts after the removed part down one. |
147 |
* @param part The part to remove |
148 |
* @return true if part removed, false otherwise |
149 |
* @exception MessagingException if no such Part exists |
150 |
* @exception IllegalWriteException if the underlying implementation |
151 |
* does not support modification of existing values |
152 |
*/ |
153 |
public boolean removeBodyPart(BodyPart part) |
154 |
throws MessagingException |
155 |
{ |
156 |
if (parts == null) |
157 |
{ |
158 |
throw new MessagingException("No such BodyPart"); |
159 |
} |
160 |
synchronized (parts) |
161 |
{ |
162 |
boolean success = parts.remove(part); |
163 |
if (success) |
164 |
{ |
165 |
part.setParent(null); |
166 |
} |
167 |
return success; |
168 |
} |
169 |
} |
170 |
|
171 |
/** |
172 |
* Remove the part at specified location(starting from 0). |
173 |
* Shifts all the parts after the removed part down one. |
174 |
* @param index Index of the part to remove |
175 |
* @exception IndexOutOfBoundsException if the given index is out of range. |
176 |
* @exception IllegalWriteException if the underlying implementation |
177 |
* does not support modification of existing values |
178 |
*/ |
179 |
public void removeBodyPart(int index) |
180 |
throws MessagingException |
181 |
{ |
182 |
if (parts == null) |
183 |
{ |
184 |
throw new IndexOutOfBoundsException("No such BodyPart"); |
185 |
} |
186 |
synchronized (parts) |
187 |
{ |
188 |
BodyPart part = (BodyPart) parts.get(index); |
189 |
parts.remove(index); |
190 |
part.setParent(null); |
191 |
} |
192 |
} |
193 |
|
194 |
/** |
195 |
* Adds a Part to the multipart. |
196 |
* The BodyPart is appended to the list of existing Parts. |
197 |
* @param part The Part to be appended |
198 |
* @exception IllegalWriteException if the underlying implementation |
199 |
* does not support modification of existing values |
200 |
*/ |
201 |
public synchronized void addBodyPart(BodyPart part) |
202 |
throws MessagingException |
203 |
{ |
204 |
if (parts == null) |
205 |
{ |
206 |
parts = new ArrayList(); |
207 |
} |
208 |
synchronized (parts) |
209 |
{ |
210 |
parts.add(part); |
211 |
part.setParent(this); |
212 |
} |
213 |
} |
214 |
|
215 |
/** |
216 |
* Adds a BodyPart at position index. |
217 |
* If index is not the last one in the list, the subsequent parts |
218 |
* are shifted up. If index is larger than the number of parts present, |
219 |
* the BodyPart is appended to the end. |
220 |
* @param part The BodyPart to be inserted |
221 |
* @param index Location where to insert the part |
222 |
* @exception IllegalWriteException if the underlying implementation |
223 |
* does not support modification of existing values |
224 |
*/ |
225 |
public synchronized void addBodyPart(BodyPart part, int index) |
226 |
throws MessagingException |
227 |
{ |
228 |
if (parts == null) |
229 |
{ |
230 |
parts = new ArrayList(); |
231 |
} |
232 |
synchronized (parts) |
233 |
{ |
234 |
parts.add(index, part); |
235 |
part.setParent(this); |
236 |
} |
237 |
} |
238 |
|
239 |
/** |
240 |
* Output an appropriately encoded bytestream to the given OutputStream. |
241 |
* The implementation subclass decides the appropriate encoding algorithm |
242 |
* to be used. The bytestream is typically used for sending. |
243 |
*/ |
244 |
public abstract void writeTo(OutputStream os) |
245 |
throws IOException, MessagingException; |
246 |
|
247 |
/** |
248 |
* Return the Part that contains this Multipart object, or null if not known. |
249 |
*/ |
250 |
public Part getParent() |
251 |
{ |
252 |
return parent; |
253 |
} |
254 |
|
255 |
/** |
256 |
* Set the parent of this Multipart to be the specified Part. |
257 |
* Normally called by the Message or BodyPart |
258 |
* <code>setContent(Multipart)</code> method. parent may be null if |
259 |
* the Multipart is being removed from its containing Part. |
260 |
*/ |
261 |
public void setParent(Part part) |
262 |
{ |
263 |
parent = part; |
264 |
} |
265 |
|
266 |
} |