Hi,

I think I managed make it compatible to existing code and yet still mush
faster (8-10 sec of 60 I had in the morning ). The Mime part will be creates
as soon as it requested, otherwise plain Envelope used 
Also I set up initial buffer in couple of classes...

Please take a look

Also, if comparing to yesterday's picture timeload, we have 4 big time
consumers, which I suppose quite logical

1. DocumentBulder.parse 
2. RPCMessage.extractFromEnvelope 
3. EnvelopeMaprshall 
4. InputStream.read 

Pavel

> -----Original Message-----
> From: Scott Nichol [mailto:snicholnews@;scottnichol.com]
> Sent: Thursday, November 14, 2002 6:54 PM
> To: [EMAIL PROTECTED]
> Subject: Re: Using mime parts - huge drawbacks
> 
> 
> Thanks for yet another valuable contribution!  I've committed this
> patch.  Your others will have to wait a little while since I have to
> earn some money today (instead of working on Apache SOAP).
> 
> I have some questions.
> 
> 1. What do you use to do this profile?  I have very little experience
> with profilers, mainly with JInsight, but that was over a year ago.
> 
> 2. What is "ComplexRequest"?
> 
> 3. Do you know what version of JavaMail you are using?
> 
> Something very interesting that I had not noticed before is that
> provider.invoke gets on the request and response contexts, so 
> that even
> "plain" RPCs have their SOAP envelope put into SOAPContext and
> subsequently extracted.  I am thinking that the SOAPContext 
> should gain
> the ability to hold a SOAP envelope other than simply as the root part
> to avoid the expense of extracting it.  In fact, SOAPContext should be
> able to keep track of whether there are any attachments versus just an
> evelope to optimize the situation where there is only an envelope.  We
> would use lazy evaluation to stuff it into the root part if the root
> part is requested, but otherwise provide shortcuts to just access the
> envelope.
> 
> Scott Nichol
> 
> ----- Original Message -----
> From: "Pavel Ausianik" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Sent: Thursday, November 14, 2002 9:04 AM
> Subject: RE: Using mime parts - huge drawbacks
> 
> 
> > Scott,
> >
> > Here is server time picture taken on the Tomcat server , processing
> > ComplexRequest.
> > The red ellipses show that MimePart  initialization takes 10-15% of
> CPU
> > load.
> > The blue ellipses show that ContentType is also quite expensive for
> benefits
> > it provide. I prepared patch for caching ContentType...
> >
> > Pavel
> >
> > > -----Original Message-----
> > > From: Scott Nichol [mailto:snicholnews@;scottnichol.com]
> > > Sent: Wednesday, November 13, 2002 5:48 PM
> > > To: [EMAIL PROTECTED]
> > > Subject: Re: Using mime parts - huge drawbacks
> > >
> > >
> > > Pavel,
> > >
> > > Yes, this is a good observation.  In the case where there are no
> > > attachments, the process could be streamlined by serializing
> directly.
> > > I am still actively working on this part of the code
> > > (TransportMessage,
> > > SOAPContext, Call) and will look at sidestepping some of the
> activity
> > > where there are no attachments, just a SOAP envelope, which
> > > as you point
> > > out is the typical scenario.
> > >
> > > Scott Nichol
> > >
> > > ----- Original Message -----
> > > From: "Pavel Ausianik" <[EMAIL PROTECTED]>
> > > To: <[EMAIL PROTECTED]>
> > > Sent: Wednesday, November 13, 2002 9:04 AM
> > > Subject: Using mime parts - huge drawbacks
> > >
> > >
> > > > Hello,
> > > >
> > > > thinking more on the current code I have found interesting
> > > thing. Most
> > > > requests we have a simple, straight SOAP envelopes, without any
> > > attachments.
> > > > Looking how it is processed I have found following (traced from
> > > > httpconnection):
> > > >
> > > > In SOAPHTTPConnection.send() we call TransportMessage.save().
> > > > Let's look into it (see my comment how I understand it:
> > > >
> > > >         String rootContentType = null;
> > > >
> > > > // Root Part is Not set for Simple Envelope !
> > > >
> > > >         if (ctx.isRootPartSet()) {
> > > > //... Not in use for simple case
> > > >         }
> > > >
> > > >         if (rootContentType == null)
> > > >             rootContentType =
> Constants.HEADERVAL_CONTENT_TYPE_UTF8;
> > > >         if (getEnvelope() != null) {
> > > >
> > > > // Now really create root part - how important it is if we
> > > now how to
> > > write
> > > > this Envelope without involving Mime !!!
> > > >
> > > >             ctx.setRootPart(envelope, rootContentType);
> > > >         } else {
> > > > //... Not in use for simple case
> > > >         }
> > > >
> > > >         // Print the whole response to a byte array.
> > > > // Tracing into this code we'll found that all it will do it add
> > > > unnecessary header to envelope
> > > > // The headers include Content-Type - we know which is,
> > > > // Content-id  - do we need it? Even if yes we can create any id
> > > > // Content-Transfer-Encoding - not for HTTp, anyway we 
> force it to
> 8
> > > bit
> > > > // Content-Lenght - easy to calculate
> > > >
> > > >         ByteArrayOutputStream payload =
> > > >             new ByteArrayOutputStream(1024);
> > > >         ctx.writeTo(payload);
> > > >         bytes = payload.toByteArray();
> > > >
> > > >         // Now strip off the headers. (Grmbl, get rid 
> of JavaMail
> > > >         // for MIME support). Just intercept the Content-Type
> > > > // Remove headers which created right now....
> > > >
> > > > ....
> > > >
> > > >         // TODO: should not send for HTTP response
> > > >         headers.put("Accept-Encoding", "x-gzip");
> > > >         if (Boolean.TRUE.equals(ctx.getGzip())) {
> > > >             // Deflate
> > > >             ByteArrayOutputStream baos =
> > > >                                new
> > > ByteArrayOutputStream(bytes.length
> > > * 2);
> > > >             GZIPOutputStream gzos = new GZIPOutputStream(baos);
> > > >             gzos.write(bytes, offset, bytes.length - offset);
> > > >             gzos.close();
> > > >             baos.close();
> > > >             bytes = baos.toByteArray();
> > > >             offset = 0;
> > > >
> > > >             headers.put("Content-Encoding", "x-gzip");
> > > >         }
> > > >
> > > > Seems like we are doing wonderful job of running a lot 
> unnecessary
> > > > operations,  involving a lot of memory allocations... It
> > > could be most
> > > > advanced improvement we ever done!
> > > >
> > > > Best regards,
> > > > Pavel
> > > >
> > > >
> > > >
> > > > --
> > > > To unsubscribe, e-mail:
> > <mailto:soap-dev-unsubscribe@;xml.apache.org>
> > > For additional commands, e-mail:
> <mailto:soap-dev-help@;xml.apache.org>
> > >
> > >
> >
> >
> > --
> > To unsubscribe, e-mail:   
> <mailto:soap-dev-unsubscribe@;xml.apache.org>
> > For additional commands, e-mail: 
> <mailto:soap-dev-help@;xml.apache.org>
> >
> >
> 
> 
> --------------------------------------------------------------
> ----------
> --------
> 
> 
> > --
> > To unsubscribe, e-mail:   
> <mailto:soap-dev-unsubscribe@;xml.apache.org>
> > For additional commands, e-mail: 
> <mailto:soap-dev-help@;xml.apache.org>
> 
> 
> --
> To unsubscribe, e-mail:   <mailto:soap-dev-unsubscribe@;xml.apache.org>
> For additional commands, e-mail: <mailto:soap-dev-help@;xml.apache.org>
> 

Index: SOAPContext.java
===================================================================
RCS file: /home/cvspublic/xml-soap/java/src/org/apache/soap/rpc/SOAPContext.java,v
retrieving revision 1.13
diff -u -r1.13 SOAPContext.java
--- SOAPContext.java    6 Nov 2002 18:08:04 -0000       1.13
+++ SOAPContext.java    15 Nov 2002 13:36:17 -0000
@@ -83,13 +83,17 @@
     protected MimeMultipart parts;
     protected Hashtable     bag    = new Hashtable();
     protected ClassLoader   loader = null ;
-    protected Vector        multiRef = new Vector();
-    protected Hashtable     deserializedMultiRef = new Hashtable();
+    protected List          multiRef = null;
+    protected Map           deserializedMultiRef = null;
     protected String        currentId = null;
     protected boolean       docLitSerialization = false;
     protected Boolean       gzip = null;
     protected Boolean       acceptGzip = null;
 
+    protected boolean       isRootPartEnvelope = false;
+    protected String        rootPartString = null;
+    protected String        rootPartContentType = "";
+
     // Constants for checking type for base64 encoding
     private static MimeType MIME_STREAM;
     private static MimeType MIME_IMAGE;
@@ -159,6 +163,7 @@
      * @return          the Part, or null if no such part exists.
      */
     public MimeBodyPart getBodyPart(int index) {
+        fillRootPart();
       /* Actually, this method never throws a MessagingException. In case a
        * future implementation does, catch it and throw an
        * IndexOutOfBoundsException
@@ -188,6 +193,7 @@
      * @return          the Part, or null if no such part exists.
      */
     public MimeBodyPart getBodyPart(String CID) {
+        fillRootPart();
         if (parts == null) {
             return null;
         }
@@ -221,6 +227,7 @@
      * @return          the Part or null if not found
      */
     public MimeBodyPart findBodyPart(String uri) {
+        fillRootPart();
         if (parts == null || uri == null) {
             return null;
         }
@@ -419,10 +426,12 @@
      * @exception       MessagingException
      */
     public void setRootPart(MimeBodyPart part) throws MessagingException {
+         if (rootPartSet && !isRootPartEnvelope)
+             parts.removeBodyPart(getRootPart());
+        isRootPartEnvelope = false;
+
         String rootCid = '<' + MimeUtils.getUniqueValue() + '>';
         part.setHeader(Constants.HEADER_CONTENT_ID, rootCid);
-        if (rootPartSet)
-            parts.removeBodyPart(getRootPart());
         addBodyPart(part, 0);
         rootPartSet = true;
     }
@@ -437,7 +446,10 @@
      */
     public void setRootPart(String s, String contentType)
         throws MessagingException, IOException {
-        setRootPart(s.getBytes("UTF8"), contentType);
+        isRootPartEnvelope = true;
+        rootPartContentType = contentType;
+        rootPartString = s;
+        rootPartSet = true;
     }
 
     /**
@@ -466,6 +478,59 @@
     }
 
     /**
+     * In case MimePart is requested converts Envelope to MimePart
+     */
+    private void fillRootPart() {
+        if (isRootPartEnvelope) {
+            try {
+                byte[] rootPartBytes = rootPartString.getBytes(
+                        MimeUtils.getEncoding(rootPartContentType, "UTF8"));
+
+                ByteArrayDataSource ds =
+                        new ByteArrayDataSource(rootPartBytes, rootPartContentType);
+                DataHandler dh = new DataHandler(ds);
+                MimeBodyPart bp = new MimeBodyPart();
+                bp.setDataHandler(dh);
+                bp.setHeader(Constants.HEADER_CONTENT_LENGTH,
+                             String.valueOf(ds.getSize()));
+
+                // Avoid letting JavaMail determine a transfer-encoding of
+                // quoted-printable or base64... Force 8-bit encoding.
+                bp.setHeader("Content-Transfer-Encoding", "8bit");
+                setRootPart(bp);
+            }
+            catch (MessagingException e) {} // Should never happen
+            catch (UnsupportedEncodingException e) {} // Should never happen
+        }
+    }
+
+    /**
+     * Return Envelope String set up as setRootPart(String)
+     * or converted from MimeBodyPart
+     *
+     * @return          Envelope String
+     */
+    public String getEnvelope() {
+        if (isRootPartEnvelope) {
+            return rootPartString;
+        }
+        // Envelope was set up as MimeBodyPart - let's get a text from it
+        try {
+            MimeBodyPart rootPart = getRootPart();
+            if (rootPart != null) {
+                String ctype = rootPart.getContentType();
+                ContentType type = MimeUtils.getContentType(ctype);
+                if (type != null && Constants.CTYPE_TEXT_ALL.match(type)) {
+                    ByteArrayDataSource ds = new ByteArrayDataSource(
+                        rootPart.getInputStream(), ctype);
+                    return ds.getText();
+                }
+            }
+        } catch (Exception e) {}
+        return null;
+    }
+
+    /**
      * Find the root part. For multipart, search for a "start" Content-Type
      * header modifier, if not present or invalid, assume the first part is
      * the root.
@@ -474,9 +539,10 @@
      * @exception       MessagingException
      */
     public MimeBodyPart getRootPart() throws MessagingException {
+        fillRootPart();
         MimeBodyPart rootPart = null;
         if (getCount() > 1) {
-            String startCid = new ContentType(
+            String startCid = MimeUtils.getContentType(
                 parts.getContentType()).getParameter("start");
             if (startCid != null)
                 rootPart = getBodyPart(MimeUtils.decode(startCid));
@@ -487,6 +553,22 @@
     }
 
     /**
+     * Returns root part ContentType.
+     *
+     * @return          root BodyPart ContentType
+     * @exception       MessagingException
+     */
+    public String getRootPartContentType() throws MessagingException {
+        if (isRootPartEnvelope)
+            return rootPartContentType;
+        else {
+            MimeBodyPart rootPart = getRootPart();
+            return rootPart == null ? null : rootPart.getContentType();
+        }
+    }
+
+
+    /**
      * Set the MultiPart Mime subtype. This method should be invoked only on
      * a new MimeMultipart object created by the client. The default subtype
      * of such a multipart object is "related".<p>
@@ -514,10 +596,11 @@
      * @return          number of parts
      */
     public int getCount() throws MessagingException {
+        int countRoot = isRootPartEnvelope ? 1 : 0;
         if (parts == null)
-            return 0;
+            return countRoot;
         else
-            return parts.getCount();
+            return parts.getCount() + countRoot;
     }
 
     /**
@@ -529,7 +612,7 @@
      */
     public String getContentType() throws MessagingException {
         if (parts == null)
-            return null;
+            return isRootPartEnvelope ? rootPartContentType : null;
         else
             if (parts.getCount() == 1)
                 return getRootPart().getContentType();
@@ -690,14 +773,16 @@
      * @return The id of the element.
      */
     public int addMultiRef(Object obj, Serializer ser) {
+        if (multiRef == null)
+            multiRef = new ArrayList();
         // While a Hashtable might seem a better choice than a vector here,
         // a Vector is easier to work with during serialization, since
         // multiRefs may be added during the serialization of other multiRefs.
         for (int i = 0; i < multiRef.size(); i++) {
-            if (((MultiRefInfo) multiRef.elementAt(i)).obj == obj)
+            if (((MultiRefInfo) multiRef.get(i)).obj == obj)
                 return i;
         }
-        multiRef.addElement(new MultiRefInfo(obj, ser));
+        multiRef.add(new MultiRefInfo(obj, ser));
         return multiRef.size() - 1;
     }
 
@@ -708,7 +793,7 @@
      * @return The multiRef object for the id.
      */
     public Object getMultiRefObject(int id) {
-        return ((MultiRefInfo) multiRef.elementAt(id)).obj;
+        return multiRef != null ? ((MultiRefInfo) multiRef.get(id)).obj : null;
     }
 
     /**
@@ -718,7 +803,7 @@
      * @return The multiRef serializer for the id.
      */
     public Serializer getMultiRefSerializer(int id) {
-        return ((MultiRefInfo) multiRef.elementAt(id)).ser;
+        return  multiRef != null ? ((MultiRefInfo) multiRef.get(id)).ser : null;
     }
 
     /**
@@ -727,7 +812,7 @@
      * @return The number of multiRefs.
      */
     public int getMultiRefCount() {
-        return multiRef.size();
+        return  multiRef != null ? multiRef.size() : 0;
     }
 
     /**
@@ -737,6 +822,8 @@
      * @param o The deserialized object.
      */
     public void addDeserializedMultiRef(String id, Object o) {
+        if (deserializedMultiRef == null)
+            deserializedMultiRef = new HashMap();
         deserializedMultiRef.put(id, o);
     }
 
@@ -747,7 +834,7 @@
      * @return The multiRef for the id.
      */
     public Object getDeserializedMultiRef(String id) {
-        return deserializedMultiRef.get(id);
+        return deserializedMultiRef == null ? null :deserializedMultiRef.get(id);
     }
 
     /**
@@ -779,7 +866,9 @@
 
         pw.print("}]");
 
-        pw.print(" multiRefs: " + multiRef.size() + " deserializedMultiRefs: " + 
deserializedMultiRef.size());
+        pw.print(" multiRefs: " + (multiRef != null ? multiRef.size() : '0') +
+                 " deserializedMultiRefs: " +
+                (deserializedMultiRef != null ? deserializedMultiRef.size() : '0'));
 
         return sw.toString();
     }
Index: Call.java
===================================================================
RCS file: /home/cvspublic/xml-soap/java/src/org/apache/soap/rpc/Call.java,v
retrieving revision 1.21
diff -u -r1.21 Call.java
--- Call.java   14 Nov 2002 16:22:08 -0000      1.21
+++ Call.java   15 Nov 2002 13:50:21 -0000
@@ -187,7 +187,7 @@
   {
     this.st = st;
   }
-   
+
   public SOAPTransport getSOAPTransport()
   {
     return st;
@@ -195,16 +195,16 @@
 
   /**
    * Set timeout in our MessageContext.
-   * 
+   *
    * @param value the maximum amount of time, in milliseconds
    */
   public void setTimeout (int value) {
     to = value;
   }
-    
+
   /**
    * Get timeout from our MessageContext.
-   * 
+   *
    * @return value the maximum amount of time, in milliseconds
    */
   public int getTimeout () {
@@ -226,7 +226,7 @@
   public void setUseDocumentBuilder(boolean useDocumentBuilder) {
     this.useDocumentBuilder = useDocumentBuilder;
   }
-    
+
   /**
    * Add a MIME BodyPart.
    *
@@ -271,15 +271,13 @@
     BufferedReader in = null;
     String payloadStr = null;
 
-    MimeBodyPart rootPart = respCtx.getRootPart();
-    String ctype = rootPart.getContentType();
+    String ctype = respCtx.getRootPartContentType();
     ContentType type = null;
     type = MimeUtils.getContentType(ctype);
 
     if (type != null && Constants.CTYPE_TEXT_ALL.match(type)) {
       // Get the input stream to read the response envelope from.
-      in = st.receive();
-      payloadStr = IOUtils.getStringFromReader(in);
+      payloadStr = respCtx.getEnvelope();
     }
 
     // Check Content-Type of root part of response to see if it's
@@ -336,7 +334,7 @@
         st = new SOAPHTTPConnection();
 
       // set the timeout
-      if (to != 0 && st instanceof SOAPHTTPConnection) 
+      if (to != 0 && st instanceof SOAPHTTPConnection)
         ((SOAPHTTPConnection)st).setTimeout(to);
 
       // Post the call envelope.
Index: RPCJavaProvider.java
===================================================================
RCS file: 
/home/cvspublic/xml-soap/java/src/org/apache/soap/providers/RPCJavaProvider.java,v
retrieving revision 1.5
diff -u -r1.5 RPCJavaProvider.java
--- RPCJavaProvider.java        17 May 2001 17:45:46 -0000      1.5
+++ RPCJavaProvider.java        15 Nov 2002 13:51:26 -0000
@@ -84,7 +84,7 @@
                         String targetObjectURI,
                         SOAPContext reqContext )
         throws SOAPException {
-      
+
       HttpServlet servlet = (HttpServlet) reqContext.getProperty( 
Constants.BAG_HTTPSERVLET );
       HttpSession session = (HttpSession) reqContext.getProperty( 
Constants.BAG_HTTPSESSION );
 
@@ -126,10 +126,10 @@
                throws SOAPException {
       // invoke the method on the target object
       try {
-        Response resp = RPCRouter.invoke( dd, call, targetObject, 
+        Response resp = RPCRouter.invoke( dd, call, targetObject,
                                           reqContext, resContext );
         Envelope env = resp.buildEnvelope();
-        StringWriter  sw = new StringWriter();
+        StringWriter  sw = new StringWriter(1024);
         env.marshall( sw, call.getSOAPMappingRegistry(), resContext );
         resContext.setRootPart( sw.toString(), Constants.HEADERVAL_CONTENT_TYPE_UTF8);
       }
Index: RPCRouterServlet.java
===================================================================
RCS file: 
/home/cvspublic/xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java,v
retrieving revision 1.42
diff -u -r1.42 RPCRouterServlet.java
--- RPCRouterServlet.java       10 Sep 2002 07:27:25 -0000      1.42
+++ RPCRouterServlet.java       15 Nov 2002 13:52:27 -0000
@@ -96,18 +96,18 @@
     For example, you may add the following
     description to web.xml when using Tomcat:
 
-    <context-param>    
+    <context-param>
         <param-name>EnvelopeEditorFactory</param-name>
         <param-value>MyEnvelopeEditorFactory</param-value>
-    </context-param>    
-    <context-param>    
+    </context-param>
+    <context-param>
         <param-name>XMLParser</param-name>
         <param-value>SampleXMLDocumentBuilderFactory</param-value>
-    </context-param>    
-    <context-param>    
+    </context-param>
+    <context-param>
         <param-name>ConfigFile</param-name>
         <param-value>myconfig.xml</param-value>
-    </context-param>    
+    </context-param>
     <servlet>
       <servlet-name>RPCRouterServlet</servlet-name>
       <servlet-class>org.apache.soap.server.http.RPCRouterServlet</servlet-class>
@@ -134,7 +134,7 @@
   public void init() throws ServletException {
     ClassLoader servletClassLoader =
       Thread.currentThread().getContextClassLoader();
-    
+
     try
     {
       /*Make sure that we got a useful classloader; if we can not
@@ -146,7 +146,7 @@
     {
       servletClassLoader = getClass().getClassLoader();
     }
-    
+
     if (servletClassLoader == null)
     {
       /*This is needed because some containers use hashtable to store
@@ -178,10 +178,10 @@
         try {
           Properties props = new Properties();
          /*First we put in the servletContext parameters, and then
-           overwrite them with the servletConfig parameters if 
+           overwrite them with the servletConfig parameters if
            they are present.*/
           Enumeration enum = servletContext.getInitParameterNames();
-         
+
           while (enum.hasMoreElements()) {
             String name = (String)enum.nextElement();
 
@@ -299,16 +299,17 @@
           reqCtx.setProperty( Constants.BAG_HTTPSERVLET, this );
           reqCtx.setProperty( Constants.BAG_HTTPSERVLETREQUEST, req );
           reqCtx.setProperty( Constants.BAG_HTTPSERVLETRESPONSE, res );
-  
+
           // Carry the request context from the read to the creation of
           // the Call object.
-  
+
           // Generate Envelope after the incoming message is translated by
           // EnvelopeEditor
           // Note: XMLParser that is specified by init-param isused in
           // this process.
-          DocumentBuilder xdb = XMLParserUtils.getXMLDocBuilder();
+          DocumentBuilder xdb = XMLParserUtils.getXMLDocBuilderFromPool();
 
+          try {
           callEnv =
             ServerHTTPUtils.readEnvelopeFromRequest(xdb,
                                                     req.getContentType(),
@@ -318,6 +319,10 @@
                                                     res,
                                                     reqCtx,
                                                     ServerHTTPUtils.getHeaders(req));
+          }
+          finally {
+                XMLParserUtils.returnDocumentBuilderToPool(xdb);
+          }
           if (callEnv == null)
             return;
           call = RPCRouter.extractCallFromEnvelope(serviceManager, callEnv,
@@ -332,7 +337,7 @@
             : Constants.FAULT_CODE_CLIENT;
           throw new SOAPException (faultCode, msg, e);
         }
-  
+
         // get the deployment descriptor for this service (will except if
         // not known)
         dd = serviceManager.query (targetID);
@@ -369,8 +374,8 @@
           // Handle scripts
           provider = new org.apache.soap.providers.RPCJavaProvider();
         }
-        
-        provider.locate( dd, callEnv, call, call.getMethodName(), fullTargetID, 
+
+        provider.locate( dd, callEnv, call, call.getMethodName(), fullTargetID,
                          reqCtx );
         ServerUtils.setResponseGzip(dd, reqCtx, resCtx);
         provider.invoke( reqCtx, resCtx );
@@ -395,21 +400,21 @@
         // the status code for faults should always be the internal
         // server error status code (per soap spec)
         status = res.SC_INTERNAL_SERVER_ERROR;
-  
+
         String respEncStyle = null;
         if(call != null)
             respEncStyle = call.getEncodingStyleURI();
         if(respEncStyle == null)
           respEncStyle = Constants.NS_URI_SOAP_ENC;
-  
+
         resCtx = new SOAPContext(); // get rid of old one
-        resp = new Response (null, null, fault, null, null, respEncStyle, 
+        resp = new Response (null, null, fault, null, null, respEncStyle,
                              resCtx);
-        SOAPMappingRegistry smr = 
+        SOAPMappingRegistry smr =
          (call != null) ? call.getSOAPMappingRegistry ()
                         : ServerHTTPUtils.getSMRFromContext (context);
         Envelope env = resp.buildEnvelope();
-        StringWriter sw = new StringWriter();
+        StringWriter sw = new StringWriter(1024);
         env.marshall(sw, smr, resp.getSOAPContext());
         resp.getSOAPContext().setRootPart( sw.toString(),
                                            Constants.HEADERVAL_CONTENT_TYPE_UTF8);
Index: TransportMessage.java
===================================================================
RCS file: 
/home/cvspublic/xml-soap/java/src/org/apache/soap/transport/TransportMessage.java,v
retrieving revision 1.19
diff -u -r1.19 TransportMessage.java
--- TransportMessage.java       14 Nov 2002 05:00:42 -0000      1.19
+++ TransportMessage.java       15 Nov 2002 14:00:47 -0000
@@ -169,7 +169,7 @@
         if (contentLength != 0) {
             int offset = 0;
             int bytesRead = 0;
-    
+
             // We're done reading when we get all the content OR when the stream
             // returns a -1.
             while ((contentLength < 0 || offset < contentLength) && (bytesRead >= 0)) 
{
@@ -258,15 +258,12 @@
         // Parse and validate content type.
         ContentType cType = null;
         if (contentType != null) {
-            try {
-                // Hack since WebSphere puts ;; instead of just ;
-                int pos = contentType.indexOf( ";;" );
-                if ( pos != -1 )
-                  contentType = contentType.substring(0,pos) +
-                                contentType.substring(pos+1) ;
-                cType = new ContentType(contentType);
-            } catch(ParseException pe) {
-            }
+            // Hack since WebSphere puts ;; instead of just ;
+            int pos = contentType.indexOf( ";;" );
+            if ( pos != -1 )
+              contentType = contentType.substring(0,pos) +
+                            contentType.substring(pos+1) ;
+            cType = MimeUtils.getContentType(contentType);
         }
         if (cType == null)
             throw new SOAPException(Constants.FAULT_CODE_PROTOCOL,
@@ -321,20 +318,29 @@
 
             // Find root part.
             rootPart = ctx.getRootPart();
-            rootContentType = new ContentType(rootPart.getContentType());
+            rootContentType = MimeUtils.getContentType(rootPart.getContentType());
             ByteArrayDataSource bads = new ByteArrayDataSource(
                 rootPart.getInputStream(), null);
             rootBytes = bads.toByteArray();
         } else {
             rootBytes = bytes;
             rootContentType = cType;
-            // Set the single part as the root part of SOAPContext.
-            ByteArrayDataSource ds = new ByteArrayDataSource(bytes,
-                                                             contentType);
-            DataHandler dh = new DataHandler(ds);
-            rootPart = new MimeBodyPart();
-            rootPart.setDataHandler(dh);
-            ctx.addBodyPart(rootPart);
+
+            // If the root part is text, extract it as a String.
+            // Note that we could use JAF's help to do this (see save())
+            // but implementing it ourselves is safer and faster.
+            if (Constants.CTYPE_TEXT_ALL.match(rootContentType)) {
+                String charset = rootContentType.getParameter("charset");
+                // Hmm, risky, the default charset is transport-specific...
+                if (charset == null || charset.equals(""))
+                    charset = Constants.HEADERVAL_DEFAULT_CHARSET;
+                envelope = new String(rootBytes, MimeUtility.javaCharset(charset));
+                // Set the envelope as a String.
+                ctx.setRootPart(envelope, contentType);
+            } else
+                // Set the single part as the root part of SOAPContext.
+                ctx.setRootPart(bytes, contentType);
+            return envelope;
         }
 
         // If the root part is text, extract it as a String.
@@ -391,16 +397,7 @@
          * Otherwise, assume that the SOAPContext already has a root part,
          * and try to use it as the envelope.
          */
-        String rootContentType = null;
-        if (ctx.isRootPartSet()) {
-            MimeBodyPart rootPart = ctx.getRootPart();
-            if (rootPart != null)
-                // Note: don't call MimeBodyPart.getContent() because it will
-                // default to "text/plain" if the Content-Type header isn't
-                // set.
-                rootContentType = rootPart.getHeader(
-                    Constants.HEADER_CONTENT_TYPE, null);
-        }
+        String rootContentType = ctx.getRootPartContentType();
         if (rootContentType == null)
             rootContentType = Constants.HEADERVAL_CONTENT_TYPE_UTF8;
         if (getEnvelope() != null && !rootPartIsEnvelope) {
@@ -420,7 +417,7 @@
                 new ByteArrayOutputStream(65536);
             ctx.writeTo(payload);
             bytes = payload.toByteArray();
-    
+
             // Now strip off the headers. (Grmbl, get rid of JavaMail
             // for MIME support). Just intercept the Content-Type
             // header. We don't want any of the MIME headers, and we know the
@@ -509,21 +506,8 @@
      */
     public String getEnvelope() {
         if (envelope == null) {
-            // Assign the root part, if any, to the envelope.
-            try {
-                MimeBodyPart rootPart = ctx.getRootPart();
-                if (rootPart != null) {
-                    String ctype = rootPart.getContentType();
-                    ContentType type = new ContentType(ctype);
-                    if (type != null && Constants.CTYPE_TEXT_ALL.match(type)) {
-                        ByteArrayDataSource ds = new ByteArrayDataSource(
-                            rootPart.getInputStream(), ctype);
-                        envelope = ds.getText();
-                    }
-                    rootPartIsEnvelope = true;
-                }
-            } catch (Exception e) {
-            }
+            // get an enveope from SOAPContext
+            envelope = ctx.getEnvelope();
         }
         return envelope;
     }

<<attachment: untitled.GIF>>

--
To unsubscribe, e-mail:   <mailto:soap-dev-unsubscribe@;xml.apache.org>
For additional commands, e-mail: <mailto:soap-dev-help@;xml.apache.org>

Reply via email to