You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by ve...@apache.org on 2011/08/03 21:41:50 UTC

svn commit: r1153625 - in /webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments: ./ impl/

Author: veithen
Date: Wed Aug  3 19:41:48 2011
New Revision: 1153625

URL: http://svn.apache.org/viewvc?rev=1153625&view=rev
Log:
AXIOM-377 (step 1): Logically separate the header parsing code from the content buffering code.

Rationale: In order to decide whether an attachment can be streamed or needs to be buffered, it is necessary to inspect the headers, in particular to determine the content ID.

Added:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java
      - copied, changed from r1153608, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnFile.java
      - copied, changed from r1153608, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnMemory.java
      - copied, changed from r1153608, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStore.java
      - copied, changed from r1153608, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStoreFactory.java
      - copied, changed from r1153228, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java
Removed:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java?rev=1153625&r1=1153624&r2=1153625&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEMessage.java Wed Aug  3 19:41:48 2011
@@ -21,16 +21,19 @@ package org.apache.axiom.attachments;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Collections;
+import java.util.Hashtable;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
 
 import javax.activation.DataHandler;
+import javax.mail.Header;
 import javax.mail.MessagingException;
 import javax.mail.internet.ContentType;
 import javax.mail.internet.ParseException;
 
-import org.apache.axiom.attachments.impl.PartFactory;
+import org.apache.axiom.attachments.impl.ContentStore;
+import org.apache.axiom.attachments.impl.ContentStoreFactory;
 import org.apache.axiom.attachments.lifecycle.LifecycleManager;
 import org.apache.axiom.attachments.lifecycle.impl.LifecycleManagerImpl;
 import org.apache.axiom.om.OMException;
@@ -40,6 +43,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.stream.EntityState;
+import org.apache.james.mime4j.stream.Field;
 import org.apache.james.mime4j.stream.MimeConfig;
 import org.apache.james.mime4j.stream.MimeTokenStream;
 import org.apache.james.mime4j.stream.RecursionMode;
@@ -359,13 +363,18 @@ class MIMEMessage extends AttachmentsImp
         boolean isSOAPPart = (partIndex == 0);
         int threshhold = (fileCacheEnable) ? fileStorageThreshold : 0;
 
-        // The PartFactory will determine which Part implementation is most appropriate.
-        Part part = PartFactory.createPart(getLifecycleManager(), parser, 
-                                      isSOAPPart, 
-                                      threshhold, 
-                                      attachmentRepoDir, 
-                                      contentLength);  // content-length for the whole message
         try {
+            Hashtable headers = readHeaders();
+            
+            Header contentTypeHeader = (Header)headers.get("content-type");
+            // The PartFactory will determine which Part implementation is most appropriate.
+            ContentStore content = ContentStoreFactory.createContentStore(getLifecycleManager(), parser, 
+                                          isSOAPPart, 
+                                          contentTypeHeader == null ? null : contentTypeHeader.getValue(),
+                                          threshhold, 
+                                          attachmentRepoDir, 
+                                          contentLength);  // content-length for the whole message
+            
             EntityState state = parser.next();
             if (state == EntityState.T_EPILOGUE) {
                 while (parser.next() != EntityState.T_END_MULTIPART) {
@@ -374,12 +383,48 @@ class MIMEMessage extends AttachmentsImp
             } else if (state != EntityState.T_START_BODYPART && state != EntityState.T_END_MULTIPART) {
                 throw new IllegalStateException("Internal error: unexpected parser state " + state);
             }
+            
+            partIndex++;
+            return new PartImpl(headers, content);
         } catch (IOException ex) {
             throw new OMException(ex);
         } catch (MimeException ex) {
             throw new OMException(ex);
         }
-        partIndex++;
-        return part;
+    }
+
+    private Hashtable readHeaders() throws IOException, MimeException {
+        if(log.isDebugEnabled()){
+            log.debug("initHeaders");
+        }
+        
+        checkParserState(parser.next(), EntityState.T_START_HEADER);
+        
+        Hashtable headers = new Hashtable();
+        while (parser.next() == EntityState.T_FIELD) {
+            Field field = parser.getField();
+            String name = field.getName();
+            String value = field.getBody();
+            
+            if (log.isDebugEnabled()){
+                log.debug("addHeader: (" + name + ") value=(" + value +")");
+            }
+            Header headerObj = new Header(name, value);
+            
+            // Use the lower case name as the key
+            String key = name.toLowerCase();
+            headers.put(key, headerObj);
+        }
+        
+        checkParserState(parser.next(), EntityState.T_BODY);
+        
+        return headers;
+    }
+    
+    private static void checkParserState(EntityState state, EntityState expected) throws IllegalStateException {
+        if (expected != state) {
+            throw new IllegalStateException("Internal error: expected parser to be in state "
+                    + expected + ", but got " + state);
+        }
     }
 }

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java?rev=1153625&r1=1153624&r2=1153625&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Part.java Wed Aug  3 19:41:48 2011
@@ -29,7 +29,7 @@ import javax.mail.MessagingException;
  * 
  * A Part is created with the PartFactory.
  * 
- * @see org.apache.axiom.attachments.impl.PartFactory
+ * @see org.apache.axiom.attachments.impl.ContentStoreFactory
  */
 public interface Part {
 

Copied: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java (from r1153608, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java)
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java?p2=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java&p1=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java&r1=1153608&r2=1153625&rev=1153625&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/PartImpl.java Wed Aug  3 19:41:48 2011
@@ -17,9 +17,10 @@
  * under the License.
  */
 
-package org.apache.axiom.attachments.impl;
+package org.apache.axiom.attachments;
 
 import org.apache.axiom.attachments.Part;
+import org.apache.axiom.attachments.impl.ContentStore;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -31,29 +32,29 @@ import javax.mail.internet.HeaderTokeniz
 import java.util.Hashtable;
 
 /**
- * AbstractPart is a base class for the actual 
- * Part implementations.  The primary purpose of AbstractPart is
- * to define some of the common methods to promote code reuse.
+ * Actual implementation of the {@link Part} interface.
  */
-abstract class AbstractPart implements Part {
+final class PartImpl implements Part {
 
-    private static Log log = LogFactory.getLog(AbstractPart.class);
+    private static Log log = LogFactory.getLog(PartImpl.class);
                                                  
     // Key is the lower-case name.
     // Value is a javax.mail.Header object
     private Hashtable headers;
     
+    private final ContentStore content;
     
     /**
      * The actual parts are constructed with the PartFactory.
-     * @see org.apache.axiom.attachments.impl.PartFactory
+     * @see org.apache.axiom.attachments.impl.ContentStoreFactory
      * @param headers
      */
-    AbstractPart(Hashtable in) {
+    PartImpl(Hashtable in, ContentStore content) {
         headers = in;
         if (headers == null) {
             headers = new Hashtable();
         }
+        this.content = content;
     }
     
     public String getHeader(String name) {
@@ -121,9 +122,12 @@ abstract class AbstractPart implements P
 
     }
 
-    // The following classes must be implemented by the derived class.
-    public abstract DataHandler getDataHandler() throws MessagingException;
+    public DataHandler getDataHandler() throws MessagingException {
+        return content.getDataHandler();
+    }
 
-    public abstract long getSize() throws MessagingException;
+    public long getSize() throws MessagingException {
+        return content.getSize();
+    }
 
 }

Copied: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnFile.java (from r1153608, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java)
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnFile.java?p2=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnFile.java&p1=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java&r1=1153608&r2=1153625&rev=1153625&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnFile.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnFile.java Wed Aug  3 19:41:48 2011
@@ -27,7 +27,6 @@ import javax.mail.MessagingException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Hashtable;
 
 /**
  * PartOnFile stores that attachment in a file.
@@ -35,9 +34,9 @@ import java.util.Hashtable;
  * the in-memory footprint.
  * 
  * The PartOnFile object is created by the PartFactory
- * @see PartFactory
+ * @see ContentStoreFactory
  */
-public class PartOnFile extends AbstractPart {
+public class ContentOnFile extends ContentStore {
 
     FileAccessor fileAccessor;
     LifecycleManager manager;
@@ -50,8 +49,8 @@ public class PartOnFile extends Abstract
      * @param in2 InputStream containing data
      * @param attachmentDir String 
      */
-    PartOnFile(LifecycleManager manager, Hashtable headers, InputStream is1, InputStream is2, String attachmentDir) throws IOException {
-        super(headers);
+    ContentOnFile(LifecycleManager manager, String contentType, InputStream is1, InputStream is2, String attachmentDir) throws IOException {
+        super(contentType);
         fileAccessor = manager.create(attachmentDir);
         
         // Now write the data to the backing file

Copied: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnMemory.java (from r1153608, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java)
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnMemory.java?p2=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnMemory.java&p1=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java&r1=1153608&r2=1153625&rev=1153625&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentOnMemory.java Wed Aug  3 19:41:48 2011
@@ -29,7 +29,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.Hashtable;
 
 /**
  * PartOnMemoryEnhanced stores the attachment in memory (in non-contigous byte arrays)
@@ -37,9 +36,9 @@ import java.util.Hashtable;
  * performance.
  * 
  * The PartOnMemoryEnhanced object is created by the PartFactory
- * @see PartFactory
+ * @see ContentStoreFactory
  */
-public class PartOnMemoryEnhanced extends AbstractPart {
+public class ContentOnMemory extends ContentStore {
 
     ArrayList data;  // Arrays of 4K buffers
     int length;      // total length of data
@@ -50,8 +49,8 @@ public class PartOnMemoryEnhanced extend
      * @param data array list of 4K byte[]
      * @param length (length of data in bytes)
      */
-    PartOnMemoryEnhanced(Hashtable headers, ArrayList data, int length) {
-        super(headers);
+    ContentOnMemory(String contentType, ArrayList data, int length) {
+        super(contentType);
         this.data =  data;
         this.length = length;
     }
@@ -94,7 +93,7 @@ public class PartOnMemoryEnhanced extend
          * @see javax.activation.DataSource#getContentType()
          */
         public String getContentType() {
-            String ct = getHeader("content-type");
+            String ct = ContentOnMemory.this.getContentType();
             return (ct == null) ?
                     "application/octet-stream" :
                     ct;

Copied: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStore.java (from r1153608, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java)
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStore.java?p2=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStore.java&p1=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java&r1=1153608&r2=1153625&rev=1153625&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/AbstractPart.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStore.java Wed Aug  3 19:41:48 2011
@@ -19,108 +19,23 @@
 
 package org.apache.axiom.attachments.impl;
 
-import org.apache.axiom.attachments.Part;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
 import javax.activation.DataHandler;
-import javax.mail.Header;
 import javax.mail.MessagingException;
-import javax.mail.internet.HeaderTokenizer;
-
-import java.util.Hashtable;
 
 /**
- * AbstractPart is a base class for the actual 
- * Part implementations.  The primary purpose of AbstractPart is
- * to define some of the common methods to promote code reuse.
+ * Stores the content of a MIME part.
  */
-abstract class AbstractPart implements Part {
-
-    private static Log log = LogFactory.getLog(AbstractPart.class);
-                                                 
-    // Key is the lower-case name.
-    // Value is a javax.mail.Header object
-    private Hashtable headers;
-    
+public abstract class ContentStore {
+    private final String contentType;
     
-    /**
-     * The actual parts are constructed with the PartFactory.
-     * @see org.apache.axiom.attachments.impl.PartFactory
-     * @param headers
-     */
-    AbstractPart(Hashtable in) {
-        headers = in;
-        if (headers == null) {
-            headers = new Hashtable();
-        }
-    }
-    
-    public String getHeader(String name) {
-        String key = name.toLowerCase();
-        Header header = (Header) headers.get(key);
-        String value = header == null ? null : header.getValue();
-        if(log.isDebugEnabled()){
-            log.debug("getHeader name=(" + name + ") value=(" + value +")");
-        }
-        return value;
-    }
-
-    public String getContentID() throws MessagingException {
-        return getHeader("content-id");
+    ContentStore(String contentType) {
+        this.contentType = contentType;
     }
-
-    public String getContentType() throws MessagingException {
-        return getHeader("content-type");
+                                                 
+    public String getContentType() {
+        return contentType;
     }
     
-    /**
-     * @return contentTransferEncoding
-     * @throws MessagingException
-     */
-    public String getContentTransferEncoding() throws MessagingException {
-        if(log.isDebugEnabled()){
-            log.debug("getContentTransferEncoding()");
-        }
-        String cte = getHeader("content-transfer-encoding");
-       
-        if(log.isDebugEnabled()){
-            log.debug(" CTE =" + cte);
-        }
-
-        if(cte!=null){
-            cte = cte.trim();
-            
-            if(cte.equalsIgnoreCase("7bit") || 
-                cte.equalsIgnoreCase("8bit") ||
-                cte.equalsIgnoreCase("quoted-printable") ||
-                cte.equalsIgnoreCase("base64")){
-
-                return cte;
-            }
-            
-            HeaderTokenizer ht = new HeaderTokenizer(cte, HeaderTokenizer.MIME);
-            boolean done = false;
-            while(!done){
-                HeaderTokenizer.Token token = ht.next();
-                switch(token.getType()){
-                case HeaderTokenizer.Token.EOF:
-                    if(log.isDebugEnabled()){
-                        log.debug("HeaderTokenizer EOF");
-                    }
-                    done = true;
-                    break;
-                case HeaderTokenizer.Token.ATOM:                    
-                    return token.getValue();
-                }
-            }
-            return cte;
-        }
-        return null;
-
-
-    }
-
     // The following classes must be implemented by the derived class.
     public abstract DataHandler getDataHandler() throws MessagingException;
 

Copied: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStoreFactory.java (from r1153228, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java)
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStoreFactory.java?p2=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStoreFactory.java&p1=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java&r1=1153228&r2=1153625&rev=1153625&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/ContentStoreFactory.java Wed Aug  3 19:41:48 2011
@@ -19,25 +19,17 @@
 
 package org.apache.axiom.attachments.impl;
 
-import org.apache.axiom.attachments.Part;
 import org.apache.axiom.attachments.lifecycle.LifecycleManager;
 import org.apache.axiom.attachments.utils.BAAInputStream;
 import org.apache.axiom.attachments.utils.BAAOutputStream;
 import org.apache.axiom.om.OMException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.stream.EntityState;
-import org.apache.james.mime4j.stream.Field;
 import org.apache.james.mime4j.stream.MimeTokenStream;
 
-import javax.mail.Header;
-
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
-import java.util.Hashtable;
-import java.util.Map;
 
 /**
  * The PartFactory creates an object that represents a Part
@@ -47,12 +39,12 @@ import java.util.Map;
  * other layers of the code.  The PartFactory helps maintain this
  * abstraction, and makes it easier to add new implementations.
  */
-public class PartFactory {
+public class ContentStoreFactory {
     
     private static int inflight = 0;  // How many attachments are currently being built.
     private static String semifore = "PartFactory.semifore";
     
-    private static Log log = LogFactory.getLog(PartFactory.class);
+    private static Log log = LogFactory.getLog(ContentStoreFactory.class);
     
     // Maximum number of threads allowed through createPart
     private static int INFLIGHT_MAX = 4;
@@ -82,8 +74,9 @@ public class PartFactory {
      * @return Part
      * @throws OMException if any exception is encountered while processing.
      */
-    public static Part createPart(LifecycleManager manager, MimeTokenStream parser,
+    public static ContentStore createContentStore(LifecycleManager manager, MimeTokenStream parser,
                     boolean isSOAPPart,
+                    String contentType,
                     int thresholdSize,
                     String attachmentDir,
                     int messageContentLength
@@ -97,15 +90,9 @@ public class PartFactory {
         }
         
         try {
-            checkParserState(parser.getState(), EntityState.T_START_BODYPART);
-            
-            // Read enough of the InputStream to build the headers 
-            // The readHeaders returns some extra bits that were read, but are part
-            // of the data section.
-            Hashtable headers = new Hashtable();
-            readHeaders(parser, headers);
+            checkParserState(parser.getState(), EntityState.T_BODY);
             
-            Part part;
+            ContentStore part;
             try {
                 
                 // Message throughput is increased if the number of threads in this
@@ -144,7 +131,7 @@ public class PartFactory {
                     // keeps the data in non-contiguous byte buffers.
                     BAAOutputStream baaos = new BAAOutputStream();
                     BufferUtils.inputStream2OutputStream(parser.getDecodedInputStream(), baaos);
-                    part = new PartOnMemoryEnhanced(headers, baaos.buffers(), baaos.length());
+                    part = new ContentOnMemory(contentType, baaos.buffers(), baaos.length());
                 } else {
                     // We need to read the input stream to determine whether
                     // the size is bigger or smaller than the threshold.
@@ -153,13 +140,13 @@ public class PartFactory {
                     int count = BufferUtils.inputStream2OutputStream(in, baaos, thresholdSize);
 
                     if (count < thresholdSize) {
-                        part = new PartOnMemoryEnhanced(headers, baaos.buffers(), baaos.length());
+                        part = new ContentOnMemory(contentType, baaos.buffers(), baaos.length());
                     } else {
                         // A BAAInputStream is an input stream over a list of non-contiguous 4K buffers.
                         BAAInputStream baais = 
                             new BAAInputStream(baaos.buffers(), baaos.length());
 
-                        part = new PartOnFile(manager, headers, 
+                        part = new ContentOnFile(manager, contentType, 
                                               baais,
                                               in, 
                                               attachmentDir);
@@ -184,37 +171,6 @@ public class PartFactory {
     }
     
     /**
-     * The implementing class must call initHeaders prior to using
-     * any of the Part methods.  
-     * @param is
-     * @param headers
-     */
-    private static void readHeaders(MimeTokenStream parser, Map headers) throws IOException, MimeException {
-        if(log.isDebugEnabled()){
-            log.debug("initHeaders");
-        }
-        
-        checkParserState(parser.next(), EntityState.T_START_HEADER);
-        
-        while (parser.next() == EntityState.T_FIELD) {
-            Field field = parser.getField();
-            String name = field.getName();
-            String value = field.getBody();
-            
-            if (log.isDebugEnabled()){
-                log.debug("addHeader: (" + name + ") value=(" + value +")");
-            }
-            Header headerObj = new Header(name, value);
-            
-            // Use the lower case name as the key
-            String key = name.toLowerCase();
-            headers.put(key, headerObj);
-        }
-        
-        checkParserState(parser.next(), EntityState.T_BODY);
-    }
-    
-    /**
      * This method checks the configured threshold and
      * the current runtime information.  If it appears that we could
      * run out of memory, the threshold is reduced.