cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dk...@apache.org
Subject git commit: [CXF-5686] Fix problems of Providers replying with faults with schema validation on
Date Tue, 15 Apr 2014 19:18:11 GMT
Repository: cxf
Updated Branches:
  refs/heads/master 3791ce7b4 -> 7ac69b005


[CXF-5686] Fix problems of Providers replying with faults with schema validation on


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/7ac69b00
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/7ac69b00
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/7ac69b00

Branch: refs/heads/master
Commit: 7ac69b0058cc1acf5c2cf26c41baeee21554575a
Parents: 3791ce7
Author: Daniel Kulp <dkulp@apache.org>
Authored: Tue Apr 15 15:14:17 2014 -0400
Committer: Daniel Kulp <dkulp@apache.org>
Committed: Tue Apr 15 15:17:50 2014 -0400

----------------------------------------------------------------------
 .../interceptors/MessageModeOutInterceptor.java | 109 +++++++++++++++++--
 .../ValidationClientServerTest.java             |  34 +++++-
 .../schema_validation/ValidationServer.java     |  72 +++++++++++-
 3 files changed, 198 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/7ac69b00/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/MessageModeOutInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/MessageModeOutInterceptor.java
b/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/MessageModeOutInterceptor.java
index 76f9ec3..dd82c9c 100644
--- a/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/MessageModeOutInterceptor.java
+++ b/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/interceptors/MessageModeOutInterceptor.java
@@ -26,19 +26,24 @@ import java.util.List;
 
 import javax.activation.DataSource;
 import javax.xml.namespace.QName;
+import javax.xml.soap.Detail;
 import javax.xml.soap.MessageFactory;
 import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPFault;
 import javax.xml.soap.SOAPHeader;
 import javax.xml.soap.SOAPMessage;
 import javax.xml.soap.SOAPPart;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.validation.Schema;
 
 import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 
-
+import org.apache.cxf.annotations.SchemaValidation.SchemaValidationType;
 import org.apache.cxf.attachment.AttachmentDeserializer;
 import org.apache.cxf.binding.soap.Soap12;
 import org.apache.cxf.binding.soap.SoapFault;
@@ -48,7 +53,9 @@ import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
 import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor.SAAJOutEndingInterceptor;
 import org.apache.cxf.binding.soap.saaj.SAAJStreamWriter;
 import org.apache.cxf.binding.soap.saaj.SAAJUtils;
+import org.apache.cxf.helpers.DOMUtils;
 import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.helpers.ServiceUtils;
 import org.apache.cxf.interceptor.AbstractOutDatabindingInterceptor;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.interceptor.StaxOutInterceptor;
@@ -59,10 +66,12 @@ import org.apache.cxf.message.MessageImpl;
 import org.apache.cxf.message.MessageUtils;
 import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
+import org.apache.cxf.service.model.BindingFaultInfo;
 import org.apache.cxf.service.model.BindingMessageInfo;
 import org.apache.cxf.service.model.BindingOperationInfo;
 import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.staxutils.W3CDOMStreamWriter;
+import org.apache.cxf.ws.addressing.EndpointReferenceUtils;
 
 public class MessageModeOutInterceptor extends AbstractPhaseInterceptor<Message> {
     MessageModeOutInterceptorInternal internal;
@@ -147,11 +156,82 @@ public class MessageModeOutInterceptor extends AbstractPhaseInterceptor<Message>
                 XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(out);
                 message.setContent(XMLStreamWriter.class, writer);
             }
+        } else if (ServiceUtils.isSchemaValidationEnabled(SchemaValidationType.OUT, message)
+            && Source.class.isAssignableFrom(type)) {
+            //if schema validation is on, we'll end up converting to a DOMSource anyway,

+            //let's convert and check for a fault
+            MessageContentsList list = (MessageContentsList)message.getContent(List.class);
+            Source ds = (Source)list.get(0);
+            if (!(ds instanceof DOMSource)) {
+                try {
+                    ds = new DOMSource(StaxUtils.read(ds));
+                } catch (XMLStreamException e) {
+                    throw new Fault(e);
+                }
+                list.set(0,  ds);
+                validatePossibleFault(message, bop, ((DOMSource)ds).getNode());
+            }
         }
         
     }
     
     
+    private void validatePossibleFault(Message message, BindingOperationInfo bop, Node ds)
{
+        Element el = DOMUtils.getFirstElement(ds);
+        if (!"Fault".equals(el.getLocalName())) {
+            return;
+        }
+        message.put(Message.RESPONSE_CODE, 500);
+
+        el = DOMUtils.getFirstElement(el);
+        while (el != null && !"detail".equals(el.getLocalName())) {
+            el = DOMUtils.getNextElement(el);
+        }
+        if (el != null) {
+            Schema schema = EndpointReferenceUtils.getSchema(message.getExchange().getService()
+                                                             .getServiceInfos().get(0),
+                                                         message.getExchange().getBus());
+            try {
+                validateFaultDetail(el, schema, bop);
+            } catch (Exception e) {
+                throw new Fault(e);
+            }
+
+            //We validated what we can from a fault standpoint
+            message.put(Message.SCHEMA_VALIDATION_ENABLED, Boolean.FALSE);
+        }
+    }
+    private void validateFaultDetail(Element detail, Schema schema, BindingOperationInfo
bop) throws Exception {
+        Element el = DOMUtils.getFirstElement(detail);
+        while (el != null) {
+            QName qn = DOMUtils.getElementQName(el);
+            for (BindingFaultInfo bfi : bop.getFaults()) {
+                if (bfi.getFaultInfo().getMessagePartByIndex(0).getConcreteName().equals(qn))
{
+                    //Found a fault with the correct QName, we can validate it
+                    schema.newValidator().validate(new DOMSource(el));
+                }
+            }
+            el = DOMUtils.getNextElement(el);
+        }
+    }
+    private void validateFault(SoapMessage message, SOAPFault fault, BindingOperationInfo
bop) {
+        if (ServiceUtils.isSchemaValidationEnabled(SchemaValidationType.OUT, message)) {
+            Schema schema = EndpointReferenceUtils.getSchema(message.getExchange().getService()
+                                                             .getServiceInfos().get(0),
+                                                         message.getExchange().getBus());
+            Detail d = fault.getDetail();
+            try {
+                validateFaultDetail(d, schema, bop);
+            } catch (Exception e) {
+                throw new SoapFault(e.getMessage(), e, message.getVersion().getReceiver());
+            }
+            
+            //We validated what we can from a fault standpoint
+            message.put(Message.SCHEMA_VALIDATION_ENABLED, Boolean.FALSE);
+        }
+    }
+    
+    
     private void doSoap(Message message) {
         MessageContentsList list = (MessageContentsList)message.getContent(List.class);
         if (list == null || list.isEmpty()) {
@@ -233,28 +313,32 @@ public class MessageModeOutInterceptor extends AbstractPhaseInterceptor<Message>
                                         message.getVersion().getSender());
                 }
             }
-            message.setContent(SOAPMessage.class, soapMessage);
-            
-            if (!message.containsKey(SAAJOutInterceptor.ORIGINAL_XML_WRITER)) {
-                XMLStreamWriter origWriter = message.getContent(XMLStreamWriter.class);
-                message.put(SAAJOutInterceptor.ORIGINAL_XML_WRITER, origWriter);
-            }
-            W3CDOMStreamWriter writer = new SAAJStreamWriter(soapMessage.getSOAPPart());
-            // Replace stax writer with DomStreamWriter
-            message.setContent(XMLStreamWriter.class, writer);
-            message.setContent(SOAPMessage.class, soapMessage);
 
             BindingOperationInfo bop = message.getExchange().get(BindingOperationInfo.class);
-
             DocumentFragment frag = soapMessage.getSOAPPart().createDocumentFragment();
             try {
                 Node body = SAAJUtils.getBody(soapMessage);
                 Node nd = body.getFirstChild();
                 while (nd != null) {
+                    if (nd instanceof SOAPFault) {
+                        message.put(Message.RESPONSE_CODE, 500);
+                        validateFault(message, (SOAPFault)nd, bop);
+                    }
                     body.removeChild(nd);
                     frag.appendChild(nd);
                     nd = SAAJUtils.getBody(soapMessage).getFirstChild();
                 }
+
+                message.setContent(SOAPMessage.class, soapMessage);
+                
+                if (!message.containsKey(SAAJOutInterceptor.ORIGINAL_XML_WRITER)) {
+                    XMLStreamWriter origWriter = message.getContent(XMLStreamWriter.class);
+                    message.put(SAAJOutInterceptor.ORIGINAL_XML_WRITER, origWriter);
+                }
+                W3CDOMStreamWriter writer = new SAAJStreamWriter(soapMessage.getSOAPPart());
+                // Replace stax writer with DomStreamWriter
+                message.setContent(XMLStreamWriter.class, writer);
+                message.setContent(SOAPMessage.class, soapMessage);
                 
                 int index = 0;
 
@@ -281,6 +365,7 @@ public class MessageModeOutInterceptor extends AbstractPhaseInterceptor<Message>
                 if (buffer == null) {
                     message.put(AbstractOutDatabindingInterceptor.OUT_BUFFERING, Boolean.FALSE);
                 }
+                
             } catch (Exception ex) {
                 throw new Fault(ex);
             }

http://git-wip-us.apache.org/repos/asf/cxf/blob/7ac69b00/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationClientServerTest.java
----------------------------------------------------------------------
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationClientServerTest.java
b/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationClientServerTest.java
index b04eda2..3dfb0a9 100644
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationClientServerTest.java
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationClientServerTest.java
@@ -61,9 +61,37 @@ public class ValidationClientServerTest extends AbstractBusClientServerTestBase
         assertTrue("server did not launch correctly", launchServer(ValidationServer.class,
true));
     }
 
-    // TODO : Change this test so that we test the combinations of
-    // client and server with schema validation enabled/disabled...
-    // Only tests client side validation enabled/server side disabled.
+    @Test
+    public void testSchemaValidationProviderPayload() throws Exception {
+        doProviderTest("PProvider");
+    }
+    @Test
+    public void testSchemaValidationProviderMessage() throws Exception {
+        doProviderTest("MProvider");
+    }
+    private void doProviderTest(String postfix) throws Exception {
+        SchemaValidation validation = createService(Boolean.FALSE, postfix);
+        SomeRequest req = new SomeRequest();
+        req.setId("9999999999");
+        try {
+            validation.doSomething(req);
+            fail("Should have faulted");
+        } catch (DoSomethingFault e) {
+            assertEquals("1234", e.getFaultInfo().getErrorCode());
+        }
+        req.setId("8888888888");
+        try {
+            validation.doSomething(req);
+            fail("Should have faulted");
+        } catch (DoSomethingFault e) {
+            fail("Should not have happened");
+        } catch (WebServiceException e) {
+            String expected = "Value '1' is not facet-valid";
+            assertTrue(e.getMessage().indexOf(expected) != -1);
+        }
+        ((java.io.Closeable)validation).close();
+    }
+    
     @Test
     public void testSchemaValidationServer() throws Exception {
         SchemaValidation validation = createService(Boolean.FALSE, "SoapPortValidate");

http://git-wip-us.apache.org/repos/asf/cxf/blob/7ac69b00/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationServer.java
----------------------------------------------------------------------
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationServer.java
b/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationServer.java
index 79f2939..5f2404d 100644
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationServer.java
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/schema_validation/ValidationServer.java
@@ -20,18 +20,27 @@
 package org.apache.cxf.systest.schema_validation;
 
 
+import java.io.StringReader;
 import java.util.LinkedList;
 import java.util.List;
 
 import javax.jws.WebService;
+import javax.xml.stream.XMLStreamException;
 import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
 import javax.xml.ws.Endpoint;
 import javax.xml.ws.Provider;
 import javax.xml.ws.Service;
 import javax.xml.ws.ServiceMode;
 import javax.xml.ws.WebServiceProvider;
 
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.annotations.Logging;
 import org.apache.cxf.annotations.SchemaValidation;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.testutil.common.AbstractBusTestServerBase;
 
 public class ValidationServer extends AbstractBusTestServerBase {
@@ -67,22 +76,81 @@ public class ValidationServer extends AbstractBusTestServerBase {
         
     }
 
+    private static String getResponse(String v) {
+        if ("9999999999".equals(v)) {
+            return "<soap:Fault xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+                + "<faultcode>soap:Server</faultcode>"
+                + "<faultstring>Fault</faultstring>"
+                + "<detail>"
+                + "<SomeFault xmlns=\"http://apache.org/schema_validation/types\">"
+                + "    <errorCode>1234</errorCode></SomeFault>"
+                + "</detail>"
+                + "</soap:Fault>";
+        } else if ("8888888888".equals(v)) {
+            return "<soap:Fault xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+                + "<faultcode>soap:Server</faultcode>"
+                + "<faultstring>Fault</faultstring>"
+                + "<detail>"
+                + "<SomeFault xmlns=\"http://apache.org/schema_validation/types\">"
+                + "    <errorCode>1</errorCode></SomeFault>"
+                + "</detail>"
+                + "</soap:Fault>";
+        }
+        return "";
+    }
 
-    @WebServiceProvider
+    @WebServiceProvider(wsdlLocation = "classpath:/wsdl/schema_validation.wsdl",
+        serviceName = "SchemaValidationService", 
+        portName = "SoapPort",
+        targetNamespace = "http://apache.org/schema_validation")
     @ServiceMode(Service.Mode.PAYLOAD)
     @SchemaValidation
+    @Logging
     static class PayloadProvider implements Provider<Source> {
         @Override
         public Source invoke(Source request) {
+            try {
+                Document doc = StaxUtils.read(request);
+                String name = doc.getDocumentElement().getLocalName();
+                if ("SomeRequest".equals(name)) {
+                    String v = DOMUtils.getFirstElement(doc.getDocumentElement()).getTextContent();
+                    return new StreamSource(new StringReader(getResponse(v)));
+                }
+            } catch (XMLStreamException e) {
+                e.printStackTrace();
+            }
             return null;
         }
     }
-    @WebServiceProvider
+    
+    @WebServiceProvider(wsdlLocation = "classpath:/wsdl/schema_validation.wsdl",
+        serviceName = "SchemaValidationService", 
+        portName = "SoapPort",
+        targetNamespace = "http://apache.org/schema_validation")
     @ServiceMode(Service.Mode.MESSAGE)
     @SchemaValidation
     static class MessageProvider implements Provider<Source> {
         @Override
         public Source invoke(Source request) {
+            try {
+                Document doc = StaxUtils.read(request);
+                Element el = DOMUtils.getFirstElement(doc.getDocumentElement());
+                while (!"Body".equals(el.getLocalName())) {
+                    el = DOMUtils.getNextElement(el);
+                }
+                el = DOMUtils.getFirstElement(el);
+                String name = el.getLocalName();
+                
+                if ("SomeRequest".equals(name)) {
+                    String v = DOMUtils.getFirstElement(el).getTextContent();
+                    return new StreamSource(
+                        new StringReader("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
+                            + "<soap:Body>" + getResponse(v) + "</soap:Body></soap:Envelope>"));
+                }
+            } catch (XMLStreamException ex) {
+                ex.printStackTrace();
+            }
+            
             return null;
         }
     }


Mime
View raw message