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

org.apache.cxf.ws.addressing.soap.MAPCodec Maven / Gradle / Ivy

There is a newer version: 4.0.5
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.ws.addressing.soap;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

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.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor;
import org.apache.cxf.common.jaxb.JAXBUtils;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.ws.addressing.AddressingProperties;
import org.apache.cxf.ws.addressing.AttributedURIType;
import org.apache.cxf.ws.addressing.ContextUtils;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.apache.cxf.ws.addressing.EndpointReferenceUtils;
import org.apache.cxf.ws.addressing.JAXWSAConstants;
import org.apache.cxf.ws.addressing.MAPAggregator;
import org.apache.cxf.ws.addressing.Names;
import org.apache.cxf.ws.addressing.ReferenceParametersType;
import org.apache.cxf.ws.addressing.RelatesToType;
import org.apache.cxf.ws.addressing.VersionTransformer.Names200408;


/**
 * SOAP interceptor responsible for {en|de}coding the Message Addressing
 * Properties for {outgo|incom}ing messages.
 */
public class MAPCodec extends AbstractSoapInterceptor {
    public static final MAPCodec INSTANCE = new MAPCodec();

    private static final Logger LOG = LogUtils.getL7dLogger(MAPCodec.class);
    private static final String IS_REFERENCE_PARAM_ATTR_NAME = "IsReferenceParameter";
    private static final ResourceBundle BUNDLE = LOG.getResourceBundle();
    private static final String DECOUPLED_FAULT_SUPPORT =
        "org.apache.cxf.ws.addressing.decoupled_fault_support";

    /**
     * REVISIT: map usage that the *same* interceptor instance
     * is used in all chains.
     */
    protected final Map uncorrelatedExchanges
        = new ConcurrentHashMap<>();

    private VersionTransformer transformer;
    private HeaderFactory headerFactory;

    /**
     * Constructor.
     */
    public MAPCodec() {
        super(Phase.PRE_PROTOCOL);
        transformer = new VersionTransformer(this);
    }

    public static synchronized MAPCodec getInstance(Bus bus) {
        MAPCodec mc = bus.getExtension(MAPCodec.class);
        if (mc == null) {
            return createMAPCodec(bus);
        }
        return mc;
    }
    private static synchronized MAPCodec createMAPCodec(Bus bus) {
        MAPCodec mc = bus.getExtension(MAPCodec.class);
        if (mc == null) {
            bus.setExtension(new MAPCodec(), MAPCodec.class);
            mc = bus.getExtension(MAPCodec.class);
        }
        return mc;
    }

    public Map getUncorrelatedExchanges() {
        return uncorrelatedExchanges;
    }

    /**
     * @return the set of SOAP headers understood by this handler
     */
    public Set getUnderstoodHeaders() {
        return VersionTransformer.HEADERS;
    }

    /**
     * Invoked for normal processing of inbound and outbound messages.
     *
     * @param message the messsage
     */
    public void handleMessage(SoapMessage message) {
        mediate(message);
    }

    /**
     * Invoked when unwinding normal interceptor chain when a fault occurred.
     *
     * @param message the messsage message
     */
    public void handleFault(SoapMessage message) {
        if (!message.getExchange().isOneWay()) {
            AddressingProperties maps = ContextUtils.retrieveMAPs(message, false, true, false);
            if (ContextUtils.isRequestor(message)
                && maps != null) {
                //fault occurred trying to send the message, remove it
                uncorrelatedExchanges.remove(maps.getMessageID().getValue());
            } else if (!ContextUtils.isRequestor(message)
                && maps == null
                && !message.containsKey(MAPAggregator.class.getName())) {
                //fault occurred while processing the incoming message, but possibly
                //before the MAPAggregator was called.   We need to see if we can
                //try and map this if at all possible so a FaultTo/ReplyTo can
                //be properly determined to get the fault back to the rightful
                //place.
                for (Interceptor i : message.getInterceptorChain()) {
                    if (i instanceof MAPAggregator) {
                        try {
                            MAPAggregator agg = (MAPAggregator)i;
                            agg.handleMessage(message);
                        } catch (Throwable t) {
                            //ignore
                        }
                        return;
                    }
                }
            }
        }
        if (MessageUtils.getContextualBoolean(message, DECOUPLED_FAULT_SUPPORT, false)) {
            new DecoupledFaultHandler().handleFault(message);
        }
    }

    /**
     * Mediate message flow, performing MAP {en|de}coding.
     *
     * @param message the message message
     */
    private void mediate(SoapMessage message) {
        if (!MessageUtils.getContextualBoolean(message, MAPAggregator.ADDRESSING_DISABLED, false)) {
            if (ContextUtils.isOutbound(message)) {
                encode(message, ContextUtils.retrieveMAPs(message, false, true));
            } else if (null == ContextUtils.retrieveMAPs(message, false, false, false)) {
                AddressingProperties maps = decode(message);
                ContextUtils.storeMAPs(maps, message, false);
                markPartialResponse(message, maps);
                restoreExchange(message, maps);

                if (maps != null
                    && !MessageUtils.isRequestor(message)
                    && message.getExchange().getBindingOperationInfo() == null
                    && !MessageUtils.isOutbound(message)
                    && maps.getAction() != null) {
                    //try and use the Action from the maps to find the operation
                    String action = maps.getAction().getValue();
                    if (action != null) {
                        boolean strict = MessageUtils.getContextualBoolean(message,
                                                                           "ws-addressing.strict.action.checking",
                                                                           false);
                        SoapActionInInterceptor.getAndSetOperation(message, action, strict);
                    }
                }
            }
        }
    }

    /**
     * Encode the current MAPs in protocol-specific headers.
     *
     * @param message the messsage message
     * @param maps the MAPs to encode
     */
    private void encode(SoapMessage message,
                        AddressingProperties maps) {
        if (maps != null) {
            cacheExchange(message, maps);
            LOG.log(Level.FINE, "Outbound WS-Addressing headers");
            try {
                List
header = message.getHeaders(); discardMAPs(header, maps); JAXBContext jaxbContext = org.apache.cxf.ws.addressing.VersionTransformer.getExposedJAXBContext( maps.getNamespaceURI()); QName duplicate = maps.getDuplicate(); encodeAsExposed(maps, message, maps.getAction(), Names.WSA_ACTION_QNAME, AttributedURIType.class, jaxbContext); if (Names.WSA_ACTION_QNAME.equals(duplicate)) { encodeAsExposed(maps, message, maps.getAction(), Names.WSA_ACTION_QNAME, AttributedURIType.class, jaxbContext); } encodeAsExposed(maps, message, maps.getMessageID(), Names.WSA_MESSAGEID_QNAME, AttributedURIType.class, jaxbContext); if (Names.WSA_MESSAGEID_QNAME.equals(duplicate)) { encodeAsExposed(maps, message, maps.getMessageID(), Names.WSA_MESSAGEID_QNAME, AttributedURIType.class, jaxbContext); } encodeAsExposed(maps, message, maps.getTo(), Names.WSA_TO_QNAME, AttributedURIType.class, jaxbContext); if (Names.WSA_TO_QNAME.equals(duplicate)) { encodeAsExposed(maps, message, maps.getTo(), Names.WSA_TO_QNAME, AttributedURIType.class, jaxbContext); } if (needsReplyTo(maps, message)) { encodeAsExposed(maps, message, maps.getReplyTo(), Names.WSA_REPLYTO_QNAME, EndpointReferenceType.class, jaxbContext); if (Names.WSA_REPLYTO_QNAME.equals(duplicate)) { encodeAsExposed(maps, message, maps.getReplyTo(), Names.WSA_REPLYTO_QNAME, EndpointReferenceType.class, jaxbContext); } } encodeAsExposed(maps, message, maps.getRelatesTo(), Names.WSA_RELATESTO_QNAME, RelatesToType.class, jaxbContext); if (Names.WSA_RELATESTO_QNAME.equals(duplicate)) { encodeAsExposed(maps, message, maps.getRelatesTo(), Names.WSA_RELATESTO_QNAME, RelatesToType.class, jaxbContext); } encodeAsExposed(maps, message, maps.getFrom(), Names.WSA_FROM_QNAME, EndpointReferenceType.class, jaxbContext); if (Names.WSA_FROM_QNAME.equals(duplicate)) { encodeAsExposed(maps, message, maps.getFrom(), Names.WSA_FROM_QNAME, EndpointReferenceType.class, jaxbContext); } if (needsFaultTo(maps)) { encodeAsExposed(maps, message, maps.getFaultTo(), Names.WSA_FAULTTO_QNAME, EndpointReferenceType.class, jaxbContext); if (Names.WSA_FAULTTO_QNAME.equals(duplicate)) { encodeAsExposed(maps, message, maps.getFaultTo(), Names.WSA_FAULTTO_QNAME, EndpointReferenceType.class, jaxbContext); } } encodeReferenceParameters(maps, message, jaxbContext); maps.setDuplicate(null); propogateAction(maps.getAction(), message); applyMAPValidation(message); } catch (JAXBException je) { LOG.log(Level.WARNING, "SOAP_HEADER_ENCODE_FAILURE_MSG", je); } } } private boolean needsReplyTo(AddressingProperties maps, SoapMessage m) { if (!MessageUtils.getContextualBoolean(m, "ws-addressing.write.optional.replyto", true)) { if (ContextUtils.isNoneAddress(maps.getReplyTo()) && m.getExchange().isOneWay()) { //one-way + none, not needed return false; } if (ContextUtils.isAnonymousAddress(maps.getReplyTo())) { //anonymous is the default if not specified, not needed return false; } } return maps.getReplyTo() != null && maps.getReplyTo().getAddress() != null && maps.getReplyTo().getAddress().getValue() != null && !(Names200408.WSA_NAMESPACE_NAME.equals(maps.getNamespaceURI()) && maps.getReplyTo().getAddress().getValue() .equals(ContextUtils.getNoneEndpointReference().getAddress().getValue())); } private boolean needsFaultTo(AddressingProperties maps) { return maps.getFaultTo() != null && maps.getFaultTo().getAddress() != null && maps.getFaultTo().getAddress().getValue() != null && !maps.getFaultTo().getAddress().getValue() .equals(maps.getReplyTo().getAddress().getValue()); } private void encodeReferenceParameters(AddressingProperties maps, SoapMessage msg, JAXBContext ctx) throws JAXBException { Element header = null; EndpointReferenceType toEpr = maps.getToEndpointReference(); if (null != toEpr) { ReferenceParametersType params = toEpr.getReferenceParameters(); if (null != params) { for (Object o : params.getAny()) { if (o instanceof Element || o instanceof JAXBElement) { if (header == null) { header = getHeaderFactory().getHeader(msg.getVersion()); } if (o instanceof Element) { Element e = (Element)o; Node importedNode = header.getOwnerDocument().importNode(e, true); header.appendChild(importedNode); } else { JAXBElement jaxbEl = (JAXBElement) o; ctx.createMarshaller().marshal(jaxbEl, header); } Element lastAdded = (Element)header.getLastChild(); header.removeChild(lastAdded); addIsReferenceParameterMarkerAttribute(lastAdded, maps.getNamespaceURI()); Header holder = new Header(new QName(lastAdded.getNamespaceURI(), lastAdded.getLocalName()), lastAdded); msg.getHeaders().add(holder); } else { LOG.log(Level.WARNING, "IGNORE_NON_ELEMENT_REF_PARAM_MSG", o); } } } } } private void addIsReferenceParameterMarkerAttribute(Element lastAdded, String namespaceURI) { String pfx = lastAdded.lookupPrefix(namespaceURI); if (StringUtils.isEmpty(pfx)) { //attributes cannot be in empty namespace... if (lastAdded.lookupNamespaceURI(JAXWSAConstants.WSA_PREFIX) == null) { pfx = JAXWSAConstants.WSA_PREFIX; Attr attr = lastAdded.getOwnerDocument() .createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:wsa"); attr.setValue(namespaceURI); lastAdded.setAttributeNodeNS(attr); } else if (lastAdded.lookupNamespaceURI(JAXWSAConstants.WSA_PREFIX).equals(namespaceURI)) { pfx = JAXWSAConstants.WSA_PREFIX; } else { int cnt = 1; while (lastAdded.lookupNamespaceURI(JAXWSAConstants.WSA_PREFIX + cnt) != null) { cnt++; } pfx = JAXWSAConstants.WSA_PREFIX + cnt; Attr attr = lastAdded.getOwnerDocument() .createAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:wsa" + cnt); attr.setValue(namespaceURI); lastAdded.setAttributeNodeNS(attr); } } Attr isRefParamAttr = lastAdded.getOwnerDocument().createAttributeNS(namespaceURI, pfx + ":" + IS_REFERENCE_PARAM_ATTR_NAME); isRefParamAttr.setTextContent("1"); lastAdded.setAttributeNodeNS(isRefParamAttr); } /** * Encode message in exposed version. * * @param maps the MAPs, where getNamespceURI() specifies the WS-Addressing * version to expose * @param message the SoapMessage * @param value the value to encode * @param name the QName for the header * @param clz the class * @param context the JAXB context to use */ private void encodeAsExposed(AddressingProperties maps, SoapMessage message, T value, QName name, Class clz, JAXBContext context) throws JAXBException { if (value != null) { LOG.log(Level.FINE, "{0} : {1}", new Object[] {name.getLocalPart(), getLogText(value)}); boolean mu = maps.isRequired() || maps.getMustUnderstand().contains(name); transformer.encodeAsExposed(message, maps.getNamespaceURI(), value, name.getLocalPart(), clz, context, mu); } } /** * Decode the MAPs from protocol-specific headers. * * @param message the SOAP message * @return the decoded MAPs * @exception SOAPFaultException if decoded MAPs are invalid */ public AddressingProperties unmarshalMAPs(SoapMessage message) { // REVISIT generate MessageAddressingHeaderRequired fault if an // expected header is missing AddressingProperties maps = null; Unmarshaller unmarshaller = null; try { List
header = message.getHeaders(); if (header != null) { LOG.log(Level.FINE, "Inbound WS-Addressing headers"); Set referenceParameterHeaders = null; QName invalidCardinalityQName = null; Iterator
iter = header.iterator(); while (iter.hasNext()) { Header hdr = iter.next(); if (hdr.getObject() instanceof Element) { Element headerElement = (Element)hdr.getObject(); String headerURI = headerElement.getNamespaceURI(); // Need to check the uri before getting unmarshaller else // would get wrong unmarshaller and fail to process required // headers. if (org.apache.cxf.ws.addressing.VersionTransformer.isSupported(headerURI)) { if (unmarshaller == null) { JAXBContext jaxbContext = org.apache.cxf.ws.addressing.VersionTransformer.getExposedJAXBContext(headerURI); unmarshaller = jaxbContext.createUnmarshaller(); unmarshaller.setEventHandler(null); } if (maps == null) { maps = new AddressingProperties(); maps.exposeAs(headerURI); } String localName = headerElement.getLocalName(); if (Names.WSA_MESSAGEID_NAME.equals(localName)) { invalidCardinalityQName = maps.getMessageID() != null ? Names.WSA_MESSAGEID_QNAME : null; maps.setMessageID(decodeAsNative( headerURI, AttributedURIType.class, headerElement, unmarshaller)); } else if (Names.WSA_TO_NAME.equals(localName)) { invalidCardinalityQName = maps.getTo() != null ? Names.WSA_TO_QNAME : null; AttributedURIType addr = decodeAsNative( headerURI, AttributedURIType.class, headerElement, unmarshaller); maps.setTo(EndpointReferenceUtils.getEndpointReference(addr)); } else if (Names.WSA_FROM_NAME.equals(localName)) { invalidCardinalityQName = maps.getFrom() != null ? Names.WSA_FROM_QNAME : null; maps.setFrom(decodeAsNative( headerURI, EndpointReferenceType.class, headerElement, unmarshaller)); } else if (Names.WSA_REPLYTO_NAME.equals(localName)) { invalidCardinalityQName = maps.getReplyTo() != null ? Names.WSA_REPLYTO_QNAME : null; maps.setReplyTo(decodeAsNative( headerURI, EndpointReferenceType.class, headerElement, unmarshaller)); } else if (Names.WSA_FAULTTO_NAME.equals(localName)) { invalidCardinalityQName = maps.getFaultTo() != null ? Names.WSA_FAULTTO_QNAME : null; maps.setFaultTo(decodeAsNative( headerURI, EndpointReferenceType.class, headerElement, unmarshaller)); } else if (Names.WSA_RELATESTO_NAME.equals(localName)) { maps.setRelatesTo(decodeAsNative( headerURI, RelatesToType.class, headerElement, unmarshaller)); } else if (Names.WSA_ACTION_NAME.equals(localName)) { invalidCardinalityQName = maps.getAction() != null ? Names.WSA_ACTION_QNAME : null; maps.setAction(decodeAsNative( headerURI, AttributedURIType.class, headerElement, unmarshaller)); } } else if (null != headerElement.getAttribute(IS_REFERENCE_PARAM_ATTR_NAME)) { if (null == referenceParameterHeaders) { referenceParameterHeaders = new HashSet<>(); } referenceParameterHeaders.add(headerElement); } else if (headerURI.contains(Names.WSA_NAMESPACE_PATTERN)) { LOG.log(Level.WARNING, "UNSUPPORTED_VERSION_MSG", headerURI); } } } if (maps != null && !MessageUtils.isRequestor(message) && maps.getReplyTo() == null) { //per spec, if unspecified, replyTo is anon AttributedURIType address = ContextUtils.getAttributedURI(Names.WSA_ANONYMOUS_ADDRESS); EndpointReferenceType replyTo = ContextUtils.WSA_OBJECT_FACTORY.createEndpointReferenceType(); replyTo.setAddress(address); maps.setReplyTo(replyTo); } if (null != referenceParameterHeaders && null != maps) { decodeReferenceParameters(referenceParameterHeaders, maps, unmarshaller); } if (invalidCardinalityQName != null) { storeInvalidCardinalityFault(message, invalidCardinalityQName); } } } catch (JAXBException je) { LOG.log(Level.WARNING, "SOAP_HEADER_DECODE_FAILURE_MSG", je); } finally { JAXBUtils.closeUnmarshaller(unmarshaller); } return maps; } private void storeInvalidCardinalityFault(SoapMessage message, QName wsaHeaderName) { LOG.log(Level.WARNING, "INVALID_CARDINALITY_MESSAGE", wsaHeaderName); String reason = BUNDLE.getString("INVALID_ADDRESSING_PROPERTY_MESSAGE"); ContextUtils.storeMAPFaultName(Names.INVALID_CARDINALITY_NAME, message); ContextUtils.storeMAPFaultReason(reason, message); } private void decodeReferenceParameters(Set referenceParameterHeaders, AddressingProperties maps, Unmarshaller unmarshaller) throws JAXBException { EndpointReferenceType toEpr = maps.getToEndpointReference(); if (null != toEpr) { for (Element e : referenceParameterHeaders) { if (DOMUtils.getChild(e, Node.ELEMENT_NODE) == null) { JAXBElement el = unmarshaller.unmarshal(e, String.class); ContextUtils.applyReferenceParam(toEpr, el); } else { ContextUtils.applyReferenceParam(toEpr, e); } } } } /** * Decodes a MAP from a exposed version. * * @param encodedAs specifies the encoded version * @param clz the class * @param headerElement the SOAP header element * @param unmarshaller the JAXB unmarshaller to use * @return the decoded value */ public T decodeAsNative(String encodedAs, Class clz, Element headerElement, Unmarshaller unmarshaller) throws JAXBException { T value = clz.cast(transformer.decodeAsNative(encodedAs, clz, headerElement, unmarshaller)); LOG.log(Level.FINE, "{0} : {1}", new Object[] {headerElement.getLocalName(), getLogText(value)}); return value; } /** * Return a text representation of a header value for logging. * * @param header type * @param value header value * @return */ private String getLogText(T value) { String text = "unknown"; if (value == null) { text = "null"; } else if (value instanceof AttributedURIType) { text = ((AttributedURIType)value).getValue(); } else if (value instanceof EndpointReferenceType) { text = ((EndpointReferenceType)value).getAddress() != null ? ((EndpointReferenceType)value).getAddress().getValue() : "null"; } else if (value instanceof RelatesToType) { text = ((RelatesToType)value).getValue(); } return text; } /** * Decode the MAPs from protocol-specific headers. * * @param message the messsage * @return the decoded MAPs * @exception SOAPFaultException if decoded MAPs are invalid */ private AddressingProperties decode(SoapMessage message) { // REVISIT generate MessageAddressingHeaderRequired fault if an // expected header is missing return unmarshalMAPs(message); } /** * Encodes an MAP as a SOAP header. * * @param message the message to store the headers on * @param value the value to encode * @param qname the QName for the header * @param clz the class * @param ctx the JAXBContent * @param mustUnderstand */ protected void encodeMAP(SoapMessage message, T value, QName qname, Class clz, JAXBContext ctx, boolean mustUnderstand) throws JAXBException { JAXBDataBinding jaxbDataBinding = new JAXBDataBinding(ctx); SoapHeader h = new SoapHeader(qname, new JAXBElement(qname, clz, value), jaxbDataBinding); h.setMustUnderstand(mustUnderstand); message.getHeaders().add(h); } /** * Decodes a MAP from a SOAP header. * * @param clz the class * @param headerElement the SOAP header element * @param unmarshaller the JAXB unmarshaller to use * @return the decoded value */ protected T decodeMAP(Class clz, Element headerElement, Unmarshaller unmarshaller) throws JAXBException { JAXBElement element = unmarshaller.unmarshal(headerElement, clz); return element.getValue(); } /** * Discard any pre-existing MAP headers - this may occur if the runtime * re-uses a SOAP message. * * @param header the SOAP header * @param maps the current MAPs */ private void discardMAPs(List
header, AddressingProperties maps) { Iterator
iter = header.iterator(); while (iter.hasNext()) { Header hdr = iter.next(); if (Names.WSA_NAMESPACE_NAME.equals(hdr.getName().getNamespaceURI()) || Names200408.WSA_NAMESPACE_NAME.equals(hdr.getName().getNamespaceURI())) { iter.remove(); } } } /** * Propagate action to SOAPAction header * * @param action the Action property * @param message the SOAP message */ private void propogateAction(AttributedURIType action, SoapMessage message) { if (!(action == null || "".equals(action.getValue()))) { Map> mimeHeaders = CastUtils.cast((Map) message.get(Message.MIME_HEADERS)); if (mimeHeaders != null) { List soapActionHeaders = mimeHeaders.get("SOAPAction"); // only propogate to SOAPAction header if currently non-empty if (!(soapActionHeaders == null || soapActionHeaders.isEmpty() || "".equals(soapActionHeaders.get(0)))) { LOG.log(Level.FINE, "encoding wsa:Action in SOAPAction header {0}", action.getValue()); soapActionHeaders.clear(); soapActionHeaders.add("\"" + action.getValue() + "\""); } } } } /** * Apply results of validation of incoming MAPs. * * @param message the message * @exception SOAPFaultException if the MAPs are invalid * @exception SOAPException if SOAPFault cannot be constructed */ private void applyMAPValidation(SoapMessage message) { String faultName = ContextUtils.retrieveMAPFaultName(message); if (faultName != null) { String reason = ContextUtils.retrieveMAPFaultReason(message); throw createSOAPFaut(faultName, Names.WSA_NAMESPACE_NAME, reason); } } /** * Create a SoapFault. * * @param localName the fault local name * @param namespace the fault namespace * @param reason the fault reason * @return a new SoapFault */ private SoapFault createSOAPFaut(String localName, String namespace, String reason) { return new SoapFault(reason, new QName(namespace, localName)); } /** * Cache exchange for correlated response * * @param message the current message * @param maps the addressing properties */ private void cacheExchange(SoapMessage message, AddressingProperties maps) { if (ContextUtils.isRequestor(message) && !message.getExchange().isOneWay()) { uncorrelatedExchanges.put(maps.getMessageID().getValue(), message.getExchange()); } } /** * Restore exchange for correlated response * * @param message the current message * @param maps the addressing properties */ private void restoreExchange(SoapMessage message, AddressingProperties maps) { if (maps != null && maps.getRelatesTo() != null && !Names.WSA_UNSPECIFIED_RELATIONSHIP.equals(maps.getRelatesTo().getValue()) && isRelationshipReply(maps.getRelatesTo())) { Exchange correlatedExchange = uncorrelatedExchanges.remove(maps.getRelatesTo().getValue()); if (correlatedExchange != null) { synchronized (correlatedExchange) { message.setExchange(correlatedExchange); } } else if (ContextUtils.isRequestor(message) && !message.getExchange().isOneWay()) { if (ContextUtils.retrieveDeferUncorrelatedMessageAbort(message)) { LOG.fine("deferring uncorrelated message abort"); ContextUtils.storeDeferredUncorrelatedMessageAbort(message); } else if (!MessageUtils.getContextualBoolean(message, "org.apache.cxf.ws.addressing.MAPAggregator.addressingDisabled", false)) { //see if it can directly be correlated with the out message: Message outmsg = message.getExchange().getOutMessage(); AddressingProperties outp = outmsg != null ? ContextUtils.retrieveMAPs(outmsg, false, true, false) : null; if (outp == null || !outp.getMessageID().getValue().equals(maps.getRelatesTo().getValue())) { LOG.log(Level.WARNING, "CORRELATION_FAILURE_MSG"); message.getInterceptorChain().abort(); } } } } else if (isRequestor(message)) { if (maps == null) { Message m = message.getExchange().getOutMessage(); maps = ContextUtils.retrieveMAPs(m, false, true, false); if (maps != null) { Exchange ex = uncorrelatedExchanges.get(maps.getMessageID().getValue()); if (ex == message.getExchange()) { uncorrelatedExchanges.remove(maps.getMessageID().getValue()); LOG.log(Level.WARNING, "RESPONSE_NOT_USING_WSADDRESSING"); } } } else if (maps.getRelatesTo() == null && maps.getAction() != null && (Names.WSA_DEFAULT_FAULT_ACTION.equals(maps.getAction().getValue()) || Names.WSA_DEFAULT_SOAP_FAULT_ACTION.equals(maps.getAction().getValue()) || "http://docs.oasis-open.org/wsrf/fault".equals(maps.getAction().getValue()))) { //there is an Action header that points to a fault and no relatesTo. Use the out map for the ID Message m = message.getExchange().getOutMessage(); maps = ContextUtils.retrieveMAPs(m, false, true, false); if (maps != null) { uncorrelatedExchanges.remove(maps.getMessageID().getValue()); } } } } /** * @param relatesTo the current RelatesTo * @return true iff the relationship type is reply */ private boolean isRelationshipReply(RelatesToType relatesTo) { return Names.WSA_RELATIONSHIP_REPLY.equals(relatesTo.getRelationshipType()); } /** * Marks a message as partial response * * @param message the current message */ private void markPartialResponse(SoapMessage message, AddressingProperties maps) { if (ContextUtils.isRequestor(message) && null != maps && (null == maps.getRelatesTo() || (null != maps.getRelatesTo() && Names.WSA_UNSPECIFIED_RELATIONSHIP.equals(maps.getRelatesTo().getValue())))) { message.put(Message.PARTIAL_RESPONSE_MESSAGE, Boolean.TRUE); } } protected HeaderFactory getHeaderFactory() { if (headerFactory == null) { headerFactory = new HeaderFactory() { public Element getHeader(SoapVersion soapversion) { Document doc = DOMUtils.getEmptyDocument(); return doc.createElementNS(soapversion.getHeader().getNamespaceURI(), soapversion.getHeader().getLocalPart()); } }; } return headerFactory; } protected void setHeaderFactory(HeaderFactory factory) { headerFactory = factory; } public interface HeaderFactory { Element getHeader(SoapVersion soapversion); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy