1616
1717package org .springframework .ws .soap .security .wss4j ;
1818
19+ import java .io .ByteArrayInputStream ;
20+ import java .io .ByteArrayOutputStream ;
1921import java .io .IOException ;
2022import java .security .Principal ;
2123import java .security .cert .X509Certificate ;
2224import java .util .Vector ;
2325import javax .security .auth .callback .Callback ;
2426import javax .security .auth .callback .CallbackHandler ;
2527import javax .security .auth .callback .UnsupportedCallbackException ;
26- import javax .xml .soap .SOAPException ;
28+ import javax .xml .soap .MessageFactory ;
2729
2830import org .apache .axiom .soap .SOAPEnvelope ;
2931import org .apache .axiom .soap .SOAPFactory ;
4446import org .springframework .beans .factory .InitializingBean ;
4547import org .springframework .util .Assert ;
4648import org .springframework .util .StringUtils ;
49+ import org .springframework .ws .context .DefaultMessageContext ;
4750import org .springframework .ws .context .MessageContext ;
4851import org .springframework .ws .soap .SoapMessage ;
4952import org .springframework .ws .soap .axiom .AxiomSoapMessage ;
5053import org .springframework .ws .soap .axiom .support .AxiomUtils ;
5154import org .springframework .ws .soap .saaj .SaajSoapMessage ;
5255import org .springframework .ws .soap .saaj .SaajSoapMessageException ;
56+ import org .springframework .ws .soap .saaj .SaajSoapMessageFactory ;
5357import org .springframework .ws .soap .security .AbstractWsSecurityInterceptor ;
5458import org .springframework .ws .soap .security .WsSecuritySecurementException ;
5559import org .springframework .ws .soap .security .WsSecurityValidationException ;
@@ -440,7 +444,7 @@ protected void secureMessage(SoapMessage soapMessage, MessageContext messageCont
440444 }
441445 RequestData requestData = initializeRequestData (messageContext );
442446
443- Document envelopeAsDocument = toDocument (soapMessage );
447+ Document envelopeAsDocument = toDocument (soapMessage , messageContext );
444448 try {
445449 // In case on signature confirmation with no other securement
446450 // action, we need to pass an empty securementActionsVector to avoid
@@ -485,7 +489,7 @@ protected void validateMessage(SoapMessage soapMessage, MessageContext messageCo
485489 return ;
486490 }
487491
488- Document envelopeAsDocument = toDocument (soapMessage );
492+ Document envelopeAsDocument = toDocument (soapMessage , messageContext );
489493
490494 // Header processing
491495 WSSecurityEngine securityEngine = WSSecurityEngine .getInstance ();
@@ -590,16 +594,27 @@ private void processPrincipal(Vector results) {
590594 }
591595
592596 /** Converts the given {@link SoapMessage} into a {@link Document}. */
593- private Document toDocument (SoapMessage soapMessage ) {
597+ private Document toDocument (SoapMessage soapMessage , MessageContext messageContext ) {
594598 if (soapMessage instanceof SaajSoapMessage ) {
595- javax .xml .soap .SOAPMessage saajMessage = ((SaajSoapMessage ) soapMessage ).getSaajMessage ();
599+ SaajSoapMessage saajSoapMessage = (SaajSoapMessage ) soapMessage ;
600+ // return saajSoapMessage.getSaajMessage().getSOAPPart(); // does not work, see SWS-345
601+ Assert .isInstanceOf (DefaultMessageContext .class , messageContext );
602+ DefaultMessageContext defaultMessageContext = (DefaultMessageContext ) messageContext ;
603+ Assert .isInstanceOf (SaajSoapMessageFactory .class , defaultMessageContext .getMessageFactory ());
604+ MessageFactory messageFactory =
605+ ((SaajSoapMessageFactory ) defaultMessageContext .getMessageFactory ()).getMessageFactory ();
596606 try {
597- saajMessage .saveChanges ();
607+ ByteArrayOutputStream bos = new ByteArrayOutputStream ();
608+ saajSoapMessage .writeTo (bos );
609+ ByteArrayInputStream bis = new ByteArrayInputStream (bos .toByteArray ());
610+ javax .xml .soap .SOAPMessage saajMessage =
611+ messageFactory .createMessage (saajSoapMessage .getSaajMessage ().getMimeHeaders (), bis );
612+ saajSoapMessage .setSaajMessage (saajMessage );
613+ return saajMessage .getSOAPPart ();
598614 }
599- catch (SOAPException ex ) {
615+ catch (Exception ex ) {
600616 throw new SaajSoapMessageException ("Could not save changes" , ex );
601617 }
602- return saajMessage .getSOAPPart ();
603618 }
604619 else if (soapMessage instanceof AxiomSoapMessage ) {
605620 AxiomSoapMessage axiomMessage = (AxiomSoapMessage ) soapMessage ;
@@ -612,20 +627,10 @@ else if (soapMessage instanceof AxiomSoapMessage) {
612627
613628 /**
614629 * Replaces the contents of the given {@link SoapMessage} with that of the document parameter. Only required when
615- * using Axiom, since the document returned by {@link #toDocument(org.springframework.ws.soap.SoapMessage)} is live
616- * for a {@link SaajSoapMessage}.
630+ * using Axiom, since the document returned by {@link #toDocument} is live for a {@link SaajSoapMessage}.
617631 */
618632 private void replaceMessage (SoapMessage soapMessage , Document envelope ) {
619- if (soapMessage instanceof SaajSoapMessage ) {
620- javax .xml .soap .SOAPMessage saajMessage = ((SaajSoapMessage ) soapMessage ).getSaajMessage ();
621- try {
622- saajMessage .saveChanges ();
623- }
624- catch (SOAPException ex ) {
625- throw new SaajSoapMessageException ("Could not save changes" , ex );
626- }
627- }
628- else if (soapMessage instanceof AxiomSoapMessage ) {
633+ if (soapMessage instanceof AxiomSoapMessage ) {
629634 // construct a new Axiom message with the processed envelope
630635 AxiomSoapMessage axiomMessage = (AxiomSoapMessage ) soapMessage ;
631636 SOAPEnvelope envelopeFromDOMDocument = AxiomUtils .toEnvelope (envelope );
0 commit comments