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

org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor 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.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.logging.Logger;

import javax.xml.namespace.QName;

import org.apache.cxf.binding.soap.HeaderUtil;
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.common.i18n.Message;
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.interceptor.Fault;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.interceptor.OneWayProcessorInterceptor;
import org.apache.cxf.phase.Phase;

public class MustUnderstandInterceptor extends AbstractSoapInterceptor {
    public static final String FAULT = "MustUnderstand.Fault";

    private static final Logger LOG = LogUtils.getL7dLogger(MustUnderstandInterceptor.class);

    private static final ResourceBundle BUNDLE = LOG.getResourceBundle();
    
    private MustUnderstandEndingInterceptor ending = new MustUnderstandEndingInterceptor();
        
    public MustUnderstandInterceptor() {
        super(Phase.PRE_PROTOCOL);
    }
    public MustUnderstandInterceptor(String phase) {
        super(phase);
    }

    public void handleMessage(SoapMessage soapMessage) {
        Set paramHeaders = HeaderUtil.getHeaderQNameInOperationParam(soapMessage);

        if (soapMessage.getHeaders().isEmpty() && paramHeaders.isEmpty()) {
            return;
        }
        
        SoapVersion soapVersion = soapMessage.getVersion();              
        Set
mustUnderstandHeaders = new HashSet
(); Set serviceRoles = new HashSet(); Set notUnderstandHeaders = new HashSet(); Set
ultimateReceiverHeaders = new HashSet
(); Set mustUnderstandQNames = new HashSet(); initServiceSideInfo(mustUnderstandQNames, soapMessage, serviceRoles, paramHeaders); buildMustUnderstandHeaders(mustUnderstandHeaders, soapMessage, serviceRoles, ultimateReceiverHeaders); checkUnderstand(mustUnderstandHeaders, mustUnderstandQNames, notUnderstandHeaders); if (!notUnderstandHeaders.isEmpty()) { SoapFault soapFault = new SoapFault(new Message("MUST_UNDERSTAND", BUNDLE, notUnderstandHeaders), soapVersion.getMustUnderstand()); if (!isRequestor(soapMessage)) { soapMessage.put(MustUnderstandInterceptor.FAULT, soapFault); soapMessage.getInterceptorChain().add(ending); } else { throw soapFault; } } if (!ultimateReceiverHeaders.isEmpty() && !isRequestor(soapMessage)) { checkUltimateReceiverHeaders(ultimateReceiverHeaders, mustUnderstandQNames, soapMessage); } } public void handleFault(SoapMessage message) { SoapFault soapFault = (SoapFault)message.get(MustUnderstandInterceptor.FAULT); if (soapFault != null && !message.getExchange().isOneWay() && soapFault != message.getContent(Exception.class)) { message.setContent(Exception.class, soapFault); } } private void checkUltimateReceiverHeaders(Set
ultimateReceiverHeaders, Set mustUnderstandQNames, SoapMessage soapMessage) { soapMessage.getInterceptorChain() .add(new UltimateReceiverMustUnderstandInterceptor(mustUnderstandQNames)); Object o = soapMessage.getContextualProperty("endpoint-processes-headers"); if (o == null) { o = Collections.EMPTY_LIST; } Collection o2; if (o instanceof Collection) { o2 = CastUtils.cast((Collection)o); } else { o2 = Collections.singleton(o); } for (Object obj : o2) { QName qn; if (obj instanceof QName) { qn = (QName)obj; } else { qn = QName.valueOf((String)obj); } Iterator
hit = ultimateReceiverHeaders.iterator(); while (hit.hasNext()) { Header h = hit.next(); if (qn.equals(h.getName())) { hit.remove(); } } } if (!ultimateReceiverHeaders.isEmpty()) { Set notFound = new HashSet(); for (Header h : ultimateReceiverHeaders) { if (!mustUnderstandQNames.contains(h.getName())) { notFound.add(h.getName()); } } if (!notFound.isEmpty()) { // Defer throwing soap fault exception in SOAPHeaderInterceptor once the isOneway can // be detected SoapFault soapFault = new SoapFault(new Message("MUST_UNDERSTAND", BUNDLE, notFound), soapMessage.getVersion().getMustUnderstand()); soapMessage.put(MustUnderstandInterceptor.FAULT, soapFault); soapMessage.getInterceptorChain().add(ending); } } } private void initServiceSideInfo(Set mustUnderstandQNames, SoapMessage soapMessage, Set serviceRoles, Set paramHeaders) { if (paramHeaders != null) { mustUnderstandQNames.addAll(paramHeaders); } for (Interceptor interceptorInstance : soapMessage.getInterceptorChain()) { if (interceptorInstance instanceof SoapInterceptor) { SoapInterceptor si = (SoapInterceptor) interceptorInstance; Set roles = si.getRoles(); if (roles != null) { serviceRoles.addAll(roles); } Set understoodHeaders = si.getUnderstoodHeaders(); if (understoodHeaders != null) { mustUnderstandQNames.addAll(understoodHeaders); } } } } private void buildMustUnderstandHeaders(Set
mustUnderstandHeaders, SoapMessage soapMessage, Set serviceRoles, Set
ultimateReceiverHeaders) { for (Header header : soapMessage.getHeaders()) { if (header instanceof SoapHeader && ((SoapHeader)header).isMustUnderstand()) { String role = ((SoapHeader)header).getActor(); if (!StringUtils.isEmpty(role)) { role = role.trim(); if (role.equals(soapMessage.getVersion().getNextRole())) { mustUnderstandHeaders.add(header); } else if (role.equals(soapMessage.getVersion().getUltimateReceiverRole())) { ultimateReceiverHeaders.add(header); } else { for (URI roleFromBinding : serviceRoles) { if (role.equals(roleFromBinding.toString())) { mustUnderstandHeaders.add(header); } } } } else { // if role omitted, the soap node is ultimate receiver, // needs to understand ultimateReceiverHeaders.add(header); } } } } private void checkUnderstand(Set
mustUnderstandHeaders, Set mustUnderstandQNames, Set notUnderstandHeaders) { for (Header header : mustUnderstandHeaders) { QName qname = header.getName(); if (!mustUnderstandQNames.contains(qname)) { notUnderstandHeaders.add(header.getName()); } } } /** * */ private class UltimateReceiverMustUnderstandInterceptor extends AbstractSoapInterceptor { Set knownHeaders; public UltimateReceiverMustUnderstandInterceptor(Set knownHeaders) { super(Phase.INVOKE); this.knownHeaders = knownHeaders; } public void handleMessage(SoapMessage soapMessage) throws Fault { SoapVersion soapVersion = soapMessage.getVersion(); Set notFound = new HashSet(); List
heads = soapMessage.getHeaders(); for (Header header : heads) { if (header instanceof SoapHeader && ((SoapHeader)header).isMustUnderstand() && header.getDirection() == Header.Direction.DIRECTION_IN && !knownHeaders.contains(header.getName()) && (StringUtils.isEmpty(((SoapHeader)header).getActor()) || soapVersion.getUltimateReceiverRole() .equals(((SoapHeader)header).getActor()))) { notFound.add(header.getName()); } } if (!notFound.isEmpty()) { throw new SoapFault(new Message("MUST_UNDERSTAND", BUNDLE, notFound), soapVersion.getMustUnderstand()); } } } public class MustUnderstandEndingInterceptor extends AbstractSoapInterceptor { public MustUnderstandEndingInterceptor() { super(Phase.PRE_LOGICAL); addAfter(OneWayProcessorInterceptor.class.getName()); } public MustUnderstandEndingInterceptor(String phase) { super(phase); } public void handleMessage(SoapMessage message) throws Fault { // throws soapFault after the response code 202 is set in OneWayProcessorInterceptor if (message.get(MustUnderstandInterceptor.FAULT) != null) { SoapFault soapFault = (SoapFault)message.get(MustUnderstandInterceptor.FAULT); throw soapFault; } } } }