snichol     2002/11/20 13:34:43

  Modified:    java/src/org/apache/soap/providers RPCJavaProvider.java
               java/src/org/apache/soap/rpc Call.java SOAPContext.java
               java/src/org/apache/soap/server ServerUtils.java
               java/src/org/apache/soap/server/http RPCRouterServlet.java
               java/src/org/apache/soap/transport TransportMessage.java
  Log:
  Submitted by: Pavel Ausianik <[EMAIL PROTECTED]>
  
  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...
  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!
  
  I think I managed make it compatible to existing code and yet still
  much faster (8-10 sec of 60 I had in the morning ). The Mime
  part will be created as soon as it requested, otherwise plain Envelope used
  Also I set up initial buffer in couple of classes...
  
  Revision  Changes    Path
  1.6       +1 -1      xml-soap/java/src/org/apache/soap/providers/RPCJavaProvider.java
  
  Index: RPCJavaProvider.java
  ===================================================================
  RCS file: 
/home/cvs/xml-soap/java/src/org/apache/soap/providers/RPCJavaProvider.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- RPCJavaProvider.java      17 May 2001 17:45:46 -0000      1.5
  +++ RPCJavaProvider.java      20 Nov 2002 21:34:42 -0000      1.6
  @@ -129,7 +129,7 @@
           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);
         }
  
  
  
  1.23      +2 -4      xml-soap/java/src/org/apache/soap/rpc/Call.java
  
  Index: Call.java
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/rpc/Call.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- Call.java 19 Nov 2002 02:47:38 -0000      1.22
  +++ Call.java 20 Nov 2002 21:34:42 -0000      1.23
  @@ -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
  
  
  
  1.16      +109 -17   xml-soap/java/src/org/apache/soap/rpc/SOAPContext.java
  
  Index: SOAPContext.java
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/rpc/SOAPContext.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- SOAPContext.java  19 Nov 2002 02:47:38 -0000      1.15
  +++ SOAPContext.java  20 Nov 2002 21:34:42 -0000      1.16
  @@ -78,17 +78,22 @@
    *
    * @author Wouter Cloetens ([EMAIL PROTECTED])
    * @author Scott Nichol ([EMAIL PROTECTED])
  + * @author Pavel Ausianik ([EMAIL PROTECTED])
    */
   public class SOAPContext {
       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 = "";
       protected boolean       oneWay = false;
   
       // Constants for checking type for base64 encoding
  @@ -160,6 +165,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
  @@ -189,6 +195,7 @@
        * @return          the Part, or null if no such part exists.
        */
       public MimeBodyPart getBodyPart(String CID) {
  +        fillRootPart();
           if (parts == null) {
               return null;
           }
  @@ -222,6 +229,7 @@
        * @return          the Part or null if not found
        */
       public MimeBodyPart findBodyPart(String uri) {
  +        fillRootPart();
           if (parts == null || uri == null) {
               return null;
           }
  @@ -420,10 +428,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;
       }
  @@ -438,7 +448,10 @@
        */
       public void setRootPart(String s, String contentType)
           throws MessagingException, IOException {
  -        setRootPart(s.getBytes("UTF8"), contentType);
  +        isRootPartEnvelope = true;
  +        rootPartContentType = contentType;
  +        rootPartString = s;
  +        rootPartSet = true;
       }
   
       /**
  @@ -458,7 +471,6 @@
           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");
  @@ -467,6 +479,60 @@
       }
   
       /**
  +     * 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");
  +                bp.setHeader(Constants.HEADERVAL_CONTENT_TYPE, rootPartContentType);
  +                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.
  @@ -475,9 +541,10 @@
        * @exception       MessagingException
        */
       public MimeBodyPart getRootPart() throws MessagingException {
  +        fillRootPart();
           MimeBodyPart rootPart = null;
           if (getCount() > 1) {
  -            String startCid = MimeUtils.getContentType(
  +            String startCid = new ContentType(
                   parts.getContentType()).getParameter("start");
               if (startCid != null)
                   rootPart = getBodyPart(MimeUtils.decode(startCid));
  @@ -488,6 +555,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>
  @@ -515,10 +598,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;
       }
   
       /**
  @@ -530,7 +614,7 @@
        */
       public String getContentType() throws MessagingException {
           if (parts == null)
  -            return null;
  +            return isRootPartEnvelope ? rootPartContentType : null;
           else
               if (parts.getCount() == 1)
                   return getRootPart().getContentType();
  @@ -554,6 +638,8 @@
               getRootPart().writeTo(os);
           }
           else {
  +            // fill Root part first
  +            fillRootPart();
               Session session = Session.getDefaultInstance(new Properties(), null);
               MimeMessage msg = new MimeMessage(session);
               msg.setContent(parts);
  @@ -691,14 +777,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;
       }
   
  @@ -709,7 +797,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;
       }
   
       /**
  @@ -719,7 +807,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;
       }
   
       /**
  @@ -728,7 +816,7 @@
        * @return The number of multiRefs.
        */
       public int getMultiRefCount() {
  -        return multiRef.size();
  +        return  multiRef != null ? multiRef.size() : 0;
       }
   
       /**
  @@ -738,6 +826,8 @@
        * @param o The deserialized object.
        */
       public void addDeserializedMultiRef(String id, Object o) {
  +        if (deserializedMultiRef == null)
  +            deserializedMultiRef = new HashMap();
           deserializedMultiRef.put(id, o);
       }
   
  @@ -748,7 +838,7 @@
        * @return The multiRef for the id.
        */
       public Object getDeserializedMultiRef(String id) {
  -        return deserializedMultiRef.get(id);
  +        return deserializedMultiRef == null ? null :deserializedMultiRef.get(id);
       }
   
       /**
  @@ -794,7 +884,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();
       }
  
  
  
  1.11      +5 -3      xml-soap/java/src/org/apache/soap/server/ServerUtils.java
  
  Index: ServerUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/server/ServerUtils.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- ServerUtils.java  5 Sep 2002 16:50:52 -0000       1.10
  +++ ServerUtils.java  20 Nov 2002 21:34:42 -0000      1.11
  @@ -147,11 +147,13 @@
           reqMsg.read();
           // Check Content-Type of root part of request to see if it's
           // consistent with a SOAP envelope (text/xml).
  -        MimeBodyPart rootPart = ctx.getRootPart();
  -        if (!rootPart.isMimeType(Constants.HEADERVAL_CONTENT_TYPE))
  +        String ctype = ctx.getRootPartContentType();
  +        ContentType type = null;
  +        type = MimeUtils.getContentType(ctype);
  +        if (type == null || !Constants.CTYPE_TEXT_XML.match(type))
               throw new SOAPException(Constants.FAULT_CODE_PROTOCOL,
                   "Unsupported content type \"" +
  -                rootPart.getContentType() + "\", must be: \"" +
  +                ctype + "\", must be: \"" +
                   Constants.HEADERVAL_CONTENT_TYPE + "\".");
           // Apply Transport-Hook-Extension
           reqMsg.editIncoming(editor);
  
  
  
  1.43      +1 -1      
xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java
  
  Index: RPCRouterServlet.java
  ===================================================================
  RCS file: 
/home/cvs/xml-soap/java/src/org/apache/soap/server/http/RPCRouterServlet.java,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- RPCRouterServlet.java     10 Sep 2002 07:27:25 -0000      1.42
  +++ RPCRouterServlet.java     20 Nov 2002 21:34:42 -0000      1.43
  @@ -409,7 +409,7 @@
          (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);
  
  
  
  1.23      +24 -34    
xml-soap/java/src/org/apache/soap/transport/TransportMessage.java
  
  Index: TransportMessage.java
  ===================================================================
  RCS file: 
/home/cvs/xml-soap/java/src/org/apache/soap/transport/TransportMessage.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- TransportMessage.java     20 Nov 2002 07:29:32 -0000      1.22
  +++ TransportMessage.java     20 Nov 2002 21:34:42 -0000      1.23
  @@ -330,13 +330,22 @@
           } 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.
  @@ -394,20 +403,14 @@
            * 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);
  -        }
  -        if (rootContentType == null)
  -            rootContentType = Constants.HEADERVAL_CONTENT_TYPE_UTF8;
           if (getEnvelope() != null && !rootPartIsEnvelope) {
  -            ctx.setRootPart(envelope, rootContentType);
  +            rootContentType = Constants.HEADERVAL_CONTENT_TYPE_UTF8;
  +            ctx.setRootPart(envelope, Constants.HEADERVAL_CONTENT_TYPE_UTF8);
               rootPartIsEnvelope = true;
  +        } else {
  +            rootContentType = ctx.getRootPartContentType();
  +            if (rootContentType == null)
  +                rootContentType = Constants.HEADERVAL_CONTENT_TYPE_UTF8;
           }
   
           // If we only have one part, it is the envelope, so handle
  @@ -511,21 +514,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 = MimeUtils.getContentType(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;
       }
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to