/**************************************************************** * 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 = null; 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(); } } /* * 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; } }