You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2009/11/02 18:30:53 UTC

svn commit: r831978 - in /cxf/trunk: rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/ systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ testutils/src/main/java/org/apache/hello_world_soap_http/

Author: dkulp
Date: Mon Nov  2 17:30:52 2009
New Revision: 831978

URL: http://svn.apache.org/viewvc?rev=831978&view=rev
Log:
[CXF-1277] Enable schema validation for RPC/Lit

Modified:
    cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java
    cxf/trunk/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerRPCLitTest.java
    cxf/trunk/testutils/src/main/java/org/apache/hello_world_soap_http/RPCLitGreeterImpl.java

Modified: cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java?rev=831978&r1=831977&r2=831978&view=diff
==============================================================================
--- cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java (original)
+++ cxf/trunk/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java Mon Nov  2 17:30:52 2009
@@ -56,12 +56,15 @@
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.util.StreamReaderDelegate;
 import javax.xml.transform.stream.StreamResult;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 
 import org.apache.cxf.common.i18n.Message;
 import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.SOAPConstants;
+import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.service.model.MessagePartInfo;
@@ -76,6 +79,85 @@
  * Utility functions for JAXB.
  */
 public final class JAXBEncoderDecoder {
+    private static final class AddXSITypeStreamReader extends StreamReaderDelegate {
+        private boolean first = true;
+        private final QName typeQName;
+
+        private AddXSITypeStreamReader(XMLStreamReader reader, QName typeQName) {
+            super(reader);
+            this.typeQName = typeQName;
+        }
+
+        public int getAttributeCount() {
+            return super.getAttributeCount() + (first ? 1 : 0);
+        }
+
+        public String getAttributeLocalName(int index) {
+            if (first && index == 0) {
+                return "type";
+            }
+            return super.getAttributeLocalName(index - 1);
+        }
+
+        public QName getAttributeName(int index) {
+            if (first && index == 0) {
+                return new QName(SOAPConstants.XSI_NS, "type");
+            }
+            return super.getAttributeName(index - 1);
+        }
+
+        public String getAttributeNamespace(int index) {
+            if (first && index == 0) {
+                return SOAPConstants.XSI_NS;
+            }
+            return super.getAttributeNamespace(index - 1);
+        }
+
+        public String getAttributePrefix(int index) {
+            if (first && index == 0) {
+                return "xsi";
+            }
+            return super.getAttributePrefix(index - 1);
+        }
+
+        public String getAttributeType(int index) {
+            if (first && index == 0) {
+                return "#TEXT";
+            }
+            return super.getAttributeType(index - 1);
+        }
+
+        public String getAttributeValue(int index) {
+            if (first && index == 0) {
+                String pfx = this.getNamespaceContext().getPrefix(typeQName.getNamespaceURI());
+                if (StringUtils.isEmpty(pfx)) {
+                    return typeQName.getLocalPart();
+                }
+                return pfx + ":" + typeQName.getLocalPart();
+            }
+            return super.getAttributeValue(index);
+        }
+
+        public int next()  throws XMLStreamException {
+            first = false;
+            return super.next();
+        }
+
+        public String getAttributeValue(String namespaceUri,
+                                        String localName) {
+            if (first
+                && SOAPConstants.XSI_NS.equals(namespaceUri)
+                && "type".equals(localName)) {
+                String pfx = this.getNamespaceContext().getPrefix(typeQName.getNamespaceURI());
+                if (StringUtils.isEmpty(pfx)) {
+                    return typeQName.getLocalPart();
+                }
+                return pfx + ":" + typeQName.getLocalPart();
+            }
+            return super.getAttributeValue(namespaceUri, localName);
+        }
+    }
+
     private static final Logger LOG = LogUtils.getLogger(JAXBEncoderDecoder.class);
 
     private JAXBEncoderDecoder() {
@@ -144,6 +226,10 @@
                     writeObject(marshaller, source, new JAXBElement(elName, String.class, mObj));
                 } else if (mObj instanceof JAXBElement) {
                     writeObject(marshaller, source, mObj);
+                } else if (marshaller.getSchema() != null) {
+                    //force xsi:type so types can be validated instead of trying to 
+                    //use the RPC/lit element names that aren't in the schema 
+                    writeObject(marshaller, source, new JAXBElement(elName, Object.class, mObj));
                 } else {
                     writeObject(marshaller, source, new JAXBElement(elName, cls, mObj));
                 }
@@ -528,6 +614,10 @@
 
             String obj = (String)unmarshall(u, source, elName, String.class, unwrap);
             return new HexBinaryAdapter().unmarshal(obj);
+        } else if (part != null && u.getSchema() != null
+            && !(part.getXmlSchema() instanceof XmlSchemaElement)) {
+            //Validating RPC/Lit, make sure we don't try a root element name thing
+            source = updateSourceWithXSIType(source, part.getTypeQName());
         }
 
         Object o = unmarshall(u, source, elName, clazz, unwrap);
@@ -539,6 +629,17 @@
         return o;
     }
 
+    private static Object updateSourceWithXSIType(Object source, final QName typeQName) {
+        if (source instanceof XMLStreamReader) {
+            XMLStreamReader reader = (XMLStreamReader)source;
+            String type = reader.getAttributeValue(SOAPConstants.XSI_NS, "type");
+            if (StringUtils.isEmpty(type)) {
+                source = new AddXSITypeStreamReader(reader, typeQName);
+            }
+        }
+        return source;
+    }
+
     private static Object createSet(MessagePartInfo part, List<Object> ret) {
         Type genericType = (Type)part.getProperty("generic.type");
         Class tp2 = (Class)((ParameterizedType)genericType).getRawType();
@@ -551,6 +652,7 @@
         } catch (Exception e) {
             c = new HashSet<Object>();
         }
+        
         c.addAll(ret);
         return c;
     }

Modified: cxf/trunk/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerRPCLitTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerRPCLitTest.java?rev=831978&r1=831977&r2=831978&view=diff
==============================================================================
--- cxf/trunk/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerRPCLitTest.java (original)
+++ cxf/trunk/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerRPCLitTest.java Mon Nov  2 17:30:52 2009
@@ -32,6 +32,7 @@
 import javax.jws.soap.SOAPBinding;
 import javax.jws.soap.SOAPBinding.Style;
 import javax.jws.soap.SOAPBinding.Use;
+import javax.xml.bind.UnmarshalException;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -39,8 +40,10 @@
 import javax.xml.namespace.QName;
 import javax.xml.transform.Source;
 import javax.xml.transform.stream.StreamSource;
+import javax.xml.ws.BindingProvider;
 import javax.xml.ws.Dispatch;
 import javax.xml.ws.Endpoint;
+import javax.xml.ws.soap.SOAPFaultException;
 import javax.xml.xpath.XPathConstants;
 
 import org.w3c.dom.Document;
@@ -154,15 +157,25 @@
         in.setElem3(45);
 
         try {            
+            ((BindingProvider)greeter).getRequestContext().put("schema-validation-enabled", Boolean.TRUE);
             MyComplexStruct out = greeter.sendReceiveData(in); 
             assertNotNull("no response received from service", out);
             assertEquals(in.getElem1(), out.getElem1());
             assertEquals(in.getElem2(), out.getElem2());
             assertEquals(in.getElem3(), out.getElem3());
+            
+            
+            
         } catch (UndeclaredThrowableException ex) {
             throw (Exception) ex.getCause();
         }
         
+        try {
+            in.setElem2("invalid");
+            greeter.sendReceiveData(in); 
+        } catch (SOAPFaultException f) {
+            assertTrue(f.getCause() instanceof UnmarshalException);
+        }
     }
     
     @Test

Modified: cxf/trunk/testutils/src/main/java/org/apache/hello_world_soap_http/RPCLitGreeterImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/testutils/src/main/java/org/apache/hello_world_soap_http/RPCLitGreeterImpl.java?rev=831978&r1=831977&r2=831978&view=diff
==============================================================================
--- cxf/trunk/testutils/src/main/java/org/apache/hello_world_soap_http/RPCLitGreeterImpl.java (original)
+++ cxf/trunk/testutils/src/main/java/org/apache/hello_world_soap_http/RPCLitGreeterImpl.java Mon Nov  2 17:30:52 2009
@@ -49,6 +49,9 @@
         System.out.println("Executing operation sendReceiveData");
         System.out.println("Received struct with values :\nElement-1 : " + in.getElem1() + "\nElement-2 : "
                            + in.getElem2() + "\nElement-3 : " + in.getElem3() + "\n");
+        if ("invalid".equals(in.getElem2())) {
+            in.setElem2(null);
+        }
         return in;
     }