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 2014/04/15 22:33:50 UTC
[5/8] git commit: [CXF-5686] Fix problems of Providers replying with
faults with schema validation on
[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/03e877f6
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/03e877f6
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/03e877f6
Branch: refs/heads/2.7.x-fixes
Commit: 03e877f6c2f81e1220cba66cf295de98db7ea5c5
Parents: 49de470
Author: Daniel Kulp <dk...@apache.org>
Authored: Tue Apr 15 15:14:17 2014 -0400
Committer: Daniel Kulp <dk...@apache.org>
Committed: Tue Apr 15 16:01:26 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/03e877f6/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/03e877f6/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/03e877f6/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;
}
}