/**************************************************************** | |
* 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.descriptor; | |
import java.util.HashMap; | |
import java.util.Map; | |
import org.apache.commons.logging.Log; | |
import org.apache.commons.logging.LogFactory; | |
import org.apache.james.mime4j.parser.Field; | |
import org.apache.james.mime4j.util.MimeUtil; | |
/** | |
* Encapsulates the values of the MIME-specific header fields | |
* (which starts with <code>Content-</code>). | |
*/ | |
public class DefaultBodyDescriptor implements MutableBodyDescriptor { | |
private static final String US_ASCII = "us-ascii"; | |
private static final String SUB_TYPE_EMAIL = "rfc822"; | |
private static final String MEDIA_TYPE_TEXT = "text"; | |
private static final String MEDIA_TYPE_MESSAGE = "message"; | |
private static final String EMAIL_MESSAGE_MIME_TYPE = MEDIA_TYPE_MESSAGE + "/" + SUB_TYPE_EMAIL; | |
private static final String DEFAULT_SUB_TYPE = "plain"; | |
private static final String DEFAULT_MEDIA_TYPE = MEDIA_TYPE_TEXT; | |
private static final String DEFAULT_MIME_TYPE = DEFAULT_MEDIA_TYPE + "/" + DEFAULT_SUB_TYPE; | |
private static Log log = LogFactory.getLog(DefaultBodyDescriptor.class); | |
private String mediaType = DEFAULT_MEDIA_TYPE; | |
private String subType = DEFAULT_SUB_TYPE; | |
private String mimeType = DEFAULT_MIME_TYPE; | |
private String boundary = null; | |
private String charset = US_ASCII; | |
private String transferEncoding = "7bit"; | |
private Map<String, String> parameters = new HashMap<String, String>(); | |
private boolean contentTypeSet; | |
private boolean contentTransferEncSet; | |
private long contentLength = -1; | |
/** | |
* Creates a new root <code>BodyDescriptor</code> instance. | |
*/ | |
public DefaultBodyDescriptor() { | |
this(null); | |
} | |
/** | |
* Creates a new <code>BodyDescriptor</code> instance. | |
* | |
* @param parent the descriptor of the parent or <code>null</code> if this | |
* is the root descriptor. | |
*/ | |
public DefaultBodyDescriptor(BodyDescriptor parent) { | |
if (parent != null && MimeUtil.isSameMimeType("multipart/digest", parent.getMimeType())) { | |
mimeType = EMAIL_MESSAGE_MIME_TYPE; | |
subType = SUB_TYPE_EMAIL; | |
mediaType = MEDIA_TYPE_MESSAGE; | |
} else { | |
mimeType = DEFAULT_MIME_TYPE; | |
subType = DEFAULT_SUB_TYPE; | |
mediaType = DEFAULT_MEDIA_TYPE; | |
} | |
} | |
/** | |
* Should be called for each <code>Content-</code> header field of | |
* a MIME message or part. | |
* | |
* @param field the MIME field. | |
*/ | |
public void addField(Field field) { | |
String name = field.getName(); | |
String value = field.getBody(); | |
name = name.trim().toLowerCase(); | |
if (name.equals("content-transfer-encoding") && !contentTransferEncSet) { | |
contentTransferEncSet = true; | |
value = value.trim().toLowerCase(); | |
if (value.length() > 0) { | |
transferEncoding = value; | |
} | |
} else if (name.equals("content-length") && contentLength == -1) { | |
try { | |
contentLength = Long.parseLong(value.trim()); | |
} catch (NumberFormatException e) { | |
log.error("Invalid content-length: " + value); | |
} | |
} else if (name.equals("content-type") && !contentTypeSet) { | |
parseContentType(value); | |
} | |
} | |
private void parseContentType(String value) { | |
contentTypeSet = true; | |
Map<String, String> params = MimeUtil.getHeaderParams(value); | |
String main = params.get(""); | |
String type = null; | |
String subtype = null; | |
if (main != null) { | |
main = main.toLowerCase().trim(); | |
int index = main.indexOf('/'); | |
boolean valid = false; | |
if (index != -1) { | |
type = main.substring(0, index).trim(); | |
subtype = main.substring(index + 1).trim(); | |
if (type.length() > 0 && subtype.length() > 0) { | |
main = type + "/" + subtype; | |
valid = true; | |
} | |
} | |
if (!valid) { | |
main = null; | |
type = null; | |
subtype = null; | |
} | |
} | |
String b = params.get("boundary"); | |
if (main != null | |
&& ((main.startsWith("multipart/") && b != null) | |
|| !main.startsWith("multipart/"))) { | |
mimeType = main; | |
this.subType = subtype; | |
this.mediaType = type; | |
} | |
if (MimeUtil.isMultipart(mimeType)) { | |
boundary = b; | |
} | |
String c = params.get("charset"); | |
charset = null; | |
if (c != null) { | |
c = c.trim(); | |
if (c.length() > 0) { | |
charset = c.toLowerCase(); | |
} | |
} | |
if (charset == null && MEDIA_TYPE_TEXT.equals(mediaType)) { | |
charset = US_ASCII; | |
} | |
/* | |
* Add all other parameters to parameters. | |
*/ | |
parameters.putAll(params); | |
parameters.remove(""); | |
parameters.remove("boundary"); | |
parameters.remove("charset"); | |
} | |
/** | |
* Return the MimeType | |
* | |
* @return mimeType | |
*/ | |
public String getMimeType() { | |
return mimeType; | |
} | |
/** | |
* Return the boundary | |
* | |
* @return boundary | |
*/ | |
public String getBoundary() { | |
return boundary; | |
} | |
/** | |
* Return the charset | |
* | |
* @return charset | |
*/ | |
public String getCharset() { | |
return charset; | |
} | |
/** | |
* Return all parameters for the BodyDescriptor | |
* | |
* @return parameters | |
*/ | |
public Map<String, String> getContentTypeParameters() { | |
return parameters; | |
} | |
/** | |
* Return the TransferEncoding | |
* | |
* @return transferEncoding | |
*/ | |
public String getTransferEncoding() { | |
return transferEncoding; | |
} | |
@Override | |
public String toString() { | |
return mimeType; | |
} | |
public long getContentLength() { | |
return contentLength; | |
} | |
public String getMediaType() { | |
return mediaType; | |
} | |
public String getSubType() { | |
return subType; | |
} | |
} |