You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-dev@ws.apache.org by sn...@apache.org on 2002/07/26 06:48:29 UTC

cvs commit: xml-soap/java/src/org/apache/soap/util/xml DOMUtils.java

snichol     2002/07/25 21:48:29

  Modified:    java/docs changes.html
               java/src/org/apache/soap/rpc Call.java
               java/src/org/apache/soap/util/xml DOMUtils.java
  Log:
  Based on a submission by Raj Yellapragada (rajaism@yahoo.com).
  
  Add the ability to select between parsing XML using a
  DocumentBuilder versus a Transform from a SAXSource to a
  DOMResult on a per-Call basis.  This is on the client only.
  
  While I have used the basic method provided by Raj, I made
  two changes:
  
  1. Rather than always using the Transform, I have made it selectable.
     I am hoping this will encourage experimentation while providing a
     known stable base for the more risk-averse.
  
  2. Use reflection to access the JAXP classes not in javax.xml.parsers.
     This means the code will not break in environments where folks have,
     e.g., Xerces in their CLASSPATH, but not Xalan.
  
  If this technique proves to improve performance, it would make sense
  to have it available on the server side as well, possibly moving code
  into XMLParserUtils.
  
  Revision  Changes    Path
  1.33      +19 -9     xml-soap/java/docs/changes.html
  
  Index: changes.html
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/docs/changes.html,v
  retrieving revision 1.32
  retrieving revision 1.33
  diff -u -r1.32 -r1.33
  --- changes.html	11 Jul 2002 15:45:54 -0000	1.32
  +++ changes.html	26 Jul 2002 04:48:29 -0000	1.33
  @@ -16,15 +16,8 @@
   most recent version is at the top.</p>
   
   <ul>
  -  <li><A name="v2.3.1"><STRONG>Version 2.3.1</STRONG></A>
  +  <li><A name="post2.3.1"><STRONG>Post 2.3.1</STRONG></A>
       <ul>
  -      <li>Added logic to use xsi:nil, instead of xsi:null,
  -      when using the 2001 Schema spec.</li>
  -      <li>Fixed behavior when the 1999 or 2000 schema URI
  -      is specified so that the serialization logic uses
  -      the older version of both the xsi and the xsd namespaces;
  -      it was previously just using the older xsd namespace.</li>
  -      <!-- 2.3.1 released with the above -->
         <li>Enhanced cookie support (used for session maintenance)
         by supporting multiple Set-Cookie[2] headers from the server
         and supporting RFC 2109 and RFC 2965 more completely.</li>
  @@ -34,7 +27,9 @@
         service class.  (From general wish list in TODO.)</li>
         <li>Added the ability to get copies of HTTP request and
         response programmatically.  This is useful when debugging
  -      SSL, as wire dumps are of no use then.</li>
  +      SSL, as wire dumps are of no use then.  (Although the JSSE
  +      reference implementation provides full packet contents as
  +      debug.)</li>
         <li>In the absence of an xsi:type attribute, check the element
         namespace URI for SOAP-ENC to imply a type.  For now, just
         support SOAP-ENC:Array.  This allows interop with .NET arrays
  @@ -49,6 +44,21 @@
         <li>Remove deadlock for a service that in the constructor invokes
         another service when both services are at application scope.  The
         deadlock still occurs if both services are at session scope.</li>
  +      <li>Add the ability to select between parsing XML using a
  +      DocumentBuilder versus a Transform from a SAXSource to a
  +      DOMResult on a per-Call basis.  This is on the client only.
  +      If testing establishes that the Transform offers a significant
  +      speed improvement, the server code may be changed as well.</li>
  +    </ul>
  +  </li>
  +  <li><A name="v2.3.1"><STRONG>Version 2.3.1</STRONG></A>
  +    <ul>
  +      <li>Added logic to use xsi:nil, instead of xsi:null,
  +      when using the 2001 Schema spec.</li>
  +      <li>Fixed behavior when the 1999 or 2000 schema URI
  +      is specified so that the serialization logic uses
  +      the older version of both the xsi and the xsd namespaces;
  +      it was previously just using the older xsd namespace.</li>
       </ul>
     </li>
   </ul>
  
  
  
  1.16      +74 -7     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.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- Call.java	22 Jul 2002 17:59:06 -0000	1.15
  +++ Call.java	26 Jul 2002 04:48:29 -0000	1.16
  @@ -81,6 +81,8 @@
    *
    * @author Matthew J. Duftler (duftler@us.ibm.com)
    * @author Sanjiva Weerawarana (sanjiva@watson.ibm.com)
  + * @author Raj Yellapragada (rajaism@yahoo.com)
  + * @author Scott Nichol (snichol@computer.org)
    */
   public class Call extends RPCMessage
   {
  @@ -88,6 +90,7 @@
     private SOAPMappingRegistry smr = null;
     private SOAPTransport       st  = null;;
     private int                 to  = 0;
  +  private boolean             useDocumentBuilder = true;
   
     public Call()
     {
  @@ -150,6 +153,22 @@
     public int getTimeout () {
       return to;
     }
  +
  +  /**
  +   * Gets whether to use a DocumentBuilder (as opposed to trying to
  +   * do a SAX transform).
  +   */
  +  public boolean getUseDocumentBuilder() {
  +    return useDocumentBuilder;
  +  }
  +
  +  /**
  +   * Sets whether to use a DocumentBuilder (as opposed to trying to
  +   * do a SAX transform).
  +   */
  +  public void setUseDocumentBuilder(boolean useDocumentBuilder) {
  +    this.useDocumentBuilder = useDocumentBuilder;
  +  }
       
     /**
      * Add a MIME BodyPart.
  @@ -230,11 +249,6 @@
       {
         smr = new SOAPMappingRegistry();
       }
  -    // if the parser hasn't been created yet, do it now
  -    if (xdb == null)
  -    {
  -      xdb = XMLParserUtils.getXMLDocBuilder();
  -    }
   
       try
       {
  @@ -260,8 +274,7 @@
         String payloadStr = getEnvelopeString(st);
   
         // Parse the incoming response stream.
  -      Document respDoc =
  -        xdb.parse(new InputSource(new StringReader(payloadStr)));
  +      Document respDoc = parsePayload(payloadStr);
         Element payload = null;
   
         if (respDoc != null)
  @@ -309,5 +322,59 @@
         throw new SOAPException(Constants.FAULT_CODE_PROTOCOL,
                                 e.getMessage(), e);
       }
  +  }
  +
  +  /**
  +   * Parses the payload into a DOM.  Depending on what JAXP facilities are
  +   * available at run-time, this will either use the DOM parser or the SAX
  +   * parser plus a transformation.
  +   */
  +  private Document parsePayload(String payload) throws IOException, SAXException {
  +  	InputSource input = new InputSource(new StringReader(payload));
  +  	if (!useDocumentBuilder) {
  +      try {
  +        // If classes required for transformation are all present, use that method
  +        Class domResultClass = Class.forName("javax.xml.transform.dom.DOMResult");
  +        Class transformerFactoryClass = Class.forName("javax.xml.transform.TransformerFactory");
  +        Class transformerClass = Class.forName("javax.xml.transform.Transformer");
  +        Class saxSourceClass = Class.forName("javax.xml.transform.sax.SAXSource");
  +        Class sourceClass = Class.forName("javax.xml.transform.Source");
  +        Class resultClass = Class.forName("javax.xml.transform.Result");
  +
  +	    Object output = domResultClass.newInstance();
  +        Object source = saxSourceClass.newInstance();
  +
  +        // Create factory and use to create transformer
  +        Method method = transformerFactoryClass.getDeclaredMethod("newInstance", new Class[]{});
  +	    Object xformFactory = method.invoke(null, new Object[]{});
  +        method = transformerFactoryClass.getDeclaredMethod("newTransformer", new Class[]{});
  +	    Object idTransform = method.invoke(xformFactory, new Object[]{});
  +
  +        // Set input source for SAX source
  +        method = saxSourceClass.getDeclaredMethod("setInputSource", new Class[]{InputSource.class});
  +        method.invoke(source, new Object[]{input});
  +
  +        // Transform from SAX source to DOM result
  +        method = transformerClass.getDeclaredMethod("transform", new Class[]{sourceClass, resultClass});
  +        method.invoke(idTransform, new Object[]{source, output});
  +
  +        // Grab document node from DOM result
  +        method = domResultClass.getDeclaredMethod("getNode", new Class[]{});
  +
  +        // If all has worked, we return here; for exceptions,
  +        // we fall through to the DOM parser.
  +	    return (Document) method.invoke(output, new Object[]{});
  +      } catch (ClassNotFoundException e) {
  +      } catch (NoSuchMethodException e) {
  +      } catch (InvocationTargetException e) {
  +      } catch (InstantiationException e) {
  +      } catch (IllegalAccessException e) {
  +      }
  +    }
  +
  +    // if the DOM parser hasn't been created yet, do it now
  +    if (xdb == null)
  +      xdb = XMLParserUtils.getXMLDocBuilder();
  +    return xdb.parse(input);
     }
   }
  
  
  
  1.6       +11 -3     xml-soap/java/src/org/apache/soap/util/xml/DOMUtils.java
  
  Index: DOMUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/util/xml/DOMUtils.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DOMUtils.java	13 Nov 2001 18:25:09 -0000	1.5
  +++ DOMUtils.java	26 Jul 2002 04:48:29 -0000	1.6
  @@ -250,9 +250,17 @@
       while (tempNode != null && tempNode.getNodeType () == Node.ELEMENT_NODE)
       {
         Element tempEl = (Element) tempNode;
  -      String namespaceURI = (prefix == null)
  -                            ? getAttribute (tempEl, "xmlns")
  -                            : getAttributeNS (tempEl, NS_URI_XMLNS, prefix);
  +      String namespaceURI;
  +      
  +      if (prefix == null) {
  +        namespaceURI = getAttribute(tempEl, "xmlns");
  +      } else {
  +        namespaceURI = getAttributeNS(tempEl, NS_URI_XMLNS, prefix);
  +        if (namespaceURI == null) {
  +          // SAX parser (maybe others?) need this
  +          namespaceURI = getAttribute(tempEl, "xmlns:" + prefix);
  +        }
  +      }
   
         if (namespaceURI != null)
         {