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
020package org.apache.james.mime4j.field;
021
022import org.apache.james.mime4j.MimeException;
023import org.apache.james.mime4j.codec.DecodeMonitor;
024import org.apache.james.mime4j.dom.FieldParser;
025import org.apache.james.mime4j.dom.field.AddressListField;
026import org.apache.james.mime4j.dom.field.ContentDescriptionField;
027import org.apache.james.mime4j.dom.field.ContentDispositionField;
028import org.apache.james.mime4j.dom.field.ContentIdField;
029import org.apache.james.mime4j.dom.field.ContentLanguageField;
030import org.apache.james.mime4j.dom.field.ContentLengthField;
031import org.apache.james.mime4j.dom.field.ContentLocationField;
032import org.apache.james.mime4j.dom.field.ContentMD5Field;
033import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
034import org.apache.james.mime4j.dom.field.ContentTypeField;
035import org.apache.james.mime4j.dom.field.DateTimeField;
036import org.apache.james.mime4j.dom.field.FieldName;
037import org.apache.james.mime4j.dom.field.MailboxField;
038import org.apache.james.mime4j.dom.field.MailboxListField;
039import org.apache.james.mime4j.dom.field.MimeVersionField;
040import org.apache.james.mime4j.dom.field.ParsedField;
041import org.apache.james.mime4j.dom.field.UnstructuredField;
042import org.apache.james.mime4j.stream.Field;
043import org.apache.james.mime4j.stream.RawField;
044import org.apache.james.mime4j.stream.RawFieldParser;
045import org.apache.james.mime4j.util.ByteSequence;
046import org.apache.james.mime4j.util.ContentUtil;
047
048/**
049 * Default (strict) implementation of the {@link FieldParser} interface. 
050 */
051public class DefaultFieldParser extends DelegatingFieldParser {
052
053    private static final FieldParser<ParsedField> PARSER = new DefaultFieldParser();
054
055    /**
056     * Gets the default instance of this class.
057     *
058     * @return the default instance
059     */
060    public static FieldParser<ParsedField> getParser() {
061        return PARSER;
062    }
063
064    /**
065     * Parses the given byte sequence and returns an instance of the {@link ParsedField} class. 
066     * The type of the class returned depends on the field name; see {@link #parse(String)} for 
067     * a table of field names and their corresponding classes.
068     *
069     * @param raw the bytes to parse.
070     * @param monitor decoding monitor used while parsing/decoding.
071     * @return a parsed field.
072     * @throws MimeException if the raw string cannot be split into field name and body.
073     */
074    public static ParsedField parse(
075            final ByteSequence raw,
076            final DecodeMonitor monitor) throws MimeException {
077        Field rawField = RawFieldParser.DEFAULT.parseField(raw);
078        return PARSER.parse(rawField, monitor);
079    }
080
081    /**
082     * Parses the given string and returns an instance of the {@link ParsedField} class. 
083     * The type of the class returned depends on the field name:
084     * <p>
085     * <table>
086     *   <tr><th>Class returned</th><th>Field names</th></tr>
087     *   <tr><td>{@link ContentTypeField}</td><td>Content-Type</td></tr>
088     *   <tr><td>{@link ContentLengthField}</td><td>Content-Length</td></tr>
089     *   <tr><td>{@link ContentTransferEncodingField}</td><td>Content-Transfer-Encoding</td></tr>
090     *   <tr><td>{@link ContentDispositionField}</td><td>Content-Disposition</td></tr>
091     *   <tr><td>{@link ContentDescriptionField}</td><td>Content-Description</td></tr>
092     *   <tr><td>{@link ContentIdField}</td><td>Content-ID</td></tr>
093     *   <tr><td>{@link ContentMD5Field}</td><td>Content-MD5</td></tr>
094     *   <tr><td>{@link ContentLanguageField}</td><td>Content-Language</td></tr>
095     *   <tr><td>{@link ContentLocationField}</td><td>Content-Location</td></tr>
096     *   <tr><td>{@link MimeVersionField}</td><td>MIME-Version</td></tr>
097     *   <tr><td>{@link DateTimeField}</td><td>Date, Resent-Date</td></tr>
098     *   <tr><td>{@link MailboxField}</td><td>Sender, Resent-Sender</td></tr>
099     *   <tr><td>{@link MailboxListField}</td><td>From, Resent-From</td></tr>
100     *   <tr><td>{@link AddressListField}</td><td>To, Cc, Bcc, Reply-To, Resent-To, Resent-Cc, Resent-Bcc</td></tr>
101     *   <tr><td>{@link UnstructuredField}</td><td>Subject and others</td></tr>
102     * </table>
103     *
104     * @param rawStr the string to parse.
105     * @return a parsed field.
106     * @throws MimeException if the raw string cannot be split into field name and body.
107     */
108    public static ParsedField parse(
109            final String rawStr,
110            final DecodeMonitor monitor) throws MimeException {
111        ByteSequence raw = ContentUtil.encode(rawStr);
112        RawField rawField = RawFieldParser.DEFAULT.parseField(raw);
113        // Do not retain the original raw representation as the field
114        // may require folding
115        return PARSER.parse(rawField, monitor);
116    }
117
118    public static ParsedField parse(final String rawStr) throws MimeException {
119        return parse(rawStr, DecodeMonitor.SILENT);
120    }
121
122    public DefaultFieldParser() {
123        super(UnstructuredFieldImpl.PARSER);
124        setFieldParser(FieldName.CONTENT_TYPE,
125                ContentTypeFieldImpl.PARSER);
126        setFieldParser(FieldName.CONTENT_LENGTH,
127                ContentLengthFieldImpl.PARSER);
128        setFieldParser(FieldName.CONTENT_TRANSFER_ENCODING,
129                ContentTransferEncodingFieldImpl.PARSER);
130        setFieldParser(FieldName.CONTENT_DISPOSITION,
131                ContentDispositionFieldImpl.PARSER);
132        setFieldParser(FieldName.CONTENT_ID,
133                ContentIdFieldImpl.PARSER);
134        setFieldParser(FieldName.CONTENT_MD5,
135                ContentMD5FieldImpl.PARSER);
136        setFieldParser(FieldName.CONTENT_DESCRIPTION,
137                ContentDescriptionFieldImpl.PARSER);
138        setFieldParser(FieldName.CONTENT_LANGUAGE,
139                ContentLanguageFieldImpl.PARSER);
140        setFieldParser(FieldName.CONTENT_LOCATION,
141                ContentLocationFieldImpl.PARSER);
142        setFieldParser(FieldName.MIME_VERSION,
143                MimeVersionFieldImpl.PARSER);
144
145        FieldParser<DateTimeField> dateTimeParser = DateTimeFieldImpl.PARSER;
146        setFieldParser(FieldName.DATE, dateTimeParser);
147        setFieldParser(FieldName.RESENT_DATE, dateTimeParser);
148
149        FieldParser<MailboxListField> mailboxListParser = MailboxListFieldImpl.PARSER;
150        setFieldParser(FieldName.FROM, mailboxListParser);
151        setFieldParser(FieldName.RESENT_FROM, mailboxListParser);
152
153        FieldParser<MailboxField> mailboxParser = MailboxFieldImpl.PARSER;
154        setFieldParser(FieldName.SENDER, mailboxParser);
155        setFieldParser(FieldName.RESENT_SENDER, mailboxParser);
156
157        FieldParser<AddressListField> addressListParser = AddressListFieldImpl.PARSER;
158        setFieldParser(FieldName.TO, addressListParser);
159        setFieldParser(FieldName.RESENT_TO, addressListParser);
160        setFieldParser(FieldName.CC, addressListParser);
161        setFieldParser(FieldName.RESENT_CC, addressListParser);
162        setFieldParser(FieldName.BCC, addressListParser);
163        setFieldParser(FieldName.RESENT_BCC, addressListParser);
164        setFieldParser(FieldName.REPLY_TO, addressListParser);
165    }
166
167}