| /**************************************************************** |
| * Licensed to the Apache Software Foundation (ASF) under one * |
| * or more contributor license agreements. See the NOTICE file * |
| * distributed with this work for additional information * |
| * regarding copyright ownership. The ASF licenses this file * |
| * to you under the Apache License, Version 2.0 (the * |
| * "License"); you may not use this file except in compliance * |
| * with the License. You may obtain a copy of the License at * |
| * * |
| * http://www.apache.org/licenses/LICENSE-2.0 * |
| * * |
| * Unless required by applicable law or agreed to in writing, * |
| * software distributed under the License is distributed on an * |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * |
| * KIND, either express or implied. See the License for the * |
| * specific language governing permissions and limitations * |
| * under the License. * |
| ****************************************************************/ |
| |
| package org.apache.james.mime4j.field; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.TimeZone; |
| import java.util.regex.Pattern; |
| |
| import org.apache.james.mime4j.codec.DecodeMonitor; |
| import org.apache.james.mime4j.codec.EncoderUtil; |
| import org.apache.james.mime4j.dom.FieldParser; |
| import org.apache.james.mime4j.dom.address.Address; |
| import org.apache.james.mime4j.dom.address.Mailbox; |
| import org.apache.james.mime4j.dom.field.AddressListField; |
| import org.apache.james.mime4j.dom.field.ContentDispositionField; |
| import org.apache.james.mime4j.dom.field.ContentTransferEncodingField; |
| import org.apache.james.mime4j.dom.field.ContentTypeField; |
| import org.apache.james.mime4j.dom.field.DateTimeField; |
| import org.apache.james.mime4j.dom.field.FieldName; |
| import org.apache.james.mime4j.dom.field.MailboxField; |
| import org.apache.james.mime4j.dom.field.MailboxListField; |
| import org.apache.james.mime4j.dom.field.MimeVersionField; |
| import org.apache.james.mime4j.dom.field.ParsedField; |
| import org.apache.james.mime4j.dom.field.UnstructuredField; |
| import org.apache.james.mime4j.field.address.AddressFormatter; |
| import org.apache.james.mime4j.stream.Field; |
| import org.apache.james.mime4j.stream.NameValuePair; |
| import org.apache.james.mime4j.stream.RawField; |
| import org.apache.james.mime4j.util.MimeUtil; |
| |
| /** |
| * Factory for concrete {@link Field} instances. |
| */ |
| public class Fields { |
| |
| private static final Pattern FIELD_NAME_PATTERN = Pattern |
| .compile("[\\x21-\\x39\\x3b-\\x7e]+"); |
| |
| private Fields() { |
| } |
| |
| public static MimeVersionField version(String ver) { |
| return parse(MimeVersionFieldLenientImpl.PARSER, FieldName.MIME_VERSION, ver); |
| } |
| |
| /** |
| * Creates a <i>Content-Type</i> field from the specified raw field value. |
| * The specified string gets folded into a multiple-line representation if |
| * necessary but is otherwise taken as is. |
| * |
| * @param contentType |
| * raw content type containing a MIME type and optional |
| * parameters. |
| * @return the newly created <i>Content-Type</i> field. |
| */ |
| public static ContentTypeField contentType(String contentType) { |
| return parse(ContentTypeFieldImpl.PARSER, FieldName.CONTENT_TYPE, |
| contentType); |
| } |
| |
| /** |
| * Creates a <i>Content-Type</i> field from the specified MIME type and |
| * parameters. |
| * |
| * @param mimeType |
| * a MIME type (such as <code>"text/plain"</code> or |
| * <code>"application/octet-stream"</code>). |
| * @param parameters |
| * map containing content-type parameters such as |
| * <code>"boundary"</code>. |
| * @return the newly created <i>Content-Type</i> field. |
| */ |
| public static ContentTypeField contentType(String mimeType, |
| Map<String, String> parameters) { |
| if (!isValidMimeType(mimeType)) |
| throw new IllegalArgumentException(); |
| |
| if (parameters == null || parameters.isEmpty()) { |
| return parse(ContentTypeFieldImpl.PARSER, FieldName.CONTENT_TYPE, |
| mimeType); |
| } else { |
| StringBuilder sb = new StringBuilder(mimeType); |
| for (Map.Entry<String, String> entry : parameters.entrySet()) { |
| sb.append("; "); |
| sb.append(EncoderUtil.encodeHeaderParameter(entry.getKey(), |
| entry.getValue())); |
| } |
| String contentType = sb.toString(); |
| return contentType(contentType); |
| } |
| } |
| |
| /** |
| * Creates a <i>Content-Type</i> field from the specified MIME type and |
| * parameters. |
| * |
| * @param mimeType |
| * a MIME type (such as <code>"text/plain"</code> or |
| * <code>"application/octet-stream"</code>). |
| * @param parameters |
| * list of content-type parameter name/value pairs. |
| * @return the newly created <i>Content-Type</i> field. |
| */ |
| public static ContentTypeField contentType(String mimeType, |
| Iterable<NameValuePair> parameters) { |
| if (!isValidMimeType(mimeType)) { |
| throw new IllegalArgumentException(mimeType + " is not a valid MIME type"); |
| } |
| if (parameters == null) { |
| return parse(ContentTypeFieldImpl.PARSER, FieldName.CONTENT_TYPE, |
| mimeType); |
| } else { |
| StringBuilder sb = new StringBuilder(mimeType); |
| for (NameValuePair param : parameters) { |
| sb.append("; "); |
| String name = param.getName(); |
| String value = param.getValue(); |
| sb.append(EncoderUtil.encodeHeaderParameter(name, value != null ? value : "")); |
| } |
| String contentType = sb.toString(); |
| return contentType(contentType); |
| } |
| } |
| |
| /** |
| * Creates a <i>Content-Type</i> field from the specified MIME type and |
| * parameters. |
| * |
| * @param mimeType |
| * a MIME type (such as <code>"text/plain"</code> or |
| * <code>"application/octet-stream"</code>). |
| * @param parameters |
| * array of content-type parameter name/value pairs. |
| * @return the newly created <i>Content-Type</i> field. |
| */ |
| public static ContentTypeField contentType(String mimeType, NameValuePair... parameters) { |
| return contentType(mimeType, parameters != null || parameters.length == 0 ? Arrays.asList(parameters) : null); |
| } |
| |
| /** |
| * Creates a <i>Content-Transfer-Encoding</i> field from the specified raw |
| * field value. |
| * |
| * @param contentTransferEncoding |
| * an encoding mechanism such as <code>"7-bit"</code> |
| * or <code>"quoted-printable"</code>. |
| * @return the newly created <i>Content-Transfer-Encoding</i> field. |
| */ |
| public static ContentTransferEncodingField contentTransferEncoding( |
| String contentTransferEncoding) { |
| return parse(ContentTransferEncodingFieldImpl.PARSER, |
| FieldName.CONTENT_TRANSFER_ENCODING, contentTransferEncoding); |
| } |
| |
| /** |
| * Creates a <i>Content-Disposition</i> field from the specified raw field |
| * value. The specified string gets folded into a multiple-line |
| * representation if necessary but is otherwise taken as is. |
| * |
| * @param contentDisposition |
| * raw content disposition containing a disposition type and |
| * optional parameters. |
| * @return the newly created <i>Content-Disposition</i> field. |
| */ |
| public static ContentDispositionField contentDisposition( |
| String contentDisposition) { |
| return parse(ContentDispositionFieldImpl.PARSER, |
| FieldName.CONTENT_DISPOSITION, contentDisposition); |
| } |
| |
| /** |
| * Creates a <i>Content-Disposition</i> field from the specified |
| * disposition type and parameters. |
| * |
| * @param dispositionType |
| * a disposition type (usually <code>"inline"</code> |
| * or <code>"attachment"</code>). |
| * @param parameters |
| * map containing disposition parameters such as |
| * <code>"filename"</code>. |
| * @return the newly created <i>Content-Disposition</i> field. |
| */ |
| public static ContentDispositionField contentDisposition( |
| String dispositionType, Map<String, String> parameters) { |
| if (!isValidDispositionType(dispositionType)) |
| throw new IllegalArgumentException(); |
| |
| if (parameters == null || parameters.isEmpty()) { |
| return parse(ContentDispositionFieldImpl.PARSER, |
| FieldName.CONTENT_DISPOSITION, dispositionType); |
| } else { |
| StringBuilder sb = new StringBuilder(dispositionType); |
| for (Map.Entry<String, String> entry : parameters.entrySet()) { |
| sb.append("; "); |
| sb.append(EncoderUtil.encodeHeaderParameter(entry.getKey(), |
| entry.getValue())); |
| } |
| String contentDisposition = sb.toString(); |
| return contentDisposition(contentDisposition); |
| } |
| } |
| |
| /** |
| * Creates a <i>Content-Disposition</i> field from the specified |
| * disposition type and parameters. |
| * |
| * @param dispositionType |
| * a disposition type (usually <code>"inline"</code> |
| * or <code>"attachment"</code>). |
| * @param parameters |
| * list of disposition parameter name/value pairs. |
| * @return the newly created <i>Content-Disposition</i> field. |
| */ |
| public static ContentDispositionField contentDisposition( |
| String dispositionType, Iterable<NameValuePair> parameters) { |
| if (!isValidDispositionType(dispositionType)) |
| throw new IllegalArgumentException(); |
| |
| if (parameters == null) { |
| return parse(ContentDispositionFieldImpl.PARSER, |
| FieldName.CONTENT_DISPOSITION, dispositionType); |
| } else { |
| StringBuilder sb = new StringBuilder(dispositionType); |
| for (NameValuePair param : parameters) { |
| sb.append("; "); |
| String name = param.getName(); |
| String value = param.getValue(); |
| sb.append(EncoderUtil.encodeHeaderParameter(name, value != null ? value : "")); |
| } |
| String contentDisposition = sb.toString(); |
| return contentDisposition(contentDisposition); |
| } |
| } |
| |
| /** |
| * Creates a <i>Content-Disposition</i> field from the specified |
| * disposition type and filename. |
| * |
| * @param dispositionType |
| * a disposition type (usually <code>"inline"</code> |
| * or <code>"attachment"</code>). |
| * @param filename |
| * filename parameter value or <code>null</code> if the |
| * parameter should not be included. |
| * @return the newly created <i>Content-Disposition</i> field. |
| */ |
| public static ContentDispositionField contentDisposition( |
| String dispositionType, String filename) { |
| return contentDisposition(dispositionType, filename, -1, null, null, |
| null); |
| } |
| |
| /** |
| * Creates a <i>Content-Disposition</i> field from the specified values. |
| * |
| * @param dispositionType |
| * a disposition type (usually <code>"inline"</code> |
| * or <code>"attachment"</code>). |
| * @param filename |
| * filename parameter value or <code>null</code> if the |
| * parameter should not be included. |
| * @param size |
| * size parameter value or <code>-1</code> if the parameter |
| * should not be included. |
| * @return the newly created <i>Content-Disposition</i> field. |
| */ |
| public static ContentDispositionField contentDisposition( |
| String dispositionType, String filename, long size) { |
| return contentDisposition(dispositionType, filename, size, null, null, |
| null); |
| } |
| |
| /** |
| * Creates a <i>Content-Disposition</i> field from the specified values. |
| * |
| * @param dispositionType |
| * a disposition type (usually <code>"inline"</code> |
| * or <code>"attachment"</code>). |
| * @param filename |
| * filename parameter value or <code>null</code> if the |
| * parameter should not be included. |
| * @param size |
| * size parameter value or <code>-1</code> if the parameter |
| * should not be included. |
| * @param creationDate |
| * creation-date parameter value or <code>null</code> if the |
| * parameter should not be included. |
| * @param modificationDate |
| * modification-date parameter value or <code>null</code> if |
| * the parameter should not be included. |
| * @param readDate |
| * read-date parameter value or <code>null</code> if the |
| * parameter should not be included. |
| * @return the newly created <i>Content-Disposition</i> field. |
| */ |
| public static ContentDispositionField contentDisposition( |
| String dispositionType, String filename, long size, |
| Date creationDate, Date modificationDate, Date readDate) { |
| Map<String, String> parameters = new HashMap<String, String>(); |
| if (filename != null) { |
| parameters.put(ContentDispositionFieldImpl.PARAM_FILENAME, filename); |
| } |
| if (size >= 0) { |
| parameters.put(ContentDispositionFieldImpl.PARAM_SIZE, Long |
| .toString(size)); |
| } |
| if (creationDate != null) { |
| parameters.put(ContentDispositionFieldImpl.PARAM_CREATION_DATE, |
| MimeUtil.formatDate(creationDate, null)); |
| } |
| if (modificationDate != null) { |
| parameters.put(ContentDispositionFieldImpl.PARAM_MODIFICATION_DATE, |
| MimeUtil.formatDate(modificationDate, null)); |
| } |
| if (readDate != null) { |
| parameters.put(ContentDispositionFieldImpl.PARAM_READ_DATE, MimeUtil |
| .formatDate(readDate, null)); |
| } |
| return contentDisposition(dispositionType, parameters); |
| } |
| |
| /** |
| * Creates a <i>Date</i> field from the specified <code>Date</code> |
| * value. The default time zone of the host is used to format the date. |
| * |
| * @param date |
| * date value for the header field. |
| * @return the newly created <i>Date</i> field. |
| */ |
| public static DateTimeField date(Date date) { |
| return date0(FieldName.DATE, date, null); |
| } |
| |
| /** |
| * Creates a date field from the specified field name and <code>Date</code> |
| * value. The default time zone of the host is used to format the date. |
| * |
| * @param fieldName |
| * a field name such as <code>Date</code> or |
| * <code>Resent-Date</code>. |
| * @param date |
| * date value for the header field. |
| * @return the newly created date field. |
| */ |
| public static DateTimeField date(String fieldName, Date date) { |
| checkValidFieldName(fieldName); |
| return date0(fieldName, date, null); |
| } |
| |
| /** |
| * Creates a date field from the specified field name, <code>Date</code> |
| * and <code>TimeZone</code> values. |
| * |
| * @param fieldName |
| * a field name such as <code>Date</code> or |
| * <code>Resent-Date</code>. |
| * @param date |
| * date value for the header field. |
| * @param zone |
| * the time zone to be used for formatting the date. |
| * @return the newly created date field. |
| */ |
| public static DateTimeField date(String fieldName, Date date, TimeZone zone) { |
| checkValidFieldName(fieldName); |
| return date0(fieldName, date, zone); |
| } |
| |
| /** |
| * Creates a <i>Message-ID</i> field for the specified host name. |
| * |
| * @param hostname |
| * host name to be included in the message ID or |
| * <code>null</code> if no host name should be included. |
| * @return the newly created <i>Message-ID</i> field. |
| */ |
| public static UnstructuredField generateMessageId(String hostname) { |
| String fieldValue = MimeUtil.createUniqueMessageId(hostname); |
| return parse(UnstructuredFieldImpl.PARSER, FieldName.MESSAGE_ID, fieldValue); |
| } |
| |
| /** |
| * Creates a <i>Message-ID</i> field with the given message ID. |
| * |
| * @param messageId |
| * message ID value. |
| */ |
| public static UnstructuredField messageId(String messageId) { |
| return parse(UnstructuredFieldImpl.PARSER, FieldName.MESSAGE_ID, messageId); |
| } |
| |
| /** |
| * Creates a <i>Subject</i> field from the specified string value. The |
| * specified string may contain non-ASCII characters. |
| * |
| * @param subject |
| * the subject string. |
| * @return the newly created <i>Subject</i> field. |
| */ |
| public static UnstructuredField subject(String subject) { |
| int usedCharacters = FieldName.SUBJECT.length() + 2; |
| String fieldValue = EncoderUtil.encodeIfNecessary(subject, |
| EncoderUtil.Usage.TEXT_TOKEN, usedCharacters); |
| |
| return parse(UnstructuredFieldImpl.PARSER, FieldName.SUBJECT, fieldValue); |
| } |
| |
| /** |
| * Creates a <i>Sender</i> field for the specified mailbox address. |
| * |
| * @param mailbox |
| * address to be included in the field. |
| * @return the newly created <i>Sender</i> field. |
| */ |
| public static MailboxField sender(Mailbox mailbox) { |
| return mailbox0(FieldName.SENDER, mailbox); |
| } |
| |
| /** |
| * Creates a <i>From</i> field for the specified mailbox address. |
| * |
| * @param mailbox |
| * address to be included in the field. |
| * @return the newly created <i>From</i> field. |
| */ |
| public static MailboxListField from(Mailbox mailbox) { |
| return mailboxList0(FieldName.FROM, Collections.singleton(mailbox)); |
| } |
| |
| /** |
| * Creates a <i>From</i> field for the specified mailbox addresses. |
| * |
| * @param mailboxes |
| * addresses to be included in the field. |
| * @return the newly created <i>From</i> field. |
| */ |
| public static MailboxListField from(Mailbox... mailboxes) { |
| return mailboxList0(FieldName.FROM, Arrays.asList(mailboxes)); |
| } |
| |
| /** |
| * Creates a <i>From</i> field for the specified mailbox addresses. |
| * |
| * @param mailboxes |
| * addresses to be included in the field. |
| * @return the newly created <i>From</i> field. |
| */ |
| public static MailboxListField from(Iterable<Mailbox> mailboxes) { |
| return mailboxList0(FieldName.FROM, mailboxes); |
| } |
| |
| /** |
| * Creates a <i>To</i> field for the specified mailbox or group address. |
| * |
| * @param address |
| * mailbox or group address to be included in the field. |
| * @return the newly created <i>To</i> field. |
| */ |
| public static AddressListField to(Address address) { |
| return addressList0(FieldName.TO, Collections.singleton(address)); |
| } |
| |
| /** |
| * Creates a <i>To</i> field for the specified mailbox or group addresses. |
| * |
| * @param addresses |
| * mailbox or group addresses to be included in the field. |
| * @return the newly created <i>To</i> field. |
| */ |
| public static AddressListField to(Address... addresses) { |
| return addressList0(FieldName.TO, Arrays.asList(addresses)); |
| } |
| |
| /** |
| * Creates a <i>To</i> field for the specified mailbox or group addresses. |
| * |
| * @param addresses |
| * mailbox or group addresses to be included in the field. |
| * @return the newly created <i>To</i> field. |
| */ |
| public static AddressListField to(Iterable<Address> addresses) { |
| return addressList0(FieldName.TO, addresses); |
| } |
| |
| /** |
| * Creates a <i>Cc</i> field for the specified mailbox or group address. |
| * |
| * @param address |
| * mailbox or group address to be included in the field. |
| * @return the newly created <i>Cc</i> field. |
| */ |
| public static AddressListField cc(Address address) { |
| return addressList0(FieldName.CC, Collections.singleton(address)); |
| } |
| |
| /** |
| * Creates a <i>Cc</i> field for the specified mailbox or group addresses. |
| * |
| * @param addresses |
| * mailbox or group addresses to be included in the field. |
| * @return the newly created <i>Cc</i> field. |
| */ |
| public static AddressListField cc(Address... addresses) { |
| return addressList0(FieldName.CC, Arrays.asList(addresses)); |
| } |
| |
| /** |
| * Creates a <i>Cc</i> field for the specified mailbox or group addresses. |
| * |
| * @param addresses |
| * mailbox or group addresses to be included in the field. |
| * @return the newly created <i>Cc</i> field. |
| */ |
| public static AddressListField cc(Iterable<Address> addresses) { |
| return addressList0(FieldName.CC, addresses); |
| } |
| |
| /** |
| * Creates a <i>Bcc</i> field for the specified mailbox or group address. |
| * |
| * @param address |
| * mailbox or group address to be included in the field. |
| * @return the newly created <i>Bcc</i> field. |
| */ |
| public static AddressListField bcc(Address address) { |
| return addressList0(FieldName.BCC, Collections.singleton(address)); |
| } |
| |
| /** |
| * Creates a <i>Bcc</i> field for the specified mailbox or group addresses. |
| * |
| * @param addresses |
| * mailbox or group addresses to be included in the field. |
| * @return the newly created <i>Bcc</i> field. |
| */ |
| public static AddressListField bcc(Address... addresses) { |
| return addressList0(FieldName.BCC, Arrays.asList(addresses)); |
| } |
| |
| /** |
| * Creates a <i>Bcc</i> field for the specified mailbox or group addresses. |
| * |
| * @param addresses |
| * mailbox or group addresses to be included in the field. |
| * @return the newly created <i>Bcc</i> field. |
| */ |
| public static AddressListField bcc(Iterable<Address> addresses) { |
| return addressList0(FieldName.BCC, addresses); |
| } |
| |
| /** |
| * Creates a <i>Reply-To</i> field for the specified mailbox or group |
| * address. |
| * |
| * @param address |
| * mailbox or group address to be included in the field. |
| * @return the newly created <i>Reply-To</i> field. |
| */ |
| public static AddressListField replyTo(Address address) { |
| return addressList0(FieldName.REPLY_TO, Collections.singleton(address)); |
| } |
| |
| /** |
| * Creates a <i>Reply-To</i> field for the specified mailbox or group |
| * addresses. |
| * |
| * @param addresses |
| * mailbox or group addresses to be included in the field. |
| * @return the newly created <i>Reply-To</i> field. |
| */ |
| public static AddressListField replyTo(Address... addresses) { |
| return addressList0(FieldName.REPLY_TO, Arrays.asList(addresses)); |
| } |
| |
| /** |
| * Creates a <i>Reply-To</i> field for the specified mailbox or group |
| * addresses. |
| * |
| * @param addresses |
| * mailbox or group addresses to be included in the field. |
| * @return the newly created <i>Reply-To</i> field. |
| */ |
| public static AddressListField replyTo(Iterable<Address> addresses) { |
| return addressList0(FieldName.REPLY_TO, addresses); |
| } |
| |
| /** |
| * Creates a mailbox field from the specified field name and mailbox |
| * address. Valid field names are <code>Sender</code> and |
| * <code>Resent-Sender</code>. |
| * |
| * @param fieldName |
| * the name of the mailbox field (<code>Sender</code> or |
| * <code>Resent-Sender</code>). |
| * @param mailbox |
| * mailbox address for the field value. |
| * @return the newly created mailbox field. |
| */ |
| public static MailboxField mailbox(String fieldName, Mailbox mailbox) { |
| checkValidFieldName(fieldName); |
| return mailbox0(fieldName, mailbox); |
| } |
| |
| /** |
| * Creates a mailbox-list field from the specified field name and mailbox |
| * addresses. Valid field names are <code>From</code> and |
| * <code>Resent-From</code>. |
| * |
| * @param fieldName |
| * the name of the mailbox field (<code>From</code> or |
| * <code>Resent-From</code>). |
| * @param mailboxes |
| * mailbox addresses for the field value. |
| * @return the newly created mailbox-list field. |
| */ |
| public static MailboxListField mailboxList(String fieldName, |
| Iterable<Mailbox> mailboxes) { |
| checkValidFieldName(fieldName); |
| return mailboxList0(fieldName, mailboxes); |
| } |
| |
| /** |
| * Creates an address-list field from the specified field name and mailbox |
| * or group addresses. Valid field names are <code>To</code>, |
| * <code>Cc</code>, <code>Bcc</code>, <code>Reply-To</code>, |
| * <code>Resent-To</code>, <code>Resent-Cc</code> and |
| * <code>Resent-Bcc</code>. |
| * |
| * @param fieldName |
| * the name of the mailbox field (<code>To</code>, |
| * <code>Cc</code>, <code>Bcc</code>, <code>Reply-To</code>, |
| * <code>Resent-To</code>, <code>Resent-Cc</code> or |
| * <code>Resent-Bcc</code>). |
| * @param addresses |
| * mailbox or group addresses for the field value. |
| * @return the newly created address-list field. |
| */ |
| public static AddressListField addressList(String fieldName, |
| Iterable<? extends Address> addresses) { |
| checkValidFieldName(fieldName); |
| return addressList0(fieldName, addresses); |
| } |
| |
| private static DateTimeField date0(String fieldName, Date date, |
| TimeZone zone) { |
| final String formattedDate = MimeUtil.formatDate(date, zone); |
| return parse(DateTimeFieldImpl.PARSER, fieldName, formattedDate); |
| } |
| |
| private static MailboxField mailbox0(String fieldName, Mailbox mailbox) { |
| String fieldValue = encodeAddresses(Collections.singleton(mailbox)); |
| return parse(MailboxFieldImpl.PARSER, fieldName, fieldValue); |
| } |
| |
| private static MailboxListField mailboxList0(String fieldName, |
| Iterable<Mailbox> mailboxes) { |
| String fieldValue = encodeAddresses(mailboxes); |
| return parse(MailboxListFieldImpl.PARSER, fieldName, fieldValue); |
| } |
| |
| private static AddressListField addressList0(String fieldName, |
| Iterable<? extends Address> addresses) { |
| String fieldValue = encodeAddresses(addresses); |
| return parse(AddressListFieldImpl.PARSER, fieldName, fieldValue); |
| } |
| |
| private static void checkValidFieldName(String fieldName) { |
| if (!FIELD_NAME_PATTERN.matcher(fieldName).matches()) |
| throw new IllegalArgumentException("Invalid field name"); |
| } |
| |
| private static boolean isValidMimeType(String mimeType) { |
| if (mimeType == null) |
| return false; |
| |
| int idx = mimeType.indexOf('/'); |
| if (idx == -1) |
| return false; |
| |
| String type = mimeType.substring(0, idx); |
| String subType = mimeType.substring(idx + 1); |
| return EncoderUtil.isToken(type) && EncoderUtil.isToken(subType); |
| } |
| |
| private static boolean isValidDispositionType(String dispositionType) { |
| return dispositionType != null && EncoderUtil.isToken(dispositionType); |
| |
| } |
| |
| private static <F extends ParsedField> F parse(FieldParser<F> parser, |
| String fieldName, String fieldBody) { |
| RawField rawField = new RawField(fieldName, fieldBody); |
| return parser.parse(rawField, DecodeMonitor.SILENT); |
| } |
| |
| private static String encodeAddresses(Iterable<? extends Address> addresses) { |
| StringBuilder sb = new StringBuilder(); |
| |
| for (Address address : addresses) { |
| if (sb.length() > 0) { |
| sb.append(", "); |
| } |
| AddressFormatter.DEFAULT.encode(sb, address); |
| } |
| return sb.toString(); |
| } |
| |
| } |