Package org.springframework.ws.soap.saaj

Source Code of org.springframework.ws.soap.saaj.SaajSoapMessage

/*
* 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.
* 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.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.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

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.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.ws.mime.Attachment;
import org.springframework.ws.mime.AttachmentException;
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.saaj.support.SaajUtils;
import org.springframework.ws.soap.support.SoapUtils;
import org.springframework.ws.transport.TransportConstants;
import org.springframework.ws.transport.TransportOutputStream;

/**
* SAAJ-specific implementation of the {@link SoapMessage} interface. Created via the {@link SaajSoapMessageFactory},
* wraps a {@link SOAPMessage}.
*
* @author Arjen Poutsma
* @see SOAPMessage
* @since 1.0.0
*/
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;

    private final boolean langAttributeOnSoap11FaultString;

    /**
     * Create a new {@code SaajSoapMessage} based on the given SAAJ {@code SOAPMessage}.
     *
     * @param soapMessage the SAAJ SOAPMessage
     */
    public SaajSoapMessage(SOAPMessage soapMessage) {
        this(soapMessage, true, null);
    }

    /**
     * Create a new {@code SaajSoapMessage} based on the given SAAJ {@code SOAPMessage}.
     *
     * @param soapMessage the SAAJ SOAPMessage
     * @param messageFactory the SAAJ message factory
     */
    public SaajSoapMessage(SOAPMessage soapMessage, MessageFactory messageFactory) {
        this(soapMessage, true, messageFactory);
    }

    /**
     * Create a new {@code SaajSoapMessage} based on the given SAAJ {@code SOAPMessage}.
     *
     * @param soapMessage the SAAJ SOAPMessage
     * @param langAttributeOnSoap11FaultString
     *                    whether a {@code xml:lang} attribute is allowed on SOAP 1.1 {@code <faultstring>} elements
     */
    public SaajSoapMessage(SOAPMessage soapMessage, boolean langAttributeOnSoap11FaultString) {
        this(soapMessage, langAttributeOnSoap11FaultString, null);
    }

    /**
     * Create a new {@code SaajSoapMessage} based on the given SAAJ {@code SOAPMessage}.
     *
     * @param soapMessage the SAAJ SOAPMessage
     * @param langAttributeOnSoap11FaultString
     *                    whether a {@code xml:lang} attribute is allowed on SOAP 1.1 {@code <faultstring>} 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;
      MimeHeaders headers = soapMessage.getMimeHeaders();
        if (ObjectUtils.isEmpty(headers.getHeader(TransportConstants.HEADER_SOAP_ACTION))) {
            headers.addHeader(TransportConstants.HEADER_SOAP_ACTION, "\"\"");
        }
        this.messageFactory = messageFactory;
    }

    /** Return the SAAJ {@code SOAPMessage} that this {@code SaajSoapMessage} is based on. */
    public SOAPMessage getSaajMessage() {
        return saajMessage;
    }

    /** Sets the SAAJ {@code SOAPMessage} that this {@code SaajSoapMessage} is based on. */
    public void setSaajMessage(SOAPMessage soapMessage) {
        Assert.notNull(soapMessage, "soapMessage must not be null");
        saajMessage = soapMessage;
        envelope = null;
    }

    @Override
    public SoapEnvelope getEnvelope() {
        if (envelope == null) {
            try {
              SOAPEnvelope saajEnvelope = getSaajMessage().getSOAPPart().getEnvelope();
                envelope = new SaajSoapEnvelope(saajEnvelope, langAttributeOnSoap11FaultString);
            }
            catch (SOAPException ex) {
                throw new SaajSoapEnvelopeException(ex);
            }
        }
        return envelope;
    }

    @Override
    public String getSoapAction() {
      MimeHeaders mimeHeaders = getSaajMessage().getMimeHeaders();
        if (SoapVersion.SOAP_11 == getVersion()) {
            String[] actions = mimeHeaders.getHeader(TransportConstants.HEADER_SOAP_ACTION);
            return ObjectUtils.isEmpty(actions) ? TransportConstants.EMPTY_SOAP_ACTION : actions[0];
        }
        else if (SoapVersion.SOAP_12 == getVersion()) {
            String[] contentTypes = mimeHeaders.getHeader(TransportConstants.HEADER_CONTENT_TYPE);
            return !ObjectUtils.isEmpty(contentTypes) ? SoapUtils.extractActionFromContentType(contentTypes[0]) :
                    TransportConstants.EMPTY_SOAP_ACTION;
        }
        else {
            throw new IllegalStateException("Unsupported SOAP version: " + getVersion());
        }
    }

    @Override
    public void setSoapAction(String soapAction) {
      MimeHeaders mimeHeaders = getSaajMessage().getMimeHeaders();
        soapAction = SoapUtils.escapeAction(soapAction);
        if (SoapVersion.SOAP_11 == getVersion()) {
            mimeHeaders.setHeader(TransportConstants.HEADER_SOAP_ACTION, soapAction);
        }
        else if (SoapVersion.SOAP_12 == getVersion()) {
            // force save of Content Type header
          try {
              saajMessage.saveChanges();
          }
          catch (SOAPException ex) {
              throw new SaajSoapMessageException("Could not save message", ex);
          }
          String[] contentTypes = mimeHeaders.getHeader(TransportConstants.HEADER_CONTENT_TYPE);
            String contentType = !ObjectUtils.isEmpty(contentTypes) ? contentTypes[0] : getVersion().getContentType();
            contentType = SoapUtils.setActionInContentType(contentType, soapAction);
            mimeHeaders.setHeader(TransportConstants.HEADER_CONTENT_TYPE, contentType);
            mimeHeaders.removeHeader(TransportConstants.HEADER_SOAP_ACTION);
        }
        else {
            throw new IllegalStateException("Unsupported SOAP version: " + getVersion());
        }

    }

    @Override
    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);
        }
    }

    @Override
    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);
            }
        }
    }

    @Override
    public void writeTo(OutputStream outputStream) throws IOException {
      MimeHeaders mimeHeaders = getSaajMessage().getMimeHeaders();
        if (ObjectUtils.isEmpty(mimeHeaders.getHeader(TransportConstants.HEADER_ACCEPT))) {
            mimeHeaders.setHeader(TransportConstants.HEADER_ACCEPT, getVersion().getContentType());
        }
        try {
          SOAPMessage message = getSaajMessage();
            message.saveChanges();
          if (outputStream instanceof TransportOutputStream) {
              TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
              // some SAAJ implementations (Axis 1) do not have a Content-Type header by default
              MimeHeaders headers = message.getMimeHeaders();
              if (ObjectUtils
                  .isEmpty(
                      headers.getHeader(TransportConstants.HEADER_CONTENT_TYPE))) {
                  SOAPEnvelope envelope1 = message.getSOAPPart().getEnvelope();
                  if (envelope1.getElementQName().getNamespaceURI()
                          .equals(SoapVersion.SOAP_11.getEnvelopeNamespaceUri())) {
                      headers.addHeader(TransportConstants.HEADER_CONTENT_TYPE, SoapVersion.SOAP_11.getContentType());
                  }
                  else {
                      headers.addHeader(TransportConstants.HEADER_CONTENT_TYPE, SoapVersion.SOAP_12.getContentType());
                  }
                    message.saveChanges();
              }
              for (Iterator<?> iterator = headers.getAllHeaders(); iterator.hasNext();) {
                  MimeHeader mimeHeader = (MimeHeader) iterator.next();
                  transportOutputStream.addHeader(mimeHeader.getName(), mimeHeader.getValue());
              }
          }
          message.writeTo(outputStream);

          outputStream.flush();
        }
        catch (SOAPException ex) {
            throw new SaajSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
        }
    }

  @Override
    public boolean isXopPackage() {
      SOAPPart saajPart = saajMessage.getSOAPPart();
      String[] contentTypes = saajPart.getMimeHeader(TransportConstants.HEADER_CONTENT_TYPE);
      for (String contentType : contentTypes) {
          if (contentType.contains(CONTENT_TYPE_XOP)) {
              return true;
          }
      }
      return false;
    }

    @Override
    public boolean convertToXopPackage() {
      convertMessageToXop();
      convertPartToXop();
      return true;
    }

    private void convertMessageToXop() {
        MimeHeaders mimeHeaders = saajMessage.getMimeHeaders();
        String[] oldContentTypes = mimeHeaders.getHeader(TransportConstants.HEADER_CONTENT_TYPE);
        String oldContentType =
                !ObjectUtils.isEmpty(oldContentTypes) ? oldContentTypes[0] : getVersion().getContentType();
      mimeHeaders.setHeader(TransportConstants.HEADER_CONTENT_TYPE,
          CONTENT_TYPE_XOP + ";type=" + '"' + oldContentType + '"');
    }

    private void convertPartToXop() {
        SOAPPart saajPart = saajMessage.getSOAPPart();
        String[] oldContentTypes = saajPart.getMimeHeader(TransportConstants.HEADER_CONTENT_TYPE);
        String oldContentType =
                !ObjectUtils.isEmpty(oldContentTypes) ? oldContentTypes[0] : getVersion().getContentType();
      saajPart.setMimeHeader(TransportConstants.HEADER_CONTENT_TYPE,
          CONTENT_TYPE_XOP + ";type=" + '"' + oldContentType + '"');
    }

    @Override
    @SuppressWarnings("unchecked")
    public Iterator<Attachment> getAttachments() throws AttachmentException {
      Iterator<AttachmentPart> iterator = getSaajMessage().getAttachments();
        return new SaajAttachmentIterator(iterator);
    }

    @Override
    @SuppressWarnings("unchecked")
    public Attachment getAttachment(String contentId) {
        Assert.hasLength(contentId, "contentId must not be empty");
        MimeHeaders mimeHeaders = new MimeHeaders();
        mimeHeaders.setHeader(TransportConstants.HEADER_CONTENT_ID, contentId);
      Iterator<AttachmentPart> iterator = getSaajMessage().getAttachments(mimeHeaders);
        if (!iterator.hasNext()) {
            return null;
        }
        AttachmentPart saajAttachment = iterator.next();
        return new SaajAttachment(saajAttachment);
    }

    @Override
    public Attachment addAttachment(String contentId, DataHandler dataHandler) {
        Assert.hasLength(contentId, "contentId must not be empty");
        Assert.notNull(dataHandler, "dataHandler must not be null");
      SOAPMessage message = getSaajMessage();
      AttachmentPart attachmentPart = message.createAttachmentPart(dataHandler);
      message.addAttachmentPart(attachmentPart);
      attachmentPart.setContentId(contentId);
        attachmentPart.setMimeHeader(TransportConstants.HEADER_CONTENT_TRANSFER_ENCODING,
            "binary");
        return new SaajAttachment(attachmentPart);
    }

    public String toString() {
        StringBuilder builder = new StringBuilder("SaajSoapMessage");
        try {
          SOAPEnvelope envelope = saajMessage.getSOAPPart().getEnvelope();
            if (envelope != null) {
              SOAPBody body = envelope.getBody();
                if (body != null) {
                    SOAPElement bodyElement = SaajUtils.getFirstBodyElement(body);
                    if (bodyElement != null) {
                        builder.append(' ');
                      builder.append(bodyElement.getElementQName());
                    }
                }
            }
        }
        catch (SOAPException ex) {
            // ignore
        }
        return builder.toString();
    }

    private static class SaajAttachmentIterator implements Iterator<Attachment> {

        private final Iterator<AttachmentPart> saajIterator;

        private SaajAttachmentIterator(Iterator<AttachmentPart> saajIterator) {
            this.saajIterator = saajIterator;
        }

        @Override
        public boolean hasNext() {
            return saajIterator.hasNext();
        }

        @Override
        public Attachment next() {
            AttachmentPart saajAttachment = saajIterator.next();
            return new SaajAttachment(saajAttachment);
        }

        @Override
        public void remove() {
            saajIterator.remove();
        }
    }

}
TOP

Related Classes of org.springframework.ws.soap.saaj.SaajSoapMessage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.