Author: ay Date: Fri May 17 09:08:40 2013 New Revision: 1483706 URL: http://svn.apache.org/r1483706 Log: Merged revisions 1483699 via svn merge from https://svn.apache.org/repos/asf/cxf/branches/2.7.x-fixes
........ r1483699 | ay | 2013-05-17 10:58:54 +0200 (Fri, 17 May 2013) | 9 lines Merged revisions 1483696 via svn merge from https://svn.apache.org/repos/asf/cxf/trunk ........ r1483696 | ay | 2013-05-17 10:54:44 +0200 (Fri, 17 May 2013) | 1 line [CXF-5009] Allow multiple subcodes in a SOAP 1.2 fault ........ ........ Modified: cxf/branches/2.6.x-fixes/ (props changed) cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapFault.java cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultInInterceptor.java cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultOutInterceptor.java cxf/branches/2.6.x-fixes/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/interceptor/SoapFaultSerializerTest.java cxf/branches/2.6.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java Propchange: cxf/branches/2.6.x-fixes/ ('svn:mergeinfo' removed) Propchange: cxf/branches/2.6.x-fixes/ ------------------------------------------------------------------------------ Binary property 'svnmerge-integrated' - no diff available. Modified: cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapFault.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapFault.java?rev=1483706&r1=1483705&r2=1483706&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapFault.java (original) +++ cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/SoapFault.java Fri May 17 09:08:40 2013 @@ -20,6 +20,8 @@ package org.apache.cxf.binding.soap; import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.ResourceBundle; @@ -48,7 +50,7 @@ public class SoapFault extends Fault { * FaultHandler) be mapped to "Sender" instead. */ - private QName subCode; + private List<QName> subCodes; private String role; private String node; private Map<String, String> namespaces = new HashMap<String, String>(); @@ -84,7 +86,7 @@ public class SoapFault extends Fault { } public String getSubCodeString(String prefix, String defaultPrefix) { - return getFaultCodeString(prefix, defaultPrefix, subCode); + return getFaultCodeString(prefix, defaultPrefix, getRootSubCode()); } private String getFaultCodeString(String prefix, String defaultPrefix, QName fCode) { @@ -100,6 +102,19 @@ public class SoapFault extends Fault { return codePrefix + ":" + fCode.getLocalPart(); } + + private QName getRootSubCode() { + return subCodes != null && subCodes.size() > 0 ? subCodes.get(0) : null; + } + + private void setRootSubCode(QName subCode) { + if (subCodes == null) { + subCodes = new LinkedList<QName>(); + } else { + subCodes.clear(); + } + subCodes.add(subCode); + } public String getReason() { return getMessage(); @@ -132,21 +147,53 @@ public class SoapFault extends Fault { } /** - * Returns the SubCode for the Fault Code. + * Returns the SubCode for the Fault Code. If there are more than one Subcode entries + * in this fault, the first Subcode is returned. * * @return The SubCode element as detailed by the SOAP 1.2 spec. */ public QName getSubCode() { - return subCode; + return getRootSubCode(); + } + + /** + * Returns the SubCode list for the Fault Code. + * + * @return The SubCode element list as detailed by the SOAP 1.2 spec. + */ + public List<QName> getSubCodes() { + return subCodes; } /** - * Sets the SubCode for the Fault Code. + * Sets the SubCode for the Fault Code. If there are more than one Subcode entries + * in this fault, the first Subcode is set while the other entries are removed. * * @param subCode The SubCode element as detailed by the SOAP 1.2 spec. */ public void setSubCode(QName subCode) { - this.subCode = subCode; + setRootSubCode(subCode); + } + + /** + * Sets the SubCode list for the Fault Code. + * + * @param subCode The SubCode element list as detailed by the SOAP 1.2 spec. + */ + public void setSubCodes(List<QName> subCodes) { + this.subCodes = subCodes; + } + + /** + * Appends the SubCode to the SubCode list. + * + * @param subCode The SubCode element as detailed by the SOAP 1.2 spec. + */ + public void appendSubCode(QName subCode) { + if (subCodes == null) { + subCodes = new LinkedList<QName>(); + } + subCodes.add(subCode); } public Map<String, String> getNamespaces() { Modified: cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultInInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultInInterceptor.java?rev=1483706&r1=1483705&r2=1483706&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultInInterceptor.java (original) +++ cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultInInterceptor.java Fri May 17 09:08:40 2013 @@ -20,6 +20,8 @@ package org.apache.cxf.binding.soap.interceptor; import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.logging.Logger; @@ -30,6 +32,7 @@ import javax.xml.xpath.XPathConstants; import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import org.apache.cxf.binding.soap.Soap11; import org.apache.cxf.binding.soap.Soap12; @@ -67,7 +70,7 @@ public class Soap12FaultInInterceptor ex XMLStreamReader reader) { String exMessage = null; QName faultCode = null; - QName subCode = null; + List<QName> subCodes = null; String role = null; String node = null; Element detail = null; @@ -103,11 +106,16 @@ public class Soap12FaultInInterceptor ex faultCode = XMLUtils.getQName(el.getTextContent(), el); } - el = (Element)xu.getValue("//s:Fault/s:Code/s:Subcode/s:Value", + el = (Element)xu.getValue("//s:Fault/s:Code/s:Subcode", fault, XPathConstants.NODE); if (el != null) { - subCode = XMLUtils.getQName(el.getTextContent(), el); + subCodes = new LinkedList<QName>(); + NodeList vlist = el.getElementsByTagNameNS(Soap12.SOAP_NAMESPACE, "Value"); + for (int i = 0; i < vlist.getLength(); i++) { + Node v = vlist.item(i); + subCodes.add(XMLUtils.getQName(v.getTextContent(), v)); + } } exMessage = (String) xu.getValue("//s:Fault/s:Reason/s:Text/text()", @@ -140,7 +148,7 @@ public class Soap12FaultInInterceptor ex } SoapFault fault = new SoapFault(exMessage, faultCode); - fault.setSubCode(subCode); + fault.setSubCodes(subCodes); fault.setDetail(detail); fault.setRole(role); fault.setNode(node); Modified: cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultOutInterceptor.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultOutInterceptor.java?rev=1483706&r1=1483705&r2=1483706&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultOutInterceptor.java (original) +++ cxf/branches/2.6.x-fixes/rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Soap12FaultOutInterceptor.java Fri May 17 09:08:40 2013 @@ -23,6 +23,7 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamWriter; import org.w3c.dom.Element; @@ -92,14 +93,19 @@ public class Soap12FaultOutInterceptor e defaultPrefix)); writer.writeEndElement(); - if (fault.getSubCode() != null) { - writer.writeStartElement(defaultPrefix, "Subcode", ns); - writer.writeStartElement(defaultPrefix, "Value", ns); - writer.writeCharacters(fault.getSubCodeString(getFaultCodePrefix(writer, - fault.getSubCode()), - defaultPrefix)); - writer.writeEndElement(); - writer.writeEndElement(); + if (fault.getSubCodes() != null) { + int fscCount = 0; + for (QName fsc : fault.getSubCodes()) { + writer.writeStartElement(defaultPrefix, "Subcode", ns); + writer.writeStartElement(defaultPrefix, "Value", ns); + writer.writeCharacters(getCodeString(getFaultCodePrefix(writer, fsc), + defaultPrefix, fsc)); + writer.writeEndElement(); + fscCount++; + } + while (fscCount-- > 0) { + writer.writeEndElement(); + } } writer.writeEndElement(); @@ -151,5 +157,20 @@ public class Soap12FaultOutInterceptor e } return code; } + + //REVISIT either make SoapFault's this method public or put this method into a soap fault utility class + private static String getCodeString(String prefix, String defaultPrefix, QName code) { + String codePrefix = null; + if (StringUtils.isEmpty(prefix)) { + codePrefix = code.getPrefix(); + if (StringUtils.isEmpty(codePrefix)) { + codePrefix = defaultPrefix; + } + } else { + codePrefix = prefix; + } + + return codePrefix + ":" + code.getLocalPart(); + } } } Modified: cxf/branches/2.6.x-fixes/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/interceptor/SoapFaultSerializerTest.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/interceptor/SoapFaultSerializerTest.java?rev=1483706&r1=1483705&r2=1483706&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/interceptor/SoapFaultSerializerTest.java (original) +++ cxf/branches/2.6.x-fixes/rt/bindings/soap/src/test/java/org/apache/cxf/binding/soap/interceptor/SoapFaultSerializerTest.java Fri May 17 09:08:40 2013 @@ -142,9 +142,66 @@ public class SoapFaultSerializerTest ext 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.appendSubCode(new QName("http://cxf.apache.org/soap/fault", "invalidsoap", "cxffaultcode")); + fault.appendSubCode(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 = DOMUtils.readXml(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); Modified: cxf/branches/2.6.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java URL: http://svn.apache.org/viewvc/cxf/branches/2.6.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java?rev=1483706&r1=1483705&r2=1483706&view=diff ============================================================================== --- cxf/branches/2.6.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java (original) +++ cxf/branches/2.6.x-fixes/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/JaxWsClientProxy.java Fri May 17 09:08:40 2013 @@ -29,6 +29,7 @@ import java.util.Map; import java.util.concurrent.Future; import java.util.logging.Logger; +import javax.xml.namespace.QName; import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFault; @@ -219,10 +220,12 @@ public class JaxWsClientProxy extends or if (role != null) { soapFault.setFaultActor(role); } - if (((SoapFault)ex).getSubCode() != null + if (((SoapFault)ex).getSubCodes() != null && !SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE.equals(soapFault.getNamespaceURI())) { // set the subcode only if it is supported (e.g, 1.2) - soapFault.appendFaultSubcode(((SoapFault)ex).getSubCode()); + for (QName fsc : ((SoapFault)ex).getSubCodes()) { + soapFault.appendFaultSubcode(fsc); + } } if (((SoapFault)ex).hasDetails()) {
