From: tgolabek Date: Wed, 23 May 2018 09:40:17 +0000 (+0200) Subject: Refactor of an AAIRestInterface X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=6d8fa7d179b8de802ae386b317ddd1214eac1c47;p=vid.git Refactor of an AAIRestInterface Refactor and some additional tests added Issue-ID: VID-229 Change-Id: I7b6865b8092e7265c0342e3b21d1510a96be7d4a Signed-off-by: tgolabek --- diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/exceptions/HttpClientBuilderException.java b/vid-app-common/src/main/java/org/onap/vid/aai/exceptions/HttpClientBuilderException.java new file mode 100644 index 000000000..8815c300a --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/exceptions/HttpClientBuilderException.java @@ -0,0 +1,12 @@ +package org.onap.vid.aai.exceptions; + +public class HttpClientBuilderException extends Exception { + + public HttpClientBuilderException() { + super(); + } + + public HttpClientBuilderException(Throwable cause) { + super(cause); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/exceptions/InvalidPropertyException.java b/vid-app-common/src/main/java/org/onap/vid/aai/exceptions/InvalidPropertyException.java new file mode 100644 index 000000000..d850ffbfd --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/exceptions/InvalidPropertyException.java @@ -0,0 +1,4 @@ +package org.onap.vid.aai.exceptions; + +public class InvalidPropertyException extends Exception { +} diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAIRestInterface.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAIRestInterface.java index 226850d2d..6f3b6e4a8 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/util/AAIRestInterface.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/AAIRestInterface.java @@ -19,360 +19,295 @@ */ package org.onap.vid.aai.util; +import com.att.eelf.configuration.EELFLogger; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; +import org.onap.vid.aai.exceptions.HttpClientBuilderException; +import org.onap.vid.aai.exceptions.InvalidPropertyException; +import org.onap.vid.utils.Logging; +import org.springframework.http.HttpMethod; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.KeyManagementException; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.Base64; -import java.util.Date; +import java.util.Optional; import java.util.UUID; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.Entity; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import com.att.eelf.configuration.EELFLogger; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.portalsdk.core.util.SystemProperties; -import org.eclipse.jetty.util.security.Password; -import org.onap.vid.utils.Logging; -import org.springframework.http.HttpMethod; -import static org.onap.vid.utils.Logging.getHttpServletRequest; +import static javax.ws.rs.core.Response.Status.OK; import static org.onap.vid.utils.Logging.requestIdHeaderKey; - /** * The Class AAIRestInterface. */ public class AAIRestInterface { - /** The logger. */ - EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AAIRestInterface.class); - - final private EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("aai"); - - /** The Constant dateFormat. */ - final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); - - /** The client. */ - private static Client client = null; - - /** The rest srvr base URL. */ - private String restSrvrBaseURL; - - /** The certificate path. */ - public String certificatePath = ""; - - private String START_STRING = " start"; - - private String TRANSACTION_ID_HEADER = "X-TransactionId"; - private String FROM_APP_ID_HEADER = "X-FromAppId"; - private String SUCCESSFUL_API_MESSAGE=" REST api POST was successful!"; - private String URL_DECLERATION = ", url="; - - - - - - - /** - * Instantiates a new AAI rest interface. - * - * @param certPath the cert path - */ - public AAIRestInterface(String certPath) - { - certificatePath = certPath; - } - - /** - * Encode URL. - * - * @param nodeKey the node key - * @return the string - * @throws UnsupportedEncodingException the unsupported encoding exception - */ - public String encodeURL (String nodeKey) throws UnsupportedEncodingException { - return URLEncoder.encode(nodeKey, "UTF-8").replaceAll("\\+", "%20"); - } - - /** - * Inits the rest client. - */ - private void initRestClient() - { - String methodName = "initRestClient"; - - if (client == null) { - try { - client = HttpsAuthClient.getClient(certificatePath); - } - catch (KeyManagementException e){ - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== KeyManagementException in " + methodName + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== KeyManagementException in " + methodName + e.toString()); - } catch (Exception e) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== Exception in REST call to DB in initRestClient" + e.toString()); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== Exception in REST call to DB : " + e.toString()); - } - } - } - - /** - * Sets the rest srvr base URL. - * - * @param baseURL the base URL - */ - public void SetRestSrvrBaseURL(String baseURL) - { - if (baseURL == null) - { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== REST Server base URL cannot be null."); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== REST Server base URL cannot be null."); - } - - restSrvrBaseURL = baseURL; - } - - /** - * Gets the rest srvr base URL. - * - * @return the rest srvr base URL - */ - public String getRestSrvrBaseURL() - { - return restSrvrBaseURL; - } - - - /** - * Rest get. - * - * @param fromAppId the from app id - * @param transId the trans id - * @param requestUri the request uri - * @param xml the xml - * @return the string - * @throws UnsupportedEncodingException - */ - public Response RestGet(String fromAppId, String transId, String requestUri, boolean xml) throws UnsupportedEncodingException { - String methodName = "RestGet"; - - String responseType = MediaType.APPLICATION_JSON; - if (xml) - responseType = MediaType.APPLICATION_XML; - - initRestClient(); - - String clientCert = SystemProperties.getProperty(AAIProperties.AAI_USE_CLIENT_CERT); - - boolean useClientCert = false; - if (clientCert != null && - SystemProperties.getProperty(AAIProperties.AAI_USE_CLIENT_CERT).equalsIgnoreCase("true")) { - useClientCert = true; - } - String url = ""; - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + START_STRING); - - url = SystemProperties.getProperty(AAIProperties.AAI_SERVER_URL) + requestUri; - - - logger.debug(dateFormat.format(new Date()) + "<== " + url + " for the get REST API"); - Logging.logRequest(outgoingRequestsLogger, HttpMethod.GET, url); - - final Response cres; - if (useClientCert == true) { - cres = client.target(url) - .request() - .accept(responseType) - .header(TRANSACTION_ID_HEADER, transId) - .header(FROM_APP_ID_HEADER, fromAppId) - .header("Content-Type", MediaType.APPLICATION_JSON) - .header(requestIdHeaderKey, getHttpServletRequest().getHeader(requestIdHeaderKey)) - .get(); - } else { - - String vidUsername = SystemProperties.getProperty(AAIProperties.AAI_VID_USERNAME); - String vidPassword = Password.deobfuscate(SystemProperties.getProperty(AAIProperties.AAI_VID_PASSWD_X)); - String encodeThis = vidUsername + ":" + vidPassword; - - cres = client.target(url) - .request() - .accept(responseType) - .header(TRANSACTION_ID_HEADER, transId) - .header(FROM_APP_ID_HEADER, fromAppId) - .header("Content-Type", "application/json") - .header("Authorization", "Basic " + Base64.getEncoder().encodeToString(encodeThis.getBytes("utf-8"))) - .header(requestIdHeaderKey, getHttpServletRequest().getHeader(requestIdHeaderKey)) - .get(); - } - Logging.logResponse(outgoingRequestsLogger, HttpMethod.GET, url, cres); -// String r = cres.readEntity(String.class); - if (cres.getStatus() == 200) { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + SUCCESSFUL_API_MESSAGE); - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + methodName + SUCCESSFUL_API_MESSAGE); - } else { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName +" with status="+cres.getStatus()+URL_DECLERATION+url); - } - return cres; -// logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName +" resp=" + r ); -// return r; - } - - - /** - * Delete. - * - * @param sourceID the source ID - * @param transId the trans id - * @param path the path - * @return true, if successful - */ - public boolean Delete(String sourceID, String transId, String path) { - String methodName = "Delete"; - String url=""; - transId += ":" + UUID.randomUUID().toString(); - logger.debug(dateFormat.format(new Date()) + "<== " + methodName + START_STRING); - - initRestClient(); - String request = "{}"; - url = SystemProperties.getProperty(AAIProperties.AAI_SERVER_URL) + path; - Logging.logRequest(outgoingRequestsLogger, HttpMethod.DELETE, url); - final Response cres = client.target(url) - .request() - .accept(MediaType.APPLICATION_JSON) - .header(TRANSACTION_ID_HEADER, transId) - .header(FROM_APP_ID_HEADER, sourceID) - .header(requestIdHeaderKey, getHttpServletRequest().getHeader(requestIdHeaderKey)) - //.entity(request) - .delete(); - Logging.logResponse(outgoingRequestsLogger, HttpMethod.DELETE, url, cres); - if (cres.getStatus() == 404) { // resource not found - String msg = "Resource does not exist...: " + cres.getStatus() - + ":" + cres.readEntity(String.class); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + msg); - return false; - } else if (cres.getStatus() == 200 || cres.getStatus() == 204){ - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + "Resource " + url + " deleted"); - return true; - } else { - String msg = "Deleting Resource failed: " + cres.getStatus() - + ":" + cres.readEntity(String.class); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + msg); - } - - return false; - } - - - /** - * Rest put. - * - * @param fromAppId the from app id - * @param transId the trans id - * @param path the path - * @param payload the payload - * @param xml the xml - * @return the string - */ - public Response RestPut(String fromAppId, String transId, String path, String payload, boolean xml) { - String methodName = "RestPut"; - String url=""; - transId = UUID.randomUUID().toString(); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + START_STRING); - - try { - - String responseType = MediaType.APPLICATION_JSON; - if (xml) - responseType = "application/xml"; - - initRestClient(); - - url = SystemProperties.getProperty(AAIProperties.AAI_SERVER_URL) + path; - String vidUsername = SystemProperties.getProperty(AAIProperties.AAI_VID_USERNAME); - String vidPassword = Password.deobfuscate(SystemProperties.getProperty(AAIProperties.AAI_VID_PASSWD_X)); - String encodeThis = vidUsername + ":" + vidPassword; - - Logging.logRequest(outgoingRequestsLogger, HttpMethod.PUT, url, payload); - final Response cres = client.target(url) - .request() - .accept(responseType) - .header(TRANSACTION_ID_HEADER, transId) - .header(FROM_APP_ID_HEADER, fromAppId) - .header("Authorization", "Basic " + Base64.getEncoder().encodeToString(encodeThis.getBytes("utf-8"))) - .header(requestIdHeaderKey, getHttpServletRequest().getHeader(requestIdHeaderKey)) - .put(Entity.entity(payload, MediaType.APPLICATION_JSON)); - Logging.logResponse(outgoingRequestsLogger, HttpMethod.PUT, url, cres); - - if (cres.getStatus() == 200 && cres.getStatus() <= 299) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + methodName + URL_DECLERATION); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + URL_DECLERATION); - } else { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName +" with status="+cres.getStatus()+URL_DECLERATION+url); - } - return cres; - } catch (Exception e) { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + URL_DECLERATION+url+ ", Exception: " + e.toString()); - } - return null; - } - - - - /** - * Rest post. - * - * @param fromAppId the from app id - * @param transId the trans id - * @param path the path - * @param payload the payload - * @param xml the xml - * @return the string - */ - public Response RestPost(String fromAppId, String transId, String path, String payload, boolean xml) { - String methodName = "RestPost"; - String url=""; - transId = UUID.randomUUID().toString(); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + START_STRING); - - try { - - String responseType = MediaType.APPLICATION_JSON; - if (xml) - responseType = "application/xml"; - - initRestClient(); - - url = SystemProperties.getProperty(AAIProperties.AAI_SERVER_URL_BASE) + path; - String vidUsername = SystemProperties.getProperty(AAIProperties.AAI_VID_USERNAME); - String vidPassword = Password.deobfuscate(SystemProperties.getProperty(AAIProperties.AAI_VID_PASSWD_X)); - String encodeThis = vidUsername + ":" + vidPassword; - - Logging.logRequest(outgoingRequestsLogger, HttpMethod.POST, url, payload); - final Response cres = client.target(url) - .request() - .accept(responseType) - .header(TRANSACTION_ID_HEADER, transId) - .header(FROM_APP_ID_HEADER, fromAppId) - .header("Authorization", "Basic " + Base64.getEncoder().encodeToString(encodeThis.getBytes("utf-8"))) - .header(requestIdHeaderKey, getHttpServletRequest().getHeader(requestIdHeaderKey)) - .post(Entity.entity(payload, MediaType.APPLICATION_JSON)); - Logging.logResponse(outgoingRequestsLogger, HttpMethod.POST, url, cres); - - if (cres.getStatus() == 200 && cres.getStatus() <= 299) { - logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + methodName + URL_DECLERATION); - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + URL_DECLERATION); - } else { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + " with status="+cres.getStatus()+URL_DECLERATION+url); - } - return cres; - } catch (Exception e) { - logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + methodName + URL_DECLERATION+url+ ", Exception: " + e.toString()); - } - return null; - } + final private EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("aai"); + + /** + * The client. + */ + private static Client client = null; + + /** + * The rest srvr base URL. + */ + private String restSrvrBaseURL; + + private static final String START_STRING = " start"; + private static final String TRANSACTION_ID_HEADER = "X-TransactionId"; + private static final String FROM_APP_ID_HEADER = "X-FromAppId"; + private static final String SUCCESSFUL_API_MESSAGE = " REST api call was successful!"; + private static final String URL_DECLERATION = ", url="; + + private final LogHelper logHelper; + private final ServletRequestHelper servletRequestHelper; + private final SystemPropertyHelper systemPropertyHelper; + + /** + * Instantiates a new AAI rest interface. + * + * @param certPath the cert path + */ + public AAIRestInterface(String certPath) { + this.logHelper = new LogHelper(EELFLoggerDelegate.getLogger(AAIRestInterface.class)); + this.servletRequestHelper = new ServletRequestHelper(); + this.systemPropertyHelper = new SystemPropertyHelper(); + initRestClient(certPath); + } + + /** + * For testing purpose + */ + AAIRestInterface(String certPath, LogHelper logHelper, Optional client, + ServletRequestHelper servletRequestHelper, SystemPropertyHelper systemPropertyHelper){ + this.logHelper = logHelper; + this.servletRequestHelper = servletRequestHelper; + this.systemPropertyHelper = systemPropertyHelper; + if (client.isPresent()){ + this.client = client.get(); + }else{ + initRestClient(certPath); + } + + } + + /** + * Sets the rest srvr base URL. + * + * @param baseURL the base URL + */ + public void SetRestSrvrBaseURL(String baseURL) { + if (baseURL == null) { + logHelper.multilog("<== REST Server base URL cannot be null."); + } + restSrvrBaseURL = baseURL; + } + + /** + * Gets the rest srvr base URL. + * + * @return the rest srvr base URL + */ + public String getRestSrvrBaseURL() { + return restSrvrBaseURL; + } + + /** + * Rest get. + * + * @param fromAppId the from app id + * @param transId the trans id + * @param requestUri the request uri + * @param xml the xml + * @return the string + */ + public Response RestGet(String fromAppId, String transId, String requestUri, boolean xml) { + String methodName = "RestGet"; + + logHelper.logDebug(methodName + START_STRING); + logHelper.logDebug(systemPropertyHelper.getFullServicePath(requestUri) + " for the get REST API"); + Logging.logRequest(outgoingRequestsLogger, HttpMethod.GET, systemPropertyHelper.getFullServicePath(requestUri)); + Response response = null; + try { + Invocation.Builder requestBuilder = client.target(systemPropertyHelper.getFullServicePath(requestUri)) + .request() + .accept(xml ? MediaType.APPLICATION_XML : MediaType.APPLICATION_JSON) + .header(TRANSACTION_ID_HEADER, transId) + .header(FROM_APP_ID_HEADER, fromAppId) + .header("Content-Type", MediaType.APPLICATION_JSON) + .header(requestIdHeaderKey, servletRequestHelper.getServletRequest().getHeader(requestIdHeaderKey)); + response = systemPropertyHelper.isClientCertEnabled() ? requestBuilder.get() : authenticateRequest(requestBuilder) + .get(); + Logging.logResponse(outgoingRequestsLogger, HttpMethod.GET, systemPropertyHelper.getFullServicePath(requestUri), response); + if (response.getStatusInfo().equals(OK)) { + logHelper.multilog(methodName + SUCCESSFUL_API_MESSAGE); + } else { + logHelper.logDebug(methodName + " with status=" + response.getStatus() + URL_DECLERATION + systemPropertyHelper.getFullServicePath(requestUri)); + } + }catch (Exception e){ + logHelper.logDebug(getFailedResponseLogMessage(requestUri, methodName, e)); + } + return response; + } + + /** + * Delete. + * + * @param sourceID the source ID + * @param transId the trans id + * @param path the path + * @return true, if successful + */ + public boolean Delete(String sourceID, String transId, String path) { + String methodName = "Delete"; + transId += ":" + UUID.randomUUID().toString(); + logHelper.logDebug(methodName + START_STRING); + Boolean response = false; + try { + Logging.logRequest(outgoingRequestsLogger, HttpMethod.DELETE, systemPropertyHelper.getFullServicePath(path)); + final Response cres = client.target(systemPropertyHelper.getFullServicePath(path)) + .request() + .accept(MediaType.APPLICATION_JSON) + .header(TRANSACTION_ID_HEADER, transId) + .header(FROM_APP_ID_HEADER, sourceID) + .header(requestIdHeaderKey, servletRequestHelper.getServletRequest().getHeader(requestIdHeaderKey)) + .delete(); + Logging.logResponse(outgoingRequestsLogger, HttpMethod.DELETE, systemPropertyHelper.getFullServicePath(path), cres); + if (cres.getStatusInfo().equals(Response.Status.NOT_FOUND)) { + logHelper.logDebug("Resource does not exist...: " + cres.getStatus() + + ":" + cres.readEntity(String.class)); + response = false; + } else if (cres.getStatusInfo().equals(OK) || cres.getStatusInfo().equals(Response.Status.NO_CONTENT)) { + logHelper.logDebug("Resource " + systemPropertyHelper.getFullServicePath(path) + " deleted"); + response = true; + } else { + logHelper.logDebug("Deleting Resource failed: " + cres.getStatus() + + ":" + cres.readEntity(String.class)); + } + }catch(Exception e){ + logHelper.logDebug(getFailedResponseLogMessage(path, methodName, e)); + } + return response; + } + + /** + * Rest put. + * + * @param fromAppId the from app id + * @param transId the trans id + * @param path the path + * @param payload the payload + * @param xml the xml + * @return the string + */ + public Response RestPut(String fromAppId, String transId, String path, String payload, boolean xml) { + String methodName = "RestPut"; + transId = UUID.randomUUID().toString(); + logHelper.logDebug(methodName + START_STRING); + Response response = null; + try { + Logging.logRequest(outgoingRequestsLogger, HttpMethod.PUT, systemPropertyHelper.getFullServicePath(path), payload); + response = authenticateRequest(client.target(systemPropertyHelper.getFullServicePath(path)) + .request() + .accept(xml ? MediaType.APPLICATION_XML : MediaType.APPLICATION_JSON) + .header(TRANSACTION_ID_HEADER, transId) + .header(FROM_APP_ID_HEADER, fromAppId)) + .header(requestIdHeaderKey, servletRequestHelper.getServletRequest().getHeader(requestIdHeaderKey)) + .put(Entity.entity(payload, MediaType.APPLICATION_JSON)); + Logging.logResponse(outgoingRequestsLogger, HttpMethod.PUT, systemPropertyHelper.getFullServicePath(path), response); + if (response.getStatusInfo().equals(OK)) { + logHelper.multilog(getValidResponseLogMessage(methodName)); + } else { + logHelper.logDebug(getInvalidResponseLogMessage(path, methodName, response)); + } + } catch (Exception e) { + logHelper.logDebug(getFailedResponseLogMessage(path, methodName, e)); + } + return response; + } + + /** + * Rest post. + * + * @param fromAppId the from app id + * @param transId the trans id + * @param path the path + * @param payload the payload + * @param xml the xml + * @return the string + */ + public Response RestPost(String fromAppId, String transId, String path, String payload, boolean xml) { + String methodName = "RestPost"; + transId = UUID.randomUUID().toString(); + logHelper.logDebug(methodName + START_STRING); + Response response = null; + try { + Logging.logRequest(outgoingRequestsLogger, HttpMethod.POST, systemPropertyHelper.getFullServicePath(path), payload); + response = authenticateRequest(client.target(systemPropertyHelper.getFullServicePath(path)) + .request() + .accept(xml ? MediaType.APPLICATION_XML : MediaType.APPLICATION_JSON) + .header(TRANSACTION_ID_HEADER, transId) + .header(FROM_APP_ID_HEADER, fromAppId)) + .header(requestIdHeaderKey, servletRequestHelper.getServletRequest().getHeader(requestIdHeaderKey)) + .post(Entity.entity(payload, MediaType.APPLICATION_JSON)); + Logging.logResponse(outgoingRequestsLogger, HttpMethod.POST, systemPropertyHelper.getFullServicePath(path), response); + if (response.getStatusInfo().equals(OK)) { + logHelper.multilog(getValidResponseLogMessage(methodName)); + } else { + logHelper.logDebug(getInvalidResponseLogMessage(path, methodName, response)); + } + } catch (Exception e) { + logHelper.logDebug(getFailedResponseLogMessage(path, methodName, e)); + } + return response; + } + + /** + * Encode URL. + * + * @param nodeKey the node key + * @return the string + * @throws UnsupportedEncodingException the unsupported encoding exception + */ + String encodeURL(String nodeKey) throws UnsupportedEncodingException { + return URLEncoder.encode(nodeKey, "UTF-8").replaceAll("\\+", "%20"); + } + + /** + * Inits the rest client. + */ + private void initRestClient(String certificatePath) { + String methodName = "initRestClient"; + if (client == null) { + try { + client = new HttpsAuthClient(systemPropertyHelper, new SSLContextProvider(logHelper)).getClient(certificatePath); + } catch (HttpClientBuilderException e) { + logHelper.multilog("<== HttpClientBuilderException in " + methodName, e); + } + } + } + + private String getFailedResponseLogMessage(String path, String methodName, Exception e) { + return methodName + URL_DECLERATION + systemPropertyHelper.getFullServicePath(path) + ", Exception: " + e.toString(); + } + + private String getValidResponseLogMessage(String methodName) { + return methodName + URL_DECLERATION; + } + + private String getInvalidResponseLogMessage(String path, String methodName, Response cres) { + return methodName + " with status=" + cres.getStatus() + URL_DECLERATION + systemPropertyHelper.getFullServicePath(path); + } + + private Invocation.Builder authenticateRequest(Invocation.Builder requestBuilder) throws InvalidPropertyException, UnsupportedEncodingException { + return requestBuilder + .header("Authorization", "Basic " + systemPropertyHelper.getEncodedCredentials()); + } } diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/HttpsAuthClient.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/HttpsAuthClient.java index 3bc8e4a35..9a6de152c 100644 --- a/vid-app-common/src/main/java/org/onap/vid/aai/util/HttpsAuthClient.java +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/HttpsAuthClient.java @@ -21,120 +21,79 @@ package org.onap.vid.aai.util; -import java.io.FileInputStream; -import java.security.KeyManagementException; -import java.security.KeyStore; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.onap.vid.aai.exceptions.HttpClientBuilderException; -import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; +import java.nio.file.FileSystems; -import org.eclipse.jetty.util.security.Password; -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.HttpUrlConnectorProvider; -import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; -import org.onap.portalsdk.core.util.SystemProperties; /** * The Class HttpsAuthClient. */ -public class HttpsAuthClient{ - /** The logger. */ - static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(HttpsAuthClient.class); - - /** - * Gets the client. - * - * @param certFilePath the cert file path - * @return the client - * @throws KeyManagementException the key management exception - */ - public static Client getClient(String certFilePath) throws KeyManagementException { - - ClientConfig config = new ClientConfig(); - //config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); - //config.getClasses().add(org.onap.aai.util.CustomJacksonJaxBJsonProvider.class); - - try { - - config.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, Boolean.TRUE ); - - config.connectorProvider(new HttpUrlConnectorProvider().useSetMethodWorkaround()); - String truststore_path = certFilePath + org.onap.vid.aai.util.AAIProperties.FILESEPARTOR + SystemProperties.getProperty(org.onap.vid.aai.util.AAIProperties.AAI_TRUSTSTORE_FILENAME); - String truststore_password = SystemProperties.getProperty(org.onap.vid.aai.util.AAIProperties.AAI_TRUSTSTORE_PASSWD_X); - String decrypted_truststore_password = Password.deobfuscate(truststore_password); - - boolean useClientCert = false; - - String keystore_path = certFilePath + org.onap.vid.aai.util.AAIProperties.FILESEPARTOR + SystemProperties.getProperty(org.onap.vid.aai.util.AAIProperties.AAI_KEYSTORE_FILENAME); - String keystore_password = SystemProperties.getProperty(org.onap.vid.aai.util.AAIProperties.AAI_KEYSTORE_PASSWD_X); - String decrypted_keystore_password = Password.deobfuscate(keystore_password); - - String clientCert = SystemProperties.getProperty(org.onap.vid.aai.util.AAIProperties.AAI_USE_CLIENT_CERT); - - if (clientCert != null && - SystemProperties.getProperty(org.onap.vid.aai.util.AAIProperties.AAI_USE_CLIENT_CERT).equalsIgnoreCase("true")) { - useClientCert = true; - } - - System.setProperty("javax.net.ssl.trustStore", truststore_path); - System.setProperty("javax.net.ssl.trustStorePassword", decrypted_truststore_password); - HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){ - public boolean verify(String string,SSLSession ssls) { - return true; - } - }); - - final SSLContext ctx = SSLContext.getInstance("TLS"); - - KeyManagerFactory kmf = null; - if (useClientCert) { - - try { - kmf = KeyManagerFactory.getInstance("SunX509"); - FileInputStream fin = new FileInputStream(keystore_path); - KeyStore ks = KeyStore.getInstance("PKCS12"); - char[] pwd = decrypted_keystore_password.toCharArray(); - ks.load(fin, pwd); - kmf.init(ks, pwd); - } catch (Exception e) { - //System.out.println("Error setting up kmf: exiting"); - logger.debug(EELFLoggerDelegate.debugLogger, "Error setting up kmf: exiting"); - e.printStackTrace(); - return null; - } - ctx.init(kmf.getKeyManagers(), null, null); - - return ClientBuilder.newBuilder() - .sslContext(ctx) - .hostnameVerifier(new HostnameVerifier() { - @Override - public boolean verify( String s, SSLSession sslSession ) { - return true; - } - }).withConfig(config) - .build() - .register(org.onap.vid.aai.util.CustomJacksonJaxBJsonProvider.class); - } else { - return ClientBuilder.newBuilder() - .hostnameVerifier(new HostnameVerifier() { - @Override - public boolean verify( String s, SSLSession sslSession ) { - return true; - } - }).withConfig(config) - .build() - .register(org.onap.vid.aai.util.CustomJacksonJaxBJsonProvider.class); - } - } catch (Exception e) { - logger.debug(EELFLoggerDelegate.debugLogger, "Error setting up config: exiting"); - //System.out.println("Error setting up config: exiting"); - e.printStackTrace(); - System.exit(1); - return null; - } - } -} +public class HttpsAuthClient { + + private static final String SSL_TRUST_STORE = "javax.net.ssl.trustStore"; + private static final String SSL_TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword"; + + private final SystemPropertyHelper systemPropertyHelper; + private final SSLContextProvider sslContextProvider; + + public HttpsAuthClient(SystemPropertyHelper systemPropertyHelper, SSLContextProvider sslContextProvider) { + this.systemPropertyHelper = systemPropertyHelper; + this.sslContextProvider = sslContextProvider; + } + + /** + * Gets the client. + * + * @param certFilePath the cert file path + * @throws HttpClientBuilderException some problem was found during build of ssl context + * @return the client + */ + public Client getClient(String certFilePath) throws HttpClientBuilderException { + ClientConfig config = prepareClientConfig(); + boolean useClientCert = Boolean.valueOf(systemPropertyHelper.getAAIUseClientCert().orElse("false")); + + setSystemProperties(certFilePath); + ignoreHostname(); + + return useClientCert ? getTrustedClient(config, getKeystorePath(certFilePath), + systemPropertyHelper.getEncodedKeystorePassword()) : getUntrustedClient(config); + } + + private void ignoreHostname() { + HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true); + } + + private Client getUntrustedClient(ClientConfig config) { + return ClientBuilder.newBuilder().withConfig(config).build().register(CustomJacksonJaxBJsonProvider.class); + } + + private Client getTrustedClient(ClientConfig config, String keystore_path, String decrypted_keystore_password) throws HttpClientBuilderException { + return ClientBuilder.newBuilder() + .sslContext(sslContextProvider.getSslContext(keystore_path, decrypted_keystore_password)) + .withConfig(config) + .build() + .register(CustomJacksonJaxBJsonProvider.class); + } + + private String getKeystorePath(String certFilePath) { + return certFilePath + FileSystems.getDefault().getSeparator() + systemPropertyHelper.getAAIKeystoreFilename(); + } + + private void setSystemProperties(String certFilePath) { + System.setProperty(SSL_TRUST_STORE, certFilePath + FileSystems.getDefault().getSeparator() + + systemPropertyHelper.getAAITruststoreFilename().orElse("")); + System.setProperty(SSL_TRUST_STORE_PASSWORD, systemPropertyHelper.getEncodedTruststorePassword()); + } + + private ClientConfig prepareClientConfig() { + ClientConfig config = new ClientConfig(); + config.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, Boolean.TRUE); + config.connectorProvider(new HttpUrlConnectorProvider().useSetMethodWorkaround()); + return config; + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/LogHelper.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/LogHelper.java new file mode 100644 index 000000000..f1d772453 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/LogHelper.java @@ -0,0 +1,49 @@ +package org.onap.vid.aai.util; + +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Wrapper for logging messages + */ +public class LogHelper { + /** + * The Constant dateFormat. + */ + final static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSSS"); + + private EELFLoggerDelegate logger; + + LogHelper(EELFLoggerDelegate logger) { + this.logger = logger; + } + + void multilog(String msg, Throwable e) { + logInfo(msg, e); + logDebug(msg, e); + } + + void multilog(String msg) { + logInfo(msg); + logDebug(msg); + } + + void logInfo(String msg, Throwable e) { + logInfo(msg + e.toString()); + } + + void logDebug(String msg, Throwable e) { + logDebug(msg + e.toString()); + } + + void logInfo(String msg) { + logger.info(EELFLoggerDelegate.errorLogger, dateFormat.format(new Date()) + "<== " + msg); + } + + void logDebug(String msg) { + logger.debug(EELFLoggerDelegate.debugLogger, dateFormat.format(new Date()) + "<== " + msg); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/SSLContextProvider.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/SSLContextProvider.java new file mode 100644 index 000000000..8e7364cfc --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/SSLContextProvider.java @@ -0,0 +1,40 @@ +package org.onap.vid.aai.util; + +import org.onap.vid.aai.exceptions.HttpClientBuilderException; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; + +public class SSLContextProvider { + + private final LogHelper logHelper; + + public SSLContextProvider(LogHelper logHelper) { + this.logHelper = logHelper; + } + + public SSLContext getSslContext(String keystore_path, String decrypted_keystore_password) throws HttpClientBuilderException { + try { + final SSLContext ctx = SSLContext.getInstance("TLS"); + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(new FileInputStream(keystore_path), decrypted_keystore_password.toCharArray()); + kmf.init(ks, decrypted_keystore_password.toCharArray()); + ctx.init(kmf.getKeyManagers(), null, null); + return ctx; + } catch (IOException | CertificateException | UnrecoverableKeyException | NoSuchAlgorithmException + | KeyStoreException | KeyManagementException e) { + logHelper.logDebug("Error setting up ssl context."); + throw new HttpClientBuilderException(e); + } + } + +} diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/ServletRequestHelper.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/ServletRequestHelper.java new file mode 100644 index 000000000..6cc98903e --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/ServletRequestHelper.java @@ -0,0 +1,14 @@ +package org.onap.vid.aai.util; + +import javax.servlet.http.HttpServletRequest; +import static org.onap.vid.utils.Logging.getHttpServletRequest; + +/** + * Wrapper for getting current context attributes + */ +public class ServletRequestHelper { + + public HttpServletRequest getServletRequest() { + return getHttpServletRequest(); + } +} diff --git a/vid-app-common/src/main/java/org/onap/vid/aai/util/SystemPropertyHelper.java b/vid-app-common/src/main/java/org/onap/vid/aai/util/SystemPropertyHelper.java new file mode 100644 index 000000000..b5f3aecb7 --- /dev/null +++ b/vid-app-common/src/main/java/org/onap/vid/aai/util/SystemPropertyHelper.java @@ -0,0 +1,71 @@ +package org.onap.vid.aai.util; + +import org.eclipse.jetty.util.security.Password; +import org.onap.portalsdk.core.util.SystemProperties; +import org.onap.vid.aai.exceptions.InvalidPropertyException; + +import java.io.UnsupportedEncodingException; +import java.util.Base64; +import java.util.Optional; + +public class SystemPropertyHelper { + + public Optional getAAIUseClientCert(){ + return getSystemProperty(AAIProperties.AAI_USE_CLIENT_CERT); + } + + public Optional getAAIServerUrl(){ + return getSystemProperty(AAIProperties.AAI_SERVER_URL); + } + + public Optional getAAIVIDUsername(){ + return getSystemProperty(AAIProperties.AAI_VID_USERNAME); + } + + public Optional getAAIVIDPasswd(){ + return getSystemProperty(AAIProperties.AAI_VID_PASSWD_X); + } + + public Optional getAAITruststorePasswd(){ + return getSystemProperty(AAIProperties.AAI_TRUSTSTORE_PASSWD_X); + } + + public Optional getAAITruststoreFilename(){ + return getSystemProperty(AAIProperties.AAI_TRUSTSTORE_FILENAME); + } + + public Optional getAAIKeystoreFilename(){ + return getSystemProperty(AAIProperties.AAI_KEYSTORE_FILENAME); + } + + public Optional getAAIKeystorePasswd(){ + return getSystemProperty(AAIProperties.AAI_KEYSTORE_PASSWD_X); + } + + public boolean isClientCertEnabled() { + return getAAIUseClientCert().isPresent() && + getAAIUseClientCert().orElseGet(() -> "false").equalsIgnoreCase("true"); + } + + public String getFullServicePath(String path) { + return getAAIServerUrl().orElse("") + path; + } + + public String getEncodedCredentials() throws InvalidPropertyException, UnsupportedEncodingException { + String vidUsername = getAAIVIDUsername().orElseThrow(InvalidPropertyException::new); + String vidPassword = Password.deobfuscate(getAAIVIDPasswd().orElseThrow(InvalidPropertyException::new)); + return Base64.getEncoder().encodeToString((vidUsername + ":" + vidPassword).getBytes("utf-8")); + } + + public String getEncodedTruststorePassword(){ + return Password.deobfuscate(getAAITruststorePasswd().orElse("")); + } + + public String getEncodedKeystorePassword(){ + return Password.deobfuscate(getAAIKeystorePasswd().orElse("")); + } + + private Optional getSystemProperty(String propertyKey){ + return Optional.ofNullable(SystemProperties.getProperty(propertyKey)); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/util/AAIRestInterfaceTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/util/AAIRestInterfaceTest.java index 35ebb66e7..94554fa00 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/util/AAIRestInterfaceTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/util/AAIRestInterfaceTest.java @@ -1,76 +1,9 @@ package org.onap.vid.aai.util; -import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +@RunWith(Suite.class) +@Suite.SuiteClasses({ParametrizedAAIRestInterfaceTest.class, SingleAAIRestInterfaceTest.class}) public class AAIRestInterfaceTest { - - private AAIRestInterface createTestSubject() { - return new AAIRestInterface(""); - } - - @Test - public void testEncodeURL() throws Exception { - AAIRestInterface testSubject; - String nodeKey = ""; - String result; - - // default test - testSubject = createTestSubject(); - result = testSubject.encodeURL(nodeKey); - } - - @Test - public void testSetRestSrvrBaseURL() throws Exception { - AAIRestInterface testSubject; - String baseURL = ""; - - // test 1 - testSubject = createTestSubject(); - baseURL = null; - testSubject.SetRestSrvrBaseURL(baseURL); - - // test 2 - testSubject = createTestSubject(); - baseURL = ""; - testSubject.SetRestSrvrBaseURL(baseURL); - } - - @Test - public void testGetRestSrvrBaseURL() throws Exception { - AAIRestInterface testSubject; - String result; - - // default test - testSubject = createTestSubject(); - result = testSubject.getRestSrvrBaseURL(); - } - - - @Test - public void testRestPut() throws Exception { - AAIRestInterface testSubject; - String fromAppId = ""; - String transId = ""; - String path = ""; - String payload = ""; - boolean xml = false; - - // default test - testSubject = createTestSubject(); - testSubject.RestPut(fromAppId, transId, path, payload, xml); - } - - @Test - public void testRestPost() throws Exception { - AAIRestInterface testSubject; - String fromAppId = ""; - String transId = ""; - String path = ""; - String payload = ""; - boolean xml = false; - - // default test - testSubject = createTestSubject(); - testSubject.RestPost(fromAppId, transId, path, payload, xml); - } -} \ No newline at end of file +} diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/util/CustomJacksonJaxBJsonProviderTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/util/CustomJacksonJaxBJsonProviderTest.java index dcd962f1b..6c08e54b8 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/util/CustomJacksonJaxBJsonProviderTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/util/CustomJacksonJaxBJsonProviderTest.java @@ -1,5 +1,11 @@ package org.onap.vid.aai.util; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.SerializationFeature; +import org.junit.Assert; import org.junit.Test; public class CustomJacksonJaxBJsonProviderTest { @@ -9,11 +15,19 @@ public class CustomJacksonJaxBJsonProviderTest { } @Test - public void testGetMapper() throws Exception { - CustomJacksonJaxBJsonProvider testSubject; + public void testMapperHasCorrectConfig() throws Exception { + CustomJacksonJaxBJsonProvider testSubject = createTestSubject(); + DeserializationConfig deserializationConfig = testSubject.getMapper().getDeserializationConfig(); + SerializationConfig serializationConfig = testSubject.getMapper().getSerializationConfig(); - // default test - testSubject = createTestSubject(); - testSubject.getMapper(); + Assert.assertFalse(serializationConfig.hasSerializationFeatures(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS.getMask())); + Assert.assertFalse(serializationConfig.hasSerializationFeatures(SerializationFeature.INDENT_OUTPUT.getMask())); + Assert.assertFalse(serializationConfig.hasSerializationFeatures(SerializationFeature.WRAP_ROOT_VALUE.getMask())); + Assert.assertFalse(serializationConfig.hasSerializationFeatures(SerializationFeature.CLOSE_CLOSEABLE.getMask())); + + Assert.assertFalse(deserializationConfig.hasDeserializationFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES.getMask())); + Assert.assertFalse(deserializationConfig.hasDeserializationFeatures(DeserializationFeature.UNWRAP_ROOT_VALUE.getMask())); + + Assert.assertEquals(serializationConfig.getSerializationInclusion(), JsonInclude.Include.NON_NULL); } } \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/util/HttpsAuthClientTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/util/HttpsAuthClientTest.java index 88d53c03f..0f9983916 100644 --- a/vid-app-common/src/test/java/org/onap/vid/aai/util/HttpsAuthClientTest.java +++ b/vid-app-common/src/test/java/org/onap/vid/aai/util/HttpsAuthClientTest.java @@ -1,18 +1,69 @@ package org.onap.vid.aai.util; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.vid.aai.exceptions.HttpClientBuilderException; +import javax.net.ssl.SSLContext; +import java.util.Optional; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) public class HttpsAuthClientTest { + @Mock + private SystemPropertyHelper systemPropertyHelper; + @Mock + private SSLContextProvider sslContextProvider; + @Mock + private SSLContext sslContext; + + public static final String CERT_FILE_PATH = "any_path"; private HttpsAuthClient createTestSubject() { - return new HttpsAuthClient(); + return new HttpsAuthClient(systemPropertyHelper, sslContextProvider); + } + + @Before + public void setUp() throws Exception { + when(systemPropertyHelper.getAAITruststoreFilename()).thenReturn(Optional.of("filename")); + when(systemPropertyHelper.getEncodedTruststorePassword()).thenReturn("password"); + } + + @Test(expected = HttpClientBuilderException.class) + public void testHttpClientBuilderExceptionOnGetClient() throws HttpClientBuilderException { + //when + when(systemPropertyHelper.getAAIUseClientCert()).thenReturn(Optional.of("true")); + when(sslContextProvider.getSslContext(anyString(), anyString())).thenThrow(new HttpClientBuilderException()); + createTestSubject().getClient("nonExistingFile"); + } + + @Test + public void testGetSecuredClient() throws Exception { + // when + when(systemPropertyHelper.getAAIUseClientCert()).thenReturn(Optional.of("true")); + when(sslContextProvider.getSslContext(anyString(), anyString())).thenReturn(sslContext); + createTestSubject().getClient(CERT_FILE_PATH); + + //then + verify(sslContextProvider).getSslContext(anyString(), anyString()); } @Test - public void testGetClient() throws Exception { - String certFilePath = ""; + public void testGetUnsecuredClient() throws Exception { + // when + when(systemPropertyHelper.getAAIUseClientCert()).thenReturn(Optional.of("false")); + when(sslContextProvider.getSslContext(anyString(), anyString())).thenReturn(sslContext); + createTestSubject().getClient(CERT_FILE_PATH); - // default test - HttpsAuthClient.getClient(certFilePath); + //then + verify(sslContextProvider, never()).getSslContext(anyString(), anyString()); } } \ No newline at end of file diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/util/LogHelperTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/util/LogHelperTest.java new file mode 100644 index 000000000..f0e07dddc --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/aai/util/LogHelperTest.java @@ -0,0 +1,69 @@ +package org.onap.vid.aai.util; + +import com.att.eelf.configuration.EELFLogger; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.matchesPattern; +import static org.mockito.Mockito.verify; + +@RunWith(MockitoJUnitRunner.class) +public class LogHelperTest { + + public static final String TEST_MESSAGE = "TestMessage"; + public static final String PREFIX_REGEXP = "^\\d\\d\\:\\d\\d\\:\\d\\d\\:\\d\\d\\d\\d<==\\s\\b"; + + @Mock + private EELFLoggerDelegate eelfLoggerDelegate; + @Captor + private ArgumentCaptor captorInfo; + @Captor + private ArgumentCaptor captorDebug; + + private LogHelper logHelper; + + @Before + public void setUp() throws Exception { + logHelper = new LogHelper(eelfLoggerDelegate); + } + + @Test + public void testMultilogShouldHaveCorrectFormat(){ + logHelper.multilog(TEST_MESSAGE); + verify(eelfLoggerDelegate).info(Mockito.any(EELFLogger.class), captorInfo.capture()); + assertThat(captorInfo.getValue(), matchesPattern(PREFIX_REGEXP+TEST_MESSAGE+"\\b$")); + verify(eelfLoggerDelegate).debug(Mockito.any(EELFLogger.class), captorDebug.capture()); + assertThat(captorDebug.getValue(), matchesPattern(PREFIX_REGEXP+TEST_MESSAGE+"\\b$")); + } + + @Test + public void testMultilogWithThrowableShouldHaveCorrectFormat(){ + logHelper.multilog(TEST_MESSAGE + " ", new NullPointerException(TEST_MESSAGE)); + verify(eelfLoggerDelegate).info(Mockito.any(EELFLogger.class), captorInfo.capture()); + assertThat(captorInfo.getValue(), matchesPattern(PREFIX_REGEXP+TEST_MESSAGE+"\\b.*\\bNullPointerException\\b.*$")); + verify(eelfLoggerDelegate).debug(Mockito.any(EELFLogger.class), captorDebug.capture()); + assertThat(captorDebug.getValue(), matchesPattern(PREFIX_REGEXP+TEST_MESSAGE+"\\b.*\\bNullPointerException\\b.*$")); + } + + @Test + public void testDebuglogShouldHaveCorrectFormat(){ + logHelper.logDebug(TEST_MESSAGE); + verify(eelfLoggerDelegate).debug(Mockito.any(EELFLogger.class), captorDebug.capture()); + assertThat(captorDebug.getValue(), matchesPattern(PREFIX_REGEXP+TEST_MESSAGE+"\\b$")); + } + + @Test + public void testDebuglogWithThrowableShouldHaveCorrectFormat(){ + logHelper.logDebug(TEST_MESSAGE + " ", new NullPointerException(TEST_MESSAGE)); + verify(eelfLoggerDelegate).debug(Mockito.any(EELFLogger.class), captorDebug.capture()); + assertThat(captorDebug.getValue(), matchesPattern(PREFIX_REGEXP+TEST_MESSAGE+"\\b.*\\bNullPointerException\\b.*$")); + } +} diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/util/ParametrizedAAIRestInterfaceTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/util/ParametrizedAAIRestInterfaceTest.java new file mode 100644 index 000000000..1c8185cf2 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/aai/util/ParametrizedAAIRestInterfaceTest.java @@ -0,0 +1,104 @@ +package org.onap.vid.aai.util; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.vid.aai.exceptions.InvalidPropertyException; +import org.testng.Assert; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Optional; + +import static javax.ws.rs.core.Response.Status.NO_CONTENT; +import static javax.ws.rs.core.Response.Status.OK; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(Parameterized.class) +public class ParametrizedAAIRestInterfaceTest { + + private static final String PATH = "path"; + private static final String HTTP_LOCALHOST = "http://localhost/"; + @Mock + private LogHelper logHelper; + @Mock + private Client client; + @Mock + private WebTarget webTarget; + @Mock + private Invocation.Builder builder; + @Mock + private ServletRequestHelper servletRequestHelper; + @Mock + private HttpServletRequest httpServletRequest; + @Mock + private Response response; + @Mock + private SystemPropertyHelper systemPropertyHelper; + + private AAIRestInterface testSubject; + private Response.Status status; + + @Parameterized.Parameters + public static Collection data() { + return Arrays.asList(OK, NO_CONTENT); + } + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mockSystemProperties(); + testSubject = createTestSubject(); + when(client.target(HTTP_LOCALHOST+PATH)).thenReturn(webTarget); + when(webTarget.request()).thenReturn(builder); + when(builder.accept(Mockito.anyString())).thenReturn(builder); + when(builder.header(Mockito.anyString(), Mockito.anyString())).thenReturn(builder); + when(servletRequestHelper.getServletRequest()).thenReturn(httpServletRequest); + } + + public ParametrizedAAIRestInterfaceTest(Response.Status status) { + this.status = status; + } + + private AAIRestInterface createTestSubject() { + return new AAIRestInterface("", logHelper, Optional.of(client), servletRequestHelper, systemPropertyHelper); + } + + @Test + public void testRestDeleteWithValidResponse() throws Exception { + // given + String methodName = "Delete"; + + // when + when(builder.delete()).thenReturn(response); + when(response.getStatusInfo()).thenReturn(status); + boolean finalResponse = testSubject.Delete("", "", PATH); + + // then + verify(builder).delete(); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug("Resource " + HTTP_LOCALHOST + PATH + " deleted"); + Assert.assertTrue(finalResponse); + } + + private void mockSystemProperties() throws UnsupportedEncodingException, InvalidPropertyException { + when(systemPropertyHelper.getAAIServerUrl()).thenReturn(Optional.of(HTTP_LOCALHOST)); + when(systemPropertyHelper.getAAIUseClientCert()).thenReturn(Optional.of("cert")); + when(systemPropertyHelper.getAAIVIDPasswd()).thenReturn(Optional.of("passwd")); + when(systemPropertyHelper.getAAIVIDUsername()).thenReturn(Optional.of("user")); + when(systemPropertyHelper.getEncodedCredentials()).thenReturn("someCredentials"); + when(systemPropertyHelper.getFullServicePath(Mockito.anyString())).thenReturn("http://localhost/path"); + } + +} diff --git a/vid-app-common/src/test/java/org/onap/vid/aai/util/SingleAAIRestInterfaceTest.java b/vid-app-common/src/test/java/org/onap/vid/aai/util/SingleAAIRestInterfaceTest.java new file mode 100644 index 000000000..ab2bdc0d5 --- /dev/null +++ b/vid-app-common/src/test/java/org/onap/vid/aai/util/SingleAAIRestInterfaceTest.java @@ -0,0 +1,316 @@ +package org.onap.vid.aai.util; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.vid.aai.exceptions.InvalidPropertyException; +import org.testng.Assert; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.UnsupportedEncodingException; +import java.util.Optional; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.OK; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class SingleAAIRestInterfaceTest { + + private static final String PATH = "path"; + private static final String HTTP_LOCALHOST = "http://localhost/"; + @Mock + private LogHelper logHelper; + @Mock + private Client client; + @Mock + private WebTarget webTarget; + @Mock + private Invocation.Builder builder; + @Mock + private ServletRequestHelper servletRequestHelper; + @Mock + private HttpServletRequest httpServletRequest; + @Mock + private Response response; + @Mock + private SystemPropertyHelper systemPropertyHelper; + + private AAIRestInterface testSubject; + + @Before + public void setUp() throws Exception { + mockSystemProperties(); + testSubject = createTestSubject(); + when(client.target(HTTP_LOCALHOST+PATH)).thenReturn(webTarget); + when(webTarget.request()).thenReturn(builder); + when(builder.accept(Mockito.anyString())).thenReturn(builder); + when(builder.header(Mockito.anyString(), Mockito.anyString())).thenReturn(builder); + when(servletRequestHelper.getServletRequest()).thenReturn(httpServletRequest); + } + + private AAIRestInterface createTestSubject() { + return new AAIRestInterface("", logHelper, Optional.of(client), servletRequestHelper, systemPropertyHelper); + } + + @Test + public void testEncodeURL() throws Exception { + String nodeKey = "some unusual uri"; + Assert.assertEquals(testSubject.encodeURL(nodeKey), "some%20unusual%20uri"); + } + + @Test + public void testSetRestSrvrBaseURLWithNullValue() throws Exception { + testSubject.SetRestSrvrBaseURL(null); + Mockito.verify(logHelper).multilog("<== REST Server base URL cannot be null."); + } + + @Test + public void testSetRestSrvrBaseURL() throws Exception { + String baseUrl = "anything"; + testSubject.SetRestSrvrBaseURL(baseUrl); + Mockito.verifyZeroInteractions(logHelper); + Assert.assertEquals(testSubject.getRestSrvrBaseURL(), baseUrl); + } + + @Test + public void testRestJsonPutWithResponse200() throws Exception { + // given + String methodName = "RestPut"; + String payload = "{\"id\": 1}"; + Entity entity = Entity.entity(payload, MediaType.APPLICATION_JSON); + + // when + when(builder.put(Mockito.any(Entity.class))).thenReturn(response); + when(response.getStatusInfo()).thenReturn(OK); + Response finalResponse = testSubject.RestPut("", "", PATH, payload, false); + + // then + verify(builder).put(entity); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).multilog(methodName + ", url="); + Assert.assertEquals(response, finalResponse); + } + + @Test + public void testFailedRestJsonPut() throws Exception { + // given + String methodName = "RestPut"; + String payload = "{\"id\": 1}"; + Entity entity = Entity.entity(payload, MediaType.APPLICATION_JSON); + + // when + when(builder.put(Mockito.any(Entity.class))).thenThrow(new RuntimeException()); + Response finalResponse = testSubject.RestPut("", "", PATH, payload, false); + + // then + verify(builder).put(entity); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug(methodName + ", url=" + HTTP_LOCALHOST + PATH + ", Exception: java.lang.RuntimeException"); + Assert.assertEquals(finalResponse, null); + } + + @Test + public void testRestJsonPutWithResponse400() throws Exception { + // given + String methodName = "RestPut"; + String payload = "{\"id\": 1}"; + Entity entity = Entity.entity(payload, MediaType.APPLICATION_JSON); + + // when + when(builder.put(Mockito.any(Entity.class))).thenReturn(response); + when(response.getStatusInfo()).thenReturn(BAD_REQUEST); + when(response.getStatus()).thenReturn(BAD_REQUEST.getStatusCode()); + Response finalResponse = testSubject.RestPut("", "", PATH, payload, false); + + // then + verify(builder).put(entity); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug(methodName + " with status=400, url=" + HTTP_LOCALHOST + PATH); + Assert.assertEquals(response, finalResponse); + } + + @Test + public void testRestPostWithResponse200() throws Exception { + // given + String methodName = "RestPost"; + String payload = "{\"id\": 1}"; + Entity entity = Entity.entity(payload, MediaType.APPLICATION_JSON); + + // when + when(builder.post(Mockito.any(Entity.class))).thenReturn(response); + when(response.getStatusInfo()).thenReturn(OK); + Response finalResponse = testSubject.RestPost("", "", PATH, payload, false); + + // then + verify(builder).post(entity); + verify(logHelper).multilog(methodName + ", url="); + Assert.assertEquals(response, finalResponse); + } + + @Test + public void testRestPostWithResponse400() throws Exception { + // given + String methodName = "RestPost"; + String payload = "{\"id\": 1}"; + Entity entity = Entity.entity(payload, MediaType.APPLICATION_JSON); + + // when + when(builder.post(Mockito.any(Entity.class))).thenReturn(response); + when(response.getStatusInfo()).thenReturn(BAD_REQUEST); + when(response.getStatus()).thenReturn(BAD_REQUEST.getStatusCode()); + Response finalResponse = testSubject.RestPost("", "", PATH, payload, false); + + // then + verify(builder).post(entity); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug(methodName + " with status=400, url=" + HTTP_LOCALHOST + PATH); + Assert.assertEquals(response, finalResponse); + } + + @Test + public void testFailedRestPost() throws Exception { + // given + String methodName = "RestPost"; + String payload = "{\"id\": 1}"; + Entity entity = Entity.entity(payload, MediaType.APPLICATION_JSON); + + // when + when(builder.post(Mockito.any(Entity.class))).thenThrow(new RuntimeException()); + Response finalResponse = testSubject.RestPost("", "", PATH, payload, false); + + // then + verify(builder).post(entity); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug(methodName + ", url=" + HTTP_LOCALHOST + PATH + ", Exception: java.lang.RuntimeException"); + Assert.assertEquals(finalResponse, null); + } + + @Test + public void testRestDeleteWithResponse400() throws Exception { + // given + String methodName = "Delete"; + + // when + when(builder.delete()).thenReturn(response); + when(response.getStatusInfo()).thenReturn(BAD_REQUEST); + String reason = "Any reason"; + when(response.readEntity(String.class)).thenReturn(reason); + when(response.getStatus()).thenReturn(BAD_REQUEST.getStatusCode()); + boolean finalResponse = testSubject.Delete("", "", PATH); + + // then + verify(builder).delete(); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug("Deleting Resource failed: 400:" + reason); + Assert.assertFalse(finalResponse); + } + + @Test + public void testRestDeleteWithResponse404() throws Exception { + // given + String methodName = "Delete"; + + // when + when(builder.delete()).thenReturn(response); + when(response.getStatusInfo()).thenReturn(NOT_FOUND); + String reason = "Any reason"; + when(response.readEntity(String.class)).thenReturn(reason); + when(response.getStatus()).thenReturn(NOT_FOUND.getStatusCode()); + boolean finalResponse = testSubject.Delete("", "", PATH); + + // then + verify(builder).delete(); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug("Resource does not exist...: 404:" + reason); + Assert.assertFalse(finalResponse); + } + + @Test + public void testFailedRestDelete() throws Exception { + // given + String methodName = "Delete"; + + // when + when(builder.delete()).thenThrow(new RuntimeException()); + boolean finalResponse = testSubject.Delete("", "", PATH); + + // then + verify(builder).delete(); + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug(methodName + ", url=" + HTTP_LOCALHOST + PATH + ", Exception: java.lang.RuntimeException"); + Assert.assertFalse(finalResponse); + } + + @Test + public void testRestJsonGetWithResponse200() throws Exception { + // given + String methodName = "RestGet"; + + // when + when(builder.get()).thenReturn(response); + when(response.getStatusInfo()).thenReturn(OK); + Response finalResponse = testSubject.RestGet("", "", PATH, false); + + // then + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug(HTTP_LOCALHOST + PATH + " for the get REST API"); + verify(logHelper).multilog(methodName + " REST api call was successful!"); + Assert.assertEquals(response, finalResponse); + } + + @Test + public void testRestJsonGetWithResponse400() throws Exception { + // given + String methodName = "RestGet"; + + // when + when(builder.get()).thenReturn(response); + when(response.getStatusInfo()).thenReturn(BAD_REQUEST); + when(response.getStatus()).thenReturn(BAD_REQUEST.getStatusCode()); + Response finalResponse = testSubject.RestGet("", "", PATH, false); + + // then + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug(HTTP_LOCALHOST + PATH + " for the get REST API"); + verify(logHelper).logDebug(methodName + " with status=400, url=" + HTTP_LOCALHOST + PATH); + Assert.assertEquals(response, finalResponse); + } + + @Test + public void testFailedRestGet() throws Exception { + // given + String methodName = "RestGet"; + + // when + when(builder.get()).thenThrow(new RuntimeException()); + Response finalResponse = testSubject.RestGet("", "", PATH, false); + + // then + verify(logHelper).logDebug(methodName + " start"); + verify(logHelper).logDebug(HTTP_LOCALHOST + PATH + " for the get REST API"); + verify(logHelper).logDebug(methodName + ", url=" + HTTP_LOCALHOST + PATH + ", Exception: java.lang.RuntimeException"); + Assert.assertEquals(finalResponse, null); + } + + private void mockSystemProperties() throws UnsupportedEncodingException, InvalidPropertyException { + when(systemPropertyHelper.getAAIServerUrl()).thenReturn(Optional.of(HTTP_LOCALHOST)); + when(systemPropertyHelper.getAAIUseClientCert()).thenReturn(Optional.of("cert")); + when(systemPropertyHelper.getAAIVIDPasswd()).thenReturn(Optional.of("passwd")); + when(systemPropertyHelper.getAAIVIDUsername()).thenReturn(Optional.of("user")); + when(systemPropertyHelper.getEncodedCredentials()).thenReturn("someCredentials"); + when(systemPropertyHelper.getFullServicePath(Mockito.anyString())).thenReturn("http://localhost/path"); + } + +} \ No newline at end of file