MIME4J-302 Use lowercase when looking up known headers

An optimization implemented in MaximalBodyDescriptor aims at reducing the costs of toLowerCase calls: upon known header names lookup the lowercase version of the field instead of the normal version to benefit optimizations (calling toLowerCase on a lowerCase string do not do allocation, it just iterates String content). It might be worth generalizing it.
diff --git a/dom/src/main/java/org/apache/james/mime4j/dom/Message.java b/dom/src/main/java/org/apache/james/mime4j/dom/Message.java
index 6084dd1..d004a71 100644
--- a/dom/src/main/java/org/apache/james/mime4j/dom/Message.java
+++ b/dom/src/main/java/org/apache/james/mime4j/dom/Message.java
@@ -442,7 +442,7 @@
          * @return the identifier of this message.
          */
         public String getMessageId() {
-            Field field = obtainField(FieldName.MESSAGE_ID);
+            Field field = obtainField(FieldName.MESSAGE_ID_LOWERCASE);
             return field != null ? field.getBody() : null;
         }
 
@@ -484,7 +484,7 @@
          * @return the subject of this message.
          */
         public String getSubject() {
-            UnstructuredField field = obtainField(FieldName.SUBJECT);
+            UnstructuredField field = obtainField(FieldName.SUBJECT_LOWERCASE);
             return field != null ? field.getValue() : null;
         }
 
@@ -513,7 +513,7 @@
          * @return the date of this message.
          */
         public Date getDate() {
-            DateTimeField field = obtainField(FieldName.DATE);
+            DateTimeField field = obtainField(FieldName.DATE_LOWERCASE);
             return field != null ? field.getDate() : null;
         }
 
@@ -558,7 +558,7 @@
          * @return the sender of this message.
          */
         public Mailbox getSender() {
-            return getMailbox(FieldName.SENDER);
+            return getMailbox(FieldName.SENDER_LOWERCASE);
         }
 
         /**
@@ -593,7 +593,7 @@
          * @return value of the from field of this message.
          */
         public MailboxList getFrom() {
-            return getMailboxList(FieldName.FROM);
+            return getMailboxList(FieldName.FROM_LOWERCASE);
         }
 
         /**
@@ -664,7 +664,7 @@
          * @return value of the to field of this message.
          */
         public AddressList getTo() {
-            return getAddressList(FieldName.TO);
+            return getAddressList(FieldName.TO_LOWERCASE);
         }
 
         /**
@@ -735,7 +735,7 @@
          * @return value of the cc field of this message.
          */
         public AddressList getCc() {
-            return getAddressList(FieldName.CC);
+            return getAddressList(FieldName.CC_LOWERCASE);
         }
 
         /**
@@ -782,7 +782,7 @@
          * @return value of the bcc field of this message.
          */
         public AddressList getBcc() {
-            return getAddressList(FieldName.BCC);
+            return getAddressList(FieldName.BCC_LOWERCASE);
         }
 
         /**
@@ -829,7 +829,7 @@
          * @return value of the reply to field of this message.
          */
         public AddressList getReplyTo() {
-            return getAddressList(FieldName.REPLY_TO);
+            return getAddressList(FieldName.REPLY_TO_LOWERCASE);
         }
 
         /**
@@ -902,7 +902,7 @@
             MessageImpl message = new MessageImpl();
             HeaderImpl header = new HeaderImpl();
             message.setHeader(header);
-            if (!containsField(FieldName.MIME_VERSION)) {
+            if (!containsField(FieldName.MIME_VERSION_LOWERCASE)) {
                 header.setField(Fields.version("1.0"));
             }
             for (Field field : getFields()) {
diff --git a/dom/src/main/java/org/apache/james/mime4j/dom/field/FieldName.java b/dom/src/main/java/org/apache/james/mime4j/dom/field/FieldName.java
index 163154a..9edc5f4 100644
--- a/dom/src/main/java/org/apache/james/mime4j/dom/field/FieldName.java
+++ b/dom/src/main/java/org/apache/james/mime4j/dom/field/FieldName.java
@@ -19,15 +19,20 @@
 
 package org.apache.james.mime4j.dom.field;
 
+import java.util.Locale;
+
 /**
  * Constants for common header field names.
  */
 public class FieldName {
 
     public static final String CONTENT_TYPE = "Content-Type";
+    public static final String CONTENT_TYPE_LOWERCASE = CONTENT_TYPE.toLowerCase(Locale.US);
     public static final String CONTENT_LENGTH = "Content-Length";
     public static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
+    public static final String CONTENT_TRANSFER_ENCODING_LOWERCASE = CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.US);
     public static final String CONTENT_DISPOSITION = "Content-Disposition";
+    public static final String CONTENT_DISPOSITION_LOWERCASE = CONTENT_DISPOSITION.toLowerCase(Locale.US);
     public static final String CONTENT_ID = "Content-ID";
     public static final String CONTENT_MD5 = "Content-MD5";
     public static final String CONTENT_DESCRIPTION = "Content-Description";
@@ -35,16 +40,26 @@
     public static final String CONTENT_LOCATION = "Content-Location";
 
     public static final String MIME_VERSION = "MIME-Version";
+    public static final String MIME_VERSION_LOWERCASE = MIME_VERSION.toLowerCase(Locale.US);
     public static final String DATE = "Date";
+    public static final String DATE_LOWERCASE = DATE.toLowerCase(Locale.US);
     public static final String MESSAGE_ID = "Message-ID";
+    public static final String MESSAGE_ID_LOWERCASE = MESSAGE_ID.toLowerCase(Locale.US);
     public static final String SUBJECT = "Subject";
+    public static final String SUBJECT_LOWERCASE = SUBJECT.toLowerCase(Locale.US);
 
     public static final String FROM = "From";
+    public static final String FROM_LOWERCASE = FROM.toLowerCase(Locale.US);
     public static final String SENDER = "Sender";
+    public static final String SENDER_LOWERCASE = SENDER.toLowerCase(Locale.US);
     public static final String TO = "To";
+    public static final String TO_LOWERCASE = TO.toLowerCase(Locale.US);
     public static final String CC = "Cc";
+    public static final String CC_LOWERCASE = CC.toLowerCase(Locale.US);
     public static final String BCC = "Bcc";
+    public static final String BCC_LOWERCASE = BCC.toLowerCase(Locale.US);
     public static final String REPLY_TO = "Reply-To";
+    public static final String REPLY_TO_LOWERCASE = REPLY_TO.toLowerCase(Locale.US);
 
     public static final String RESENT_DATE = "Resent-Date";
 
diff --git a/dom/src/main/java/org/apache/james/mime4j/internal/AbstractEntityBuilder.java b/dom/src/main/java/org/apache/james/mime4j/internal/AbstractEntityBuilder.java
index c8f0871..ef98769 100644
--- a/dom/src/main/java/org/apache/james/mime4j/internal/AbstractEntityBuilder.java
+++ b/dom/src/main/java/org/apache/james/mime4j/internal/AbstractEntityBuilder.java
@@ -256,7 +256,7 @@
      *         type has been set.
      */
     public String getMimeType() {
-        ContentTypeField field = obtainField(FieldName.CONTENT_TYPE);
+        ContentTypeField field = obtainField(FieldName.CONTENT_TYPE_LOWERCASE);
         return field != null ? field.getMimeType() : null;
     }
 
@@ -267,7 +267,7 @@
      *         type has been set.
      */
     public String getCharset() {
-        ContentTypeField field = obtainField(FieldName.CONTENT_TYPE);
+        ContentTypeField field = obtainField(FieldName.CONTENT_TYPE_LOWERCASE);
         return field != null ? field.getCharset() : null;
     }
 
@@ -293,7 +293,7 @@
      * @return the transfer encoding.
      */
     public String getContentTransferEncoding() {
-        ContentTransferEncodingField field = obtainField(FieldName.CONTENT_TRANSFER_ENCODING);
+        ContentTransferEncodingField field = obtainField(FieldName.CONTENT_TRANSFER_ENCODING_LOWERCASE);
         return field != null ? field.getEncoding() : null;
     }
 
@@ -319,7 +319,7 @@
      *         type has been set.
      */
     public String getDispositionType() {
-        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION);
+        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION_LOWERCASE);
         return field != null ? field.getDispositionType() : null;
     }
 
@@ -428,7 +428,7 @@
      *         <code>null</code> if the filename has not been set.
      */
     public String getFilename() {
-        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION);
+        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION_LOWERCASE);
         return field != null ? field.getFilename() : null;
     }
 
@@ -439,7 +439,7 @@
      *         <code>-1</code> if the filename has not been set.
      */
     public long getSize() {
-        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION);
+        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION_LOWERCASE);
         return field != null ? field.getSize() : -1;
     }
 
@@ -450,7 +450,7 @@
      *         <code>null</code> if the filename has not been set.
      */
     public Date getCreationDate() {
-        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION);
+        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION_LOWERCASE);
         return field != null ? field.getCreationDate() : null;
     }
 
@@ -461,7 +461,7 @@
      *         <code>null</code> if the filename has not been set.
      */
     public Date getModificationDate() {
-        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION);
+        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION_LOWERCASE);
         return field != null ? field.getModificationDate() : null;
     }
 
@@ -472,7 +472,7 @@
      *         <code>null</code> if the filename has not been set.
      */
     public Date getReadDate() {
-        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION);
+        ContentDispositionField field = obtainField(FieldName.CONTENT_DISPOSITION_LOWERCASE);
         return field != null ? field.getReadDate() : null;
     }
 
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/AbstractEntity.java b/dom/src/main/java/org/apache/james/mime4j/message/AbstractEntity.java
index d050059..e69db7c 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/AbstractEntity.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/AbstractEntity.java
@@ -126,12 +126,12 @@
     public String getMimeType() {
         ContentTypeField childType = getContentTypeField();
         Entity parent = getParent();
-        ContentTypeField parentType = parent != null ? (ContentTypeField) (parent).getHeader().getField(FieldName.CONTENT_TYPE) : null;
+        ContentTypeField parentType = parent != null ? (ContentTypeField) (parent).getHeader().getField(FieldName.CONTENT_TYPE_LOWERCASE) : null;
         return calcMimeType(childType, parentType);
     }
 
     private ContentTypeField getContentTypeField() {
-        return (ContentTypeField) getHeader().getField(FieldName.CONTENT_TYPE);
+        return (ContentTypeField) getHeader().getField(FieldName.CONTENT_TYPE_LOWERCASE);
     }
 
     /**
@@ -140,7 +140,7 @@
      * @return the MIME character set encoding.
      */
     public String getCharset() {
-        return calcCharset((ContentTypeField) getHeader().getField(FieldName.CONTENT_TYPE));
+        return calcCharset((ContentTypeField) getHeader().getField(FieldName.CONTENT_TYPE_LOWERCASE));
     }
 
     /**
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/AbstractMessage.java b/dom/src/main/java/org/apache/james/mime4j/message/AbstractMessage.java
index 170dd9f..44949ab 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/AbstractMessage.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/AbstractMessage.java
@@ -45,7 +45,7 @@
      * @return the identifier of this message.
      */
     public String getMessageId() {
-        Field field = obtainField(FieldName.MESSAGE_ID);
+        Field field = obtainField(FieldName.MESSAGE_ID_LOWERCASE);
         if (field == null)
             return null;
 
@@ -59,7 +59,7 @@
      * @return the subject of this message.
      */
     public String getSubject() {
-        UnstructuredField field = obtainField(FieldName.SUBJECT);
+        UnstructuredField field = obtainField(FieldName.SUBJECT_LOWERCASE);
         if (field == null)
             return null;
 
@@ -73,7 +73,7 @@
      * @return the date of this message.
      */
     public Date getDate() {
-        DateTimeField dateField = obtainField(FieldName.DATE);
+        DateTimeField dateField = obtainField(FieldName.DATE_LOWERCASE);
         if (dateField == null)
             return null;
 
@@ -88,7 +88,7 @@
      * @return the sender of this message.
      */
     public Mailbox getSender() {
-        return getMailbox(FieldName.SENDER);
+        return getMailbox(FieldName.SENDER_LOWERCASE);
     }
 
     /**
@@ -99,7 +99,7 @@
      * @return value of the from field of this message.
      */
     public MailboxList getFrom() {
-        return getMailboxList(FieldName.FROM);
+        return getMailboxList(FieldName.FROM_LOWERCASE);
     }
 
     /**
@@ -110,7 +110,7 @@
      * @return value of the to field of this message.
      */
     public AddressList getTo() {
-        return getAddressList(FieldName.TO);
+        return getAddressList(FieldName.TO_LOWERCASE);
     }
 
     /**
@@ -121,7 +121,7 @@
      * @return value of the cc field of this message.
      */
     public AddressList getCc() {
-        return getAddressList(FieldName.CC);
+        return getAddressList(FieldName.CC_LOWERCASE);
     }
 
     /**
@@ -132,7 +132,7 @@
      * @return value of the bcc field of this message.
      */
     public AddressList getBcc() {
-        return getAddressList(FieldName.BCC);
+        return getAddressList(FieldName.BCC_LOWERCASE);
     }
 
     /**
@@ -143,7 +143,7 @@
      * @return value of the reply to field of this message.
      */
     public AddressList getReplyTo() {
-        return getAddressList(FieldName.REPLY_TO);
+        return getAddressList(FieldName.REPLY_TO_LOWERCASE);
     }
 
     private Mailbox getMailbox(String fieldName) {
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/DefaultMessageWriter.java b/dom/src/main/java/org/apache/james/mime4j/message/DefaultMessageWriter.java
index 4ce7f7b..5c4c1ce 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/DefaultMessageWriter.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/DefaultMessageWriter.java
@@ -250,7 +250,7 @@
                     "Missing header in parent entity");
 
         ContentTypeField contentType = (ContentTypeField) header
-                .getField(FieldName.CONTENT_TYPE);
+                .getField(FieldName.CONTENT_TYPE_LOWERCASE);
         if (contentType == null)
             throw new IllegalArgumentException(
                     "Content-Type field not specified");