/** * 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.systest.ws.addressing; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.namespace.QName; import javax.xml.soap.SOAPException; import org.w3c.dom.Document; import org.w3c.dom.Element; 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.headers.Header; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.interceptor.Fault; 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.Names; import org.apache.cxf.ws.addressing.soap.VersionTransformer; import org.apache.cxf.ws.addressing.v200408.AttributedURI; import static org.apache.cxf.ws.addressing.JAXWSAConstants.ADDRESSING_PROPERTIES_INBOUND; import static org.apache.cxf.ws.addressing.JAXWSAConstants.ADDRESSING_PROPERTIES_OUTBOUND; /** * Verifies presence of expected SOAP headers. */ public class HeaderVerifier extends AbstractSoapInterceptor { VerificationCache verificationCache; String currentNamespaceURI; public HeaderVerifier() { super(Phase.POST_PROTOCOL); } public HeaderVerifier(String s) { super(s); } public Set<QName> getUnderstoodHeaders() { return Names.HEADERS; } public void handleMessage(SoapMessage message) { if (!MessageUtils.isRequestor(message) && !MessageUtils.isOutbound(message) && getPhase().equals(Phase.POST_PROTOCOL)) { message.getInterceptorChain().add(new AbstractSoapInterceptor(Phase.UNMARSHAL) { public void handleMessage(SoapMessage message) throws Fault { mediate(message); } }); return; } mediate(message); } public void handleFault(SoapMessage message) { mediate(message); } private void mediate(SoapMessage message) { boolean outgoingPartialResponse = isOutgoingPartialResponse(message); if (outgoingPartialResponse) { addPartialResponseHeader(message); } verify(message, outgoingPartialResponse); } private void addPartialResponseHeader(SoapMessage message) { try { // add piggybacked wsa:From header to partial response List<Header> header = message.getHeaders(); Document doc = DOMUtils.createDocument(); SoapVersion ver = message.getVersion(); Element hdr = doc.createElementNS(ver.getHeader().getNamespaceURI(), ver.getHeader().getLocalPart()); hdr.setPrefix(ver.getHeader().getPrefix()); marshallFrom("urn:piggyback_responder", hdr, getMarshaller()); Element elem = DOMUtils.getFirstElement(hdr); while (elem != null) { Header holder = new Header( new QName(elem.getNamespaceURI(), elem.getLocalName()), elem, null); header.add(holder); elem = DOMUtils.getNextElement(elem); } } catch (Exception e) { verificationCache.put("SOAP header addition failed: " + e); e.printStackTrace(); } } private void verify(SoapMessage message, boolean outgoingPartialResponse) { try { List<String> wsaHeaders = new ArrayList<>(); List<Header> headers = message.getHeaders(); if (headers != null) { recordWSAHeaders(headers, wsaHeaders, Names.WSA_NAMESPACE_NAME); recordWSAHeaders(headers, wsaHeaders, VersionTransformer.Names200408.WSA_NAMESPACE_NAME); recordWSAHeaders(headers, wsaHeaders, MAPTestBase.CUSTOMER_NAME.getNamespaceURI()); } boolean partialResponse = isIncomingPartialResponse(message) || outgoingPartialResponse; verificationCache.put(MAPTest.verifyHeaders(wsaHeaders, partialResponse, isRequestLeg(message), false)); } catch (SOAPException se) { verificationCache.put("SOAP header verification failed: " + se); } } private void recordWSAHeaders(List<Header> headers, List<String> wsaHeaders, String namespaceURI) { Iterator<Header> iter = headers.iterator(); while (iter.hasNext()) { Object obj = iter.next().getObject(); if (obj instanceof Element) { Element hdr = (Element) obj; if (namespaceURI.equals(hdr.getNamespaceURI())) { if (namespaceURI.endsWith("addressing")) { currentNamespaceURI = namespaceURI; wsaHeaders.add(hdr.getLocalName()); } else if (MAPTestBase.CUSTOMER_NAME.getNamespaceURI().equals(namespaceURI)) { String headerText = hdr.getTextContent(); if (MAPTestBase.CUSTOMER_KEY.equals(headerText)) { wsaHeaders.add(hdr.getLocalName()); } } } } else if (obj instanceof JAXBElement) { JAXBElement<?> el = (JAXBElement<?>)obj; if (namespaceURI.equals(el.getName().getNamespaceURI())) { if (namespaceURI.endsWith("addressing")) { currentNamespaceURI = namespaceURI; wsaHeaders.add(el.getName().getLocalPart()); } else if (MAPTestBase.CUSTOMER_NAME.getNamespaceURI().equals(namespaceURI)) { String headerText = (String)el.getValue(); if (MAPTestBase.CUSTOMER_KEY.equals(headerText)) { wsaHeaders.add(el.getName().getLocalPart()); } } } } } } private boolean isRequestLeg(SoapMessage message) { return (ContextUtils.isRequestor(message) && ContextUtils.isOutbound(message)) || (!ContextUtils.isRequestor(message) && !ContextUtils.isOutbound(message)); } private boolean isOutgoingPartialResponse(SoapMessage message) { AddressingProperties maps = (AddressingProperties)message.get(ADDRESSING_PROPERTIES_OUTBOUND); return ContextUtils.isOutbound(message) && !ContextUtils.isRequestor(message) && maps != null && Names.WSA_ANONYMOUS_ADDRESS.equals(maps.getTo().getValue()); } private boolean isIncomingPartialResponse(SoapMessage message) throws SOAPException { AddressingProperties maps = (AddressingProperties)message.get(ADDRESSING_PROPERTIES_INBOUND); return !ContextUtils.isOutbound(message) && ContextUtils.isRequestor(message) && maps != null && Names.WSA_ANONYMOUS_ADDRESS.equals(maps.getTo().getValue()); } private Marshaller getMarshaller() throws JAXBException { JAXBContext jaxbContext = VersionTransformer.getExposedJAXBContext(currentNamespaceURI); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); return marshaller; } private void marshallFrom(String from, Element header, Marshaller marshaller) throws JAXBException { if (Names.WSA_NAMESPACE_NAME.equals(currentNamespaceURI)) { String u = "urn:piggyback_responder"; AttributedURIType value = org.apache.cxf.ws.addressing.ContextUtils.getAttributedURI(u); marshaller.marshal( new JAXBElement<AttributedURIType>(Names.WSA_FROM_QNAME, AttributedURIType.class, value), header); } else if (VersionTransformer.Names200408.WSA_NAMESPACE_NAME.equals( currentNamespaceURI)) { AttributedURI value = VersionTransformer.Names200408.WSA_OBJECT_FACTORY.createAttributedURI(); value.setValue(from); QName qname = new QName(VersionTransformer.Names200408.WSA_NAMESPACE_NAME, Names.WSA_FROM_NAME); marshaller.marshal( new JAXBElement<AttributedURI>(qname, AttributedURI.class, value), header); } } public void setVerificationCache(VerificationCache cache) { verificationCache = cache; } }