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/01 00:36:21 UTC

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

Author: veithen
Date: Sun Jul 31 22:36:19 2011
New Revision: 1152656

URL: http://svn.apache.org/viewvc?rev=1152656&view=rev
Log:
AXIOM-326: Use mime4j instead of our own MIME parsing code.

Removed:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/BoundaryDelimitedStream.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/BoundaryPushbackInputStream.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MIMEBodyPartInputStream.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/attachments/BoundaryPushbackInputStreamTest.java
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/pom.xml
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsImpl.java
    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/MultipartAttachmentStreams.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.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-osgi/axiom-osgi-run/pom.xml
    webservices/commons/trunk/modules/axiom/modules/axiom-parent/pom.xml

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/pom.xml
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/pom.xml?rev=1152656&r1=1152655&r2=1152656&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/pom.xml (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/pom.xml Sun Jul 31 22:36:19 2011
@@ -59,6 +59,10 @@
             <artifactId>geronimo-stax-api_1.0_spec</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>apache-mime4j-core</artifactId>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java?rev=1152656&r1=1152655&r2=1152656&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentSet.java Sun Jul 31 22:36:19 2011
@@ -87,9 +87,4 @@ class AttachmentSet extends AttachmentsI
     long getContentLength() throws IOException {
         return -1;
     }
-
-    InputStream getIncomingAttachmentsAsSingleStream() {
-        throw new IllegalStateException(
-                "The attachments map was created programatically. No streams are available.");
-    }
 }

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java?rev=1152656&r1=1152655&r2=1152656&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java Sun Jul 31 22:36:19 2011
@@ -310,10 +310,9 @@ public class Attachments implements OMAt
     }
 
     /**
-     * Returns the rest of mime stream. It will contain all attachments without
-     * soappart (first attachment) with headers and mime boundary. Raw content! 
+     * @deprecated As of Axiom 1.2.13, this method is no longer supported.
      */
     public InputStream getIncomingAttachmentsAsSingleStream() throws IllegalStateException {
-        return impl.getIncomingAttachmentsAsSingleStream();
+        throw new UnsupportedOperationException();
     }
 }
\ No newline at end of file

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsImpl.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsImpl.java?rev=1152656&r1=1152655&r2=1152656&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsImpl.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/AttachmentsImpl.java Sun Jul 31 22:36:19 2011
@@ -43,5 +43,4 @@ abstract class AttachmentsImpl {
     abstract Set getContentIDs(boolean fetchAll);
     abstract Map getMap();
     abstract long getContentLength() throws IOException;
-    abstract InputStream getIncomingAttachmentsAsSingleStream();
 }

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=1152656&r1=1152655&r2=1152656&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 Sun Jul 31 22:36:19 2011
@@ -20,8 +20,6 @@ package org.apache.axiom.attachments;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.PushbackInputStream;
-import java.io.UnsupportedEncodingException;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -40,6 +38,11 @@ import org.apache.axiom.om.util.Detachab
 import org.apache.axiom.util.UIDGenerator;
 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.MimeConfig;
+import org.apache.james.mime4j.stream.MimeTokenStream;
+import org.apache.james.mime4j.stream.RecursionMode;
 
 class MIMEMessage extends AttachmentsImpl {
     private static final Log log = LogFactory.getLog(MIMEMessage.class);
@@ -49,17 +52,10 @@ class MIMEMessage extends AttachmentsImp
     
     private final int contentLength; // Content Length
 
-    /** Mime <code>boundary</code> which separates mime parts */
-    private final byte[] boundary;
-
-    /**
-     * <code>pushbackInStream</code> stores the reference to the incoming stream A PushbackStream
-     * has the ability to "push back" or "unread" one byte.
-     */
-    private final PushbackInputStream pushbackInStream;
-    private static final int PUSHBACK_SIZE = 4 * 1024;
     private final DetachableInputStream filterIS;
 
+    private final MimeTokenStream parser;
+    
     /**
      * Stores the Data Handlers of the already parsed Mime Body Parts in the order that the attachments
      * occur in the message. This map is keyed using the content-ID's.
@@ -78,12 +74,6 @@ class MIMEMessage extends AttachmentsImp
     /** <code>boolean</code> Indicating if any data handlers have been directly requested */
     private boolean partsRequested;
 
-    /**
-     * <code>endOfStreamReached</code> flag which is to be set by MIMEBodyPartStream when MIME
-     * message terminator is found.
-     */
-    private boolean endOfStreamReached;
-
     private String firstPartId;
 
     private final boolean fileCacheEnable;
@@ -112,21 +102,6 @@ class MIMEMessage extends AttachmentsImp
                     , e);
         }
 
-        // Boundary always have the prefix "--".
-        try {
-            String boundaryParam = contentType.getParameter("boundary");
-            if (boundaryParam == null) {
-                throw new OMException("Content-type has no 'boundary' parameter");
-            }
-            // A MIME boundary only contains ASCII characters (see RFC2046)
-            this.boundary = ("--" + boundaryParam).getBytes("ascii");
-            if (log.isDebugEnabled()) {
-                log.debug("boundary=" + new String(this.boundary));
-            }
-        } catch (UnsupportedEncodingException e) {
-            throw new OMException(e);
-        }
-
         // If the length is not known, install a TeeInputStream
         // so that we can retrieve it later.
         InputStream is = inStream;
@@ -136,36 +111,21 @@ class MIMEMessage extends AttachmentsImp
         } else {
             filterIS = null;
         }
-        pushbackInStream = new PushbackInputStream(is,
-                                                   PUSHBACK_SIZE);
-
-        // Move the read pointer to the beginning of the first part
-        // read till the end of first boundary
-        while (true) {
-            int value;
+        
+        MimeConfig config = new MimeConfig();
+        config.setStrictParsing(true);
+        parser = new MimeTokenStream(config);
+        parser.setRecursionMode(RecursionMode.M_NO_RECURSE);
+        parser.parseHeadless(is, contentTypeString);
+        
+        // Move the parser to the beginning of the first part
+        while (parser.getState() != EntityState.T_START_BODYPART) {
             try {
-                value = pushbackInStream.read();
-                if ((byte) value == boundary[0]) {
-                    int boundaryIndex = 0;
-                    while ((boundaryIndex < boundary.length)
-                            && ((byte) value == boundary[boundaryIndex])) {
-                        value = pushbackInStream.read();
-                        if (value == -1) {
-                            throw new OMException(
-                                    "Unexpected End of Stream while searching for first Mime Boundary");
-                        }
-                        boundaryIndex++;
-                    }
-                    if (boundaryIndex == boundary.length) { // boundary found
-                        pushbackInStream.read();
-                        break;
-                    }
-                } else if (value == -1) {
-                    throw new OMException(
-                            "Mime parts not found. Stream ended while searching for the boundary");
-                }
-            } catch (IOException e1) {
-                throw new OMException("Stream Error" + e1.toString(), e1);
+                parser.next();
+            } catch (IOException ex) {
+                throw new OMException(ex);
+            } catch (MimeException ex) {
+                throw new OMException(ex);
             }
         }
 
@@ -280,11 +240,7 @@ class MIMEMessage extends AttachmentsImp
         streamsRequested = true;
         
         if (this.streams == null) {
-            BoundaryDelimitedStream boundaryDelimitedStream =
-                    new BoundaryDelimitedStream(pushbackInStream,
-                                                boundary, 1024);
-        
-            this.streams = new MultipartAttachmentStreams(boundaryDelimitedStream);
+            this.streams = new MultipartAttachmentStreams(parser);
         }
         
         return this.streams;
@@ -323,34 +279,12 @@ class MIMEMessage extends AttachmentsImp
     }
     
     /**
-     * endOfStreamReached will be set to true if the message ended in MIME Style having "--" suffix
-     * with the last mime boundary
-     *
-     * @param value
-     */
-    void setEndOfStream(boolean value) {
-        this.endOfStreamReached = value;
-    }
-    
-    InputStream getIncomingAttachmentsAsSingleStream() {
-        if (partsRequested) {
-            throw new IllegalStateException(
-                    "The attachments stream can only be accessed once; either by using the IncomingAttachmentStreams class or by getting a " +
-                            "collection of AttachmentPart objects. They cannot both be called within the life time of the same service request.");
-        }
-
-        streamsRequested = true;
-
-        return this.pushbackInStream;
-    }
-    
-    /**
      * @return the Next valid MIME part + store the Part in the Parts List
      * @throws OMException throw if content id is null or if two MIME parts contain the same
      *                     content-ID & the exceptions throws by getPart()
      */
     private DataHandler getNextPartDataHandler() throws OMException {
-        if (endOfStreamReached) {
+        if (parser.getState() == EntityState.T_END_MULTIPART) {
             return null;
         } else {
             Part nextPart = getPart();
@@ -425,19 +359,23 @@ class MIMEMessage extends AttachmentsImp
         boolean isSOAPPart = (partIndex == 0);
         int threshhold = (fileCacheEnable) ? fileStorageThreshold : 0;
 
-        // Create a MIMEBodyPartInputStream that simulates a single stream for this MIME body part
-        MIMEBodyPartInputStream partStream =
-            new MIMEBodyPartInputStream(pushbackInStream,
-                                        boundary,
-                                        this,
-                                        PUSHBACK_SIZE);
-
         // The PartFactory will determine which Part implementation is most appropriate.
-        Part part = PartFactory.createPart(getLifecycleManager(), partStream, 
+        Part part = PartFactory.createPart(getLifecycleManager(), parser, 
                                       isSOAPPart, 
                                       threshhold, 
                                       attachmentRepoDir, 
                                       contentLength);  // content-length for the whole message
+        try {
+            if (parser.next() == EntityState.T_EPILOGUE) {
+                while (parser.next() != EntityState.T_END_MULTIPART) {
+                    // Just loop
+                }
+            }
+        } catch (IOException ex) {
+            throw new OMException(ex);
+        } catch (MimeException ex) {
+            throw new OMException(ex);
+        }
         partIndex++;
         return part;
     }

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MultipartAttachmentStreams.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MultipartAttachmentStreams.java?rev=1152656&r1=1152655&r2=1152656&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MultipartAttachmentStreams.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/MultipartAttachmentStreams.java Sun Jul 31 22:36:19 2011
@@ -20,12 +20,15 @@
 package org.apache.axiom.attachments;
 
 import org.apache.axiom.om.OMException;
+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 javax.mail.MessagingException;
-import javax.mail.internet.InternetHeaders;
 import java.io.IOException;
-import java.util.Enumeration;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 
 /**
  * The MultipartAttachmentStreams class is used to create IncomingAttachmentInputStream objects when
@@ -38,12 +41,11 @@ import java.util.Enumeration;
  * such guarantee, we must fall back to caching these first parts. Afterwards, we can stream the
  * rest of the attachments that are after the SOAP part of the request message.
  */
-public final class MultipartAttachmentStreams extends IncomingAttachmentStreams {
-    private BoundaryDelimitedStream _delimitedStream = null;
+final class MultipartAttachmentStreams extends IncomingAttachmentStreams {
+    private final MimeTokenStream parser;
 
-    public MultipartAttachmentStreams(BoundaryDelimitedStream delimitedStream)
-            throws OMException {
-        this._delimitedStream = delimitedStream;
+    public MultipartAttachmentStreams(MimeTokenStream parser) throws OMException {
+        this.parser = parser;
     }
 
     public IncomingAttachmentInputStream getNextStream() throws OMException {
@@ -53,40 +55,48 @@ public final class MultipartAttachmentSt
             throw new IllegalStateException("nextStreamNotReady");
         }
 
-        InternetHeaders headers;
-
         try {
-            _delimitedStream = _delimitedStream.getNextStream();
-            if (_delimitedStream == null) {
+            if (parser.getState() == EntityState.T_BODY) {
+                if (parser.next() != EntityState.T_END_BODYPART) {
+                    throw new IllegalStateException();
+                }
+                parser.next();
+            }
+            
+            if (parser.getState() != EntityState.T_START_BODYPART) {
                 return null;
             }
-
-            headers = new InternetHeaders(_delimitedStream);
-
-        } catch (IOException ioe) {
-            ioe.printStackTrace();
-            throw new OMException(ioe);
-        } catch (MessagingException me) {
-            me.printStackTrace();
-            throw new OMException(me);
-        }
-
-        stream = new IncomingAttachmentInputStream(_delimitedStream, this);
-
-        Header header;
-        String name;
-        String value;
-        Enumeration e = headers.getAllHeaders();
-        while (e != null && e.hasMoreElements()) {
-            header = (Header) e.nextElement();
-            name = header.getName();
-            value = header.getValue();
-            if (IncomingAttachmentInputStream.HEADER_CONTENT_ID.equals(name)
-                    || IncomingAttachmentInputStream.HEADER_CONTENT_TYPE.equals(name)
-                    || IncomingAttachmentInputStream.HEADER_CONTENT_LOCATION.equals(name)) {
-                value = value.trim();
+            
+            if (parser.next() != EntityState.T_START_HEADER) {
+                throw new IllegalStateException();
+            }
+            
+            List fields = new ArrayList();
+            while (parser.next() == EntityState.T_FIELD) {
+                fields.add(parser.getField());
+            }
+            
+            if (parser.next() != EntityState.T_BODY) {
+                throw new IllegalStateException();
+            }
+            
+            stream = new IncomingAttachmentInputStream(parser.getInputStream(), this);
+    
+            for (Iterator it = fields.iterator(); it.hasNext(); ) {
+                Field field = (Field)it.next();
+                String name = field.getName();
+                String value = field.getBody();
+                if (IncomingAttachmentInputStream.HEADER_CONTENT_ID.equals(name)
+                        || IncomingAttachmentInputStream.HEADER_CONTENT_TYPE.equals(name)
+                        || IncomingAttachmentInputStream.HEADER_CONTENT_LOCATION.equals(name)) {
+                    value = value.trim();
+                }
+                stream.addHeader(name, value);
             }
-            stream.addHeader(name, value);
+        } catch (MimeException ex) {
+            throw new OMException(ex);
+        } catch (IOException ex) {
+            throw new OMException(ex);
         }
 
         setReadyToGetNextStream(false);

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java?rev=1152656&r1=1152655&r2=1152656&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java Sun Jul 31 22:36:19 2011
@@ -167,26 +167,21 @@ public class BufferUtils {
 
             // Read directly into the ByteBuffer array
             int bytesRead = is.read(bb.array());
-            // Continue reading until no bytes are read and no
-            // bytes are now available.
-            while (bytesRead > 0 || is.available() > 0) {
-                if (bytesRead > 0) {
-                    int written = 0;
-                    
-                    
-                    if (bytesRead < BUFFER_LEN) {
-                        // If the ByteBuffer is not full, allocate a new one
-                        ByteBuffer temp = ByteBuffer.allocate(bytesRead);
-                        temp.put(bb.array(), 0, bytesRead);
-                        temp.position(0);
-                        written = channel.write(temp);
-                    } else {
-                        // Write to channel
-                        bb.position(0);
-                        written = channel.write(bb);
-                        bb.clear();
-                    }
-                  
+            while (bytesRead != -1) {
+                int written = 0;
+                
+                
+                if (bytesRead < BUFFER_LEN) {
+                    // If the ByteBuffer is not full, allocate a new one
+                    ByteBuffer temp = ByteBuffer.allocate(bytesRead);
+                    temp.put(bb.array(), 0, bytesRead);
+                    temp.position(0);
+                    written = channel.write(temp);
+                } else {
+                    // Write to channel
+                    bb.position(0);
+                    written = channel.write(bb);
+                    bb.clear();
                 }
                 
                 // REVIEW: Do we need to ensure that bytesWritten is 

Modified: 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/PartFactory.java?rev=1152656&r1=1152655&r2=1152656&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/PartFactory.java Sun Jul 31 22:36:19 2011
@@ -19,7 +19,6 @@
 
 package org.apache.axiom.attachments.impl;
 
-import org.apache.axiom.attachments.MIMEBodyPartInputStream;
 import org.apache.axiom.attachments.Part;
 import org.apache.axiom.attachments.lifecycle.LifecycleManager;
 import org.apache.axiom.attachments.utils.BAAInputStream;
@@ -27,10 +26,13 @@ import org.apache.axiom.attachments.util
 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.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -73,7 +75,7 @@ public class PartFactory {
      * @return Part
      * @throws OMException if any exception is encountered while processing.
      */
-    public static Part createPart(LifecycleManager manager, MIMEBodyPartInputStream in,
+    public static Part createPart(LifecycleManager manager, MimeTokenStream parser,
                     boolean isSOAPPart,
                     int thresholdSize,
                     String attachmentDir,
@@ -92,7 +94,7 @@ public class PartFactory {
             // The readHeaders returns some extra bits that were read, but are part
             // of the data section.
             Hashtable headers = new Hashtable();
-            InputStream dross = readHeaders(in, headers);
+            readHeaders(parser, headers);
             
             Part part;
             try {
@@ -132,18 +134,16 @@ public class PartFactory {
                     // of resizing and GC.  The BAAOutputStream 
                     // keeps the data in non-contiguous byte buffers.
                     BAAOutputStream baaos = new BAAOutputStream();
-                    BufferUtils.inputStream2OutputStream(dross, baaos);
-                    BufferUtils.inputStream2OutputStream(in, baaos);
+                    BufferUtils.inputStream2OutputStream(parser.getInputStream(), baaos);
                     part = new PartOnMemoryEnhanced(headers, baaos.buffers(), baaos.length());
                 } else {
                     // We need to read the input stream to determine whether
                     // the size is bigger or smaller than the threshold.
                     BAAOutputStream baaos = new BAAOutputStream();
-                    int t1 = BufferUtils.inputStream2OutputStream(dross, baaos, thresholdSize);
-                    int t2 =  BufferUtils.inputStream2OutputStream(in, baaos, thresholdSize - t1);
-                    int total = t1 + t2;
+                    InputStream in = parser.getInputStream();
+                    int count = BufferUtils.inputStream2OutputStream(in, baaos, thresholdSize);
 
-                    if (total < thresholdSize) {
+                    if (count < thresholdSize) {
                         return new PartOnMemoryEnhanced(headers, baaos.buffers(), baaos.length());
                     } else {
                         // A BAAInputStream is an input stream over a list of non-contiguous 4K buffers.
@@ -157,6 +157,9 @@ public class PartFactory {
                     }
 
                 } 
+                if (parser.next() != EntityState.T_END_BODYPART) {
+                    throw new IllegalStateException();
+                }
             } finally {
                 if (!isSOAPPart) {
                     synchronized(semifore) {
@@ -179,117 +182,33 @@ public class PartFactory {
      * @param is
      * @param headers
      */
-    private static InputStream readHeaders(InputStream in, Map headers) throws IOException {
+    private static void readHeaders(MimeTokenStream parser, Map headers) throws IOException, MimeException {
         if(log.isDebugEnabled()){
             log.debug("initHeaders");
         }
-        boolean done = false;
-        
         
-        final int BUF_SIZE = 1024;
-        byte[] headerBytes = new byte[BUF_SIZE];
-        
-        int size = in.read(headerBytes);
-        int index = 0;
-        StringBuffer sb = new StringBuffer(50);
+        if (parser.next() != EntityState.T_START_HEADER) {
+            throw new IllegalStateException();
+        }
         
-        while (!done && index < size) {
+        while (parser.next() == EntityState.T_FIELD) {
+            Field field = parser.getField();
+            String name = field.getName();
+            String value = field.getBody();
             
-            // Get the next byte
-            int ch = headerBytes[index];
-            index++;
-            if (index == size) {
-                size = in.read(headerBytes);
-                index =0;
+            if (log.isDebugEnabled()){
+                log.debug("addHeader: (" + name + ") value=(" + value +")");
             }
-                
-            if (ch == 13) {
-                
-                // Get the next byte
-                ch = headerBytes[index];
-                index++;
-                if (index == size) {
-                    size = in.read(headerBytes);
-                    index =0;
-                }
-                
-                if (ch == 10) {
-                    // 13, 10 indicates we are starting a new line...thus a new header
-                    // Get the next byte
-                    ch = headerBytes[index];
-                    index++;
-                    if (index == size) {
-                        size = in.read(headerBytes);
-                        index =0;
-                    }
-                    
-                    if (ch == 13) {
-                        
-                        // Get the next byte
-                        ch = headerBytes[index];
-                        index++;
-                        if (index == size) {
-                            size = in.read(headerBytes);
-                            index =0;
-                        }
-                        
-                        if (ch == 10) {
-                            // Blank line indicates we are done.
-                            readHeader(sb, headers);
-                            sb.delete(0, sb.length()); // Clear the buffer for reuse
-                            done = true;
-                        } 
-                    } else {
-                        
-                        // Semicolon is a continuation character
-                        String check = sb.toString().trim();
-                        if (!check.endsWith(";")) {
-                            // now parse and add the header String
-                            readHeader(sb, headers);
-                            sb.delete(0, sb.length()); // Clear the buffer for reuse
-                        }
-                        sb.append((char) ch);
-                    }
-                } else {
-                    sb.append(13);
-                    sb.append((char) ch);
-                }
-            } else {
-                sb.append((char) ch);
-            }
-        }
-        if(log.isDebugEnabled()){
-            log.debug("End initHeaders");
+            Header headerObj = new Header(name, value);
+            
+            // Use the lower case name as the key
+            String key = name.toLowerCase();
+            headers.put(key, headerObj);
         }
         
-        // Return an input stream containing the dross bits
-        if (index >= size) {
-            index = size;
+        if (parser.next() != EntityState.T_BODY) {
+            throw new IllegalStateException();
         }
-        ByteArrayInputStream dross = new ByteArrayInputStream(headerBytes, index, size-index);
-        return dross;
-    }
-    
-    
-    /**
-     * Parse the header into a name and value pair.
-     * Add the name value pair to the map.
-     * @param header StringBuffer
-     * @param headers Map
-     */
-    private static void readHeader(StringBuffer header, Map headers) {
-        int delimiter = header.indexOf(":");
-        String name = header.substring(0, delimiter).trim();
-        String value = header.substring(delimiter + 1, header.length()).trim();
-        
-        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);
     }
     
     /**

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-osgi/axiom-osgi-run/pom.xml
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-osgi/axiom-osgi-run/pom.xml?rev=1152656&r1=1152655&r2=1152656&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-osgi/axiom-osgi-run/pom.xml (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-osgi/axiom-osgi-run/pom.xml Sun Jul 31 22:36:19 2011
@@ -81,6 +81,11 @@
             <version>4.0.1</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.james</groupId>
+            <artifactId>apache-mime4j-core</artifactId>
+            <scope>test</scope>
+        </dependency>
 
         <!--
             I'd prefer to use these slf4j bundles rather than the springsource

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-parent/pom.xml
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-parent/pom.xml?rev=1152656&r1=1152655&r2=1152656&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-parent/pom.xml (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-parent/pom.xml Sun Jul 31 22:36:19 2011
@@ -404,6 +404,11 @@
                 </exclusions>
             </dependency>
             <dependency>
+                <groupId>org.apache.james</groupId>
+                <artifactId>apache-mime4j-core</artifactId>
+                <version>0.8-SNAPSHOT</version>
+            </dependency>
+            <dependency>
                 <groupId>junit</groupId>
                 <artifactId>junit</artifactId>
                 <version>3.8.2</version>