You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2009/07/16 23:10:04 UTC

svn commit: r794858 - in /webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom: mime/ mime/impl/ mime/impl/javamail/ om/impl/

Author: veithen
Date: Thu Jul 16 21:10:03 2009
New Revision: 794858

URL: http://svn.apache.org/viewvc?rev=794858&view=rev
Log:
Added a new API for MIME multipart package writers. This will eventually replace MIMEOutputUtils for MTOM and SwA (currently only for MTOM).

Reasons:
* It will allow us to add an alternative (and more optimized) implementation that is not based on JavaMail.
* It provides a more flexible (but still simpler) API than MIMEOutputUtils (which imposes too much constraints on how the API is used).

Also refactored MTOMXMLStreamWriter to use this new API. Note that the relevant methods in MIMEOutputUtils are still there but have been deprecated.

Added:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriter.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriterFactory.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/JavaMailMultipartWriterFactory.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/MultipartWriterImpl.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/package.html   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMMultipartWriter.java   (with props)
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriter.java?rev=794858&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriter.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriter.java Thu Jul 16 21:10:03 2009
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.mime;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.activation.DataHandler;
+
+/**
+ * Writes a MIME multipart package as used by XOP/MTOM and SOAP with Attachments.
+ * Objects implementing this interface are created using a {@link MultipartWriterFactory}. MIME
+ * parts are written using {@link #writePart(String, String, String)} or
+ * {@link #writePart(DataHandler, String, String)}. Calls to both methods can be mixed, i.e. it
+ * is not required to use the same method for all MIME parts. Instead, the caller should choose
+ * the most convenient method for each part (depending on the form in which the content is
+ * available). After all parts have been written, {@link #complete()} must be called to write the
+ * final MIME boundary.
+ * <p>
+ * The following semantics are defined for the <code>contentTransferEncoding</code> and
+ * <code>contentID</code> arguments of the two write methods:
+ * <ul>
+ *   <li>It is the responsibility of the implementation to apply the content transfer encoding
+ *       as specified by the <code>contentTransferEncoding</code> argument. The caller only
+ *       provides the unencoded data. The implementation should support at least <tt>binary</tt>
+ *       and <tt>base64</tt>. If it doesn't support the specified encoding, it may use an
+ *       alternative one. In any case, the implementation must make sure that the MIME part
+ *       has a <tt>Content-Transfer-Encoding</tt> header appropriate for the applied
+ *       encoding.</li>
+ *   <li>The content ID passed as argument is always the raw ID (without the angle brackets).
+ *       It is the responsibility of the implementation to properly format the value
+ *       of the <tt>Content-ID</tt> header.</li>
+ * </ul>
+ */
+public interface MultipartWriter {
+    /**
+     * Start writing a MIME part. The methods returns an {@link OutputStream} that the caller can
+     * use to write the content of the MIME part. After writing the content,
+     * {@link OutputStream#close()} must be called to complete the writing of the MIME part.
+     * 
+     * @param contentType
+     *            the value of the <tt>Content-Type</tt> header of the MIME part
+     * @param contentTransferEncoding
+     *            the content transfer encoding to be used (see above)
+     * @param contentID
+     *            the content ID of the MIME part (see above)
+     * @return an output stream to write the content of the MIME part
+     * @throws IOException
+     *             if an I/O error occurs when writing to the underlying stream
+     */
+    OutputStream writePart(String contentType, String contentTransferEncoding, String contentID)
+            throws IOException;
+    
+    /**
+     * Write a MIME part. The content is provided by a {@link DataHandler} object, which also
+     * specifies the content type of the part.
+     * 
+     * @param dataHandler
+     *            the content of the MIME part to write
+     * @param contentTransferEncoding
+     *            the content transfer encoding to be used (see above)
+     * @param contentID
+     *            the content ID of the MIME part (see above)
+     * @throws IOException
+     *             if an I/O error occurs when writing the part to the underlying stream
+     */
+    void writePart(DataHandler dataHandler, String contentTransferEncoding, String contentID)
+            throws IOException;
+    
+    /**
+     * Complete writing of the MIME multipart package. This method does <b>not</b> close the
+     * underlying stream.
+     * 
+     * @throws IOException
+     *             if an I/O error occurs when writing to the underlying stream
+     */
+    void complete() throws IOException;
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriterFactory.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriterFactory.java?rev=794858&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriterFactory.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriterFactory.java Thu Jul 16 21:10:03 2009
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.mime;
+
+import java.io.OutputStream;
+
+/**
+ * Factory for {@link MultipartWriter} instances.
+ */
+public interface MultipartWriterFactory {
+    /**
+     * Create a new {@link MultipartWriter} instance that writes a MIME multipart package to a given
+     * output stream.
+     * 
+     * @param out
+     *            The output stream to write the MIME package to.
+     * @param boundary
+     *            The MIME boundary to use. The value should not include the leading dashes, i.e. it
+     *            is the same value as used in the <tt>boundary</tt> content type parameter.
+     * @return the writer instance
+     */
+    MultipartWriter createMultipartWriter(OutputStream out, String boundary);
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/MultipartWriterFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/JavaMailMultipartWriterFactory.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/JavaMailMultipartWriterFactory.java?rev=794858&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/JavaMailMultipartWriterFactory.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/JavaMailMultipartWriterFactory.java Thu Jul 16 21:10:03 2009
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.mime.impl.javamail;
+
+import java.io.OutputStream;
+
+import org.apache.axiom.mime.MultipartWriter;
+import org.apache.axiom.mime.MultipartWriterFactory;
+
+/**
+ * Factory for the JavaMail based {@link MultipartWriter} implementation.
+ */
+public class JavaMailMultipartWriterFactory implements MultipartWriterFactory {
+    // TODO: we should have some sort of service locator to discover the implementation
+    public static MultipartWriterFactory INSTANCE = new JavaMailMultipartWriterFactory();
+
+    public MultipartWriter createMultipartWriter(OutputStream out, String boundary) {
+        return new MultipartWriterImpl(out, boundary);
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/JavaMailMultipartWriterFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/MultipartWriterImpl.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/MultipartWriterImpl.java?rev=794858&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/MultipartWriterImpl.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/MultipartWriterImpl.java Thu Jul 16 21:10:03 2009
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.mime.impl.javamail;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import javax.activation.DataHandler;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeBodyPart;
+
+import org.apache.axiom.mime.MultipartWriter;
+import org.apache.axiom.util.blob.BlobDataSource;
+import org.apache.axiom.util.blob.MemoryBlob;
+import org.apache.axiom.util.blob.WritableBlob;
+
+class MultipartWriterImpl implements MultipartWriter {
+    private static byte[] DASH_DASH = { '-', '-' };
+    private static byte[] CR_LF = { 13, 10 };
+    
+    class PartOutputStream extends OutputStream {
+        private final String contentType;
+        private final String contentTransferEncoding;
+        private final String contentID;
+        private final WritableBlob blob;
+        private final OutputStream parent;
+
+        public PartOutputStream(String contentType, String contentTransferEncoding,
+                String contentID) {
+            this.contentType = contentType;
+            this.contentTransferEncoding = contentTransferEncoding;
+            this.contentID = contentID;
+            blob = new MemoryBlob();
+            parent = blob.getOutputStream();
+        }
+
+        public void write(int b) throws IOException {
+            parent.write(b);
+        }
+
+        public void write(byte[] b, int off, int len) throws IOException {
+            parent.write(b, off, len);
+        }
+
+        public void write(byte[] b) throws IOException {
+            parent.write(b);
+        }
+        
+        public void close() throws IOException {
+            parent.close();
+            writePart(new DataHandler(new BlobDataSource(blob, contentType)),
+                    contentTransferEncoding, contentID);
+        }
+    }
+    
+    private final OutputStream out;
+    private final byte[] boundary;
+
+    public MultipartWriterImpl(OutputStream out, String boundary) {
+        this.out = out;
+        try {
+            this.boundary = boundary.getBytes("ascii");
+        } catch (UnsupportedEncodingException ex) {
+            // If we ever get here, then there is something really wrong with the JRE...
+            throw new RuntimeException(ex);
+        }
+    }
+    
+    public OutputStream writePart(String contentType, String contentTransferEncoding,
+            String contentID) throws IOException {
+        return new PartOutputStream(contentType, contentTransferEncoding, contentID);
+    }
+
+    public void writePart(DataHandler dataHandler, String contentTransferEncoding,
+            String contentID) throws IOException {
+        MimeBodyPart mimeBodyPart = new MimeBodyPart();
+        try {
+            mimeBodyPart.setDataHandler(dataHandler);
+            mimeBodyPart.addHeader("Content-ID", "<" + contentID + ">");
+            mimeBodyPart.addHeader("Content-Type", dataHandler.getContentType());
+            mimeBodyPart.addHeader("Content-Transfer-Encoding", contentTransferEncoding);
+        } catch (MessagingException ex) {
+            IOException ex2 = new IOException("Unable to create MimeBodyPart");
+            ex2.initCause(ex);
+            throw ex2;
+        }
+        out.write(DASH_DASH);
+        out.write(boundary);
+        out.write(CR_LF);
+        try {
+            mimeBodyPart.writeTo(out);
+        } catch (MessagingException ex) {
+            IOException ex2 = new IOException("Unable to write the MimeBodyPart object");
+            ex2.initCause(ex);
+            throw ex2;
+        }
+        out.write(CR_LF);
+    }
+
+    public void complete() throws IOException {
+        out.write(DASH_DASH);
+        out.write(boundary);
+        out.write(DASH_DASH);
+        out.write(CR_LF);
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/impl/javamail/MultipartWriterImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/package.html
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/package.html?rev=794858&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/package.html (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/package.html Thu Jul 16 21:10:03 2009
@@ -0,0 +1,8 @@
+<html>
+<body>
+Contains interfaces for MIME message processing.
+<p>
+The APIs in this package have been designed as low level provider interfaces independent of
+Axiom's core APIs.
+</body>
+</html>
\ No newline at end of file

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/mime/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java?rev=794858&r1=794857&r2=794858&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MIMEOutputUtils.java Thu Jul 16 21:10:03 2009
@@ -56,15 +56,7 @@
     private static byte[] CRLF = { 13, 10 };
 
     /**
-     * Invoked by MTOMXMLStreamWriter to write the SOAP Part and the attachements. 
-     * 
-     * @param outStream OutputStream target
-     * @param bufferedXML String containing XML of SOAPPart
-     * @param binaryNodeList Text nodes with the attachment Data Handlers
-     * @param boundary Boundary String
-     * @param contentId Content-ID of SOAPPart
-     * @param charSetEncoding Character Encoding of SOAPPart
-     * @param SOAPContentType Content-Type of SOAPPart
+     * @deprecated use {@link OMMultipartWriter} instead
      */
     public static void complete(OutputStream outStream, 
                                 byte[] xmlData,
@@ -76,17 +68,9 @@
         complete(outStream, xmlData, binaryNodeList, boundary,
                  contentId, charSetEncoding, SOAPContentType, null);
     }
+    
     /**
-     * Invoked by MTOMXMLStreamWriter to write the SOAP Part and the attachements. 
-     * 
-     * @param outStream OutputStream target
-     * @param bufferedXML String containing XML of SOAPPart
-     * @param binaryNodeList Text nodes with the attachment Data Handlers
-     * @param boundary Boundary String
-     * @param contentId Content-ID of SOAPPart
-     * @param charSetEncoding Character Encoding of SOAPPart
-     * @param SOAPContentType Content-Type of SOAPPart
-     * @param OMOutputFormat 
+     * @deprecated use {@link OMMultipartWriter} instead
      */
     public static void complete(OutputStream outStream, 
                                 byte[] xmlData,

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java?rev=794858&r1=794857&r2=794858&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/MTOMXMLStreamWriter.java Thu Jul 16 21:10:03 2009
@@ -19,10 +19,9 @@
 
 package org.apache.axiom.om.impl;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
 import java.util.LinkedList;
 
 import javax.activation.DataHandler;
@@ -38,8 +37,6 @@
 import org.apache.axiom.om.OMText;
 import org.apache.axiom.om.util.CommonUtils;
 import org.apache.axiom.om.util.StAXUtils;
-import org.apache.axiom.soap.SOAP11Constants;
-import org.apache.axiom.soap.SOAP12Constants;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -60,7 +57,8 @@
     private XMLStreamWriter xmlWriter;
     private OutputStream outStream;
     private LinkedList binaryNodeList = new LinkedList();
-    private ByteArrayOutputStream bufferedXML;  // XML for the SOAPPart
+    private OMMultipartWriter multipartWriter;
+    private OutputStream rootPartOutputStream;
     private OMOutputFormat format = new OMOutputFormat();
     
     // State variables
@@ -96,13 +94,19 @@
         this.format = format;
         this.outStream = outStream;
 
-        if (format.getCharSetEncoding() == null) //Default encoding is UTF-8
-            format.setCharSetEncoding(OMOutputFormat.DEFAULT_CHAR_SET_ENCODING);
+        String encoding = format.getCharSetEncoding();
+        if (encoding == null) { //Default encoding is UTF-8
+            format.setCharSetEncoding(encoding = OMOutputFormat.DEFAULT_CHAR_SET_ENCODING);
+        }
 
         if (format.isOptimized()) {
-            // REVIEW If the buffered XML gets too big, should it be written out to a file 
-            bufferedXML = new ByteArrayOutputStream();
-            xmlWriter = StAXUtils.createXMLStreamWriter(bufferedXML,format.getCharSetEncoding());
+            multipartWriter = new OMMultipartWriter(outStream, format);
+            try {
+                rootPartOutputStream = multipartWriter.writeRootPart();
+            } catch (IOException ex) {
+                throw new XMLStreamException(ex);
+            }
+            xmlWriter = StAXUtils.createXMLStreamWriter(rootPartOutputStream, encoding);
         } else {
             xmlWriter = StAXUtils.createXMLStreamWriter(outStream,
                                                         format.getCharSetEncoding());
@@ -166,7 +170,6 @@
             log.debug("Calling MTOMXMLStreamWriter.flush");
         }
         xmlWriter.flush();
-        String SOAPContentType;
         // flush() triggers the optimized attachment writing.
         // If the optimized attachments are specified, and the xml
         // document is completed, then write out the attachments.
@@ -175,24 +178,14 @@
                 log.debug("The XML writing is completed.  Now the attachments are written");
             }
             isComplete = true;
-            if (format.isSOAP11()) {
-                SOAPContentType = SOAP11Constants.SOAP_11_CONTENT_TYPE;
-            } else {
-                SOAPContentType = SOAP12Constants.SOAP_12_CONTENT_TYPE;
-            }
             try {
-                MIMEOutputUtils.complete(outStream,
-                                         bufferedXML.toByteArray(),
-                                         binaryNodeList,
-                                         format.getMimeBoundary(),
-                                         format.getRootContentId(),
-                                         format.getCharSetEncoding(),
-                                         SOAPContentType, 
-                                         format);
-                bufferedXML.close();
-                bufferedXML = null;
-            } catch (UnsupportedEncodingException e) {
-                throw new OMException(e);
+                rootPartOutputStream.close();
+                for (Iterator it = binaryNodeList.iterator(); it.hasNext();) {
+                    OMText text = (OMText) it.next();
+                    multipartWriter.writePart((DataHandler) text.getDataHandler(),
+                            text.getContentID());
+                }
+                multipartWriter.complete();
             } catch (IOException e) {
                 throw new OMException(e);
             }
@@ -419,8 +412,8 @@
      */
     public OutputStream getOutputStream() throws XMLStreamException {  
         OutputStream os = null;
-        if (bufferedXML != null) {
-            os = bufferedXML;
+        if (rootPartOutputStream != null) {
+            os = rootPartOutputStream;
         } else {
             os = outStream;
         }
@@ -428,8 +421,8 @@
         if (isDebugEnabled) {
             if (os == null) {
                 log.debug("Direct access to the output stream is not available.");
-            } else if (bufferedXML != null) {
-                log.debug("Returning access to the buffered xml stream: " + bufferedXML);
+            } else if (rootPartOutputStream != null) {
+                log.debug("Returning access to the buffered xml stream: " + rootPartOutputStream);
             } else {
                 log.debug("Returning access to the original output stream: " + os);
             }

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMMultipartWriter.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMMultipartWriter.java?rev=794858&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMMultipartWriter.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMMultipartWriter.java Thu Jul 16 21:10:03 2009
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.om.impl;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.activation.DataHandler;
+
+import org.apache.axiom.attachments.ConfigurableDataHandler;
+import org.apache.axiom.mime.MultipartWriter;
+import org.apache.axiom.mime.impl.javamail.JavaMailMultipartWriterFactory;
+import org.apache.axiom.om.OMOutputFormat;
+import org.apache.axiom.om.util.CommonUtils;
+import org.apache.axiom.soap.SOAP11Constants;
+import org.apache.axiom.soap.SOAP12Constants;
+
+/**
+ * Writes a MIME multipart package as used by XOP/MTOM and SOAP with Attachments. This class wraps a
+ * {@link MultipartWriter}, providing a higher level API. In particular it will configure content
+ * types and content transfer encodings based on information from an {@link OMOutputFormat} object.
+ */
+public class OMMultipartWriter {
+    private final OMOutputFormat format;
+    private final MultipartWriter writer;
+    private final boolean useCTEBase64;
+    private final String rootPartContentType;
+    
+    public OMMultipartWriter(OutputStream out, OMOutputFormat format) {
+        this.format = format;
+        
+        // TODO: need some config mechanism to look up the factory
+        writer = JavaMailMultipartWriterFactory.INSTANCE.createMultipartWriter(out,
+                format.getMimeBoundary());
+        
+        useCTEBase64 = format != null && Boolean.TRUE.equals(
+                format.getProperty(OMOutputFormat.USE_CTE_BASE64_FOR_NON_TEXTUAL_ATTACHMENTS));
+        
+        if (format.isOptimized()) {
+            String soapContentType;
+            if (format.isSOAP11()) {
+                soapContentType = SOAP11Constants.SOAP_11_CONTENT_TYPE;
+            } else {
+                soapContentType = SOAP12Constants.SOAP_12_CONTENT_TYPE;
+            }
+            rootPartContentType = "application/xop+xml; charset=" + format.getCharSetEncoding()
+                    + "; type=\"" + soapContentType + "\"";            
+        } else {
+            // TODO: need to support SwA here
+            throw new IllegalArgumentException();
+        }
+    }
+
+    private String getContentTransferEncoding(String contentType) {
+        if (useCTEBase64 && !CommonUtils.isTextualPart(contentType)) {
+            return "base64";
+        } else {
+            return "binary";
+        }
+    }
+    
+    /**
+     * Start writing the root part of the MIME package. This method delegates to
+     * {@link MultipartWriter#writePart(String, String, String)}, but computes the content type,
+     * content transfer encoding and content ID from the {@link OMOutputFormat}.
+     * 
+     * @return an output stream to write the content of the MIME part
+     * @throws IOException
+     *             if an I/O error occurs when writing to the underlying stream
+     */
+    public OutputStream writeRootPart() throws IOException {
+        return writer.writePart(rootPartContentType, "binary", format.getRootContentId());
+    }
+
+    /**
+     * Write a MIME part. This method delegates to
+     * {@link MultipartWriter#writePart(DataHandler, String, String)}, but computes the appropriate
+     * content transfer encoding from the {@link OMOutputFormat}.
+     * 
+     * @param dataHandler
+     *            the content of the MIME part to write
+     * @param contentID
+     *            the content ID of the MIME part
+     * @throws IOException
+     *             if an I/O error occurs when writing the part to the underlying stream
+     */
+    public void writePart(DataHandler dataHandler, String contentID) throws IOException {
+        String contentTransferEncoding;
+        if (dataHandler instanceof ConfigurableDataHandler) {
+            contentTransferEncoding = ((ConfigurableDataHandler)dataHandler).getTransferEncoding();
+        } else {
+            contentTransferEncoding = getContentTransferEncoding(dataHandler.getContentType());
+        }
+        writer.writePart(dataHandler, contentTransferEncoding, contentID);
+    }
+
+    /**
+     * Complete writing of the MIME multipart package. This method delegates to
+     * {@link MultipartWriter#complete()}.
+     * 
+     * @throws IOException
+     *             if an I/O error occurs when writing to the underlying stream
+     */
+    public void complete() throws IOException {
+        writer.complete();
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/impl/OMMultipartWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native