1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/****************************************************************
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed to the Apache Software Foundation (ASF) under one   *
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * or more contributor license agreements.  See the NOTICE file *
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed with this work for additional information        *
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * regarding copyright ownership.  The ASF licenses this file   *
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * to you under the Apache License, Version 2.0 (the            *
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * "License"); you may not use this file except in compliance   *
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * with the License.  You may obtain a copy of the License at   *
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *                                                              *
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *   http://www.apache.org/licenses/LICENSE-2.0                 *
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *                                                              *
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing,   *
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * software distributed under the License is distributed on an  *
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * KIND, either express or implied.  See the License for the    *
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * specific language governing permissions and limitations      *
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * under the License.                                           *
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook ****************************************************************/
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage org.apache.james.mime4j.field;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.StringReader;
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.ArrayList;
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.Collections;
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.HashMap;
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.Map;
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook//BEGIN android-changed: Stubbing out logging
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport org.apache.james.mime4j.Log;
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport org.apache.james.mime4j.LogFactory;
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook//END android-changed
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport org.apache.james.mime4j.field.contenttype.parser.ContentTypeParser;
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport org.apache.james.mime4j.field.contenttype.parser.ParseException;
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport org.apache.james.mime4j.field.contenttype.parser.TokenMgrError;
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Represents a <code>Content-Type</code> field.
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p>TODO: Remove dependency on Java 1.4 regexps</p>
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @version $Id: ContentTypeField.java,v 1.6 2005/01/27 14:16:31 ntherning Exp $
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class ContentTypeField extends Field {
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The prefix of all <code>multipart</code> MIME types.
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String TYPE_MULTIPART_PREFIX = "multipart/";
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The <code>multipart/digest</code> MIME type.
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String TYPE_MULTIPART_DIGEST = "multipart/digest";
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The <code>text/plain</code> MIME type.
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String TYPE_TEXT_PLAIN = "text/plain";
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The <code>message/rfc822</code> MIME type.
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String TYPE_MESSAGE_RFC822 = "message/rfc822";
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The name of the <code>boundary</code> parameter.
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String PARAM_BOUNDARY = "boundary";
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The name of the <code>charset</code> parameter.
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final String PARAM_CHARSET = "charset";
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private String mimeType = "";
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private Map<String, String> parameters = null;
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private ParseException parseException;
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected ContentTypeField(String name, String body, String raw, String mimeType, Map<String, String> parameters, ParseException parseException) {
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        super(name, body, raw);
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.mimeType = mimeType;
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.parameters = parameters;
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.parseException = parseException;
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Gets the exception that was raised during parsing of
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * the field value, if any; otherwise, null.
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public ParseException getParseException() {
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return parseException;
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Gets the MIME type defined in this Content-Type field.
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the MIME type or an empty string if not set.
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public String getMimeType() {
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mimeType;
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Gets the MIME type defined in the child's
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Content-Type field or derives a MIME type from the parent
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * if child is <code>null</code> or hasn't got a MIME type value set.
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * If child's MIME type is multipart but no boundary
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * has been set the MIME type of child will be derived from
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * the parent.
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param child the child.
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param parent the parent.
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the MIME type.
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static String getMimeType(ContentTypeField child,
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                                     ContentTypeField parent) {
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (child == null || child.getMimeType().length() == 0
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                || child.isMultipart() && child.getBoundary() == null) {
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (parent != null && parent.isMimeType(TYPE_MULTIPART_DIGEST)) {
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return TYPE_MESSAGE_RFC822;
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } else {
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return TYPE_TEXT_PLAIN;
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return child.getMimeType();
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Gets the value of a parameter. Parameter names are case-insensitive.
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param name the name of the parameter to get.
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the parameter value or <code>null</code> if not set.
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public String getParameter(String name) {
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return parameters != null
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    ? parameters.get(name.toLowerCase())
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    : null;
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Gets all parameters.
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the parameters.
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public Map<String, String> getParameters() {
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (parameters != null) {
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Collections.unmodifiableMap(parameters);
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return Collections.emptyMap();
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Gets the value of the <code>boundary</code> parameter if set.
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the <code>boundary</code> parameter value or <code>null</code>
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *             if not set.
156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public String getBoundary() {
158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getParameter(PARAM_BOUNDARY);
159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Gets the value of the <code>charset</code> parameter if set.
163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the <code>charset</code> parameter value or <code>null</code>
165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *         if not set.
166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public String getCharset() {
168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getParameter(PARAM_CHARSET);
169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Gets the value of the <code>charset</code> parameter if set for the
173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * given field. Returns the default <code>us-ascii</code> if not set or if
174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>f</code> is <code>null</code>.
175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
176bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the <code>charset</code> parameter value.
177bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
178bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static String getCharset(ContentTypeField f) {
179bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (f != null) {
180bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (f.getCharset() != null && f.getCharset().length() > 0) {
181bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return f.getCharset();
182bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
183bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
184bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return "us-ascii";
185bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
186bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
187bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
188bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Determines if the MIME type of this field matches the given one.
189bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
190bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param mimeType the MIME type to match against.
191bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return <code>true</code> if the MIME type of this field matches,
192bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *         <code>false</code> otherwise.
193bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
194bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean isMimeType(String mimeType) {
195bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return this.mimeType.equalsIgnoreCase(mimeType);
196bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
197bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
198bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
199bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Determines if the MIME type of this field is <code>multipart/*</code>.
200bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
201bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return <code>true</code> if this field is has a <code>multipart/*</code>
202bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *         MIME type, <code>false</code> otherwise.
203bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
204bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean isMultipart() {
205bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mimeType.startsWith(TYPE_MULTIPART_PREFIX);
206bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
208bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static class Parser implements FieldParser {
209bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private static Log log = LogFactory.getLog(Parser.class);
210bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
211bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Field parse(final String name, final String body, final String raw) {
212bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            ParseException parseException = null;
213bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            String mimeType = "";
214bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Map<String, String> parameters = null;
215bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
216bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            ContentTypeParser parser = new ContentTypeParser(new StringReader(body));
217bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            try {
218bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                parser.parseAll();
219bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
220bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            catch (ParseException e) {
221bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (log.isDebugEnabled()) {
222bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    log.debug("Parsing value '" + body + "': "+ e.getMessage());
223bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
224bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                parseException = e;
225bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
226bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            catch (TokenMgrError e) {
227bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (log.isDebugEnabled()) {
228bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    log.debug("Parsing value '" + body + "': "+ e.getMessage());
229bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
230bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                parseException = new ParseException(e.getMessage());
231bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
232bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
233bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            try {
234bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final String type = parser.getType();
235bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final String subType = parser.getSubType();
236bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
237bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (type != null && subType != null) {
238bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mimeType = (type + "/" + parser.getSubType()).toLowerCase();
239bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
240bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    ArrayList<String> paramNames = parser.getParamNames();
241bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    ArrayList<String> paramValues = parser.getParamValues();
242bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
243bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    if (paramNames != null && paramValues != null) {
244bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        for (int i = 0; i < paramNames.size() && i < paramValues.size(); i++) {
245bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            if (parameters == null)
246bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                                parameters = new HashMap<String, String>((int)(paramNames.size() * 1.3 + 1));
247bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            String paramName = paramNames.get(i).toLowerCase();
248bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            String paramValue = paramValues.get(i);
249bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            parameters.put(paramName, paramValue);
250bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        }
251bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    }
252bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
253bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
254bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            catch (NullPointerException npe) {
255bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
256bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return new ContentTypeField(name, body, raw, mimeType, parameters, parseException);
257bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
258bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
259bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
260