001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020 package org.apache.james.mime4j.message;
021
022 import java.util.Arrays;
023 import java.util.Collection;
024 import java.util.Collections;
025 import java.util.Date;
026 import java.util.TimeZone;
027
028 import org.apache.james.mime4j.dom.Header;
029 import org.apache.james.mime4j.dom.Message;
030 import org.apache.james.mime4j.dom.address.Address;
031 import org.apache.james.mime4j.dom.address.AddressList;
032 import org.apache.james.mime4j.dom.address.Mailbox;
033 import org.apache.james.mime4j.dom.address.MailboxList;
034 import org.apache.james.mime4j.dom.field.AddressListField;
035 import org.apache.james.mime4j.dom.field.DateTimeField;
036 import org.apache.james.mime4j.dom.field.FieldName;
037 import org.apache.james.mime4j.dom.field.MailboxField;
038 import org.apache.james.mime4j.dom.field.MailboxListField;
039 import org.apache.james.mime4j.dom.field.ParsedField;
040 import org.apache.james.mime4j.dom.field.UnstructuredField;
041 import org.apache.james.mime4j.stream.Field;
042
043 /**
044 * Abstract MIME message.
045 */
046 public abstract class AbstractMessage extends AbstractEntity implements Message {
047
048 /**
049 * Returns the value of the <i>Message-ID</i> header field of this message
050 * or <code>null</code> if it is not present.
051 *
052 * @return the identifier of this message.
053 */
054 public String getMessageId() {
055 Field field = obtainField(FieldName.MESSAGE_ID);
056 if (field == null)
057 return null;
058
059 return field.getBody();
060 }
061
062 /**
063 * Creates and sets a new <i>Message-ID</i> header field for this message.
064 * A <code>Header</code> is created if this message does not already have
065 * one.
066 *
067 * @param hostname
068 * host name to be included in the identifier or
069 * <code>null</code> if no host name should be included.
070 */
071 public void createMessageId(String hostname) {
072 Header header = obtainHeader();
073
074 header.setField(newMessageId(hostname));
075 }
076
077 protected abstract ParsedField newMessageId(String hostname);
078
079 /**
080 * Returns the (decoded) value of the <i>Subject</i> header field of this
081 * message or <code>null</code> if it is not present.
082 *
083 * @return the subject of this message.
084 */
085 public String getSubject() {
086 UnstructuredField field = obtainField(FieldName.SUBJECT);
087 if (field == null)
088 return null;
089
090 return field.getValue();
091 }
092
093 /**
094 * Sets the <i>Subject</i> header field for this message. The specified
095 * string may contain non-ASCII characters, in which case it gets encoded as
096 * an 'encoded-word' automatically. A <code>Header</code> is created if
097 * this message does not already have one.
098 *
099 * @param subject
100 * subject to set or <code>null</code> to remove the subject
101 * header field.
102 */
103 public void setSubject(String subject) {
104 Header header = obtainHeader();
105
106 if (subject == null) {
107 header.removeFields(FieldName.SUBJECT);
108 } else {
109 header.setField(newSubject(subject));
110 }
111 }
112
113 /**
114 * Returns the value of the <i>Date</i> header field of this message as
115 * <code>Date</code> object or <code>null</code> if it is not present.
116 *
117 * @return the date of this message.
118 */
119 public Date getDate() {
120 DateTimeField dateField = obtainField(FieldName.DATE);
121 if (dateField == null)
122 return null;
123
124 return dateField.getDate();
125 }
126
127 /**
128 * Sets the <i>Date</i> header field for this message. This method uses the
129 * default <code>TimeZone</code> of this host to encode the specified
130 * <code>Date</code> object into a string.
131 *
132 * @param date
133 * date to set or <code>null</code> to remove the date header
134 * field.
135 */
136 public void setDate(Date date) {
137 setDate(date, null);
138 }
139
140 /**
141 * Sets the <i>Date</i> header field for this message. The specified
142 * <code>TimeZone</code> is used to encode the specified <code>Date</code>
143 * object into a string.
144 *
145 * @param date
146 * date to set or <code>null</code> to remove the date header
147 * field.
148 * @param zone
149 * a time zone.
150 */
151 public void setDate(Date date, TimeZone zone) {
152 Header header = obtainHeader();
153
154 if (date == null) {
155 header.removeFields(FieldName.DATE);
156 } else {
157 header.setField(newDate(date, zone));
158 }
159 }
160
161 /**
162 * Returns the value of the <i>Sender</i> header field of this message as
163 * <code>Mailbox</code> object or <code>null</code> if it is not
164 * present.
165 *
166 * @return the sender of this message.
167 */
168 public Mailbox getSender() {
169 return getMailbox(FieldName.SENDER);
170 }
171
172 /**
173 * Sets the <i>Sender</i> header field of this message to the specified
174 * mailbox address.
175 *
176 * @param sender
177 * address to set or <code>null</code> to remove the header
178 * field.
179 */
180 public void setSender(Mailbox sender) {
181 setMailbox(FieldName.SENDER, sender);
182 }
183
184 /**
185 * Returns the value of the <i>From</i> header field of this message as
186 * <code>MailboxList</code> object or <code>null</code> if it is not
187 * present.
188 *
189 * @return value of the from field of this message.
190 */
191 public MailboxList getFrom() {
192 return getMailboxList(FieldName.FROM);
193 }
194
195 /**
196 * Sets the <i>From</i> header field of this message to the specified
197 * mailbox address.
198 *
199 * @param from
200 * address to set or <code>null</code> to remove the header
201 * field.
202 */
203 public void setFrom(Mailbox from) {
204 setMailboxList(FieldName.FROM, from);
205 }
206
207 /**
208 * Sets the <i>From</i> header field of this message to the specified
209 * mailbox addresses.
210 *
211 * @param from
212 * addresses to set or <code>null</code> or no arguments to
213 * remove the header field.
214 */
215 public void setFrom(Mailbox... from) {
216 setMailboxList(FieldName.FROM, from);
217 }
218
219 /**
220 * Sets the <i>From</i> header field of this message to the specified
221 * mailbox addresses.
222 *
223 * @param from
224 * addresses to set or <code>null</code> or an empty collection
225 * to remove the header field.
226 */
227 public void setFrom(Collection<Mailbox> from) {
228 setMailboxList(FieldName.FROM, from);
229 }
230
231 /**
232 * Returns the value of the <i>To</i> header field of this message as
233 * <code>AddressList</code> object or <code>null</code> if it is not
234 * present.
235 *
236 * @return value of the to field of this message.
237 */
238 public AddressList getTo() {
239 return getAddressList(FieldName.TO);
240 }
241
242 /**
243 * Sets the <i>To</i> header field of this message to the specified
244 * address.
245 *
246 * @param to
247 * address to set or <code>null</code> to remove the header
248 * field.
249 */
250 public void setTo(Address to) {
251 setAddressList(FieldName.TO, to);
252 }
253
254 /**
255 * Sets the <i>To</i> header field of this message to the specified
256 * addresses.
257 *
258 * @param to
259 * addresses to set or <code>null</code> or no arguments to
260 * remove the header field.
261 */
262 public void setTo(Address... to) {
263 setAddressList(FieldName.TO, to);
264 }
265
266 /**
267 * Sets the <i>To</i> header field of this message to the specified
268 * addresses.
269 *
270 * @param to
271 * addresses to set or <code>null</code> or an empty collection
272 * to remove the header field.
273 */
274 public void setTo(Collection<? extends Address> to) {
275 setAddressList(FieldName.TO, to);
276 }
277
278 /**
279 * Returns the value of the <i>Cc</i> header field of this message as
280 * <code>AddressList</code> object or <code>null</code> if it is not
281 * present.
282 *
283 * @return value of the cc field of this message.
284 */
285 public AddressList getCc() {
286 return getAddressList(FieldName.CC);
287 }
288
289 /**
290 * Sets the <i>Cc</i> header field of this message to the specified
291 * address.
292 *
293 * @param cc
294 * address to set or <code>null</code> to remove the header
295 * field.
296 */
297 public void setCc(Address cc) {
298 setAddressList(FieldName.CC, cc);
299 }
300
301 /**
302 * Sets the <i>Cc</i> header field of this message to the specified
303 * addresses.
304 *
305 * @param cc
306 * addresses to set or <code>null</code> or no arguments to
307 * remove the header field.
308 */
309 public void setCc(Address... cc) {
310 setAddressList(FieldName.CC, cc);
311 }
312
313 /**
314 * Sets the <i>Cc</i> header field of this message to the specified
315 * addresses.
316 *
317 * @param cc
318 * addresses to set or <code>null</code> or an empty collection
319 * to remove the header field.
320 */
321 public void setCc(Collection<? extends Address> cc) {
322 setAddressList(FieldName.CC, cc);
323 }
324
325 /**
326 * Returns the value of the <i>Bcc</i> header field of this message as
327 * <code>AddressList</code> object or <code>null</code> if it is not
328 * present.
329 *
330 * @return value of the bcc field of this message.
331 */
332 public AddressList getBcc() {
333 return getAddressList(FieldName.BCC);
334 }
335
336 /**
337 * Sets the <i>Bcc</i> header field of this message to the specified
338 * address.
339 *
340 * @param bcc
341 * address to set or <code>null</code> to remove the header
342 * field.
343 */
344 public void setBcc(Address bcc) {
345 setAddressList(FieldName.BCC, bcc);
346 }
347
348 /**
349 * Sets the <i>Bcc</i> header field of this message to the specified
350 * addresses.
351 *
352 * @param bcc
353 * addresses to set or <code>null</code> or no arguments to
354 * remove the header field.
355 */
356 public void setBcc(Address... bcc) {
357 setAddressList(FieldName.BCC, bcc);
358 }
359
360 /**
361 * Sets the <i>Bcc</i> header field of this message to the specified
362 * addresses.
363 *
364 * @param bcc
365 * addresses to set or <code>null</code> or an empty collection
366 * to remove the header field.
367 */
368 public void setBcc(Collection<? extends Address> bcc) {
369 setAddressList(FieldName.BCC, bcc);
370 }
371
372 /**
373 * Returns the value of the <i>Reply-To</i> header field of this message as
374 * <code>AddressList</code> object or <code>null</code> if it is not
375 * present.
376 *
377 * @return value of the reply to field of this message.
378 */
379 public AddressList getReplyTo() {
380 return getAddressList(FieldName.REPLY_TO);
381 }
382
383 /**
384 * Sets the <i>Reply-To</i> header field of this message to the specified
385 * address.
386 *
387 * @param replyTo
388 * address to set or <code>null</code> to remove the header
389 * field.
390 */
391 public void setReplyTo(Address replyTo) {
392 setAddressList(FieldName.REPLY_TO, replyTo);
393 }
394
395 /**
396 * Sets the <i>Reply-To</i> header field of this message to the specified
397 * addresses.
398 *
399 * @param replyTo
400 * addresses to set or <code>null</code> or no arguments to
401 * remove the header field.
402 */
403 public void setReplyTo(Address... replyTo) {
404 setAddressList(FieldName.REPLY_TO, replyTo);
405 }
406
407 /**
408 * Sets the <i>Reply-To</i> header field of this message to the specified
409 * addresses.
410 *
411 * @param replyTo
412 * addresses to set or <code>null</code> or an empty collection
413 * to remove the header field.
414 */
415 public void setReplyTo(Collection<? extends Address> replyTo) {
416 setAddressList(FieldName.REPLY_TO, replyTo);
417 }
418
419 private Mailbox getMailbox(String fieldName) {
420 MailboxField field = obtainField(fieldName);
421 if (field == null)
422 return null;
423
424 return field.getMailbox();
425 }
426
427 private void setMailbox(String fieldName, Mailbox mailbox) {
428 Header header = obtainHeader();
429
430 if (mailbox == null) {
431 header.removeFields(fieldName);
432 } else {
433 header.setField(newMailbox(fieldName, mailbox));
434 }
435 }
436
437 private MailboxList getMailboxList(String fieldName) {
438 MailboxListField field = obtainField(fieldName);
439 if (field == null)
440 return null;
441
442 return field.getMailboxList();
443 }
444
445 private void setMailboxList(String fieldName, Mailbox mailbox) {
446 setMailboxList(fieldName, mailbox == null ? null : Collections
447 .singleton(mailbox));
448 }
449
450 private void setMailboxList(String fieldName, Mailbox... mailboxes) {
451 setMailboxList(fieldName, mailboxes == null ? null : Arrays
452 .asList(mailboxes));
453 }
454
455 private void setMailboxList(String fieldName, Collection<Mailbox> mailboxes) {
456 Header header = obtainHeader();
457
458 if (mailboxes == null || mailboxes.isEmpty()) {
459 header.removeFields(fieldName);
460 } else {
461 header.setField(newMailboxList(fieldName, mailboxes));
462 }
463 }
464
465 private AddressList getAddressList(String fieldName) {
466 AddressListField field = obtainField(fieldName);
467 if (field == null)
468 return null;
469
470 return field.getAddressList();
471 }
472
473 private void setAddressList(String fieldName, Address address) {
474 setAddressList(fieldName, address == null ? null : Collections
475 .singleton(address));
476 }
477
478 private void setAddressList(String fieldName, Address... addresses) {
479 setAddressList(fieldName, addresses == null ? null : Arrays
480 .asList(addresses));
481 }
482
483 private void setAddressList(String fieldName, Collection<? extends Address> addresses) {
484 Header header = obtainHeader();
485
486 if (addresses == null || addresses.isEmpty()) {
487 header.removeFields(fieldName);
488 } else {
489 header.setField(newAddressList(fieldName, addresses));
490 }
491 }
492
493 protected abstract AddressListField newAddressList(String fieldName, Collection<? extends Address> addresses);
494
495 protected abstract UnstructuredField newSubject(String subject);
496
497 protected abstract DateTimeField newDate(Date date, TimeZone zone);
498
499 protected abstract MailboxField newMailbox(String fieldName, Mailbox mailbox);
500
501 protected abstract MailboxListField newMailboxList(String fieldName, Collection<Mailbox> mailboxes);
502
503
504 }