Rewrite rest-client to use Jersey 2.x API 46/73246/2 1.4.0
authorLee, Tian (tl5884) <TianL@amdocs.com>
Wed, 21 Nov 2018 12:02:49 +0000 (12:02 +0000)
committerLee, Tian (tl5884) <TianL@amdocs.com>
Wed, 21 Nov 2018 12:11:43 +0000 (12:11 +0000)
This is to fix clashes with the rs-api 2.x jars that Spring Boot
requires on the classpath.

Change-Id: Ic36cdf0d650f96c54824e2f51c7f8060b2588c66
Issue-ID: AAI-1939
Signed-off-by: Lee, Tian (tl5884) <TianL@amdocs.com>
README.md
pom.xml
src/main/java/org/onap/aai/restclient/client/RestClient.java
src/main/java/org/onap/aai/restclient/rest/RestClientBuilder.java
src/main/resources/logging/RESTClientMsgs.properties
src/test/java/org/onap/aai/restclient/client/OperationResultTest.java
src/test/java/org/onap/aai/restclient/client/RestfulClientTest.java
src/test/java/org/onap/aai/restclient/rest/RestClientBuilderTest.java

index cd22ba5..0da4736 100644 (file)
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ Note, that all of the above configuration parameters are optional and will be se
 ### Querying The A&AI
 Once your service has a client instance, it can query the _Active & Available Inventory_ by specifying an HTTP endpoint, headers, and the expected response format:
 
-       MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
+       MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();
        headers.put("Accept", Arrays.asList(new String[]{"application/json"}));
        headers.put("X-FromAppId", Arrays.asList(new String[]{"APP-ID"}));
        headers.put("X-TransactionId", Arrays.asList(new String[]{UUID.randomUUID().toString()}));
diff --git a/pom.xml b/pom.xml
index b386cd6..251e63c 100644 (file)
--- a/pom.xml
+++ b/pom.xml
 <?xml version="1.0"?>
 <!--
-============LICENSE_START=======================================================
-org.onap.aai
-================================================================================
-Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
-Copyright © 2017-2018 Amdocs
-================================================================================
-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=========================================================
+    ============LICENSE_START=======================================================
+    org.onap.aai
+    ================================================================================
+    Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+    Copyright © 2017-2018 Amdocs
+    ================================================================================
+    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=========================================================
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-       <modelVersion>4.0.0</modelVersion>
-       <parent>
-               <groupId>org.onap.oparent</groupId>
-               <artifactId>oparent</artifactId>
-               <version>1.2.0</version>
-       </parent>
-
-       <groupId>org.onap.aai</groupId>
-       <artifactId>rest-client</artifactId>
-       <version>1.4.0-SNAPSHOT</version>
-       <name>aai-rest-client</name>
-
-       <properties>
-              <checkstyle.config.location>google_checks.xml</checkstyle.config.location>
-              <!-- Sonar Properties -->
-              <sonar.language>java</sonar.language>
-              <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
-              <sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath>
-              <sonar.jacoco.reportPath>${project.build.directory}/code-coverage/jacoco-ut.exec</sonar.jacoco.reportPath>
-              <sonar.jacoco.reportMissing.force.zero>false</sonar.jacoco.reportMissing.force.zero>
-              <sonar.projectVersion>${project.version}</sonar.projectVersion>
-        </properties>
-
-       <dependencies>
-               <dependency>
-                       <groupId>com.sun.jersey</groupId>
-                       <artifactId>jersey-client</artifactId>
-                       <version>1.18</version>
-               </dependency>
-
-               <dependency>
-                       <groupId>org.onap.aai.logging-service</groupId>
-                       <artifactId>common-logging</artifactId>
-                       <version>1.2.2</version>
-               </dependency>
-
-               <dependency>
-                       <groupId>org.mockito</groupId>
-                       <artifactId>mockito-all</artifactId>
-                       <version>1.10.19</version>
-                       <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>
-    <dependency>
-      <groupId>javax.ws.rs</groupId>
-      <artifactId>javax.ws.rs-api</artifactId>
-      <version>2.0</version>
-    </dependency>
-
-  </dependencies>
-
-       <build>
-               <pluginManagement>
-                       <plugins>
-                               <plugin>
-                                       <groupId>org.apache.maven.plugins</groupId>
-                                       <artifactId>maven-compiler-plugin</artifactId>
-                                       <configuration>
-                                               <source>1.8</source>
-                                               <target>1.8</target>
-                                       </configuration>
-                               </plugin>
-                               <plugin>
-                                       <artifactId>maven-release-plugin</artifactId>
-                                       <version>2.4.2</version>
-                                       <dependencies>
-                                               <dependency>
-                                                       <groupId>org.apache.maven.scm</groupId>
-                                                       <artifactId>maven-scm-provider-gitexe</artifactId>
-                                                       <version>1.8.1</version>
-                                               </dependency>
-                                       </dependencies>
-                               </plugin>
-
-                               <!-- Checkstyle plugin - used to report on compliance with -->
-                               <!-- the Google style guide. -->
-                               <plugin>
-                                       <groupId>org.apache.maven.plugins</groupId>
-                                       <artifactId>maven-site-plugin</artifactId>
-                                       <version>3.6</version>
-                               </plugin>
-                       </plugins>
-               </pluginManagement>
-               <plugins>
-                       <!-- license plugin -->
-                       <!-- Uncomment this to add a license header to every source file
-                       <plugin>
-                               <groupId>com.mycila</groupId>
-                               <artifactId>license-maven-plugin</artifactId>
-                               <version>3.0</version>
-                               <configuration>
-                                       <header>License.txt</header>
-                                       <includes>
-                                               <include>src/main/java/**</include>
-                                       </includes>
-                               </configuration>
-                               <executions>
-                                       <execution>
-                                               <goals>
-                                                       <goal>format</goal>
-                                               </goals>
-                                               <phase>process-sources</phase>
-                                       </execution>
-                               </executions>
-                       </plugin>
-                       -->
-
-                        <plugin>
-                              <groupId>org.sonatype.plugins</groupId>
-                              <artifactId>nexus-staging-maven-plugin</artifactId>
-                              <version>1.6.7</version>
-                              <extensions>true</extensions>
-                              <configuration>
-                                    <nexusUrl>${onap.nexus.url}</nexusUrl>
-                                    <stagingProfileId>176c31dfe190a</stagingProfileId>
-                                    <serverId>ecomp-staging</serverId>
-                              </configuration>
-                        </plugin>
-
-                        <plugin>
-                              <groupId>org.codehaus.mojo</groupId>
-                              <artifactId>sonar-maven-plugin</artifactId>
-                              <version>3.2</version>
-                        </plugin>
-                        <plugin>
-                              <groupId>org.jacoco</groupId>
-                              <artifactId>jacoco-maven-plugin</artifactId>
-                              <version>0.7.7.201606060606</version>
-                              <configuration>
-                                    <dumpOnExit>true</dumpOnExit>
-                              </configuration>
-                              <executions>
-                                    <execution>
-                                          <id>jacoco-initialize-unit-tests</id>
-                                          <goals>
-                                                <goal>prepare-agent</goal>
-                                          </goals>
-                                          <configuration>
-                                                <destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile>
-                                                <!-- <append>true</append> -->
-                                          </configuration>
-                                    </execution>
-                              </executions>
-                     </plugin>
-
-               </plugins>
-       </build>
-
-       <reporting>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-checkstyle-plugin</artifactId>
-                               <version>2.17</version>
-                               <reportSets>
-                                       <reportSet>
-                                               <reports>
-                                                       <report>checkstyle</report>
-                                               </reports>
-                                       </reportSet>
-                               </reportSets>
-                       </plugin>
-               </plugins>
-       </reporting>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onap.oparent</groupId>
+        <artifactId>oparent</artifactId>
+        <version>1.2.1</version>
+    </parent>
+
+    <groupId>org.onap.aai</groupId>
+    <artifactId>rest-client</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <name>aai-rest-client</name>
+
+    <properties>
+        <checkstyle.config.location>google_checks.xml</checkstyle.config.location>
+        <!-- Sonar Properties -->
+        <sonar.language>java</sonar.language>
+        <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
+        <sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath>
+        <sonar.jacoco.reportPath>${project.build.directory}/code-coverage/jacoco-ut.exec</sonar.jacoco.reportPath>
+        <sonar.jacoco.reportMissing.force.zero>false</sonar.jacoco.reportMissing.force.zero>
+        <sonar.projectVersion>${project.version}</sonar.projectVersion>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-client</artifactId>
+            <version>2.27</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onap.aai.logging-service</groupId>
+            <artifactId>common-logging</artifactId>
+            <version>1.2.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.10.19</version>
+            <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>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <configuration>
+                        <source>1.8</source>
+                        <target>1.8</target>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-release-plugin</artifactId>
+                    <version>2.4.2</version>
+                    <dependencies>
+                        <dependency>
+                            <groupId>org.apache.maven.scm</groupId>
+                            <artifactId>maven-scm-provider-gitexe</artifactId>
+                            <version>1.8.1</version>
+                        </dependency>
+                    </dependencies>
+                </plugin>
+
+                <!-- Checkstyle plugin - used to report on compliance with -->
+                <!-- the Google style guide. -->
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-site-plugin</artifactId>
+                    <version>3.6</version>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>com.mycila</groupId>
+                <artifactId>license-maven-plugin</artifactId>
+                <version>3.0</version>
+                <configuration>
+                    <header>License.txt</header>
+                    <includes>
+                        <include>src/main/java/**</include>
+                        <include>src/test/java/**</include>
+                        <include>pom.xml</include>
+                    </includes>
+                    <skipExistingHeaders>true</skipExistingHeaders>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <!-- Set goal from "check" to "format" to auto update license headers -->
+                            <goal>check</goal>
+                        </goals>
+                        <phase>validate</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.sonatype.plugins</groupId>
+                <artifactId>nexus-staging-maven-plugin</artifactId>
+                <version>1.6.7</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <nexusUrl>${onap.nexus.url}</nexusUrl>
+                    <stagingProfileId>176c31dfe190a</stagingProfileId>
+                    <serverId>ecomp-staging</serverId>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>sonar-maven-plugin</artifactId>
+                <version>3.2</version>
+            </plugin>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>0.7.7.201606060606</version>
+                <configuration>
+                    <dumpOnExit>true</dumpOnExit>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>jacoco-initialize-unit-tests</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                        <configuration>
+                            <destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile>
+                            <!-- <append>true</append> -->
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+    </build>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>2.17</version>
+                <reportSets>
+                    <reportSet>
+                        <reports>
+                            <report>checkstyle</report>
+                        </reports>
+                    </reportSet>
+                </reportSets>
+            </plugin>
+        </plugins>
+    </reporting>
 
 </project>
index f4f184c..89d5c62 100644 (file)
@@ -23,869 +23,854 @@ package org.onap.aai.restclient.client;
 import java.io.ByteArrayOutputStream;
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-
+import java.util.stream.Collectors;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation.Builder;
+import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
-
-import org.onap.aai.restclient.enums.RestAuthenticationMode;
-import org.onap.aai.restclient.logging.RestClientMsgs;
-import org.onap.aai.restclient.rest.RestClientBuilder;
 import org.onap.aai.cl.api.LogFields;
 import org.onap.aai.cl.api.LogLine;
 import org.onap.aai.cl.api.Logger;
 import org.onap.aai.cl.eelf.LoggerFactory;
 import org.onap.aai.cl.mdc.MdcContext;
 import org.onap.aai.cl.mdc.MdcOverride;
+import org.onap.aai.restclient.enums.RestAuthenticationMode;
+import org.onap.aai.restclient.logging.RestClientMsgs;
+import org.onap.aai.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 {
 
-  /**
-   * This is a generic builder that is used for constructing the REST client that we will use to
-   * communicate with the REST endpoint.
-   */
-  private RestClientBuilder clientBuilder;
-  
-  private final ConcurrentMap<String,InitializedClient> CLIENT_CACHE = new ConcurrentHashMap<>();
-  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 metric statements. */
-  private Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger("AAIRESTClient");
-
-  private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
-
-  /** Reusable function call for GET REST operations. */
-  private final RestOperation getOp = new GetRestOperation();
-
-  /** Reusable function call for PUT REST operations. */
-  private final RestOperation putOp = new PutRestOperation();
-
-  /** Reusable function call for POST REST operations. */
-  private final RestOperation postOp = new PostRestOperation();
-
-  /** 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() {
-    
-    clientBuilder = new RestClientBuilder();
-  
-  }
-
-
-  /**
-   * Creates a new instance of the {@link RestClient} using the supplied {@link RestClientBuilder}.
-   *
-   * @param rcBuilder - The REST client builder that this instance of the {@link RestClient} should
-   *        use.
-   */
-  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
+    /**
+     * This is a generic builder that is used for constructing the REST client that we will use to communicate with the
+     * REST endpoint.
      */
-    clientBuilder.setBasicAuthPassword(password);
-    return this;
-  }
-
-
-  /**
-   * Sets the flag to indicate whether or not validation should be performed against the host name
-   * of the server we are trying to communicate with.
-   *
-   * @parameter validate - Set to true to enable validation, false to disable
-   *
-   * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
-   */
-  public RestClient validateServerHostname(boolean validate) {
-    logger.debug("Set validate server hostname = " + validate);
-    clientBuilder.setValidateServerHostname(validate);
-    return this;
-  }
-
-
-  /**
-   * Sets the flag to indicate whether or not validation should be performed against the certificate
-   * chain.
-   *
-   * @parameter validate - Set to true to enable validation, false to disable.
-   *
-   * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
-   */
-  public RestClient validateServerCertChain(boolean validate) {
-    logger.debug("Set validate server certificate chain = " + validate);
-    clientBuilder.setValidateServerCertChain(validate);
-    return this;
-  }
-
-
-  /**
-   * Assigns the client certificate file to use.
-   *
-   * @param filename - The name of the certificate file.
-   *
-   * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
-   */
-  public RestClient clientCertFile(String filename) {
-    logger.debug("Set client certificate filename = " + filename);
-    clientBuilder.setClientCertFileName(filename);
-    return this;
-  }
-
-
-  /**
-   * Assigns the client certificate password to use.
-   *
-   * @param password - The certificate password.
-   *
-   * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
-   */
-  public RestClient clientCertPassword(String password) {
-    clientBuilder.setClientCertPassword(password);
-    return this;
-  }
-
-
-  /**
-   * Assigns the name of the trust store file to use.
-   *
-   * @param filename - the name of the trust store file.
-   *
-   * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
-   */
-  public RestClient trustStore(String filename) {
-    logger.debug("Set trust store filename = " + filename);
-    clientBuilder.setTruststoreFilename(filename);
-    return this;
-  }
-
-
-  /**
-   * Assigns the connection timeout (in ms) to use when connecting to the target server.
-   *
-   * @param timeout - The length of time to wait in ms before timing out.
-   *
-   * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
-   */
-  public RestClient connectTimeoutMs(int timeout) {
-    logger.debug("Set connection timeout = " + timeout + " ms");
-    clientBuilder.setConnectTimeoutInMs(timeout);
-    return this;
-  }
-
-
-  /**
-   * Assigns the read timeout (in ms) to use when communicating with the target server.
-   *
-   * @param timeout The read timeout in milliseconds.
-   *
-   * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
-   */
-  public RestClient readTimeoutMs(int timeout) {
-    logger.debug("Set read timeout = " + timeout + " ms");
-    clientBuilder.setReadTimeoutInMs(timeout);
-    return this;
-  }
-  
-  /**
-   * Configures the client for a specific SSL protocol
-   *
-   * @param sslProtocol - protocol string constant such as TLS, TLSv1, TLSv1.1, TLSv1.2
-   *
-   * @return The AAIRESTClient instance. 
-   */
-  public RestClient sslProtocol(String sslProtocol) {
-    logger.debug("Set sslProtocol = " + sslProtocol);
-    clientBuilder.setSslProtocol(sslProtocol);
-    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 variant of the method will perform a requested number of retries in the event that the
-   * first request is unsuccessful.
-   *
-   * @param operation - the REST operation type to send to the url
-   * @param url - The REST endpoint to submit the REST request to.
-   * @param payload - They payload to provide in the REST request, if applicable
-   * @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 REST request.
-   */
-  protected OperationResult processRequest(RestOperation operation, String url, String payload,
-      Map<String, List<String>> headers, MediaType contentType, MediaType responseType,
-      int numRetries) {
-
-
-    OperationResult result = null;
-
-    long startTimeInMs = System.currentTimeMillis();
-    for (int retryCount = 0; retryCount < numRetries; retryCount++) {
-
-      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.
-      
-      if (!shouldRetry(result)) {
-        
-        logger.info(RestClientMsgs.HTTP_REQUEST_TIME_WITH_RETRIES, operation.getRequestType().toString(),url,
-            Long.toString(System.currentTimeMillis() - startTimeInMs), 
-            Integer.toString(retryCount));
-        
-        result.setNumRetries(retryCount);
-        
-        return result;
-      }
+    private RestClientBuilder clientBuilder;
+
+    private final ConcurrentMap<String, InitializedClient> CLIENT_CACHE = new ConcurrentHashMap<>();
+    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 metric statements. */
+    private Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger("AAIRESTClient");
 
-      // Our submission was unsuccessful...
-      try {
-        // Sleep between re-tries to be nice to the target system.
-        Thread.sleep(50);
-
-      } catch (InterruptedException e) {
-        logger.error(RestClientMsgs.HTTP_REQUEST_INTERRUPTED, url, e.getLocalizedMessage());
-        Thread.currentThread().interrupt();
-        break;
-      }
+    private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
+
+    /** Reusable function call for GET REST operations. */
+    private final RestOperation getOp = new GetRestOperation();
+
+    /** Reusable function call for PUT REST operations. */
+    private final RestOperation putOp = new PutRestOperation();
+
+    /** Reusable function call for POST REST operations. */
+    private final RestOperation postOp = new PostRestOperation();
+
+    /** 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() {
+        clientBuilder = new RestClientBuilder();
     }
 
-    // If we've gotten this far, then we failed all of our retries.
-    if (result == null) {
-        result = new OperationResult();
-    }
-
-    result.setNumRetries(numRetries);
-    result.setResultCode(504);
-    result.setFailureCause("Failed to get a successful result after multiple retries to target server.");
-
-
-    return result;
-  }
-
-  /**
-   * This method operates on a REST endpoint by submitting an HTTP operation request against the
-   * supplied URL.
-   *
-   * @param operation - the REST operation type to send to the url
-   * @param url - The REST endpoint to submit the REST request to.
-   * @param payload - They payload to provide in the REST request, if applicable
-   * @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 REST request.
-   */
-  protected OperationResult processRequest(RestOperation operation, String url, String payload,
-      Map<String, List<String>> headers, MediaType contentType, MediaType responseType) {
-
-    ClientResponse clientResponse = null;
-    OperationResult operationResult = new OperationResult();
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
-    String requestType = operation.getRequestType().name();
-
-    // Grab the current time so that we can log how long the
-    // query took once we are done.
-    long startTimeInMs = System.currentTimeMillis();
-    MdcOverride override = new MdcOverride();
-    override.addAttribute(MdcContext.MDC_START_TIME, formatter.format(startTimeInMs));
-
-    logger.info(RestClientMsgs.HTTP_REQUEST, requestType, url);
-
-    try {
-
-      // Get a REST client instance for our request.
-      Client client = getClient();
-
-      // Debug log the request
-      debugRequest(url, payload, headers, responseType);
-
-      // Get a client request builder, and submit our GET request.
-      Builder builder = getClientBuilder(client, url, payload, headers, contentType, responseType);
-      clientResponse = operation.processOperation(builder);
-
-      populateOperationResult(clientResponse, operationResult);
-
-      // Debug log the response
-      if (clientResponse != null) {
-        debugResponse(operationResult, clientResponse.getHeaders());
-      }
-
-    } catch (Exception ex) {
-
-      logger.error(RestClientMsgs.HTTP_REQUEST_ERROR, requestType, url, ex.getLocalizedMessage());
-      operationResult.setResultCode(500);
-      operationResult.setFailureCause(
-          "Error during GET operation to AAI with message = " + ex.getLocalizedMessage());
-
-    } finally {
-
-      if (logger.isDebugEnabled()) {
-        logger.debug(baos.toString());
-      }
-
-      // Not every valid response code is actually represented by the Response.Status
-      // object, so we need to guard against missing codes, otherwise we throw null
-      // pointer exceptions when we try to generate our metrics logs...
-      Response.Status responseStatus =
-          Response.Status.fromStatusCode(operationResult.getResultCode());
-      String responseStatusCodeString = "";
-      if (responseStatus != null) {
-        responseStatusCodeString = responseStatus.toString();
-      }
-
-      metricsLogger.info(RestClientMsgs.HTTP_REQUEST_TIME,
-          new LogFields().setField(LogLine.DefinedFields.STATUS_CODE, responseStatusCodeString)
-              .setField(LogLine.DefinedFields.RESPONSE_CODE, operationResult.getResultCode())
-              .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, operationResult.getResult()),
-          override, requestType, Long.toString(System.currentTimeMillis() - startTimeInMs), url);
-      logger.info(RestClientMsgs.HTTP_REQUEST_TIME, requestType,
-          Long.toString(System.currentTimeMillis() - startTimeInMs), url);
-      logger.info(RestClientMsgs.HTTP_RESPONSE, url,
-          operationResult.getResultCode() + " " + responseStatusCodeString);
-    }
-
-    return operationResult;
-  }
-
-  /**
-   * This method submits an HTTP PUT request against the supplied URL.
-   *
-   * @param url - The REST endpoint to submit the PUT 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 PUT request.
-   */
-  public OperationResult put(String url, String payload, Map<String, List<String>> headers,
-      MediaType contentType, MediaType responseType) {
-    return processRequest(putOp, url, payload, headers, contentType, responseType);
-  }
-
-  /**
-   * This method submits an HTTP POST request against the supplied URL.
-   *
-   * @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 post(String url, String payload, Map<String, List<String>> headers,
-      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.
-   *
-   * @param url - The REST endpoint to submit the GET 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 GET request.
-   */
-  public OperationResult get(String url, Map<String, List<String>> headers,
-      MediaType responseType) {
-    return processRequest(getOp, url, null, headers, null, responseType);
-  }
-
-  /**
-   * This method submits an HTTP GET request against the supplied URL. 
-   * This variant of the method will perform a requested number of retries in the event that the
-   * first request is unsuccessful.
-   * 
-   * @param url - The REST endpoint to submit the GET request to.
-   * @param headers - The headers that should be passed in the request
-   * @param responseType - The expected format of the response.
-   * @param numRetries - The number of times to try resubmitting the request in the event of a
-   *        failure.
-   * 
-   * @return The result of the GET request.
-   */
-  public OperationResult get(String url, Map<String, List<String>> headers, MediaType responseType,
-      int numRetries) {
-    return processRequest(getOp, url, null, headers, null, responseType, numRetries);
-  }
-
-  /**
-   * This method submits an HTTP DELETE request against the supplied URL.
-   *
-   * @param url - The REST endpoint to submit the DELETE 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 DELETE request.
-   */
-  public OperationResult delete(String url, Map<String, List<String>> headers,
-      MediaType responseType) {
-    return processRequest(deleteOp, url, null, headers, null, responseType);
-  }
-
-  /**
-   * This method does a health check ("ping") against the supplied URL.
-   *
-   * @param url - The REST endpoint to attempt a health check.
-   * @param srcAppName - The name of the application using this client.
-   * @param destAppName - The name of the destination app.
-   *
-   * @return A boolean value. True if connection attempt was successful, false otherwise.
-   *
-   */
-  public boolean healthCheck(String url, String srcAppName, String destAppName) {
-    return healthCheck(url, srcAppName, destAppName, MediaType.TEXT_PLAIN_TYPE);
-
-  }
-
-  /**
-   * This method does a health check ("ping") against the supplied URL.
-   *
-   * @param url - The REST endpoint to attempt a health check.
-   * @param srcAppName - The name of the application using this client.
-   * @param destAppName - The name of the destination app.
-   * @param responseType - The response type.
-   *
-   * @return A boolean value. True if connection attempt was successful, false otherwise.
-   *
-   */
-  public boolean healthCheck(String url, String srcAppName, String destAppName,
-      MediaType responseType) {
-    MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
-    headers.put(Headers.FROM_APP_ID, Arrays.asList(new String[] {srcAppName}));
-    headers.put(Headers.TRANSACTION_ID, Arrays.asList(new String[] {UUID.randomUUID().toString()}));
-
-    try {
-      logger.info(RestClientMsgs.HEALTH_CHECK_ATTEMPT, destAppName, url);
-      OperationResult result = get(url, headers, responseType);
-
-      if (result != null && result.getFailureCause() == null) {
-        logger.info(RestClientMsgs.HEALTH_CHECK_SUCCESS, destAppName, url);
-        return true;
-      } else {
-        logger.error(RestClientMsgs.HEALTH_CHECK_FAILURE, destAppName, url, result != null ? result.getFailureCause()
-                                                                                           : null);
-        return false;
-      }
-    } catch (Exception e) {
-      logger.error(RestClientMsgs.HEALTH_CHECK_FAILURE, destAppName, url, e.getMessage());
-      return false;
+    /**
+     * Creates a new instance of the {@link RestClient} using the supplied {@link RestClientBuilder}.
+     *
+     * @param rcBuilder - The REST client builder that this instance of the {@link RestClient} should use.
+     */
+    public RestClient(RestClientBuilder rcBuilder) {
+        clientBuilder = rcBuilder;
     }
-  }
 
-  /**
-   * This method constructs a client request builder that can be used for submitting REST requests
-   * to the supplied URL endpoint.
-   *
-   * @param client - The REST client we will be using to talk to the server.
-   * @param url - The URL endpoint that our request will be submitted to.
-   * @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 A client request builder.
-   */
-  private Builder getClientBuilder(Client client, String url, String payload,
-      Map<String, List<String>> headers, MediaType contentType, MediaType responseType) {
+    public RestClient authenticationMode(RestAuthenticationMode mode) {
+        logger.debug("Set rest authentication mode= " + mode);
+        clientBuilder.setAuthenticationMode(mode);
+        return this;
+    }
 
-    WebResource resource = client.resource(url);
-    Builder builder = resource.accept(responseType);
+    public RestClient basicAuthUsername(String username) {
+        logger.debug("Set SSL BasicAuth username = " + username);
+        clientBuilder.setBasicAuthUsername(username);
+        return this;
+    }
 
-    if (contentType != null) {
-      builder.type(contentType);
+    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;
     }
 
-    if (payload != null) {
-      builder.entity(payload);
+    /**
+     * Sets the flag to indicate whether or not validation should be performed against the host name of the server we
+     * are trying to communicate with.
+     *
+     * @parameter validate - Set to true to enable validation, false to disable
+     *
+     * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
+     */
+    public RestClient validateServerHostname(boolean validate) {
+        logger.debug("Set validate server hostname = " + validate);
+        clientBuilder.setValidateServerHostname(validate);
+        return this;
     }
 
-    if (headers != null) {
-      for (Entry<String, List<String>> header : headers.entrySet()) {
-        builder.header(header.getKey(), String.join(";",header.getValue()));
-      }
-      
-      //Added additional check to prevent adding duplicate authorization header if client is already sending the authorization header 
-      // AAI-1097 - For AAI calls when Rest authentication mode is selected as SSL_BASIC getting 403 error
-      if (clientBuilder.getAuthenticationMode() == RestAuthenticationMode.SSL_BASIC && headers.get(Headers.AUTHORIZATION) == null) {
-        builder = builder.header(Headers.AUTHORIZATION,
-            clientBuilder.getBasicAuthenticationCredentials());
-      }
-      
+    /**
+     * Sets the flag to indicate whether or not validation should be performed against the certificate chain.
+     *
+     * @parameter validate - Set to true to enable validation, false to disable.
+     *
+     * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
+     */
+    public RestClient validateServerCertChain(boolean validate) {
+        logger.debug("Set validate server certificate chain = " + validate);
+        clientBuilder.setValidateServerCertChain(validate);
+        return this;
     }
 
-    return builder;
-  }
+    /**
+     * Assigns the client certificate file to use.
+     *
+     * @param filename - The name of the certificate file.
+     *
+     * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
+     */
+    public RestClient clientCertFile(String filename) {
+        logger.debug("Set client certificate filename = " + filename);
+        clientBuilder.setClientCertFileName(filename);
+        return this;
+    }
 
-  private void debugRequest(String url, String payload, Map<String, List<String>> headers,
-      MediaType responseType) {
-    if (!logger.isDebugEnabled()) {
-      return;
+    /**
+     * Assigns the client certificate password to use.
+     *
+     * @param password - The certificate password.
+     *
+     * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
+     */
+    public RestClient clientCertPassword(String password) {
+        clientBuilder.setClientCertPassword(password);
+        return this;
     }
 
-    StringBuilder debugRequest = new StringBuilder("REQUEST:\n");
-    debugRequest.append("URL: ").append(url).append("\n");
-    debugRequest.append("Payload: ").append(payload).append("\n");
-    debugRequest.append("Response Type: ").append(responseType).append("\n");
+    /**
+     * Assigns the name of the trust store file to use.
+     *
+     * @param filename - the name of the trust store file.
+     *
+     * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
+     */
+    public RestClient trustStore(String filename) {
+        logger.debug("Set trust store filename = " + filename);
+        clientBuilder.setTruststoreFilename(filename);
+        return this;
+    }
 
-    if (headers == null) {
-      logger.debug(debugRequest.toString());
-      return;
+    /**
+     * Assigns the connection timeout (in ms) to use when connecting to the target server.
+     *
+     * @param timeout - The length of time to wait in ms before timing out.
+     *
+     * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
+     */
+    public RestClient connectTimeoutMs(int timeout) {
+        logger.debug("Set connection timeout = " + timeout + " ms");
+        clientBuilder.setConnectTimeoutInMs(timeout);
+        return this;
     }
 
-    debugRequest.append("Headers: ");
-    for (Entry<String, List<String>> header : headers.entrySet()) {
-      debugRequest.append("\n\t").append(header.getKey()).append(":");
-      for (String headerEntry : header.getValue()) {
-        debugRequest.append("\"").append(headerEntry).append("\" ");
-      }
+    /**
+     * Assigns the read timeout (in ms) to use when communicating with the target server.
+     *
+     * @param timeout The read timeout in milliseconds.
+     *
+     * @return The AAIRESTClient instance. This is useful for chaining parameter assignments.
+     */
+    public RestClient readTimeoutMs(int timeout) {
+        logger.debug("Set read timeout = " + timeout + " ms");
+        clientBuilder.setReadTimeoutInMs(timeout);
+        return this;
     }
 
-    logger.debug(debugRequest.toString());
+    /**
+     * Configures the client for a specific SSL protocol
+     *
+     * @param sslProtocol - protocol string constant such as TLS, TLSv1, TLSv1.1, TLSv1.2
+     *
+     * @return The AAIRESTClient instance.
+     */
+    public RestClient sslProtocol(String sslProtocol) {
+        logger.debug("Set sslProtocol = " + sslProtocol);
+        clientBuilder.setSslProtocol(sslProtocol);
+        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;
+        }
 
-  private void debugResponse(OperationResult operationResult,
-      MultivaluedMap<String, String> headers) {
+        return true;
 
-    if (!logger.isDebugEnabled()) {
-      return;
     }
 
-    StringBuilder debugResponse = new StringBuilder("RESPONSE:\n");
-    debugResponse.append("Result: ").append(operationResult.getResultCode()).append("\n");
-    debugResponse.append("Failure Cause: ").append(operationResult.getFailureCause()).append("\n");
-    debugResponse.append("Payload: ").append(operationResult.getResult()).append("\n");
+    /**
+     * This method operates on a REST endpoint by submitting an HTTP operation request against the supplied URL. This
+     * variant of the method will perform a requested number of retries in the event that the first request is
+     * unsuccessful.
+     *
+     * @param operation - the REST operation type to send to the url
+     * @param url - The REST endpoint to submit the REST request to.
+     * @param payload - They payload to provide in the REST request, if applicable
+     * @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 REST request.
+     */
+    protected OperationResult processRequest(RestOperation operation, String url, String payload,
+            Map<String, List<String>> headers, MediaType contentType, MediaType responseType, int numRetries) {
+
+
+        OperationResult result = null;
 
-    if (headers == null) {
-      logger.debug(debugResponse.toString());
-      return;
+        long startTimeInMs = System.currentTimeMillis();
+        for (int retryCount = 0; retryCount < numRetries; retryCount++) {
+
+            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.
+
+            if (!shouldRetry(result)) {
+
+                logger.info(RestClientMsgs.HTTP_REQUEST_TIME_WITH_RETRIES, operation.getRequestType().toString(), url,
+                        Long.toString(System.currentTimeMillis() - startTimeInMs), Integer.toString(retryCount));
+
+                result.setNumRetries(retryCount);
+
+                return result;
+            }
+
+            // Our submission was unsuccessful...
+            try {
+                // Sleep between re-tries to be nice to the target system.
+                Thread.sleep(50);
+
+            } catch (InterruptedException e) {
+                logger.error(RestClientMsgs.HTTP_REQUEST_INTERRUPTED, url, e.getLocalizedMessage());
+                Thread.currentThread().interrupt();
+                break;
+            }
+        }
+
+        // If we've gotten this far, then we failed all of our retries.
+        if (result == null) {
+            result = new OperationResult();
+        }
+
+        result.setNumRetries(numRetries);
+        result.setResultCode(504);
+        result.setFailureCause("Failed to get a successful result after multiple retries to target server.");
+
+
+        return result;
     }
 
-    debugResponse.append("Headers: ");
-    for (Entry<String, List<String>> header : headers.entrySet()) {
-      debugResponse.append("\n\t").append(header.getKey()).append(":");
-      for (String headerEntry : header.getValue()) {
-        debugResponse.append("\"").append(headerEntry).append("\" ");
-      }
+    /**
+     * This method operates on a REST endpoint by submitting an HTTP operation request against the supplied URL.
+     *
+     * @param operation - the REST operation type to send to the url
+     * @param url - The REST endpoint to submit the REST request to.
+     * @param payload - They payload to provide in the REST request, if applicable
+     * @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 REST request.
+     */
+    protected OperationResult processRequest(RestOperation operation, String url, String payload,
+            Map<String, List<String>> headers, MediaType contentType, MediaType responseType) {
+
+        Response clientResponse = null;
+        OperationResult operationResult = new OperationResult();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        String requestType = operation.getRequestType().name();
+
+        // Grab the current time so that we can log how long the
+        // query took once we are done.
+        long startTimeInMs = System.currentTimeMillis();
+        MdcOverride override = new MdcOverride();
+        override.addAttribute(MdcContext.MDC_START_TIME, formatter.format(startTimeInMs));
+
+        logger.info(RestClientMsgs.HTTP_REQUEST, requestType, url);
+
+        try {
+
+            // Get a REST client instance for our request.
+            Client client = getClient();
+
+            // Debug log the request
+            debugRequest(url, payload, headers, responseType);
+
+            // Get a client request builder, and submit our GET request.
+            Builder builder = getClientBuilder(client, url, headers, responseType);
+            clientResponse = operation.processOperation(builder, payload, contentType);
+
+            populateOperationResult(clientResponse, operationResult);
+
+            // Debug log the response
+            if (clientResponse != null) {
+                debugResponse(operationResult, clientResponse.getHeaders());
+            }
+
+        } catch (Exception ex) {
+
+            logger.error(RestClientMsgs.HTTP_REQUEST_ERROR, requestType, url, ex.getLocalizedMessage());
+            operationResult.setResultCode(500);
+            operationResult
+                    .setFailureCause("Error during GET operation to AAI with message = " + ex.getLocalizedMessage());
+
+        } finally {
+
+            if (logger.isDebugEnabled()) {
+                logger.debug(baos.toString());
+            }
+
+            // Not every valid response code is actually represented by the Response.Status
+            // object, so we need to guard against missing codes, otherwise we throw null
+            // pointer exceptions when we try to generate our metrics logs...
+            Response.Status responseStatus = Response.Status.fromStatusCode(operationResult.getResultCode());
+            String responseStatusCodeString = "";
+            if (responseStatus != null) {
+                responseStatusCodeString = responseStatus.toString();
+            }
+
+            metricsLogger.info(RestClientMsgs.HTTP_REQUEST_TIME,
+                    new LogFields().setField(LogLine.DefinedFields.STATUS_CODE, responseStatusCodeString)
+                            .setField(LogLine.DefinedFields.RESPONSE_CODE, operationResult.getResultCode())
+                            .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, operationResult.getResult()),
+                    override, requestType, Long.toString(System.currentTimeMillis() - startTimeInMs), url);
+            logger.info(RestClientMsgs.HTTP_REQUEST_TIME, requestType,
+                    Long.toString(System.currentTimeMillis() - startTimeInMs), url);
+            logger.info(RestClientMsgs.HTTP_RESPONSE, url,
+                    operationResult.getResultCode() + " " + responseStatusCodeString);
+        }
+
+        return operationResult;
     }
 
-    logger.debug(debugResponse.toString());
-  }
+    /**
+     * This method submits an HTTP PUT request against the supplied URL.
+     *
+     * @param url - The REST endpoint to submit the PUT 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 PUT request.
+     */
+    public OperationResult put(String url, String payload, Map<String, List<String>> headers, MediaType contentType,
+            MediaType responseType) {
+        return processRequest(putOp, url, payload, headers, contentType, responseType);
+    }
 
-  /**
-   * 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.
-   */
-  protected Client getClient() throws Exception {
+    /**
+     * This method submits an HTTP POST request against the supplied URL.
+     *
+     * @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 post(String url, String payload, Map<String, List<String>> headers, MediaType contentType,
+            MediaType responseType) {
+        return processRequest(postOp, url, payload, headers, contentType, responseType);
+    }
 
-    /*
-     * 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.
+    /**
+     * 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 PATCH 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 HEAD 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.
+     *
+     * @param url - The REST endpoint to submit the GET 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 GET request.
+     */
+    public OperationResult get(String url, Map<String, List<String>> headers, MediaType responseType) {
+        return processRequest(getOp, url, null, headers, null, responseType);
+    }
+
+    /**
+     * This method submits an HTTP GET request against the supplied URL. This variant of the method will perform a
+     * requested number of retries in the event that the first request is unsuccessful.
+     * 
+     * @param url - The REST endpoint to submit the GET request to.
+     * @param headers - The headers that should be passed in the request
+     * @param responseType - The expected format of the response.
+     * @param numRetries - The number of times to try resubmitting the request in the event of a failure.
      * 
-     * 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.
+     * @return The result of the GET request.
      */
-    final InitializedClient clientInstance =
-        CLIENT_CACHE.computeIfAbsent(REST_CLIENT_INSTANCE, k -> loggedClientInitialization());
-    
-    if (clientInstance.getCaughtException() != null) {
-      throw new InstantiationException(clientInstance.getCaughtException().getMessage());
+    public OperationResult get(String url, Map<String, List<String>> headers, MediaType responseType, int numRetries) {
+        return processRequest(getOp, url, null, headers, null, responseType, numRetries);
     }
 
-    return clientInstance.getClient();
+    /**
+     * This method submits an HTTP DELETE request against the supplied URL.
+     *
+     * @param url - The REST endpoint to submit the DELETE 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 DELETE request.
+     */
+    public OperationResult delete(String url, Map<String, List<String>> headers, MediaType responseType) {
+        return processRequest(deleteOp, url, null, headers, null, responseType);
+    }
 
-  }
+    /**
+     * This method does a health check ("ping") against the supplied URL.
+     *
+     * @param url - The REST endpoint to attempt a health check.
+     * @param srcAppName - The name of the application using this client.
+     * @param destAppName - The name of the destination app.
+     *
+     * @return A boolean value. True if connection attempt was successful, false otherwise.
+     *
+     */
+    public boolean healthCheck(String url, String srcAppName, String destAppName) {
+        return healthCheck(url, srcAppName, destAppName, MediaType.TEXT_PLAIN_TYPE);
 
-  /**
-   * 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());
+    /**
+     * This method does a health check ("ping") against the supplied URL.
+     *
+     * @param url - The REST endpoint to attempt a health check.
+     * @param srcAppName - The name of the application using this client.
+     * @param destAppName - The name of the destination app.
+     * @param responseType - The response type.
+     *
+     * @return A boolean value. True if connection attempt was successful, false otherwise.
+     *
+     */
+    public boolean healthCheck(String url, String srcAppName, String destAppName, MediaType responseType) {
+        Map<String, List<String>> headers = new HashMap<>();
+        headers.put(Headers.FROM_APP_ID, Arrays.asList(new String[] {srcAppName}));
+        headers.put(Headers.TRANSACTION_ID, Arrays.asList(new String[] {UUID.randomUUID().toString()}));
+
+        try {
+            logger.info(RestClientMsgs.HEALTH_CHECK_ATTEMPT, destAppName, url);
+            OperationResult result = get(url, headers, responseType);
+
+            if (result != null && result.getFailureCause() == null) {
+                logger.info(RestClientMsgs.HEALTH_CHECK_SUCCESS, destAppName, url);
+                return true;
+            } else {
+                logger.error(RestClientMsgs.HEALTH_CHECK_FAILURE, destAppName, url,
+                        result != null ? result.getFailureCause() : null);
+                return false;
+            }
+        } catch (Exception e) {
+            logger.error(RestClientMsgs.HEALTH_CHECK_FAILURE, destAppName, url, e.getMessage());
+            return false;
+        }
     }
-    
-    InitializedClient initClient = new InitializedClient();
-    
-    try {
-      initClient.setClient(clientBuilder.getClient());
-    } catch ( Exception error) {
-      initClient.setCaughtException(error);
+
+    /**
+     * This method constructs a client request builder that can be used for submitting REST requests to the supplied URL
+     * endpoint.
+     *
+     * @param client - The REST client we will be using to talk to the server.
+     * @param url - The URL endpoint that our request will be submitted to.
+     * @param headers - The headers that should be passed in the request
+     * @param responseType - The expected format of the response.
+     *
+     * @return A client request builder.
+     */
+    private Builder getClientBuilder(Client client, String url, Map<String, List<String>> headers,
+            MediaType responseType) {
+
+        WebTarget target = client.target(url);
+
+        Builder builder = target.request().accept(responseType);
+
+        if (headers != null) {
+            for (Entry<String, List<String>> header : headers.entrySet()) {
+                builder.header(header.getKey(), String.join(";", header.getValue()));
+            }
+
+            // Added additional check to prevent adding duplicate authorization header if client is already sending the
+            // authorization header
+            // AAI-1097 - For AAI calls when Rest authentication mode is selected as SSL_BASIC getting 403 error
+            if (clientBuilder.getAuthenticationMode() == RestAuthenticationMode.SSL_BASIC
+                    && headers.get(Headers.AUTHORIZATION) == null) {
+                builder = builder.header(Headers.AUTHORIZATION, clientBuilder.getBasicAuthenticationCredentials());
+            }
+
+        }
+
+        return builder;
     }
-    
-    return initClient;
 
-  }
+    private void debugRequest(String url, String payload, Map<String, List<String>> headers, MediaType responseType) {
+        if (!logger.isDebugEnabled()) {
+            return;
+        }
+
+        StringBuilder debugRequest = new StringBuilder("REQUEST:\n");
+        debugRequest.append("URL: ").append(url).append("\n");
+        debugRequest.append("Payload: ").append(payload).append("\n");
+        debugRequest.append("Response Type: ").append(responseType).append("\n");
+
+        if (headers == null) {
+            logger.debug(debugRequest.toString());
+            return;
+        }
 
+        debugRequest.append("Headers: ");
+        for (Entry<String, List<String>> header : headers.entrySet()) {
+            debugRequest.append("\n\t").append(header.getKey()).append(":");
+            for (String headerEntry : header.getValue()) {
+                debugRequest.append("\"").append(headerEntry).append("\" ");
+            }
+        }
 
-  /**
-   * This method populates the fields of an {@link OperationResult} instance based on the contents
-   * of a {@link ClientResponse} received in response to a REST request.
-   */
-  private void populateOperationResult(ClientResponse response, OperationResult opResult) {
+        logger.debug(debugRequest.toString());
 
-    // If we got back a NULL response, then just produce a generic
-    // error code and result indicating this.
-    if (response == null) {
-      opResult.setResultCode(500);
-      opResult.setFailureCause("Client response was null");
-      return;
     }
-        
-    int statusCode = response.getStatus();
-    opResult.setResultCode(statusCode);
 
-    if (opResult.wasSuccessful()) {
-        if (statusCode != Response.Status.NO_CONTENT.getStatusCode()) {
-            opResult.setResult(response.getEntity(String.class));
+    private void debugResponse(OperationResult operationResult, MultivaluedMap<String, Object> headers) {
+
+        if (!logger.isDebugEnabled()) {
+            return;
+        }
+
+        StringBuilder debugResponse = new StringBuilder("RESPONSE:\n");
+        debugResponse.append("Result: ").append(operationResult.getResultCode()).append("\n");
+        debugResponse.append("Failure Cause: ").append(operationResult.getFailureCause()).append("\n");
+        debugResponse.append("Payload: ").append(operationResult.getResult()).append("\n");
+
+        if (headers == null) {
+            logger.debug(debugResponse.toString());
+            return;
         }
-    } else {
-        opResult.setFailureCause(response.getEntity(String.class));
+
+        debugResponse.append("Headers: ");
+        for (Entry<String, List<Object>> header : headers.entrySet()) {
+            debugResponse.append("\n\t").append(header.getKey()).append(":");
+            for (Object headerEntry : header.getValue()) {
+                debugResponse.append("\"").append(headerEntry).append("\" ");
+            }
+        }
+
+        logger.debug(debugResponse.toString());
     }
 
-    opResult.setHeaders(response.getHeaders());
-  }
+    /**
+     * 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.
+     */
+    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());
+        }
+
+        return clientInstance.getClient();
 
-  private class GetRestOperation implements RestOperation {
-    public ClientResponse processOperation(Builder builder) {
-      return builder.get(ClientResponse.class);
     }
 
-    public RequestType getRequestType() {
-      return RequestType.GET;
+    /**
+     * 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 (Exception error) {
+            initClient.setCaughtException(error);
+        }
+
+        return initClient;
+
     }
-  }
 
-  private class PutRestOperation implements RestOperation {
-    public ClientResponse processOperation(Builder builder) {
-      return builder.put(ClientResponse.class);
+
+    /**
+     * This method populates the fields of an {@link OperationResult} instance based on the contents of a
+     * {@link Response} received in response to a REST request.
+     */
+    private void populateOperationResult(Response response, OperationResult opResult) {
+
+        // If we got back a NULL response, then just produce a generic
+        // error code and result indicating this.
+        if (response == null) {
+            opResult.setResultCode(500);
+            opResult.setFailureCause("Client response was null");
+            return;
+        }
+
+        int statusCode = response.getStatus();
+        opResult.setResultCode(statusCode);
+
+        if (opResult.wasSuccessful()) {
+            if (statusCode != Response.Status.NO_CONTENT.getStatusCode()) {
+                opResult.setResult(response.readEntity(String.class));
+            }
+        } else {
+            opResult.setFailureCause(response.readEntity(String.class));
+        }
+
+        opResult.setHeaders(convertHeaderObjectsToString(response.getHeaders()));
     }
 
-    public RequestType getRequestType() {
-      return RequestType.PUT;
+    private MultivaluedMap<String, String> convertHeaderObjectsToString(MultivaluedMap<String, Object> headers) {
+        MultivaluedMap<String, String> result = new MultivaluedHashMap<>();
+        headers.forEach((k, v) -> result.addAll(k, v.stream().map(Object::toString).collect(Collectors.toList())));
+        return result;
     }
-  }
 
-  private class PostRestOperation implements RestOperation {
-    public ClientResponse processOperation(Builder builder) {
-      return builder.post(ClientResponse.class);
+    private class GetRestOperation implements RestOperation {
+        @Override
+        public Response processOperation(Builder builder, String payload, MediaType contentType) {
+            return builder.get();
+        }
+
+        @Override
+        public RequestType getRequestType() {
+            return RequestType.GET;
+        }
     }
 
-    public RequestType getRequestType() {
-      return RequestType.POST;
+    private class PutRestOperation implements RestOperation {
+        @Override
+        public Response processOperation(Builder builder, String payload, MediaType contentType) {
+            return builder.put(Entity.entity(payload, contentType));
+        }
+
+        @Override
+        public RequestType getRequestType() {
+            return RequestType.PUT;
+        }
     }
-  }
 
-  private class DeleteRestOperation implements RestOperation {
-    public ClientResponse processOperation(Builder builder) {
-      return builder.delete(ClientResponse.class);
+    private class PostRestOperation implements RestOperation {
+        @Override
+        public Response processOperation(Builder builder, String payload, MediaType contentType) {
+            return builder.post(Entity.entity(payload, contentType));
+        }
+
+        @Override
+        public RequestType getRequestType() {
+            return RequestType.POST;
+        }
     }
 
-    public RequestType getRequestType() {
-      return RequestType.DELETE;
+    private class DeleteRestOperation implements RestOperation {
+        @Override
+        public Response processOperation(Builder builder, String payload, MediaType contentType) {
+            return builder.delete();
+        }
+
+        @Override
+        public RequestType getRequestType() {
+            return RequestType.DELETE;
+        }
     }
-  }
-  
-  private class HeadRestOperation implements RestOperation {
-    public ClientResponse processOperation(Builder builder) {
-      return builder.head();
+
+    private class HeadRestOperation implements RestOperation {
+        @Override
+        public Response processOperation(Builder builder, String payload, MediaType contentType) {
+            return builder.head();
+        }
+
+        @Override
+        public RequestType getRequestType() {
+            return RequestType.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.
+         */
+        @Override
+        public Response processOperation(Builder builder, String payload, MediaType contentType) {
+            builder = builder.header("X-HTTP-Method-Override", "PATCH");
+            return builder.post(Entity.entity(payload, contentType));
+        }
+
+        @Override
+        public RequestType getRequestType() {
+            return RequestType.PATCH;
+        }
     }
-  }
 
-  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.
+     * Interface used wrap a Jersey REST call using a functional interface.
      */
-    public ClientResponse processOperation(Builder builder) {
-      builder = builder.header("X-HTTP-Method-Override", "PATCH");
-      return builder.post(ClientResponse.class);
+    private interface RestOperation {
+
+        /**
+         * Method used to wrap the functionality of making a REST call out to the endpoint.
+         * 
+         * @param builder the Jersey builder used to make the request
+         * @param payload the request payload
+         * @param contentType the content type of the payload
+         * @return the response from the REST endpoint
+         */
+        public Response processOperation(Builder builder, String payload, MediaType contentType);
+
+        /**
+         * Returns the REST request type.
+         */
+        public RequestType getRequestType();
+
+        /**
+         * The supported REST request types.
+         */
+        public enum RequestType {
+            GET, PUT, POST, DELETE, PATCH, HEAD
+        }
     }
 
-    public RequestType getRequestType() {
-      return RequestType.PATCH;
-    }
-  }
+    /*
+     * 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;
+        }
 
-  /**
-   * Interface used wrap a Jersey REST call using a functional interface.
-   */
-  private interface RestOperation {
+        public Client getClient() {
+            return client;
+        }
 
-    /**
-     * Method used to wrap the functionality of making a REST call out to the endpoint.
-     *
-     * @param builder the Jersey builder used to make the request
-     * @return the response from the REST endpoint
-     */
-    public ClientResponse processOperation(Builder builder);
+        public void setClient(Client client) {
+            this.client = client;
+        }
 
-    /**
-     * Returns the REST request type.
-     */
-    public RequestType getRequestType();
+        public Throwable getCaughtException() {
+            return caughtException;
+        }
+
+        public void setCaughtException(Throwable caughtException) {
+            this.caughtException = caughtException;
+        }
+
+    }
 
-    /**
-     * The supported REST request types.
-     */
-    public enum RequestType {
-      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;
-    }
-  
-  }
-  
 }
index 26c5fdf..38a8558 100644 (file)
@@ -22,281 +22,262 @@ package org.onap.aai.restclient.rest;
 \r
 import java.io.FileInputStream;\r
 import java.security.KeyStore;\r
-import java.security.cert.X509Certificate;\r
-\r
-import javax.net.ssl.HostnameVerifier;\r
 import javax.net.ssl.KeyManagerFactory;\r
 import javax.net.ssl.SSLContext;\r
 import javax.net.ssl.SSLSession;\r
 import javax.net.ssl.TrustManager;\r
-import javax.net.ssl.X509TrustManager;\r
-\r
+import javax.ws.rs.client.Client;\r
+import javax.ws.rs.client.ClientBuilder;\r
+import org.glassfish.jersey.client.ClientProperties;\r
 import org.onap.aai.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
- * 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
+ * This is a generic REST Client builder with flexible security validation. Sometimes it's nice to be able to disable\r
+ * server chain cert validation and hostname validation to work-around lab issues, but at the same time be able to\r
+ * provide complete validation with client cert + hostname + server cert chain validation. I used the ModelLoader REST\r
+ * client as a base and merged in the TSUI client I wrote which also validates the server hostname and server\r
+ * certificate chain.\r
  */\r
 public class RestClientBuilder {\r
 \r
-  public static final boolean DEFAULT_VALIDATE_SERVER_HOST = false;\r
-  public static final boolean DEFAULT_VALIDATE_CERT_CHAIN = false;\r
-  public static final String DEFAULT_CLIENT_CERT_FILENAME = null;\r
-  public static final String DEFAULT_CERT_PASSWORD = null;\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.SSL_CERT;\r
-  public static final String DEFAULT_BASIC_AUTH_USERNAME = "";\r
-  public static final String DEFAULT_BASIC_AUTH_PASSWORD = "";\r
-  public static final String DEFAULT_SSL_PROTOCOL = "TLS";\r
-\r
-  private static final String KEYSTORE_ALGORITHM = "SunX509";\r
-  private static final String KEYSTORE_TYPE = "PKCS12";\r
-  private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";\r
-\r
-  private boolean validateServerHostname;\r
-  private boolean validateServerCertChain;\r
-  private String clientCertFileName;\r
-  private String clientCertPassword;\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
-  private String sslProtocol;\r
-\r
-  /**\r
-   * Rest Client Builder.\r
-   */\r
-  public RestClientBuilder() {\r
-    validateServerHostname = DEFAULT_VALIDATE_SERVER_HOST;\r
-    validateServerCertChain = DEFAULT_VALIDATE_CERT_CHAIN;\r
-    clientCertFileName = DEFAULT_CLIENT_CERT_FILENAME;\r
-    clientCertPassword = DEFAULT_CERT_PASSWORD;\r
-    truststoreFilename = DEFAULT_TRUST_STORE_FILENAME;\r
-    connectTimeoutInMs = DEFAULT_CONNECT_TIMEOUT_MS;\r
-    readTimeoutInMs = DEFAULT_READ_TIMEOUT_MS;\r
-    authenticationMode = DEFAULT_AUTH_MODE;\r
-    basicAuthUsername = DEFAULT_BASIC_AUTH_USERNAME;\r
-    basicAuthPassword = DEFAULT_BASIC_AUTH_PASSWORD;\r
-    sslProtocol = DEFAULT_SSL_PROTOCOL;\r
-  }\r
-\r
-  public boolean isValidateServerHostname() {\r
-    return validateServerHostname;\r
-  }\r
-\r
-  public void setValidateServerHostname(boolean validateServerHostname) {\r
-    this.validateServerHostname = validateServerHostname;\r
-  }\r
-\r
-  public boolean isValidateServerCertChain() {\r
-    return validateServerCertChain;\r
-  }\r
-\r
-  public void setValidateServerCertChain(boolean validateServerCertChain) {\r
-    this.validateServerCertChain = validateServerCertChain;\r
-  }\r
-\r
-  public String getClientCertFileName() {\r
-    return clientCertFileName;\r
-  }\r
-\r
-  public void setClientCertFileName(String clientCertFileName) {\r
-    this.clientCertFileName = clientCertFileName;\r
-  }\r
-\r
-  public String getClientCertPassword() {\r
-    return clientCertPassword;\r
-  }\r
-\r
-  public void setClientCertPassword(String clientCertPassword) {\r
-    this.clientCertPassword = clientCertPassword;\r
-  }\r
-\r
-  public String getTruststoreFilename() {\r
-    return truststoreFilename;\r
-  }\r
-\r
-  public void setTruststoreFilename(String truststoreFilename) {\r
-    this.truststoreFilename = truststoreFilename;\r
-  }\r
-\r
-  public int getConnectTimeoutInMs() {\r
-    return connectTimeoutInMs;\r
-  }\r
-\r
-  public void setConnectTimeoutInMs(int connectTimeoutInMs) {\r
-    this.connectTimeoutInMs = connectTimeoutInMs;\r
-  }\r
-\r
-  public int getReadTimeoutInMs() {\r
-    return readTimeoutInMs;\r
-  }\r
-\r
-  public void setReadTimeoutInMs(int readTimeoutInMs) {\r
-    this.readTimeoutInMs = readTimeoutInMs;\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
-  public String getSslProtocol() {\r
-    return sslProtocol;\r
-  }\r
-\r
-  public void setSslProtocol(String sslProtocol) {\r
-    this.sslProtocol = sslProtocol;\r
-  }\r
-\r
-  /**\r
-   * Returns Client configured for SSL\r
-   */\r
-  public Client getClient() throws Exception {\r
-\r
-    switch (authenticationMode) {\r
-      case SSL_BASIC:\r
-      case SSL_CERT:\r
-        return getClient(true);\r
-\r
-      default:\r
-        // return basic non-authenticating HTTP client\r
-        return getClient(false);\r
+    public static final boolean DEFAULT_VALIDATE_SERVER_HOST = false;\r
+    public static final boolean DEFAULT_VALIDATE_CERT_CHAIN = false;\r
+    public static final String DEFAULT_CLIENT_CERT_FILENAME = null;\r
+    public static final String DEFAULT_CERT_PASSWORD = null;\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.SSL_CERT;\r
+    public static final String DEFAULT_BASIC_AUTH_USERNAME = "";\r
+    public static final String DEFAULT_BASIC_AUTH_PASSWORD = "";\r
+    public static final String DEFAULT_SSL_PROTOCOL = "TLS";\r
+\r
+    private static final String KEYSTORE_ALGORITHM = "SunX509";\r
+    private static final String KEYSTORE_TYPE = "PKCS12";\r
+    private static final String TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore";\r
+\r
+    private boolean validateServerHostname;\r
+    private boolean validateServerCertChain;\r
+    private String clientCertFileName;\r
+    private String clientCertPassword;\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
+    private String sslProtocol;\r
+\r
+    /**\r
+     * Rest Client Builder.\r
+     */\r
+    public RestClientBuilder() {\r
+        validateServerHostname = DEFAULT_VALIDATE_SERVER_HOST;\r
+        validateServerCertChain = DEFAULT_VALIDATE_CERT_CHAIN;\r
+        clientCertFileName = DEFAULT_CLIENT_CERT_FILENAME;\r
+        clientCertPassword = DEFAULT_CERT_PASSWORD;\r
+        truststoreFilename = DEFAULT_TRUST_STORE_FILENAME;\r
+        connectTimeoutInMs = DEFAULT_CONNECT_TIMEOUT_MS;\r
+        readTimeoutInMs = DEFAULT_READ_TIMEOUT_MS;\r
+        authenticationMode = DEFAULT_AUTH_MODE;\r
+        basicAuthUsername = DEFAULT_BASIC_AUTH_USERNAME;\r
+        basicAuthPassword = DEFAULT_BASIC_AUTH_PASSWORD;\r
+        sslProtocol = DEFAULT_SSL_PROTOCOL;\r
+    }\r
+\r
+    public boolean isValidateServerHostname() {\r
+        return validateServerHostname;\r
+    }\r
+\r
+    public void setValidateServerHostname(boolean validateServerHostname) {\r
+        this.validateServerHostname = validateServerHostname;\r
+    }\r
+\r
+    public boolean isValidateServerCertChain() {\r
+        return validateServerCertChain;\r
+    }\r
+\r
+    public void setValidateServerCertChain(boolean validateServerCertChain) {\r
+        this.validateServerCertChain = validateServerCertChain;\r
+    }\r
+\r
+    public String getClientCertFileName() {\r
+        return clientCertFileName;\r
+    }\r
+\r
+    public void setClientCertFileName(String clientCertFileName) {\r
+        this.clientCertFileName = clientCertFileName;\r
+    }\r
+\r
+    public String getClientCertPassword() {\r
+        return clientCertPassword;\r
+    }\r
+\r
+    public void setClientCertPassword(String clientCertPassword) {\r
+        this.clientCertPassword = clientCertPassword;\r
+    }\r
+\r
+    public String getTruststoreFilename() {\r
+        return truststoreFilename;\r
+    }\r
+\r
+    public void setTruststoreFilename(String truststoreFilename) {\r
+        this.truststoreFilename = truststoreFilename;\r
+    }\r
+\r
+    public int getConnectTimeoutInMs() {\r
+        return connectTimeoutInMs;\r
+    }\r
+\r
+    public void setConnectTimeoutInMs(int connectTimeoutInMs) {\r
+        this.connectTimeoutInMs = connectTimeoutInMs;\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
-      if (truststoreFilename != null) {\r
-        System.setProperty(TRUST_STORE_PROPERTY, truststoreFilename);\r
-      } else {\r
-        throw new IllegalArgumentException("Trust store filename must be set!");\r
-      }\r
-\r
-    // Set up the SSL context, keystore, etc. to use for our connection\r
-    // to the AAI.\r
-    SSLContext ctx = SSLContext.getInstance(sslProtocol);\r
-    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM);\r
-    KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE);\r
-\r
-    char[] pwd = null;\r
-    if (clientCertPassword != null) {\r
-      pwd = clientCertPassword.toCharArray();\r
+    public int getReadTimeoutInMs() {\r
+        return readTimeoutInMs;\r
     }\r
 \r
-    if (clientCertFileName != null) {\r
-      FileInputStream fin = new FileInputStream(clientCertFileName);\r
+    public void setReadTimeoutInMs(int readTimeoutInMs) {\r
+        this.readTimeoutInMs = readTimeoutInMs;\r
+    }\r
+\r
+    public RestAuthenticationMode getAuthenticationMode() {\r
+        return authenticationMode;\r
+    }\r
 \r
-      // Load the keystore and initialize the key manager factory.\r
-      ks.load(fin, pwd);\r
-      kmf.init(ks, pwd);\r
+    public void setAuthenticationMode(RestAuthenticationMode authenticationMode) {\r
+        this.authenticationMode = authenticationMode;\r
+    }\r
 \r
-      ctx.init(kmf.getKeyManagers(), trustAllCerts, null);\r
-    } else {\r
-      ctx.init(null, trustAllCerts, null);\r
+    public String getBasicAuthUsername() {\r
+        return basicAuthUsername;\r
     }\r
 \r
-    // Are we performing validation of the server host name?\r
-    if (validateServerHostname) {\r
-      clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
-          new HTTPSProperties(null, ctx));\r
-\r
-    } else {\r
-      clientConfig.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,\r
-          new HTTPSProperties(new HostnameVerifier() {\r
-            @Override\r
-            public boolean verify(String str, SSLSession sslSession) {\r
-              return true;\r
-            }\r
-          }, ctx));\r
+    public void setBasicAuthUsername(String basicAuthUsername) {\r
+        this.basicAuthUsername = basicAuthUsername;\r
     }\r
-  }\r
 \r
+    public String getBasicAuthPassword() {\r
+        return basicAuthPassword;\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
+    public void setBasicAuthPassword(String basicAuthPassword) {\r
+        this.basicAuthPassword = basicAuthPassword;\r
+    }\r
 \r
-    ClientConfig clientConfig = new DefaultClientConfig();\r
+    public String getSslProtocol() {\r
+        return sslProtocol;\r
+    }\r
 \r
-    if (useSsl) {\r
-      setupSecureSocketLayerClientConfig(clientConfig);\r
+    public void setSslProtocol(String sslProtocol) {\r
+        this.sslProtocol = sslProtocol;\r
     }\r
 \r
-    // Finally, create and initialize our client...\r
-    Client client = null;\r
-    client = Client.create(clientConfig);\r
-    client.setConnectTimeout(connectTimeoutInMs);\r
-    client.setReadTimeout(readTimeoutInMs);\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
+     * Returns Client configured for SSL\r
+     */\r
+    public Client getClient() throws Exception {\r
+\r
+        switch (authenticationMode) {\r
+            case SSL_BASIC:\r
+            case SSL_CERT:\r
+                return getClient(true);\r
+\r
+            default:\r
+                // return basic non-authenticating HTTP client\r
+                return getClient(false);\r
+        }\r
+\r
+    }\r
+\r
+    protected void setupSecureSocketLayerClientConfig(ClientBuilder builder) throws Exception {\r
+        // Check to see if we need to perform proper validation of\r
+        // the certificate chains.\r
+        TrustManager[] trustAllCerts = null;\r
+        if (truststoreFilename != null) {\r
+            System.setProperty(TRUST_STORE_PROPERTY, truststoreFilename);\r
+        } else {\r
+            throw new IllegalArgumentException("Trust store filename must be set!");\r
+        }\r
+\r
+        // Set up the SSL context, keystore, etc. to use for our connection\r
+        // to the AAI.\r
+        SSLContext ctx = SSLContext.getInstance(sslProtocol);\r
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYSTORE_ALGORITHM);\r
+        KeyStore ks = KeyStore.getInstance(KEYSTORE_TYPE);\r
+\r
+        char[] pwd = null;\r
+        if (clientCertPassword != null) {\r
+            pwd = clientCertPassword.toCharArray();\r
+        }\r
+\r
+        if (clientCertFileName != null) {\r
+            FileInputStream fin = new FileInputStream(clientCertFileName);\r
+\r
+            // Load the keystore and initialize the key manager factory.\r
+            ks.load(fin, pwd);\r
+            kmf.init(ks, pwd);\r
+\r
+            ctx.init(kmf.getKeyManagers(), trustAllCerts, null);\r
+        } else {\r
+            ctx.init(null, trustAllCerts, null);\r
+        }\r
+\r
+        builder.sslContext(ctx);\r
+\r
+        // Are we performing validation of the server host name?\r
+        if (!validateServerHostname) {\r
+            builder.hostnameVerifier((String str, SSLSession sslSession) -> true);\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
+        // Finally, create and initialize our client...\r
+        ClientBuilder builder = ClientBuilder.newBuilder();\r
+        if (useSsl) {\r
+            setupSecureSocketLayerClientConfig(builder);\r
+        }\r
+        Client client = builder.build();\r
+        client.property(ClientProperties.CONNECT_TIMEOUT, connectTimeoutInMs);\r
+        client.property(ClientProperties.READ_TIMEOUT, readTimeoutInMs);\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 (non-Javadoc)\r
+     * \r
+     * @see java.lang.Object#toString()\r
+     */\r
+    @Override\r
+    public String toString() {\r
+        return "RestClientBuilder [validateServerHostname=" + validateServerHostname + ", validateServerCertChain="\r
+                + 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
index 75d2b8d..2d1ce83 100644 (file)
@@ -44,6 +44,10 @@ HEALTH_CHECK_SUCCESS=\
     AC0006I|\
     Successfully established connection to {0} at {1}
 
+HTTP_REQUEST_TIME_WITH_RETRIES=\
+    AC0007I|\
+    {0} request at url = {1} operation time = {2} attempt number = {3}
+
 HTTP_REQUEST_INTERRUPTED=\
     AC2001E|\
     {0} request interrupted while sleeping at url = {1} with cause = {2}
index 6f18f9a..c002b97 100644 (file)
@@ -28,13 +28,10 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import javax.ws.rs.core.MultivaluedHashMap;
 import javax.ws.rs.core.MultivaluedMap;
-
 import org.junit.Before;
 import org.junit.Test;
-import org.onap.aai.restclient.client.OperationResult;
-
-import com.sun.jersey.core.util.MultivaluedMapImpl;
 
 public class OperationResultTest {
 
@@ -63,7 +60,7 @@ public class OperationResultTest {
     assertEquals(opResult.getResult(),"no content found");
     assertTrue(opResult.wasSuccessful());
     
-    MultivaluedMap<String,String> multiMap = new MultivaluedMapImpl();
+    MultivaluedMap<String,String> multiMap = new MultivaluedHashMap<>();
     multiMap.add("p1","v1");
     multiMap.add("p2","v2");
     opResult.setHeaders(multiMap);
index 5eb7f1f..9fe09a1 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * ============LICENSE_START===========================================================================================
  * Copyright (c) 2017 AT&T Intellectual Property.
- * Copyright (c) 2017 Amdocs 
- * Modification Copyright (c) 2018 IBM. 
+ * Copyright (c) 2017 Amdocs
+ * Modification Copyright (c) 2018 IBM.
  * All rights reserved.
  * =====================================================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
@@ -14,7 +14,7 @@
  * 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.onap.aai.restclient.client;
@@ -24,63 +24,59 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.Invocation.Builder;
+import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
-import org.onap.aai.restclient.client.OperationResult;
-import org.onap.aai.restclient.client.RestClient;
 import org.onap.aai.restclient.enums.RestAuthenticationMode;
 import org.onap.aai.restclient.rest.RestClientBuilder;
 
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.UniformInterfaceException;
-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 static final String TEST_URL = "http://localhost:9000/aai/v7";
 
-    private final MultivaluedMapImpl emptyMap = new MultivaluedMapImpl();
+    private final MultivaluedMap<String, String> emptyMap = new MultivaluedHashMap<>();
 
     private RestClientBuilder mockClientBuilder;
     private Client mockedClient;
-    private WebResource mockedWebResource;
+    private WebTarget mockedWebTarget;
     private Builder mockedBuilder;
-    private ClientResponse mockedClientResponse;
+    private Response mockedClientResponse;
 
     /**
      * Test case initialization
-     * 
+     *
      * @throws Exception the exception
      */
-    @SuppressWarnings("unchecked")
     @Before
     public void init() throws Exception {
-        mockedClientResponse = Mockito.mock(ClientResponse.class);
+        mockedClientResponse = Mockito.mock(Response.class);
         setResponseStatus(Response.Status.OK);
-        Mockito.when(mockedClientResponse.getHeaders()).thenReturn(emptyMap);
-        Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("hello");
+        Mockito.when(mockedClientResponse.getHeaders()).thenReturn(new MultivaluedHashMap<>());
+        Mockito.when(mockedClientResponse.readEntity(String.class)).thenReturn("hello");
 
         mockedBuilder = Mockito.mock(Builder.class);
-        Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
-        Mockito.when(mockedBuilder.post(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
-        Mockito.when(mockedBuilder.put(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
-        Mockito.when(mockedBuilder.delete(Mockito.any(Class.class))).thenReturn(mockedClientResponse);
+        Mockito.when(mockedBuilder.get()).thenReturn(mockedClientResponse);
+        Mockito.when(mockedBuilder.post(Mockito.any())).thenReturn(mockedClientResponse);
+        Mockito.when(mockedBuilder.put(Mockito.any())).thenReturn(mockedClientResponse);
+        Mockito.when(mockedBuilder.delete()).thenReturn(mockedClientResponse);
         Mockito.when(mockedBuilder.head()).thenReturn(mockedClientResponse);
+        Mockito.when(mockedBuilder.accept(Mockito.any(MediaType.class))).thenReturn(mockedBuilder);
 
-        mockedWebResource = Mockito.mock(WebResource.class);
-        Mockito.when(mockedWebResource.accept(Mockito.<MediaType>anyVararg())).thenReturn(mockedBuilder);
+        mockedWebTarget = Mockito.mock(WebTarget.class);
+        Mockito.when(mockedWebTarget.request()).thenReturn(mockedBuilder);
 
         mockedClient = Mockito.mock(Client.class);
-        Mockito.when(mockedClient.resource(Mockito.anyString())).thenReturn(mockedWebResource);
+        Mockito.when(mockedClient.target(Mockito.anyString())).thenReturn(mockedWebTarget);
 
         mockClientBuilder = Mockito.mock(RestClientBuilder.class);
         Mockito.when(mockClientBuilder.getClient()).thenReturn(mockedClient);
@@ -170,24 +166,24 @@ public class RestfulClientTest {
         assertNull(result.getResult());
         assertNull(result.getFailureCause());
     }
-    
+
     @Test
     public void validateSuccessfulPost_withMultivaluedHeader() throws Exception {
         RestClient restClient = buildClient();
 
-        MultivaluedMapImpl headerMap = new MultivaluedMapImpl();
-        
+        MultivaluedMap<String, String> headerMap = new MultivaluedHashMap<>();
+
         headerMap.add("txnId", "123");
         headerMap.add("txnId", "456");
         headerMap.add("txnId", "789");
 
         OperationResult result = restClient.post(TEST_URL, "", headerMap, MediaType.APPLICATION_JSON_TYPE,
-            MediaType.APPLICATION_JSON_TYPE);
+                MediaType.APPLICATION_JSON_TYPE);
 
-        // capture the txnId header from the outgoing request  
+        // capture the txnId header from the outgoing request
         ArgumentCaptor<String> txnIdHeaderName = ArgumentCaptor.forClass(String.class);
         ArgumentCaptor<String> txnIdHeaderValue = ArgumentCaptor.forClass(String.class);
-        
+
         Mockito.verify(mockedBuilder, Mockito.atLeast(1)).header(txnIdHeaderName.capture(), txnIdHeaderValue.capture());
         assertEquals("123;456;789", txnIdHeaderValue.getValue());
 
@@ -220,7 +216,7 @@ public class RestfulClientTest {
     @Test
     public void validateResourceNotFoundGet() throws Exception {
         setResponseStatus(Response.Status.NOT_FOUND);
-        Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("RNF");
+        Mockito.when(mockedClientResponse.readEntity(String.class)).thenReturn("RNF");
 
         OperationResult result = buildClient().get(TEST_URL, emptyMap, MediaType.APPLICATION_JSON_TYPE);
 
@@ -249,7 +245,7 @@ public class RestfulClientTest {
 
     @Test
     public void validateHealthCheckFailureWithThrownException() throws Exception {
-        Mockito.when(mockedBuilder.get(Mockito.any(Class.class))).thenThrow(new IllegalArgumentException("error"));
+        Mockito.when(mockedBuilder.get()).thenThrow(new IllegalArgumentException("error"));
 
         boolean targetServiceHealthy =
                 buildClient().healthCheck("http://localhost:9000/aai/util/echo", "startSerice", "targetService");
@@ -260,7 +256,7 @@ public class RestfulClientTest {
     @Test
     public void validateSuccessfulGetWithRetries() throws Exception {
         Mockito.when(mockedClientResponse.getStatus()).thenReturn(408).thenReturn(Response.Status.OK.getStatusCode());
-        Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("error").thenReturn("ok");
+        Mockito.when(mockedClientResponse.readEntity(String.class)).thenReturn("error").thenReturn("ok");
 
         OperationResult result = buildClient().get(TEST_URL, emptyMap, MediaType.APPLICATION_JSON_TYPE, 3);
 
@@ -273,7 +269,7 @@ public class RestfulClientTest {
     @Test
     public void validateFailedGetWithRetriesCausedByResourceNotFound() throws Exception {
         setResponseStatus(Response.Status.NOT_FOUND);
-        Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("error").thenReturn("ok");
+        Mockito.when(mockedClientResponse.readEntity(String.class)).thenReturn("error").thenReturn("ok");
 
         OperationResult result = buildClient().get(TEST_URL, emptyMap, MediaType.APPLICATION_JSON_TYPE, 3);
 
@@ -286,7 +282,7 @@ public class RestfulClientTest {
     @Test
     public void validateFailedGetAfterMaxRetries() throws Exception {
         setResponseStatus(Response.Status.INTERNAL_SERVER_ERROR);
-        Mockito.when(mockedClientResponse.getEntity(String.class)).thenReturn("error");
+        Mockito.when(mockedClientResponse.readEntity(String.class)).thenReturn("error");
 
         OperationResult result = buildClient().get(TEST_URL, emptyMap, MediaType.APPLICATION_JSON_TYPE, 3);
 
@@ -315,7 +311,6 @@ public class RestfulClientTest {
         assertNull(result.getFailureCause());
     }
 
-
     @Test
     public void validateSuccessfulHead() throws Exception {
         OperationResult result = buildClient().head(TEST_URL, emptyMap, MediaType.APPLICATION_JSON_TYPE);
@@ -323,7 +318,6 @@ public class RestfulClientTest {
         assertEquals(Response.Status.OK.getStatusCode(), result.getResultCode());
         assertNotNull(result.getResult());
         assertNull(result.getFailureCause());
-
     }
 
     @Test
@@ -335,12 +329,11 @@ public class RestfulClientTest {
         assertEquals(Response.Status.OK.getStatusCode(), result.getResultCode());
         assertNotNull(result.getResult());
         assertNull(result.getFailureCause());
-
     }
 
     @Test
     public void testGetClient() throws Exception {
-        RestClientBuilder restClientBuilder= new RestClientBuilder();
+        RestClientBuilder restClientBuilder = new RestClientBuilder();
         restClientBuilder.setAuthenticationMode(RestAuthenticationMode.SSL_BASIC);
         restClientBuilder.setTruststoreFilename("truststore");
         assertTrue(restClientBuilder.getClient() instanceof Client);
@@ -348,7 +341,7 @@ public class RestfulClientTest {
 
     /**
      * Specify the status code of the response object returned by the mocked client
-     * 
+     *
      * @param status object storing the status code to mock in the ClientResponse
      */
     private void setResponseStatus(Status status) {
@@ -360,9 +353,9 @@ public class RestfulClientTest {
      */
     private void setResponseToNoContent() {
         setResponseStatus(Response.Status.NO_CONTENT);
-        // The Jersey client throws an exception when getEntity() is called following a 204 response
-        UniformInterfaceException uniformInterfaceException = new UniformInterfaceException(mockedClientResponse);
-        Mockito.when(mockedClientResponse.getEntity(String.class)).thenThrow(uniformInterfaceException);
+        // The Jersey client throws an exception when readEntity() is called following a 204 response
+        ProcessingException processingException = new ProcessingException("No content");
+        Mockito.when(mockedClientResponse.readEntity(String.class)).thenThrow(processingException);
     }
 
     /**
index 7155f9a..3878813 100644 (file)
@@ -26,243 +26,216 @@ import static org.junit.Assert.assertEquals;
 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 javax.ws.rs.client.Client;\r
 import org.junit.Before;\r
 import org.junit.Test;\r
 import org.onap.aai.restclient.enums.RestAuthenticationMode;\r
-import org.onap.aai.restclient.rest.RestClientBuilder;\r
-\r
-import com.sun.jersey.api.client.Client;\r
-import com.sun.jersey.client.urlconnection.HTTPSProperties;\r
 \r
 /**\r
- * This suite of tests is intended to exercise the functionality of the generice REST client\r
- * builder.\r
+ * This suite of tests is intended to exercise the functionality of the generice REST client builder.\r
  */\r
 public class RestClientBuilderTest {\r
 \r
-  /**\r
-   * Test case initialization\r
-   * \r
-   * @throws Exception the exception\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
-  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
-  \r
-  @Test\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
-  @Test\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
-  @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
-    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
-      assertNotNull(sslProps.getHostnameVerifier());\r
-    } else {\r
-      fail("Unexpected value for https properties object");\r
+    /**\r
+     * Test case initialization\r
+     *\r
+     * @throws Exception the exception\r
+     */\r
+    @Before\r
+    public void init() throws Exception {}\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
-  }\r
-\r
-  @Test (expected=IllegalArgumentException.class)\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
-  \r
-  @Test (expected=IllegalArgumentException.class)\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
-  }\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
+    @Test\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
-  }\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
-  @Test\r
-  public void validateSslProtocolConfiguration() throws Exception {\r
-    \r
-    RestClientBuilder restClientBuilder = new RestClientBuilder();\r
-    assertEquals(RestClientBuilder.DEFAULT_SSL_PROTOCOL, restClientBuilder.getSslProtocol());\r
-    \r
-    restClientBuilder.setSslProtocol("TLSv1.2");\r
-    assertEquals("TLSv1.2", restClientBuilder.getSslProtocol());\r
-    \r
-  }\r
-    \r
+\r
+    @Test\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
+    }\r
+\r
+\r
+    @Test\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
+    }\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
+        restClientBuilder.setTruststoreFilename("truststore");\r
+\r
+        Client client = restClientBuilder.getClient();\r
+        assertNotNull(client.getHostnameVerifier());\r
+        assertEquals("truststore", System.getProperty("javax.net.ssl.trustStore"));\r
+    }\r
+\r
+    @Test(expected = IllegalArgumentException.class)\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
+        restClientBuilder.getClient();\r
+    }\r
+\r
+    @Test(expected = IllegalArgumentException.class)\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
+        restClientBuilder.getClient();\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
+        // TODO\r
+        assertNotNull(client.getHostnameVerifier());\r
+        assertEquals("truststore", System.getProperty("javax.net.ssl.trustStore"));\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
+        // TODO\r
+        assertNull(client.getHostnameVerifier());\r
+        assertEquals("truststore", System.getProperty("javax.net.ssl.trustStore"));\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 truststore being\r
+         * null\r
+         */\r
+        restClientBuilder.getClient();\r
+\r
+    }\r
+\r
+    @Test\r
+    public void validateSslProtocolConfiguration() throws Exception {\r
+\r
+        RestClientBuilder restClientBuilder = new RestClientBuilder();\r
+        assertEquals(RestClientBuilder.DEFAULT_SSL_PROTOCOL, restClientBuilder.getSslProtocol());\r
+\r
+        restClientBuilder.setSslProtocol("TLSv1.2");\r
+        assertEquals("TLSv1.2", restClientBuilder.getSslProtocol());\r
+\r
+    }\r
+\r
 }\r