/**
* 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.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPPart;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.xpath.XPathConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import junit.framework.AssertionFailedError;
import org.apache.cxf.binding.soap.Soap11;
import org.apache.cxf.binding.soap.Soap12;
import org.apache.cxf.binding.soap.SoapFault;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.SoapVersion;
import org.apache.cxf.binding.soap.interceptor.Soap11FaultOutInterceptor.Soap11FaultOutInterceptorInternal;
import org.apache.cxf.binding.soap.interceptor.Soap12FaultOutInterceptor.Soap12FaultOutInterceptorInternal;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor.SAAJPreInInterceptor;
import org.apache.cxf.helpers.XPathUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.ExchangeImpl;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.staxutils.StaxUtils;
import org.junit.Assert;
import org.junit.Test;
public class SoapFaultSerializerTest extends Assert {
private void assertValid(String xpathExpression, Document doc) {
Map<String, String> namespaces = new HashMap<>();
namespaces.put("s", "http://schemas.xmlsoap.org/soap/envelope/");
namespaces.put("xsd", "http://www.w3.org/2001/XMLSchema");
namespaces.put("wsdl", "http://schemas.xmlsoap.org/wsdl/");
namespaces.put("wsdlsoap", "http://schemas.xmlsoap.org/wsdl/soap/");
namespaces.put("soap", "http://schemas.xmlsoap.org/soap/");
namespaces.put("soap12env", "http://www.w3.org/2003/05/soap-envelope");
namespaces.put("xml", "http://www.w3.org/XML/1998/namespace");
XPathUtils xpu = new XPathUtils(namespaces);
if (!xpu.isExist(xpathExpression, doc, XPathConstants.NODE)) {
throw new AssertionFailedError("Failed to select any nodes for expression:\n" + xpathExpression
+ " from document:\n" + StaxUtils.toString(doc));
}
}
@Test
public void testSoap11Out() throws Exception {
String faultString = "Hadrian caused this Fault!";
SoapFault fault = new SoapFault(faultString, Soap11.getInstance().getSender());
SoapMessage m = new SoapMessage(new MessageImpl());
m.setExchange(new ExchangeImpl());
m.setContent(Exception.class, fault);
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(out);
writer.writeStartDocument();
writer.writeStartElement("Body");
m.setContent(XMLStreamWriter.class, writer);
Soap11FaultOutInterceptorInternal.INSTANCE.handleMessage(m);
writer.writeEndElement();
writer.writeEndDocument();
writer.close();
Document faultDoc = StaxUtils.read(new ByteArrayInputStream(out.toByteArray()));
assertValid("//s:Fault/faultcode[text()='ns1:Client']", faultDoc);
assertValid("//s:Fault/faultstring[text()='" + faultString + "']", faultDoc);
XMLStreamReader reader = StaxUtils.createXMLStreamReader(new ByteArrayInputStream(out.toByteArray()));
m.setContent(XMLStreamReader.class, reader);
reader.nextTag();
Soap11FaultInInterceptor inInterceptor = new Soap11FaultInInterceptor();
inInterceptor.handleMessage(m);
SoapFault fault2 = (SoapFault)m.getContent(Exception.class);
assertNotNull(fault2);
assertEquals(fault.getMessage(), fault2.getMessage());
assertEquals(Soap11.getInstance().getSender(), fault2.getFaultCode());
}
@Test
public void testSoap12Out() throws Exception {
String faultString = "Hadrian caused this Fault!";
SoapFault fault = new SoapFault(faultString, Soap12.getInstance().getSender());
QName qname = new QName("http://cxf.apache.org/soap/fault", "invalidsoap", "cxffaultcode");
fault.setSubCode(qname);
SoapMessage m = new SoapMessage(new MessageImpl());
m.setVersion(Soap12.getInstance());
m.setContent(Exception.class, fault);
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(out);
writer.writeStartDocument();
writer.writeStartElement("Body");
m.setContent(XMLStreamWriter.class, writer);
Soap12FaultOutInterceptorInternal.INSTANCE.handleMessage(m);
writer.writeEndElement();
writer.writeEndDocument();
writer.close();
Document faultDoc = StaxUtils.read(new ByteArrayInputStream(out.toByteArray()));
assertValid("//soap12env:Fault/soap12env:Code/soap12env:Value[text()='ns1:Sender']",
faultDoc);
assertValid("//soap12env:Fault/soap12env:Code/soap12env:Subcode/"
+ "soap12env:Value[text()='ns2:invalidsoap']",
faultDoc);
assertValid("//soap12env:Fault/soap12env:Reason/soap12env:Text[@xml:lang='en']",
faultDoc);
assertValid("//soap12env:Fault/soap12env:Reason/soap12env:Text[text()='" + faultString + "']",
faultDoc);
XMLStreamReader reader = StaxUtils.createXMLStreamReader(new ByteArrayInputStream(out.toByteArray()));
m.setContent(XMLStreamReader.class, reader);
reader.nextTag();
Soap12FaultInInterceptor inInterceptor = new Soap12FaultInInterceptor();
inInterceptor.handleMessage(m);
SoapFault fault2 = (SoapFault)m.getContent(Exception.class);
assertNotNull(fault2);
assertEquals(Soap12.getInstance().getSender(), fault2.getFaultCode());
assertEquals(fault.getMessage(), fault2.getMessage());
assertEquals(fault.getSubCode(), fault2.getSubCode());
}
@Test
public void testSoap12WithMultipleSubCodesOut() throws Exception {
String faultString = "Hadrian caused this Fault!";
SoapFault fault = new SoapFault(faultString, Soap12.getInstance().getSender());
fault.addSubCode(new QName("http://cxf.apache.org/soap/fault", "invalidsoap", "cxffaultcode"));
fault.addSubCode(new QName("http://cxf.apache.org/soap/fault2", "invalidsoap2", "cxffaultcode2"));
SoapMessage m = new SoapMessage(new MessageImpl());
m.setVersion(Soap12.getInstance());
m.setContent(Exception.class, fault);
ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(out);
writer.writeStartDocument();
writer.writeStartElement("Body");
m.setContent(XMLStreamWriter.class, writer);
Soap12FaultOutInterceptorInternal.INSTANCE.handleMessage(m);
writer.writeEndElement();
writer.writeEndDocument();
writer.close();
Document faultDoc = StaxUtils.read(new ByteArrayInputStream(out.toByteArray()));
assertValid("//soap12env:Fault/soap12env:Code/soap12env:Value[text()='ns1:Sender']",
faultDoc);
assertValid("//soap12env:Fault/soap12env:Code/soap12env:Subcode/"
+ "soap12env:Value[text()='ns2:invalidsoap']",
faultDoc);
assertValid("//soap12env:Fault/soap12env:Code/soap12env:Subcode/soap12env:Subcode/"
+ "soap12env:Value[text()='ns2:invalidsoap2']",
faultDoc);
assertValid("//soap12env:Fault/soap12env:Reason/soap12env:Text[@xml:lang='en']",
faultDoc);
assertValid("//soap12env:Fault/soap12env:Reason/soap12env:Text[text()='" + faultString + "']",
faultDoc);
XMLStreamReader reader = StaxUtils.createXMLStreamReader(new ByteArrayInputStream(out.toByteArray()));
m.setContent(XMLStreamReader.class, reader);
reader.nextTag();
Soap12FaultInInterceptor inInterceptor = new Soap12FaultInInterceptor();
inInterceptor.handleMessage(m);
SoapFault fault2 = (SoapFault)m.getContent(Exception.class);
assertNotNull(fault2);
assertEquals(Soap12.getInstance().getSender(), fault2.getFaultCode());
assertEquals(fault.getMessage(), fault2.getMessage());
assertEquals(fault.getSubCodes(), fault2.getSubCodes());
}
@Test
public void testFaultToSoapFault() throws Exception {
Exception ex = new Exception();
Fault fault = new Fault(ex, Fault.FAULT_CODE_CLIENT);
verifyFaultToSoapFault(fault, null, true, Soap11.getInstance());
verifyFaultToSoapFault(fault, null, true, Soap12.getInstance());
fault = new Fault(ex, Fault.FAULT_CODE_SERVER);
verifyFaultToSoapFault(fault, null, false, Soap11.getInstance());
verifyFaultToSoapFault(fault, null, false, Soap12.getInstance());
fault.setMessage("fault-one");
verifyFaultToSoapFault(fault, "fault-one", false, Soap11.getInstance());
ex = new Exception("fault-two");
fault = new Fault(ex, Fault.FAULT_CODE_CLIENT);
verifyFaultToSoapFault(fault, "fault-two", true, Soap11.getInstance());
fault = new Fault(ex, new QName("http://cxf.apache.org", "myFaultCode"));
SoapFault f = verifyFaultToSoapFault(fault, "fault-two", false, Soap12.getInstance());
assertEquals("myFaultCode", f.getSubCodes().get(0).getLocalPart());
}
private SoapFault verifyFaultToSoapFault(Fault fault, String msg, boolean sender, SoapVersion v) {
SoapFault sf = SoapFault.createFault(fault, v);
assertEquals(sender ? v.getSender() : v.getReceiver(), sf.getFaultCode());
assertEquals(msg, sf.getMessage());
return sf;
}
@Test
public void testCXF1864() throws Exception {
SoapMessage m = new SoapMessage(new MessageImpl());
m.setVersion(Soap12.getInstance());
XMLStreamReader reader = StaxUtils.createXMLStreamReader(this.getClass()
.getResourceAsStream("cxf1864.xml"));
m.setContent(XMLStreamReader.class, reader);
reader.nextTag();
Soap12FaultInInterceptor inInterceptor = new Soap12FaultInInterceptor();
inInterceptor.handleMessage(m);
SoapFault fault2 = (SoapFault)m.getContent(Exception.class);
assertNotNull(fault2);
assertEquals(Soap12.getInstance().getReceiver(), fault2.getFaultCode());
}
@Test
public void testCXF4181() throws Exception {
//Try WITH SAAJ
SoapMessage m = new SoapMessage(new MessageImpl());
m.put(Message.HTTP_REQUEST_METHOD, "POST");
m.setVersion(Soap12.getInstance());
XMLStreamReader reader = StaxUtils.createXMLStreamReader(this.getClass()
.getResourceAsStream("cxf4181.xml"));
m.setContent(XMLStreamReader.class, reader);
new SAAJPreInInterceptor().handleMessage(m);
new ReadHeadersInterceptor(null).handleMessage(m);
new StartBodyInterceptor().handleMessage(m);
new SAAJInInterceptor().handleMessage(m);
new Soap12FaultInInterceptor().handleMessage(m);
Node nd = m.getContent(Node.class);
SOAPPart part = (SOAPPart)nd;
assertEquals("S", part.getEnvelope().getPrefix());
assertEquals("S2", part.getEnvelope().getHeader().getPrefix());
assertEquals("S3", part.getEnvelope().getBody().getPrefix());
SOAPFault fault = part.getEnvelope().getBody().getFault();
assertEquals("S", fault.getPrefix());
assertEquals("Authentication Failure", fault.getFaultString());
SoapFault fault2 = (SoapFault)m.getContent(Exception.class);
assertNotNull(fault2);
assertEquals(Soap12.getInstance().getSender(), fault2.getFaultCode());
assertEquals(new QName("http://schemas.xmlsoap.org/ws/2005/02/trust", "FailedAuthentication"),
fault2.getSubCode());
Element el = part.getEnvelope().getBody();
nd = el.getFirstChild();
int count = 0;
while (nd != null) {
if (nd instanceof Element) {
count++;
}
nd = nd.getNextSibling();
}
assertEquals(1, count);
//Try WITHOUT SAAJ
m = new SoapMessage(new MessageImpl());
m.setVersion(Soap12.getInstance());
reader = StaxUtils.createXMLStreamReader(this.getClass()
.getResourceAsStream("cxf4181.xml"));
m.setContent(XMLStreamReader.class, reader);
m.put(Message.HTTP_REQUEST_METHOD, "POST");
new ReadHeadersInterceptor(null).handleMessage(m);
new StartBodyInterceptor().handleMessage(m);
new Soap12FaultInInterceptor().handleMessage(m);
nd = m.getContent(Node.class);
fault2 = (SoapFault)m.getContent(Exception.class);
assertNotNull(fault2);
assertEquals(Soap12.getInstance().getSender(), fault2.getFaultCode());
assertEquals(new QName("http://schemas.xmlsoap.org/ws/2005/02/trust", "FailedAuthentication"),
fault2.getSubCode());
}
@Test
public void testCXF5493() throws Exception {
SoapMessage m = new SoapMessage(new MessageImpl());
m.setVersion(Soap11.getInstance());
XMLStreamReader reader = StaxUtils.createXMLStreamReader(this.getClass()
.getResourceAsStream("cxf5493.xml"));
m.setContent(XMLStreamReader.class, reader);
reader.nextTag(); //env
reader.nextTag(); //body
reader.nextTag(); //fault
Soap11FaultInInterceptor inInterceptor = new Soap11FaultInInterceptor();
inInterceptor.handleMessage(m);
SoapFault fault2 = (SoapFault)m.getContent(Exception.class);
assertNotNull(fault2);
assertEquals(Soap11.getInstance().getReceiver(), fault2.getFaultCode());
assertEquals("some text containing a xml tag <xml-tag>", fault2.getMessage());
m = new SoapMessage(new MessageImpl());
m.put(Message.HTTP_REQUEST_METHOD, "POST");
m.setVersion(Soap11.getInstance());
reader = StaxUtils.createXMLStreamReader(this.getClass().getResourceAsStream("cxf5493.xml"));
m.setContent(XMLStreamReader.class, reader);
new SAAJPreInInterceptor().handleMessage(m);
new ReadHeadersInterceptor(null).handleMessage(m);
new StartBodyInterceptor().handleMessage(m);
new SAAJInInterceptor().handleMessage(m);
new Soap11FaultInInterceptor().handleMessage(m);
fault2 = (SoapFault)m.getContent(Exception.class);
assertNotNull(fault2);
assertEquals(Soap11.getInstance().getReceiver(), fault2.getFaultCode());
assertEquals("some text containing a xml tag <xml-tag>", fault2.getMessage());
}
}