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
020 package org.apache.james.mime4j.message;
021
022 import java.util.Collections;
023 import java.util.Date;
024 import java.util.HashMap;
025 import java.util.List;
026 import java.util.Locale;
027 import java.util.Map;
028
029 import org.apache.james.mime4j.dom.field.ContentDescriptionField;
030 import org.apache.james.mime4j.dom.field.ContentDispositionField;
031 import org.apache.james.mime4j.dom.field.ContentIdField;
032 import org.apache.james.mime4j.dom.field.ContentLanguageField;
033 import org.apache.james.mime4j.dom.field.ContentLengthField;
034 import org.apache.james.mime4j.dom.field.ContentLocationField;
035 import org.apache.james.mime4j.dom.field.ContentMD5Field;
036 import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
037 import org.apache.james.mime4j.dom.field.ContentTypeField;
038 import org.apache.james.mime4j.dom.field.FieldName;
039 import org.apache.james.mime4j.dom.field.MimeVersionField;
040 import org.apache.james.mime4j.dom.field.ParsedField;
041 import org.apache.james.mime4j.field.MimeVersionFieldImpl;
042 import org.apache.james.mime4j.stream.BodyDescriptor;
043 import org.apache.james.mime4j.util.MimeUtil;
044
045 /**
046 * Extended {@link BodyDescriptor} implementation with complete content details.
047 */
048 public class MaximalBodyDescriptor implements BodyDescriptor {
049
050 private static final String CONTENT_TYPE = FieldName.CONTENT_TYPE.toLowerCase(Locale.US);
051 private static final String CONTENT_LENGTH = FieldName.CONTENT_LENGTH.toLowerCase(Locale.US);
052 private static final String CONTENT_TRANSFER_ENCODING = FieldName.CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.US);
053 private static final String CONTENT_DISPOSITION = FieldName.CONTENT_DISPOSITION.toLowerCase(Locale.US);
054 private static final String CONTENT_ID = FieldName.CONTENT_ID.toLowerCase(Locale.US);
055 private static final String CONTENT_MD5 = FieldName.CONTENT_MD5.toLowerCase(Locale.US);
056 private static final String CONTENT_DESCRIPTION = FieldName.CONTENT_DESCRIPTION.toLowerCase(Locale.US);
057 private static final String CONTENT_LANGUAGE = FieldName.CONTENT_LANGUAGE.toLowerCase(Locale.US);
058 private static final String CONTENT_LOCATION = FieldName.CONTENT_LOCATION.toLowerCase(Locale.US);
059 private static final String MIME_VERSION = FieldName.MIME_VERSION.toLowerCase(Locale.US);
060
061 private final String mediaType;
062 private final String subType;
063 private final String mimeType;
064 private final String boundary;
065 private final String charset;
066 private final Map<String, ParsedField> fields;
067
068 MaximalBodyDescriptor(
069 final String mimeType,
070 final String mediaType,
071 final String subType,
072 final String boundary,
073 final String charset,
074 final Map<String, ParsedField> fields) {
075 super();
076 this.mimeType = mimeType;
077 this.mediaType = mediaType;
078 this.subType = subType;
079 this.boundary = boundary;
080 this.charset = charset;
081 this.fields = fields != null ? new HashMap<String, ParsedField>(fields) :
082 Collections.<String, ParsedField>emptyMap();
083 }
084
085 public String getMimeType() {
086 return mimeType;
087 }
088
089 public String getBoundary() {
090 return boundary;
091 }
092
093 public String getCharset() {
094 return charset;
095 }
096
097 public String getMediaType() {
098 return mediaType;
099 }
100
101 public String getSubType() {
102 return subType;
103 }
104
105 public Map<String, String> getContentTypeParameters() {
106 ContentTypeField contentTypeField = (ContentTypeField) fields.get(CONTENT_TYPE);
107 return contentTypeField != null ? contentTypeField.getParameters() :
108 Collections.<String, String>emptyMap();
109 }
110
111 public String getTransferEncoding() {
112 ContentTransferEncodingField contentTransferEncodingField =
113 (ContentTransferEncodingField) fields.get(CONTENT_TRANSFER_ENCODING);
114 return contentTransferEncodingField != null ? contentTransferEncodingField.getEncoding() :
115 MimeUtil.ENC_7BIT;
116 }
117
118 public long getContentLength() {
119 ContentLengthField contentLengthField = (ContentLengthField) fields.get(CONTENT_LENGTH);
120 return contentLengthField != null ? contentLengthField.getContentLength() : -1;
121 }
122
123 /**
124 * Gets the MIME major version
125 * as specified by the <code>MIME-Version</code>
126 * header.
127 * Defaults to one.
128 * @return positive integer
129 */
130 public int getMimeMajorVersion() {
131 MimeVersionField mimeVersionField = (MimeVersionField) fields.get(MIME_VERSION);
132 return mimeVersionField != null ? mimeVersionField.getMajorVersion() :
133 MimeVersionFieldImpl.DEFAULT_MAJOR_VERSION;
134 }
135
136 /**
137 * Gets the MIME minor version
138 * as specified by the <code>MIME-Version</code>
139 * header.
140 * Defaults to zero.
141 * @return positive integer
142 */
143 public int getMimeMinorVersion() {
144 MimeVersionField mimeVersionField = (MimeVersionField) fields.get(MIME_VERSION);
145 return mimeVersionField != null ? mimeVersionField.getMinorVersion() :
146 MimeVersionFieldImpl.DEFAULT_MINOR_VERSION;
147 }
148
149
150 /**
151 * Gets the value of the <a href='http://www.faqs.org/rfcs/rfc2045'>RFC</a>
152 * <code>Content-Description</code> header.
153 * @return value of the <code>Content-Description</code> when present,
154 * null otherwise
155 */
156 public String getContentDescription() {
157 ContentDescriptionField contentDescriptionField =
158 (ContentDescriptionField) fields.get(CONTENT_DESCRIPTION);
159 return contentDescriptionField != null ? contentDescriptionField.getDescription() : null;
160 }
161
162 /**
163 * Gets the value of the <a href='http://www.faqs.org/rfcs/rfc2045'>RFC</a>
164 * <code>Content-ID</code> header.
165 * @return value of the <code>Content-ID</code> when present,
166 * null otherwise
167 */
168 public String getContentId() {
169 ContentIdField contentIdField = (ContentIdField) fields.get(CONTENT_ID);
170 return contentIdField != null ? contentIdField.getId() : null;
171 }
172
173 /**
174 * Gets the disposition type of the <code>content-disposition</code> field.
175 * The value is case insensitive and will be converted to lower case.
176 * See <a href='http://www.faqs.org/rfcs/rfc2183.html'>RFC2183</a>.
177 * @return content disposition type,
178 * or null when this has not been set
179 */
180 public String getContentDispositionType() {
181 ContentDispositionField contentDispositionField =
182 (ContentDispositionField) fields.get(CONTENT_DISPOSITION);
183 return contentDispositionField != null ? contentDispositionField.getDispositionType() : null;
184 }
185
186 /**
187 * Gets the parameters of the <code>content-disposition</code> field.
188 * See <a href='http://www.faqs.org/rfcs/rfc2183.html'>RFC2183</a>.
189 * @return parameter value strings indexed by parameter name strings,
190 * not null
191 */
192 public Map<String, String> getContentDispositionParameters() {
193 ContentDispositionField contentDispositionField =
194 (ContentDispositionField) fields.get(CONTENT_DISPOSITION);
195 return contentDispositionField != null ? contentDispositionField.getParameters() :
196 Collections.<String, String>emptyMap();
197 }
198
199 /**
200 * Gets the <code>filename</code> parameter value of the <code>content-disposition</code> field.
201 * See <a href='http://www.faqs.org/rfcs/rfc2183.html'>RFC2183</a>.
202 * @return filename parameter value,
203 * or null when it is not present
204 */
205 public String getContentDispositionFilename() {
206 ContentDispositionField contentDispositionField =
207 (ContentDispositionField) fields.get(CONTENT_DISPOSITION);
208 return contentDispositionField != null ? contentDispositionField.getFilename() : null;
209 }
210
211 /**
212 * Gets the <code>modification-date</code> parameter value of the <code>content-disposition</code> field.
213 * See <a href='http://www.faqs.org/rfcs/rfc2183.html'>RFC2183</a>.
214 * @return modification-date parameter value,
215 * or null when this is not present
216 */
217 public Date getContentDispositionModificationDate() {
218 ContentDispositionField contentDispositionField =
219 (ContentDispositionField) fields.get(CONTENT_DISPOSITION);
220 return contentDispositionField != null ? contentDispositionField.getModificationDate() : null;
221 }
222
223 /**
224 * Gets the <code>creation-date</code> parameter value of the <code>content-disposition</code> field.
225 * See <a href='http://www.faqs.org/rfcs/rfc2183.html'>RFC2183</a>.
226 * @return creation-date parameter value,
227 * or null when this is not present
228 */
229 public Date getContentDispositionCreationDate() {
230 ContentDispositionField contentDispositionField =
231 (ContentDispositionField) fields.get(CONTENT_DISPOSITION);
232 return contentDispositionField != null ? contentDispositionField.getCreationDate() : null;
233 }
234
235 /**
236 * Gets the <code>read-date</code> parameter value of the <code>content-disposition</code> field.
237 * See <a href='http://www.faqs.org/rfcs/rfc2183.html'>RFC2183</a>.
238 * @return read-date parameter value,
239 * or null when this is not present
240 */
241 public Date getContentDispositionReadDate() {
242 ContentDispositionField contentDispositionField =
243 (ContentDispositionField) fields.get(CONTENT_DISPOSITION);
244 return contentDispositionField != null ? contentDispositionField.getReadDate() : null;
245 }
246
247 /**
248 * Gets the <code>size</code> parameter value of the <code>content-disposition</code> field.
249 * See <a href='http://www.faqs.org/rfcs/rfc2183.html'>RFC2183</a>.
250 * @return size parameter value,
251 * or -1 if this size has not been set
252 */
253 public long getContentDispositionSize() {
254 ContentDispositionField contentDispositionField =
255 (ContentDispositionField) fields.get(CONTENT_DISPOSITION);
256 return contentDispositionField != null ? contentDispositionField.getSize() : -1;
257 }
258
259 /**
260 * Get the <code>content-language</code> header values.
261 * Each applicable language tag will be returned in order.
262 * See <a href='http://tools.ietf.org/html/rfc4646'>RFC4646</a>
263 * <cite>http://tools.ietf.org/html/rfc4646</cite>.
264 * @return list of language tag Strings,
265 * or null if no header exists
266 */
267 public List<String> getContentLanguage() {
268 ContentLanguageField contentLanguageField =
269 (ContentLanguageField) fields.get(CONTENT_LANGUAGE);
270 return contentLanguageField != null ? contentLanguageField.getLanguages() :
271 Collections.<String>emptyList();
272 }
273
274 /**
275 * Get the <code>content-location</code> header value.
276 * See <a href='http://tools.ietf.org/html/rfc2557'>RFC2557</a>
277 * @return the URL content-location
278 * or null if no header exists
279 */
280 public String getContentLocation() {
281 ContentLocationField contentLocationField =
282 (ContentLocationField) fields.get(CONTENT_LOCATION);
283 return contentLocationField != null ? contentLocationField.getLocation() : null;
284 }
285
286 /**
287 * Gets the raw, Base64 encoded value of the
288 * <code>Content-MD5</code> field.
289 * See <a href='http://tools.ietf.org/html/rfc1864'>RFC1864</a>.
290 * @return raw encoded content-md5
291 * or null if no header exists
292 */
293 public String getContentMD5Raw() {
294 ContentMD5Field contentMD5Field = (ContentMD5Field) fields.get(CONTENT_MD5);
295 return contentMD5Field != null ? contentMD5Field.getMD5Raw() : null;
296 }
297
298 @Override
299 public String toString() {
300 StringBuilder sb = new StringBuilder();
301 sb.append("[mimeType=");
302 sb.append(mimeType);
303 sb.append(", mediaType=");
304 sb.append(mediaType);
305 sb.append(", subType=");
306 sb.append(subType);
307 sb.append(", boundary=");
308 sb.append(boundary);
309 sb.append(", charset=");
310 sb.append(charset);
311 sb.append("]");
312 return sb.toString();
313 }
314
315 }