Author: midon
Date: Fri Jul 18 18:40:06 2008
New Revision: 678089

URL: http://svn.apache.org/viewvc?rev=678089&view=rev
Log:
ODE-310: better status code handling for 4xx & 5xx

Modified:
    
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
    
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
    
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
    
ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java

Modified: 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
URL: 
http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java?rev=678089&r1=678088&r2=678089&view=diff
==============================================================================
--- 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
 (original)
+++ 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
 Fri Jul 18 18:40:06 2008
@@ -39,6 +39,7 @@
 import org.apache.ode.bpel.iapi.ProcessConf;
 import org.apache.ode.bpel.iapi.Scheduler;
 import org.apache.ode.utils.DOMUtils;
+import static org.apache.ode.utils.http.StatusCode.*;
 import org.apache.ode.utils.wsdl.Messages;
 import org.apache.ode.utils.wsdl.WsdlUtils;
 import org.w3c.dom.Element;
@@ -276,10 +277,8 @@
                                 _2xx_success();
                             } else if (statusCode >= 300 && statusCode < 400) {
                                 _3xx_redirection();
-                            } else if (statusCode >= 400 && statusCode < 500) {
-                                _4xx_badRequest();
-                            } else if (statusCode >= 500 && statusCode < 600) {
-                                _5xx_serverError();
+                            } else if (statusCode >= 400 && statusCode < 600) {
+                                _4xx_5xx_error();
                             } else {
                                 unmanagedStatus();
                             }
@@ -310,20 +309,26 @@
                 errmsg = "[Service: " + serviceName + ", Port: " + portName + 
", Operation: " + operation.getName() + "] Status-Line: " + 
method.getStatusLine() + " for " + method.getURI();
                 log.warn(errmsg);
             }
-            PartnerRoleMessageExchange odeMex = (PartnerRoleMessageExchange) 
server.getEngine().getMessageExchange(mexId);
-            Object[] fault = httpMethodConverter.parseFault(odeMex, method);
-            Message response = (Message) fault[1];
-            QName faultName = (QName) fault[0];
-
-            // finally send the fault. We did it!
-            if (log.isWarnEnabled())
-                log.warn("[Service: " + serviceName + ", Port: " + portName + 
", Operation: " + operation.getName() + "] Fault response: faultName=" + 
faultName + " faultType=" + response.getType() + "\n" + 
DOMUtils.domToString(response.getMessage()));
-
-            odeMex.replyWithFault(faultName, response);
+            int status = method.getStatusCode();
+            if (status == _503_SERVICE_UNAVAILABLE
+                    || status == _504_GATEWAY_TIMEOUT) {
+                // reply with a failure, meaning the request might be repeated
+                replyWithFailure("HTTP Status-Line: " + method.getStatusLine() 
+ " for " + method.getURI());
+            } else {
+                // reply with a fault, meaning the request should not be 
repeated later
+                replyWithFault();
+            }
         }
 
-        private void _4xx_badRequest() throws Exception {
-            replyWithFailure("HTTP Status-Line: " + method.getStatusLine() + " 
for " + method.getURI());
+        private void _4xx_5xx_error() throws Exception {
+            int status = method.getStatusCode();
+            if(HttpHelper.isFaultOrFailure(status)>0){
+                // reply with a fault, meaning the request should not be 
repeated
+                replyWithFault();
+            } else {
+                // reply with a failure, meaning the request might be repeated 
later
+                replyWithFailure("HTTP Status-Line: " + method.getStatusLine() 
+ " for " + method.getURI());
+            }
         }
 
         private void _3xx_redirection() throws Exception {
@@ -355,6 +360,20 @@
             }
         }
 
+        void replyWithFault() {
+            PartnerRoleMessageExchange odeMex = (PartnerRoleMessageExchange) 
server.getEngine().getMessageExchange(mexId);
+            Object[] fault = httpMethodConverter.parseFault(odeMex, method);
+            Message response = (Message) fault[1];
+            QName faultName = (QName) fault[0];
+
+            // finally send the fault. We did it!
+            if (log.isWarnEnabled())
+                log.warn("[Service: " + serviceName + ", Port: " + portName + 
", Operation: " + operation.getName() + "] Fault response: faultName=" + 
faultName + " faultType=" + response.getType() + "\n" + 
DOMUtils.domToString(response.getMessage()));
+
+            odeMex.replyWithFault(faultName, response);
+        }
+
+
         void replyWithFailure(String errmsg) {
             replyWithFailure(errmsg, null);
         }
@@ -365,4 +384,4 @@
             odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg, 
HttpHelper.prepareDetailsElement(method));
         }
     }
-}
+}
\ No newline at end of file

Modified: 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
URL: 
http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java?rev=678089&r1=678088&r2=678089&view=diff
==============================================================================
--- 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
 (original)
+++ 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
 Fri Jul 18 18:40:06 2008
@@ -30,21 +30,18 @@
 import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
 import org.apache.commons.httpclient.methods.StringRequestEntity;
-import org.apache.commons.httpclient.methods.RequestEntity;
 import org.apache.commons.httpclient.params.HttpParams;
 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.utils.DOMUtils;
+import org.apache.ode.utils.http.HttpUtils;
+import static org.apache.ode.utils.http.StatusCode.*;
 import org.w3c.dom.Element;
 import org.w3c.dom.Document;
 
 import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.StringWriter;
-import java.io.PipedOutputStream;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -128,7 +125,7 @@
     public static Element prepareDetailsElement(HttpMethod method) {
         Header h = method.getResponseHeader("Content-Type");
         String receivedType = h != null ? h.getValue() : null;
-        boolean bodyIsXml = receivedType != null && 
HttpHelper.isXml(receivedType);
+        boolean bodyIsXml = receivedType != null && 
HttpUtils.isXml(receivedType);
 
 
         Document doc = DOMUtils.newDocument();
@@ -203,20 +200,6 @@
         return sb.toString();
     }
 
-    public static final String XML_MIME_TYPE_REGEX = 
"(text/xml)|(application/xml)|((.*)\\+xml)";
-    private static final String TEXT_MIME_TYPE_REGEX = "text/(?!xml$).*";
-    private static final Pattern XML_MIME_TYPE_PATTERN = 
Pattern.compile(XML_MIME_TYPE_REGEX);
-    private static final Pattern TEXT_MIME_TYPE_PATTERN = 
Pattern.compile(TEXT_MIME_TYPE_REGEX);
-
-    public static boolean isXml(String contentType) {
-        return XML_MIME_TYPE_PATTERN.matcher(contentType).matches();
-    }
-
-    public static boolean isText(String contentType) {
-        return TEXT_MIME_TYPE_PATTERN.matcher(contentType).matches();
-    }
-
-
     public static String requestToString(HttpMethod m) {
         StringBuilder sb = new StringBuilder(256);
         try {
@@ -278,4 +261,44 @@
         }
         return sb.toString();
     }
+
+    /**
+     *
+     * @param s, the status code to test, must be in [400, 600[
+     * @return 1 if fault, -1 if failure, 0 if undetermined
+     */
+    public static int isFaultOrFailure(int s) {
+        if (s < 400 || s >= 600) {
+            throw new IllegalArgumentException("Status-Code must be in 
interval [400;600[");
+        }
+        if (s == _500_INTERNAL_SERVER_ERROR
+                || s == _501_NOT_IMPLEMENTED
+                || s == _502_BAD_GATEWAY
+                || s == _505_HTTP_VERSION_NOT_SUPPORTED
+                || s == _400_BAD_REQUEST
+                || s == _402_PAYMENT_REQUIRED
+                || s == _403_FORBIDDEN
+                || s == _404_NOT_FOUND
+                || s == _405_METHOD_NOT_ALLOWED
+                || s == _406_NOT_ACCEPTABLE
+                || s == _407_PROXY_AUTHENTICATION_REQUIRED
+                || s == _409_CONFLICT
+                || s == _410_GONE
+                || s == _412_PRECONDITION_FAILED
+                || s == _413_REQUEST_TOO_LONG
+                || s == _414_REQUEST_URI_TOO_LONG
+                || s == _415_UNSUPPORTED_MEDIA_TYPE
+                || s == _411_LENGTH_REQUIRED
+                || s == _416_REQUESTED_RANGE_NOT_SATISFIABLE
+                || s == _417_EXPECTATION_FAILED) {
+            return 1;
+        } else if (s == _503_SERVICE_UNAVAILABLE
+                || s == _504_GATEWAY_TIMEOUT
+                || s == _401_UNAUTHORIZED
+                || s == _408_REQUEST_TIMEOUT) {
+            return -1;
+        } else {
+            return 0;
+        }
+    }
 }

Modified: 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
URL: 
http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java?rev=678089&r1=678088&r2=678089&view=diff
==============================================================================
--- 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
 (original)
+++ 
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
 Fri Jul 18 18:40:06 2008
@@ -39,6 +39,9 @@
 import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
 import org.apache.ode.utils.DOMUtils;
 import org.apache.ode.utils.Namespaces;
+import org.apache.ode.utils.http.HttpUtils;
+import static org.apache.ode.utils.http.HttpUtils.bodyAllowed;
+import static org.apache.ode.utils.http.StatusCode.*;
 import org.apache.ode.utils.wsdl.Messages;
 import org.apache.ode.utils.wsdl.WsdlUtils;
 import org.w3c.dom.Document;
@@ -194,7 +197,7 @@
                     String errMsg = "XML Types are not supported. Parts must 
use elements.";
                     if (log.isErrorEnabled()) log.error(errMsg);
                     throw new RuntimeException(errMsg);
-                } else if (HttpHelper.isXml(contentType)) {
+                } else if (HttpUtils.isXml(contentType)) {
                     if (log.isDebugEnabled()) log.debug("Content-Type [" + 
contentType + "] equivalent to 'text/xml'");
                     // stringify the first element
                     String xmlString = 
DOMUtils.domToString(DOMUtils.getFirstChildElement(partValue));
@@ -431,12 +434,12 @@
 
         // 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();
+        int status = method.getStatusCode();
 
-        boolean xmlExpected = outputContent != null && 
HttpHelper.isXml(outputContent.getType());
+        boolean xmlExpected = outputContent != null && 
HttpUtils.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;
+        boolean isBodyMandatory = isBodyExpected && bodyAllowed(status) && 
status != _202_ACCEPTED;
         final String body;
         try {
             body = method.getResponseBodyAsString();
@@ -459,7 +462,7 @@
                     Header h = method.getResponseHeader("Content-Type");
                     String receivedType = h != null ? h.getValue() : null;
                     boolean contentTypeSet = receivedType != null;
-                    boolean xmlReceived = contentTypeSet && 
HttpHelper.isXml(receivedType);
+                    boolean xmlReceived = contentTypeSet && 
HttpUtils.isXml(receivedType);
 
                     // a few checks
                     if (!contentTypeSet) {
@@ -506,7 +509,7 @@
             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)) {
+        } else if (receivedType != null && !HttpUtils.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 {
 

Modified: 
ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java
URL: 
http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java?rev=678089&r1=678088&r2=678089&view=diff
==============================================================================
--- 
ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java
 (original)
+++ 
ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java
 Fri Jul 18 18:40:06 2008
@@ -20,8 +20,7 @@
 package org.apache.ode.axis2.httpbinding;
 
 import junit.framework.TestCase;
-import org.apache.ode.utils.DOMUtils;
-import org.w3c.dom.Document;
+import org.apache.ode.utils.http.HttpUtils;
 
 /**
  *
@@ -51,26 +50,26 @@
     public void testIsXml() {
 
         for (String s : IS_XML) {
-            assertTrue(s+" is an xml type", HttpHelper.isXml(s));
+            assertTrue(s+" is an xml type", HttpUtils.isXml(s));
         }
         for (String s : IS_TEXT) {
-            assertFalse(s+" is not an xml type", HttpHelper.isXml(s));
+            assertFalse(s+" is not an xml type", HttpUtils.isXml(s));
         }
         for (String s : IS_IMAGE) {
-            assertFalse(s+" is not an xml type", HttpHelper.isXml(s));
+            assertFalse(s+" is not an xml type", HttpUtils.isXml(s));
         }
 
     }
 
     public void testIsText() {
         for (String s : IS_TEXT) {
-            assertTrue(s+" is a text type", HttpHelper.isText(s));
+            assertTrue(s+" is a text type", HttpUtils.isText(s));
         }
         for (String s : IS_XML) {
-            assertFalse(s+" is not a text type", HttpHelper.isText(s));
+            assertFalse(s+" is not a text type", HttpUtils.isText(s));
         }
         for (String s : IS_IMAGE) {
-            assertFalse(s+" is not a text type", HttpHelper.isXml(s));
+            assertFalse(s+" is not a text type", HttpUtils.isXml(s));
         }
     }
 }


Reply via email to