Update rest-client with additional operations 73/4473/2
authordave.adams (da490c) <dave.adams@amdocs.com>
Wed, 24 May 2017 21:08:10 +0000 (17:08 -0400)
committerdave.adams (da490c) <dave.adams@amdocs.com>
Wed, 24 May 2017 21:53:38 +0000 (17:53 -0400)
Change-Id: Ia19c5156d40c816dc1ee77cece92c43f40791c59
Signed-off-by: dave.adams (da490c) <dave.adams@amdocs.com>
16 files changed:
README.md
pom.xml
src/main/java/org/openecomp/restclient/client/Headers.java
src/main/java/org/openecomp/restclient/client/OperationResult.java
src/main/java/org/openecomp/restclient/client/RestClient.java
src/main/java/org/openecomp/restclient/enums/RestAuthenticationMode.java [new file with mode: 0644]
src/main/java/org/openecomp/restclient/logging/RestClientMsgs.java
src/main/java/org/openecomp/restclient/rest/HttpUtil.java
src/main/java/org/openecomp/restclient/rest/RestClientBuilder.java
src/main/resources/logging/RESTClientMsgs.properties
src/test/java/org/openecomp/restclient/client/OperationResultTest.java [new file with mode: 0644]
src/test/java/org/openecomp/restclient/client/RESTClientTest.java [deleted file]
src/test/java/org/openecomp/restclient/client/RestfulClientTest.java [new file with mode: 0644]
src/test/java/org/openecomp/restclient/enums/RestAuthenticationModeTest.java [new file with mode: 0644]
src/test/java/org/openecomp/restclient/rest/HttpUtilTest.java [new file with mode: 0644]
src/test/java/org/openecomp/restclient/rest/RestClientBuilderTest.java

index d17a448..4151a47 100644 (file)
--- a/README.md
+++ b/README.md
@@ -11,16 +11,19 @@ In order to make the _REST Client_ library available to your microservice, inclu
     <dependency>
         <groupId>org.openecomp.aai</groupId>
         <artifactId>rest-client</artifactId>
     <dependency>
         <groupId>org.openecomp.aai</groupId>
         <artifactId>rest-client</artifactId>
-        <version>1.0.0-SNAPSHOT</version>
+        <version>1.1.0-SNAPSHOT</version>
     </dependency>
     
 ## Code Examples
 
 ### Creating and Configuring a Client Instance
     </dependency>
     
 ## Code Examples
 
 ### Creating and Configuring a Client Instance
-In order to start talking to a service, you need to create a client instance and configure it.  The _RestClient_ uses a fluent interface which allows it to be both instantiated and configured as in the following example:
+In order to start talking to a service, you need to create a client instance and configure it.  The _RestClient_ uses a fluent interface which allows it to be both instantiated and configured as in the following examples:
+
+i)  A client using an SSL Client Certificate:
 
     // Create an instance of the Rest Client and configure it.
     RestClient myClient = new RestClient()
 
     // Create an instance of the Rest Client and configure it.
     RestClient myClient = new RestClient()
+        .authenticationMode(RestAuthenticationMode.SSL_CERT)
         .validateServerHostname(false)
         .validateServerCertChain(true)
         .clientCertFile("certificate_filename")
         .validateServerHostname(false)
         .validateServerCertChain(true)
         .clientCertFile("certificate_filename")
@@ -28,6 +31,24 @@ In order to start talking to a service, you need to create a client instance and
         .connectTimeoutMs(1000)
         .readTimeoutMs(1000)
         
         .connectTimeoutMs(1000)
         .readTimeoutMs(1000)
         
+ii) A client using SSL Basic-Auth:
+
+    // Create an instance of the Rest Client and configure it.
+    RestClient myClient = new RestClient()
+        .authenticationMode(RestAuthenticationMode.SSL_BASIC)
+        .basicAuthUsername("username")
+        .basicAuthPassword("password")
+        .connectTimeoutMs(1000)
+        .readTimeoutMs(1000)
+
+iii) A client using non-authentication HTTP:
+
+    // Create an instance of the Rest Client and configure it.
+    RestClient myClient = new RestClient()
+        .authenticationMode(RestAuthenticationMode.HTTP_NOAUTH)
+        .connectTimeoutMs(1000)
+        .readTimeoutMs(1000)
+        
 Note, that all of the above configuration parameters are optional and will be set to default values if they are not specified.
 
 ### Querying The A&AI
 Note, that all of the above configuration parameters are optional and will be set to default values if they are not specified.
 
 ### Querying The A&AI
diff --git a/pom.xml b/pom.xml
index 59374ae..45a5f3e 100644 (file)
--- a/pom.xml
+++ b/pom.xml
                        <artifactId>common-logging</artifactId>
                        <version>1.0.0</version>
                </dependency>
                        <artifactId>common-logging</artifactId>
                        <version>1.0.0</version>
                </dependency>
-
+               
                <dependency>
                <dependency>
-                       <groupId>com.sun.jersey.jersey-test-framework</groupId>
-                       <artifactId>jersey-test-framework-grizzly2</artifactId>
-                       <version>1.18</version>
+                       <groupId>org.mockito</groupId>
+                       <artifactId>mockito-all</artifactId>
+                       <version>1.10.19</version>
                        <scope>test</scope>
                </dependency>
                        <scope>test</scope>
                </dependency>
+               
+               <dependency>
+                       <groupId>org.powermock</groupId>
+                       <artifactId>powermock-module-junit4</artifactId>
+                       <version>1.6.2</version>
+                       <scope>test</scope>
+               </dependency>
+               
+               <dependency>
+                       <groupId>org.powermock</groupId>
+                       <artifactId>powermock-api-mockito</artifactId>
+                       <version>1.6.2</version>
+                       <scope>test</scope>
+               </dependency>
+               
+               <dependency>
+                       <groupId>org.powermock</groupId>
+                       <artifactId>powermock-module-javaagent</artifactId>
+                       <version>1.6.2</version>
+                       <scope>test</scope>
+               </dependency>
+               
+               <dependency>
+                       <groupId>org.powermock</groupId>
+                       <artifactId>powermock-module-junit4-rule-agent</artifactId>
+                       <version>1.6.2</version>
+                       <scope>test</scope>
+               </dependency>           
 
        </dependencies>
 
 
        </dependencies>
 
index aac817e..dbfb6bb 100644 (file)
@@ -33,5 +33,5 @@ public final class Headers {
   public static final String IF_MATCH = "If-Match";\r
   public static final String IF_NONE_MATCH = "If-None-Match";\r
   public static final String ACCEPT = "Accept";\r
   public static final String IF_MATCH = "If-Match";\r
   public static final String IF_NONE_MATCH = "If-None-Match";\r
   public static final String ACCEPT = "Accept";\r
-\r
+  public static final String AUTHORIZATION = "Authorization";\r
 }\r
 }\r
index c9d0f9c..1a301b9 100644 (file)
@@ -28,10 +28,32 @@ import javax.ws.rs.core.MultivaluedMap;
 \r
 public class OperationResult {\r
 \r
 \r
 public class OperationResult {\r
 \r
+  private String requestedLink;\r
   private String result;\r
   private String failureCause;\r
   private String result;\r
   private String failureCause;\r
+  private boolean fromCache;\r
   private int resultCode;\r
   private int resultCode;\r
-  private MultivaluedMap<String, String> headers;\r
+  private int numRetries;\r
+  private MultivaluedMap<String, String> responseHeaders;\r
+\r
+\r
+  public OperationResult() {\r
+    super();\r
+    this.numRetries = 0;\r
+    this.fromCache = false;\r
+  }\r
+\r
+  /**\r
+   * Instantiates a new operation result.\r
+   *\r
+   * @param resultCode the result code\r
+   * @param result the result\r
+   */\r
+  public OperationResult(int resultCode, String result) {\r
+    this();\r
+    this.resultCode = resultCode;\r
+    this.result = result;\r
+  }\r
 \r
   /**\r
    * Get the HTTP headers of the response.\r
 \r
   /**\r
    * Get the HTTP headers of the response.\r
@@ -39,13 +61,21 @@ public class OperationResult {
    * @return the HTTP headers of the response.\r
    */\r
   public MultivaluedMap<String, String> getHeaders() {\r
    * @return the HTTP headers of the response.\r
    */\r
   public MultivaluedMap<String, String> getHeaders() {\r
-    return headers;\r
+    return responseHeaders;\r
   }\r
 \r
   }\r
 \r
-  public void setHeaders(MultivaluedMap<String, String> headers) {\r
-    this.headers = headers;\r
+  /**\r
+   * Returns true if the HTTP Status Code 200 <= x <= 299\r
+   *\r
+   * @return true, if successful\r
+   */\r
+  public boolean wasSuccessful() {\r
+    return (resultCode > 199 && resultCode < 300);\r
   }\r
 \r
   }\r
 \r
+  public void setHeaders(MultivaluedMap<String, String> headers) {\r
+    this.responseHeaders = headers;\r
+  }\r
 \r
   public String getResult() {\r
     return result;\r
 \r
   public String getResult() {\r
     return result;\r
@@ -62,22 +92,67 @@ public class OperationResult {
   public String getFailureCause() {\r
     return failureCause;\r
   }\r
   public String getFailureCause() {\r
     return failureCause;\r
   }\r
-\r
+  \r
+  /**\r
+   * Sets the result.\r
+   *\r
+   * @param resultCode the result code\r
+   * @param result the result\r
+   */\r
+  public void setResult(int resultCode, String result) {\r
+    this.resultCode = resultCode;\r
+    this.result = result;\r
+  }\r
+  \r
   public void setFailureCause(String failureCause) {\r
     this.failureCause = failureCause;\r
   }\r
 \r
   public void setFailureCause(String failureCause) {\r
     this.failureCause = failureCause;\r
   }\r
 \r
+  /**\r
+   * Sets the failure cause.\r
+   *\r
+   * @param resultCode the result code\r
+   * @param failureCause the result error\r
+   */\r
+  public void setFailureCause(int resultCode, String failureCause) {\r
+    this.resultCode = resultCode;\r
+    this.failureCause = failureCause;\r
+  }\r
+\r
+  \r
   public void setResultCode(int resultCode) {\r
     this.resultCode = resultCode;\r
   }\r
 \r
   public void setResultCode(int resultCode) {\r
     this.resultCode = resultCode;\r
   }\r
 \r
-  public OperationResult() {\r
-    super();\r
+  public String getRequestedLink() {\r
+    return requestedLink;\r
+  }\r
+\r
+  public void setRequestedLink(String requestedLink) {\r
+    this.requestedLink = requestedLink;\r
+  }\r
+\r
+  public boolean isFromCache() {\r
+    return fromCache;\r
+  }\r
+\r
+  public void setFromCache(boolean fromCache) {\r
+    this.fromCache = fromCache;\r
+  }\r
+\r
+  public int getNumRetries() {\r
+    return numRetries;\r
+  }\r
+\r
+  public void setNumRetries(int numRetries) {\r
+    this.numRetries = numRetries;\r
   }\r
 \r
   @Override\r
   public String toString() {\r
   }\r
 \r
   @Override\r
   public String toString() {\r
-    return "OperationResult [result=" + result + ", resultCode=" + resultCode + "]";\r
+    return "OperationResult [result=" + result + ", requestedLink=" + requestedLink\r
+        + ", failureCause=" + failureCause + ", resultCode=" + resultCode + ", numRetries="\r
+        + numRetries + ", responseHeaders=" + responseHeaders + "]";\r
   }\r
 \r
 }\r
   }\r
 \r
 }\r
index 900c4e0..02d19e6 100644 (file)
  */
 package org.openecomp.restclient.client;
 
  */
 package org.openecomp.restclient.client;
 
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.api.client.WebResource.Builder;
-import com.sun.jersey.core.util.MultivaluedMapImpl;
-
-import org.openecomp.cl.api.LogFields;
-import org.openecomp.cl.api.LogLine;
-import org.openecomp.cl.api.Logger;
-import org.openecomp.cl.eelf.LoggerFactory;
-import org.openecomp.cl.mdc.MdcContext;
-import org.openecomp.cl.mdc.MdcOverride;
-import org.openecomp.restclient.logging.RestClientMsgs;
-import org.openecomp.restclient.rest.RestClientBuilder;
-
 import java.io.ByteArrayOutputStream;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.io.ByteArrayOutputStream;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
@@ -46,16 +31,36 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.UUID;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 
 
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 
+import org.openecomp.cl.api.LogFields;
+import org.openecomp.cl.api.LogLine;
+import org.openecomp.cl.api.Logger;
+import org.openecomp.cl.eelf.LoggerFactory;
+import org.openecomp.cl.mdc.MdcContext;
+import org.openecomp.cl.mdc.MdcOverride;
+import org.openecomp.restclient.enums.RestAuthenticationMode;
+import org.openecomp.restclient.logging.RestClientMsgs;
+import org.openecomp.restclient.rest.RestClientBuilder;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
 
 /**
  * This class provides a general client implementation that micro services can use for communicating
  * with the endpoints via their exposed REST interfaces.
 
 /**
  * This class provides a general client implementation that micro services can use for communicating
  * with the endpoints via their exposed REST interfaces.
+ * 
  */
  */
+
 public class RestClient {
 
   /**
 public class RestClient {
 
   /**
@@ -63,11 +68,9 @@ public class RestClient {
    * communicate with the REST endpoint.
    */
   private RestClientBuilder clientBuilder;
    * communicate with the REST endpoint.
    */
   private RestClientBuilder clientBuilder;
-
-  /**
-   * The low level instance of the REST client that will be used to communicate with the endpoint.
-   */
-  private Client restClient = null;
+  
+  private final ConcurrentMap<String,InitializedClient> CLIENT_CACHE = new ConcurrentHashMap<String,InitializedClient>();
+  private static final String REST_CLIENT_INSTANCE = "REST_CLIENT_INSTANCE";
 
   /** Standard logger for producing log statements. */
   private Logger logger = LoggerFactory.getInstance().getLogger("AAIRESTClient");
 
   /** Standard logger for producing log statements. */
   private Logger logger = LoggerFactory.getInstance().getLogger("AAIRESTClient");
@@ -89,11 +92,20 @@ public class RestClient {
   /** Reusable function call for DELETE REST operations. */
   private final RestOperation deleteOp = new DeleteRestOperation();
 
   /** Reusable function call for DELETE REST operations. */
   private final RestOperation deleteOp = new DeleteRestOperation();
 
+  /** Reusable function call for HEAD REST operations. */
+  private final RestOperation headOp = new HeadRestOperation();
+
+  /** Reusable function call for PATCH REST operations. */
+  private final RestOperation patchOp = new PatchRestOperation();
+  
+  
   /**
    * Creates a new instance of the {@link RestClient}.
    */
   public RestClient() {
   /**
    * Creates a new instance of the {@link RestClient}.
    */
   public RestClient() {
+    
     clientBuilder = new RestClientBuilder();
     clientBuilder = new RestClientBuilder();
+  
   }
 
 
   }
 
 
@@ -106,6 +118,27 @@ public class RestClient {
   public RestClient(RestClientBuilder rcBuilder) {
     clientBuilder = rcBuilder;
   }
   public RestClient(RestClientBuilder rcBuilder) {
     clientBuilder = rcBuilder;
   }
+  
+  public RestClient authenticationMode(RestAuthenticationMode mode) {
+    logger.debug("Set rest authentication mode= " + mode);
+    clientBuilder.setAuthenticationMode(mode);
+    return this;
+  }
+  
+  public RestClient basicAuthUsername(String username) {
+    logger.debug("Set SSL BasicAuth username = " + username);
+    clientBuilder.setBasicAuthUsername(username);
+    return this;
+  }
+  
+  public RestClient basicAuthPassword(String password) {
+    /*
+     * purposely not logging out the password, I guess we could obfuscate it if we really want to
+     * see it in the logs
+     */
+    clientBuilder.setBasicAuthPassword(password);
+    return this;
+  }
 
 
   /**
 
 
   /**
@@ -160,7 +193,6 @@ public class RestClient {
    * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
    */
   public RestClient clientCertPassword(String password) {
    * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
    */
   public RestClient clientCertPassword(String password) {
-    logger.debug("Set client certificate password = " + password);
     clientBuilder.setClientCertPassword(password);
     return this;
   }
     clientBuilder.setClientCertPassword(password);
     return this;
   }
@@ -207,6 +239,26 @@ public class RestClient {
     return this;
   }
 
     return this;
   }
 
+  private boolean shouldRetry(OperationResult operationResult) {
+
+    if (operationResult == null) {
+      return true;
+    }
+
+    int resultCode = operationResult.getResultCode();
+
+    if (resultCode == 200) {
+      return false;
+    }
+
+    if (resultCode == 404) {
+      return false;
+    }
+
+    return true;
+
+  }
+  
   /**
    * This method operates on a REST endpoint by submitting an HTTP operation request against the
    * supplied URL.    
   /**
    * This method operates on a REST endpoint by submitting an HTTP operation request against the
    * supplied URL.    
@@ -232,23 +284,29 @@ public class RestClient {
     long startTimeInMs = System.currentTimeMillis();
     for (int retryCount = 0; retryCount < numRetries; retryCount++) {
 
     long startTimeInMs = System.currentTimeMillis();
     for (int retryCount = 0; retryCount < numRetries; retryCount++) {
 
-      logger.info(RestClientMsgs.HTTP_REQUEST_WITH_RETRIES, url, Integer.toString(retryCount + 1));
-
+      logger.info(RestClientMsgs.HTTP_REQUEST_WITH_RETRIES, operation.getRequestType().toString(),
+          url, Integer.toString(retryCount + 1));
+      
       // Submit our query to the AAI.
       result = processRequest(operation, url, payload, headers, contentType, responseType);
 
       // If the submission was successful then we're done.
       // Submit our query to the AAI.
       result = processRequest(operation, url, payload, headers, contentType, responseType);
 
       // If the submission was successful then we're done.
-      if (Integer.toString(result.getResultCode()).charAt(0) == '2') {
-        logger.info(RestClientMsgs.HTTP_REQUEST_TIME_WITH_RETRIES,
-            Long.toString(System.currentTimeMillis() - startTimeInMs), url,
+      
+      if (!shouldRetry(result)) {
+        
+        logger.info(RestClientMsgs.HTTP_REQUEST_TIME_WITH_RETRIES, operation.getRequestType().toString(),url,
+            Long.toString(System.currentTimeMillis() - startTimeInMs), 
             Integer.toString(retryCount));
             Integer.toString(retryCount));
+        
+        result.setNumRetries(retryCount);
+        
         return result;
       }
 
       // Our submission was unsuccessful...
       try {
         // Sleep between re-tries to be nice to the target system.
         return result;
       }
 
       // Our submission was unsuccessful...
       try {
         // Sleep between re-tries to be nice to the target system.
-        Thread.sleep(500);
+        Thread.sleep(50);
 
       } catch (InterruptedException e) {
         logger.error(RestClientMsgs.HTTP_REQUEST_INTERRUPTED, url, e.getLocalizedMessage());
 
       } catch (InterruptedException e) {
         logger.error(RestClientMsgs.HTTP_REQUEST_INTERRUPTED, url, e.getLocalizedMessage());
@@ -257,9 +315,10 @@ public class RestClient {
     }
 
     // If we've gotten this far, then we failed all of our retries.
     }
 
     // If we've gotten this far, then we failed all of our retries.
+    result.setNumRetries(numRetries);
     result.setResultCode(504);
     result.setFailureCause(
     result.setResultCode(504);
     result.setFailureCause(
-        "Failed to get a successful result " + "after multiple retries to target server");
+        "Failed to get a successful result after multiple retries to target server.");
 
     return result;
   }
 
     return result;
   }
@@ -379,7 +438,39 @@ public class RestClient {
       MediaType contentType, MediaType responseType) {
     return processRequest(postOp, url, payload, headers, contentType, responseType);
   }
       MediaType contentType, MediaType responseType) {
     return processRequest(postOp, url, payload, headers, contentType, responseType);
   }
+  
+  /**
+   * This method submits an HTTP POST request against the supplied URL, and emulates a PATCH
+   * operation by setting a special header value
+   *
+   * @param url - The REST endpoint to submit the POST request to.
+   * @param payload - the payload to send to the supplied URL
+   * @param headers - The headers that should be passed in the request
+   * @param contentType - The content type of the payload
+   * @param responseType - The expected format of the response.
+   *
+   * @return The result of the POST request.
+   */
+  public OperationResult patch(String url, String payload, Map<String, List<String>> headers,
+      MediaType contentType, MediaType responseType) {
+    return processRequest(patchOp, url, payload, headers, contentType, responseType);
+  }
 
 
+  
+  /**
+   * This method submits an HTTP HEAD request against the supplied URL
+   *
+   * @param url - The REST endpoint to submit the POST request to.
+   * @param headers - The headers that should be passed in the request
+   * @param responseType - The expected format of the response.
+   *
+   * @return The result of the POST request.
+   */
+  public OperationResult head(String url, Map<String, List<String>> headers,
+      MediaType responseType) {
+    return processRequest(headOp, url, null, headers, null, responseType);
+  }
+  
   /**
    * This method submits an HTTP GET request against the supplied URL.
    *
   /**
    * This method submits an HTTP GET request against the supplied URL.
    *
@@ -508,6 +599,12 @@ public class RestClient {
       for (Entry<String, List<String>> header : headers.entrySet()) {
         builder.header(header.getKey(), header.getValue());
       }
       for (Entry<String, List<String>> header : headers.entrySet()) {
         builder.header(header.getKey(), header.getValue());
       }
+      
+      if (clientBuilder.getAuthenticationMode() == RestAuthenticationMode.SSL_BASIC) {
+        builder = builder.header(Headers.AUTHORIZATION,
+            clientBuilder.getBasicAuthenticationCredentials());
+      }
+      
     }
 
     return builder;
     }
 
     return builder;
@@ -554,39 +651,58 @@ public class RestClient {
     }
   }
 
     }
   }
 
-
   /**
    * This method creates an instance of the low level REST client to use for communicating with the
    * AAI, if one has not already been created, otherwise it returns the already created instance.
    *
    * @return A {@link Client} instance.
    */
   /**
    * This method creates an instance of the low level REST client to use for communicating with the
    * AAI, if one has not already been created, otherwise it returns the already created instance.
    *
    * @return A {@link Client} instance.
    */
-  private synchronized Client getClient() throws Exception {
+  protected Client getClient() throws Exception {
+
+    /*
+     * Attempting a new way of doing non-blocking thread-safe lazy-initialization by using Java 1.8
+     * computeIfAbsent functionality. A null value will not be stored, but once a valid mapping has
+     * been established, then the same value will be returned.
+     * 
+     * One awkwardness of the computeIfAbsent is the lack of support for thrown exceptions, which
+     * required a bit of hoop jumping to preserve the original exception for the purpose of
+     * maintaining the pre-existing this API signature.
+     */
+    final InitializedClient clientInstance =
+        CLIENT_CACHE.computeIfAbsent(REST_CLIENT_INSTANCE, k -> loggedClientInitialization());
+    
+    if (clientInstance.getCaughtException() != null) {
+      throw new InstantiationException(clientInstance.getCaughtException().getMessage());
+    }
 
 
-    if (restClient == null) {
+    return clientInstance.getClient();
 
 
-      if (logger.isDebugEnabled()) {
-        logger.debug("Instantiating REST client with following parameters:");
-        logger.debug(
-            "  validate server hostname          = " + clientBuilder.isValidateServerHostname());
-        logger.debug(
-            "  validate server certificate chain = " + clientBuilder.isValidateServerCertChain());
-        logger.debug(
-            "  client certificate filename       = " + clientBuilder.getClientCertFileName());
-        logger.debug(
-            "  client certificate password       = " + clientBuilder.getClientCertPassword());
-        logger.debug(
-            "  trust store filename              = " + clientBuilder.getTruststoreFilename());
-        logger.debug("  connection timeout                = "
-            + clientBuilder.getConnectTimeoutInMs() + " ms");
-        logger.debug(
-            "  read timeout                      = " + clientBuilder.getReadTimeoutInMs() + " ms");
-      }
+  }
 
 
-      restClient = clientBuilder.getClient();
+  /**
+   * This method will only be called if computerIfAbsent is true.  The return value is null, then the result is not
+   * stored in the map. 
+   * 
+   * @return a new client instance or null
+   */
+  private InitializedClient loggedClientInitialization() {
+
+    if (logger.isDebugEnabled()) {
+      logger.debug("Instantiating REST client with following parameters:");
+      logger.debug(clientBuilder.toString());
+    }
+    
+    InitializedClient initClient = new InitializedClient();
+    
+    try {
+      initClient.setClient(clientBuilder.getClient());
+    } catch ( Throwable error ) {
+      initClient.setCaughtException(error);
     }
     }
+    
+    return initClient;
 
 
-    return restClient;
   }
 
 
   }
 
 
@@ -609,10 +725,10 @@ public class RestClient {
 
     opResult.setResultCode(statusCode);
 
 
     opResult.setResultCode(statusCode);
 
-    if ((statusCode < 200) || (statusCode > 299)) {
-      opResult.setFailureCause(payload);
-    } else {
+    if (opResult.wasSuccessful()) {
       opResult.setResult(payload);
       opResult.setResult(payload);
+    } else {
+      opResult.setFailureCause(payload);
     }
 
     opResult.setHeaders(response.getHeaders());
     }
 
     opResult.setHeaders(response.getHeaders());
@@ -657,6 +773,34 @@ public class RestClient {
       return RequestType.DELETE;
     }
   }
       return RequestType.DELETE;
     }
   }
+  
+  private class HeadRestOperation implements RestOperation {
+    public ClientResponse processOperation(Builder builder) {
+      return builder.head();
+    }
+
+    public RequestType getRequestType() {
+      return RequestType.HEAD;
+    }
+  }
+
+  private class PatchRestOperation implements RestOperation {
+
+    /**
+     * Technically there is no standarized PATCH operation for the 
+     * jersey client, but we can use the method-override approach 
+     * instead.
+     */
+    public ClientResponse processOperation(Builder builder) {
+      builder = builder.header("X-HTTP-Method-Override", "PATCH");
+      return builder.post(ClientResponse.class);
+    }
+
+    public RequestType getRequestType() {
+      return RequestType.PATCH;
+    }
+  }
+
 
   /**
    * Interface used wrap a Jersey REST call using a functional interface.
 
   /**
    * Interface used wrap a Jersey REST call using a functional interface.
@@ -680,7 +824,36 @@ public class RestClient {
      * The supported REST request types.
      */
     public enum RequestType {
      * The supported REST request types.
      */
     public enum RequestType {
-      GET, PUT, POST, DELETE;
+      GET, PUT, POST, DELETE, PATCH, HEAD
+    }
+  }
+  
+  /*
+   * An entity to encapsulate an expected result and a potential failure cause when returning from a
+   * functional interface during the computeIfAbsent call.
+   */
+  private class InitializedClient {
+    private Client client;
+    private Throwable caughtException;
+    
+    public InitializedClient() {
+      client = null;
+      caughtException = null;
+    }
+    
+    public Client getClient() {
+      return client;
+    }
+    public void setClient(Client client) {
+      this.client = client;
+    }
+    public Throwable getCaughtException() {
+      return caughtException;
+    }
+    public void setCaughtException(Throwable caughtException) {
+      this.caughtException = caughtException;
     }
     }
+  
   }
   }
+  
 }
 }
diff --git a/src/main/java/org/openecomp/restclient/enums/RestAuthenticationMode.java b/src/main/java/org/openecomp/restclient/enums/RestAuthenticationMode.java
new file mode 100644 (file)
index 0000000..5174b75
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * ============LICENSE_START=======================================================
+ * RestClient
+ * ================================================================================
+ * Copyright Â© 2017 AT&T Intellectual Property.
+ * Copyright Â© 2017 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ */
+package org.openecomp.restclient.enums;
+
+/**
+ * Authentication Modes:
+ * <li>HTTP_NOAUTH - intended to represent basic HTTP no authentication
+ * <li>SSL_BASIC - HTTP/S with username/password
+ * <li>SSL_CERT - HTTP/S with client cert
+ */
+
+public enum RestAuthenticationMode {
+  HTTP_NOAUTH("HTTP_NO_AUTH"), SSL_BASIC("SSL_BASIC"), SSL_CERT("SSL_CERT"), UNKNOWN_MODE(
+      "UNKNOWN_MODE");
+
+  private String authenticationModeLabel;
+
+  private RestAuthenticationMode(String authModelLabel) {
+    this.authenticationModeLabel = authModelLabel;
+  }
+
+  public String getAuthenticationModeLabel() {
+    return authenticationModeLabel;
+  }
+
+  public static RestAuthenticationMode getRestAuthenticationMode(String authenticationMode) {
+
+    RestAuthenticationMode mappedMode = RestAuthenticationMode.UNKNOWN_MODE;
+
+    if (authenticationMode == null) {
+      return mappedMode;
+    }
+
+    try {
+      mappedMode = RestAuthenticationMode.valueOf(authenticationMode);
+    } catch (Exception exc) {
+      mappedMode = RestAuthenticationMode.UNKNOWN_MODE;
+    }
+
+    return mappedMode;
+
+  }
+
+}
index 0b59139..49ac648 100644 (file)
@@ -102,8 +102,13 @@ public enum RestClientMsgs implements LogMessageEnum {
    *    {0} = URL \r
    *    {1} - Response code\r
    */\r
    *    {0} = URL \r
    *    {1} - Response code\r
    */\r
-  HTTP_RESPONSE;\r
+  HTTP_RESPONSE,\r
 \r
 \r
+  /**\r
+   * . Arguments: \r
+   *     {0} = failure cause\r
+   */\r
+  CLIENT_INITIALIZATION_FAILURE;\r
 \r
   /**\r
    * Static initializer to ensure the resource bundles for this class are loaded...\r
 \r
   /**\r
    * Static initializer to ensure the resource bundles for this class are loaded...\r
index 89af684..4ea8928 100644 (file)
@@ -50,7 +50,7 @@ public class HttpUtil {
    * @return true if the response is of the informational class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassInformational(int response) {\r
    * @return true if the response is of the informational class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassInformational(int response) {\r
-    return isExpectedHttpResponseClass(response, '1');\r
+    return ( response >= 100 && response <= 199);\r
   }\r
 \r
   /**\r
   }\r
 \r
   /**\r
@@ -60,7 +60,8 @@ public class HttpUtil {
    * @return true if the response is of the success class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassSuccess(int response) {\r
    * @return true if the response is of the success class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassSuccess(int response) {\r
-    return isExpectedHttpResponseClass(response, '2');\r
+    return ( response >= 200 && response <= 299);\r
+\r
   }\r
 \r
   /**\r
   }\r
 \r
   /**\r
@@ -70,7 +71,7 @@ public class HttpUtil {
    * @return true if the response is of the redirection class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassRedirection(int response) {\r
    * @return true if the response is of the redirection class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassRedirection(int response) {\r
-    return isExpectedHttpResponseClass(response, '3');\r
+    return ( response >= 300 && response <= 399);\r
   }\r
 \r
   /**\r
   }\r
 \r
   /**\r
@@ -80,7 +81,7 @@ public class HttpUtil {
    * @return true if the response is of the client error class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassClientError(int response) {\r
    * @return true if the response is of the client error class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassClientError(int response) {\r
-    return isExpectedHttpResponseClass(response, '4');\r
+    return ( response >= 400 && response <= 499);\r
   }\r
 \r
   /**\r
   }\r
 \r
   /**\r
@@ -90,26 +91,7 @@ public class HttpUtil {
    * @return true if the response is of the server error class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassServerError(int response) {\r
    * @return true if the response is of the server error class and false otherwise\r
    */\r
   public static boolean isHttpResponseClassServerError(int response) {\r
-    return isExpectedHttpResponseClass(response, '5');\r
+    return ( response >= 500 && response <= 599);\r
   }\r
 \r
   }\r
 \r
-  /**\r
-   * Helper method to determine if we have received the response class we are expecting.\r
-   *\r
-   * @param response the http response we got from our request\r
-   * @param expectedClass the expected http response class ie: 1, 2, 3, 4, 5 which maps to 1xx, 2xx,\r
-   *        3xx, 4xx, 5xx respectively\r
-   * @return true if the response if of our expected class and false if not\r
-   */\r
-  private static boolean isExpectedHttpResponseClass(int response, char expectedClass) {\r
-    if (response < 100 || response >= 600) {\r
-      return false;\r
-    }\r
-\r
-    if (Integer.toString(response).charAt(0) == expectedClass) {\r
-      return true;\r
-    }\r
-\r
-    return false;\r
-  }\r
 }\r
 }\r
index 3d546fe..0afd8a6 100644 (file)
  */\r
 package org.openecomp.restclient.rest;\r
 \r
  */\r
 package org.openecomp.restclient.rest;\r
 \r
-import com.sun.jersey.api.client.Client;\r
-import com.sun.jersey.api.client.config.ClientConfig;\r
-import com.sun.jersey.api.client.config.DefaultClientConfig;\r
-import com.sun.jersey.client.urlconnection.HTTPSProperties;\r
-\r
 import java.io.FileInputStream;\r
 import java.security.KeyStore;\r
 import java.security.cert.X509Certificate;\r
 import java.io.FileInputStream;\r
 import java.security.KeyStore;\r
 import java.security.cert.X509Certificate;\r
@@ -40,16 +35,19 @@ import javax.net.ssl.SSLSession;
 import javax.net.ssl.TrustManager;\r
 import javax.net.ssl.X509TrustManager;\r
 \r
 import javax.net.ssl.TrustManager;\r
 import javax.net.ssl.X509TrustManager;\r
 \r
+import org.openecomp.restclient.enums.RestAuthenticationMode;\r
+\r
+import com.sun.jersey.api.client.Client;\r
+import com.sun.jersey.api.client.config.ClientConfig;\r
+import com.sun.jersey.api.client.config.DefaultClientConfig;\r
+import com.sun.jersey.client.urlconnection.HTTPSProperties;\r
+\r
 /**\r
  * This is a generic REST Client builder with flexible security validation. Sometimes it's nice to\r
  * be able to disable server chain cert validation and hostname validation to work-around lab\r
  * issues, but at the same time be able to provide complete validation with client cert + hostname +\r
 /**\r
  * This is a generic REST Client builder with flexible security validation. Sometimes it's nice to\r
  * be able to disable server chain cert validation and hostname validation to work-around lab\r
  * issues, but at the same time be able to provide complete validation with client cert + hostname +\r
- * server cert chain validation.  \r
- * I used the ModelLoader REST client as a base and merged in the TSUI client I wrote which also\r
- * validates the server hostname and server certificate chain.\r
- * \r
- * @author DAVEA\r
- *\r
+ * server cert chain validation. I used the ModelLoader REST client as a base and merged in the TSUI\r
+ * client I wrote which also validates the server hostname and server certificate chain.\r
  */\r
 public class RestClientBuilder {\r
 \r
  */\r
 public class RestClientBuilder {\r
 \r
@@ -60,15 +58,14 @@ public class RestClientBuilder {
   public static final String DEFAULT_TRUST_STORE_FILENAME = null;\r
   public static final int DEFAULT_CONNECT_TIMEOUT_MS = 60000;\r
   public static final int DEFAULT_READ_TIMEOUT_MS = 60000;\r
   public static final String DEFAULT_TRUST_STORE_FILENAME = null;\r
   public static final int DEFAULT_CONNECT_TIMEOUT_MS = 60000;\r
   public static final int DEFAULT_READ_TIMEOUT_MS = 60000;\r
+  public static final RestAuthenticationMode DEFAULT_AUTH_MODE = RestAuthenticationMode.HTTP_NOAUTH;\r
+  public static final String DEFAULT_BASIC_AUTH_USERNAME = "";\r
+  public static final String DEFAULT_BASIC_AUTH_PASSWORD = "";\r
 \r
   private static final String SSL_PROTOCOL = "TLS";\r
   private static final String KEYSTORE_ALGORITHM = "SunX509";\r
   private static final String KEYSTORE_TYPE = "PKCS12";\r
 \r
 \r
   private static final String SSL_PROTOCOL = "TLS";\r
   private static final String KEYSTORE_ALGORITHM = "SunX509";\r
   private static final String KEYSTORE_TYPE = "PKCS12";\r
 \r
-  /*\r
-   * TODO: implement fluent interface?\r
-   */\r
-\r
   private boolean validateServerHostname;\r
   private boolean validateServerCertChain;\r
   private String clientCertFileName;\r
   private boolean validateServerHostname;\r
   private boolean validateServerCertChain;\r
   private String clientCertFileName;\r
@@ -76,6 +73,9 @@ public class RestClientBuilder {
   private String truststoreFilename;\r
   private int connectTimeoutInMs;\r
   private int readTimeoutInMs;\r
   private String truststoreFilename;\r
   private int connectTimeoutInMs;\r
   private int readTimeoutInMs;\r
+  private RestAuthenticationMode authenticationMode;\r
+  private String basicAuthUsername;\r
+  private String basicAuthPassword;\r
 \r
   /**\r
    * Rest Client Builder.\r
 \r
   /**\r
    * Rest Client Builder.\r
@@ -88,6 +88,9 @@ public class RestClientBuilder {
     truststoreFilename = DEFAULT_TRUST_STORE_FILENAME;\r
     connectTimeoutInMs = DEFAULT_CONNECT_TIMEOUT_MS;\r
     readTimeoutInMs = DEFAULT_READ_TIMEOUT_MS;\r
     truststoreFilename = DEFAULT_TRUST_STORE_FILENAME;\r
     connectTimeoutInMs = DEFAULT_CONNECT_TIMEOUT_MS;\r
     readTimeoutInMs = DEFAULT_READ_TIMEOUT_MS;\r
+    authenticationMode = RestAuthenticationMode.HTTP_NOAUTH;\r
+    basicAuthUsername = DEFAULT_BASIC_AUTH_USERNAME;\r
+    basicAuthPassword = DEFAULT_BASIC_AUTH_PASSWORD;\r
   }\r
 \r
   public boolean isValidateServerHostname() {\r
   }\r
 \r
   public boolean isValidateServerHostname() {\r
@@ -146,13 +149,50 @@ public class RestClientBuilder {
     this.readTimeoutInMs = readTimeoutInMs;\r
   }\r
 \r
     this.readTimeoutInMs = readTimeoutInMs;\r
   }\r
 \r
+\r
+\r
+  public RestAuthenticationMode getAuthenticationMode() {\r
+    return authenticationMode;\r
+  }\r
+\r
+  public void setAuthenticationMode(RestAuthenticationMode authenticationMode) {\r
+    this.authenticationMode = authenticationMode;\r
+  }\r
+\r
+  public String getBasicAuthUsername() {\r
+    return basicAuthUsername;\r
+  }\r
+\r
+  public void setBasicAuthUsername(String basicAuthUsername) {\r
+    this.basicAuthUsername = basicAuthUsername;\r
+  }\r
+\r
+  public String getBasicAuthPassword() {\r
+    return basicAuthPassword;\r
+  }\r
+\r
+  public void setBasicAuthPassword(String basicAuthPassword) {\r
+    this.basicAuthPassword = basicAuthPassword;\r
+  }\r
+\r
   /**\r
   /**\r
-   * Returns Client.\r
+   * Returns Client configured for SSL\r
    */\r
   public Client getClient() throws Exception {\r
 \r
    */\r
   public Client getClient() throws Exception {\r
 \r
-    ClientConfig clientConfig = new DefaultClientConfig();\r
+    switch (authenticationMode) {\r
+      case SSL_BASIC:\r
+      case SSL_CERT:\r
+        return getClient(true);\r
 \r
 \r
+      default:\r
+        // return basic non-authenticating HTTP client\r
+        return getClient(false);\r
+    }\r
+\r
+  }\r
+\r
+  protected void setupSecureSocketLayerClientConfig(ClientConfig clientConfig) throws Exception {\r
     // Check to see if we need to perform proper validation of\r
     // the certificate chains.\r
     TrustManager[] trustAllCerts = null;\r
     // Check to see if we need to perform proper validation of\r
     // the certificate chains.\r
     TrustManager[] trustAllCerts = null;\r
@@ -201,7 +241,6 @@ public class RestClientBuilder {
       ctx.init(null, trustAllCerts, null);\r
     }\r
 \r
       ctx.init(null, trustAllCerts, null);\r
     }\r
 \r
-\r
     // Are we performing validation of the server host name?\r
     if (validateServerHostname) {\r
       clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
     // Are we performing validation of the server host name?\r
     if (validateServerHostname) {\r
       clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
@@ -216,6 +255,21 @@ public class RestClientBuilder {
             }\r
           }, ctx));\r
     }\r
             }\r
           }, ctx));\r
     }\r
+  }\r
+\r
+\r
+  /**\r
+   * Returns client instance\r
+   * \r
+   * @param useSsl - used to configure the client with an ssl-context or just plain http\r
+   */\r
+  protected Client getClient(boolean useSsl) throws Exception {\r
+\r
+    ClientConfig clientConfig = new DefaultClientConfig();\r
+\r
+    if (useSsl) {\r
+      setupSecureSocketLayerClientConfig(clientConfig);\r
+    }\r
 \r
     // Finally, create and initialize our client...\r
     Client client = null;\r
 \r
     // Finally, create and initialize our client...\r
     Client client = null;\r
@@ -226,4 +280,34 @@ public class RestClientBuilder {
     // ...and return it to the caller.\r
     return client;\r
   }\r
     // ...and return it to the caller.\r
     return client;\r
   }\r
+\r
+  public String getBasicAuthenticationCredentials() {\r
+\r
+    String usernameAndPassword = getBasicAuthUsername() + ":" + getBasicAuthPassword();\r
+    return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());\r
+  }\r
+\r
+  /* \r
+   * Added a little bit of logic to obfuscate passwords that could be logged out\r
+   * (non-Javadoc)\r
+   * @see java.lang.Object#toString()\r
+   */\r
+  @Override\r
+  public String toString() {\r
+    return "RestClientBuilder [validateServerHostname=" + validateServerHostname\r
+        + ", validateServerCertChain=" + validateServerCertChain + ", "\r
+        + (clientCertFileName != null ? "clientCertFileName=" + clientCertFileName + ", " : "")\r
+        + (clientCertPassword != null\r
+            ? "clientCertPassword="\r
+                + java.util.Base64.getEncoder().encodeToString(clientCertPassword.getBytes()) + ", "\r
+            : "")\r
+        + (truststoreFilename != null ? "truststoreFilename=" + truststoreFilename + ", " : "")\r
+        + "connectTimeoutInMs=" + connectTimeoutInMs + ", readTimeoutInMs=" + readTimeoutInMs + ", "\r
+        + (authenticationMode != null ? "authenticationMode=" + authenticationMode + ", " : "")\r
+        + (basicAuthUsername != null ? "basicAuthUsername=" + basicAuthUsername + ", " : "")\r
+        + (basicAuthPassword != null ? "basicAuthPassword="\r
+            + java.util.Base64.getEncoder().encodeToString(basicAuthPassword.getBytes()) : "")\r
+        + "]";\r
+  }\r
+\r
 }\r
 }\r
index 9df0764..75d2b8d 100644 (file)
@@ -55,3 +55,7 @@ HTTP_REQUEST_ERROR=\
 HEALTH_CHECK_FAILURE=\
     AC2003E|\
     Failed to establish connection to {0} at {1}. Cause {2}
 HEALTH_CHECK_FAILURE=\
     AC2003E|\
     Failed to establish connection to {0} at {1}. Cause {2}
+    
+CLIENT_INITIALIZATION_FAILURE=\
+    AC2004E|\
+    Failure to initialize rest client. Cause {0}    
diff --git a/src/test/java/org/openecomp/restclient/client/OperationResultTest.java b/src/test/java/org/openecomp/restclient/client/OperationResultTest.java
new file mode 100644 (file)
index 0000000..df85877
--- /dev/null
@@ -0,0 +1,83 @@
+package org.openecomp.restclient.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+public class OperationResultTest {
+
+  /**
+   * Test case initialization
+   * 
+   * @throws Exception the exception
+   */
+  @Before
+  public void init() throws Exception {
+  }
+  
+  @Test
+  public void validateConstruction() {
+    
+    OperationResult opResult = new OperationResult();
+    assertEquals(opResult.getNumRetries(),0);
+    assertFalse(opResult.isFromCache());
+    assertFalse(opResult.wasSuccessful());
+    opResult.setResultCode(612);
+    assertFalse(opResult.wasSuccessful());
+    assertNull(opResult.getHeaders());
+    
+    opResult = new OperationResult(204,"no content found");
+    assertEquals(opResult.getResultCode(),204);
+    assertEquals(opResult.getResult(),"no content found");
+    assertTrue(opResult.wasSuccessful());
+    
+    MultivaluedMap<String,String> multiMap = new MultivaluedMapImpl();
+    multiMap.add("p1","v1");
+    multiMap.add("p2","v2");
+    opResult.setHeaders(multiMap);
+    assertNotNull(opResult.getHeaders());
+    assertEquals(opResult.getHeaders().size(), 2);
+    
+  }
+  
+  @Test
+  public void validateAccesors() {
+    
+    OperationResult opResult = new OperationResult();
+    
+    opResult.setFailureCause("failure");
+    opResult.setFromCache(false);
+    opResult.setNumRetries(101);
+    opResult.setRequestedLink("http://localhost:1234");
+    opResult.setResult("result");
+    opResult.setResultCode(555);
+
+    assertEquals(opResult.getFailureCause(), "failure");
+    assertFalse(opResult.isFromCache());
+    assertEquals(opResult.getNumRetries(),101);
+    assertEquals(opResult.getRequestedLink(),"http://localhost:1234");
+    assertEquals(opResult.getResult(), "result");
+    assertEquals(opResult.getResultCode(),555);
+    
+    opResult.setResult(212, "mostly successful");
+    assertEquals(opResult.getResultCode(),212);
+    assertEquals(opResult.getResult(), "mostly successful");
+    
+    assertTrue(opResult.toString().contains("OperationResult"));
+    
+    opResult.setFailureCause(511, "things melting");
+    assertEquals(opResult.getResultCode(),511);
+    assertEquals(opResult.getFailureCause(), "things melting");
+    
+  }
+    
+}
diff --git a/src/test/java/org/openecomp/restclient/client/RESTClientTest.java b/src/test/java/org/openecomp/restclient/client/RESTClientTest.java
deleted file mode 100644 (file)
index b049c38..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-package org.openecomp.restclient.client;\r
-\r
-import org.junit.Before;\r
-import org.junit.Test;\r
-import org.openecomp.restclient.client.OperationResult;\r
-import org.openecomp.restclient.client.RestClient;\r
-import org.openecomp.restclient.rest.RestClientBuilder;\r
-\r
-import static org.junit.Assert.assertTrue;\r
-import static org.junit.Assert.assertNull;\r
-import static org.junit.Assert.assertEquals;\r
-\r
-import javax.ws.rs.GET;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.core.MediaType;\r
-\r
-import com.sun.jersey.test.framework.AppDescriptor;\r
-import com.sun.jersey.test.framework.JerseyTest;\r
-import com.sun.jersey.test.framework.WebAppDescriptor;\r
-\r
-import com.sun.jersey.api.client.Client;\r
-\r
-\r
-/**\r
- * This suite of tests is intended to exercise the behaviour of the {@link RestClient}.\r
- */\r
-public class RESTClientTest extends JerseyTest {\r
-\r
-  private static final String GOOD_AAI_ENDPOINT = "testaai/good";\r
-  private static final String FAIL_ALWAYS_AAI_ENDPOINT = "testaai/failalways";\r
-  private static final String FAIL_THEN_SUCCEED_ENDPOINT = "testaai/failthensucceed";\r
-  private static final String INVALID_AAI_ENDPOINT = "testaai/bad";\r
-\r
-  private static final String AAI_GET_REPLY_PAYLOAD = "Reply from AAI";\r
-\r
-  private static final int SUCCESS_RESULT_CODE = 200;\r
-  private static final int INVALID_END_POINT_RESULT_CODE = 404;\r
-  private static final int INTERNAL_ERR_RESULT_CODE = 500;\r
-  private static final int TIMEOUT_RESULT_CODE = 504;\r
-\r
-\r
-  /**\r
-   * Creates a new instance of the {@link RESTClientTest} test suite.\r
-   */\r
-  public RESTClientTest() throws Exception {\r
-\r
-    // Tell our in memory container to look here for resource endpoints.\r
-    super("org.openecomp.restclient.client");\r
-  }\r
-\r
-\r
-  @Override\r
-  protected AppDescriptor configure() {\r
-    return new WebAppDescriptor.Builder().build();\r
-  }\r
-\r
-\r
-  /**\r
-   * Perform common initialization actions that need to run before every unit test.\r
-   */\r
-  @Before\r
-  public void setup() {\r
-\r
-    // Initialize our test endpoints to make sure that all of their\r
-    // counters have valid starting values\r
-    AAI_FailAlways_Stub.initialize();\r
-    AAI_FailThenSucceed_Stub.initialize();\r
-  }\r
-\r
-\r
-  /**\r
-   * This test validates that all of the {@link RestClient}'s configurable parameters can be set via\r
-   * its fluent interface and that those values are successfully passed down to the underlying\r
-   * {@link RestClientBuilder} instance.\r
-   */\r
-  @Test\r
-  public void configureAAIClientTest() {\r
-\r
-    final boolean VALIDATE_SERVER = true;\r
-    final boolean VALIDATE_CERT_CHAIN = true;\r
-    final String CLIENT_CERT_FILE = "myCertFile";\r
-    final String CLIENT_CERT_PASSWORD = "My voice is my password";\r
-    final String TRUST_STORE = "myTrustStore";\r
-    final int CONNECT_TIMEOUT = 5000;\r
-    final int READ_TIMEOUT = 5000;\r
-\r
-    // Create an instance of our test version of the REST client builder.\r
-    TestRestClientBuilder clientBuilder = new TestRestClientBuilder();\r
-\r
-    // Now, create a new instance of the {@link AAIClient} and configure\r
-    // its parameters.\r
-    RestClient testClient =\r
-        new RestClient(clientBuilder).validateServerHostname(true).validateServerCertChain(true)\r
-            .clientCertFile("myCertFile").clientCertPassword("My voice is my password")\r
-            .trustStore("myTrustStore").connectTimeoutMs(5000).readTimeoutMs(5000);\r
-\r
-    // Validate that the parameters of the test REST client builder that\r
-    // we passed to the AAI client have been set according to what we\r
-    // passed in when we instantiated the AAI client.\r
-    assertEquals("Unexpected 'validate server host name' value", VALIDATE_SERVER,\r
-        clientBuilder.isValidateServerHostname());\r
-    assertEquals("Unexpected 'validate certificat chain' value", VALIDATE_CERT_CHAIN,\r
-        clientBuilder.isValidateServerCertChain());\r
-    assertTrue("Unexpected client certificate filename",\r
-        CLIENT_CERT_FILE.equals(clientBuilder.getClientCertFileName()));\r
-    assertTrue("Unexpected client certificate password",\r
-        CLIENT_CERT_PASSWORD.equals(clientBuilder.getClientCertPassword()));\r
-    assertTrue("Unexpected trust store filename",\r
-        TRUST_STORE.equals(clientBuilder.getTruststoreFilename()));\r
-    assertEquals("Unexpected connection timeout value", CONNECT_TIMEOUT,\r
-        clientBuilder.getConnectTimeoutInMs());\r
-    assertEquals("Unexpected read timeout value", READ_TIMEOUT, clientBuilder.getReadTimeoutInMs());\r
-  }\r
-\r
-\r
-  /**\r
-   * This test validates that the {@link RestClient} can submit a GET request to a valid REST\r
-   * endpoint and receive a valid response.\r
-   */\r
-  @Test\r
-  public void queryAAI_SuccessTest() {\r
-\r
-    // Create an instance of the AAIClient that uses our test version of\r
-    // the REST client builder.\r
-    RestClient testClient = new RestClient(new TestRestClientBuilder());\r
-\r
-    // Query our stubbed out AAI with a URL that we expecte to get a successful\r
-    // reply from.\r
-    OperationResult or =\r
-        testClient.get(getBaseURI() + GOOD_AAI_ENDPOINT, null, MediaType.APPLICATION_JSON_TYPE);\r
-\r
-    // Validate that a successful query returns a result code of 200.\r
-    assertEquals("Unexpected result code", SUCCESS_RESULT_CODE, or.getResultCode());\r
-\r
-    // Validate that no error cause gets set on a successful query.\r
-    assertNull("Operation result failure code should not be set for successful GET",\r
-        or.getFailureCause());\r
-\r
-    // Validate that our query returned the expected payload from our dummy\r
-    // AAI.\r
-    assertTrue("Incorrect payload returned from AAI query",\r
-        AAI_GET_REPLY_PAYLOAD.equals(or.getResult()));\r
-  }\r
-\r
-\r
-  /**\r
-   * This test validates that the {@link RestClient} behaves as expected when query requests are\r
-   * unsuccessful.\r
-   * <p>\r
-   * Specifically, the following scenarios are covered:<br>\r
-   * 1) Submitting a GET request to an invalid REST endpoint 2) Submitting a GET request to a valid\r
-   * endpoint which throws an error rather than replying successfully.\r
-   * <p>\r
-   * Note that this test exercises the 'single attempt' variant of the query method.\r
-   */\r
-  @Test\r
-  public void queryAAI_FailureTest() {\r
-\r
-    // Create an instance of the AAIClient that uses our test version of\r
-    // the REST client builder.\r
-    RestClient testClient = new RestClient(new TestRestClientBuilder());\r
-\r
-    // Query our stubbed out AAI with a URL that we expecte to get a successful\r
-    // reply from.\r
-    OperationResult or =\r
-        testClient.get(getBaseURI() + INVALID_AAI_ENDPOINT, null, MediaType.APPLICATION_JSON_TYPE);\r
-\r
-    // Validate that an attempt to query a non-existing endpoint results in\r
-    // a 404 error.\r
-    assertEquals("Unexpected result code", INVALID_END_POINT_RESULT_CODE, or.getResultCode());\r
-\r
-    // Validate that no payload was set since the query failed.\r
-    assertNull("Payload should not be set on 404 error", or.getResult());\r
-\r
-    // Now, submit a query request to the stubbed AAI.\r
-    or = testClient.get(getBaseURI() + FAIL_ALWAYS_AAI_ENDPOINT, null,\r
-        MediaType.APPLICATION_JSON_TYPE);\r
-\r
-    // Validate that a query to a avalid returns a result code of 500.\r
-    assertEquals("Unexpected result code", INTERNAL_ERR_RESULT_CODE, or.getResultCode());\r
-  }\r
-\r
-\r
-  /**\r
-   * This test validates the behaviour of querying the AAI with a number of retries requested in the\r
-   * case where we never get a successful reply.\r
-   */\r
-  @Test\r
-  public void queryAAIWithRetries_TimeoutTest() {\r
-\r
-    int NUM_RETRIES = 3;\r
-\r
-\r
-    // Create an instance of the AAIClient that uses our test version of\r
-    // the REST client builder.\r
-    RestClient testClient = new RestClient(new TestRestClientBuilder());\r
-\r
-    // Initialize our test endpoint to make sure that all of its\r
-    // counters have valid starting values\r
-    // AAI_FailAlways_Stub.initialize();\r
-\r
-    // Perform a query against the stubbed AAI, specifying a number of times\r
-    // to retry in the event of an error.\r
-    OperationResult or = testClient.get(getBaseURI() + FAIL_ALWAYS_AAI_ENDPOINT, null,\r
-        MediaType.APPLICATION_JSON_TYPE, NUM_RETRIES);\r
-\r
-    // Validate that failing for all of our retry attempts results in a\r
-    // 504 error.\r
-    assertEquals("Unexpected result code", TIMEOUT_RESULT_CODE, or.getResultCode());\r
-\r
-    // Validate that our stubbed AAI actually received the expected number\r
-    // of retried requests.\r
-    assertEquals("Unexpected number of retries", NUM_RETRIES, AAI_FailAlways_Stub.getCount);\r
-  }\r
-\r
-\r
-  /**\r
-   * This test validates the behaviour of querying the AAI with a number of retries requested in the\r
-   * case where our query initially fails but then succeeds on one of the subsequent retries.\r
-   */\r
-  @Test\r
-  public void queryAAIWithRetries_FailThenSucceedTest() {\r
-\r
-    int num_retries = AAI_FailThenSucceed_Stub.MAX_FAILURES + 2;\r
-\r
-    // Create an instance of the AAIClient that uses our test version of\r
-    // the REST client builder.\r
-    RestClient testClient = new RestClient(new TestRestClientBuilder());\r
-\r
-    // Initialize our test endpoint to make sure that all of its\r
-    // counters have valid starting values.\r
-    // AAI_FailThenSucceed_Stub.initialize();\r
-\r
-    // Perform a query against the stubbed AAI, specifying a number of times\r
-    // to retry in the event of an error.\r
-    OperationResult or = testClient.get(getBaseURI() + FAIL_THEN_SUCCEED_ENDPOINT, null,\r
-        MediaType.APPLICATION_JSON_TYPE, num_retries);\r
-\r
-    // Validate that after failing a few attempts we finally got back a\r
-    // success code.\r
-    assertEquals("Unexpected result code", SUCCESS_RESULT_CODE, or.getResultCode());\r
-\r
-    // Validate that our stubbed AAI actually received the expected number\r
-    // of retried requests.\r
-    assertEquals("Unexpected number of retries", AAI_FailThenSucceed_Stub.MAX_FAILURES + 1,\r
-        AAI_FailThenSucceed_Stub.getCount);\r
-  }\r
-\r
-\r
-  /**\r
-   * This class provides a simple in-memory REST end point to stand in for a real AAI.\r
-   * <p>\r
-   * This endpoint always returns a valid reply to a GET request and is used for success path\r
-   * testing.\r
-   */\r
-  @Path(GOOD_AAI_ENDPOINT)\r
-  public static class AAI_Success_Stub {\r
-\r
-    /**\r
-     * This is the end point for GET requests. It just returns a simple, pre-canned response\r
-     * payload.\r
-     * \r
-     * @return - A pre-canned response.\r
-     */\r
-    @GET\r
-    public String getEndpoint() {\r
-      return AAI_GET_REPLY_PAYLOAD;\r
-    }\r
-  }\r
-\r
-\r
-  /**\r
-   * This class provides a simple in-memory REST end point to stand in for a real AAI.\r
-   * <p>\r
-   * This endpoint always returns throws an error instead of responding successfully and is used for\r
-   * certain failure path tests.\r
-   */\r
-  @Path(FAIL_ALWAYS_AAI_ENDPOINT)\r
-  public static class AAI_FailAlways_Stub {\r
-\r
-    /**\r
-     * Maintains a running count of the number of GET requests that have been received.\r
-     */\r
-    public static int getCount;\r
-\r
-\r
-    /**\r
-     * Resets all of the endpoints counters.\r
-     */\r
-    public static void initialize() {\r
-      getCount = 0;\r
-    }\r
-\r
-\r
-    /**\r
-     * This is the end point for GET requests. It just throws an error instead of returning a valid\r
-     * response.\r
-     * \r
-     * @return - NONE. We actually throw an exception intentionally instead of returning.\r
-     */\r
-    @GET\r
-    public String getEndpoint() {\r
-\r
-      // Keep track of the number of get requests that we have received\r
-      // so that this value can be used for validation purposes later.\r
-      getCount++;\r
-\r
-      // Always just throw an error instead of replying successfully.\r
-      throw new UnsupportedOperationException("Intentional Failure");\r
-    }\r
-  }\r
-\r
-\r
-  /**\r
-   * This class provides a simple in-memory REST end point to stand in for a real AAI.\r
-   * <p>\r
-   * This end point will throw errors instead of responding for a certain number of requests, after\r
-   * which it will return a valid, pre-canned response.\r
-   * \r
-   * @return - A pre-canned response.\r
-   */\r
-  @Path(FAIL_THEN_SUCCEED_ENDPOINT)\r
-  public static class AAI_FailThenSucceed_Stub {\r
-\r
-    /**\r
-     * The number of requests for which we should throw errors before responding successfully.\r
-     */\r
-    public static int MAX_FAILURES = 2;\r
-\r
-    /**\r
-     * Maintains a running count of the number of GET requests that have been received.\r
-     */\r
-    public static int getCount;\r
-\r
-    /**\r
-     * Maintains a running count of the number of requests which we have failed, so that we will\r
-     * know when to stop failing and return a valid response.\r
-     */\r
-    private static int failCount;\r
-\r
-\r
-    /**\r
-     * Resets all of the endpoints counters.\r
-     */\r
-    public static void initialize() {\r
-      getCount = 0;\r
-      failCount = 0;\r
-    }\r
-\r
-\r
-    /**\r
-     * This is the end point for GET requests. It will throw errors for a certain number of requests\r
-     * and then return a valid response.\r
-     * \r
-     * @return - A pre-canned response string.\r
-     */\r
-    @GET\r
-    public String getEndpoint() {\r
-\r
-      // Keep track of the number of get requests that we have received\r
-      // so that this value can be used for validation purposes later.\r
-      getCount++;\r
-\r
-      // We only want to fail a set number of times, so check now to\r
-      // see what we should do.\r
-      if (failCount < MAX_FAILURES) {\r
-        failCount++;\r
-        throw new UnsupportedOperationException("Intentional Failure");\r
-\r
-      } else {\r
-        // We've failed as often as we need to. Time to reply\r
-        // successfully.\r
-        failCount = 0;\r
-        return AAI_GET_REPLY_PAYLOAD;\r
-      }\r
-    }\r
-  }\r
-\r
-\r
-  /**\r
-   * This class overrides the behaviour of the {@link RestClientBuilder} used by the\r
-   * {@link RestClient} to just return the in memory client provided by the JerseyTest framework.\r
-   */\r
-  private class TestRestClientBuilder extends RestClientBuilder {\r
-\r
-    @Override\r
-    public Client getClient() throws Exception {\r
-      return client();\r
-    }\r
-  }\r
-}\r
diff --git a/src/test/java/org/openecomp/restclient/client/RestfulClientTest.java b/src/test/java/org/openecomp/restclient/client/RestfulClientTest.java
new file mode 100644 (file)
index 0000000..c116482
--- /dev/null
@@ -0,0 +1,721 @@
+package org.openecomp.restclient.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.openecomp.restclient.enums.RestAuthenticationMode;
+import org.openecomp.restclient.rest.RestClientBuilder;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+
+public class RestfulClientTest {
+
+  private RestClientBuilder mockClientBuilder;
+  private Client mockedClient;
+  
+  /**
+   * Test case initialization
+   * 
+   * @throws Exception the exception
+   */
+  @Before
+  public void init() throws Exception {
+    mockClientBuilder = Mockito.mock( RestClientBuilder.class );
+    mockedClient = Mockito.mock( Client.class );
+  }
+  
+  @Test
+  public void validateConstructors() {
+    
+    RestClient restClient = new RestClient();
+    assertNotNull(restClient);
+    
+    restClient = null;
+    restClient = new RestClient( mockClientBuilder );
+    assertNotNull(restClient);
+    
+  }
+  
+  @Test
+  public void validateBasicClientConstruction() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    RestClient restClient = new RestClient( mockClientBuilder );
+    assertNotNull(restClient);
+    
+    Client client = restClient.authenticationMode(RestAuthenticationMode.HTTP_NOAUTH)
+        .connectTimeoutMs(1000).readTimeoutMs(500).getClient();
+   
+    assertNotNull(client);
+    
+  }
+  
+  @Test
+  public void validateClientWithSslBasicAuthConstruction() throws Exception {
+
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    RestClient restClient = new RestClient( mockClientBuilder );
+    assertNotNull(restClient);
+    
+    Client client = restClient.authenticationMode(RestAuthenticationMode.SSL_BASIC)
+        .connectTimeoutMs(1000).readTimeoutMs(500).basicAuthPassword("password")
+        .basicAuthUsername("username").getClient();
+   
+    assertNotNull(client);
+    
+  }
+  
+  @Test
+  public void validateClientWithSslCertConstruction() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    RestClient restClient = new RestClient( mockClientBuilder );
+    assertNotNull(restClient);
+    
+    Client client =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password").getClient();
+   
+    assertNotNull(client);
+    
+    client = null;
+    client = restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+        .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password")
+        .validateServerCertChain(true).validateServerHostname(true).getClient();
+
+    assertNotNull(client);
+
+    client = null;
+    client = restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+        .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password")
+        .trustStore("truststore").getClient();
+
+    assertNotNull(client);
+    
+  }
+  
+  @Test
+  public void validateSuccessfulPut() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.put(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(200);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result = restClient.put("http://localhost:9000/aai/v7", "", headers, MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
+    
+    assertEquals(200, result.getResultCode());
+    assertNotNull(result.getResult());
+    assertNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateSuccessfulPost() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.post(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(200);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result = restClient.post("http://localhost:9000/aai/v7", "", headers, MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
+    
+    assertEquals(200, result.getResultCode());
+    assertNotNull(result.getResult());
+    assertNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateSuccessfulGet() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(200);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result =
+        restClient.get("http://localhost:9000/aai/v7", headers, MediaType.APPLICATION_JSON_TYPE);
+    
+    assertEquals(200, result.getResultCode());
+    assertNotNull(result.getResult());
+    assertNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateSuccessfulGetWithBasicAuth() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(200);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_BASIC).connectTimeoutMs(1000)
+            .readTimeoutMs(500).basicAuthUsername("username").basicAuthUsername("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result =
+        restClient.get("http://localhost:9000/aai/v7", headers, MediaType.APPLICATION_JSON_TYPE);
+    
+    assertEquals(200, result.getResultCode());
+    assertNotNull(result.getResult());
+    assertNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateResourceNotFoundGet() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(404);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("RNF");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result =
+        restClient.get("http://localhost:9000/aai/v7", headers, MediaType.APPLICATION_JSON_TYPE);
+    
+    assertEquals(404, result.getResultCode());
+    assertNull(result.getResult());
+    assertNotNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateHealthCheck() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(200);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    boolean targetServiceHealthy =
+        restClient.healthCheck("http://localhost:9000/aai/util/echo", "startSerice", "targetService");
+    
+    assertEquals(true, targetServiceHealthy);
+    
+  }
+  
+  @Test
+  public void validateHealthCheckFailureWith403() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(403);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    boolean targetServiceHealthy =
+        restClient.healthCheck("http://localhost:9000/aai/util/echo", "startSerice", "targetService");
+    
+    assertEquals(false, targetServiceHealthy);
+    
+  }
+  
+  @Test
+  public void validateHealthCheckFailureWithThrownException() throws Exception {
+
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenThrow(new IllegalArgumentException("error"));
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+/*    Mockito.when(mockedClientResponse.getStatus()).thenReturn(403);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());*/
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    boolean targetServiceHealthy =
+        restClient.healthCheck("http://localhost:9000/aai/util/echo", "startSerice", "targetService");
+    
+    assertEquals(false, targetServiceHealthy);
+    
+  }
+  @Test  
+  public void validateSuccessfulGetWithRetries() throws Exception {
+    
+    RestClientBuilder myClientBuilder = Mockito.mock(RestClientBuilder.class);
+    Client myClient = Mockito.mock(Client.class);
+    
+    Mockito.when(myClientBuilder.getClient()).thenReturn(myClient).thenReturn(myClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( myClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    
+    /*
+     * Finally the elements we want to validate
+     */
+
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(408).thenReturn(200);
+
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("error").thenReturn("ok");
+    
+    MultivaluedMap<String, String> emptyHeaderMap = new MultivaluedMapImpl();
+    
+    // Mockito is smart, the last recorded thenReturn is repeated successively
+    // for all subsequent calls to the method.
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(emptyHeaderMap);
+
+    RestClient restClient = new RestClient( myClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result =
+        restClient.get("http://localhost:9000/aai/v7", headers, MediaType.APPLICATION_JSON_TYPE, 3);
+    
+    assertEquals(200, result.getResultCode());
+    assertNotNull(result.getResult());
+    assertNull(result.getFailureCause());
+    
+  }
+  
+  
+  @Test  
+  public void validateFailedGetWithRetriesCausedByResourceNotFound() throws Exception {
+    
+    RestClientBuilder myClientBuilder = Mockito.mock(RestClientBuilder.class);
+    Client myClient = Mockito.mock(Client.class);
+    
+    Mockito.when(myClientBuilder.getClient()).thenReturn(myClient).thenReturn(myClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( myClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    
+    /*
+     * Finally the elements we want to validate
+     */
+
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(404);
+
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("error").thenReturn("ok");
+    
+    MultivaluedMap<String, String> emptyHeaderMap = new MultivaluedMapImpl();
+    
+    // Mockito is smart, the last recorded thenReturn is repeated successively
+    // for all subsequent calls to the method.
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(emptyHeaderMap);
+
+    RestClient restClient = new RestClient( myClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result =
+        restClient.get("http://localhost:9000/aai/v7", headers, MediaType.APPLICATION_JSON_TYPE, 3);
+    
+    assertEquals(404, result.getResultCode());
+    assertNull(result.getResult());
+    assertNotNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateFailedGetAfterMaxRetries() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    
+    Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(null);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(500).thenReturn(500).thenReturn(500);
+
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("error")
+        .thenReturn("error").thenReturn("error");
+    
+    MultivaluedMap<String, String> emptyHeaderMap = new MultivaluedMapImpl();
+    
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(emptyHeaderMap)
+        .thenReturn(emptyHeaderMap).thenReturn(emptyHeaderMap);
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result =
+        restClient.get("http://localhost:9000/aai/v7", headers, MediaType.APPLICATION_JSON_TYPE, 3);
+    
+    
+    assertEquals(504, result.getResultCode());
+    assertNull(result.getResult());
+    assertNotNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateSuccessfulDelete() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.delete(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(200);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result = restClient.delete("http://localhost:9000/aai/v7", headers, 
+        MediaType.APPLICATION_JSON_TYPE);
+    
+    assertEquals(200, result.getResultCode());
+    assertNotNull(result.getResult());
+    assertNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateSuccessfulHead() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.head()).thenReturn(mockedClientResponse);
+
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(200);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result =
+        restClient.head("http://localhost:9000/aai/v7", headers, MediaType.APPLICATION_JSON_TYPE);
+    
+    assertEquals(200, result.getResultCode());
+    assertNotNull(result.getResult());
+    assertNull(result.getFailureCause());
+    
+  }
+  
+  @Test
+  public void validateSuccessfulPatch() throws Exception {
+    
+    Mockito.when( mockClientBuilder.getClient() ).thenReturn(mockedClient);
+    
+    WebResource mockedWebResource = Mockito.mock(WebResource.class);
+    Builder mockedBuilder = Mockito.mock(Builder.class);
+    ClientResponse mockedClientResponse = Mockito.mock(ClientResponse.class);
+    
+    Mockito.when( mockedClient.resource(Mockito.anyString())).thenReturn( mockedWebResource );
+    Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn( mockedBuilder );
+    Mockito.when(mockedBuilder.post(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+    Mockito.when(mockedBuilder.header("X-HTTP-Method-Override", "PATCH")).thenReturn(mockedBuilder);
+    /*
+     * Finally the elements we want to validate
+     */
+    
+    Mockito.when(mockedClientResponse.getStatus()).thenReturn(200);
+    Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+    Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedMapImpl());
+
+    RestClient restClient = new RestClient( mockClientBuilder );
+    
+    assertNotNull(restClient);
+    
+    restClient =
+        restClient.authenticationMode(RestAuthenticationMode.SSL_CERT).connectTimeoutMs(1000)
+            .readTimeoutMs(500).clientCertFile("cert").clientCertPassword("password");
+    
+    assertNotNull(restClient);
+    
+    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+
+    OperationResult result = restClient.patch("http://localhost:9000/aai/v7", "", headers, MediaType.APPLICATION_JSON_TYPE,
+        MediaType.APPLICATION_JSON_TYPE);
+    
+    assertEquals(200, result.getResultCode());
+    assertNotNull(result.getResult());
+    assertNull(result.getFailureCause());
+    
+  }
+    
+}
diff --git a/src/test/java/org/openecomp/restclient/enums/RestAuthenticationModeTest.java b/src/test/java/org/openecomp/restclient/enums/RestAuthenticationModeTest.java
new file mode 100644 (file)
index 0000000..f4b280b
--- /dev/null
@@ -0,0 +1,33 @@
+package org.openecomp.restclient.enums;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class RestAuthenticationModeTest {
+
+  /**
+   * Test case initialization
+   * 
+   * @throws Exception the exception
+   */
+  @Before
+  public void init() throws Exception {
+  }
+  
+  @Test
+  public void validateEnumMappings() {
+    
+    assertEquals(RestAuthenticationMode.getRestAuthenticationMode(null), RestAuthenticationMode.UNKNOWN_MODE);
+    assertEquals(RestAuthenticationMode.getRestAuthenticationMode("OAuth"), RestAuthenticationMode.UNKNOWN_MODE);
+    assertEquals(RestAuthenticationMode.getRestAuthenticationMode("SSL_BASIC"), RestAuthenticationMode.SSL_BASIC);
+    assertEquals(RestAuthenticationMode.getRestAuthenticationMode("SSL_CERT"), RestAuthenticationMode.SSL_CERT);
+    assertEquals(RestAuthenticationMode.getRestAuthenticationMode("HTTP_NOAUTH"), RestAuthenticationMode.HTTP_NOAUTH);
+    
+    assertEquals(RestAuthenticationMode.SSL_BASIC.getAuthenticationModeLabel(),"SSL_BASIC");
+    
+    
+  }
+    
+}
diff --git a/src/test/java/org/openecomp/restclient/rest/HttpUtilTest.java b/src/test/java/org/openecomp/restclient/rest/HttpUtilTest.java
new file mode 100644 (file)
index 0000000..d1d88ea
--- /dev/null
@@ -0,0 +1,51 @@
+package org.openecomp.restclient.rest;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class HttpUtilTest {
+
+  /**
+   * Test case initialization
+   * 
+   * @throws Exception the exception
+   */
+  @Before
+  public void init() throws Exception {
+  }
+  
+  @Test
+  public void validateAccesors() {
+    
+    assertFalse(HttpUtil.isHttpResponseClassInformational(-1));
+    assertFalse(HttpUtil.isHttpResponseClassInformational(99));
+    assertTrue(HttpUtil.isHttpResponseClassInformational(183));
+    assertFalse(HttpUtil.isHttpResponseClassInformational(200));
+
+    assertFalse(HttpUtil.isHttpResponseClassSuccess(199));
+    assertTrue(HttpUtil.isHttpResponseClassSuccess(202));
+    assertFalse(HttpUtil.isHttpResponseClassSuccess(300));
+
+    assertFalse(HttpUtil.isHttpResponseClassRedirection(299));
+    assertTrue(HttpUtil.isHttpResponseClassRedirection(307));
+    assertFalse(HttpUtil.isHttpResponseClassRedirection(401));
+
+    assertFalse(HttpUtil.isHttpResponseClassClientError(399));
+    assertTrue(HttpUtil.isHttpResponseClassClientError(404));
+    assertFalse(HttpUtil.isHttpResponseClassClientError(555));
+
+    assertFalse(HttpUtil.isHttpResponseClassServerError(499));
+    assertTrue(HttpUtil.isHttpResponseClassServerError(504));
+    assertFalse(HttpUtil.isHttpResponseClassServerError(662));
+    
+    int[] successCodes = { 201, 202, 205, 299 };
+    
+    assertTrue(HttpUtil.isHttpResponseInList(201, successCodes));
+    assertFalse(HttpUtil.isHttpResponseInList(301, successCodes));
+    
+  }
+    
+}
index 93e5520..e299e36 100644 (file)
@@ -1,18 +1,18 @@
 package org.openecomp.restclient.rest;\r
 \r
 package org.openecomp.restclient.rest;\r
 \r
-import java.util.Map;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertTrue;\r
+import static org.junit.Assert.fail;\r
 \r
 import org.junit.Before;\r
 import org.junit.Test;\r
 \r
 import org.junit.Before;\r
 import org.junit.Test;\r
-import org.openecomp.restclient.rest.RestClientBuilder;\r
-\r
-import static org.junit.Assert.*;\r
+import org.openecomp.restclient.enums.RestAuthenticationMode;\r
 \r
 import com.sun.jersey.api.client.Client;\r
 \r
 import com.sun.jersey.api.client.Client;\r
-\r
 import com.sun.jersey.client.urlconnection.HTTPSProperties;\r
 \r
 import com.sun.jersey.client.urlconnection.HTTPSProperties;\r
 \r
-\r
 /**\r
  * This suite of tests is intended to exercise the functionality of the generice REST client\r
  * builder.\r
 /**\r
  * This suite of tests is intended to exercise the functionality of the generice REST client\r
  * builder.\r
@@ -20,147 +20,231 @@ import com.sun.jersey.client.urlconnection.HTTPSProperties;
 public class RestClientBuilderTest {\r
 \r
   /**\r
 public class RestClientBuilderTest {\r
 \r
   /**\r
-   * This test validates that we can enable and disable certificate chain verification and that the\r
-   * associated parameters are correctly set.\r
+   * Test case initialization\r
+   * \r
+   * @throws Exception the exception\r
    */\r
    */\r
+  @Before\r
+  public void init() throws Exception {\r
+  }\r
+  \r
+  private String generateAuthorizationHeaderValue(String username, String password) {\r
+    String usernameAndPassword = username + ":" + password;\r
+    return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());\r
+  }\r
+  \r
   @Test\r
   @Test\r
-  public void certificateChainVerificationTest() throws Exception {\r
-\r
-    final String TRUST_STORE_FILENAME = "myTrustStore";\r
-\r
-\r
-    // Instantiate a RestClientBuilder with default parameters and\r
-    // get a client instance.\r
-    RestClientBuilder builder = new RestClientBuilder();\r
-    Client client = builder.getClient();\r
-\r
-    // Validate that, by default, no trust store has been set.\r
-    assertNull("Trust store filename should not be set for default builder",\r
-        System.getProperty("javax.net.ssl.trustStore"));\r
-\r
-    // Now, enable certificate chain verification, but don't specify\r
-    // a trust store filename.\r
-    builder.setValidateServerCertChain(true);\r
-\r
-    // Now, get a new client instance. We expect the builder to complain\r
-    // because there is no trust store filename.\r
-    try {\r
-      Client client2 = builder.getClient();\r
-      fail("Expected exception due to no trust store filename.");\r
-\r
-    } catch (IllegalArgumentException e) {\r
-      assertTrue(e.getMessage().contains("Trust store filename must be set"));\r
-    }\r
+  public void validateAccesors() {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    // test defaults\r
+    assertEquals(restClientBuilder.isValidateServerHostname(), RestClientBuilder.DEFAULT_VALIDATE_SERVER_HOST);\r
+    assertEquals(restClientBuilder.isValidateServerCertChain(), RestClientBuilder.DEFAULT_VALIDATE_CERT_CHAIN);\r
+    assertEquals(restClientBuilder.getClientCertFileName(), RestClientBuilder.DEFAULT_CLIENT_CERT_FILENAME);\r
+    assertEquals(restClientBuilder.getClientCertPassword(), RestClientBuilder.DEFAULT_CERT_PASSWORD);\r
+    assertEquals(restClientBuilder.getTruststoreFilename(), RestClientBuilder.DEFAULT_TRUST_STORE_FILENAME);\r
+    assertEquals(restClientBuilder.getConnectTimeoutInMs(), RestClientBuilder.DEFAULT_CONNECT_TIMEOUT_MS);\r
+    assertEquals(restClientBuilder.getReadTimeoutInMs(), RestClientBuilder.DEFAULT_READ_TIMEOUT_MS);\r
+    assertEquals(restClientBuilder.getAuthenticationMode(), RestClientBuilder.DEFAULT_AUTH_MODE);\r
+    assertEquals(restClientBuilder.getBasicAuthUsername(), RestClientBuilder.DEFAULT_BASIC_AUTH_USERNAME);\r
+    assertEquals(restClientBuilder.getBasicAuthPassword(), RestClientBuilder.DEFAULT_BASIC_AUTH_PASSWORD);\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.UNKNOWN_MODE);\r
+    restClientBuilder.setBasicAuthPassword("password");\r
+    restClientBuilder.setBasicAuthUsername("username");\r
+    restClientBuilder.setClientCertFileName("filename");\r
+    restClientBuilder.setClientCertPassword("password");\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    restClientBuilder.setTruststoreFilename("truststore");\r
+    restClientBuilder.setValidateServerCertChain(true);\r
+    restClientBuilder.setValidateServerHostname(true);\r
+    \r
+    assertEquals(restClientBuilder.isValidateServerHostname(), true);\r
+    assertEquals(restClientBuilder.isValidateServerCertChain(), true);\r
+    assertEquals(restClientBuilder.getClientCertFileName(), "filename");\r
+    assertEquals(restClientBuilder.getClientCertPassword(), "password");\r
+    assertEquals(restClientBuilder.getTruststoreFilename(), "truststore");\r
+    assertEquals(restClientBuilder.getConnectTimeoutInMs(), 12345);\r
+    assertEquals(restClientBuilder.getReadTimeoutInMs(), 54321);\r
+    assertEquals(restClientBuilder.getAuthenticationMode(), RestAuthenticationMode.UNKNOWN_MODE);\r
+    assertEquals(restClientBuilder.getBasicAuthUsername(), "username");\r
+    assertEquals(restClientBuilder.getBasicAuthPassword(), "password");\r
+    \r
+    assertEquals(restClientBuilder.getBasicAuthenticationCredentials(),\r
+        generateAuthorizationHeaderValue("username", "password"));\r
+\r
+    assertTrue(restClientBuilder.toString().contains("RestClientBuilder"));\r
 \r
 \r
-    // Now, set a value for the trust store filename and try again to\r
-    // get a client instance. This time it should succeed and we should\r
-    // see that our trust name filename was set.\r
-    builder.setTruststoreFilename(TRUST_STORE_FILENAME);\r
-    Client client3 = builder.getClient();\r
-\r
-    // Validate that the trust store filename was set.\r
-    assertNotNull("Expected trust store filename to be set",\r
-        System.getProperty("javax.net.ssl.trustStore"));\r
-\r
-    // Validate that the filename is set to the value we specified.\r
-    assertTrue(\r
-        "Unexpected trust store filename value " + System.getProperty("javax.net.ssl.trustStore"),\r
-        System.getProperty("javax.net.ssl.trustStore").equals(TRUST_STORE_FILENAME));\r
   }\r
   }\r
-\r
-\r
-  /**\r
-   * This test validates that we can set timeout values in our client builder and that those values\r
-   * are reflected in the client produced by the builder.\r
-   */\r
+  \r
   @Test\r
   @Test\r
-  public void timeoutValuesTest() throws Exception {\r
-\r
-    // Instantiate a RestClientBuilder with default parameters.\r
-    RestClientBuilder builder = new RestClientBuilder();\r
-\r
-    // Now, get a client instance and retrieve the client properties.\r
-    Client client = builder.getClient();\r
-\r
-    Map<String, Object> props = client.getProperties();\r
-\r
-    // Validate that the connection and read timeouts are set to the\r
-    // default values.\r
-    assertEquals("Unexpected connect timeout parameter",\r
-        props.get("com.sun.jersey.client.property.connectTimeout"),\r
-        RestClientBuilder.DEFAULT_CONNECT_TIMEOUT_MS);\r
-    assertEquals("Unexpected read timeout parameter",\r
-        props.get("com.sun.jersey.client.property.readTimeout"),\r
-        RestClientBuilder.DEFAULT_READ_TIMEOUT_MS);\r
-\r
-    // Now, change the timeouts in the builder to non-default values.\r
-    builder.setConnectTimeoutInMs(RestClientBuilder.DEFAULT_CONNECT_TIMEOUT_MS + 100);\r
-    builder.setReadTimeoutInMs(RestClientBuilder.DEFAULT_READ_TIMEOUT_MS + 100);\r
-\r
-    // Retrieve a new client instance and get the client properties.\r
-    Client client2 = builder.getClient();\r
-    props = client2.getProperties();\r
-\r
-    // Validate that the connection and read timeouts are set to the\r
-    // new values.\r
-    assertEquals("Unexpected connect timeout parameter",\r
-        props.get("com.sun.jersey.client.property.connectTimeout"),\r
-        RestClientBuilder.DEFAULT_CONNECT_TIMEOUT_MS + 100);\r
-    assertEquals("Unexpected read timeout parameter",\r
-        props.get("com.sun.jersey.client.property.readTimeout"),\r
-        RestClientBuilder.DEFAULT_READ_TIMEOUT_MS + 100);\r
+  public void validateNoAuthClientCreation() throws Exception {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.HTTP_NOAUTH);\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    \r
+    Client client = restClientBuilder.getClient();\r
+    assertNotNull(client);\r
+    assertNull(client.getProperties().get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES));\r
   }\r
   }\r
-\r
-\r
-  /**\r
-   * This test validates that we can enable and disable host name verification in the clients\r
-   * produced by our builder.\r
-   */\r
+  \r
+  \r
   @Test\r
   @Test\r
-  public void hostNameVerifierTest() throws Exception {\r
-\r
-    // Instantiate a RestClientBuilder with default parameters.\r
-    RestClientBuilder builder = new RestClientBuilder();\r
-\r
-    // Now, get a client instance.\r
-    Client client1 = builder.getClient();\r
-\r
-    // Retrieve the client's HTTPS properties.\r
-    HTTPSProperties httpProps = getHTTPSProperties(client1);\r
-\r
-    // By default, hostname verification should be disabled, which means\r
-    // that our builder will have injected its own {@link HostnameVerifier}\r
-    // which just always returns true.\r
-    assertNotNull(httpProps.getHostnameVerifier());\r
-\r
-    // Verify that the host name verifier returns true regardless of what\r
-    // hostname we pass in.\r
-    assertTrue("Default hostname verifier should always return true",\r
-        httpProps.getHostnameVerifier().verify("not_a_valid_hostname", null));\r
-\r
-\r
-    // Now, enable hostname verification for our client builder, and\r
-    // get a new client.\r
-    builder.setValidateServerHostname(true);\r
-    Client client2 = builder.getClient();\r
-\r
-    // Retrieve the client's HTTPS properties.\r
-    httpProps = getHTTPSProperties(client2);\r
-\r
-    // Verify that with hostname verification enabled, our builder did not\r
-    // insert its own stubbed verifier.\r
-    assertNull(httpProps.getHostnameVerifier());\r
+  public void validateUnknownModeCreateNoAuthClient() throws Exception {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.UNKNOWN_MODE);\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    \r
+    Client client = restClientBuilder.getClient();\r
+    assertNotNull(client);\r
+    assertNull(client.getProperties().get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES));\r
   }\r
 \r
   }\r
 \r
+  @Test\r
+  public void validateBasicAuthSslClient() throws Exception {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.SSL_BASIC);\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    restClientBuilder.setBasicAuthUsername("username");\r
+    restClientBuilder.setBasicAuthPassword("password");\r
+    \r
+    Client client = restClientBuilder.getClient();\r
+   \r
+    Object sslPropertiesObj = client.getProperties().get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES);\r
+    HTTPSProperties sslProps = null;\r
+    if ( sslPropertiesObj instanceof HTTPSProperties ) {\r
+      sslProps = (HTTPSProperties)sslPropertiesObj;\r
+      assertNotNull(sslProps.getHostnameVerifier());\r
+    } else {\r
+      fail("Unexpected value for https properties object");\r
+    }\r
+    \r
+  }\r
 \r
 \r
-  /**\r
-   * This is a convenience method which extracts the HTTPS properties from a supplied client.\r
-   *\r
-   * @parameter aClient - The client to retrieve the HTTPS properties from.\r
-   */\r
-  private HTTPSProperties getHTTPSProperties(Client aClient) {\r
-\r
-    Map<String, Object> props = aClient.getProperties();\r
-    return (HTTPSProperties) props.get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES);\r
+  @Test\r
+  public void validateSslCertClient_noHostOrCertChainValidation() throws Exception {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.SSL_CERT);\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    restClientBuilder.setValidateServerCertChain(false);\r
+    restClientBuilder.setValidateServerHostname(false);\r
+    \r
+    Client client = restClientBuilder.getClient();\r
+   \r
+    Object sslPropertiesObj = client.getProperties().get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES);\r
+    HTTPSProperties sslProps = null;\r
+    if ( sslPropertiesObj instanceof HTTPSProperties ) {\r
+      sslProps = (HTTPSProperties)sslPropertiesObj;\r
+      assertNotNull(sslProps.getHostnameVerifier());\r
+    } else {\r
+      fail("Unexpected value for https properties object");\r
+    }  }\r
+  \r
+  @Test\r
+  public void validateSslCertClient_hostOnlyValidation() throws Exception {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.SSL_CERT);\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    restClientBuilder.setValidateServerCertChain(false);\r
+    restClientBuilder.setValidateServerHostname(true);\r
+    \r
+    Client client = restClientBuilder.getClient();\r
+   \r
+    Object sslPropertiesObj = client.getProperties().get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES);\r
+    HTTPSProperties sslProps = null;\r
+    if ( sslPropertiesObj instanceof HTTPSProperties ) {\r
+      sslProps = (HTTPSProperties)sslPropertiesObj;\r
+      assertNull(sslProps.getHostnameVerifier());\r
+    } else {\r
+      fail("Unexpected value for https properties object");\r
+    }\r
+   }\r
+  \r
+  @Test\r
+  public void validateSslCertClient_certChainOnlyValidation() throws Exception {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.SSL_CERT);\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    restClientBuilder.setValidateServerCertChain(true);\r
+    restClientBuilder.setValidateServerHostname(false);\r
+    restClientBuilder.setTruststoreFilename("truststore");\r
+    restClientBuilder.setClientCertPassword(null);\r
+    \r
+    Client client = restClientBuilder.getClient();\r
+   \r
+    Object sslPropertiesObj = client.getProperties().get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES);\r
+    HTTPSProperties sslProps = null;\r
+    if ( sslPropertiesObj instanceof HTTPSProperties ) {\r
+      sslProps = (HTTPSProperties)sslPropertiesObj;\r
+      assertNotNull(sslProps.getHostnameVerifier());\r
+    } else {\r
+      fail("Unexpected value for https properties object");\r
+    }\r
+  }\r
+  \r
+  @Test\r
+  public void validateSslCertClient_withHostAndCertChainValidation() throws Exception {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.SSL_CERT);\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    restClientBuilder.setValidateServerCertChain(true);\r
+    restClientBuilder.setValidateServerHostname(true);\r
+    restClientBuilder.setClientCertPassword("password");\r
+    restClientBuilder.setTruststoreFilename("truststore");\r
+    \r
+    Client client = restClientBuilder.getClient();\r
+   \r
+    Object sslPropertiesObj = client.getProperties().get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES);\r
+    HTTPSProperties sslProps = null;\r
+    if ( sslPropertiesObj instanceof HTTPSProperties ) {\r
+      sslProps = (HTTPSProperties)sslPropertiesObj;\r
+      assertNull(sslProps.getHostnameVerifier());\r
+    } else {\r
+      fail("Unexpected value for https properties object");\r
+    }  }\r
+  \r
+  @Test (expected=IllegalArgumentException.class)\r
+  public void validateSslCertClient_illegalArgumentExceptionWhenTruststoreIsNull() throws Exception {\r
+    \r
+    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+    \r
+    restClientBuilder.setAuthenticationMode(RestAuthenticationMode.SSL_CERT);\r
+    restClientBuilder.setConnectTimeoutInMs(12345);\r
+    restClientBuilder.setReadTimeoutInMs(54321);\r
+    restClientBuilder.setValidateServerCertChain(true);\r
+    restClientBuilder.setValidateServerHostname(true);\r
+    restClientBuilder.setTruststoreFilename(null);\r
+    \r
+    /*\r
+     * Creating the client in this scenario will cause an IllegalArgumentException caused by the\r
+     * truststore being null\r
+     */\r
+    Client client = restClientBuilder.getClient();\r
+   \r
   }\r
   }\r
+  \r
+    \r
 }\r
 }\r