source: contrib/MailArchiver/sources/vendor/mime4j/apache-mime4j-0.7-SNAPSHOT-20110327.010440-17/dom/src/main/java/org/apache/james/mime4j/field/Fields.java @ 6785

Revision 6785, 24.6 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2946 - Liberado codigo do MailArchiver?. Documentação na subpasta DOCS.

Line 
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
20package org.apache.james.mime4j.field;
21
22import java.util.Arrays;
23import java.util.Collections;
24import java.util.Date;
25import java.util.HashMap;
26import java.util.Map;
27import java.util.TimeZone;
28import java.util.regex.Pattern;
29
30import org.apache.james.mime4j.codec.DecodeMonitor;
31import org.apache.james.mime4j.codec.EncoderUtil;
32import org.apache.james.mime4j.dom.address.Address;
33import org.apache.james.mime4j.dom.address.Mailbox;
34import org.apache.james.mime4j.dom.field.AddressListField;
35import org.apache.james.mime4j.dom.field.ContentDispositionField;
36import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
37import org.apache.james.mime4j.dom.field.ContentTypeField;
38import org.apache.james.mime4j.dom.field.DateTimeField;
39import org.apache.james.mime4j.dom.field.Field;
40import org.apache.james.mime4j.dom.field.FieldName;
41import org.apache.james.mime4j.dom.field.MailboxField;
42import org.apache.james.mime4j.dom.field.MailboxListField;
43import org.apache.james.mime4j.dom.field.ParsedField;
44import org.apache.james.mime4j.dom.field.UnstructuredField;
45import org.apache.james.mime4j.field.AddressListFieldImpl;
46import org.apache.james.mime4j.field.ContentDispositionFieldImpl;
47import org.apache.james.mime4j.field.ContentTransferEncodingFieldImpl;
48import org.apache.james.mime4j.field.ContentTypeFieldImpl;
49import org.apache.james.mime4j.field.DateTimeFieldImpl;
50import org.apache.james.mime4j.field.MailboxFieldImpl;
51import org.apache.james.mime4j.field.MailboxListFieldImpl;
52import org.apache.james.mime4j.field.UnstructuredFieldImpl;
53import org.apache.james.mime4j.field.address.AddressFormatter;
54import org.apache.james.mime4j.stream.RawField;
55import org.apache.james.mime4j.util.MimeUtil;
56
57/**
58 * Factory for concrete {@link Field} instances.
59 */
60public class Fields {
61
62    private static final Pattern FIELD_NAME_PATTERN = Pattern
63            .compile("[\\x21-\\x39\\x3b-\\x7e]+");
64
65    private Fields() {
66    }
67
68    /**
69     * Creates a <i>Content-Type</i> field from the specified raw field value.
70     * The specified string gets folded into a multiple-line representation if
71     * necessary but is otherwise taken as is.
72     *
73     * @param contentType
74     *            raw content type containing a MIME type and optional
75     *            parameters.
76     * @return the newly created <i>Content-Type</i> field.
77     */
78    public static ContentTypeField contentType(String contentType) {
79        return parse(ContentTypeFieldImpl.PARSER, FieldName.CONTENT_TYPE,
80                contentType);
81    }
82
83    /**
84     * Creates a <i>Content-Type</i> field from the specified MIME type and
85     * parameters.
86     *
87     * @param mimeType
88     *            a MIME type (such as <code>&quot;text/plain&quot;</code> or
89     *            <code>&quot;application/octet-stream&quot;</code>).
90     * @param parameters
91     *            map containing content-type parameters such as
92     *            <code>&quot;boundary&quot;</code>.
93     * @return the newly created <i>Content-Type</i> field.
94     */
95    public static ContentTypeField contentType(String mimeType,
96            Map<String, String> parameters) {
97        if (!isValidMimeType(mimeType))
98            throw new IllegalArgumentException();
99
100        if (parameters == null || parameters.isEmpty()) {
101            return parse(ContentTypeFieldImpl.PARSER, FieldName.CONTENT_TYPE,
102                    mimeType);
103        } else {
104            StringBuilder sb = new StringBuilder(mimeType);
105            for (Map.Entry<String, String> entry : parameters.entrySet()) {
106                sb.append("; ");
107                sb.append(EncoderUtil.encodeHeaderParameter(entry.getKey(),
108                        entry.getValue()));
109            }
110            String contentType = sb.toString();
111            return contentType(contentType);
112        }
113    }
114
115    /**
116     * Creates a <i>Content-Transfer-Encoding</i> field from the specified raw
117     * field value.
118     *
119     * @param contentTransferEncoding
120     *            an encoding mechanism such as <code>&quot;7-bit&quot;</code>
121     *            or <code>&quot;quoted-printable&quot;</code>.
122     * @return the newly created <i>Content-Transfer-Encoding</i> field.
123     */
124    public static ContentTransferEncodingField contentTransferEncoding(
125            String contentTransferEncoding) {
126        return parse(ContentTransferEncodingFieldImpl.PARSER,
127                FieldName.CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
128    }
129
130    /**
131     * Creates a <i>Content-Disposition</i> field from the specified raw field
132     * value. The specified string gets folded into a multiple-line
133     * representation if necessary but is otherwise taken as is.
134     *
135     * @param contentDisposition
136     *            raw content disposition containing a disposition type and
137     *            optional parameters.
138     * @return the newly created <i>Content-Disposition</i> field.
139     */
140    public static ContentDispositionField contentDisposition(
141            String contentDisposition) {
142        return parse(ContentDispositionFieldImpl.PARSER,
143                FieldName.CONTENT_DISPOSITION, contentDisposition);
144    }
145
146    /**
147     * Creates a <i>Content-Disposition</i> field from the specified
148     * disposition type and parameters.
149     *
150     * @param dispositionType
151     *            a disposition type (usually <code>&quot;inline&quot;</code>
152     *            or <code>&quot;attachment&quot;</code>).
153     * @param parameters
154     *            map containing disposition parameters such as
155     *            <code>&quot;filename&quot;</code>.
156     * @return the newly created <i>Content-Disposition</i> field.
157     */
158    public static ContentDispositionField contentDisposition(
159            String dispositionType, Map<String, String> parameters) {
160        if (!isValidDispositionType(dispositionType))
161            throw new IllegalArgumentException();
162
163        if (parameters == null || parameters.isEmpty()) {
164            return parse(ContentDispositionFieldImpl.PARSER,
165                    FieldName.CONTENT_DISPOSITION, dispositionType);
166        } else {
167            StringBuilder sb = new StringBuilder(dispositionType);
168            for (Map.Entry<String, String> entry : parameters.entrySet()) {
169                sb.append("; ");
170                sb.append(EncoderUtil.encodeHeaderParameter(entry.getKey(),
171                        entry.getValue()));
172            }
173            String contentDisposition = sb.toString();
174            return contentDisposition(contentDisposition);
175        }
176    }
177
178    /**
179     * Creates a <i>Content-Disposition</i> field from the specified
180     * disposition type and filename.
181     *
182     * @param dispositionType
183     *            a disposition type (usually <code>&quot;inline&quot;</code>
184     *            or <code>&quot;attachment&quot;</code>).
185     * @param filename
186     *            filename parameter value or <code>null</code> if the
187     *            parameter should not be included.
188     * @return the newly created <i>Content-Disposition</i> field.
189     */
190    public static ContentDispositionField contentDisposition(
191            String dispositionType, String filename) {
192        return contentDisposition(dispositionType, filename, -1, null, null,
193                null);
194    }
195
196    /**
197     * Creates a <i>Content-Disposition</i> field from the specified values.
198     *
199     * @param dispositionType
200     *            a disposition type (usually <code>&quot;inline&quot;</code>
201     *            or <code>&quot;attachment&quot;</code>).
202     * @param filename
203     *            filename parameter value or <code>null</code> if the
204     *            parameter should not be included.
205     * @param size
206     *            size parameter value or <code>-1</code> if the parameter
207     *            should not be included.
208     * @return the newly created <i>Content-Disposition</i> field.
209     */
210    public static ContentDispositionField contentDisposition(
211            String dispositionType, String filename, long size) {
212        return contentDisposition(dispositionType, filename, size, null, null,
213                null);
214    }
215
216    /**
217     * Creates a <i>Content-Disposition</i> field from the specified values.
218     *
219     * @param dispositionType
220     *            a disposition type (usually <code>&quot;inline&quot;</code>
221     *            or <code>&quot;attachment&quot;</code>).
222     * @param filename
223     *            filename parameter value or <code>null</code> if the
224     *            parameter should not be included.
225     * @param size
226     *            size parameter value or <code>-1</code> if the parameter
227     *            should not be included.
228     * @param creationDate
229     *            creation-date parameter value or <code>null</code> if the
230     *            parameter should not be included.
231     * @param modificationDate
232     *            modification-date parameter value or <code>null</code> if
233     *            the parameter should not be included.
234     * @param readDate
235     *            read-date parameter value or <code>null</code> if the
236     *            parameter should not be included.
237     * @return the newly created <i>Content-Disposition</i> field.
238     */
239    public static ContentDispositionField contentDisposition(
240            String dispositionType, String filename, long size,
241            Date creationDate, Date modificationDate, Date readDate) {
242        Map<String, String> parameters = new HashMap<String, String>();
243        if (filename != null) {
244            parameters.put(ContentDispositionFieldImpl.PARAM_FILENAME, filename);
245        }
246        if (size >= 0) {
247            parameters.put(ContentDispositionFieldImpl.PARAM_SIZE, Long
248                    .toString(size));
249        }
250        if (creationDate != null) {
251            parameters.put(ContentDispositionFieldImpl.PARAM_CREATION_DATE,
252                    MimeUtil.formatDate(creationDate, null));
253        }
254        if (modificationDate != null) {
255            parameters.put(ContentDispositionFieldImpl.PARAM_MODIFICATION_DATE,
256                    MimeUtil.formatDate(modificationDate, null));
257        }
258        if (readDate != null) {
259            parameters.put(ContentDispositionFieldImpl.PARAM_READ_DATE, MimeUtil
260                    .formatDate(readDate, null));
261        }
262        return contentDisposition(dispositionType, parameters);
263    }
264
265    /**
266     * Creates a <i>Date</i> field from the specified <code>Date</code>
267     * value. The default time zone of the host is used to format the date.
268     *
269     * @param date
270     *            date value for the header field.
271     * @return the newly created <i>Date</i> field.
272     */
273    public static DateTimeField date(Date date) {
274        return date0(FieldName.DATE, date, null);
275    }
276
277    /**
278     * Creates a date field from the specified field name and <code>Date</code>
279     * value. The default time zone of the host is used to format the date.
280     *
281     * @param fieldName
282     *            a field name such as <code>Date</code> or
283     *            <code>Resent-Date</code>.
284     * @param date
285     *            date value for the header field.
286     * @return the newly created date field.
287     */
288    public static DateTimeField date(String fieldName, Date date) {
289        checkValidFieldName(fieldName);
290        return date0(fieldName, date, null);
291    }
292
293    /**
294     * Creates a date field from the specified field name, <code>Date</code>
295     * and <code>TimeZone</code> values.
296     *
297     * @param fieldName
298     *            a field name such as <code>Date</code> or
299     *            <code>Resent-Date</code>.
300     * @param date
301     *            date value for the header field.
302     * @param zone
303     *            the time zone to be used for formatting the date.
304     * @return the newly created date field.
305     */
306    public static DateTimeField date(String fieldName, Date date, TimeZone zone) {
307        checkValidFieldName(fieldName);
308        return date0(fieldName, date, zone);
309    }
310
311    /**
312     * Creates a <i>Message-ID</i> field for the specified host name.
313     *
314     * @param hostname
315     *            host name to be included in the message ID or
316     *            <code>null</code> if no host name should be included.
317     * @return the newly created <i>Message-ID</i> field.
318     */
319    public static UnstructuredField messageId(String hostname) {
320        String fieldValue = MimeUtil.createUniqueMessageId(hostname);
321        return parse(UnstructuredFieldImpl.PARSER, FieldName.MESSAGE_ID, fieldValue);
322    }
323
324    /**
325     * Creates a <i>Subject</i> field from the specified string value. The
326     * specified string may contain non-ASCII characters.
327     *
328     * @param subject
329     *            the subject string.
330     * @return the newly created <i>Subject</i> field.
331     */
332    public static UnstructuredField subject(String subject) {
333        int usedCharacters = FieldName.SUBJECT.length() + 2;
334        String fieldValue = EncoderUtil.encodeIfNecessary(subject,
335                EncoderUtil.Usage.TEXT_TOKEN, usedCharacters);
336
337        return parse(UnstructuredFieldImpl.PARSER, FieldName.SUBJECT, fieldValue);
338    }
339
340    /**
341     * Creates a <i>Sender</i> field for the specified mailbox address.
342     *
343     * @param mailbox
344     *            address to be included in the field.
345     * @return the newly created <i>Sender</i> field.
346     */
347    public static MailboxField sender(Mailbox mailbox) {
348        return mailbox0(FieldName.SENDER, mailbox);
349    }
350
351    /**
352     * Creates a <i>From</i> field for the specified mailbox address.
353     *
354     * @param mailbox
355     *            address to be included in the field.
356     * @return the newly created <i>From</i> field.
357     */
358    public static MailboxListField from(Mailbox mailbox) {
359        return mailboxList0(FieldName.FROM, Collections.singleton(mailbox));
360    }
361
362    /**
363     * Creates a <i>From</i> field for the specified mailbox addresses.
364     *
365     * @param mailboxes
366     *            addresses to be included in the field.
367     * @return the newly created <i>From</i> field.
368     */
369    public static MailboxListField from(Mailbox... mailboxes) {
370        return mailboxList0(FieldName.FROM, Arrays.asList(mailboxes));
371    }
372
373    /**
374     * Creates a <i>From</i> field for the specified mailbox addresses.
375     *
376     * @param mailboxes
377     *            addresses to be included in the field.
378     * @return the newly created <i>From</i> field.
379     */
380    public static MailboxListField from(Iterable<Mailbox> mailboxes) {
381        return mailboxList0(FieldName.FROM, mailboxes);
382    }
383
384    /**
385     * Creates a <i>To</i> field for the specified mailbox or group address.
386     *
387     * @param address
388     *            mailbox or group address to be included in the field.
389     * @return the newly created <i>To</i> field.
390     */
391    public static AddressListField to(Address address) {
392        return addressList0(FieldName.TO, Collections.singleton(address));
393    }
394
395    /**
396     * Creates a <i>To</i> field for the specified mailbox or group addresses.
397     *
398     * @param addresses
399     *            mailbox or group addresses to be included in the field.
400     * @return the newly created <i>To</i> field.
401     */
402    public static AddressListField to(Address... addresses) {
403        return addressList0(FieldName.TO, Arrays.asList(addresses));
404    }
405
406    /**
407     * Creates a <i>To</i> field for the specified mailbox or group addresses.
408     *
409     * @param addresses
410     *            mailbox or group addresses to be included in the field.
411     * @return the newly created <i>To</i> field.
412     */
413    public static AddressListField to(Iterable<Address> addresses) {
414        return addressList0(FieldName.TO, addresses);
415    }
416
417    /**
418     * Creates a <i>Cc</i> field for the specified mailbox or group address.
419     *
420     * @param address
421     *            mailbox or group address to be included in the field.
422     * @return the newly created <i>Cc</i> field.
423     */
424    public static AddressListField cc(Address address) {
425        return addressList0(FieldName.CC, Collections.singleton(address));
426    }
427
428    /**
429     * Creates a <i>Cc</i> field for the specified mailbox or group addresses.
430     *
431     * @param addresses
432     *            mailbox or group addresses to be included in the field.
433     * @return the newly created <i>Cc</i> field.
434     */
435    public static AddressListField cc(Address... addresses) {
436        return addressList0(FieldName.CC, Arrays.asList(addresses));
437    }
438
439    /**
440     * Creates a <i>Cc</i> field for the specified mailbox or group addresses.
441     *
442     * @param addresses
443     *            mailbox or group addresses to be included in the field.
444     * @return the newly created <i>Cc</i> field.
445     */
446    public static AddressListField cc(Iterable<Address> addresses) {
447        return addressList0(FieldName.CC, addresses);
448    }
449
450    /**
451     * Creates a <i>Bcc</i> field for the specified mailbox or group address.
452     *
453     * @param address
454     *            mailbox or group address to be included in the field.
455     * @return the newly created <i>Bcc</i> field.
456     */
457    public static AddressListField bcc(Address address) {
458        return addressList0(FieldName.BCC, Collections.singleton(address));
459    }
460
461    /**
462     * Creates a <i>Bcc</i> field for the specified mailbox or group addresses.
463     *
464     * @param addresses
465     *            mailbox or group addresses to be included in the field.
466     * @return the newly created <i>Bcc</i> field.
467     */
468    public static AddressListField bcc(Address... addresses) {
469        return addressList0(FieldName.BCC, Arrays.asList(addresses));
470    }
471
472    /**
473     * Creates a <i>Bcc</i> field for the specified mailbox or group addresses.
474     *
475     * @param addresses
476     *            mailbox or group addresses to be included in the field.
477     * @return the newly created <i>Bcc</i> field.
478     */
479    public static AddressListField bcc(Iterable<Address> addresses) {
480        return addressList0(FieldName.BCC, addresses);
481    }
482
483    /**
484     * Creates a <i>Reply-To</i> field for the specified mailbox or group
485     * address.
486     *
487     * @param address
488     *            mailbox or group address to be included in the field.
489     * @return the newly created <i>Reply-To</i> field.
490     */
491    public static AddressListField replyTo(Address address) {
492        return addressList0(FieldName.REPLY_TO, Collections.singleton(address));
493    }
494
495    /**
496     * Creates a <i>Reply-To</i> field for the specified mailbox or group
497     * addresses.
498     *
499     * @param addresses
500     *            mailbox or group addresses to be included in the field.
501     * @return the newly created <i>Reply-To</i> field.
502     */
503    public static AddressListField replyTo(Address... addresses) {
504        return addressList0(FieldName.REPLY_TO, Arrays.asList(addresses));
505    }
506
507    /**
508     * Creates a <i>Reply-To</i> field for the specified mailbox or group
509     * addresses.
510     *
511     * @param addresses
512     *            mailbox or group addresses to be included in the field.
513     * @return the newly created <i>Reply-To</i> field.
514     */
515    public static AddressListField replyTo(Iterable<Address> addresses) {
516        return addressList0(FieldName.REPLY_TO, addresses);
517    }
518
519    /**
520     * Creates a mailbox field from the specified field name and mailbox
521     * address. Valid field names are <code>Sender</code> and
522     * <code>Resent-Sender</code>.
523     *
524     * @param fieldName
525     *            the name of the mailbox field (<code>Sender</code> or
526     *            <code>Resent-Sender</code>).
527     * @param mailbox
528     *            mailbox address for the field value.
529     * @return the newly created mailbox field.
530     */
531    public static MailboxField mailbox(String fieldName, Mailbox mailbox) {
532        checkValidFieldName(fieldName);
533        return mailbox0(fieldName, mailbox);
534    }
535
536    /**
537     * Creates a mailbox-list field from the specified field name and mailbox
538     * addresses. Valid field names are <code>From</code> and
539     * <code>Resent-From</code>.
540     *
541     * @param fieldName
542     *            the name of the mailbox field (<code>From</code> or
543     *            <code>Resent-From</code>).
544     * @param mailboxes
545     *            mailbox addresses for the field value.
546     * @return the newly created mailbox-list field.
547     */
548    public static MailboxListField mailboxList(String fieldName,
549            Iterable<Mailbox> mailboxes) {
550        checkValidFieldName(fieldName);
551        return mailboxList0(fieldName, mailboxes);
552    }
553
554    /**
555     * Creates an address-list field from the specified field name and mailbox
556     * or group addresses. Valid field names are <code>To</code>,
557     * <code>Cc</code>, <code>Bcc</code>, <code>Reply-To</code>,
558     * <code>Resent-To</code>, <code>Resent-Cc</code> and
559     * <code>Resent-Bcc</code>.
560     *
561     * @param fieldName
562     *            the name of the mailbox field (<code>To</code>,
563     *            <code>Cc</code>, <code>Bcc</code>, <code>Reply-To</code>,
564     *            <code>Resent-To</code>, <code>Resent-Cc</code> or
565     *            <code>Resent-Bcc</code>).
566     * @param addresses
567     *            mailbox or group addresses for the field value.
568     * @return the newly created address-list field.
569     */
570    public static AddressListField addressList(String fieldName,
571            Iterable<Address> addresses) {
572        checkValidFieldName(fieldName);
573        return addressList0(fieldName, addresses);
574    }
575
576    private static DateTimeField date0(String fieldName, Date date,
577            TimeZone zone) {
578        final String formattedDate = MimeUtil.formatDate(date, zone);
579        return parse(DateTimeFieldImpl.PARSER, fieldName, formattedDate);
580    }
581
582    private static MailboxField mailbox0(String fieldName, Mailbox mailbox) {
583        String fieldValue = encodeAddresses(Collections.singleton(mailbox));
584        return parse(MailboxFieldImpl.PARSER, fieldName, fieldValue);
585    }
586
587    private static MailboxListField mailboxList0(String fieldName,
588            Iterable<Mailbox> mailboxes) {
589        String fieldValue = encodeAddresses(mailboxes);
590        return parse(MailboxListFieldImpl.PARSER, fieldName, fieldValue);
591    }
592
593    private static AddressListField addressList0(String fieldName,
594            Iterable<Address> addresses) {
595        String fieldValue = encodeAddresses(addresses);
596        return parse(AddressListFieldImpl.PARSER, fieldName, fieldValue);
597    }
598
599    private static void checkValidFieldName(String fieldName) {
600        if (!FIELD_NAME_PATTERN.matcher(fieldName).matches())
601            throw new IllegalArgumentException("Invalid field name");
602    }
603
604    private static boolean isValidMimeType(String mimeType) {
605        if (mimeType == null)
606            return false;
607
608        int idx = mimeType.indexOf('/');
609        if (idx == -1)
610            return false;
611
612        String type = mimeType.substring(0, idx);
613        String subType = mimeType.substring(idx + 1);
614        return EncoderUtil.isToken(type) && EncoderUtil.isToken(subType);
615    }
616
617    private static boolean isValidDispositionType(String dispositionType) {
618        if (dispositionType == null)
619            return false;
620
621        return EncoderUtil.isToken(dispositionType);
622    }
623
624    private static <F extends ParsedField> F parse(FieldParser<F> parser,
625            String fieldName, String fieldBody) {
626        RawField rawField = new RawField(fieldName, fieldBody);
627        return parser.parse(rawField.getName(), rawField.getBody(), rawField.getRaw(),
628                DecodeMonitor.SILENT);
629    }
630
631    private static String encodeAddresses(Iterable<? extends Address> addresses) {
632        StringBuilder sb = new StringBuilder();
633
634        for (Address address : addresses) {
635            if (sb.length() > 0) {
636                sb.append(", ");
637            }
638            AddressFormatter.DEFAULT.encode(sb, address);
639        }
640        return sb.toString();
641    }
642
643}
Note: See TracBrowser for help on using the repository browser.