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