diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/support/AxiomUtils.java b/core/src/main/java/org/springframework/ws/soap/axiom/support/AxiomUtils.java index ececbeb9..06e39cbd 100644 --- a/core/src/main/java/org/springframework/ws/soap/axiom/support/AxiomUtils.java +++ b/core/src/main/java/org/springframework/ws/soap/axiom/support/AxiomUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ package org.springframework.ws.soap.axiom.support; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.util.Iterator; import java.util.Locale; import javax.xml.namespace.QName; @@ -164,7 +166,12 @@ public abstract class AxiomUtils { StAXSOAPModelBuilder stAXSOAPModelBuilder = new StAXSOAPModelBuilder(XMLInputFactory.newInstance().createXMLStreamReader(bis), null); - return stAXSOAPModelBuilder.getSOAPEnvelope(); + SOAPEnvelope envelope = stAXSOAPModelBuilder.getSOAPEnvelope(); + + // Necessary to build a correct Axiom tree, see SWS-483 + envelope.serialize(new NullOutputStream()); + + return envelope; } catch (Exception ex) { IllegalArgumentException iaex = @@ -174,4 +181,17 @@ public abstract class AxiomUtils { } } + /** OutputStream that does nothing. */ + private static class NullOutputStream extends OutputStream { + + public void write(int b) throws IOException { + } + + public void write(byte[] b) throws IOException { + } + + public void write(byte[] b, int off, int len) throws IOException { + } + } + } diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java index 19fe2df9..7fbd5ba8 100755 --- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java +++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.ws.soap.security.wss4j; +import java.io.ByteArrayOutputStream; import java.util.Iterator; import java.util.Properties; import javax.xml.namespace.QName; @@ -79,4 +80,40 @@ public abstract class Wss4jMessageInterceptorHeaderTestCase extends Wss4jTestCas // expected } } + + public void testPreserveCustomHeaders() throws Exception { + interceptor.setSecurementActions("UsernameToken"); + interceptor.setSecurementUsername("Bert"); + interceptor.setSecurementPassword("Ernie"); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + SoapMessage message = loadMessage("customHeader-soap.xml"); + MessageContext messageContext = new DefaultMessageContext(message, getMessageFactory()); + message.writeTo(os); + String document = os.toString("UTF-8"); + assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1", + document); + assertXpathNotExists("Header 2 exist", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2", document); + + interceptor.secureMessage(message, messageContext); + + SoapHeaderElement element = message.getSoapHeader().addHeaderElement(new QName("http://test", "header2")); + element.setText("test2"); + + os = new ByteArrayOutputStream(); + message.writeTo(os); + document = os.toString("UTF-8"); + assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1", + document); + assertXpathEvaluatesTo("Header 2 does not exist", "test2", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2", + document); + + os = new ByteArrayOutputStream(); + message.writeTo(os); + document = os.toString("UTF-8"); + assertXpathEvaluatesTo("Header 1 does not exist", "test1", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header1", + document); + assertXpathEvaluatesTo("Header 2 does not exist", "test2", "/SOAP-ENV:Envelope/SOAP-ENV:Header/test:header2", + document); + } } diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jTestCase.java index c4686818..830bd5e8 100755 --- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jTestCase.java +++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +16,13 @@ package org.springframework.ws.soap.security.wss4j; import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; +import java.util.Properties; import javax.xml.soap.MessageFactory; import javax.xml.soap.MimeHeaders; import javax.xml.soap.SOAPMessage; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.dom.DOMSource; import junit.framework.TestCase; import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder; @@ -41,8 +41,8 @@ import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory; import org.springframework.ws.soap.axiom.support.AxiomUtils; import org.springframework.ws.soap.saaj.SaajSoapMessage; import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; -import org.springframework.xml.xpath.XPathExpression; -import org.springframework.xml.xpath.XPathExpressionFactory; +import org.springframework.xml.transform.StringSource; +import org.springframework.xml.xpath.Jaxp13XPathTemplate; public abstract class Wss4jTestCase extends TestCase { @@ -52,22 +52,26 @@ public abstract class Wss4jTestCase extends TestCase { protected final boolean saajTest = this.getClass().getSimpleName().startsWith("Saaj"); - protected Map namespaces; + protected Jaxp13XPathTemplate xpathTemplate = new Jaxp13XPathTemplate(); protected final void setUp() throws Exception { if (!axiomTest && !saajTest) { throw new IllegalArgumentException("test class name must statrt with either Axiom or Saaj"); } messageFactory = MessageFactory.newInstance(); - namespaces = new HashMap(); - namespaces.put("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"); - namespaces.put("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); - namespaces.put("ds", "http://www.w3.org/2000/09/xmldsig#"); - namespaces.put("xenc", "http://www.w3.org/2001/04/xmlenc#"); + Properties namespaces = new Properties(); + namespaces.setProperty("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"); + namespaces.setProperty("wsse", + "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); + namespaces.setProperty("ds", "http://www.w3.org/2000/09/xmldsig#"); + namespaces.setProperty("xenc", "http://www.w3.org/2001/04/xmlenc#"); // namespaces.put("wsse11", "http://docs.oasis-open.org/wss/2005/xx/oasis-2005xx-wss-wssecurity-secext-1.1.xsd"); - namespaces.put("wsse11", "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"); - namespaces.put("echo", "http://www.springframework.org/spring-ws/samples/echo"); - namespaces.put("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); + namespaces.setProperty("wsse11", "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"); + namespaces.setProperty("echo", "http://www.springframework.org/spring-ws/samples/echo"); + namespaces.setProperty("wsu", + "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); + namespaces.setProperty("test", "http://test"); + xpathTemplate.setNamespaces(namespaces); onSetup(); } @@ -75,20 +79,30 @@ public abstract class Wss4jTestCase extends TestCase { String expectedValue, String xpathExpression, Document document) { - XPathExpression expression = XPathExpressionFactory.createXPathExpression(xpathExpression, namespaces); - String actualValue = expression.evaluateAsString(document); + String actualValue = xpathTemplate.evaluateAsString(xpathExpression, new DOMSource(document)); + assertEquals(message, expectedValue, actualValue); + } + + protected void assertXpathEvaluatesTo(String message, + String expectedValue, + String xpathExpression, + String document) { + String actualValue = xpathTemplate.evaluateAsString(xpathExpression, new StringSource(document)); assertEquals(message, expectedValue, actualValue); } protected void assertXpathExists(String message, String xpathExpression, Document document) { - XPathExpression expression = XPathExpressionFactory.createXPathExpression(xpathExpression, namespaces); - Node node = expression.evaluateAsNode(document); + Node node = xpathTemplate.evaluateAsNode(xpathExpression, new DOMSource(document)); assertNotNull(message, node); } protected void assertXpathNotExists(String message, String xpathExpression, Document document) { - XPathExpression expression = XPathExpressionFactory.createXPathExpression(xpathExpression, namespaces); - Node node = expression.evaluateAsNode(document); + Node node = xpathTemplate.evaluateAsNode(xpathExpression, new DOMSource(document)); + assertNull(message, node); + } + + protected void assertXpathNotExists(String message, String xpathExpression, String document) { + Node node = xpathTemplate.evaluateAsNode(xpathExpression, new StringSource(document)); assertNull(message, node); } diff --git a/security/src/test/resources/org/springframework/ws/soap/security/wss4j/customHeader-soap.xml b/security/src/test/resources/org/springframework/ws/soap/security/wss4j/customHeader-soap.xml new file mode 100644 index 00000000..3c56bb6f --- /dev/null +++ b/security/src/test/resources/org/springframework/ws/soap/security/wss4j/customHeader-soap.xml @@ -0,0 +1,9 @@ + + + + test1 + + + QQQ + +