diff --git a/core/src/main/java/org/springframework/ws/soap/SoapMessage.java b/core/src/main/java/org/springframework/ws/soap/SoapMessage.java index 3758f650..020b77cd 100644 --- a/core/src/main/java/org/springframework/ws/soap/SoapMessage.java +++ b/core/src/main/java/org/springframework/ws/soap/SoapMessage.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 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. @@ -19,6 +19,8 @@ package org.springframework.ws.soap; import org.springframework.ws.FaultAwareWebServiceMessage; import org.springframework.ws.mime.MimeMessage; +import org.w3c.dom.Document; + /** * Represents an abstraction for SOAP messages, providing access to a SOAP Envelope. The contents of the SOAP body can * be retrieved by getPayloadSource() and getPayloadResult() on @@ -74,4 +76,20 @@ public interface SoapMessage extends MimeMessage, FaultAwareWebServiceMessage { */ SoapVersion getVersion(); + /** + * Returns this message as a {@link Document}. + * + * Depending on the underlying implementation, this Document may be 'live' or not. + * @return this soap message as a DOM document + */ + Document getDocument(); + + /** + * Returns this message as a {@link Document}. + * + * Depending on the underlying implementation, this Document may be 'live' or not. + * @return this soap message as a DOM document + */ + void setDocument(Document document); + } diff --git a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java index b0f6b356..f00224ad 100644 --- a/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java +++ b/core/src/main/java/org/springframework/ws/soap/axiom/AxiomSoapMessage.java @@ -31,6 +31,7 @@ import org.springframework.ws.soap.AbstractSoapMessage; import org.springframework.ws.soap.SoapEnvelope; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.SoapVersion; +import org.springframework.ws.soap.axiom.support.AxiomUtils; import org.springframework.ws.soap.support.SoapUtils; import org.springframework.ws.stream.StreamingPayload; import org.springframework.ws.stream.StreamingWebServiceMessage; @@ -48,6 +49,7 @@ import org.apache.axiom.soap.SOAPEnvelope; import org.apache.axiom.soap.SOAPFactory; import org.apache.axiom.soap.SOAPMessage; import org.apache.axiom.soap.SOAPProcessingException; +import org.w3c.dom.Document; /** * AXIOM-specific implementation of the {@link SoapMessage} interface. Created via the {@link AxiomSoapMessageFactory}, @@ -195,6 +197,23 @@ public class AxiomSoapMessage extends AbstractSoapMessage implements StreamingWe this.soapAction = soapAction; } + public Document getDocument() { + return AxiomUtils.toDocument(axiomMessage.getSOAPEnvelope()); + } + + public void setDocument(Document document) { + // save the Soap Action + String soapAction = getSoapAction(); + SOAPEnvelope envelope = AxiomUtils.toEnvelope(document); + SOAPMessage newMessage = axiomFactory.createSOAPMessage(); + newMessage.setSOAPEnvelope(envelope); + + // replace the Axiom message + setAxiomMessage(newMessage); + // restore the Soap Action + setSoapAction(soapAction); + } + public boolean isXopPackage() { try { return MTOMConstants.MTOM_TYPE.equals(attachments.getAttachmentSpecType()); 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 35b7f794..033a3ee8 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 @@ -135,10 +135,7 @@ public abstract class AxiomUtils { } } catch (Exception ex) { - IllegalArgumentException iaex = - new IllegalArgumentException("Error in converting SOAP Envelope to Document"); - iaex.initCause(ex); - throw iaex; + throw new IllegalArgumentException("Error in converting SOAP Envelope to Document", ex); } } diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java index 033f0e73..5984404d 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessage.java @@ -16,11 +16,14 @@ package org.springframework.ws.soap.saaj; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; import javax.activation.DataHandler; import javax.xml.soap.AttachmentPart; +import javax.xml.soap.MessageFactory; import javax.xml.soap.MimeHeaders; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPElement; @@ -41,6 +44,12 @@ import org.springframework.ws.soap.saaj.support.SaajUtils; import org.springframework.ws.soap.support.SoapUtils; import org.springframework.ws.transport.TransportConstants; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSOutput; +import org.w3c.dom.ls.LSSerializer; + /** * SAAJ-specific implementation of the {@link SoapMessage} interface. Created via the {@link SaajSoapMessageFactory}, * wraps a {@link SOAPMessage}. @@ -53,6 +62,8 @@ public class SaajSoapMessage extends AbstractSoapMessage { private static final String CONTENT_TYPE_XOP = "application/xop+xml"; + private final MessageFactory messageFactory; + private SOAPMessage saajMessage; private SoapEnvelope envelope; @@ -67,7 +78,17 @@ public class SaajSoapMessage extends AbstractSoapMessage { * @param soapMessage the SAAJ SOAPMessage */ public SaajSoapMessage(SOAPMessage soapMessage) { - this(soapMessage, true); + this(soapMessage, true, null); + } + + /** + * Create a new SaajSoapMessage based on the given SAAJ SOAPMessage. + * + * @param soapMessage the SAAJ SOAPMessage + * @param messageFactory the SAAJ message factory + */ + public SaajSoapMessage(SOAPMessage soapMessage, MessageFactory messageFactory) { + this(soapMessage, true, messageFactory); } /** @@ -78,6 +99,18 @@ public class SaajSoapMessage extends AbstractSoapMessage { * whether a {@code xml:lang} attribute is allowed on SOAP 1.1 {@code } elements */ public SaajSoapMessage(SOAPMessage soapMessage, boolean langAttributeOnSoap11FaultString) { + this(soapMessage, langAttributeOnSoap11FaultString, null); + } + + /** + * Create a new SaajSoapMessage based on the given SAAJ SOAPMessage. + * + * @param soapMessage the SAAJ SOAPMessage + * @param langAttributeOnSoap11FaultString + * whether a {@code xml:lang} attribute is allowed on SOAP 1.1 {@code } elements + * @param messageFactory the message factory + */ + public SaajSoapMessage(SOAPMessage soapMessage, boolean langAttributeOnSoap11FaultString, MessageFactory messageFactory) { Assert.notNull(soapMessage, "soapMessage must not be null"); saajMessage = soapMessage; this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString; @@ -85,6 +118,7 @@ public class SaajSoapMessage extends AbstractSoapMessage { if (ObjectUtils.isEmpty(headers.getHeader(TransportConstants.HEADER_SOAP_ACTION))) { headers.addHeader(TransportConstants.HEADER_SOAP_ACTION, "\"\""); } + this.messageFactory = messageFactory; } /** Return the SAAJ SOAPMessage that this SaajSoapMessage is based on. */ @@ -156,6 +190,54 @@ public class SaajSoapMessage extends AbstractSoapMessage { } + public Document getDocument() { + Assert.state(messageFactory != null, "Could find message factory to use"); + // return saajSoapMessage.getSaajMessage().getSOAPPart(); // does not work, see SWS-345 + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + getSaajMessage().writeTo(bos); + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + SOAPMessage saajMessage = messageFactory.createMessage(getSaajMessage().getMimeHeaders(), bis); + setSaajMessage(saajMessage); + return saajMessage.getSOAPPart(); + } + catch (SOAPException ex) { + throw new SaajSoapMessageException("Could not save changes", ex); + } + catch (IOException ex) { + throw new SaajSoapMessageException("Could not save changes", ex); + } + } + + public void setDocument(Document document) { + if (saajMessage.getSOAPPart() != document) { + Assert.state(messageFactory != null, "Could find message factory to use"); + try { + DOMImplementation implementation = document.getImplementation(); + Assert.isInstanceOf(DOMImplementationLS.class, implementation); + + DOMImplementationLS loadSaveImplementation = (DOMImplementationLS) implementation; + LSOutput output = loadSaveImplementation.createLSOutput(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + output.setByteStream(bos); + + LSSerializer serializer = loadSaveImplementation.createLSSerializer(); + serializer.write(document, output); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + + this.saajMessage = messageFactory.createMessage(saajMessage.getMimeHeaders(), bis); + + } + catch (SOAPException ex) { + throw new SaajSoapMessageException("Could not read input stream", ex); + } + catch (IOException ex) { + throw new SaajSoapMessageException("Could not read input stream", ex); + } + } + } + public void writeTo(OutputStream outputStream) throws IOException { MimeHeaders mimeHeaders = getImplementation().getMimeHeaders(getSaajMessage()); if (ObjectUtils.isEmpty(mimeHeaders.getHeader(TransportConstants.HEADER_ACCEPT))) { diff --git a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java index d77fba31..954623c3 100644 --- a/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java +++ b/core/src/main/java/org/springframework/ws/soap/saaj/SaajSoapMessageFactory.java @@ -168,7 +168,7 @@ public class SaajSoapMessageFactory implements SoapMessageFactory"), + soapMessage.getSoapBody().getPayloadResult()); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document expected = documentBuilder.newDocument(); + Element envelope = expected.createElementNS("http://schemas.xmlsoap.org/soap/envelope/", "Envelope"); + expected.appendChild(envelope); + Element body = expected.createElementNS("http://schemas.xmlsoap.org/soap/envelope/", "Body"); + envelope.appendChild(body); + Element payload = expected.createElementNS("http://www.springframework.org", "payload"); + body.appendChild(payload); + + Document result = soapMessage.getDocument(); + + assertXMLEqual(expected, result); + } + + @Override + public void testSetLiveDocument() throws Exception { + transformer.transform(new StringSource(""), + soapMessage.getSoapBody().getPayloadResult()); + + Document document = soapMessage.getDocument(); + + soapMessage.setDocument(document); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + soapMessage.writeTo(bos); + + String result = bos.toString("UTF-8"); + assertXMLEqual( + "", + result); + } + + @Override + public void testSetOtherDocument() throws Exception { + transformer.transform(new StringSource(""), + soapMessage.getSoapBody().getPayloadResult()); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + soapMessage.writeTo(bos); + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + + DOMResult domResult = new DOMResult(); + transformer.transform(new StreamSource(bis), domResult); + + Document document = (Document) domResult.getNode(); + + soapMessage.setDocument(document); + + bos = new ByteArrayOutputStream(); + soapMessage.writeTo(bos); + + String result = bos.toString("UTF-8"); + assertXMLEqual( + "", + result); + } + } diff --git a/core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageTestCase.java b/core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageTestCase.java index 5c0256e4..d16d803f 100644 --- a/core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageTestCase.java +++ b/core/src/test/java/org/springframework/ws/soap/soap12/AbstractSoap12MessageTestCase.java @@ -16,7 +16,12 @@ package org.springframework.ws.soap.soap12; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.ClassPathResource; @@ -30,6 +35,8 @@ import org.springframework.ws.transport.TransportConstants; import org.springframework.xml.transform.StringSource; import junit.framework.Assert; +import org.w3c.dom.Document; +import org.w3c.dom.Element; import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; import static org.junit.Assert.*; @@ -85,4 +92,71 @@ public abstract class AbstractSoap12MessageTestCase extends AbstractSoapMessageT contentType.indexOf("type=\"application/soap+xml\"") != -1); } + @Override + public void testToDocument() throws Exception { + transformer.transform(new StringSource(""), + soapMessage.getSoapBody().getPayloadResult()); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document expected = documentBuilder.newDocument(); + Element envelope = expected.createElementNS("http://www.w3.org/2003/05/soap-envelope", "Envelope"); + expected.appendChild(envelope); + Element body = expected.createElementNS("http://www.w3.org/2003/05/soap-envelope", "Body"); + envelope.appendChild(body); + Element payload = expected.createElementNS("http://www.springframework.org", "payload"); + body.appendChild(payload); + + Document result = soapMessage.getDocument(); + + assertXMLEqual(expected, result); + } + + @Override + public void testSetLiveDocument() throws Exception { + transformer.transform(new StringSource(""), + soapMessage.getSoapBody().getPayloadResult()); + + Document document = soapMessage.getDocument(); + + soapMessage.setDocument(document); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + soapMessage.writeTo(bos); + + String result = bos.toString("UTF-8"); + assertXMLEqual( + "", + result); + } + + @Override + public void testSetOtherDocument() throws Exception { + transformer.transform(new StringSource(""), + soapMessage.getSoapBody().getPayloadResult()); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + soapMessage.writeTo(bos); + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + + DOMResult domResult = new DOMResult(); + transformer.transform(new StreamSource(bis), domResult); + + Document document = (Document) domResult.getNode(); + + soapMessage.setDocument(document); + + bos = new ByteArrayOutputStream(); + soapMessage.writeTo(bos); + + String result = bos.toString("UTF-8"); + assertXMLEqual( + "", + result); + } + + + + } diff --git a/sandbox/src/main/java/org/springframework/ws/soap/stroap/StroapMessage.java b/sandbox/src/main/java/org/springframework/ws/soap/stroap/StroapMessage.java index eaedc378..6abbc1a7 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/stroap/StroapMessage.java +++ b/sandbox/src/main/java/org/springframework/ws/soap/stroap/StroapMessage.java @@ -16,6 +16,8 @@ package org.springframework.ws.soap.stroap; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -25,10 +27,16 @@ import java.util.List; import java.util.Map; import java.util.StringTokenizer; import javax.activation.DataHandler; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.EndDocument; +import javax.xml.stream.events.StartDocument; import javax.xml.stream.events.XMLEvent; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; @@ -48,6 +56,13 @@ import org.springframework.ws.transport.TransportInputStream; import org.springframework.ws.transport.TransportOutputStream; import org.springframework.xml.stream.AbstractXMLEventWriter; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSOutput; +import org.w3c.dom.ls.LSSerializer; +import org.xml.sax.SAXException; + /** * @author Arjen Poutsma */ @@ -55,10 +70,14 @@ public class StroapMessage extends AbstractSoapMessage implements StreamingWebSe private final MultiValueMap mimeHeaders = new LinkedMultiValueMap(); - private final StroapEnvelope envelope; + private StroapEnvelope envelope; private final StroapMessageFactory messageFactory; + private final StartDocument startDocument; + + private final EndDocument endDocument; + public StroapMessage(StroapMessageFactory messageFactory) { this(null, null, messageFactory); } @@ -79,6 +98,8 @@ public class StroapMessage extends AbstractSoapMessage implements StreamingWebSe if (!this.mimeHeaders.containsKey(TransportConstants.HEADER_ACCEPT)) { this.mimeHeaders.set(TransportConstants.HEADER_ACCEPT, messageFactory.getSoapVersion().getContentType()); } + this.startDocument = messageFactory.getEventFactory().createStartDocument(); + this.endDocument = messageFactory.getEventFactory().createEndDocument(); } static StroapMessage build(InputStream inputStream, StroapMessageFactory messageFactory) @@ -132,6 +153,79 @@ public class StroapMessage extends AbstractSoapMessage implements StreamingWebSe return messageFactory.getSoapVersion(); } + public Document getDocument() { + try { + DocumentBuilder documentBuilder = messageFactory.getDocumentBuilderFactory().newDocumentBuilder(); + try { + Document result = documentBuilder.newDocument(); + DOMResult domResult = new DOMResult(result); + XMLEventWriter eventWriter = messageFactory.getOutputFactory().createXMLEventWriter(domResult); + eventWriter.add(startDocument); + envelope.writeTo(new NoStartEndDocumentWriter(eventWriter)); + eventWriter.add(endDocument); + eventWriter.flush(); + return result; + } + catch (XMLStreamException ignored) { + // ignored + } + catch (UnsupportedOperationException ignored) { + // ignored + } + + // XMLOutputFactory does not support DOMResults, so let's do it the hard way + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + writeTo(bos); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + return documentBuilder.parse(bis); + } + catch (ParserConfigurationException ex) { + throw new StroapMessageException("Could not create DocumentBuilderFactory", ex); + } + catch (SAXException ex) { + throw new StroapMessageException("Could not save message as Document", ex); + } + catch (IOException ex) { + throw new StroapMessageException("Could not save message as Document", ex); + } + } + + public void setDocument(Document document) { + try { + try { + DOMSource domSource = new DOMSource(document); + XMLEventReader eventReader = messageFactory.getInputFactory().createXMLEventReader(domSource); + this.envelope = StroapEnvelope.build(eventReader, messageFactory); + return; + } + catch (XMLStreamException ignored) { + // ignored + } + catch (UnsupportedOperationException ignored) { + // ignored + } + // XMLInputFactory does not support DOMSources, so let's do it the hard way + DOMImplementation implementation = document.getImplementation(); + Assert.isInstanceOf(DOMImplementationLS.class, implementation); + + DOMImplementationLS loadSaveImplementation = (DOMImplementationLS) implementation; + LSOutput output = loadSaveImplementation.createLSOutput(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + output.setByteStream(bos); + + LSSerializer serializer = loadSaveImplementation.createLSSerializer(); + serializer.write(document, output); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + XMLEventReader eventReader = messageFactory.getInputFactory().createXMLEventReader(bis); + this.envelope = StroapEnvelope.build(eventReader, messageFactory); + } + catch (XMLStreamException ex) { + throw new StroapMessageException("Could not read Document", ex); + } + } + public void writeTo(OutputStream outputStream) throws IOException { if (outputStream instanceof TransportOutputStream) { TransportOutputStream tos = (TransportOutputStream) outputStream; @@ -144,9 +238,9 @@ public class StroapMessage extends AbstractSoapMessage implements StreamingWebSe } try { XMLEventWriter eventWriter = messageFactory.getOutputFactory().createXMLEventWriter(outputStream); - eventWriter.add(messageFactory.getEventFactory().createStartDocument()); + eventWriter.add(startDocument); envelope.writeTo(new NoStartEndDocumentWriter(eventWriter)); - eventWriter.add(messageFactory.getEventFactory().createEndDocument()); + eventWriter.add(endDocument); eventWriter.flush(); } catch (XMLStreamException ex) { diff --git a/sandbox/src/main/java/org/springframework/ws/soap/stroap/StroapMessageFactory.java b/sandbox/src/main/java/org/springframework/ws/soap/stroap/StroapMessageFactory.java index 004f84aa..e01874f9 100644 --- a/sandbox/src/main/java/org/springframework/ws/soap/stroap/StroapMessageFactory.java +++ b/sandbox/src/main/java/org/springframework/ws/soap/stroap/StroapMessageFactory.java @@ -18,6 +18,7 @@ package org.springframework.ws.soap.stroap; import java.io.IOException; import java.io.InputStream; +import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.stream.XMLEventFactory; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; @@ -37,6 +38,8 @@ public class StroapMessageFactory implements SoapMessageFactory { private final XMLEventFactory eventFactory = createXmlEventFactory(); + private final DocumentBuilderFactory documentBuilderFactory = createDocumentBuilderFactory(); + private boolean payloadCaching = true; public boolean isPayloadCaching() { @@ -83,6 +86,10 @@ public class StroapMessageFactory implements SoapMessageFactory { return eventFactory; } + DocumentBuilderFactory getDocumentBuilderFactory() { + return documentBuilderFactory; + } + /** * Create a {@code XMLInputFactory} that this message factory will use to create {@link * javax.xml.stream.XMLEventReader} objects. @@ -124,6 +131,20 @@ public class StroapMessageFactory implements SoapMessageFactory { return XMLEventFactory.newFactory(); } + /** + * Create a {@code DocumentBuilderFactory} that this message factory will use to create {@link org.w3c.dom.Document} objects. + *

+ * Can be overridden in subclasses, adding further initialization of the factory. The resulting factory is cached, + * so this method will only be called once. + * + * @return the created factory + */ + protected DocumentBuilderFactory createDocumentBuilderFactory() { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + return documentBuilderFactory; + } + public String toString() { StringBuilder builder = new StringBuilder("StroapMessageFactory["); if (getSoapVersion() == SoapVersion.SOAP_11) { diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java index f4466cdb..8bd04b9c 100755 --- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java +++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java @@ -16,8 +16,6 @@ package org.springframework.ws.soap.security.wss4j; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.Principal; import java.security.cert.X509Certificate; @@ -25,20 +23,13 @@ import java.util.Vector; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; -import javax.xml.soap.MessageFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.axiom.AxiomSoapMessage; -import org.springframework.ws.soap.axiom.support.AxiomUtils; -import org.springframework.ws.soap.saaj.SaajSoapMessage; -import org.springframework.ws.soap.saaj.SaajSoapMessageException; -import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; import org.springframework.ws.soap.security.AbstractWsSecurityInterceptor; import org.springframework.ws.soap.security.WsSecuritySecurementException; import org.springframework.ws.soap.security.WsSecurityValidationException; @@ -46,9 +37,6 @@ import org.springframework.ws.soap.security.callback.CallbackHandlerChain; import org.springframework.ws.soap.security.callback.CleanupCallback; import org.springframework.ws.soap.security.wss4j.callback.UsernameTokenPrincipalCallback; -import org.apache.axiom.soap.SOAPEnvelope; -import org.apache.axiom.soap.SOAPFactory; -import org.apache.axiom.soap.SOAPMessage; import org.apache.ws.security.WSConstants; import org.apache.ws.security.WSSecurityEngine; import org.apache.ws.security.WSSecurityEngineResult; @@ -484,7 +472,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl } RequestData requestData = initializeRequestData(messageContext); - Document envelopeAsDocument = toDocument(soapMessage, messageContext); + Document envelopeAsDocument = soapMessage.getDocument(); try { // In case on signature confirmation with no other securement // action, we need to pass an empty securementActionsVector to avoid @@ -499,7 +487,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl throw new Wss4jSecuritySecurementException(ex.getMessage(), ex); } - replaceMessage(soapMessage, envelopeAsDocument); + soapMessage.setDocument(envelopeAsDocument); } /** Creates and initializes a request data */ @@ -534,7 +522,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl return; } - Document envelopeAsDocument = toDocument(soapMessage, messageContext); + Document envelopeAsDocument = soapMessage.getDocument(); // Header processing @@ -564,7 +552,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl throw new Wss4jSecurityValidationException(ex.getMessage(), ex); } - replaceMessage(soapMessage, envelopeAsDocument); + soapMessage.setDocument(envelopeAsDocument); soapMessage.getEnvelope().getHeader().removeHeaderElement(WS_SECURITY_NAME); } @@ -649,60 +637,6 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl } } - /** Converts the given {@link SoapMessage} into a {@link Document}. */ - private Document toDocument(SoapMessage soapMessage, MessageContext messageContext) { - if (soapMessage instanceof SaajSoapMessage) { - SaajSoapMessage saajSoapMessage = (SaajSoapMessage) soapMessage; - // return saajSoapMessage.getSaajMessage().getSOAPPart(); // does not work, see SWS-345 - Assert.isInstanceOf(DefaultMessageContext.class, messageContext); - DefaultMessageContext defaultMessageContext = (DefaultMessageContext) messageContext; - Assert.isInstanceOf(SaajSoapMessageFactory.class, defaultMessageContext.getMessageFactory()); - MessageFactory messageFactory = - ((SaajSoapMessageFactory) defaultMessageContext.getMessageFactory()).getMessageFactory(); - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - saajSoapMessage.writeTo(bos); - ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); - javax.xml.soap.SOAPMessage saajMessage = - messageFactory.createMessage(saajSoapMessage.getSaajMessage().getMimeHeaders(), bis); - saajSoapMessage.setSaajMessage(saajMessage); - return saajMessage.getSOAPPart(); - } - catch (Exception ex) { - throw new SaajSoapMessageException("Could not save changes", ex); - } - } - else if (soapMessage instanceof AxiomSoapMessage) { - AxiomSoapMessage axiomMessage = (AxiomSoapMessage) soapMessage; - return AxiomUtils.toDocument(axiomMessage.getAxiomMessage().getSOAPEnvelope()); - } - else { - throw new IllegalArgumentException("Message type not supported [" + soapMessage + "]"); - } - } - - /** - * Replaces the contents of the given {@link SoapMessage} with that of the document parameter. Only required when - * using Axiom, since the document returned by {@link #toDocument} is live for a {@link SaajSoapMessage}. - */ - private void replaceMessage(SoapMessage soapMessage, Document envelope) { - if (soapMessage instanceof AxiomSoapMessage) { - // construct a new Axiom message with the processed envelope - AxiomSoapMessage axiomMessage = (AxiomSoapMessage) soapMessage; - // save the Soap Action - String soapAction = axiomMessage.getSoapAction(); - SOAPEnvelope envelopeFromDOMDocument = AxiomUtils.toEnvelope(envelope); - SOAPFactory factory = (SOAPFactory) axiomMessage.getAxiomMessage().getOMFactory(); - SOAPMessage newMessage = factory.createSOAPMessage(); - newMessage.setSOAPEnvelope(envelopeFromDOMDocument); - - // replace the Axiom message - axiomMessage.setAxiomMessage(newMessage); - // restore the Soap Action - axiomMessage.setSoapAction(soapAction); - } - } - @Override protected void cleanUp() { if (validationCallbackHandler != null) { diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java index 59a15bf7..c79b3e41 100755 --- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java +++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java @@ -53,7 +53,7 @@ public class SaajWss4jMessageInterceptorSignTest extends Wss4jMessageInterceptor interceptor.setSecurementUsername("rsaKey"); SOAPMessage saajMessage = saajSoap11MessageFactory.createMessage(); transformer.transform(new StringSource(PAYLOAD), new DOMResult(saajMessage.getSOAPBody())); - SoapMessage message = new SaajSoapMessage(saajMessage); + SoapMessage message = new SaajSoapMessage(saajMessage, saajSoap11MessageFactory); MessageContext messageContext = new DefaultMessageContext(message, new SaajSoapMessageFactory(saajSoap11MessageFactory)); interceptor.secureMessage(message, messageContext); @@ -74,7 +74,7 @@ public class SaajWss4jMessageInterceptorSignTest extends Wss4jMessageInterceptor ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); SOAPMessage signed = saajSoap11MessageFactory.createMessage(mimeHeaders, bis); - message = new SaajSoapMessage(signed); + message = new SaajSoapMessage(signed, saajSoap11MessageFactory); messageContext = new DefaultMessageContext(message, new SaajSoapMessageFactory(saajSoap11MessageFactory)); interceptor.validateMessage(message, messageContext); 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 70dc10ea..22822765 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 @@ -125,7 +125,7 @@ public abstract class Wss4jTestCase { try { assertTrue("Could not load SAAJ message [" + resource + "]", resource.exists()); is = resource.getInputStream(); - return new SaajSoapMessage(saajSoap11MessageFactory.createMessage(mimeHeaders, is)); + return new SaajSoapMessage(saajSoap11MessageFactory.createMessage(mimeHeaders, is), saajSoap11MessageFactory); } finally { is.close(); @@ -140,7 +140,7 @@ public abstract class Wss4jTestCase { try { assertTrue("Could not load SAAJ message [" + resource + "]", resource.exists()); is = resource.getInputStream(); - return new SaajSoapMessage(saajSoap12MessageFactory.createMessage(mimeHeaders, is)); + return new SaajSoapMessage(saajSoap12MessageFactory.createMessage(mimeHeaders, is), saajSoap12MessageFactory); } finally { is.close();