You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by mi...@apache.org on 2008/07/18 20:05:21 UTC

svn commit: r677984 - in /ode/trunk/axis2/src: main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java

Author: midon
Date: Fri Jul 18 11:05:20 2008
New Revision: 677984

URL: http://svn.apache.org/viewvc?rev=677984&view=rev
Log:
move stuff around to make code more readable

Modified:
    ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
    ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
    ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java

Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java?rev=677984&r1=677983&r2=677984&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java Fri Jul 18 11:05:20 2008
@@ -19,13 +19,11 @@
 
 package org.apache.ode.axis2.httpbinding;
 
-import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpMethod;
 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
 import org.apache.commons.httpclient.URIException;
 import org.apache.commons.httpclient.params.HttpParams;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ode.axis2.ExternalService;
@@ -40,20 +38,15 @@
 import org.apache.ode.il.epr.EndpointFactory;
 import org.apache.ode.il.epr.WSAEndpoint;
 import org.apache.ode.utils.DOMUtils;
-import org.apache.ode.utils.Namespaces;
 import org.apache.ode.utils.wsdl.Messages;
 import org.apache.ode.utils.wsdl.WsdlUtils;
 import org.w3c.dom.Element;
 
 import javax.wsdl.Binding;
-import javax.wsdl.BindingOperation;
 import javax.wsdl.Definition;
-import javax.wsdl.Fault;
 import javax.wsdl.Operation;
-import javax.wsdl.Part;
 import javax.wsdl.Port;
 import javax.wsdl.Service;
-import javax.wsdl.extensions.mime.MIMEContent;
 import javax.xml.namespace.QName;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
@@ -73,7 +66,6 @@
 
     protected BpelServer server;
     protected ProcessConf pconf;
-    private String targetNamespace;
     protected QName serviceName;
     protected String portName;
 
@@ -83,14 +75,14 @@
     protected Binding portBinding;
 
     public HttpExternalService(ProcessConf pconf, QName serviceName, String portName, BpelServer server) {
-        if(log.isDebugEnabled()) log.debug("new HTTP External service, service name=["+serviceName+"]; port name=["+portName+"]");
+        if (log.isDebugEnabled())
+            log.debug("new HTTP External service, service name=[" + serviceName + "]; port name=[" + portName + "]");
         this.portName = portName;
         this.serviceName = serviceName;
         this.server = server;
         this.pconf = pconf;
 
         Definition definition = pconf.getDefinitionForService(serviceName);
-        targetNamespace = definition.getTargetNamespace();
         Service serviceDef = definition.getService(serviceName);
         if (serviceDef == null)
             throw new IllegalArgumentException(msgs.msgServiceDefinitionNotFound(serviceName));
@@ -114,7 +106,7 @@
             throw new IllegalArgumentException(msgs.msgPortDefinitionNotFound(serviceName, portName));
         endpointReference = EndpointFactory.convertToWSA(ODEService.createServiceRef(eprElmt));
 
-        httpMethodConverter = new HttpMethodConverter(portBinding);
+        httpMethodConverter = new HttpMethodConverter(definition, serviceName, portName);
         connections = new MultiThreadedHttpConnectionManager();
     }
 
@@ -169,15 +161,15 @@
             }
         } catch (UnsupportedEncodingException e) {
             String errmsg = "The returned HTTP encoding isn't supported " + odeMex;
-            log.error("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] "+errmsg, e);
+            log.error("[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] " + errmsg, e);
             odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, null);
         } catch (URIException e) {
             String errmsg = "Invalid URI " + odeMex;
-            log.error("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] "+errmsg, e);
+            log.error("[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] " + errmsg, e);
             odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, null);
         } catch (Exception e) {
             String errmsg = "Unknown HTTP call error for ODE mex " + odeMex;
-            log.error("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] "+errmsg, e);
+            log.error("[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] " + errmsg, e);
             odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, null);
         }
 
@@ -199,7 +191,7 @@
             try {
                 // simply execute the http method
                 HttpClient client = new HttpClient(connections);
-                if (log.isDebugEnabled()){
+                if (log.isDebugEnabled()) {
                     log.debug("Executing http request : " + method.getName() + " " + method.getURI());
                     log.debug(HttpHelper.requestToString(method));
                 }
@@ -218,10 +210,10 @@
                 // Something happened, recording the failure
                 try {
                     String errmsg = "Unable to execute HTTP request : " + e.getMessage();
-                    log.error("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] "+errmsg, e);
+                    log.error("[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] " + errmsg, e);
                     odeMex.replyWithFailure(MessageExchange.FailureType.COMMUNICATION_ERROR, errmsg, null);
                 } catch (Exception e1) {
-                    String errmsg = "[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] Error executing reply transaction; reply will be lost.";
+                    String errmsg = "[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] Error executing reply transaction; reply will be lost.";
                     log.error(errmsg, e);
                 }
             } finally {
@@ -241,7 +233,7 @@
                         log.debug("OneWay HTTP Request, Status-Line: " + method.getStatusLine() + " for " + method.getURI());
                 }
             } catch (URIException e) {
-                String errmsg = "[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] Exception occured while processing the HTTP response of a one-way request: " + e.getMessage();
+                String errmsg = "[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] Exception occured while processing the HTTP response of a one-way request: " + e.getMessage();
                 log.error(errmsg, e);
             }
         }
@@ -267,13 +259,11 @@
                     unmanagedStatus();
                 }
             } catch (Exception e) {
-                String errmsg = "Exception occured while processing the HTTP response of a two-way request: " + e.getMessage();
-                log.error("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] "+errmsg, e);
-                odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, null);
+                replyWithFailure("Exception occured while processing the HTTP response of a two-way request. mexId= " + odeMex.getMessageExchangeId(), e);
             }
         }
 
-        private void unmanagedStatus() throws IOException {
+        private void unmanagedStatus() throws Exception {
             replyWithFailure("Unmanaged Status Code! Status-Line: " + method.getStatusLine() + " for " + method.getURI());
         }
 
@@ -282,183 +272,43 @@
          *
          * @throws IOException
          */
-        private void _5xx_serverError() throws IOException {
+        private void _5xx_serverError() throws Exception {
             String errmsg;
             if (log.isWarnEnabled()) {
-                errmsg = "[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] Status-Line: " + method.getStatusLine() + " for " + method.getURI();
+                errmsg = "[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] Status-Line: " + method.getStatusLine() + " for " + method.getURI();
                 log.warn(errmsg);
             }
+            Object[] fault = httpMethodConverter.parseFault(odeMex, method);
+            Message response = (Message) fault[1];
+            QName faultName = (QName) fault[0];
 
-            Operation opDef = odeMex.getOperation();
-            BindingOperation opBinding = portBinding.getBindingOperation(opDef.getName(), opDef.getInput().getName(), opDef.getOutput().getName());
-
-            final String body;
-            try {
-                body = method.getResponseBodyAsString();
-            } catch (IOException e) {
-                errmsg = "[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] Unable to get the request body : " + e.getMessage();
-                log.error(errmsg, e);
-                odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, HttpHelper.prepareDetailsElement(method));
-                return;
-            }
-            Header h = method.getResponseHeader("Content-Type");
-            String receivedType = h != null ? h.getValue() : null;
-
-            if (opDef.getFaults().isEmpty()) {
-                replyWithFailure("Operation [" + opDef.getName() + "] has no fault. This 500 error will be considered as a failure.");
-            } else if (opBinding.getBindingFaults().isEmpty()) {
-                replyWithFailure("No fault binding. This 500 error will be considered as a failure.");
-            } else if (StringUtils.isEmpty(body)) {
-                replyWithFailure("No body in the response. This 500 error will be considered as a failure.");
-            } else if (receivedType != null && !HttpHelper.isXml(receivedType)) {
-                replyWithFailure("Response Content-Type [" + receivedType + "] does not describe XML entities. Faults must be XML. This 500 error will be considered as a failure.");
-            } else {
-
-                if (receivedType == null) {
-                    if (log.isWarnEnabled())
-                        log.warn("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] Received Response with a body but no 'Content-Type' header! Will try to parse nevertheless.");
-                }
-
-                // try to parse body
-                final Element bodyElement;
-                try {
-                    bodyElement = DOMUtils.stringToDOM(body);
-                } catch (Exception e) {
-                    replyWithFailure("Unable to parse the response body as xml. This 500 error will be considered as a failure.");
-                    return;
-                }
-
-                // Guess which fault it is
-                QName bodyName = new QName(bodyElement.getNamespaceURI(), bodyElement.getNodeName());
-                Fault faultDef = WsdlUtils.inferFault(opDef, bodyName);
-
-                if (faultDef == null) {
-                    replyWithFailure("Unknown Fault Type [" + bodyName + "] This 500 error will be considered as a failure.");
-                } else if (!WsdlUtils.isOdeFault(opBinding.getBindingFault(faultDef.getName()))) {
-                    // is this fault bound with ODE extension?
-                    replyWithFailure("Fault [" + bodyName + "] is not bound with " + new QName(Namespaces.ODE_HTTP_EXTENSION_NS, "fault") + ". This 500 error will be considered as a failure.");
-                } else {
-                    // a fault has only one part
-                    Part partDef = (Part) faultDef.getMessage().getParts().values().iterator().next();
-
-                    QName faultName = new QName(targetNamespace, faultDef.getName());
-                    QName faultType = faultDef.getMessage().getQName();
-
-                    // create the ODE Message now that we know the fault
-                    Message response = odeMex.createMessage(faultType);
+            // finally send the fault. We did it!
+            if (log.isWarnEnabled())
+                log.warn("[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] Fault response: faultName=" + faultName + " faultType=" + response.getType() + "\n" + DOMUtils.domToString(response.getMessage()));
 
-                    // build the element to be sent back
-                    Element partElement = httpMethodConverter.createPartElement(partDef, bodyElement);
-                    response.setPart(partDef.getName(), partElement);
-
-                    // extract and set headers
-                    httpMethodConverter.extractHttpResponseHeaders(response, method, faultDef.getMessage(), opBinding.getBindingOutput());
-
-                    // finally send the fault. We did it!
-                    if (log.isWarnEnabled())
-                        log.warn("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] Fault response: faultName=" + faultName + " faultType=" + faultType + "\n" + DOMUtils.domToString(response.getMessage()));
-                    odeMex.replyWithFault(faultName, response);
-                }
-
-            }
+            odeMex.replyWithFault(faultName, response);
         }
 
-        private void _4xx_badRequest() throws IOException {
+        private void _4xx_badRequest() throws Exception {
             replyWithFailure("HTTP Status-Line: " + method.getStatusLine() + " for " + method.getURI());
         }
 
-        private void _3xx_redirection() throws IOException {
+        private void _3xx_redirection() throws Exception {
             // redirections should be handled transparently by http-client
             replyWithFailure("Redirections disabled! HTTP Status-Line: " + method.getStatusLine() + " for " + method.getURI());
         }
 
-        private void _2xx_success() throws IOException {
+        private void _2xx_success() throws Exception {
             if (log.isDebugEnabled())
-                log.debug("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] HTTP Status-Line: " + method.getStatusLine() + " for " + method.getURI());
+                log.debug("[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] HTTP Status-Line: " + method.getStatusLine() + " for " + method.getURI());
             if (log.isDebugEnabled()) log.debug("Received response for MEX " + odeMex);
 
             Operation opDef = odeMex.getOperation();
-            BindingOperation opBinding = portBinding.getBindingOperation(opDef.getName(), opDef.getInput().getName(), opDef.getOutput().getName());
-            javax.wsdl.Message outputMessage = odeMex.getOperation().getOutput().getMessage();
-
             // this is the message to populate and send to ODE
-            Message odeResponse = odeMex.createMessage(outputMessage.getQName());
-
-            /* process headers */
-            httpMethodConverter.extractHttpResponseHeaders(odeResponse, method, outputMessage, opBinding.getBindingOutput());
-
-            /* process the body if any */
-
-            // assumption is made that a response may have at most one body. HttpBindingValidator checks this.
-            MIMEContent outputContent = WsdlUtils.getMimeContent(opBinding.getBindingOutput().getExtensibilityElements());
-            int statusCode = method.getStatusCode();
-
-            boolean xmlExpected = outputContent != null && HttpHelper.isXml(outputContent.getType());
-            // '202/Accepted' and '204/No Content' status codes explicitly state that there is no body, so we should not fail even if a part is bound to the body response
-            boolean isBodyExpected = outputContent != null;
-            boolean isBodyMandatory = isBodyExpected && statusCode!=204 && statusCode!=202;
-
-
-            final String body;
-            try {
-                body = method.getResponseBodyAsString();
-            } catch (IOException e) {
-                String errmsg = "[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] Unable to get the request body : " + e.getMessage();
-                log.error(errmsg, e);
-                odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, HttpHelper.prepareDetailsElement(method));
-                return;
-            }
+            QName outputMsgName = odeMex.getOperation().getOutput().getMessage().getQName();
+            Message odeResponse = odeMex.createMessage(outputMsgName);
 
-            final boolean emptyBody = StringUtils.isEmpty(body);
-            if (emptyBody) {
-                if (isBodyMandatory) {
-                    replyWithFailure("Response body is mandatory but missing! Msg Id=" + odeMex.getMessageExchangeId());
-                    return;
-                }
-            } else {
-                if (isBodyExpected) {
-                    Part partDef = outputMessage.getPart(outputContent.getPart());
-                    Element partElement;
-
-                    if (xmlExpected) {
-
-                        Header h = method.getResponseHeader("Content-Type");
-                        String receivedType = h != null ? h.getValue() : null;
-                        boolean contentTypeSet = receivedType != null;
-                        boolean xmlReceived = contentTypeSet && HttpHelper.isXml(receivedType);
-
-                        // a few checks
-                        if (!contentTypeSet) {
-                            if (log.isDebugEnabled())
-                                log.debug("Received Response with a body but no 'Content-Type' header!");
-                        } else if (!xmlReceived) {
-                            if (log.isDebugEnabled())
-                                log.debug("Xml type was expected but non-xml type received! Expected Content-Type=" + outputContent.getType() + " Received Content-Type=" + receivedType);
-                        }
-
-                        // parse the body and create the message part
-                        try {
-                            Element bodyElement = DOMUtils.stringToDOM(body);
-                            partElement = httpMethodConverter.createPartElement(partDef, bodyElement);
-                        } catch (Exception e) {
-                            String errmsg = "[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] Unable to parse the response body: " + e.getMessage();
-                            log.error(errmsg, e);
-                            odeMex.replyWithFailure(MessageExchange.FailureType.FORMAT_ERROR, errmsg, HttpHelper.prepareDetailsElement(method));
-                            return;
-                        }
-                    } else {
-                        // if not xml, process it as text
-                        partElement = httpMethodConverter.createPartElement(partDef, body);
-                    }
-
-                    // set the part
-                    odeResponse.setPart(partDef.getName(), partElement);
-
-                } else {
-                    // the body was not expected but we don't know how to deal with it
-                    if (log.isDebugEnabled()) log.debug("Body received but not mapped to any part! Body=\n" + body);
-                }
-            }
+            httpMethodConverter.parseHttpResponse(odeResponse, method, opDef);
 
             // finally send the message
             try {
@@ -466,12 +316,16 @@
                     log.info("Response: " + (odeResponse.getMessage() != null ? DOMUtils.domToString(odeResponse.getMessage()) : "empty"));
                 odeMex.reply(odeResponse);
             } catch (Exception ex) {
-                replyWithFailure("Unable to process response: " + ex.getMessage());
-            }
+                replyWithFailure("Unable to process response: " + ex.getMessage(), ex);
+            }            
         }
 
         void replyWithFailure(String errmsg) {
-            log.error("[Service: "+serviceName+", Port: "+portName+", Operation: "+odeMex.getOperationName()+"] "+errmsg);
+            replyWithFailure(errmsg, null);
+        }
+
+        void replyWithFailure(String errmsg, Throwable t) {
+            log.error("[Service: " + serviceName + ", Port: " + portName + ", Operation: " + odeMex.getOperationName() + "] " + errmsg, t);
             odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, HttpHelper.prepareDetailsElement(method));
         }
     }

Modified: ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java?rev=677984&r1=677983&r2=677984&view=diff
==============================================================================
--- ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java (original)
+++ ode/trunk/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java Fri Jul 18 11:05:20 2008
@@ -19,8 +19,8 @@
 
 package org.apache.ode.axis2.httpbinding;
 
-import org.apache.commons.httpclient.HttpMethod;
 import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpMethod;
 import org.apache.commons.httpclient.methods.DeleteMethod;
 import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
 import org.apache.commons.httpclient.methods.GetMethod;
@@ -29,51 +29,61 @@
 import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.commons.httpclient.methods.StringRequestEntity;
 import org.apache.commons.httpclient.params.HttpParams;
+import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.commons.lang.StringUtils;
 import org.apache.ode.axis2.Properties;
 import org.apache.ode.axis2.util.URLEncodedTransformer;
 import org.apache.ode.axis2.util.UrlReplacementTransformer;
 import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
+import org.apache.ode.il.epr.MutableEndpoint;
 import org.apache.ode.utils.DOMUtils;
 import org.apache.ode.utils.Namespaces;
 import org.apache.ode.utils.wsdl.Messages;
 import org.apache.ode.utils.wsdl.WsdlUtils;
-import org.apache.ode.il.epr.MutableEndpoint;
-import org.w3c.dom.Element;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
 
 import javax.wsdl.Binding;
 import javax.wsdl.BindingInput;
 import javax.wsdl.BindingOperation;
+import javax.wsdl.BindingOutput;
 import javax.wsdl.Message;
 import javax.wsdl.Operation;
 import javax.wsdl.Part;
-import javax.wsdl.BindingOutput;
+import javax.wsdl.Definition;
+import javax.wsdl.Fault;
+import javax.wsdl.extensions.UnknownExtensibilityElement;
 import javax.wsdl.extensions.http.HTTPOperation;
 import javax.wsdl.extensions.mime.MIMEContent;
-import javax.wsdl.extensions.UnknownExtensibilityElement;
 import javax.xml.namespace.QName;
+import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Collection;
 
 public class HttpMethodConverter {
 
-    private static final String CONTENT_TYPE_TEXT_XML = "text/xml";
     private static final Log log = LogFactory.getLog(HttpMethodConverter.class);
 
     protected static final Messages msgs = Messages.getMessages(Messages.class);
+    protected Definition definition;
     protected Binding binding;
+    protected QName serviceName;
+    protected String portName;
 
-    public HttpMethodConverter(Binding binding) {
-        this.binding = binding;
+    public HttpMethodConverter(Definition definition, QName serviceName, String portName) {
+        this.definition = definition;
+        this.binding = definition.getService(serviceName).getPort(portName).getBinding();
+        this.serviceName = serviceName;
+        this.portName = portName;
     }
 
+
     public HttpMethod createHttpRequest(PartnerRoleMessageExchange odeMex, HttpParams params) throws UnsupportedEncodingException {
         Operation operation = odeMex.getOperation();
         BindingOperation bindingOperation = binding.getBindingOperation(operation.getName(), operation.getInput().getName(), operation.getOutput().getName());
@@ -369,11 +379,13 @@
      *
      * @param odeMessage
      * @param method
-     * @param messageDef
-     * @param bindingOutput
+     * @param operationDef
      */
-    public void extractHttpResponseHeaders(org.apache.ode.bpel.iapi.Message odeMessage, HttpMethod method, Message messageDef, BindingOutput bindingOutput) {
-        Collection<UnknownExtensibilityElement> headerBindings = WsdlUtils.getHttpHeaders(bindingOutput.getExtensibilityElements());
+    public void extractHttpResponseHeaders(org.apache.ode.bpel.iapi.Message odeMessage, HttpMethod method, Operation operationDef) {
+        Message messageDef = operationDef.getOutput().getMessage();
+
+        BindingOutput outputBinding = binding.getBindingOperation(operationDef.getName(), operationDef.getInput().getName(), operationDef.getOutput().getName()).getBindingOutput();
+        Collection<UnknownExtensibilityElement> headerBindings = WsdlUtils.getHttpHeaders(outputBinding.getExtensibilityElements());
 
         // iterate through the list of header bindings
         // and set the message parts accordingly
@@ -410,6 +422,136 @@
         odeMessage.setHeaderPart("Status-Line", HttpHelper.statusLineToElement(method.getStatusLine()));
     }
 
+    public void parseHttpResponse(org.apache.ode.bpel.iapi.Message odeResponse, HttpMethod method, Operation opDef) throws Exception {
+        BindingOperation opBinding = binding.getBindingOperation(opDef.getName(), opDef.getInput().getName(), opDef.getOutput().getName());
+        /* process headers */
+        extractHttpResponseHeaders(odeResponse, method, opDef);
+
+        /* process the body if any */
+
+        // assumption is made that a response may have at most one body. HttpBindingValidator checks this.
+        MIMEContent outputContent = WsdlUtils.getMimeContent(opBinding.getBindingOutput().getExtensibilityElements());
+        int statusCode = method.getStatusCode();
+
+        boolean xmlExpected = outputContent != null && HttpHelper.isXml(outputContent.getType());
+        // '202/Accepted' and '204/No Content' status codes explicitly state that there is no body, so we should not fail even if a part is bound to the body response
+        boolean isBodyExpected = outputContent != null;
+        boolean isBodyMandatory = isBodyExpected && statusCode != 204 && statusCode != 202;
+        final String body;
+        try {
+            body = method.getResponseBodyAsString();
+        } catch (IOException e) {
+            throw new RuntimeException("Unable to get the request body : " + e.getMessage());
+        }
+
+        final boolean emptyBody = StringUtils.isEmpty(body);
+        if (emptyBody) {
+            if (isBodyMandatory) {
+                throw new RuntimeException("Response body is mandatory but missing!");
+            }
+        } else {
+            if (isBodyExpected) {
+                Part partDef = opDef.getOutput().getMessage().getPart(outputContent.getPart());
+                Element partElement;
+
+                if (xmlExpected) {
+
+                    Header h = method.getResponseHeader("Content-Type");
+                    String receivedType = h != null ? h.getValue() : null;
+                    boolean contentTypeSet = receivedType != null;
+                    boolean xmlReceived = contentTypeSet && HttpHelper.isXml(receivedType);
+
+                    // a few checks
+                    if (!contentTypeSet) {
+                        if (log.isDebugEnabled())
+                            log.debug("Received Response with a body but no 'Content-Type' header!");
+                    } else if (!xmlReceived) {
+                        if (log.isDebugEnabled())
+                            log.debug("Xml type was expected but non-xml type received! Expected Content-Type=" + outputContent.getType() + " Received Content-Type=" + receivedType);
+                    }
+
+                    // parse the body and create the message part
+                    Element bodyElement = DOMUtils.stringToDOM(body);
+                    partElement = createPartElement(partDef, bodyElement);
+                } else {
+                    // if not xml, process it as text
+                    partElement = createPartElement(partDef, body);
+                }
+
+                // set the part
+                odeResponse.setPart(partDef.getName(), partElement);
+
+            } else {
+                // the body was not expected but we don't know how to deal with it
+                if (log.isDebugEnabled()) log.debug("Body received but not mapped to any part! Body=\n" + body);
+            }
+        }
+    }
+
+    public Object[] parseFault(PartnerRoleMessageExchange odeMex, HttpMethod method) {
+        Operation opDef = odeMex.getOperation();
+        BindingOperation opBinding = binding.getBindingOperation(opDef.getName(), opDef.getInput().getName(), opDef.getOutput().getName());
+
+        final String body;
+        try {
+            body = method.getResponseBodyAsString();
+        } catch (IOException e) {
+            throw new RuntimeException("Unable to get the request body : " + e.getMessage(), e);
+        }
+        Header h = method.getResponseHeader("Content-Type");
+        String receivedType = h != null ? h.getValue() : null;
+        if (opDef.getFaults().isEmpty()) {
+            throw new RuntimeException("Operation [" + opDef.getName() + "] has no fault. This " + method.getStatusCode() + " error will be considered as a failure.");
+        } else if (opBinding.getBindingFaults().isEmpty()) {
+            throw new RuntimeException("No fault binding. This " + method.getStatusCode() + " error will be considered as a failure.");
+        } else if (StringUtils.isEmpty(body)) {
+            throw new RuntimeException("No body in the response. This " + method.getStatusCode() + " error will be considered as a failure.");
+        } else if (receivedType != null && !HttpHelper.isXml(receivedType)) {
+            throw new RuntimeException("Response Content-Type [" + receivedType + "] does not describe XML entities. Faults must be XML. This " + method.getStatusCode() + " error will be considered as a failure.");
+        } else {
+
+            if (receivedType == null) {
+                if (log.isWarnEnabled())
+                    log.warn("[Service: " + serviceName + ", Port: " + portName + ", Operation: " + opDef.getName() + "] Received Response with a body but no 'Content-Type' header! Will try to parse nevertheless.");
+            }
+
+            // try to parse body
+            final Element bodyElement;
+            try {
+                bodyElement = DOMUtils.stringToDOM(body);
+            } catch (Exception e) {
+                throw new RuntimeException("Unable to parse the response body as xml. This " + method.getStatusCode() + " error will be considered as a failure.", e);
+            }
+
+            // Guess which fault it is
+            QName bodyName = new QName(bodyElement.getNamespaceURI(), bodyElement.getNodeName());
+            Fault faultDef = WsdlUtils.inferFault(opDef, bodyName);
+
+            if (faultDef == null) {
+                throw new RuntimeException("Unknown Fault Type [" + bodyName + "] This " + method.getStatusCode() + " error will be considered as a failure.");
+            } else if (!WsdlUtils.isOdeFault(opBinding.getBindingFault(faultDef.getName()))) {
+                // is this fault bound with ODE extension?
+                throw new RuntimeException("Fault [" + bodyName + "] is not bound with " + new QName(Namespaces.ODE_HTTP_EXTENSION_NS, "fault") + ". This " + method.getStatusCode() + " error will be considered as a failure.");
+            } else {
+                // a fault has only one part
+                Part partDef = (Part) faultDef.getMessage().getParts().values().iterator().next();
+
+                QName faultName = new QName(definition.getTargetNamespace(), faultDef.getName());
+                QName faultType = faultDef.getMessage().getQName();
+
+                // create the ODE Message now that we know the fault
+                org.apache.ode.bpel.iapi.Message response = odeMex.createMessage(faultType);
+
+                // build the element to be sent back
+                Element partElement = createPartElement(partDef, bodyElement);
+                response.setPart(partDef.getName(), partElement);
+
+                // extract and set headers
+                extractHttpResponseHeaders(response, method, opDef);
+                return new Object[]{faultName, response};
+            }
+        }
+    }
 
 }
 

Modified: ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java
URL: http://svn.apache.org/viewvc/ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java?rev=677984&r1=677983&r2=677984&view=diff
==============================================================================
--- ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java (original)
+++ ode/trunk/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpMethodConverterTest.java Fri Jul 18 11:05:20 2008
@@ -72,12 +72,12 @@
         Service deliciousService = definition.getService(new QName("http://ode/bpel/unit-test.wsdl", "DeliciousService"));
         deliciousPort = deliciousService.getPort("TagHttpPort");
         deliciousBinding = deliciousPort.getBinding();
-        deliciousBuilder = new HttpMethodConverter(deliciousBinding);
+        deliciousBuilder = new HttpMethodConverter(definition, deliciousService.getQName(), deliciousPort.getName());
 
         Service dummyService = definition.getService(new QName("http://ode/bpel/unit-test.wsdl", "DummyService"));
         dummyPort = dummyService.getPort("DummyServiceHttpport");
         dummyBinding = dummyPort.getBinding();
-        dummyBuilder = new HttpMethodConverter(dummyBinding);
+        dummyBuilder = new HttpMethodConverter(definition, dummyService.getQName(), dummyPort.getName());
 
     }