Repository: jclouds
Updated Branches:
  refs/heads/master 59a88ff89 -> 72f2652dc


Properly handler ProfitBricks service errors


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/72f2652d
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/72f2652d
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/72f2652d

Branch: refs/heads/master
Commit: 72f2652dca861a743103a8f6d8a3fe0cfdf5b00d
Parents: 59a88ff
Author: Ignasi Barrera <[email protected]>
Authored: Thu Feb 25 12:23:10 2016 +0100
Committer: Ignasi Barrera <[email protected]>
Committed: Wed Mar 2 14:51:29 2016 +0100

----------------------------------------------------------------------
 .../ProfitBricksComputeServiceAdapter.java      | 13 ++-
 .../profitbricks/domain/ServiceFault.java       | 89 +++++++++++---------
 .../handlers/ProfitBricksHttpErrorHandler.java  | 14 ++-
 ...usFromPayloadHttpCommandExecutorService.java | 11 ++-
 .../parser/ServiceFaultResponseHandler.java     | 27 ++++--
 .../parser/ServiceFaultResponseHandlerTest.java | 32 +++++--
 .../src/test/resources/fault-500.xml            |  9 ++
 7 files changed, 136 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/72f2652d/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
index fe02c41..2b4df3d 100644
--- 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
+++ 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/compute/ProfitBricksComputeServiceAdapter.java
@@ -302,11 +302,16 @@ public class ProfitBricksComputeServiceAdapter implements 
ComputeServiceAdapter<
    public Provisionable getImage(String id) {
       // try search images
       logger.trace("<< searching for image with id=%s", id);
-      Image image = api.imageApi().getImage(id);
-      if (image != null) {
-         logger.trace(">> found image [%s].", image.name());
-         return image;
+      try {
+         Image image = api.imageApi().getImage(id);
+         if (image != null) {
+            logger.trace(">> found image [%s].", image.name());
+            return image;
+         }
+      } catch (Exception ex) {
+         logger.warn(ex, ">> unexpected error getting image. Trying to get as 
a snapshot...");
       }
+      
       // try search snapshots
       logger.trace("<< not found from images. searching for snapshot with 
id=%s", id);
       Snapshot snapshot = api.snapshotApi().getSnapshot(id);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/72f2652d/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/ServiceFault.java
----------------------------------------------------------------------
diff --git 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/ServiceFault.java
 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/ServiceFault.java
index bcf9774..d429981 100644
--- 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/ServiceFault.java
+++ 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/domain/ServiceFault.java
@@ -16,55 +16,68 @@
  */
 package org.jclouds.profitbricks.domain;
 
+import org.jclouds.javax.annotation.Nullable;
+
 import com.google.auto.value.AutoValue;
 import com.google.common.base.Enums;
 
 @AutoValue
 public abstract class ServiceFault {
 
-   public enum FaultCode {
-
-      BAD_REQUEST,
-      UNEXPECTED,
-      UNAUTHORIZED,
-      RESOURCE_NOT_FOUND,
-      RESOURCE_DELETED,
-      PROVISIONING_IN_PROCESS,
-      PROVISIONING_NO_CHANGES,
-      OVER_LIMIT_SETTING,
-      SERVER_EXCEED_CAPACITY,
-      SERVICE_UNAVAILABLE,
-      UNRECOGNIZED;
-
-      public static FaultCode fromValue(String v) {
-         return Enums.getIfPresent(FaultCode.class, v).or(UNRECOGNIZED);
-      }
-   }
-
-   public abstract FaultCode faultCode();
-
-   public abstract int httpCode();
-
-   public abstract String message();
-
-   public abstract int requestId();
-
+   public abstract String faultCode();
+   public abstract String faultString();
+   @Nullable public abstract Details details();
+   
    public static Builder builder() {
       return new AutoValue_ServiceFault.Builder();
    }
-
+   
    @AutoValue.Builder
    public abstract static class Builder {
-
-      public abstract Builder faultCode(FaultCode faultCode);
-
-      public abstract Builder httpCode(int httpCode);
-
-      public abstract Builder message(String message);
-
-      public abstract Builder requestId(int requestId);
-
+      public abstract Builder faultCode(String faultCode);
+      public abstract Builder faultString(String faultString);
+      public abstract Builder details(Details details);
       public abstract ServiceFault build();
-
+   }
+   
+   @AutoValue
+   public abstract static class Details {
+   
+      public enum FaultCode {
+   
+         BAD_REQUEST,
+         UNEXPECTED,
+         UNAUTHORIZED,
+         RESOURCE_NOT_FOUND,
+         RESOURCE_DELETED,
+         PROVISIONING_IN_PROCESS,
+         PROVISIONING_NO_CHANGES,
+         OVER_LIMIT_SETTING,
+         SERVER_EXCEED_CAPACITY,
+         SERVICE_UNAVAILABLE,
+         UNRECOGNIZED;
+   
+         public static FaultCode fromValue(String v) {
+            return Enums.getIfPresent(FaultCode.class, v).or(UNRECOGNIZED);
+         }
+      }
+   
+      public abstract FaultCode faultCode();
+      public abstract int httpCode();
+      public abstract String message();
+      public abstract int requestId();
+   
+      public static Builder builder() {
+         return new AutoValue_ServiceFault_Details.Builder();
+      }
+   
+      @AutoValue.Builder
+      public abstract static class Builder {
+         public abstract Builder faultCode(FaultCode faultCode);
+         public abstract Builder httpCode(int httpCode);
+         public abstract Builder message(String message);
+         public abstract Builder requestId(int requestId);
+         public abstract Details build();
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/72f2652d/providers/profitbricks/src/main/java/org/jclouds/profitbricks/handlers/ProfitBricksHttpErrorHandler.java
----------------------------------------------------------------------
diff --git 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/handlers/ProfitBricksHttpErrorHandler.java
 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/handlers/ProfitBricksHttpErrorHandler.java
index a4ecb50..eaf26fa 100644
--- 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/handlers/ProfitBricksHttpErrorHandler.java
+++ 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/handlers/ProfitBricksHttpErrorHandler.java
@@ -16,6 +16,7 @@
  */
 package org.jclouds.profitbricks.handlers;
 
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
 import static org.jclouds.util.Closeables2.closeQuietly;
 
 import javax.inject.Singleton;
@@ -39,7 +40,15 @@ public class ProfitBricksHttpErrorHandler implements 
HttpErrorHandler {
 
    @Override
    public void handleError(final HttpCommand command, final HttpResponse 
response) {
-      Exception exception = null;
+   // it is important to always read fully and close streams
+      byte[] data = closeClientButKeepContentStream(response);
+      String message = data != null ? new String(data) : null;
+
+      Exception exception = message != null ? new 
HttpResponseException(command, response, message)
+            : new HttpResponseException(command, response);
+      message = message != null ? message : String.format("%s -> %s", 
command.getCurrentRequest().getRequestLine(),
+            response.getStatusLine());
+      
       try {
          switch (response.getStatusCode()) {
             case 400:
@@ -49,6 +58,9 @@ public class ProfitBricksHttpErrorHandler implements 
HttpErrorHandler {
             case 401:
                exception = new AuthorizationException("This request requires 
authentication.", exception);
                break;
+            case 403:
+               exception = new AuthorizationException(response.getMessage(), 
exception);
+               break;
             case 402:
             case 409:
                exception = new IllegalStateException(response.getMessage(), 
exception);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/72f2652d/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
----------------------------------------------------------------------
diff --git 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
index 00ca238..795d460 100644
--- 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
+++ 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/ResponseStatusFromPayloadHttpCommandExecutorService.java
@@ -94,10 +94,13 @@ public class 
ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrl
          try {
             if (isSoapPayload(in)) {
                ServiceFault fault = faultHandler.parse(in);
-               if (fault != null)
-                  responseBuilder
-                          .statusCode(fault.httpCode())
-                          .message(fault.message());
+               if (fault != null) {
+                  if (fault.details() != null) {
+                     
responseBuilder.statusCode(fault.details().httpCode()).message(fault.details().message());
+                  } else {
+                     responseBuilder.message(fault.faultString());
+                  }
+               }
             }
          } catch (Exception ex) {
             // ignore

http://git-wip-us.apache.org/repos/asf/jclouds/blob/72f2652d/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandler.java
----------------------------------------------------------------------
diff --git 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandler.java
 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandler.java
index f21c32e..8b790ed 100644
--- 
a/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandler.java
+++ 
b/providers/profitbricks/src/main/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandler.java
@@ -17,27 +17,40 @@
 package org.jclouds.profitbricks.http.parser;
 
 import org.jclouds.profitbricks.domain.ServiceFault;
+import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
 public class ServiceFaultResponseHandler extends 
BaseProfitBricksResponseHandler<ServiceFault> {
 
    private final ServiceFault.Builder builder;
+   private ServiceFault.Details.Builder detailsBuilder;
    private boolean done = false;
 
    ServiceFaultResponseHandler() {
       this.builder = ServiceFault.builder();
    }
+   
+   @Override
+   public void startElement(String uri, String localName, String qName, 
Attributes attributes) throws SAXException {
+      if ("detail".equals(qName)) {
+         detailsBuilder = ServiceFault.Details.builder();
+      }
+   }
 
    @Override
    protected void setPropertyOnEndTag(String qName) {
-      if ("faultCode".equals(qName))
-         
builder.faultCode(ServiceFault.FaultCode.fromValue(textToStringValue()));
+      if ("faultcode".equals(qName))
+         builder.faultCode(textToStringValue());
+      else if ("faultstring".equals(qName))
+         builder.faultString(textToStringValue());
+      else if ("faultCode".equals(qName))
+         
detailsBuilder.faultCode(ServiceFault.Details.FaultCode.fromValue(textToStringValue()));
       else if ("httpCode".equals(qName))
-         builder.httpCode(textToIntValue());
+         detailsBuilder.httpCode(textToIntValue());
       else if ("message".equals(qName))
-         builder.message(textToStringValue());
+         detailsBuilder.message(textToStringValue());
       else if ("requestId".equals(qName))
-         builder.requestId(textToIntValue());
+         detailsBuilder.requestId(textToIntValue());
    }
 
    @Override
@@ -45,8 +58,10 @@ public class ServiceFaultResponseHandler extends 
BaseProfitBricksResponseHandler
       if (done)
          return;
       setPropertyOnEndTag(qName);
-      if ("detail".equals(qName))
+      if ("S:Fault".equals(qName))
          done = true;
+      if ("detail".equals(qName))
+         builder.details(detailsBuilder.build());
       clearTextBuffer();
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/72f2652d/providers/profitbricks/src/test/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/providers/profitbricks/src/test/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandlerTest.java
 
b/providers/profitbricks/src/test/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandlerTest.java
index 2b54dd5..f8c36f6 100644
--- 
a/providers/profitbricks/src/test/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandlerTest.java
+++ 
b/providers/profitbricks/src/test/java/org/jclouds/profitbricks/http/parser/ServiceFaultResponseHandlerTest.java
@@ -21,6 +21,7 @@ import static org.testng.Assert.assertNotNull;
 
 import org.jclouds.http.functions.ParseSax;
 import org.jclouds.profitbricks.domain.ServiceFault;
+import org.jclouds.profitbricks.domain.ServiceFault.Details;
 import org.testng.annotations.Test;
 
 @Test(groups = "unit", testName = "ServiceFaultResponseHandlerTest")
@@ -37,12 +38,31 @@ public class ServiceFaultResponseHandlerTest extends 
BaseResponseHandlerTest<Ser
       ServiceFault actual = 
parser.parse(payloadFromResource("/fault-404.xml"));
       assertNotNull(actual, "Parsed content returned null");
 
-      ServiceFault expected = ServiceFault.builder()
-              .faultCode(ServiceFault.FaultCode.RESOURCE_NOT_FOUND)
-              .httpCode(404)
-              .message("The requested resource could not be found. Please 
refer to Request Id : 16370720. [VDC-6-404] The requested resource does not 
exist or already deleted by the users. ResourceId random-non-existing-id")
-              .requestId(16370720)
-              .build();
+      ServiceFault expected = ServiceFault
+            .builder()
+            .faultCode("S:Server")
+            .faultString(
+                  "The requested resource could not be found. Please refer to 
Request Id : 16370720. [VDC-6-404] The requested resource does not exist or 
already deleted by the users. ResourceId random-non-existing-id")
+            .details(
+                  Details
+                        .builder()
+                        
.faultCode(ServiceFault.Details.FaultCode.RESOURCE_NOT_FOUND)
+                        .httpCode(404)
+                        .message(
+                              "The requested resource could not be found. 
Please refer to Request Id : 16370720. [VDC-6-404] The requested resource does 
not exist or already deleted by the users. ResourceId 
random-non-existing-id")
+                        .requestId(16370720).build()).build();
+
+      assertEquals(expected, actual);
+   }
+
+   @Test
+   public void testParseSoapServiceFaultWithoutDetails() {
+      ParseSax<ServiceFault> parser = createParser();
+      ServiceFault actual = 
parser.parse(payloadFromResource("/fault-500.xml"));
+      assertNotNull(actual, "Parsed content returned null");
+
+      ServiceFault expected = 
ServiceFault.builder().faultCode("S:Server").faultString("javax.ejb.EJBException")
+            .build();
 
       assertEquals(expected, actual);
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/72f2652d/providers/profitbricks/src/test/resources/fault-500.xml
----------------------------------------------------------------------
diff --git a/providers/profitbricks/src/test/resources/fault-500.xml 
b/providers/profitbricks/src/test/resources/fault-500.xml
new file mode 100644
index 0000000..e996474
--- /dev/null
+++ b/providers/profitbricks/src/test/resources/fault-500.xml
@@ -0,0 +1,9 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/";>
+    <S:Body>
+        <S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope";>
+            <faultcode>S:Server</faultcode>
+            <faultstring>javax.ejb.EJBException</faultstring>
+        </S:Fault>
+    </S:Body>
+</S:Envelope>
\ No newline at end of file

Reply via email to