Package org.springframework.ws.soap.axiom

Source Code of org.springframework.ws.soap.axiom.AxiomSoapMessage

/*
* Copyright 2005-2014 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.axiom;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Iterator;
import javax.activation.DataHandler;
import javax.xml.stream.XMLStreamException;

import org.apache.axiom.attachments.Attachments;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.impl.MTOMConstants;
import org.apache.axiom.om.impl.OMMultipartWriter;
import org.apache.axiom.soap.SOAPBody;
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;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.mime.Attachment;
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;
import org.springframework.ws.transport.TransportConstants;
import org.springframework.ws.transport.TransportOutputStream;

/**
* AXIOM-specific implementation of the {@link SoapMessage} interface. Created via the {@link AxiomSoapMessageFactory},
* wraps a {@link SOAPMessage}.
*
* @author Arjen Poutsma
* @see SOAPMessage
* @since 1.0.0
*/
public class AxiomSoapMessage extends AbstractSoapMessage implements StreamingWebServiceMessage {

    private static final String EMPTY_SOAP_ACTION = "\"\"";

    private SOAPMessage axiomMessage;

    private final SOAPFactory axiomFactory;

    private final Attachments attachments;

    private final boolean payloadCaching;

    private AxiomSoapEnvelope envelope;

    private String soapAction;

    private final boolean langAttributeOnSoap11FaultString;

    private OMOutputFormat outputFormat;

    /**
     * Create a new, empty {@code AxiomSoapMessage}.
     *
     * @param soapFactory the AXIOM SOAPFactory
     */
    public AxiomSoapMessage(SOAPFactory soapFactory) {
        this(soapFactory, true, true);
    }

    /**
     * Create a new, empty {@code AxiomSoapMessage}.
     *
     * @param soapFactory the AXIOM SOAPFactory
     */
    public AxiomSoapMessage(SOAPFactory soapFactory, boolean payloadCaching, boolean langAttributeOnSoap11FaultString) {
        SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope();
        axiomFactory = soapFactory;
      axiomMessage = axiomFactory.createSOAPMessage();
      axiomMessage.setSOAPEnvelope(soapEnvelope);
        attachments = new Attachments();
        this.payloadCaching = payloadCaching;
        this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
        soapAction = EMPTY_SOAP_ACTION;
    }

    /**
     * Create a new {@code AxiomSoapMessage} based on the given AXIOM {@code SOAPMessage}.
     *
     * @param soapMessage    the AXIOM SOAPMessage
     * @param soapAction     the value of the SOAP Action header
     * @param payloadCaching whether the contents of the SOAP body should be cached or not
     */
    public AxiomSoapMessage(SOAPMessage soapMessage,
                            String soapAction,
                            boolean payloadCaching,
                            boolean langAttributeOnSoap11FaultString) {
        this(soapMessage, new Attachments(), soapAction, payloadCaching, langAttributeOnSoap11FaultString);
    }

    /**
     * Create a new {@code AxiomSoapMessage} based on the given AXIOM {@code SOAPMessage} and attachments.
     *
     * @param soapMessage    the AXIOM SOAPMessage
     * @param attachments    the attachments
     * @param soapAction     the value of the SOAP Action header
     * @param payloadCaching whether the contents of the SOAP body should be cached or not
     */
    public AxiomSoapMessage(SOAPMessage soapMessage,
                            Attachments attachments,
                            String soapAction,
                            boolean payloadCaching,
                            boolean langAttributeOnSoap11FaultString) {
        Assert.notNull(soapMessage, "'soapMessage' must not be null");
        Assert.notNull(attachments, "'attachments' must not be null");
        axiomMessage = soapMessage;
        axiomFactory = (SOAPFactory) soapMessage.getSOAPEnvelope().getOMFactory();
        this.attachments = attachments;
        if (!StringUtils.hasLength(soapAction)) {
            soapAction = EMPTY_SOAP_ACTION;
        }
        this.soapAction = soapAction;
        this.payloadCaching = payloadCaching;
        this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
    }

    /** Return the AXIOM {@code SOAPMessage} that this {@code AxiomSoapMessage} is based on. */
    public final SOAPMessage getAxiomMessage() {
        return axiomMessage;
    }

    /**
     * Sets the AXIOM {@code SOAPMessage} that this {@code AxiomSoapMessage} is based on.
     *
     * <p>Calling this method also clears the SOAP Action property.
     */
    public final void setAxiomMessage(SOAPMessage axiomMessage) {
        Assert.notNull(axiomMessage, "'axiomMessage' must not be null");
        this.axiomMessage = axiomMessage;
        this.envelope = null;
        this.soapAction = EMPTY_SOAP_ACTION;
    }

    /**
     * Sets the {@link OMOutputFormat} to be used when writing the message.
     *
     * @see #writeTo(java.io.OutputStream)
     */
    public void setOutputFormat(OMOutputFormat outputFormat) {
        this.outputFormat = outputFormat;
    }

    @Override
    public void setStreamingPayload(StreamingPayload payload) {
        AxiomSoapBody soapBody = (AxiomSoapBody) getSoapBody();
        soapBody.setStreamingPayload(payload);
    }

    @Override
    public SoapEnvelope getEnvelope() {
        if (envelope == null) {
            try {
                envelope = new AxiomSoapEnvelope(axiomMessage.getSOAPEnvelope(), axiomFactory, payloadCaching,
                        langAttributeOnSoap11FaultString);
            }
            catch (SOAPProcessingException ex) {
                throw new AxiomSoapEnvelopeException(ex);
            }
        }
        return envelope;
    }

    @Override
    public String getSoapAction() {
        return soapAction;
    }

    @Override
    public void setSoapAction(String soapAction) {
        soapAction = SoapUtils.escapeAction(soapAction);
        this.soapAction = soapAction;
    }

    @Override
    public Document getDocument() {
        return AxiomUtils.toDocument(axiomMessage.getSOAPEnvelope());
    }

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

    @Override
    public boolean isXopPackage() {
        try {
            return MTOMConstants.MTOM_TYPE.equals(attachments.getAttachmentSpecType());
        }
        catch (OMException ex) {
            return false;
        }
        catch (NullPointerException ex) {
            // gotta love Axis2
            return false;
        }
    }

    @Override
    public boolean convertToXopPackage() {
        return false;
    }

    @Override
    public Attachment getAttachment(String contentId) {
        Assert.hasLength(contentId, "contentId must not be empty");
        if (contentId.startsWith("<") && contentId.endsWith(">")) {
            contentId = contentId.substring(1, contentId.length() - 1);
        }
        DataHandler dataHandler = attachments.getDataHandler(contentId);
        return dataHandler != null ? new AxiomAttachment(contentId, dataHandler) : null;
    }

    @Override
    public Iterator<Attachment> getAttachments() {
        return new AxiomAttachmentIterator();
    }

    @Override
    public Attachment addAttachment(String contentId, DataHandler dataHandler) {
        Assert.hasLength(contentId, "contentId must not be empty");
        Assert.notNull(dataHandler, "dataHandler must not be null");
        attachments.addDataHandler(contentId, dataHandler);
        return new AxiomAttachment(contentId, dataHandler);
    }

    @Override
    public void writeTo(OutputStream outputStream) throws IOException {
        try {

            OMOutputFormat outputFormat = getOutputFormat();
            if (outputStream instanceof TransportOutputStream) {
                TransportOutputStream transportOutputStream = (TransportOutputStream) outputStream;
                String contentType = outputFormat.getContentType();
                if (!(outputFormat.isDoingSWA() || outputFormat.isOptimized())) {
                    String charsetEncoding = axiomMessage.getCharsetEncoding();
                    contentType += "; charset=" + charsetEncoding;
                }
                SoapVersion version = getVersion();
                if (SoapVersion.SOAP_11 == version) {
                    transportOutputStream.addHeader(TransportConstants.HEADER_SOAP_ACTION, soapAction);
                    transportOutputStream.addHeader(TransportConstants.HEADER_ACCEPT, version.getContentType());
                }
                else if (SoapVersion.SOAP_12 == version) {
                    contentType += "; action=" + soapAction;
                    transportOutputStream.addHeader(TransportConstants.HEADER_ACCEPT, version.getContentType());
                }
                transportOutputStream.addHeader(TransportConstants.HEADER_CONTENT_TYPE, contentType);

            }
            if (!(outputFormat.isOptimized()) & outputFormat.isDoingSWA()) {
                writeSwAMessage(outputStream, outputFormat);
            }
            else {
                if (payloadCaching) {
                    axiomMessage.serialize(outputStream, outputFormat);
                }
                else {
                    axiomMessage.serializeAndConsume(outputStream, outputFormat);
                }
            }
            outputStream.flush();
        }
        catch (XMLStreamException ex) {
            throw new AxiomSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
        }
        catch (OMException ex) {
            throw new AxiomSoapMessageException("Could not write message to OutputStream: " + ex.getMessage(), ex);
        }
    }

    private OMOutputFormat getOutputFormat() {
        if (outputFormat != null) {
            return outputFormat;
        }
        else {
            String charsetEncoding = axiomMessage.getCharsetEncoding();

            OMOutputFormat outputFormat = new OMOutputFormat();
            outputFormat.setCharSetEncoding(charsetEncoding);
            outputFormat.setSOAP11(getVersion() == SoapVersion.SOAP_11);
            if (isXopPackage()) {
                outputFormat.setDoOptimize(true);
            }
            else if (!attachments.getContentIDSet().isEmpty()) {
                outputFormat.setDoingSWA(true);
            }
            return outputFormat;
        }
    }

    private void writeSwAMessage(OutputStream outputStream, OMOutputFormat format)
            throws XMLStreamException, UnsupportedEncodingException {
        StringWriter writer = new StringWriter();
        SOAPEnvelope envelope = axiomMessage.getSOAPEnvelope();
        if (payloadCaching) {
            envelope.serialize(writer, format);
        }
        else {
            envelope.serializeAndConsume(writer, format);
        }

      try {
        OMMultipartWriter mpw = new OMMultipartWriter(outputStream, format);

        Writer rootPartWriter = new OutputStreamWriter(mpw.writeRootPart(),
            format.getCharSetEncoding());
        rootPartWriter.write(writer.toString());
        rootPartWriter.close();

        // Get the collection of ids associated with the attachments
        for (String id: attachments.getAllContentIDs()) {
          mpw.writePart(attachments.getDataHandler(id), id);
        }

        mpw.complete();
      }
      catch (IOException ex) {
        throw new OMException("Error writing SwA message", ex);
      }
    }

    public String toString() {
        StringBuilder builder = new StringBuilder("AxiomSoapMessage");
        if (payloadCaching) {
            try {
                SOAPEnvelope envelope = axiomMessage.getSOAPEnvelope();
                if (envelope != null) {
                    SOAPBody body = envelope.getBody();
                    if (body != null) {
                        OMElement bodyElement = body.getFirstElement();
                        if (bodyElement != null) {
                            builder.append(' ');
                            builder.append(bodyElement.getQName());
                        }
                    }
                }
            }
            catch (OMException ex) {
                // ignore
            }
        }
        return builder.toString();
    }

    private class AxiomAttachmentIterator implements Iterator<Attachment> {

        private final Iterator<String> iterator;

        @SuppressWarnings("unchecked")
        private AxiomAttachmentIterator() {
            iterator = attachments.getContentIDSet().iterator();
        }

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

        @Override
        public Attachment next() {
            String contentId = iterator.next();
            DataHandler dataHandler = attachments.getDataHandler(contentId);
            return new AxiomAttachment(contentId, dataHandler);
        }

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

}
TOP

Related Classes of org.springframework.ws.soap.axiom.AxiomSoapMessage

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.