SLING-9647 [Testing Clients] Store request and response on a ClientException
diff --git a/src/main/java/org/apache/sling/testing/clients/AbstractSlingClient.java b/src/main/java/org/apache/sling/testing/clients/AbstractSlingClient.java
index 117a475..59622c8 100644
--- a/src/main/java/org/apache/sling/testing/clients/AbstractSlingClient.java
+++ b/src/main/java/org/apache/sling/testing/clients/AbstractSlingClient.java
@@ -314,10 +314,10 @@
         if (headers != null) {
             request.setHeaders(headers.toArray(new Header[headers.size()]));
         }
-
+        SlingHttpResponse response = null;
         try {
             log.debug("request {} {}", request.getMethod(), request.getURI());
-            SlingHttpResponse response = new SlingHttpResponse(this.execute(request, context));
+            response = new SlingHttpResponse(this.execute(request, context));
             log.debug("response {}", HttpUtils.getHttpStatus(response));
             // Check the status and throw a ClientException if it doesn't match expectedStatus, but close the entity before
             if (expectedStatus != null && expectedStatus.length > 0) {
@@ -326,13 +326,15 @@
                 } catch (ClientException e) {
                     // catch the exception to make sure we close the entity before re-throwing it
                     response.close();
+                    e.setRequest(request);
+                    e.setResponse(response);
                     throw e;
                 }
             }
 
             return response;
         } catch (IOException e) {
-            throw new ClientException("Could not execute http request", e);
+            throw new ClientException("Could not execute http request", e, request, response);
         }
     }
 
diff --git a/src/main/java/org/apache/sling/testing/clients/ClientException.java b/src/main/java/org/apache/sling/testing/clients/ClientException.java
index 379ece6..e89dbc9 100644
--- a/src/main/java/org/apache/sling/testing/clients/ClientException.java
+++ b/src/main/java/org/apache/sling/testing/clients/ClientException.java
@@ -16,13 +16,17 @@
  */
 package org.apache.sling.testing.clients;
 
+import org.apache.http.client.methods.HttpUriRequest;
+
 /**
- *
+ * An exception thrown when something went wrong with using the sling testing clients
  */
 public class ClientException extends Exception {
 
     private static final long serialVersionUID = 1L;
     private int httpStatusCode = -1;
+    private HttpUriRequest request;
+    private SlingHttpResponse response;
 
     public ClientException(String message) {
         this(message, null);
@@ -32,27 +36,61 @@
         this(message, -1, throwable);
     }
 
-    public ClientException(String message, int htmlStatusCode) {
-        this(message, htmlStatusCode, null);
+    public ClientException(String message, int httpStatusCode) {
+        this(message, httpStatusCode, null);
     }
 
-    public ClientException(String message, int htmlStatusCode, Throwable throwable) {
+    public ClientException(String message, int httpStatusCode, Throwable throwable) {
         super(message, throwable);
-        this.httpStatusCode = htmlStatusCode;
+        this.httpStatusCode = httpStatusCode;
+    }
+
+    public ClientException(String message, Throwable throwable, HttpUriRequest request, SlingHttpResponse response) {
+        this(message, throwable);
+        this.request = request;
+        this.response = response;
+        if (this.response != null) {
+            this.httpStatusCode = response.getStatusLine().getStatusCode();
+        }
     }
 
     /**
-     * @return the htmlStatusCode
+     * @return The request associated with this exception or {{null}}
+     */
+    public HttpUriRequest getRequest() {
+        return request;
+    }
+
+    /**
+     * Set the request associated with this exception
+     * @param request
+     */
+    public void setRequest(HttpUriRequest request) {
+        this.request = request;
+    }
+
+    /**
+     * @return The response associated with this exception or {{null}}
+     */
+    public SlingHttpResponse getResponse() {
+        return response;
+    }
+
+    /**
+     * Set the response associated with this exception or {{null}}
+     * @param response
+     */
+    public void setResponse(SlingHttpResponse response) {
+        this.response = response;
+    }
+
+    /**
+     * @return the httpStatusCode
      */
     public int getHttpStatusCode() {
         return httpStatusCode;
     }
 
-    /*
-      * (non-Javadoc)
-      *
-      * @see java.lang.Throwable#getMessage()
-      */
     @Override
     public String getMessage() {
         String message = super.getMessage();
@@ -62,4 +100,20 @@
         return message;
     }
 
+    @Override
+    public String toString() {
+        StringBuilder messageBuilder = new StringBuilder(super.toString()).append(System.lineSeparator());
+        if (null != request) {
+            messageBuilder.append("Request: ");
+            messageBuilder.append(request.getMethod()).append(" ").append(request.getURI());
+            messageBuilder.append(System.lineSeparator());
+        }
+        if (null != response) {
+            messageBuilder.append("Response: ");
+            messageBuilder.append(response.getStatusLine().getStatusCode()).append(" ")
+                    .append(response.getStatusLine().getReasonPhrase());
+            messageBuilder.append(response.getContent());
+        }
+        return messageBuilder.toString();
+    }
 }
diff --git a/src/main/java/org/apache/sling/testing/clients/package-info.java b/src/main/java/org/apache/sling/testing/clients/package-info.java
index cd9b0bd..b8c2d58 100644
--- a/src/main/java/org/apache/sling/testing/clients/package-info.java
+++ b/src/main/java/org/apache/sling/testing/clients/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("2.0.0")
+@Version("2.1.0")
 package org.apache.sling.testing.clients;
 
 import org.osgi.annotation.versioning.Version;