Hi Folks, Here is a patch for handling SOAP 1.1 Fault Actors and SOAP 1.2 Fault Roles properly in DOOM.
Earlier org.apache.axis2.soap.impl.dom.SOAPFaultRoleImpl which was being extended by SOAP11FaultRoleImpl & SOAP12FaultRoleImpl, was using "Role" as the localName, which was causing SOAP1.1 Fault Roles not to be handles properly. -- Thanks Afkham Azeez
Index: modules/core/src/org/apache/axis2/client/MEPClient.java =================================================================== --- modules/core/src/org/apache/axis2/client/MEPClient.java (revision 365352) +++ modules/core/src/org/apache/axis2/client/MEPClient.java (working copy) @@ -174,8 +174,11 @@ } String soapVersionURI = clientOptions.getSoapVersionURI(); + String soapFactory = clientOptions.getSoapFactory(); - if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapVersionURI)) { + if(soapFactory != null && soapFactory.trim().length() != 0){ + return OMAbstractFactory.getSOAPFactory(soapFactory).getDefaultEnvelope(); + } else if (SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapVersionURI)) { return OMAbstractFactory.getSOAP12Factory().getDefaultEnvelope(); } else if (SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI.equals(soapVersionURI) || "".equals(soapVersionURI) || (soapVersionURI == null)) { @@ -243,7 +246,7 @@ protected void inferTransportOutDescription(MessageContext msgCtx) throws AxisFault { // user can set the transport by giving a TransportOutDescription or we - // will deduce that from the "to" epr information, if user has not set the + // will deduce that from the "to" epr information, if user has not set the // TransportOutDescription, lets infer that if (clientOptions.getSenderTransport() == null) { AxisConfiguration axisConfig = Index: modules/core/src/org/apache/axis2/client/Options.java =================================================================== --- modules/core/src/org/apache/axis2/client/Options.java (revision 365352) +++ modules/core/src/org/apache/axis2/client/Options.java (working copy) @@ -54,6 +54,7 @@ private Boolean isExceptionToBeThrownOnSOAPFault; // defaults to true; private long timeOutInMilliSeconds = -1; // = DEFAULT_TIMEOUT_MILLISECONDS; private Boolean useSeparateListener; // defaults to false + private String soapFactory; // Addressing specific properties private String action; @@ -214,6 +215,14 @@ return soapVersionURI == null ? SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI : soapVersionURI; } + public String getSoapFactory() { + if (soapFactory == null && parent != null) { + soapFactory = parent.getSoapFactory(); + } + + return soapFactory == null ? "" : soapFactory; + } + /** * Gets the wait time after which a client times out in a blocking scenario. * The default is Options#DEFAULT_TIMEOUT_MILLISECONDS @@ -307,6 +316,10 @@ this.messageId = messageId; } + public void setSoapFactory(String soapFactory) { + this.soapFactory = soapFactory; + } + /** * This will set the properties to the context. But in setting that one may need to "copy" all * the properties from the source properties to the target properties. To enable this we introduced @@ -408,7 +421,7 @@ if (!useSeparateListener) { boolean isTransportsEqual = senderTransport.equals(listenerTransport); boolean isATwoWaytransport = Constants.TRANSPORT_HTTP.equals(senderTransport) - || Constants.TRANSPORT_TCP.equals(senderTransport); + || Constants.TRANSPORT_TCP.equals(senderTransport); if ((!isTransportsEqual || !isATwoWaytransport)) { throw new AxisFault(Messages.getMessage("useSeparateListenerLimited")); Index: modules/doom/src/org/apache/axis2/soap/impl/dom/SOAPFaultRoleImpl.java =================================================================== --- modules/doom/src/org/apache/axis2/soap/impl/dom/SOAPFaultRoleImpl.java (revision 365352) +++ modules/doom/src/org/apache/axis2/soap/impl/dom/SOAPFaultRoleImpl.java (working copy) @@ -30,10 +30,11 @@ public abstract class SOAPFaultRoleImpl extends SOAPElement implements org.apache.axis2.soap.SOAPFaultRole { public SOAPFaultRoleImpl(SOAPFault parent, + String localName, boolean extractNamespaceFromParent) throws SOAPProcessingException { super(parent, - SOAP12Constants.SOAP_FAULT_ROLE_LOCAL_NAME, - extractNamespaceFromParent); + localName, + extractNamespaceFromParent); } public SOAPFaultRoleImpl(SOAPFault parent, OMXMLParserWrapper builder) { @@ -55,7 +56,7 @@ builderType = this.builder.getBuilderType(); } if ((builderType == PUSH_TYPE_BUILDER) - && (builder.getRegisteredContentHandler() == null)) { + && (builder.getRegisteredContentHandler() == null)) { builder.registerExternalContentHandler(new StreamWriterToContentHandlerConverter(omOutput)); } Index: modules/doom/src/org/apache/axis2/soap/impl/dom/soap11/SOAP11FaultRoleImpl.java =================================================================== --- modules/doom/src/org/apache/axis2/soap/impl/dom/soap11/SOAP11FaultRoleImpl.java (revision 365352) +++ modules/doom/src/org/apache/axis2/soap/impl/dom/soap11/SOAP11FaultRoleImpl.java (working copy) @@ -30,7 +30,7 @@ public class SOAP11FaultRoleImpl extends SOAPFaultRoleImpl { public SOAP11FaultRoleImpl(SOAPFault parent) throws SOAPProcessingException { - super(parent, false); + super(parent, SOAP11Constants.SOAP_FAULT_ACTOR_LOCAL_NAME, false); } public SOAP11FaultRoleImpl(SOAPFault parent, OMXMLParserWrapper builder) { Index: modules/doom/src/org/apache/axis2/soap/impl/dom/soap12/SOAP12FaultRoleImpl.java =================================================================== --- modules/doom/src/org/apache/axis2/soap/impl/dom/soap12/SOAP12FaultRoleImpl.java (revision 365352) +++ modules/doom/src/org/apache/axis2/soap/impl/dom/soap12/SOAP12FaultRoleImpl.java (working copy) @@ -18,13 +18,14 @@ import org.apache.axis2.om.OMElement; import org.apache.axis2.om.OMXMLParserWrapper; +import org.apache.axis2.soap.SOAP12Constants; import org.apache.axis2.soap.SOAPFault; import org.apache.axis2.soap.SOAPProcessingException; import org.apache.axis2.soap.impl.dom.SOAPFaultRoleImpl; public class SOAP12FaultRoleImpl extends SOAPFaultRoleImpl { public SOAP12FaultRoleImpl(SOAPFault parent) throws SOAPProcessingException { - super(parent, true); + super(parent, SOAP12Constants.SOAP_FAULT_ROLE_LOCAL_NAME, true); } public SOAP12FaultRoleImpl(SOAPFault parent, OMXMLParserWrapper builder) { Index: modules/doom/src/org/apache/axis2/om/impl/dom/ChildNode.java =================================================================== --- modules/doom/src/org/apache/axis2/om/impl/dom/ChildNode.java (revision 365352) +++ modules/doom/src/org/apache/axis2/om/impl/dom/ChildNode.java (working copy) @@ -23,127 +23,131 @@ public abstract class ChildNode extends NodeImpl { - protected ChildNode previousSibling; - - protected ChildNode nextSibling; - - protected ParentNode parentNode; - - - /** - * @param ownerNode - */ - protected ChildNode(DocumentImpl ownerDocument) { - super(ownerDocument); - } - - protected ChildNode() { - - } - - public OMNode getNextOMSibling() throws OMException { + protected ChildNode previousSibling; + + protected ChildNode nextSibling; + + protected ParentNode parentNode; + + + /** + * @param ownerNode + */ + protected ChildNode(DocumentImpl ownerDocument) { + super(ownerDocument); + } + + protected ChildNode() { + + } + + public OMNode getNextOMSibling() throws OMException { while ((nextSibling == null) && !this.parentNode.done) { this.parentNode.buildNext(); } return nextSibling; - } - public Node getNextSibling() { - return (Node)this.getNextOMSibling(); - } - public OMNode getPreviousOMSibling() { - return this.previousSibling; - } - public Node getPreviousSibling() { - return this.previousSibling; - } + } - /// - ///OMNode methods - /// - public void setNextOMSibling(OMNode node) { - if(node instanceof ChildNode) - this.nextSibling = (ChildNode)node; - else - throw new OMException("The node is not a " + ChildNode.class); - } + public Node getNextSibling() { + return (Node) this.getNextOMSibling(); + } - public void setPreviousOMSibling(OMNode node) { - if(node instanceof ChildNode) - this.previousSibling = (ChildNode)node; - else - throw new OMException("The node is not a " + ChildNode.class); - } - - public OMContainer getParent() throws OMException { - return (OMContainer)this.parentNode; - } - - public Node getParentNode() { - return this.parentNode; - } - - public void setParent(OMContainer element) { - if(element instanceof ParentNode) - this.parentNode = (ParentNode)element; - else - throw new OMException("The given parent is not of the type " + ParentNode.class); + public OMNode getPreviousOMSibling() { + return this.previousSibling; + } - } - - public OMNode detach() throws OMException{ - if(this.parentNode == null) { - throw new OMException("Parent level elements cannot be ditached"); - } else { - if(previousSibling == null) { // This is the first child - if(nextSibling != null) { - this.parentNode.setFirstChild(nextSibling); - } else { - this.parentNode.firstChild = null; - this.parentNode.lastChild = null; - } - } else { - ((OMNodeEx)this.getPreviousOMSibling()).setNextOMSibling(nextSibling); - } if (this.nextSibling != null) { - this.nextSibling.setPreviousOMSibling(this.previousSibling); - } - this.parentNode = null; - } - return this; - } - - public void discard() throws OMException { - throw new UnsupportedOperationException("Cannot discard this node"); - } - - /** - * Insert the given sibling next to this item - */ - public void insertSiblingAfter(OMNode sibling) throws OMException { - - if(this.parentNode != null) { - ((OMNodeEx)sibling).setParent(this.parentNode); - } - - if(sibling instanceof ChildNode) { - ChildNode domSibling = (ChildNode)sibling; - domSibling.previousSibling = this; - if(this.nextSibling != null) { - this.nextSibling.previousSibling = domSibling; - } - domSibling.nextSibling = this.nextSibling; - this.nextSibling = domSibling; - - } else { - throw new OMException("The given child is not of type " + ChildNode.class); - } - } - - /** - * Insert the given sibling before this item - */ - public void insertSiblingBefore(OMNode sibling) throws OMException { + public Node getPreviousSibling() { + return this.previousSibling; + } + + /// + ///OMNode methods + /// + public void setNextOMSibling(OMNode node) { + if (node instanceof ChildNode) + this.nextSibling = (ChildNode) node; + else + throw new OMException("The node is not a " + ChildNode.class); + } + + public void setPreviousOMSibling(OMNode node) { + if (node instanceof ChildNode) + this.previousSibling = (ChildNode) node; + else + throw new OMException("The node is not a " + ChildNode.class); + } + + public OMContainer getParent() throws OMException { + return (OMContainer) this.parentNode; + } + + public Node getParentNode() { + return this.parentNode; + } + + public void setParent(OMContainer element) { + if (element instanceof ParentNode) + this.parentNode = (ParentNode) element; + else + throw new OMException("The given parent is not of the type " + ParentNode.class); + + } + + public OMNode detach() throws OMException { + if (this.parentNode == null) { + throw new OMException("Parent level elements cannot be ditached"); + } else { + if (previousSibling == null) { // This is the first child + if (nextSibling != null) { + this.parentNode.setFirstChild(nextSibling); + } else { + this.parentNode.firstChild = null; + this.parentNode.lastChild = null; + } + } else if(nextSibling != null){ + ((OMNodeEx) this.getPreviousOMSibling()).setNextOMSibling(nextSibling); + } + if (this.nextSibling != null) { + this.nextSibling.setPreviousOMSibling(this.previousSibling); + } + this.parentNode = null; + } + return this; + } + + public void discard() throws OMException { + throw new UnsupportedOperationException("Cannot discard this node"); + } + + /** + * Insert the given sibling next to this item + */ + public void insertSiblingAfter(OMNode sibling) throws OMException { + + if (this.parentNode != null) { + ((OMNodeEx) sibling).setParent(this.parentNode); + } + + if (sibling instanceof ChildNode) { + ChildNode domSibling = (ChildNode) sibling; + domSibling.previousSibling = this; + if (this.nextSibling != null) { + this.nextSibling.previousSibling = domSibling; + } + domSibling.nextSibling = this.nextSibling; + this.nextSibling = domSibling; + + } else { + throw new OMException("The given child is not of type " + ChildNode.class); + } + } + + /** + * Insert the given sibling before this item + */ + public void insertSiblingBefore(OMNode sibling) throws OMException { // ((OMNodeEx)sibling).setParent(this.parentNode); - if(sibling instanceof ChildNode) { + if (sibling instanceof ChildNode) { // ChildNode domSibling = (ChildNode)sibling; // domSibling.nextSibling = this; // if(this.previousSibling != null) { @@ -162,24 +166,24 @@ siblingImpl.setPreviousOMSibling(previousSibling); } previousSibling = siblingImpl; - - } else { - throw new OMException("The given child is not of type " + ChildNode.class); - } - - } - - + + } else { + throw new OMException("The given child is not of type " + ChildNode.class); + } + + } + + public Node cloneNode(boolean deep) { - ChildNode newnode = (ChildNode) super.cloneNode(deep); - + ChildNode newnode = (ChildNode) super.cloneNode(deep); + // Need to break the association w/ original kids - newnode.previousSibling = null; - newnode.nextSibling = null; + newnode.previousSibling = null; + newnode.nextSibling = null; newnode.isFirstChild(false); - return newnode; + return newnode; } } Index: modules/xml/src/org/apache/axis2/om/FactoryFinder.java =================================================================== --- modules/xml/src/org/apache/axis2/om/FactoryFinder.java (revision 365352) +++ modules/xml/src/org/apache/axis2/om/FactoryFinder.java (working copy) @@ -50,12 +50,12 @@ String factoryClassName = factoryClass; //first look for a java system property - if (System.getProperty(systemPropertyName) != null) { + if (systemPropertyName != null && + System.getProperty(systemPropertyName) != null) { factoryClassName = systemPropertyName; } - ; - Object factory = null; + Object factory; try { if (loader == null) { factory = Class.forName(factoryClassName).newInstance(); @@ -82,8 +82,8 @@ public static SOAPFactory findSOAP11Factory(ClassLoader loader) throws OMFactoryException { return (SOAPFactory) findFactory(loader, - DEFAULT_SOAP11_FACTORY_CLASS_NAME, - SOAP11_FACTORY_NAME_PROPERTY); + DEFAULT_SOAP11_FACTORY_CLASS_NAME, + SOAP11_FACTORY_NAME_PROPERTY); } /** @@ -100,8 +100,8 @@ public static SOAPFactory findSOAP12Factory(ClassLoader loader) throws OMFactoryException { return (SOAPFactory) findFactory(loader, - DEFAULT_SOAP12_FACTORY_CLASS_NAME, - SOAP12_FACTORY_NAME_PROPERTY); + DEFAULT_SOAP12_FACTORY_CLASS_NAME, + SOAP12_FACTORY_NAME_PROPERTY); } /** @@ -118,7 +118,20 @@ public static OMFactory findOMFactory(ClassLoader loader) throws OMFactoryException { return (OMFactory) findFactory(loader, - DEFAULT_OM_FACTORY_CLASS_NAME, - OM_FACTORY_NAME_PROPERTY); + DEFAULT_OM_FACTORY_CLASS_NAME, + OM_FACTORY_NAME_PROPERTY); } + + /** + * + * @param classLoader + * @param soapFactory + * @return The SOAPFactory + */ + public static SOAPFactory findSOAPFactory(final ClassLoader classLoader, + final String soapFactory) { + return (SOAPFactory) findFactory(classLoader, + soapFactory, + null); + } } Index: modules/xml/src/org/apache/axis2/om/OMAbstractFactory.java =================================================================== --- modules/xml/src/org/apache/axis2/om/OMAbstractFactory.java (revision 365352) +++ modules/xml/src/org/apache/axis2/om/OMAbstractFactory.java (working copy) @@ -50,6 +50,28 @@ } /** + * This will pick up the provided <code>soapFactory</code> factory implementation from the classpath + * + * @param soapFactory Fully qualified SOAP 1.1 or SOAP 1.2 Factory implementation class name + * @return The SOAP 1.1 or 1.2 Factory implementation instance corresponding to <code>soapFactory</code> + */ + public static SOAPFactory getSOAPFactory(String soapFactory) { + return FactoryFinder.findSOAPFactory(null, soapFactory); + } + + /** + * This will pick up the provided <code>soapFactory</code> factory implementation using the provided + * <code>classLoader</code> + * + * @param classLoader + * @param soapFactory Fully qualified SOAP 1.1 or SOAP 1.2 Factory implementation class name + * @return The SOAP 1.1 or 1.2 Factory implementation instance corresponding to <code>soapFactory</code> + */ + public static SOAPFactory getSOAPFactory(ClassLoader classLoader, String soapFactory) { + return FactoryFinder.findSOAPFactory(classLoader, soapFactory); + } + + /** * This will pick up the default factory implementation from the classpath * * @return @@ -98,6 +120,8 @@ * So this method is to solve the chicken and egg problem, we have. If you do not know the SOAP version to be used * to process a particluar SOAP message you have recd, use this method to buid the SOAP envelope, and then extract the SOAP * version from that envlope and switch to the proper factory using that. + * + * @deprecated */ public static SOAPFactory getDefaultSOAPFactory() { return new SOAPLinkedListImplFactory(); Index: modules/saaj/test/org/apache/axis2/saaj/AttachmentTest.java =================================================================== --- modules/saaj/test/org/apache/axis2/saaj/AttachmentTest.java (revision 365352) +++ modules/saaj/test/org/apache/axis2/saaj/AttachmentTest.java (working copy) @@ -19,46 +19,46 @@ public AttachmentTest(String name) { super(name); } - + public void testStringAttachment() throws Exception { - SOAPConnectionFactory scFactory = SOAPConnectionFactory.newInstance(); - SOAPConnection con = scFactory.createConnection(); - - MessageFactory factory = MessageFactory.newInstance(); - SOAPMessage message = factory.createMessage(); - AttachmentPart attachment = message.createAttachmentPart(); - String stringContent = "Update address for Sunny Skies " + - "Inc., to 10 Upbeat Street, Pleasant Grove, CA 95439"; - - attachment.setContent(stringContent, "text/plain"); - attachment.setContentId("update_address"); - message.addAttachmentPart(attachment); - - assertTrue(message.countAttachments()==1); - - java.util.Iterator it = message.getAttachments(); - while (it.hasNext()) { - attachment = (AttachmentPart) it.next(); - Object content = attachment.getContent(); - String id = attachment.getContentId(); - System.out.println("Attachment " + id + " contains: " + content); - assertEquals(content,stringContent); - } - System.out.println("Here is what the XML message looks like:"); - message.writeTo(System.out); - - message.removeAllAttachments(); - assertTrue(message.countAttachments()==0); + SOAPConnectionFactory scFactory = SOAPConnectionFactory.newInstance(); + SOAPConnection con = scFactory.createConnection(); + + MessageFactory factory = MessageFactory.newInstance(); + SOAPMessage message = factory.createMessage(); + AttachmentPart attachment = message.createAttachmentPart(); + String stringContent = "Update address for Sunny Skies " + + "Inc., to 10 Upbeat Street, Pleasant Grove, CA 95439"; + + attachment.setContent(stringContent, "text/plain"); + attachment.setContentId("update_address"); + message.addAttachmentPart(attachment); + + assertTrue(message.countAttachments() == 1); + + java.util.Iterator it = message.getAttachments(); + while (it.hasNext()) { + attachment = (AttachmentPart) it.next(); + Object content = attachment.getContent(); + String id = attachment.getContentId(); + System.out.println("Attachment " + id + " contains: " + content); + assertEquals(content, stringContent); + } + System.out.println("Here is what the XML message looks like:"); + message.writeTo(System.out); + + message.removeAllAttachments(); + assertTrue(message.countAttachments() == 0); } - + public void testMultipleAttachments() throws Exception { SOAPConnectionFactory scFactory = SOAPConnectionFactory.newInstance(); SOAPConnection con = scFactory.createConnection(); MessageFactory factory = MessageFactory.newInstance(); SOAPMessage msg = factory.createMessage(); - java.net.URL url1 = new java.net.URL("http://slashdot.org/slashdot.xml"); - java.net.URL url2 = new java.net.URL("http://www.apache.org/LICENSE.txt"); + java.net.URL url1 = new java.net.URL("http://www.apache.org/licenses/LICENSE-2.0.html"); + java.net.URL url2 = new java.net.URL("http://www.apache.org/licenses/LICENSE-2.0.txt"); AttachmentPart a1 = msg.createAttachmentPart(new javax.activation.DataHandler(url1)); a1.setContentType("text/xml"); @@ -70,54 +70,58 @@ a3.setContentType("text/plain"); msg.addAttachmentPart(a3); - assertTrue(msg.countAttachments()==3); + assertTrue(msg.countAttachments() == 3); javax.xml.soap.MimeHeaders mimeHeaders = new javax.xml.soap.MimeHeaders(); mimeHeaders.addHeader("Content-Type", "text/xml"); int nAttachments = 0; java.util.Iterator iterator = msg.getAttachments(mimeHeaders); - while (iterator.hasNext()) { + while (iterator.hasNext()) { nAttachments++; - AttachmentPart ap = (AttachmentPart)iterator.next(); - assertTrue(ap.equals(a1) || ap.equals(a2)); - } - assertTrue(nAttachments==2); + AttachmentPart ap = (AttachmentPart) iterator.next(); + assertTrue(ap.equals(a1) || ap.equals(a2)); + } + assertTrue(nAttachments == 2); } - + public void testBadAttSize() throws Exception { MessageFactory factory = MessageFactory.newInstance(); SOAPMessage message = factory.createMessage(); - ByteArrayInputStream ins=new ByteArrayInputStream(new byte[5]); - DataHandler dh=new DataHandler(new Src(ins,"text/plain")); + ByteArrayInputStream ins = new ByteArrayInputStream(new byte[5]); + DataHandler dh = new DataHandler(new Src(ins, "text/plain")); AttachmentPart part = message.createAttachmentPart(dh); - assertEquals("Size should match",5,part.getSize()); + assertEquals("Size should match", 5, part.getSize()); } - class Src implements DataSource{ + class Src implements DataSource { InputStream m_src; String m_type; - public Src(InputStream data, String type){ - m_src=data; - m_type=type; + public Src(InputStream data, String type) { + m_src = data; + m_type = type; } - public String getContentType(){ + + public String getContentType() { return m_type; } - public InputStream getInputStream() throws IOException{ + + public InputStream getInputStream() throws IOException { m_src.reset(); return m_src; } - public String getName(){ + + public String getName() { return "Some-Data"; } - public OutputStream getOutputStream(){ + + public OutputStream getOutputStream() { throw new UnsupportedOperationException("I don't give output streams"); } } - + public static void main(String[] args) throws Exception { AttachmentTest tester = new AttachmentTest("TestSAAJ"); tester.testMultipleAttachments(); Index: modules/saaj/test-resources/Echo.aar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream