Author: veithen Date: Sat Nov 13 13:29:30 2010 New Revision: 1034754 URL: http://svn.apache.org/viewvc?rev=1034754&view=rev Log: AXIS2-4828: Avoid buffering (and the unnecessary byte stream -> char stream -> byte stream conversion) of the SOAP body in SOAPMessageFormatter. The message is now streamed directly to the output stream.
Modified: axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/transport/http/SOAPMessageFormatter.java axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/util/Utils.java axis/axis2/java/core/trunk/modules/kernel/test/org/apache/axis2/misc/MiscTest.java Modified: axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/transport/http/SOAPMessageFormatter.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/transport/http/SOAPMessageFormatter.java?rev=1034754&r1=1034753&r2=1034754&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/transport/http/SOAPMessageFormatter.java (original) +++ axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/transport/http/SOAPMessageFormatter.java Sat Nov 13 13:29:30 2010 @@ -19,14 +19,14 @@ package org.apache.axis2.transport.http; +import org.apache.axiom.attachments.Attachments; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMOutputFormat; -import org.apache.axiom.om.impl.MIMEOutputUtils; +import org.apache.axiom.om.impl.OMMultipartWriter; import org.apache.axiom.util.UIDGenerator; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.context.MessageContext; -import org.apache.axis2.description.Parameter; import org.apache.axis2.transport.MessageFormatter; import org.apache.axis2.transport.http.util.URLTemplatingUtil; import org.apache.axis2.util.JavaUtils; @@ -37,8 +37,8 @@ import org.apache.commons.logging.LogFac import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLStreamException; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.OutputStream; -import java.io.StringWriter; import java.net.URL; public class SOAPMessageFormatter implements MessageFormatter { @@ -53,7 +53,6 @@ public class SOAPMessageFormatter implem log.debug(" isOptimized=" + format.isOptimized()); log.debug(" isDoingSWA=" + format.isDoingSWA()); } - OMElement element = msgCtxt.getEnvelope(); if (msgCtxt.isDoingMTOM()) { int optimizedThreshold = Utils.getMtomThreshold(msgCtxt); @@ -66,23 +65,9 @@ public class SOAPMessageFormatter implem } try { if (!(format.isOptimized()) && format.isDoingSWA()) { - // Write the SOAPBody to an output stream - // (We prefer an OutputStream because it is faster) - if (log.isDebugEnabled()) { - log.debug("Doing SWA and the format is not optimized. Buffer the SOAPBody in an OutputStream"); - } - ByteArrayOutputStream bufferedSOAPBodyBAOS = new ByteArrayOutputStream(); - if (preserve) { - element.serialize(bufferedSOAPBodyBAOS, format); - } else { - element.serializeAndConsume(bufferedSOAPBodyBAOS, format); - } - // Convert the ByteArrayOutputStream to StreamWriter so that SWA can - // be added. - String bufferedSOAPBody = Utils.BAOS2String(bufferedSOAPBodyBAOS, format.getCharSetEncoding()); - StringWriter bufferedSOAPBodySW = Utils.String2StringWriter(bufferedSOAPBody); - writeSwAMessage(msgCtxt, bufferedSOAPBodySW, out, format); + writeSwAMessage(msgCtxt, out, format, preserve); } else { + OMElement element = msgCtxt.getEnvelope(); if (preserve) { element.serialize(out, format); } else { @@ -110,17 +95,7 @@ public class SOAPMessageFormatter implem ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); if (!format.isOptimized()) { if (format.isDoingSWA()) { - if (log.isDebugEnabled()) { - log.debug("Doing SWA and the format is not optimized. Buffer the SOAPBody in an OutputStream"); - } - // Why are we creating a new OMOutputFormat - OMOutputFormat format2 = new OMOutputFormat(); - format2.setCharSetEncoding(format.getCharSetEncoding()); - ByteArrayOutputStream bufferedSOAPBodyBAOS = new ByteArrayOutputStream(); - element.serializeAndConsume(bufferedSOAPBodyBAOS, format2); - String bufferedSOAPBody = Utils.BAOS2String(bufferedSOAPBodyBAOS, format2.getCharSetEncoding()); - StringWriter bufferedSOAPBodySW = Utils.String2StringWriter(bufferedSOAPBody); - writeSwAMessage(msgCtxt, bufferedSOAPBodySW, bytesOut, format); + writeSwAMessage(msgCtxt, bytesOut, format, false); } else { element.serializeAndConsume(bytesOut, format); } @@ -203,9 +178,8 @@ public class SOAPMessageFormatter implem return targetURL; } - private void writeSwAMessage(MessageContext msgCtxt, - StringWriter bufferedSOAPBody, OutputStream outputStream, - OMOutputFormat format) { + private void writeSwAMessage(MessageContext msgCtxt, OutputStream outputStream, + OMOutputFormat format, boolean preserve) throws AxisFault { if (log.isDebugEnabled()) { log.debug("start writeSwAMessage()"); } @@ -215,33 +189,66 @@ public class SOAPMessageFormatter implem if (property != null) { MM7CompatMode = JavaUtils.isTrueExplicitly(property); } - if (!MM7CompatMode) { - MIMEOutputUtils.writeSOAPWithAttachmentsMessage(bufferedSOAPBody, - outputStream, - msgCtxt.getAttachmentMap(), format); - } else { - String innerBoundary; - String partCID; - Object innerBoundaryProperty = msgCtxt - .getProperty(Constants.Configuration.MM7_INNER_BOUNDARY); - if (innerBoundaryProperty != null) { - innerBoundary = (String) innerBoundaryProperty; + + try { + OMMultipartWriter mpw = new OMMultipartWriter(outputStream, format); + + OutputStream rootPartOutputStream = mpw.writeRootPart(); + OMElement element = msgCtxt.getEnvelope(); + if (preserve) { + element.serialize(rootPartOutputStream, format); } else { - innerBoundary = "innerBoundary" - + UIDGenerator.generateMimeBoundary(); + element.serializeAndConsume(rootPartOutputStream, format); } - Object partCIDProperty = msgCtxt - .getProperty(Constants.Configuration.MM7_PART_CID); - if (partCIDProperty != null) { - partCID = (String) partCIDProperty; + rootPartOutputStream.close(); + + OMMultipartWriter attachmentsWriter; + OutputStream innerOutputStream; + if (!MM7CompatMode) { + attachmentsWriter = mpw; + innerOutputStream = null; } else { - partCID = "innerCID" - + UIDGenerator.generateContentId(); - } - MIMEOutputUtils.writeMM7Message(bufferedSOAPBody, outputStream, - msgCtxt.getAttachmentMap(), format, partCID, - innerBoundary); + String innerBoundary; + String partCID; + Object innerBoundaryProperty = msgCtxt + .getProperty(Constants.Configuration.MM7_INNER_BOUNDARY); + if (innerBoundaryProperty != null) { + innerBoundary = (String) innerBoundaryProperty; + } else { + innerBoundary = "innerBoundary" + + UIDGenerator.generateMimeBoundary(); + } + Object partCIDProperty = msgCtxt + .getProperty(Constants.Configuration.MM7_PART_CID); + if (partCIDProperty != null) { + partCID = (String) partCIDProperty; + } else { + partCID = "innerCID" + + UIDGenerator.generateContentId(); + } + OMOutputFormat innerFormat = new OMOutputFormat(format); + innerFormat.setMimeBoundary(innerBoundary); + innerOutputStream = mpw.writePart("multipart/related; boundary=\"" + innerBoundary + "\"", partCID); + attachmentsWriter = new OMMultipartWriter(innerOutputStream, innerFormat); + } + + Attachments attachments = msgCtxt.getAttachmentMap(); + for (String contentID : attachments.getAllContentIDs()) { + attachmentsWriter.writePart(attachments.getDataHandler(contentID), contentID); + } + + if (MM7CompatMode) { + attachmentsWriter.complete(); + innerOutputStream.close(); + } + + mpw.complete(); + } catch (IOException ex) { + throw AxisFault.makeFault(ex); + } catch (XMLStreamException ex) { + throw AxisFault.makeFault(ex); } + if (log.isDebugEnabled()) { log.debug("end writeSwAMessage()"); } Modified: axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/util/Utils.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/util/Utils.java?rev=1034754&r1=1034753&r2=1034754&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/util/Utils.java (original) +++ axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/util/Utils.java Sat Nov 13 13:29:30 2010 @@ -57,11 +57,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.xml.namespace.QName; - -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; @@ -658,36 +654,6 @@ public class Utils { private static boolean isIP(String hostAddress) { return hostAddress.split("[.]").length == 4; } - - /** - * Convert ByteArrayOutputStream to String - * @param baos ByteArrayOutputStream - * @param charset - * @return String - */ - public static String BAOS2String(ByteArrayOutputStream baos, String charset) { - try { - return baos.toString(charset); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - - /** - * Convert String into a StringWriter - * @param input String - * @return StringWriter - */ - public static StringWriter String2StringWriter(String input) { - StringWriter sw = null; - if (input == null || input.length() == 0) { - sw = new StringWriter(); - } else { - sw = new StringWriter(input.length()); - sw.append(input); - } - return sw; - } /** * Get the scheme part from a URI (or URL). Modified: axis/axis2/java/core/trunk/modules/kernel/test/org/apache/axis2/misc/MiscTest.java URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/kernel/test/org/apache/axis2/misc/MiscTest.java?rev=1034754&r1=1034753&r2=1034754&view=diff ============================================================================== --- axis/axis2/java/core/trunk/modules/kernel/test/org/apache/axis2/misc/MiscTest.java (original) +++ axis/axis2/java/core/trunk/modules/kernel/test/org/apache/axis2/misc/MiscTest.java Sat Nov 13 13:29:30 2010 @@ -21,10 +21,7 @@ package org.apache.axis2.misc; import org.apache.axis2.AbstractTestCase; import org.apache.axis2.AxisFault; -import org.apache.axis2.util.Utils; -import java.io.ByteArrayOutputStream; -import java.io.StringWriter; import java.lang.reflect.InvocationTargetException; public class MiscTest extends AbstractTestCase { @@ -44,24 +41,4 @@ public class MiscTest extends AbstractTe e = new AxisFault(""); } - public void testStringWriterConversion() throws Exception { - String input = " Some text \u00df with \u00fc special \u00f6 chars \u00e4. \n"; - - String charset = "utf-8"; - byte[] bytes = input.getBytes(charset); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write(bytes); - baos.flush(); - StringWriter sw = Utils.String2StringWriter(Utils.BAOS2String(baos, charset)); - assertTrue(input.equals(sw.toString())); - - charset = "utf-16"; - bytes = input.getBytes(charset); - baos = new ByteArrayOutputStream(); - baos.write(bytes); - baos.flush(); - sw = Utils.String2StringWriter(Utils.BAOS2String(baos, charset)); - assertTrue(input.equals(sw.toString())); - - } }