/** * 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.staxutils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.stream.events.XMLEvent; import javax.xml.transform.OutputKeys; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.apache.cxf.helpers.DOMUtils; import org.junit.Assert; import org.junit.Test; import static org.hamcrest.core.IsEqual.equalTo; public class StaxUtilsTest extends Assert { @Test public void testFactoryCreation() { XMLStreamReader reader = StaxUtils.createXMLStreamReader(getTestStream("./resources/amazon.xml")); assertTrue(reader != null); } private InputStream getTestStream(String resource) { return getClass().getResourceAsStream(resource); } @Test public void testCommentNode() throws Exception { //CXF-3034 Document document = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); Element root = document.createElementNS("urn:test", "root"); root.appendChild(document.createComment("test comment")); StaxUtils.copy(StaxUtils.createXMLStreamReader(root), StaxUtils.createXMLStreamWriter(System.out)); } @Test public void testToNextElement() { String soapMessage = "./resources/sayHiRpcLiteralReq.xml"; XMLStreamReader r = StaxUtils.createXMLStreamReader(getTestStream(soapMessage)); DepthXMLStreamReader reader = new DepthXMLStreamReader(r); assertTrue(StaxUtils.toNextElement(reader)); assertEquals("Envelope", reader.getLocalName()); StaxUtils.nextEvent(reader); assertTrue(StaxUtils.toNextElement(reader)); assertEquals("Body", reader.getLocalName()); } @Test public void testToNextTag() throws Exception { String soapMessage = "./resources/headerSoapReq.xml"; XMLStreamReader r = StaxUtils.createXMLStreamReader(getTestStream(soapMessage)); DepthXMLStreamReader reader = new DepthXMLStreamReader(r); reader.nextTag(); StaxUtils.toNextTag(reader, new QName("http://schemas.xmlsoap.org/soap/envelope/", "Body")); assertEquals("Body", reader.getLocalName()); } @Test public void testCopy() throws Exception { // do the stream copying String soapMessage = "./resources/headerSoapReq.xml"; ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMLStreamReader reader = StaxUtils.createXMLStreamReader(getTestStream(soapMessage)); XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(baos); StaxUtils.copy(reader, writer); writer.flush(); baos.flush(); // write output to a string String output = baos.toString(); baos.close(); // re-read the input xml doc to a string InputStreamReader inputStreamReader = new InputStreamReader(getTestStream(soapMessage)); StringWriter stringWriter = new StringWriter(); char[] buffer = new char[4096]; int n = 0; n = inputStreamReader.read(buffer); while (n > 0) { stringWriter.write(buffer, 0, n); n = inputStreamReader.read(buffer); } String input = stringWriter.toString(); stringWriter.close(); // seach for the first begin of "<soap:Envelope" to escape the apache licenses header int beginIndex = input.indexOf("<soap:Envelope"); input = input.substring(beginIndex); beginIndex = output.indexOf("<soap:Envelope"); output = output.substring(beginIndex); output = output.replaceAll("\r\n", "\n"); input = input.replaceAll("\r\n", "\n"); // compare the input and output string assertEquals(input, output); } @Test public void testCXF2468() throws Exception { Document doc = DOMUtils.newDocument(); doc.appendChild(doc.createElementNS("http://blah.org/", "blah")); Element foo = doc.createElementNS("http://blah.org/", "foo"); Attr attr = doc.createAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:nil"); attr.setValue("true"); foo.setAttributeNodeNS(attr); doc.getDocumentElement().appendChild(foo); XMLStreamReader sreader = StaxUtils.createXMLStreamReader(doc); StringWriter sw = new StringWriter(); XMLStreamWriter swriter = StaxUtils.createXMLStreamWriter(sw); StaxUtils.copy(sreader, swriter, true); swriter.flush(); assertTrue("No xsi namespace: " + sw.toString(), sw.toString().contains("XMLSchema-instance")); } @Test public void testNonNamespaceAwareParser() throws Exception { String xml = "<blah xmlns=\"http://blah.org/\" xmlns:snarf=\"http://snarf.org\">" + "<foo snarf:blop=\"blop\">foo</foo></blah>"; StringReader reader = new StringReader(xml); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(false); dbf.setValidating(false); Document doc = dbf.newDocumentBuilder().parse(new InputSource(reader)); Source source = new DOMSource(doc); dbf.setNamespaceAware(true); reader = new StringReader(xml); Document docNs = dbf.newDocumentBuilder().parse(new InputSource(reader)); Source sourceNs = new DOMSource(docNs); XMLStreamReader sreader = StaxUtils.createXMLStreamReader(source); StringWriter sw = new StringWriter(); XMLStreamWriter swriter = StaxUtils.createXMLStreamWriter(sw); //should not throw an exception StaxUtils.copy(sreader, swriter); swriter.flush(); swriter.close(); String output = sw.toString(); assertTrue(output.contains("blah")); assertTrue(output.contains("foo")); assertTrue(output.contains("snarf")); assertTrue(output.contains("blop")); sreader = StaxUtils.createXMLStreamReader(sourceNs); sw = new StringWriter(); swriter = StaxUtils.createXMLStreamWriter(sw); //should not throw an exception StaxUtils.copy(sreader, swriter); swriter.flush(); swriter.close(); output = sw.toString(); assertTrue(output.contains("blah")); assertTrue(output.contains("foo")); assertTrue(output.contains("snarf")); assertTrue(output.contains("blop")); sreader = StaxUtils.createXMLStreamReader(source); ByteArrayOutputStream bout = new ByteArrayOutputStream(); swriter = StaxUtils.createXMLStreamWriter(bout); StaxUtils.copy(sreader, swriter); swriter.flush(); swriter.close(); output = bout.toString(); assertTrue(output.contains("blah")); assertTrue(output.contains("foo")); assertTrue(output.contains("snarf")); assertTrue(output.contains("blop")); } @Test public void testEmptyNamespace() throws Exception { String testString = "<ns1:a xmlns:ns1=\"http://www.apache.org/\"><s1 xmlns=\"\">" + "abc</s1><s2 xmlns=\"\">def</s2></ns1:a>"; cycleString(testString); testString = "<a xmlns=\"http://www.apache.org/\"><s1 xmlns=\"\">" + "abc</s1><s2 xmlns=\"\">def</s2></a>"; cycleString(testString); testString = "<a xmlns=\"http://www.apache.org/\"><s1 xmlns=\"\">" + "abc</s1><s2>def</s2></a>"; cycleString(testString); testString = "<ns1:a xmlns:ns1=\"http://www.apache.org/\"><s1>" + "abc</s1><s2 xmlns=\"\">def</s2></ns1:a>"; cycleString(testString); } private void cycleString(String s) throws Exception { StringReader reader = new StringReader(s); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new InputSource(reader)); String orig = StaxUtils.toString(doc.getDocumentElement()); StringWriter sw = new StringWriter(); XMLStreamWriter swriter = StaxUtils.createXMLStreamWriter(sw); //should not throw an exception StaxUtils.writeDocument(doc, swriter, false, true); swriter.flush(); swriter.close(); String output = sw.toString(); assertEquals(s, output); W3CDOMStreamWriter domwriter = new W3CDOMStreamWriter(); StaxUtils.writeDocument(doc, domwriter, false, true); output = StaxUtils.toString(domwriter.getDocument().getDocumentElement()); assertEquals(orig, output); } @Test public void testRootPI() throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(getTestStream("./resources/rootMaterialTest.xml")); StringWriter sw = new StringWriter(); XMLStreamWriter swriter = StaxUtils.createXMLStreamWriter(sw); StaxUtils.writeDocument(doc, swriter, true, false); swriter.flush(); swriter.close(); String output = sw.toString(); assertTrue(output.contains("<?pi in='the sky'?>")); assertTrue(output.contains("<?e excl='gads'?>")); } @Test public void testRootPInoProlog() throws Exception { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(getTestStream("./resources/rootMaterialTest.xml")); StringWriter sw = new StringWriter(); XMLStreamWriter swriter = StaxUtils.createXMLStreamWriter(sw); StaxUtils.writeDocument(doc, swriter, false, false); swriter.flush(); swriter.close(); String output = sw.toString(); assertFalse(output.contains("<?pi in='the sky'?>")); assertFalse(output.contains("<?e excl='gads'?>")); } @Test public void testDefaultPrefix() throws Exception { String soapMessage = "./resources/AddRequest.xml"; ByteArrayOutputStream baos = new ByteArrayOutputStream(); XMLStreamReader reader = StaxUtils.createXMLStreamReader(getTestStream(soapMessage)); XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(baos); StaxSource staxSource = new StaxSource(reader); StaxUtils.copy(staxSource, writer); writer.flush(); baos.flush(); } @Test public void testDefaultPrefixInRootElementWithIdentityTransformer() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); String xml = "<root xmlns=\"urn:org.apache.cxf:test\">Text</root>"; StringReader stringReader = new StringReader(xml); StreamSource source = new StreamSource(stringReader); XMLStreamReader reader = StaxUtils.createXMLStreamReader(source); XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(baos); StaxSource staxSource = new StaxSource(reader); TransformerFactory transformerFactory = TransformerFactory.newInstance(); transformerFactory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.transform(staxSource, new StreamResult(baos)); writer.flush(); baos.flush(); assertThat(new String(baos.toByteArray()), equalTo(xml)); } @Test public void testDefaultPrefixInRootElementWithXalanCopyTransformer() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); String xml = "<root xmlns=\"urn:org.apache.cxf:test\">Text</root>"; StringReader stringReader = new StringReader(xml); //StreamSource source = new StreamSource(stringReader); XMLStreamReader reader = StaxUtils.createXMLStreamReader(stringReader); XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(baos); StaxSource staxSource = new StaxSource(reader); TransformerFactory transformerFactory = TransformerFactory.newInstance(); transformerFactory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true); Document doc = StaxUtils.read(getTestStream("./resources/copy.xsl")); Transformer transformer = transformerFactory.newTransformer(new DOMSource(doc)); //System.out.println("Used transformer: " + transformer.getClass().getName()); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.transform(staxSource, new StreamResult(baos)); writer.flush(); baos.flush(); assertThat(new String(baos.toByteArray()), equalTo(xml)); } @Test public void testDefaultPrefixInRootElementWithJDKInternalCopyTransformer() throws Exception { TransformerFactory trf = null; try { trf = TransformerFactory .newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", null); trf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true); ByteArrayOutputStream baos = new ByteArrayOutputStream(); String xml = "<root xmlns=\"urn:org.apache.cxf:test\">Text</root>"; StringReader stringReader = new StringReader(xml); StreamSource source = new StreamSource(stringReader); XMLStreamReader reader = StaxUtils.createXMLStreamReader(source); XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(baos); StaxSource staxSource = new StaxSource(reader); Document doc = StaxUtils.read(getTestStream("./resources/copy.xsl")); Transformer transformer = trf.newTransformer(new DOMSource(doc)); //System.out.println("Used transformer: " + transformer.getClass().getName()); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.transform(staxSource, new StreamResult(baos)); writer.flush(); baos.flush(); assertThat(new String(baos.toByteArray()), equalTo(xml)); } catch (Throwable throwable) { // ignore on non Sun/Oracle JDK return; } } @Test public void testCXF3193() throws Exception { String testString = "<a:elem1 xmlns:a=\"test\" xmlns:b=\"test\" a:attr1=\"value\"/>"; CachingXmlEventWriter writer = new CachingXmlEventWriter(); StaxUtils.copy(StaxUtils.createXMLStreamReader(new StringReader(testString)), writer); StringWriter swriter = new StringWriter(); XMLStreamWriter xwriter = StaxUtils.createXMLStreamWriter(swriter); for (XMLEvent event : writer.getEvents()) { StaxUtils.writeEvent(event, xwriter); } xwriter.flush(); String s = swriter.toString(); int idx = s.indexOf("xmlns:a"); idx = s.indexOf("xmlns:a", idx + 1); assertEquals(-1, idx); } @Test public void testCopyWithEmptyNamespace() throws Exception { StringBuilder in = new StringBuilder(); in.append("<foo xmlns=\"http://example.com/\">"); in.append("<bar xmlns=\"\"/>"); in.append("</foo>"); XMLStreamReader reader = StaxUtils.createXMLStreamReader( new ByteArrayInputStream(in.toString().getBytes())); Writer out = new StringWriter(); XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(out); StaxUtils.copy(reader, writer); writer.close(); assertEquals(in.toString(), out.toString()); } @Test public void testQName() throws Exception { StringBuilder in = new StringBuilder(); in.append("<f:foo xmlns:f=\"http://example.com/\">"); in.append("<bar>f:Bar</bar>"); in.append("<bar> f:Bar </bar>"); in.append("<bar>x:Bar</bar>"); in.append("</f:foo>"); XMLStreamReader reader = StaxUtils.createXMLStreamReader( new ByteArrayInputStream(in.toString().getBytes())); QName qname = new QName("http://example.com/", "Bar"); assertEquals(XMLStreamReader.START_ELEMENT, reader.next()); assertEquals(XMLStreamReader.START_ELEMENT, reader.next()); // first bar assertEquals(qname, StaxUtils.readQName(reader)); assertEquals(XMLStreamReader.START_ELEMENT, reader.next()); // second bar assertEquals(qname, StaxUtils.readQName(reader)); assertEquals(XMLStreamReader.START_ELEMENT, reader.next()); // third bar try { StaxUtils.readQName(reader); fail("invalid qname in mapping"); } catch (Exception e) { // ignore } } @Test public void testCopyFromTheMiddle() throws Exception { String innerXml = "<inner>\n" + "<body>body text here</body>\n" + "</inner>\n"; String xml = "<outer>\n" + innerXml + "</outer>"; StringReader reader = new StringReader(xml); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); dbf.setValidating(false); Document doc = dbf.newDocumentBuilder().parse(new InputSource(reader)); Source source = new DOMSource(doc); // Skip <outer> XMLStreamReader sreader = StaxUtils.createXMLStreamReader(source); while (!"inner".equals(sreader.getLocalName())) { sreader.next(); } StringWriter sw = new StringWriter(); XMLStreamWriter swriter = StaxUtils.createXMLStreamWriter(sw); StaxUtils.copy(sreader, swriter, true, true); swriter.flush(); swriter.close(); //System.out.println(innerXml); //System.out.println(sw.toString()); assertEquals(innerXml, sw.toString()); } }