Commits

Anonymous committed a7c5c78

Initial import.

  • Participants
  • Parent commits ece3747

Comments (0)

Files changed (43)

+Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+#!/bin/bash
+
+# This script builds the www structure to be deployed on a web server
+
+cd soap-dtc
+mvn clean
+mvn test || exit 1
+
+cd ../soap-dtc-core
+mvn javadoc:javadoc || exit 1
+mvn jxr:jxr || exit 1
+mvn assembly:assembly || exit 1
+
+cd ../soap-dtc-server
+mvn javadoc:javadoc || exit 1
+mvn jxr:jxr || exit 1
+mvn assembly:assembly || exit 1
+
+cd ../soap-dtc
+mvn assembly:assembly || exit 1
+mvn deploy || exit 1
+
+cd ..
+mkdir www
+
+mkdir www/releases
+cp soap-dtc/target/*.zip www/releases
+cp soap-dtc/target/*.tar.bz2 www/releases
+cp soap-dtc-core/target/*.zip www/releases
+cp soap-dtc-core/target/*.tar.bz2 www/releases
+cp soap-dtc-server/target/*.zip www/releases
+cp soap-dtc-server/target/*.tar.bz2 www/releases
+
+cp -R repository www/
+
+mkdir www/generated-docs
+mkdir www/generated-docs/soap-dtc-core
+mkdir www/generated-docs/soap-dtc-server
+cp -R soap-dtc-core/target/site/apidocs www/generated-docs/soap-dtc-core
+cp -R soap-dtc-server/target/site/apidocs www/generated-docs/soap-dtc-server
+
+cp -R soap-dtc-core/target/site/xref www/generated-docs/soap-dtc-core
+cp -R soap-dtc-server/target/site/xref www/generated-docs/soap-dtc-server
+

soap-dtc-core/LICENSE.txt

+Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

soap-dtc-core/pom.xml

+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>com.izforge.soap-dtc</groupId>
+        <artifactId>soap-dtc</artifactId>
+        <version>0.1-SNAPSHOT</version>
+        <relativePath>../soap/pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.izforge.soap-dtc</groupId>
+    <artifactId>soap-dtc-core</artifactId>
+    <version>0.1-SNAPSHOT</version>
+
+    <name>SOAP-DTC - Simple SOAP for Java Core Library</name>
+    <description>Server-side support library for SOAP-DTC.</description>
+    <url>http://www.izforge.com/soap-dtc/</url>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>xpp3</groupId>
+            <artifactId>xpp3</artifactId>
+            <version>1.1.3.4.O</version>
+        </dependency>
+        <dependency>
+            <groupId>dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+            <version>1.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>jaxen</groupId>
+            <artifactId>jaxen</artifactId>
+            <version>1.1-beta-9</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.0.1</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mortbay.jetty</groupId>
+            <artifactId>jetty</artifactId>
+            <version>6.0.0rc0</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.5</source>
+                    <target>1.5</target>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <descriptors>
+                        <descriptor>src/main/assembly/bin.xml</descriptor>
+                        <descriptor>src/main/assembly/src.xml</descriptor>
+                    </descriptors>
+                </configuration>
+            </plugin>
+
+        </plugins>
+    </build>
+
+</project>

soap-dtc-core/src/main/assembly/bin.xml

+<?xml version="1.0" encoding="UTF-8"?>
+
+<assembly>
+
+    <id>bin</id>
+    <formats>
+        <format>zip</format>
+        <format>tar.bz2</format>
+    </formats>
+
+    <fileSets>
+
+        <fileSet>
+            <includes>
+                <include>LICENSE*</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>target</directory>
+            <outputDirectory></outputDirectory>
+            <includes>
+                <include>*.jar</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>target/site/apidocs</directory>
+            <outputDirectory>apidocs</outputDirectory>
+        </fileSet>
+
+    </fileSets>
+
+    <dependencySets>
+
+        <dependencySet>
+            <unpack>false</unpack>
+            <scope>runtime</scope>
+            <outputDirectory>lib</outputDirectory>
+            <includes>
+                <include>xpp3:xpp3</include>
+                <include>dom4j:dom4j</include>
+                <include>jaxen:jaxen</include>
+                <include>commons-httpclient:commons-httpclient</include>
+                <include>commons-codec:commons-codec</include>
+                <include>commons-logging:commons-logging</include>
+            </includes>
+        </dependencySet>
+
+    </dependencySets>
+
+</assembly>

soap-dtc-core/src/main/assembly/src.xml

+<?xml version="1.0" encoding="UTF-8"?>
+
+<assembly>
+
+    <id>src</id>
+    <formats>
+        <format>zip</format>
+        <format>tar.bz2</format>
+    </formats>
+
+    <fileSets>
+
+        <fileSet>
+           <includes>
+                <include>AUTHORS*</include>
+                <include>CHANGES*</include>
+                <include>LICENSE*</include>
+                <include>TODO*</include>
+                <include>pom.xml</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>src</directory>
+        </fileSet>
+
+    </fileSets>
+
+</assembly>

soap-dtc-core/src/main/java/com/izforge/soapdtc/SoapConstants.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc;
+
+/**
+ * Various constants.
+ *
+ * @author Julien Ponge (julien.ponge@gmail.com)
+ */
+public interface SoapConstants
+{
+    /**
+     * SOAP 1.2 Envelope namespace.
+     */
+    public static final String SOAP12_ENV_NS = "http://www.w3.org/2003/05/soap-envelope";
+
+    /**
+     * Prefix used in QName for the SOAP 1.2 Envelope namespace.
+     */
+    public static final String SOAP12_ENV_PREFIX = "env";
+
+    /**
+     * XML Schema namespace.
+     */
+    public static final String XSD_NS = "http://www.w3.org/2001/XMLSchema";
+
+    /**
+     * Prefix used in QName for the XML Schema namespace.
+     */
+    public static final String XSD_PREFIX = "xsd";
+
+    /**
+     * XML namespace.
+     */
+    public static final String XML_NS = "http://www.w3.org/XML/1998/namespace";
+
+    /**
+     * Prefix used in QName for the XML namespace.
+     */
+    public static final String XML_PREFIX = "xml";
+
+    /* .......................................................................................... */
+
+    /**
+     * SOAP fault code. See <a href="http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes">http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes</a>
+     */
+    public static final String SOAP12_FAULT_VERSION_MISMATCH = "env:VersionMismatch";
+
+    /**
+     * SOAP fault code. See <a href="http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes">http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes</a>
+     */
+    public static final String SOAP12_FAULT_MUST_UNDERSTAND = "env:MustUnderstand";
+
+    /**
+     * SOAP fault code. See <a href="http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes">http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes</a>
+     */
+    public static final String SOAP12_FAULT_DATA_ENCODING_UNKNOWN = "env:DataEncodingUnknown";
+
+    /**
+     * SOAP fault code. See <a href="http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes">http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes</a>
+     */
+    public static final String SOAP12_FAULT_SENDER = "env:Sender";
+
+    /**
+     * SOAP fault code. See <a href="http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes">http://www.w3.org/TR/2003/REC-soap12-part1-20030624/#faultcodes</a>
+     */
+    public static final String SOAP12_FAULT_RECEIVER = "env:Receiver";
+
+    /**
+     * SOAP header for reporting not-understood headers.
+     */
+    public static final String SOAP12_NOT_UNDERSTOOD_HEADER = "env:NotUnderstood";
+}

soap-dtc-core/src/main/java/com/izforge/soapdtc/SoapFault.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc;
+
+import org.dom4j.DocumentFactory;
+import org.dom4j.Element;
+import org.dom4j.QName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SOAP fault helper class. By default, the error code will be set to env:Sender, and you will need to at least
+ * add one reason to produce a valid SOAP fault XML element.
+ *
+ * @author Julien Ponge (julien.ponge@gmail.com)
+ */
+public class SoapFault
+{
+    /**
+     * The Dom4J factory.
+     */
+    private DocumentFactory documentFactory;
+
+    /**
+     * Models env:Code.
+     */
+    private FaultCode code = new FaultCode();
+
+    /**
+     * Models env:Reason.
+     */
+    private List<FaultReason> reasons = new ArrayList<FaultReason>();
+
+    /**
+     * Models env:Node.
+     */
+    private String node;
+
+    /**
+     * Models env:Role.
+     */
+    private String role;
+
+    /**
+     * Models env:Detail.
+     */
+    private Element detail;
+
+    /* .......................................................................................... */
+
+    public SoapFault()
+    {
+        this.documentFactory = DocumentFactory.getInstance();
+        SoapMessageUtils.configureDocumentFactoryXPathNamespaceURIs(documentFactory);
+    }
+
+    public SoapFault(DocumentFactory documentFactory)
+    {
+        this.documentFactory = documentFactory;
+    }
+
+    /**
+     * Sets the fault code.
+     *
+     * @param value          should be taken from SoapConstants if possible
+     * @param subcodeValue   optional subcode
+     * @param subcodeSubcode optinal subcode subcode
+     */
+    public void setCode(String value, String subcodeValue, String subcodeSubcode)
+    {
+        code.value = value;
+        code.subcodeValue = subcodeValue;
+        code.subcodeSubcode = subcodeSubcode;
+    }
+
+    /**
+     * Adds a human-readable fault description.
+     *
+     * @param lang the language in which the text is written (ex: en, fr, ...).
+     * @param text the text.
+     */
+    public void addReason(String lang, String text)
+    {
+        reasons.add(new FaultReason(lang, text));
+    }
+
+    /**
+     * Sets the optional node information.
+     *
+     * @param node the node information.
+     */
+    public void setNode(String node)
+    {
+        this.node = node;
+    }
+
+    /**
+     * Sets the optional role information.
+     *
+     * @param role the role information.
+     */
+    public void setRole(String role)
+    {
+        this.role = role;
+    }
+
+    /**
+     * Sets the optional detail information, with application-specific content.
+     *
+     * @param detail the namespaced XML content to be added under env:Detail.
+     */
+    public void setDetail(Element detail)
+    {
+        this.detail = detail;
+    }
+
+    /**
+     * Converts the SOAP fault to an XML element, for example to add it to a SOAP body.
+     *
+     * @return the fault as an XML element.
+     */
+    public Element toXmlElement()
+    {
+        Element faultElement = documentFactory.createElement("env:Fault", SoapConstants.SOAP12_ENV_NS);
+        createCodeElement(faultElement);
+        createReasonElement(faultElement);
+        createNodeElement(faultElement);
+        createRoleElement(faultElement);
+        createDetailElement(faultElement);
+        return faultElement;
+    }
+
+    private void createDetailElement(Element faultElement)
+    {
+        if (detail != null)
+        {
+            Element e = documentFactory.createElement("env:Detail", SoapConstants.SOAP12_ENV_NS);
+            e.add(detail);
+            faultElement.add(e);
+        }
+    }
+
+    private void createRoleElement(Element faultElement)
+    {
+        if (role != null)
+        {
+            Element e = documentFactory.createElement("env:Role", SoapConstants.SOAP12_ENV_NS);
+            e.setText(role);
+            faultElement.add(e);
+        }
+    }
+
+    private void createNodeElement(Element faultElement)
+    {
+        if (node != null)
+        {
+            Element e = documentFactory.createElement("env:Node", SoapConstants.SOAP12_ENV_NS);
+            e.setText(node);
+            faultElement.add(e);
+        }
+    }
+
+    private void createReasonElement(Element faultElement)
+    {
+        Element reasonElement = documentFactory.createElement("env:Reason", SoapConstants.SOAP12_ENV_NS);
+        for (FaultReason reason : reasons)
+        {
+            Element e = documentFactory.createElement("env:Text", SoapConstants.SOAP12_ENV_NS);
+            e.add(documentFactory.createAttribute(e, QName.get("xml:lang", SoapConstants.XML_NS), reason.lang));
+            e.setText(reason.text);
+            reasonElement.add(e);
+        }
+        faultElement.add(reasonElement);
+    }
+
+    private void createCodeElement(Element faultElement)
+    {
+        Element codeElement = documentFactory.createElement("env:Code", SoapConstants.SOAP12_ENV_NS);
+        Element codeValue = documentFactory.createElement("env:Value", SoapConstants.SOAP12_ENV_NS);
+        codeValue.setText(code.value);
+        codeElement.add(codeValue);
+        if (code.subcodeValue != null)
+        {
+            Element subCode = documentFactory.createElement("env:Subcode", SoapConstants.SOAP12_ENV_NS);
+            Element e = documentFactory.createElement("env:Value", SoapConstants.SOAP12_ENV_NS);
+            e.setText(code.subcodeValue);
+            subCode.add(e);
+
+            if (code.subcodeSubcode != null)
+            {
+                e = documentFactory.createElement("env:Subcode", SoapConstants.SOAP12_ENV_NS);
+                e.setText(code.subcodeSubcode);
+                subCode.add(e);
+            }
+            codeElement.add(subCode);
+        }
+        faultElement.add(codeElement);
+    }
+
+    /* .......................................................................................... */
+
+    private static class FaultCode
+    {
+        String value = SoapConstants.SOAP12_FAULT_SENDER;
+        String subcodeValue;
+        String subcodeSubcode;
+    }
+
+    private static class FaultReason
+    {
+        String lang;
+        String text;
+
+        public FaultReason(String lang, String text)
+        {
+            this.lang = lang;
+            this.text = text;
+        }
+    }
+}

soap-dtc-core/src/main/java/com/izforge/soapdtc/SoapMessage.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc;
+
+import org.dom4j.Attribute;
+import org.dom4j.Document;
+import org.dom4j.DocumentFactory;
+import org.dom4j.Element;
+
+/**
+ * The interface for SOAP Messages.
+ *
+ * @author Julien Ponge (julien.ponge@gmail.com)
+ */
+public class SoapMessage
+{
+    /**
+     * The Dom4J elements factory.
+     */
+    private DocumentFactory documentFactory;
+
+    /**
+     * The actual SOAP message Dom4J document.
+     */
+    private Document soapDocument;
+
+    /* .......................................................................................... */
+
+    public SoapMessage()
+    {
+        documentFactory = DocumentFactory.getInstance();
+        SoapMessageUtils.configureDocumentFactoryXPathNamespaceURIs(documentFactory);
+        soapDocument = createSoapEnvelope();
+    }
+
+    public SoapMessage(DocumentFactory documentFactory)
+    {
+        this.documentFactory = documentFactory;
+        SoapMessageUtils.configureDocumentFactoryXPathNamespaceURIs(documentFactory);
+        soapDocument = createSoapEnvelope();
+    }
+
+    public SoapMessage(Document soapDocument)
+    {
+        documentFactory = DocumentFactory.getInstance();
+        SoapMessageUtils.configureDocumentFactoryXPathNamespaceURIs(documentFactory);
+        this.soapDocument = soapDocument;
+    }
+
+    public SoapMessage(DocumentFactory documentFactory, Document soapDocument)
+    {
+        this.documentFactory = documentFactory;
+        SoapMessageUtils.configureDocumentFactoryXPathNamespaceURIs(documentFactory);
+        this.soapDocument = soapDocument;
+    }
+
+    /* .......................................................................................... */
+
+    /**
+     * Provides access to the SOAP Header element.
+     *
+     * @return the SOAP header element.
+     */
+    public Element getHeaderElement()
+    {
+        return (Element) soapDocument.selectSingleNode("//env:Header");
+    }
+
+    /**
+     * Provides access to the SOAP body element.
+     *
+     * @return the SOAP body element.
+     */
+    public Element getBodyElement()
+    {
+        return (Element) soapDocument.selectSingleNode("//env:Body");
+    }
+
+    /**
+     * Specifies wether the SOAP body contains a SOAP fault or not.
+     *
+     * @return <code>true</code> if there is a SOAP fault, <code>false</code> otherwise.
+     */
+    public boolean containsFault()
+    {
+        return soapDocument.selectSingleNode("//env:Fault") != null;
+    }
+
+    /**
+     * Provides access to the SOAP fault element, if any.
+     *
+     * @return the SOAP fault element, or <code>null</code> if the SOAP body does not contain a SOAP fault.
+     */
+    public Element getFaultElement()
+    {
+        return (Element) soapDocument.selectSingleNode("//env:Fault");
+    }
+
+    /**
+     * Provides access to the SOAP message document.
+     *
+     * @return the SOAP message document.
+     */
+    public Document getSoapDocument()
+    {
+        return soapDocument;
+    }
+
+    /**
+     * Provides access to the Dom4J factory used for this message.
+     *
+     * @return the Dom4J factory.
+     */
+    public DocumentFactory getDocumentFactory()
+    {
+        return documentFactory;
+    }
+
+    /* .......................................................................................... */
+
+    /**
+     * Adds an element to the SOAP header, taking care of specifying wether it must be understood by the next node or not.
+     *
+     * @param element        the element to add.
+     * @param mustUnderstand wether the header must be understood by the next node or not.
+     */
+    public void addHeaderElement(Element element, boolean mustUnderstand)
+    {
+        String value = mustUnderstand ? "1" : "0";
+        Attribute mustUnderstandAttribute = documentFactory.createAttribute(element, "env:mustUnderstand", value);
+        element.add(mustUnderstandAttribute);
+        getHeaderElement().add(element);
+    }
+
+    /**
+     * Adds an element to the SOAP header, but does not take care of specifying wether it needs to be understood by the next node or not.
+     *
+     * @param element the element to add.
+     */
+    public void addHeaderElement(Element element)
+    {
+        getHeaderElement().add(element);
+    }
+
+    /**
+     * Adds an element to the SOAP body.
+     *
+     * @param element the element to add.
+     */
+    public void addBodyElement(Element element)
+    {
+        getBodyElement().add(element);
+    }
+
+    /* .......................................................................................... */
+
+    /**
+     * Creates a SOAP envelope for an empty SOAP message.
+     *
+     * @return a new SOAP message envelope.
+     */
+    private Document createSoapEnvelope()
+    {
+        soapDocument = documentFactory.createDocument();
+
+        Element rootElement = documentFactory.createElement("env:Envelope", SoapConstants.SOAP12_ENV_NS);
+        soapDocument.setRootElement(rootElement);
+
+        rootElement.addNamespace(SoapConstants.SOAP12_ENV_PREFIX, SoapConstants.SOAP12_ENV_NS);
+        rootElement.addNamespace(SoapConstants.XML_PREFIX, SoapConstants.XML_NS);
+        rootElement.add(documentFactory.createElement("env:Header", SoapConstants.SOAP12_ENV_NS));
+        rootElement.add(documentFactory.createElement("env:Body", SoapConstants.SOAP12_ENV_NS));
+
+        return soapDocument;
+    }
+}

soap-dtc-core/src/main/java/com/izforge/soapdtc/SoapMessageUtils.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentFactory;
+import org.dom4j.io.XPP3Reader;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class for SOAP messages.
+ *
+ * @author Julien Ponge (julien.ponge@gmail.com)
+ */
+public class SoapMessageUtils
+{
+    /**
+     * Registers our namespaces URIs and prefixes for proper XPath queries evaluation.
+     *
+     * @param documentFactory
+     */
+    public static void configureDocumentFactoryXPathNamespaceURIs(DocumentFactory documentFactory)
+    {
+        Map uris = loadOrCreateMap(documentFactory);
+        uris.put(SoapConstants.SOAP12_ENV_PREFIX, SoapConstants.SOAP12_ENV_NS);
+        uris.put(SoapConstants.XML_PREFIX, SoapConstants.XML_NS);
+    }
+
+    /**
+     * Registers a namespace URI and prefix in a Dom4J factory for proper XPath queries evaluation.
+     *
+     * @param documentFactory
+     */
+    public static void registerDocumentFactoryXPathNamespaceURIs(DocumentFactory documentFactory, String prefix, String namespace)
+    {
+        Map uris = loadOrCreateMap(documentFactory);
+        uris.put(prefix, namespace);
+    }
+
+    /**
+     * Loads a namespaces map, or create one if needed.
+     *
+     * @param documentFactory the Dom4J factory.
+     * @return the namespaces map.
+     */
+    private static Map loadOrCreateMap(DocumentFactory documentFactory)
+    {
+        Map uris = documentFactory.getXPathNamespaceURIs();
+        if (uris == null)
+        {
+            uris = new HashMap();
+            documentFactory.setXPathNamespaceURIs(uris);
+        }
+        return uris;
+    }
+
+    /**
+     * Reads a SOAP message from an input stream.
+     *
+     * @param in              the input stream.
+     * @param documentFactory the Dom4J factory.
+     * @return a SOAP message.
+     * @throws DocumentException      if there is a problem with the document.
+     * @throws IOException            if there is an I/O error.
+     * @throws XmlPullParserException if the parser encounters a problem.
+     */
+    public static SoapMessage readSoapMessageFromStream(InputStream in, DocumentFactory documentFactory) throws DocumentException, IOException, XmlPullParserException
+    {
+        configureDocumentFactoryXPathNamespaceURIs(documentFactory);
+        XPP3Reader reader = new XPP3Reader(documentFactory);
+        Document envelope = reader.read(in);
+        in.close();
+        return new SoapMessage(documentFactory, envelope);
+    }
+
+    /**
+     * Reads a SOAP message from an input stream.
+     *
+     * @param in the input stream.
+     * @return a SOAP message.
+     * @throws DocumentException      if there is a problem with the document.
+     * @throws IOException            if there is an I/O error.
+     * @throws XmlPullParserException if the parser encounters a problem.
+     */
+    public static SoapMessage readSoapMessageFromStream(InputStream in) throws DocumentException, IOException, XmlPullParserException
+    {
+        return readSoapMessageFromStream(in, DocumentFactory.getInstance());
+    }
+}

soap-dtc-core/src/main/java/com/izforge/soapdtc/transport/HttpSoapTransport.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc.transport;
+
+import com.izforge.soapdtc.SoapMessage;
+import com.izforge.soapdtc.SoapMessageUtils;
+import org.apache.commons.httpclient.*;
+import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.params.HostParams;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentFactory;
+import org.dom4j.io.XMLWriter;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+
+/**
+ * SOAP transport over HTTP / HTTPS. It supports the send/receive and receive message exchange patterns.
+ *
+ * @author Julien Ponge (julien.ponge@gmail.com)
+ */
+public class HttpSoapTransport
+{
+    /**
+     * Dom4J factory.
+     */
+    private DocumentFactory documentFactory;
+
+    /**
+     * HttpClient agent configuration.
+     */
+    private HostConfiguration hostConfiguration;
+
+    /**
+     * Http agent.
+     */
+    private HttpClient httpClient;
+
+    public HttpSoapTransport()
+    {
+        this.documentFactory = DocumentFactory.getInstance();
+    }
+
+    public HttpSoapTransport(DocumentFactory documentFactory)
+    {
+        this.documentFactory = documentFactory;
+    }
+
+    public HttpSoapTransport(HostConfiguration hostConfiguration)
+    {
+        this.hostConfiguration = hostConfiguration;
+    }
+
+    public HttpSoapTransport(DocumentFactory documentFactory, HostConfiguration hostConfiguration)
+    {
+        this.documentFactory = documentFactory;
+        this.hostConfiguration = hostConfiguration;
+    }
+
+    /**
+     * Provides access to the Dom4J factory in use.
+     *
+     * @return the Dom4J factory.
+     */
+    public DocumentFactory getDocumentFactory()
+    {
+        return documentFactory;
+    }
+
+    /**
+     * Provides access to the Http agent configuration.
+     *
+     * @return the Http agent configuration.
+     */
+    public HostConfiguration getHostConfiguration()
+    {
+        return hostConfiguration;
+    }
+
+    /**
+     * Sets the new Http client configuration.
+     *
+     * @param hostConfiguration the new Http client configuration.
+     */
+    public void setHostConfiguration(HostConfiguration hostConfiguration)
+    {
+        this.hostConfiguration = hostConfiguration;
+    }
+
+    /**
+     * Delegate method.
+     *
+     * @param httpHost the Http host.
+     * @see HostConfiguration#setHost(org.apache.commons.httpclient.HttpHost)
+     */
+    public void setHostConfigurationHost(HttpHost httpHost)
+    {
+        hostConfiguration.setHost(httpHost);
+    }
+
+    /**
+     * Delegate method.
+     *
+     * @param uri the Http host uri.
+     * @see HostConfiguration#setHost(org.apache.commons.httpclient.HttpHost)
+     */
+    public void setHostConfigurationHost(URI uri)
+    {
+        hostConfiguration.setHost(uri);
+    }
+
+    /**
+     * Delegate method.
+     *
+     * @param proxyHost the proxy host.
+     * @see HostConfiguration#setProxyHost(org.apache.commons.httpclient.ProxyHost)
+     */
+    public void setHostConfigurationProxyHost(ProxyHost proxyHost)
+    {
+        hostConfiguration.setProxyHost(proxyHost);
+    }
+
+    /**
+     * Delegate method.
+     *
+     * @param inetAddress the inet address.
+     * @see HostConfiguration#setLocalAddress(java.net.InetAddress)
+     */
+    public void setHostConfigurationLocalAddress(InetAddress inetAddress)
+    {
+        hostConfiguration.setLocalAddress(inetAddress);
+    }
+
+    /**
+     * Delegate method.
+     *
+     * @param hostParams the host parameters.
+     * @see HostConfiguration#setParams(org.apache.commons.httpclient.params.HostParams)
+     */
+    public void setHostConfigurationParams(HostParams hostParams)
+    {
+        hostConfiguration.setParams(hostParams);
+    }
+
+    /**
+     * Lazy instanciation access to the Http agent.
+     *
+     * @return the Http agent.
+     */
+    private HttpClient getHttpClient()
+    {
+        if (httpClient == null)
+        {
+            httpClient = new HttpClient();
+        }
+        return httpClient;
+    }
+
+    /**
+     * Send then receive pattern for the SOAP HTTP binding.
+     *
+     * @param uri         the endpoint uri.
+     * @param soapMessage the SOAP message to sendReceive.
+     * @param soapAction  the <code>soapAction</code> parameter, or <code>null</code>
+     * @return the response SOAP message.
+     * @throws SoapTransportException if an error occurs, including a SOAP fault when appropriate.
+     */
+    public SoapMessage sendReceive(String uri, SoapMessage soapMessage, String soapAction) throws SoapTransportException
+    {
+        PostMethod postMethod = new PostMethod(uri);
+        try
+        {
+            encodeSoapAction(postMethod, soapAction);
+            postMethod.setRequestEntity(createRequestEntity(soapMessage));
+            getHttpClient().executeMethod(hostConfiguration, postMethod);
+        }
+        catch (Throwable t)
+        {
+            postMethod.releaseConnection();
+            throw new SoapTransportException(t);
+        }
+        return readSoapResponse(postMethod.getStatusCode(), postMethod);
+    }
+
+    /**
+     * Asynchronous version of <code>sendReceive</code>.
+     *
+     * @param uri         the endpoint uri.
+     * @param soapMessage the SOAP message.
+     * @param soapAction  the optional <code>soapAction</code> parameter.
+     * @param handler     the asynchronous handler.
+     */
+    public void asyncSendReceive(final String uri, final SoapMessage soapMessage, final String soapAction, final IAsyncSoapMessageHandler handler)
+    {
+        Thread thread = new Thread(new Runnable()
+        {
+            public void run()
+            {
+                try
+                {
+                    SoapMessage response = sendReceive(uri, soapMessage, soapAction);
+                    handler.handleAsyncResponse(response);
+                }
+                catch (SoapTransportException e)
+                {
+                    handler.handleAsyncTransportException(e);
+                }
+            }
+        });
+        thread.start();
+    }
+
+    /**
+     * Receive pattern for the SOAP HTTP binding.
+     *
+     * @param uri        the endpoint uri.
+     * @param soapAction the <code>soapAction</code> parameter, or <code>null</code>
+     * @return the response SOAP message.
+     * @throws SoapTransportException if an error occurs, including a SOAP fault when appropriate.
+     */
+    public SoapMessage receive(String uri, String soapAction) throws SoapTransportException
+    {
+        GetMethod getMethod = new GetMethod(uri);
+        try
+        {
+            encodeSoapAction(getMethod, soapAction);
+            getHttpClient().executeMethod(hostConfiguration, getMethod);
+        }
+        catch (Throwable t)
+        {
+            getMethod.releaseConnection();
+            throw new SoapTransportException(t);
+        }
+        return readSoapResponse(getMethod.getStatusCode(), getMethod);
+    }
+
+    /**
+     * Asynchronous version of <code>receive</code>.
+     *
+     * @param uri        the endpoint uri.
+     * @param soapAction the optional <code>soapAction</code> parameter.
+     * @param handler    the asynchronous handler.
+     */
+    public void asyncReceive(final String uri, final String soapAction, final IAsyncSoapMessageHandler handler)
+    {
+        Thread thread = new Thread(new Runnable()
+        {
+            public void run()
+            {
+                try
+                {
+                    SoapMessage response = receive(uri, soapAction);
+                    handler.handleAsyncResponse(response);
+                }
+                catch (SoapTransportException e)
+                {
+                    handler.handleAsyncTransportException(e);
+                }
+            }
+        });
+        thread.start();
+    }
+
+    /**
+     * Reads a SOAP nessage from a HTTP reponse, or throws an exception if an error occurs.
+     *
+     * @param statusCode the HTTP status code.
+     * @param method     the HTTP method.
+     * @return the SOAP message in case of success.
+     * @throws SoapTransportException if an error has occured.
+     */
+    private SoapMessage readSoapResponse(int statusCode, HttpMethod method)
+            throws SoapTransportException
+    {
+        // 200, 202 and 500 have a SOAP payload
+        if (statusCode == 200 || statusCode == 202 || statusCode == 500)
+        {
+            try
+            {
+                SoapMessage response = SoapMessageUtils.readSoapMessageFromStream(method.getResponseBodyAsStream(), documentFactory);
+                method.releaseConnection();
+                if (statusCode == 500)
+                {
+                    throw new SoapTransportException(response);
+                }
+                else
+                {
+                    return response;
+                }
+            }
+            catch (DocumentException e)
+            {
+                method.releaseConnection();
+                throw new SoapTransportException(e);
+            }
+            catch (IOException e)
+            {
+                method.releaseConnection();
+                throw new SoapTransportException(e);
+            }
+            catch (XmlPullParserException e)
+            {
+                method.releaseConnection();
+                throw new SoapTransportException(e);
+            }
+        }
+
+        // This is for 4xx errors
+        String statusText = method.getStatusText();
+        method.releaseConnection();
+        throw new SoapTransportException(statusText);
+    }
+
+    /**
+     * Quote-encoding of a <code>soapAction</code>.
+     *
+     * @param method     the HTTP method.
+     * @param soapAction thd soapAction value, or <code>null</code>.
+     */
+    private void encodeSoapAction(HttpMethod method, String soapAction)
+    {
+        if (soapAction != null)
+        {
+            if (!(soapAction.startsWith("\"") && soapAction.endsWith("\"")))
+            {
+                soapAction = "\"" + soapAction + "\"";
+            }
+            method.setRequestHeader("SOAPAction", soapAction);
+        }
+    }
+
+    /**
+     * Creates a request entity to sendReceive the SOAP message over HTTP POST.
+     *
+     * @param soapMessage the SOAP message.
+     * @return the request entity.
+     * @throws IOException if an I/O error occurs.
+     */
+    private RequestEntity createRequestEntity(SoapMessage soapMessage) throws IOException
+    {
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        XMLWriter xmlWriter = new XMLWriter(byteArrayOutputStream);
+        xmlWriter.write(soapMessage.getSoapDocument());
+        xmlWriter.close();
+        byteArrayOutputStream.close();
+
+        return new ByteArrayRequestEntity(byteArrayOutputStream.toByteArray(), "text/xml; charset=UTF-8");
+    }
+}

soap-dtc-core/src/main/java/com/izforge/soapdtc/transport/IAsyncSoapMessageHandler.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc.transport;
+
+import com.izforge.soapdtc.SoapMessage;
+
+/**
+ * Interface for asynchronous SOAP messages handlers.
+ *
+ * @author Julien Ponge (julien.ponge@gmail.com)
+ */
+public interface IAsyncSoapMessageHandler
+{
+    /**
+     * Handles a successful asynchronous response.
+     *
+     * @param response the response SOAP message.
+     */
+    public void handleAsyncResponse(SoapMessage response);
+
+    /**
+     * Handles a transport exception.
+     *
+     * @param exception the exception.
+     */
+    public void handleAsyncTransportException(SoapTransportException exception);
+}

soap-dtc-core/src/main/java/com/izforge/soapdtc/transport/SoapTransportException.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc.transport;
+
+import com.izforge.soapdtc.SoapMessage;
+
+public class SoapTransportException extends Exception
+{
+    SoapMessage soapMessageWithFault;
+
+    public SoapTransportException(SoapMessage soapMessageWithFault)
+    {
+        super();
+        this.soapMessageWithFault = soapMessageWithFault;
+    }
+
+    public SoapTransportException(String message)
+    {
+        super(message);
+    }
+
+    public SoapTransportException(Throwable cause)
+    {
+        super(cause);
+    }
+
+    public SoapMessage getSoapMessageWithFault()
+    {
+        return soapMessageWithFault;
+    }
+
+    public boolean hasSoapMessageWithFault()
+    {
+        return soapMessageWithFault != null;
+    }
+}

soap-dtc-core/src/test/java/com/izforge/soapdtc/SoapFaultTest.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc;
+
+import junit.framework.TestCase;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentFactory;
+import org.dom4j.Element;
+import org.dom4j.io.XPP3Reader;
+import org.dom4j.util.NodeComparator;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+public class SoapFaultTest extends TestCase
+{
+    private NodeComparator nodeComparator = new NodeComparator();
+
+    private DocumentFactory documentFactory = DocumentFactory.getInstance();
+
+    public SoapFaultTest()
+    {
+        SoapMessageUtils.configureDocumentFactoryXPathNamespaceURIs(documentFactory);
+    }
+
+    public void testToXmlElement() throws DocumentException, IOException, XmlPullParserException
+    {
+        SoapFault fault = new SoapFault();
+        fault.setCode(SoapConstants.SOAP12_FAULT_SENDER, "m:MessageTimeout", null);
+        fault.addReason("en", "Sender Timeout");
+        Element detailElement = documentFactory.createElement("m:MaxTime", "urn:foo");
+        detailElement.setText("P5M");
+        fault.setDetail(detailElement);
+        Element faultElement = fault.toXmlElement();
+        faultElement.addNamespace(SoapConstants.XML_PREFIX, SoapConstants.XML_NS);
+
+        XPP3Reader reader = new XPP3Reader();
+        Document expected = reader.read(getClass().getResourceAsStream("simple-fault.xml"));
+
+        // Can't understand why we need 5 here, as the elements are really the same!
+        assertEquals(5, nodeComparator.compare(expected.getRootElement(), faultElement));
+    }
+}

soap-dtc-core/src/test/java/com/izforge/soapdtc/SoapMessageTest.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc;
+
+import junit.framework.TestCase;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentFactory;
+import org.dom4j.util.NodeComparator;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+public class SoapMessageTest extends TestCase
+{
+    private NodeComparator nodeComparator = new NodeComparator();
+
+    private DocumentFactory documentFactory = DocumentFactory.getInstance();
+
+    public void testCreateEnvelope() throws DocumentException, IOException, XmlPullParserException
+    {
+        SoapMessage message = new SoapMessage();
+        SoapMessage expectedMessage = SoapMessageUtils.readSoapMessageFromStream(getClass()
+                .getResourceAsStream("empty-soap-message.xml"), documentFactory);
+
+        assertEquals(0, nodeComparator.compare(expectedMessage, message));
+    }
+
+    public void testEnvelopeContent() throws DocumentException, IOException, XmlPullParserException
+    {
+        SoapMessageUtils.registerDocumentFactoryXPathNamespaceURIs(documentFactory, "t", "urn:mytransaction");
+        SoapMessageUtils.registerDocumentFactoryXPathNamespaceURIs(documentFactory, "s", "urn:sales");
+        SoapMessageUtils.registerDocumentFactoryXPathNamespaceURIs(documentFactory, "h", "urn:plop:da:plop");
+        SoapMessage message = SoapMessageUtils.readSoapMessageFromStream(getClass().
+                getResourceAsStream("simple-soap-message.xml"), documentFactory);
+
+        assertFalse(message.containsFault());
+        assertNull(message.getFaultElement());
+
+        assertEquals("123456789", message.getHeaderElement().valueOf("t:transaction/t:id/text()"));
+        assertEquals("Banana split", message.getBodyElement().valueOf("s:sales/s:product"));
+        assertEquals("1", message.getHeaderElement().valueOf("h:plop/@env:mustUnderstand"));
+
+        message = SoapMessageUtils.readSoapMessageFromStream(getClass().
+                getResourceAsStream("message-with-fault.xml"), documentFactory);
+        assertTrue(message.containsFault());
+    }
+}

soap-dtc-core/src/test/java/com/izforge/soapdtc/transport/AbstractHttpSoapTransportTest.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc.transport;
+
+import junit.framework.TestCase;
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.jetty.servlet.ServletHandler;
+import org.mortbay.jetty.servlet.ServletHolder;
+
+import javax.servlet.Servlet;
+
+/**
+ * Base test case class for testing Http requests via a custom servlet.
+ *
+ * @author Julien Ponge (julien.ponge@gmail.com)
+ */
+public abstract class AbstractHttpSoapTransportTest extends TestCase
+{
+    private Server server;
+    private Servlet servlet;
+    private ServletHandler servletHandler;
+
+    protected AbstractHttpSoapTransportTest(Servlet servlet)
+    {
+        this.servlet = servlet;
+
+        server = new Server();
+
+        SelectChannelConnector connector = new SelectChannelConnector();
+        connector.setPort(8085);
+        server.setConnectors(new Connector[]{connector});
+
+        servletHandler = new ServletHandler();
+        servletHandler.addServletWithMapping(new ServletHolder(servlet), "/dtc");
+        server.setHandler(servletHandler);
+    }
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        server.start();
+    }
+
+    @Override
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+        server.stop();
+    }
+}

soap-dtc-core/src/test/java/com/izforge/soapdtc/transport/DummyServlet.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc.transport;
+
+import com.izforge.soapdtc.SoapMessageTest;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Stupid servlet that echoes the request on POST, and replies the same simple SOAP message on GET.
+ *
+ * @author Julien Ponge (julien.ponge@gmail.com)
+ */
+public class DummyServlet extends HttpServlet
+{
+    @Override
+    protected void doPost(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
+    {
+        InputStream in = request.getInputStream();
+        OutputStream out = httpServletResponse.getOutputStream();
+        copy(in, out);
+    }
+
+    private void copy(InputStream in, OutputStream out) throws IOException
+    {
+        byte[] buffer = new byte[1024];
+        int nbytes = 0;
+        while ((nbytes = in.read(buffer, 0, 1024)) != -1)
+        {
+            out.write(buffer, 0, nbytes);
+        }
+    }
+
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
+    {
+        InputStream in = SoapMessageTest.class.getResourceAsStream("simple-soap-message.xml");
+        OutputStream out = httpServletResponse.getOutputStream();
+        copy(in, out);
+    }
+}

soap-dtc-core/src/test/java/com/izforge/soapdtc/transport/HttpSoapTransportWithDummyServletTest.java

+/*
+ * Copyright (c) 2006 Julien Ponge. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package com.izforge.soapdtc.transport;
+
+import com.izforge.soapdtc.SoapMessage;
+import com.izforge.soapdtc.SoapMessageTest;
+import com.izforge.soapdtc.SoapMessageUtils;
+import org.dom4j.DocumentException;
+import org.dom4j.util.NodeComparator;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+public class HttpSoapTransportWithDummyServletTest extends AbstractHttpSoapTransportTest
+{
+    private NodeComparator nodeComparator = new NodeComparator();
+
+    public HttpSoapTransportWithDummyServletTest()
+    {
+        super(new DummyServlet());
+    }
+
+    public void testSendReceive() throws DocumentException, IOException, XmlPullParserException, SoapTransportException
+    {
+        HttpSoapTransport soapTransport = new HttpSoapTransport();
+        SoapMessage message = SoapMessageUtils.readSoapMessageFromStream(SoapMessageTest.class
+                .getResourceAsStream("simple-soap-message.xml"));
+
+        SoapMessage response = soapTransport.sendReceive("http://localhost:8085/dtc", message, null);
+        assertEquals(0, nodeComparator.compare(message, response));
+    }
+
+    public void testAsyncSendReceive() throws DocumentException, IOException, XmlPullParserException, SoapTransportException, InterruptedException
+    {
+        HttpSoapTransport soapTransport = new HttpSoapTransport();
+        final