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 2017/03/07 20:03:13 UTC

[11/15] cxf git commit: [CXF-7269]schemavalidate failed when use mtom and Provider

[CXF-7269]schemavalidate failed when use mtom and Provider

# Conflicts:
#	core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java
#	systests/uncategorized/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopTest.java


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

Branch: refs/heads/3.1.x-fixes
Commit: e81a5c953173abb072372ff28e68ba4fd17dc653
Parents: 161439d
Author: Freeman Fang <fr...@gmail.com>
Authored: Tue Mar 7 16:44:03 2017 +0800
Committer: Daniel Kulp <dk...@apache.org>
Committed: Tue Mar 7 14:07:28 2017 -0500

----------------------------------------------------------------------
 .../databinding/source/XMLStreamDataWriter.java | 111 +++++++++++++++++-
 .../cxf/systest/mtom/ClientMtomXopTest.java     | 115 ++++++++++++++++++-
 testutils/pom.xml                               |   4 +
 .../cxf/mtom_xop/TestMtomProviderImpl.java      | 104 +++++++++++++++++
 testutils/src/main/resources/wsdl/mtom_xop.wsdl |   3 +
 5 files changed, 333 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/e81a5c95/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java b/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java
index c0938d5..bec5b14 100644
--- a/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java
+++ b/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java
@@ -29,12 +29,17 @@ import javax.xml.stream.XMLStreamWriter;
 import javax.xml.transform.Source;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.DocumentFragment;
 import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
+import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
 
 import org.apache.cxf.common.i18n.Message;
 import org.apache.cxf.common.logging.LogUtils;
@@ -46,9 +51,15 @@ import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.cxf.staxutils.W3CDOMStreamWriter;
 
 public class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
+    
     private static final Logger LOG = LogUtils.getL7dLogger(XMLStreamDataWriter.class);
 
+   
     private Schema schema;
+
+    public XMLStreamDataWriter() {
+        
+    }
     
     public void write(Object obj, MessagePartInfo part, XMLStreamWriter output) {
         write(obj, output);
@@ -61,7 +72,10 @@ public class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
                 DataSource ds = (DataSource)obj;
                 if (schema != null) {
                     DOMSource domSource = new DOMSource(StaxUtils.read(ds.getInputStream()));
-                    schema.newValidator().validate(domSource);
+                    Validator schemaValidator = schema.newValidator();
+                    schemaValidator.setErrorHandler(
+                        new MtomValidationErrorHandler(schemaValidator.getErrorHandler(), domSource.getNode()));
+                    schemaValidator.validate(domSource);
                     StaxUtils.copy(domSource, writer);
                 } else {
                     reader = StaxUtils.createXMLStreamReader(ds.getInputStream());
@@ -71,7 +85,10 @@ public class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
                 
             } else if (obj instanceof Node) {
                 if (schema != null) {
-                    schema.newValidator().validate(new DOMSource((Node)obj));
+                    Validator schemaValidator = schema.newValidator();
+                    schemaValidator.setErrorHandler(
+                        new MtomValidationErrorHandler(schemaValidator.getErrorHandler(), (Node)obj));
+                    schemaValidator.validate(new DOMSource((Node)obj));
                 }
                 Node nd = (Node)obj;
                 writeNode(nd, writer);
@@ -82,7 +99,10 @@ public class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
                         //make the source re-readable.
                         s = new DOMSource(StaxUtils.read(s));
                     }
-                    schema.newValidator().validate(s);
+                    Validator schemaValidator = schema.newValidator();
+                    schemaValidator.setErrorHandler(
+                        new MtomValidationErrorHandler(schemaValidator.getErrorHandler(), ((DOMSource)s).getNode()));
+                    schemaValidator.validate(s);
                 }
                 if (s instanceof DOMSource
                     && ((DOMSource) s).getNode() == null) {
@@ -153,4 +173,89 @@ public class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
     public void setProperty(String key, Object value) {
     }
     
+    private static class MtomValidationErrorHandler implements ErrorHandler {
+        private ErrorHandler origErrorHandler;
+        private Node node;
+        
+        MtomValidationErrorHandler(ErrorHandler origErrorHandler, Node node) {
+            this.origErrorHandler = origErrorHandler;
+            this.node = node;
+        }
+        
+        
+        @Override
+        public void warning(SAXParseException exception) throws SAXException {
+            
+            if (this.origErrorHandler != null) {
+                this.origErrorHandler.warning(exception);
+            } else {
+                // do nothing
+            }
+        }
+
+        @Override
+        public void error(SAXParseException exception) throws SAXException {
+            if (this.isCVC312Exception(exception)) {
+                String elementName = this.getAttachmentElementName(exception);
+                if (node != null && this.findIncludeNode(node, elementName)) {
+                    return;
+                }
+            }
+            
+            if (this.origErrorHandler != null) {
+                this.origErrorHandler.error(exception);
+            } else {
+                throw exception;
+            }
+            
+        }
+
+        @Override
+        public void fatalError(SAXParseException exception) throws SAXException {
+            if (this.origErrorHandler != null) {
+                this.origErrorHandler.fatalError(exception);
+            } else {
+                throw exception;
+            }
+            
+        }
+        
+        private boolean isCVC312Exception(SAXParseException exception) {
+            String msg = exception.getMessage();
+            return msg.startsWith("cvc-type.3.1.2: ") 
+                && msg.endsWith("is a simple type, so it must have no element information item [children].");
+                
+           
+        }
+        
+        private String getAttachmentElementName(SAXParseException exception) {
+            String msg = exception.getMessage();
+            String str[] = msg.split("'");
+            return str[1];
+        }
+        
+        private boolean findIncludeNode(Node checkNode, String mtomElement) {
+            boolean ret = false;
+            NodeList nList = checkNode.getChildNodes();
+            for (int i = 0; i < nList.getLength(); i++) {
+                Node nNode = nList.item(i);
+                if (nNode.getLocalName() != null 
+                    && nNode.getLocalName().equals(mtomElement)) {
+                    NodeList subNodeList = nNode.getChildNodes();
+                    for (int j = 0; j < subNodeList.getLength(); j++) {
+                        Node subNode = subNodeList.item(j);
+                        if (subNode.getNamespaceURI().equals("http://www.w3.org/2004/08/xop/include")
+                            && subNode.getLocalName().equals("Include")) {
+                            // This is the Mtom element which break the SchemaValidation so ignore this
+                            return true;
+                        }
+                    }
+                } else {
+                    ret = findIncludeNode(nNode, mtomElement);
+                }
+            }
+            return ret;
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/e81a5c95/systests/uncategorized/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopTest.java
----------------------------------------------------------------------
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopTest.java b/systests/uncategorized/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopTest.java
index d88d117..c5f6abb 100644
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopTest.java
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/mtom/ClientMtomXopTest.java
@@ -51,6 +51,7 @@ import org.apache.cxf.message.Message;
 import org.apache.cxf.mime.TestMtom;
 import org.apache.cxf.mime.types.XopStringType;
 import org.apache.cxf.mtom_xop.TestMtomImpl;
+import org.apache.cxf.mtom_xop.TestMtomProviderImpl;
 import org.apache.cxf.service.Service;
 import org.apache.cxf.service.model.EndpointInfo;
 import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase;
@@ -63,7 +64,9 @@ import org.junit.Test;
 public class ClientMtomXopTest extends AbstractBusClientServerTestBase {
     public static final String PORT = allocatePort(ClientMtomXopTest.class);
     public static final QName MTOM_PORT = new QName("http://cxf.apache.org/mime", "TestMtomPort");
+    public static final QName MTOM_PORT_PROVIDER = new QName("http://cxf.apache.org/mime", "TestMtomProviderPort");
     public static final QName MTOM_SERVICE = new QName("http://cxf.apache.org/mime", "TestMtomService");
+    
 
     
     public static class Server extends AbstractBusTestServerBase {
@@ -71,14 +74,21 @@ public class ClientMtomXopTest extends AbstractBusClientServerTestBase {
         protected void run() {
             Object implementor = new TestMtomImpl();
             String address = "http://localhost:" + PORT + "/mime-test";
+            String addressProvider = "http://localhost:" + PORT + "/mime-test-provider";
             try {
                 jaxep = (EndpointImpl) javax.xml.ws.Endpoint.publish(address, implementor);
                 Endpoint ep = jaxep.getServer().getEndpoint();
                 ep.getInInterceptors().add(new TestMultipartMessageInterceptor());
                 ep.getOutInterceptors().add(new TestAttachmentOutInterceptor());
-                
+                jaxep.getInInterceptors().add(new LoggingInInterceptor());
+                jaxep.getOutInterceptors().add(new LoggingOutInterceptor());
                 SOAPBinding jaxWsSoapBinding = (SOAPBinding) jaxep.getBinding();
                 jaxWsSoapBinding.setMTOMEnabled(true);
+                EndpointImpl endpoint = 
+                    (EndpointImpl)javax.xml.ws.Endpoint.publish(addressProvider, new TestMtomProviderImpl());
+                endpoint.getProperties().put("schema-validation-enabled", "true");
+                endpoint.getInInterceptors().add(new LoggingInInterceptor());
+                endpoint.getOutInterceptors().add(new LoggingOutInterceptor());
 
             } catch (Exception e) {
                 Thread.currentThread().interrupt();
@@ -197,6 +207,109 @@ public class ClientMtomXopTest extends AbstractBusClientServerTestBase {
             throw ex;
         }
     }
+        
+       
+    @Test
+    public void testMtomXopProvider() throws Exception {
+        TestMtom mtomPort = createPort(MTOM_SERVICE, MTOM_PORT_PROVIDER, TestMtom.class, true, true);
+        try {
+            Holder<DataHandler> param = new Holder<DataHandler>();
+            Holder<String> name;
+            byte bytes[];
+            InputStream in;
+
+            InputStream pre = this.getClass().getResourceAsStream("/wsdl/mtom_xop.wsdl");
+            int fileSize = 0;
+            for (int i = pre.read(); i != -1; i = pre.read()) {
+                fileSize++;
+            }
+
+            int count = 50;
+            byte[] data = new byte[fileSize *  count];
+            for (int x = 0; x < count; x++) {
+                this.getClass().getResourceAsStream("/wsdl/mtom_xop.wsdl").read(data,
+                                                                                fileSize * x,
+                                                                                fileSize);
+            }
+
+            Object[] validationTypes = new Object[]{Boolean.TRUE, SchemaValidationType.IN, SchemaValidationType.BOTH};
+
+            for (Object validationType : validationTypes) {
+                ((BindingProvider)mtomPort).getRequestContext().put(Message.SCHEMA_VALIDATION_ENABLED,
+                                                                    validationType);
+
+                param.value = new DataHandler(new ByteArrayDataSource(data, "application/octet-stream"));
+                name = new Holder<String>("call detail");
+                mtomPort.testXop(name, param);
+                assertEquals("name unchanged", "return detail + call detail", name.value);
+                assertNotNull(param.value);
+
+                in = param.value.getInputStream();
+                bytes = IOUtils.readBytesFromStream(in);
+                assertEquals(data.length, bytes.length);
+                in.close();
+
+                param.value = new DataHandler(new ByteArrayDataSource(data, "application/octet-stream"));
+                name = new Holder<String>("call detail");
+                mtomPort.testXop(name, param);
+                assertEquals("name unchanged", "return detail + call detail", name.value);
+                assertNotNull(param.value);
+
+                in = param.value.getInputStream();
+                bytes = IOUtils.readBytesFromStream(in);
+                assertEquals(data.length, bytes.length);
+                in.close();
+            }
+
+            validationTypes = new Object[]{Boolean.FALSE, SchemaValidationType.OUT, SchemaValidationType.NONE};
+            for (Object validationType : validationTypes) {
+                ((BindingProvider)mtomPort).getRequestContext().put(Message.SCHEMA_VALIDATION_ENABLED,
+                                                                validationType);
+                SAAJOutInterceptor saajOut = new SAAJOutInterceptor();
+                SAAJInInterceptor saajIn = new SAAJInInterceptor();
+
+                param.value = new DataHandler(new ByteArrayDataSource(data, "application/octet-stream"));
+                name = new Holder<String>("call detail");
+                mtomPort.testXop(name, param);
+                assertEquals("name unchanged", "return detail + call detail", name.value);
+                assertNotNull(param.value);
+
+                in = param.value.getInputStream();
+                bytes = IOUtils.readBytesFromStream(in);
+                assertEquals(data.length, bytes.length);
+                in.close();
+
+                ClientProxy.getClient(mtomPort).getInInterceptors().add(saajIn);
+                ClientProxy.getClient(mtomPort).getInInterceptors().add(saajOut);
+                param.value = new DataHandler(new ByteArrayDataSource(data, "application/octet-stream"));
+                name = new Holder<String>("call detail");
+                mtomPort.testXop(name, param);
+                assertEquals("name unchanged", "return detail + call detail", name.value);
+                assertNotNull(param.value);
+
+                in = param.value.getInputStream();
+                bytes = IOUtils.readBytesFromStream(in);
+                assertEquals(data.length, bytes.length);
+                in.close();
+
+                ClientProxy.getClient(mtomPort).getInInterceptors().remove(saajIn);
+                ClientProxy.getClient(mtomPort).getInInterceptors().remove(saajOut);
+            }
+        } catch (UndeclaredThrowableException ex) {
+            throw (Exception)ex.getCause();
+        } catch (Exception ex) {
+            if (ex.getMessage().contains("Connection reset")
+                && System.getProperty("java.specification.version", "1.5").contains("1.6")) {
+                //There seems to be a bug/interaction with Java 1.6 and Jetty where
+                //Jetty will occasionally send back a RST prior to all the data being
+                //sent back to the client when using localhost (which is what we do)
+                //we'll ignore for now
+                return;
+            }
+            System.out.println(System.getProperties());
+            throw ex;
+        }
+    }
 
     @Test
     public void testMtomWithFileName() throws Exception {

http://git-wip-us.apache.org/repos/asf/cxf/blob/e81a5c95/testutils/pom.xml
----------------------------------------------------------------------
diff --git a/testutils/pom.xml b/testutils/pom.xml
index 54f8244..8aec280 100644
--- a/testutils/pom.xml
+++ b/testutils/pom.xml
@@ -53,6 +53,10 @@
             <optional>true</optional>
         </dependency>
         <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-javamail_1.4_spec</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-core</artifactId>
             <scope>provided</scope>

http://git-wip-us.apache.org/repos/asf/cxf/blob/e81a5c95/testutils/src/main/java/org/apache/cxf/mtom_xop/TestMtomProviderImpl.java
----------------------------------------------------------------------
diff --git a/testutils/src/main/java/org/apache/cxf/mtom_xop/TestMtomProviderImpl.java b/testutils/src/main/java/org/apache/cxf/mtom_xop/TestMtomProviderImpl.java
new file mode 100644
index 0000000..de1f442
--- /dev/null
+++ b/testutils/src/main/java/org/apache/cxf/mtom_xop/TestMtomProviderImpl.java
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.mtom_xop;
+
+import java.io.InputStream;
+
+import javax.activation.DataHandler;
+import javax.mail.util.ByteArrayDataSource;
+import javax.xml.soap.AttachmentPart;
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPBodyElement;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPEnvelope;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPPart;
+import javax.xml.ws.Provider;
+import javax.xml.ws.Service.Mode;
+import javax.xml.ws.ServiceMode;
+import javax.xml.ws.WebServiceProvider;
+import javax.xml.ws.soap.MTOM;
+
+
+@WebServiceProvider(portName = "TestMtomProviderPort", 
+serviceName = "TestMtomService", 
+targetNamespace = "http://cxf.apache.org/mime", 
+wsdlLocation = "testutils/mtom_xop.wsdl")
+@ServiceMode(value = Mode.MESSAGE)
+@MTOM
+
+public class TestMtomProviderImpl implements Provider<SOAPMessage> {
+
+    public SOAPMessage invoke(final SOAPMessage request) {
+        try {
+            System.out.println("=== Received client request ===");
+
+            // create the SOAPMessage
+            SOAPMessage message = MessageFactory.newInstance().createMessage();
+            SOAPPart part = message.getSOAPPart();
+            SOAPEnvelope envelope = part.getEnvelope();
+            SOAPBody body = envelope.getBody();
+
+            
+            SOAPBodyElement testResponse = body
+                .addBodyElement(envelope.createName("testXopResponse", null, "http://cxf.apache.org/mime/types"));
+            SOAPElement name = testResponse.addChildElement("name", null, "http://cxf.apache.org/mime/types");
+            name.setTextContent("return detail + call detail");
+            SOAPElement attachinfo = testResponse.addChildElement(
+                                         "attachinfo", null, "http://cxf.apache.org/mime/types");
+            SOAPElement include = attachinfo.addChildElement("Include", "xop",
+                                                                "http://www.w3.org/2004/08/xop/include");
+
+            InputStream pre = this.getClass().getResourceAsStream("/wsdl/mtom_xop.wsdl");
+            int fileSize = 0;
+            for (int i = pre.read(); i != -1; i = pre.read()) {
+                fileSize++;
+            }
+
+            int count = 50;
+            byte[] data = new byte[fileSize *  count];
+            for (int x = 0; x < count; x++) {
+                this.getClass().getResourceAsStream("/wsdl/mtom_xop.wsdl").read(data,
+                                                                                fileSize * x,
+                                                                                fileSize);
+            }
+            
+            
+            DataHandler dh = new DataHandler(new ByteArrayDataSource(data, "application/octet-stream"));
+
+            // create the image attachment
+            AttachmentPart attachment = message.createAttachmentPart(dh);
+            attachment.setContentId("mtom_xop.wsdl");
+            message.addAttachmentPart(attachment);
+            System.out
+                .println("Adding attachment: " + attachment.getContentId() + ":" + attachment.getSize());
+
+            // add the reference to the image attachment
+            include.addAttribute(envelope.createName("href"), "cid:" + attachment.getContentId());
+
+            return message;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cxf/blob/e81a5c95/testutils/src/main/resources/wsdl/mtom_xop.wsdl
----------------------------------------------------------------------
diff --git a/testutils/src/main/resources/wsdl/mtom_xop.wsdl b/testutils/src/main/resources/wsdl/mtom_xop.wsdl
index 02b15fd..b84ded2 100644
--- a/testutils/src/main/resources/wsdl/mtom_xop.wsdl
+++ b/testutils/src/main/resources/wsdl/mtom_xop.wsdl
@@ -96,6 +96,9 @@
         <wsdl:port name="TestMtomPort" binding="tns:TestMtomBinding">
             <soap:address location="http://localhost:9036/mime-test"/>
         </wsdl:port>
+        <wsdl:port name="TestMtomProviderPort" binding="tns:TestMtomBinding">
+            <soap:address location="http://localhost:9036/mime-test-provider"/>
+        </wsdl:port>
     </wsdl:service>
     <wsdl:service name="TestMtomJMSService">
         <wsdl:port name="TestMtomJMSPort" binding="tns:TestMtomBinding">