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.util.regex.Matcher;
     23 import java.util.regex.Pattern;
     24 
     25 /**
     26  * The base class of all field classes.
     27  *
     28  *
     29  * @version $Id: Field.java,v 1.6 2004/10/25 07:26:46 ntherning Exp $
     30  */
     31 public abstract class Field {
     32     public static final String SENDER = "Sender";
     33     public static final String FROM = "From";
     34     public static final String TO = "To";
     35     public static final String CC = "Cc";
     36     public static final String BCC = "Bcc";
     37     public static final String REPLY_TO = "Reply-To";
     38     public static final String RESENT_SENDER = "Resent-Sender";
     39     public static final String RESENT_FROM = "Resent-From";
     40     public static final String RESENT_TO = "Resent-To";
     41     public static final String RESENT_CC = "Resent-Cc";
     42     public static final String RESENT_BCC = "Resent-Bcc";
     43 
     44     public static final String DATE = "Date";
     45     public static final String RESENT_DATE = "Resent-Date";
     46 
     47     public static final String SUBJECT = "Subject";
     48     public static final String CONTENT_TYPE = "Content-Type";
     49     public static final String CONTENT_TRANSFER_ENCODING =
     50                                         "Content-Transfer-Encoding";
     51 
     52     private static final String FIELD_NAME_PATTERN =
     53         "^([\\x21-\\x39\\x3b-\\x7e]+)[ \t]*:";
     54     private static final Pattern fieldNamePattern =
     55         Pattern.compile(FIELD_NAME_PATTERN);
     56 
     57     private static final DefaultFieldParser parser = new DefaultFieldParser();
     58 
     59     private final String name;
     60     private final String body;
     61     private final String raw;
     62 
     63     protected Field(final String name, final String body, final String raw) {
     64         this.name = name;
     65         this.body = body;
     66         this.raw = raw;
     67     }
     68 
     69     /**
     70      * Parses the given string and returns an instance of the
     71      * <code>Field</code> class. The type of the class returned depends on
     72      * the field name:
     73      * <table>
     74      *      <tr>
     75      *          <td><em>Field name</em></td><td><em>Class returned</em></td>
     76      *          <td>Content-Type</td><td>org.apache.james.mime4j.field.ContentTypeField</td>
     77      *          <td>other</td><td>org.apache.james.mime4j.field.UnstructuredField</td>
     78      *      </tr>
     79      * </table>
     80      *
     81      * @param s the string to parse.
     82      * @return a <code>Field</code> instance.
     83      * @throws IllegalArgumentException on parse errors.
     84      */
     85     public static Field parse(final String raw) {
     86 
     87         /*
     88          * Unfold the field.
     89          */
     90         final String unfolded = raw.replaceAll("\r|\n", "");
     91 
     92         /*
     93          * Split into name and value.
     94          */
     95         final Matcher fieldMatcher = fieldNamePattern.matcher(unfolded);
     96         if (!fieldMatcher.find()) {
     97             throw new IllegalArgumentException("Invalid field in string");
     98         }
     99         final String name = fieldMatcher.group(1);
    100 
    101         String body = unfolded.substring(fieldMatcher.end());
    102         if (body.length() > 0 && body.charAt(0) == ' ') {
    103             body = body.substring(1);
    104         }
    105 
    106         return parser.parse(name, body, raw);
    107     }
    108 
    109     /**
    110      * Gets the default parser used to parse fields.
    111      * @return the default field parser
    112      */
    113     public static DefaultFieldParser getParser() {
    114         return parser;
    115     }
    116 
    117     /**
    118      * Gets the name of the field (<code>Subject</code>,
    119      * <code>From</code>, etc).
    120      *
    121      * @return the field name.
    122      */
    123     public String getName() {
    124         return name;
    125     }
    126 
    127     /**
    128      * Gets the original raw field string.
    129      *
    130      * @return the original raw field string.
    131      */
    132     public String getRaw() {
    133         return raw;
    134     }
    135 
    136     /**
    137      * Gets the unfolded, unparsed and possibly encoded (see RFC 2047) field
    138      * body string.
    139      *
    140      * @return the unfolded unparsed field body string.
    141      */
    142     public String getBody() {
    143         return body;
    144     }
    145 
    146     /**
    147      * Determines if this is a <code>Content-Type</code> field.
    148      *
    149      * @return <code>true</code> if this is a <code>Content-Type</code> field,
    150      *         <code>false</code> otherwise.
    151      */
    152     public boolean isContentType() {
    153         return CONTENT_TYPE.equalsIgnoreCase(name);
    154     }
    155 
    156     /**
    157      * Determines if this is a <code>Subject</code> field.
    158      *
    159      * @return <code>true</code> if this is a <code>Subject</code> field,
    160      *         <code>false</code> otherwise.
    161      */
    162     public boolean isSubject() {
    163         return SUBJECT.equalsIgnoreCase(name);
    164     }
    165 
    166     /**
    167      * Determines if this is a <code>From</code> field.
    168      *
    169      * @return <code>true</code> if this is a <code>From</code> field,
    170      *         <code>false</code> otherwise.
    171      */
    172     public boolean isFrom() {
    173         return FROM.equalsIgnoreCase(name);
    174     }
    175 
    176     /**
    177      * Determines if this is a <code>To</code> field.
    178      *
    179      * @return <code>true</code> if this is a <code>To</code> field,
    180      *         <code>false</code> otherwise.
    181      */
    182     public boolean isTo() {
    183         return TO.equalsIgnoreCase(name);
    184     }
    185 
    186     /**
    187      * @see #getRaw()
    188      */
    189     public String toString() {
    190         return raw;
    191     }
    192 }
    193