source: contrib/MailArchiver/sources/vendor/mime4j/custom/dom/src/main/java/org/apache/james/mime4j/field/Fields.java @ 6785

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