All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.cxf.binding.soap.interceptor.SoapOutInterceptor Maven / Gradle / Ivy

There is a newer version: 2.7.18
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.apache.cxf.binding.soap.interceptor;


import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.w3c.dom.Element;

import org.apache.cxf.Bus;
import org.apache.cxf.binding.soap.SoapFault;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.SoapVersion;
import org.apache.cxf.binding.soap.model.SoapHeaderInfo;
import org.apache.cxf.common.i18n.BundleUtils;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.databinding.DataBinding;
import org.apache.cxf.databinding.DataWriter;
import org.apache.cxf.headers.Header;
import org.apache.cxf.headers.HeaderManager;
import org.apache.cxf.headers.HeaderProcessor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.WriteOnCloseOutputStream;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageContentsList;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.model.BindingMessageInfo;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.MessagePartInfo;
import org.apache.cxf.service.model.ServiceModelUtil;
import org.apache.cxf.staxutils.DelegatingXMLStreamWriter;
import org.apache.cxf.staxutils.StaxUtils;

public class SoapOutInterceptor extends AbstractSoapInterceptor {
    public static final String WROTE_ENVELOPE_START = "wrote.envelope.start";
    
    private static final ResourceBundle BUNDLE = BundleUtils.getBundle(SoapOutInterceptor.class);
    
    private Bus bus;
    
    public SoapOutInterceptor(Bus b) {
        super(Phase.WRITE);
        bus = b;
    }
    public SoapOutInterceptor(Bus b, String phase) {
        super(phase);
        bus = b;
    }
    
    public void handleMessage(SoapMessage message) {
        // Yes this is ugly, but it avoids us from having to implement any kind of caching strategy
        boolean wroteStart = MessageUtils.isTrue(message.get(WROTE_ENVELOPE_START));
        if (!wroteStart) {
            writeSoapEnvelopeStart(message);
            
            OutputStream os = message.getContent(OutputStream.class);
            // Unless we're caching the whole message in memory skip the envelope writing
            // if there's a fault later.
            if (!(os instanceof WriteOnCloseOutputStream) && !MessageUtils.isDOMPresent(message)) {
                message.put(WROTE_ENVELOPE_START, Boolean.TRUE);
            }
        }

        // Add a final interceptor to write end elements
        message.getInterceptorChain().add(new SoapOutEndingInterceptor());
    }
    
    private void writeSoapEnvelopeStart(final SoapMessage message) {
        final SoapVersion soapVersion = message.getVersion();
        try {            
            XMLStreamWriter xtw = message.getContent(XMLStreamWriter.class);
            String soapPrefix = xtw.getPrefix(soapVersion.getNamespace());
            if (StringUtils.isEmpty(soapPrefix)) {
                soapPrefix = "soap";
            }
            if (message.hasAdditionalEnvNs()) {
                Map nsMap = message.getEnvelopeNs();
                for (Map.Entry entry : nsMap.entrySet()) {
                    if (soapVersion.getNamespace().equals(entry.getValue())) {
                        soapPrefix = entry.getKey();
                    }
                }
                xtw.setPrefix(soapPrefix, soapVersion.getNamespace());
                xtw.writeStartElement(soapPrefix, 
                                      soapVersion.getEnvelope().getLocalPart(),
                                      soapVersion.getNamespace());
                xtw.writeNamespace(soapPrefix, soapVersion.getNamespace());
                for (Map.Entry entry : nsMap.entrySet()) {
                    if (!soapVersion.getNamespace().equals(entry.getValue())) {
                        xtw.writeNamespace(entry.getKey(), entry.getValue());
                    }
                }                
            } else {
                xtw.setPrefix(soapPrefix, soapVersion.getNamespace());
                xtw.writeStartElement(soapPrefix, 
                                      soapVersion.getEnvelope().getLocalPart(),
                                      soapVersion.getNamespace());
                String s2 = xtw.getPrefix(soapVersion.getNamespace());
                if (StringUtils.isEmpty(s2) || soapPrefix.equals(s2)) {
                    xtw.writeNamespace(soapPrefix, soapVersion.getNamespace());
                } else {
                    soapPrefix = s2;
                }
            }
            boolean preexistingHeaders = message.hasHeaders();

            if (preexistingHeaders) {
                xtw.writeStartElement(soapPrefix, 
                                      soapVersion.getHeader().getLocalPart(),
                                      soapVersion.getNamespace());   
                List
hdrList = message.getHeaders(); for (Header header : hdrList) { XMLStreamWriter writer = xtw; if (header instanceof SoapHeader) { SoapHeader soapHeader = (SoapHeader)header; writer = new SOAPHeaderWriter(xtw, soapHeader, soapVersion, soapPrefix); } DataBinding b = header.getDataBinding(); if (b == null) { HeaderProcessor hp = bus.getExtension(HeaderManager.class) .getHeaderProcessor(header.getName().getNamespaceURI()); if (hp != null) { b = hp.getDataBinding(); } } if (b != null) { MessagePartInfo part = new MessagePartInfo(header.getName(), null); part.setConcreteName(header.getName()); b.createWriter(XMLStreamWriter.class) .write(header.getObject(), part, writer); } else { Element node = (Element)header.getObject(); StaxUtils.copy(node, writer); } } } boolean endedHeader = handleHeaderPart(preexistingHeaders, message, soapPrefix); if (preexistingHeaders && !endedHeader) { xtw.writeEndElement(); } xtw.writeStartElement(soapPrefix, soapVersion.getBody().getLocalPart(), soapVersion.getNamespace()); // Interceptors followed such as Wrapped/RPC/Doc Interceptor will write SOAP body } catch (XMLStreamException e) { throw new SoapFault( new org.apache.cxf.common.i18n.Message("XML_WRITE_EXC", BUNDLE), e, soapVersion.getSender()); } } private boolean handleHeaderPart(boolean preexistingHeaders, SoapMessage message, String soapPrefix) { //add MessagePart to soapHeader if necessary boolean endedHeader = false; Exchange exchange = message.getExchange(); BindingOperationInfo bop = (BindingOperationInfo)exchange.get(BindingOperationInfo.class .getName()); if (bop == null) { return endedHeader; } XMLStreamWriter xtw = message.getContent(XMLStreamWriter.class); boolean startedHeader = false; BindingOperationInfo unwrappedOp = bop; if (bop.isUnwrapped()) { unwrappedOp = bop.getWrappedOperation(); } boolean client = isRequestor(message); BindingMessageInfo bmi = client ? unwrappedOp.getInput() : unwrappedOp.getOutput(); BindingMessageInfo wrappedBmi = client ? bop.getInput() : bop.getOutput(); if (bmi == null) { return endedHeader; } List parts = wrappedBmi.getMessageInfo().getMessageParts(); if (parts.size() > 0) { MessageContentsList objs = MessageContentsList.getContentsList(message); if (objs == null) { return endedHeader; } SoapVersion soapVersion = message.getVersion(); List headers = bmi.getExtensors(SoapHeaderInfo.class); if (headers == null) { return endedHeader; } for (SoapHeaderInfo header : headers) { MessagePartInfo part = header.getPart(); if (wrappedBmi != bmi) { part = wrappedBmi.getMessageInfo().addMessagePart(part.getName()); } if (part.getIndex() >= objs.size()) { // The optional out of band header is not a part of parameters of the method continue; } Object arg = objs.get(part); if (arg == null) { continue; } objs.remove(part); if (!(startedHeader || preexistingHeaders)) { try { xtw.writeStartElement(soapPrefix, soapVersion.getHeader().getLocalPart(), soapVersion.getNamespace()); } catch (XMLStreamException e) { throw new SoapFault(new org.apache.cxf.common.i18n.Message("XML_WRITE_EXC", BUNDLE), e, soapVersion.getSender()); } startedHeader = true; } DataWriter dataWriter = getDataWriter(message); dataWriter.write(arg, header.getPart(), xtw); } if (startedHeader || preexistingHeaders) { try { xtw.writeEndElement(); endedHeader = true; } catch (XMLStreamException e) { throw new SoapFault(new org.apache.cxf.common.i18n.Message("XML_WRITE_EXC", BUNDLE), e, soapVersion.getSender()); } } } return endedHeader; } protected DataWriter getDataWriter(Message message) { Service service = ServiceModelUtil.getService(message.getExchange()); DataWriter dataWriter = service.getDataBinding().createWriter(XMLStreamWriter.class); if (dataWriter == null) { throw new Fault(new org.apache.cxf.common.i18n.Message("NO_DATAWRITER", BUNDLE, service .getName())); } dataWriter.setAttachments(message.getAttachments()); return dataWriter; } public class SoapOutEndingInterceptor extends AbstractSoapInterceptor { public SoapOutEndingInterceptor() { super(SoapOutEndingInterceptor.class.getName(), Phase.WRITE_ENDING); } public void handleMessage(SoapMessage message) throws Fault { try { XMLStreamWriter xtw = message.getContent(XMLStreamWriter.class); if (xtw != null) { xtw.writeEndElement(); // Write Envelope end element xtw.writeEndElement(); xtw.writeEndDocument(); xtw.flush(); } } catch (XMLStreamException e) { SoapVersion soapVersion = message.getVersion(); throw new SoapFault(new org.apache.cxf.common.i18n.Message("XML_WRITE_EXC", BUNDLE), e, soapVersion.getSender()); } } } public static class SOAPHeaderWriter extends DelegatingXMLStreamWriter { final SoapHeader soapHeader; final SoapVersion soapVersion; final String soapPrefix; boolean firstDone; public SOAPHeaderWriter(XMLStreamWriter writer, SoapHeader header, SoapVersion version, String pfx) { super(writer); soapHeader = header; soapVersion = version; soapPrefix = pfx; } public void writeAttribute(String prefix, String uri, String local, String value) throws XMLStreamException { if (soapVersion.getNamespace().equals(uri) && (local.equals(soapVersion.getAttrNameMustUnderstand()) || local.equals(soapVersion.getAttrNameRole()))) { return; } super.writeAttribute(prefix, uri, local, value); } public void writeAttribute(String uri, String local, String value) throws XMLStreamException { if (soapVersion.getNamespace().equals(uri) && (local.equals(soapVersion.getAttrNameMustUnderstand()) || local.equals(soapVersion.getAttrNameRole()))) { return; } super.writeAttribute(uri, local, value); } private void writeSoapAttributes() throws XMLStreamException { if (!firstDone) { firstDone = true; if (!StringUtils.isEmpty(soapHeader.getActor())) { super.writeAttribute(soapPrefix, soapVersion.getNamespace(), soapVersion.getAttrNameRole(), soapHeader.getActor()); } boolean mu = soapHeader.isMustUnderstand(); if (mu) { String mul = soapVersion.getAttrValueMustUnderstand(mu); super.writeAttribute(soapPrefix, soapVersion.getNamespace(), soapVersion.getAttrNameMustUnderstand(), mul); } } } public void writeStartElement(String arg0, String arg1, String arg2) throws XMLStreamException { super.writeStartElement(arg0, arg1, arg2); writeSoapAttributes(); } public void writeStartElement(String arg0, String arg1) throws XMLStreamException { super.writeStartElement(arg0, arg1); writeSoapAttributes(); } public void writeStartElement(String arg0) throws XMLStreamException { super.writeStartElement(arg0); writeSoapAttributes(); } }; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy