You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cxf.apache.org by Daniel Kulp <dk...@apache.org> on 2017/03/07 13:09:56 UTC

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

Freeman,

I believe this commit would introduce CXF-7185 for the source data binding…. Can you adjust accordingly?   You can see what was done for JAXB.

Thanks!
Dan



> On Mar 7, 2017, at 3:44 AM, ffang@apache.org wrote:
> 
> Repository: cxf
> Updated Branches:
>  refs/heads/master 09fb22b25 -> 08c9194ce
> 
> 
> [CXF-7269]schemavalidate failed when use mtom and Provider
> 
> 
> Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
> Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/08c9194c
> Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/08c9194c
> Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/08c9194c
> 
> Branch: refs/heads/master
> Commit: 08c9194ce2c567ebfe59f59ee628b1197d90fd43
> Parents: 09fb22b
> Author: Freeman Fang <fr...@gmail.com>
> Authored: Tue Mar 7 16:44:03 2017 +0800
> Committer: Freeman Fang <fr...@gmail.com>
> Committed: Tue Mar 7 16:44:03 2017 +0800
> 
> ----------------------------------------------------------------------
> .../databinding/source/XMLStreamDataWriter.java | 111 ++++++++++++++++-
> .../cxf/systest/mtom/ClientMtomXopTest.java     | 119 ++++++++++++++++++-
> testutils/pom.xml                               |   4 +
> .../cxf/mtom_xop/TestMtomProviderImpl.java      | 104 ++++++++++++++++
> testutils/src/main/resources/wsdl/mtom_xop.wsdl |   3 +
> 5 files changed, 335 insertions(+), 6 deletions(-)
> ----------------------------------------------------------------------
> 
> 
> http://git-wip-us.apache.org/repos/asf/cxf/blob/08c9194c/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 8bd9b71..afbcca0 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,10 +51,16 @@ 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) {
> @@ -152,5 +172,90 @@ 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/08c9194c/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 184bd64..1616b48 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
> @@ -38,10 +38,10 @@ import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
> import org.apache.cxf.endpoint.Client;
> import org.apache.cxf.endpoint.ClientImpl;
> import org.apache.cxf.endpoint.Endpoint;
> -import org.apache.cxf.ext.logging.LoggingInInterceptor;
> -import org.apache.cxf.ext.logging.LoggingOutInterceptor;
> import org.apache.cxf.frontend.ClientProxy;
> import org.apache.cxf.helpers.IOUtils;
> +import org.apache.cxf.interceptor.LoggingInInterceptor;
> +import org.apache.cxf.interceptor.LoggingOutInterceptor;
> import org.apache.cxf.jaxws.EndpointImpl;
> import org.apache.cxf.jaxws.JaxWsClientProxy;
> import org.apache.cxf.jaxws.binding.soap.SOAPBindingImpl;
> @@ -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/08c9194c/testutils/pom.xml
> ----------------------------------------------------------------------
> diff --git a/testutils/pom.xml b/testutils/pom.xml
> index bd481ad..fb611ab 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/08c9194c/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/08c9194c/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">
> 

-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com


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

Posted by Freeman Fang <fr...@gmail.com>.
Sure, done.

Cheers
-------------
Freeman(Yue) Fang

Red Hat, Inc. 
FuseSource is now part of Red Hat



> On Mar 7, 2017, at 9:09 PM, Daniel Kulp <dk...@apache.org> wrote:
> 
> 
> Freeman,
> 
> I believe this commit would introduce CXF-7185 for the source data binding…. Can you adjust accordingly?   You can see what was done for JAXB.
> 
> Thanks!
> Dan
> 
> 
> 
>> On Mar 7, 2017, at 3:44 AM, ffang@apache.org wrote:
>> 
>> Repository: cxf
>> Updated Branches:
>> refs/heads/master 09fb22b25 -> 08c9194ce
>> 
>> 
>> [CXF-7269]schemavalidate failed when use mtom and Provider
>> 
>> 
>> Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
>> Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/08c9194c
>> Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/08c9194c
>> Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/08c9194c
>> 
>> Branch: refs/heads/master
>> Commit: 08c9194ce2c567ebfe59f59ee628b1197d90fd43
>> Parents: 09fb22b
>> Author: Freeman Fang <fr...@gmail.com>
>> Authored: Tue Mar 7 16:44:03 2017 +0800
>> Committer: Freeman Fang <fr...@gmail.com>
>> Committed: Tue Mar 7 16:44:03 2017 +0800
>> 
>> ----------------------------------------------------------------------
>> .../databinding/source/XMLStreamDataWriter.java | 111 ++++++++++++++++-
>> .../cxf/systest/mtom/ClientMtomXopTest.java     | 119 ++++++++++++++++++-
>> testutils/pom.xml                               |   4 +
>> .../cxf/mtom_xop/TestMtomProviderImpl.java      | 104 ++++++++++++++++
>> testutils/src/main/resources/wsdl/mtom_xop.wsdl |   3 +
>> 5 files changed, 335 insertions(+), 6 deletions(-)
>> ----------------------------------------------------------------------
>> 
>> 
>> http://git-wip-us.apache.org/repos/asf/cxf/blob/08c9194c/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 8bd9b71..afbcca0 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,10 +51,16 @@ 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) {
>> @@ -152,5 +172,90 @@ 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/08c9194c/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 184bd64..1616b48 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
>> @@ -38,10 +38,10 @@ import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
>> import org.apache.cxf.endpoint.Client;
>> import org.apache.cxf.endpoint.ClientImpl;
>> import org.apache.cxf.endpoint.Endpoint;
>> -import org.apache.cxf.ext.logging.LoggingInInterceptor;
>> -import org.apache.cxf.ext.logging.LoggingOutInterceptor;
>> import org.apache.cxf.frontend.ClientProxy;
>> import org.apache.cxf.helpers.IOUtils;
>> +import org.apache.cxf.interceptor.LoggingInInterceptor;
>> +import org.apache.cxf.interceptor.LoggingOutInterceptor;
>> import org.apache.cxf.jaxws.EndpointImpl;
>> import org.apache.cxf.jaxws.JaxWsClientProxy;
>> import org.apache.cxf.jaxws.binding.soap.SOAPBindingImpl;
>> @@ -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/08c9194c/testutils/pom.xml
>> ----------------------------------------------------------------------
>> diff --git a/testutils/pom.xml b/testutils/pom.xml
>> index bd481ad..fb611ab 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/08c9194c/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/08c9194c/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">
>> 
> 
> -- 
> Daniel Kulp
> dkulp@apache.org - http://dankulp.com/blog
> Talend Community Coder - http://coders.talend.com
>