blob: 510b85f07bf914861fab19d001fa81330e1c4b46 [file] [log] [blame]
/*
* 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.servicemix.camel.nmr.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.w3c.dom.NodeList;
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.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.CLIENT_ADDRESSING_PROPERTIES_INBOUND;
import static org.apache.cxf.ws.addressing.JAXWSAConstants.SERVER_ADDRESSING_PROPERTIES_OUTBOUND;
/**
* Verifies presence of expected SOAP headers.
*/
public class HeaderVerifier extends AbstractSoapInterceptor {
VerificationCache verificationCache = new GreeterImpl();
String currentNamespaceURI;
public HeaderVerifier() {
super(Phase.POST_PROTOCOL);
}
public Set<QName> getUnderstoodHeaders() {
return Names.HEADERS;
}
public void handleMessage(SoapMessage message) {
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());
NodeList nl = hdr.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Object obj = nl.item(i);
if (obj instanceof Element) {
Element elem = (Element) obj;
Header holder = new Header(
new QName(elem.getNamespaceURI(), elem.getLocalName()),
elem, null);
header.add(holder);
}
}
} 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<String>();
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,
WSAddressingTest.CUSTOMER_NAME.getNamespaceURI());
}
boolean partialResponse = isIncomingPartialResponse(message)
|| outgoingPartialResponse;
verificationCache.put(WSAddressingTest.verifyHeaders(wsaHeaders,
partialResponse,
isRequestLeg(message)));
} 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 (WSAddressingTest.CUSTOMER_NAME.getNamespaceURI().equals(namespaceURI)) {
String headerText = hdr.getTextContent();
if (WSAddressingTest.CUSTOMER_KEY.equals(headerText)) {
wsaHeaders.add(hdr.getLocalName());
}
}
}
}
}
}
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(SERVER_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(CLIENT_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;
}
}