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>