You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axis-cvs@ws.apache.org by sc...@apache.org on 2009/11/20 20:57:29 UTC

svn commit: r882698 - in /webservices/axis2/trunk/java/modules/jaxws: src/org/apache/axis2/jaxws/context/listener/ test/org/apache/axis2/jaxws/context/listener/

Author: scheu
Date: Fri Nov 20 19:57:29 2009
New Revision: 882698

URL: http://svn.apache.org/viewvc?rev=882698&view=rev
Log:
AXIS2-4550
Contributor:Lori VanGulick and Bill Nagy
Committer: Rich Scheuerle

Fix to ParserInputStream to correct namespaces.  Also a validation test.

Modified:
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ContextListenerUtils.java
    webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilder.java
    webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilderTests.java

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ContextListenerUtils.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ContextListenerUtils.java?rev=882698&r1=882697&r2=882698&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ContextListenerUtils.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ContextListenerUtils.java Fri Nov 20 19:57:29 2009
@@ -50,9 +50,9 @@
         ProviderOMContextListener.create(mc.getAxisMessageContext().getServiceContext());
     }
     
-    public static InputStream createPayloadElement(InputStream payloadContent, OMNamespace ns, String localPart, OMContainer parent){
+    public static InputStream createPayloadElement(InputStream payloadContent, OMNamespace ns, String localPart, OMContainer parent, HashMap<String, String> nsElementDecls, HashMap<String, String> attrElementDecls){
         CompositeInputStream inputStream = new CompositeInputStream();
-        InputStream startTag = getStartTag(ns, localPart, parent);
+        InputStream startTag = getStartTag(ns, localPart, parent, nsElementDecls, attrElementDecls);
         InputStream endTag = getEndTag(ns, localPart);
         //Add Element startTag
         ((CompositeInputStream)inputStream).append(startTag);
@@ -96,7 +96,7 @@
     /*
      * get startElement using namespace and local part. Add all namespace prefixes from parent elements.
      */
-    private static InputStream getStartTag(OMNamespace ns, String localPart, OMContainer parent){
+    private static InputStream getStartTag(OMNamespace ns, String localPart, OMContainer parent, HashMap<String, String> nsElementDecls, HashMap<String, String> attrElementDecls){
         if(log.isDebugEnabled()){
             log.debug("Start ParsedEntityDataSource.Data.getStartTag()");
         }            
@@ -104,17 +104,28 @@
         StringBuffer startElement = new StringBuffer();
         String prefix = (ns!=null)?ns.getPrefix():null;
         String uri = (ns!=null)?ns.getNamespaceURI():null;
+        
+        HashMap<String, String> nsDecls = new HashMap<String, String>();
+        //Get all of the namespaces associated with Body, envelope, etc
+        getParentnsdeclarations(nsDecls, parent);
+        
+        nsDecls.putAll(nsElementDecls);
+        
         if(prefix!=null && prefix.length()>0){
-            startElement.append("<"+prefix+":"+localPart+ " xmlns:"+prefix+"=\""+uri+"\"");
-            addParentNs(startElement, parent);
-
+            startElement.append("<"+prefix+":"+localPart+ " ");
+            if (!nsDecls.containsKey(prefix) || !nsDecls.get(prefix).equals(uri)){
+              nsDecls.put(prefix, uri);
+            }
         }else{
-            startElement.append("<"+localPart+" xmlns=\""+uri+"\"");
-            addParentNs(startElement, parent);
+            startElement.append("<"+localPart + " ");
         }
+        addParentNs(startElement, parent, nsDecls);
+        addAttrs(startElement, attrElementDecls);
+        
         if(log.isDebugEnabled()){
-            log.debug("StartElement ="+startElement);
+          log.debug("StartElement ="+startElement);
         }
+
         if(log.isDebugEnabled()){
             log.debug("End ParsedEntityDataSource.Data.getStartTag()");
         }
@@ -134,8 +145,9 @@
                 OMNamespace omn = (OMNamespace) ite.next();
                 String prefix = omn.getPrefix();
                 String nsUri = omn.getNamespaceURI();
-                if (!nsDecls.containsKey(prefix))
+                if (!nsDecls.containsKey(prefix)) {
                     nsDecls.put(prefix, nsUri);
+                }
             }
             parent = omElement.getParent();
         }
@@ -143,10 +155,7 @@
     /*
      * add all parent namespace declarations to the element
      */
-    private static void addParentNs(StringBuffer startElement, OMContainer parent){
-        HashMap<String, String> nsDecls = new HashMap<String, String>();
-        //Get all the namespaces associated with Body, envelope etc.
-        getParentnsdeclarations(nsDecls, parent);
+    private static void addParentNs(StringBuffer startElement, OMContainer parent, HashMap<String, String> nsDecls){
         Iterator<Map.Entry<String, String>> iter = nsDecls.entrySet().iterator();
         while (iter.hasNext()) {
             Map.Entry<String, String> entry = iter.next();
@@ -162,7 +171,21 @@
             startElement.append(uri);
             startElement.append("\"");
         }
-        startElement.append(">");
     }
 
+    private static void addAttrs(StringBuffer startElement, HashMap<String, String> attrDecls)
+    {
+      Iterator<Map.Entry<String, String>> iter = attrDecls.entrySet().iterator();
+      while (iter.hasNext()) {
+        Map.Entry<String, String> entry = iter.next();
+        String compoundName = entry.getKey();
+        String value = entry.getValue();
+        startElement.append(" ");
+        startElement.append(compoundName);
+        startElement.append("=\"");
+        startElement.append(value);
+        startElement.append("\"");
+      }
+      startElement.append(">");
+    }
 }

Modified: webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilder.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilder.java?rev=882698&r1=882697&r2=882698&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilder.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/src/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilder.java Fri Nov 20 19:57:29 2009
@@ -19,6 +19,8 @@
 package org.apache.axis2.jaxws.context.listener;
 
 import java.io.InputStream;
+import java.util.HashMap;
+import java.util.LinkedList;
 
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamReader;
@@ -87,7 +89,7 @@
             //Do not user custom builder if Parser does not have ability to read sub content.
             if(!entityReader.isParsedEntityStreamAvailable()){
                 if (log.isDebugEnabled()) {
-                    log.debug("Stream not available");
+                    log.debug("ParsedEntityStream is not available, defaulting to normal build");
                 }
                 return null;
             }
@@ -96,10 +98,13 @@
             if(parsedStream == null){
                 //cant read content from EntityReader, returning null.
                 if (log.isDebugEnabled()) {
-                    log.debug("No content available");
+                    log.debug("Unable to read content from the entity reader, defaulting to normal build");
                 }
                 return null;
             }
+            HashMap<String, String> nsElementDecls = getElementNamespaceDeclarations(reader);
+            HashMap<String, String> attrElementDecls = getElementAttributeDeclarations(reader);
+            
             //read the payload. Lets move the parser forward.
             if(reader.hasNext()){
                 reader.next();
@@ -113,7 +118,8 @@
                 }
             }
             OMNamespace ns = factory.createOMNamespace(namespace, reader.getPrefix());
-            InputStream payload = ContextListenerUtils.createPayloadElement(parsedStream, ns, localPart, parent);
+            InputStream payload = ContextListenerUtils.createPayloadElement(parsedStream, ns, localPart, parent, 
+                        nsElementDecls, attrElementDecls);
 
             ParserInputStreamDataSource ds = new ParserInputStreamDataSource(payload, encoding);
             OMSourcedElement om = null;
@@ -182,6 +188,121 @@
         }
     }
 
+    private HashMap<String, String> getElementNamespaceDeclarations(XMLStreamReader reader)
+    {
+      HashMap<String, String> nsElementDecls = new HashMap<String, String>();
+      int count = reader.getNamespaceCount();
+      for (int i = 0; i < count; i++){
+        String prefix = reader.getNamespacePrefix(i);
+        String namespace = reader.getNamespaceURI(i);
+        if (namespace != null && namespace.length() > 0){
+          nsElementDecls.put(prefix == null ? "":prefix, namespace);
+        }
+      }
+      return nsElementDecls;
+    }
+    
+    private HashMap<String, String> getElementAttributeDeclarations(XMLStreamReader reader)
+    {
+      HashMap<String, String> attrElementDecls = new HashMap<String, String>();
+      int count = reader.getAttributeCount();
+
+      for (int i = 0; i < count; i++) {
+        String prefix = reader.getAttributePrefix(i);
+        String name = reader.getAttributeLocalName(i);
+        String value = convertEntityReferences(reader.getAttributeValue(i));
+        String compoundName;
+        if (prefix != null && prefix.length() > 0){
+          compoundName = prefix+":"+name;
+        }
+        else {
+          compoundName = name;
+        }
+        attrElementDecls.put(compoundName, value);
+      }
+      return attrElementDecls;
+    }
+    
+    protected String convertEntityReferences(String value)
+    {
+      if ((value == null) || (value.length() == 0))
+        return value;
+      
+      int valueLen = value.length();
+      
+      int[] positionsToChange = null;
+      int numChanged = 0;
+      
+      for (int i = 0; i < valueLen; i++) {
+        switch (value.charAt(i)) {
+          case '<':
+          case '>':
+          case '&':
+          case '\"':
+          case '\'':
+            if (positionsToChange == null)
+            {
+              positionsToChange = new int[valueLen];
+            }
+            positionsToChange[numChanged++]=i;
+            break;
+        }
+      }
+
+      if (numChanged == 0) {
+        if(log.isDebugEnabled())
+        {
+          log.debug("No entity references were found in "+value);
+        }
+        return value;
+      }
+      else {
+        if(log.isDebugEnabled())
+        {
+          log.debug("Found "+numChanged+" entity references in "+value);
+        }
+        
+        //We'll create the new builder assuming the size of the worst case
+        StringBuilder changedValue = new StringBuilder(valueLen+numChanged*5);
+        int changedPos = 0; 
+        for (int i = 0; i < valueLen; i++) {
+          if (i == positionsToChange[changedPos]) {
+            switch (value.charAt(i)) {
+              case '<':
+                changedValue.append("&lt;");
+                changedPos++;
+                break;
+              case '>':
+                changedValue.append("&gt;");
+                changedPos++;
+                break;
+              case '&':
+                changedValue.append("&amp;");
+                changedPos++;
+                break;
+              case '\'':
+                changedValue.append("&apos;");
+                changedPos++;
+                break;
+              case '\"':
+                changedValue.append("&quot;");
+                changedPos++;
+                break;
+            }
+          }
+          else {
+            changedValue.append(value.charAt(i));
+          }
+        }
+
+        if(log.isDebugEnabled())
+        {
+          log.debug("Converted to "+changedValue.toString());
+        }
+
+        return changedValue.toString();
+      }
+    }
     /*
      * Read content from entityReader.
      */

Modified: webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilderTests.java
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilderTests.java?rev=882698&r1=882697&r2=882698&view=diff
==============================================================================
--- webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilderTests.java (original)
+++ webservices/axis2/trunk/java/modules/jaxws/test/org/apache/axis2/jaxws/context/listener/ParserInputStreamCustomBuilderTests.java Fri Nov 20 19:57:29 2009
@@ -74,6 +74,35 @@
 		}
 	}
 
+	/**
+     * Tests that ParsedEntityCustomBuilder.convertEntityReferences works as expected.
+     */
+    public void testConvertEntityReferences(){
+        try{
+            ParserInputStreamCustomBuilder customBuilder = new ParserInputStreamCustomBuilder("UTF-8");
+            // test that all expected chars are converted
+            String expectedString1 = "&lt;,&gt;,&quot;,&apos;,&amp;";
+            String convertedString = customBuilder.convertEntityReferences("<,>,\",',&");
+            assertTrue("Special chars didn't get converted!  " +
+                    "Expected: \""+expectedString1+"\" but received: \""+convertedString+"\"", 
+                    convertedString.equals(expectedString1));
+            // test that a string with no special chars is unchanged
+            String simpleString = "This is a simple string";
+            convertedString = customBuilder.convertEntityReferences(simpleString);
+            assertTrue("Simple string was changed unexpectedly.  " +
+                    "Expected: \""+simpleString+"\" but received: \""+convertedString+"\"", 
+                    convertedString.equals(simpleString));
+            
+            // test that the mockenvelope gets converted correctly
+            String expectedString2 = "&lt;soapenv:Envelope xmlns:soapenv=&quot;http://schemas.xmlsoap.org/soap/envelope/&quot;&gt;&lt;soapenv:Header/&gt;&lt;soapenv:Body&gt;&lt;invokeOp&gt;Hello Provider OM&lt;/invokeOp&gt;&lt;/soapenv:Body&gt;&lt;/soapenv:Envelope&gt;";
+            convertedString = customBuilder.convertEntityReferences(mockenvelope);
+            assertTrue("mockenvelope was not converted as expected.  " +
+                    "Expected: \""+expectedString2+"\" but received: \""+convertedString+"\"", 
+                    convertedString.equals(expectedString2));
+        }catch(Exception e){
+            fail(e.getMessage());
+        }
+    }
 	private SOAPEnvelope getMockEnvelope() throws Exception{
 		SOAPEnvelope env = (SOAPEnvelope)getOMBuilder().getDocumentElement();
 		return env;