Repository: cxf Updated Branches: refs/heads/master 0bc9bb32b -> bd7babd65
CXF-6107 support unmarshaller aware xml stream reader CXF-6107 extended to support marshaller / unmarshaller aware event readers, event writers, stream writers Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/bd7babd6 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/bd7babd6 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/bd7babd6 Branch: refs/heads/master Commit: bd7babd656fc06f3e5839bf11e186ec12fdeb6fa Parents: 0bc9bb3 Author: Jason Pell <[email protected]> Authored: Mon Nov 17 18:42:41 2014 +1100 Committer: Jason Pell <[email protected]> Committed: Tue Nov 18 10:11:40 2014 +1100 ---------------------------------------------------------------------- .../org/apache/cxf/jaxb/JAXBEncoderDecoder.java | 26 ++++++ .../cxf/jaxb/MarshallerAwareXMLWriter.java | 29 +++++++ .../cxf/jaxb/UnmarshallerAwareXMLReader.java | 29 +++++++ .../cxf/jaxb/FixNamespacesXMLEventReader.java | 41 +++++++++ .../cxf/jaxb/FixNamespacesXMLEventWriter.java | 81 ++++++++++++++++++ .../cxf/jaxb/FixNamespacesXMLStreamReader.java | 41 +++++++++ .../cxf/jaxb/FixNamespacesXMLStreamWriter.java | 42 +++++++++ .../apache/cxf/jaxb/JAXBEncoderDecoderTest.java | 90 +++++++++++++++++--- 8 files changed, 367 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/bd7babd6/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java ---------------------------------------------------------------------- diff --git a/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java index bc70625..b7b0478 100644 --- a/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java +++ b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java @@ -608,12 +608,21 @@ public final class JAXBEncoderDecoder { private static void writeObject(Marshaller u, Object source, Object mObj) throws Fault, JAXBException { if (source instanceof XMLStreamWriter) { + // allows the XML Stream Writer to adjust it's behaviour based on the state of the unmarshaller + if (source instanceof MarshallerAwareXMLWriter) { + ((MarshallerAwareXMLWriter) source).setMarshaller(u); + } u.marshal(mObj, (XMLStreamWriter)source); } else if (source instanceof OutputStream) { u.marshal(mObj, (OutputStream)source); } else if (source instanceof Node) { u.marshal(mObj, (Node)source); } else if (source instanceof XMLEventWriter) { + // allows the XML Event Writer to adjust it's behaviour based on the state of the unmarshaller + if (source instanceof MarshallerAwareXMLWriter) { + ((MarshallerAwareXMLWriter) source).setMarshaller(u); + } + u.marshal(mObj, (XMLEventWriter)source); } else { throw new Fault(new Message("UNKNOWN_SOURCE", LOG, source.getClass().getName())); @@ -836,6 +845,12 @@ public final class JAXBEncoderDecoder { DepthXMLStreamReader dr = (DepthXMLStreamReader)source; XMLStreamReader reader = dr.getReader(); + + // allows the XML Stream Reader to adjust it's behaviour based on the state of the unmarshaller + if (reader instanceof UnmarshallerAwareXMLReader) { + ((UnmarshallerAwareXMLReader) reader).setUnmarshaller(u); + } + if (u.getSchema() != null) { //validating, but we may need more namespaces reader = findExtraNamespaces(reader); @@ -844,6 +859,12 @@ public final class JAXBEncoderDecoder { .unmarshal(dr.getReader()); } else if (source instanceof XMLStreamReader) { XMLStreamReader reader = (XMLStreamReader)source; + + // allows the XML Stream Reader to adjust it's behaviour based on the state of the unmarshaller + if (reader instanceof UnmarshallerAwareXMLReader) { + ((UnmarshallerAwareXMLReader) reader).setUnmarshaller(u); + } + if (u.getSchema() != null) { //validating, but we may need more namespaces reader = findExtraNamespaces(reader); @@ -851,6 +872,11 @@ public final class JAXBEncoderDecoder { obj = unmarshalWithClass ? u.unmarshal(reader, clazz) : u .unmarshal((XMLStreamReader)source); } else if (source instanceof XMLEventReader) { + // allows the XML Event Reader to adjust it's behaviour based on the state of the unmarshaller + if (source instanceof UnmarshallerAwareXMLReader) { + ((UnmarshallerAwareXMLReader) source).setUnmarshaller(u); + } + obj = unmarshalWithClass ? u.unmarshal((XMLEventReader)source, clazz) : u .unmarshal((XMLEventReader)source); } else if (source == null) { http://git-wip-us.apache.org/repos/asf/cxf/blob/bd7babd6/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/MarshallerAwareXMLWriter.java ---------------------------------------------------------------------- diff --git a/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/MarshallerAwareXMLWriter.java b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/MarshallerAwareXMLWriter.java new file mode 100644 index 0000000..ef6bce9 --- /dev/null +++ b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/MarshallerAwareXMLWriter.java @@ -0,0 +1,29 @@ +/** + * 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.jaxb; + +import javax.xml.bind.Marshaller; + +/* + * A XML Writer that adjusts it's behaviour based on the state of the marshaller. + */ +public interface MarshallerAwareXMLWriter { + void setMarshaller(Marshaller marshaller); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/bd7babd6/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/UnmarshallerAwareXMLReader.java ---------------------------------------------------------------------- diff --git a/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/UnmarshallerAwareXMLReader.java b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/UnmarshallerAwareXMLReader.java new file mode 100644 index 0000000..27ed146 --- /dev/null +++ b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/UnmarshallerAwareXMLReader.java @@ -0,0 +1,29 @@ +/** + * 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.jaxb; + +import javax.xml.bind.Unmarshaller; + +/* + * A XML Reader that adjusts it's behaviour based on the state of the unmarshaller. + */ +public interface UnmarshallerAwareXMLReader { + void setUnmarshaller(Unmarshaller unmarshaller); +} http://git-wip-us.apache.org/repos/asf/cxf/blob/bd7babd6/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLEventReader.java ---------------------------------------------------------------------- diff --git a/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLEventReader.java b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLEventReader.java new file mode 100644 index 0000000..9845ffc --- /dev/null +++ b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLEventReader.java @@ -0,0 +1,41 @@ +/** + * 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.jaxb; + +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.util.EventReaderDelegate; + +public class FixNamespacesXMLEventReader extends EventReaderDelegate implements UnmarshallerAwareXMLReader { + private Unmarshaller unmarshaller; + + public FixNamespacesXMLEventReader(final XMLEventReader delegate) { + super(delegate); + } + + @Override + public void setUnmarshaller(Unmarshaller unmarshaller) { + this.unmarshaller = unmarshaller; + } + + public Unmarshaller getUnmarshaller() { + return unmarshaller; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/bd7babd6/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLEventWriter.java ---------------------------------------------------------------------- diff --git a/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLEventWriter.java b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLEventWriter.java new file mode 100644 index 0000000..cae032b --- /dev/null +++ b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLEventWriter.java @@ -0,0 +1,81 @@ +/** + * 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.jaxb; + +import javax.xml.bind.Marshaller; +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; + +public class FixNamespacesXMLEventWriter implements XMLEventWriter, MarshallerAwareXMLWriter { + private final XMLEventWriter delegate; + private Marshaller marshaller; + + public FixNamespacesXMLEventWriter(XMLEventWriter delegate) { + this.delegate = delegate; + } + + public void flush() throws XMLStreamException { + delegate.flush(); + } + + public void close() throws XMLStreamException { + delegate.close(); + } + + public void add(XMLEvent event) throws XMLStreamException { + delegate.add(event); + } + + public void add(XMLEventReader reader) throws XMLStreamException { + delegate.add(reader); + } + + public String getPrefix(String uri) throws XMLStreamException { + return delegate.getPrefix(uri); + } + + public void setPrefix(String prefix, String uri) throws XMLStreamException { + delegate.setPrefix(prefix, uri); + } + + public void setDefaultNamespace(String uri) throws XMLStreamException { + delegate.setDefaultNamespace(uri); + } + + public void setNamespaceContext(NamespaceContext context) throws XMLStreamException { + delegate.setNamespaceContext(context); + } + + public NamespaceContext getNamespaceContext() { + return delegate.getNamespaceContext(); + } + + @Override + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + + public Marshaller getMarshaller() { + return marshaller; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/bd7babd6/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLStreamReader.java ---------------------------------------------------------------------- diff --git a/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLStreamReader.java b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLStreamReader.java new file mode 100644 index 0000000..200f9cf --- /dev/null +++ b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLStreamReader.java @@ -0,0 +1,41 @@ +/** + * 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.jaxb; + +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.StreamReaderDelegate; + +public class FixNamespacesXMLStreamReader extends StreamReaderDelegate implements UnmarshallerAwareXMLReader { + private Unmarshaller unmarshaller; + + public FixNamespacesXMLStreamReader(final XMLStreamReader delegate) { + super(delegate); + } + + @Override + public void setUnmarshaller(Unmarshaller unmarshaller) { + this.unmarshaller = unmarshaller; + } + + public Unmarshaller getUnmarshaller() { + return unmarshaller; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/bd7babd6/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLStreamWriter.java ---------------------------------------------------------------------- diff --git a/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLStreamWriter.java b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLStreamWriter.java new file mode 100644 index 0000000..10c5a18 --- /dev/null +++ b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/FixNamespacesXMLStreamWriter.java @@ -0,0 +1,42 @@ +/** + * 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.jaxb; + +import javax.xml.bind.Marshaller; +import javax.xml.stream.XMLStreamWriter; + +import org.codehaus.stax2.util.StreamWriterDelegate; + +public class FixNamespacesXMLStreamWriter extends StreamWriterDelegate implements MarshallerAwareXMLWriter { + private Marshaller marshaller; + + public FixNamespacesXMLStreamWriter(final XMLStreamWriter delegate) { + super(delegate); + } + + @Override + public void setMarshaller(Marshaller marshaller) { + this.marshaller = marshaller; + } + + public Marshaller getMarshaller() { + return marshaller; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/bd7babd6/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBEncoderDecoderTest.java ---------------------------------------------------------------------- diff --git a/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBEncoderDecoderTest.java b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBEncoderDecoderTest.java index c4b89e7..d4cabb9 100644 --- a/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBEncoderDecoderTest.java +++ b/rt/databinding/jaxb/src/test/java/org/apache/cxf/jaxb/JAXBEncoderDecoderTest.java @@ -66,7 +66,6 @@ import org.apache.cxf.staxutils.StaxUtils; import org.apache.hello_world_soap_http.types.GreetMe; import org.apache.hello_world_soap_http.types.GreetMeResponse; import org.apache.hello_world_soap_http.types.StringStruct; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -256,7 +255,7 @@ public class JAXBEncoderDecoderTest extends Assert { } @Test - public void testMarshallIntoStax() throws Exception { + public void testMarshallIntoStaxStreamWriter() throws Exception { GreetMe obj = new GreetMe(); obj.setRequestType("Hello"); QName elName = new QName(wrapperAnnotation.targetNamespace(), @@ -268,11 +267,50 @@ public class JAXBEncoderDecoderTest extends Assert { ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMLOutputFactory opFactory = XMLOutputFactory.newInstance(); opFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); - XMLEventWriter writer = opFactory.createXMLEventWriter(baos); - + FixNamespacesXMLStreamWriter writer = new FixNamespacesXMLStreamWriter(opFactory.createXMLStreamWriter(baos)); + + assertNull(writer.getMarshaller()); + + Marshaller m = context.createMarshaller(); + JAXBEncoderDecoder.marshall(m, obj, part, writer); + assertEquals(m, writer.getMarshaller()); + writer.flush(); + writer.close(); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + XMLInputFactory ipFactory = XMLInputFactory.newInstance(); + XMLEventReader reader = ipFactory.createXMLEventReader(bais); + + Unmarshaller um = context.createUnmarshaller(); + Object val = um.unmarshal(reader, GreetMe.class); + assertTrue(val instanceof JAXBElement); + val = ((JAXBElement<?>)val).getValue(); + assertTrue(val instanceof GreetMe); + assertEquals(obj.getRequestType(), + ((GreetMe)val).getRequestType()); + } + + @Test + public void testMarshallIntoStaxEventWriter() throws Exception { + GreetMe obj = new GreetMe(); + obj.setRequestType("Hello"); + QName elName = new QName(wrapperAnnotation.targetNamespace(), + wrapperAnnotation.localName()); + MessagePartInfo part = new MessagePartInfo(elName, null); + part.setElement(true); + part.setElementQName(elName); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + XMLOutputFactory opFactory = XMLOutputFactory.newInstance(); + opFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); + FixNamespacesXMLEventWriter writer = new FixNamespacesXMLEventWriter(opFactory.createXMLEventWriter(baos)); + assertNull(writer.getMarshaller()); + //STARTDOCUMENT/ENDDOCUMENT is not required - //writer.add(eFactory.createStartDocument("utf-8", "1.0")); - JAXBEncoderDecoder.marshall(context.createMarshaller(), obj, part, writer); + //writer.add(eFactory.createStartDocument("utf-8", "1.0")); + Marshaller m = context.createMarshaller(); + JAXBEncoderDecoder.marshall(m, obj, part, writer); + assertEquals(m, writer.getMarshaller()); //writer.add(eFactory.createEndDocument()); writer.flush(); writer.close(); @@ -293,24 +331,52 @@ public class JAXBEncoderDecoderTest extends Assert { } @Test - public void testUnmarshallFromStax() throws Exception { + public void testUnmarshallFromStaxStreamReader() throws Exception { QName elName = new QName(wrapperAnnotation.targetNamespace(), wrapperAnnotation.localName()); MessagePartInfo part = new MessagePartInfo(elName, null); InputStream is = getClass().getResourceAsStream("resources/GreetMeDocLiteralReq.xml"); XMLInputFactory factory = XMLInputFactory.newInstance(); - XMLStreamReader reader = - factory.createXMLStreamReader(is); - + XMLStreamReader reader = factory.createXMLStreamReader(is); + QName[] tags = {SOAP_ENV, SOAP_BODY}; StaxStreamFilter filter = new StaxStreamFilter(tags); - reader = factory.createFilteredReader(reader, filter); + FixNamespacesXMLStreamReader filteredReader = new FixNamespacesXMLStreamReader( + factory.createFilteredReader(reader, filter)); + assertNull(filteredReader.getUnmarshaller()); + //Remove START_DOCUMENT & START_ELEMENT pertaining to Envelope and Body Tags. part.setTypeClass(GreetMe.class); - Object val = JAXBEncoderDecoder.unmarshall(context.createUnmarshaller(), reader, part, true); + Unmarshaller um = context.createUnmarshaller(); + Object val = JAXBEncoderDecoder.unmarshall(um, filteredReader, part, true); + assertEquals(um, filteredReader.getUnmarshaller()); + assertNotNull(val); + assertTrue(val instanceof GreetMe); + assertEquals("TestSOAPInputPMessage", + ((GreetMe)val).getRequestType()); + + is.close(); + } + + @Test + public void testUnmarshallFromStaxEventReader() throws Exception { + QName elName = new QName(wrapperAnnotation.targetNamespace(), + wrapperAnnotation.localName()); + MessagePartInfo part = new MessagePartInfo(elName, null); + + InputStream is = getClass().getResourceAsStream("resources/GreetMeDocLiteralReq.xml"); + XMLInputFactory factory = XMLInputFactory.newInstance(); + FixNamespacesXMLEventReader reader = new FixNamespacesXMLEventReader(factory.createXMLEventReader(is)); + + assertNull(reader.getUnmarshaller()); + + part.setTypeClass(GreetMe.class); + Unmarshaller um = context.createUnmarshaller(); + Object val = JAXBEncoderDecoder.unmarshall(um, reader, part, true); + assertEquals(um, reader.getUnmarshaller()); assertNotNull(val); assertTrue(val instanceof GreetMe); assertEquals("TestSOAPInputPMessage",
