Adding UI extensibility
[aai/sparky-be.git] / src / main / java / org / onap / aai / sparky / dal / ActiveInventoryAdapter.java
  *
  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
  */
-package org.onap.aai.sparky.dal.aai;
+package org.onap.aai.sparky.dal;
 
 import java.io.IOException;
+import java.net.URISyntaxException;
 import java.net.URLEncoder;
-import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
 
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.http.NameValuePair;
 import org.apache.http.client.utils.URIBuilder;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
+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.sparky.config.oxm.OxmEntityDescriptor;
+import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
 import org.onap.aai.sparky.config.oxm.OxmModelLoader;
-import org.onap.aai.sparky.dal.aai.config.ActiveInventoryConfig;
-import org.onap.aai.sparky.dal.aai.config.ActiveInventoryRestConfig;
-import org.onap.aai.sparky.dal.aai.enums.RestAuthenticationMode;
 import org.onap.aai.sparky.dal.exception.ElasticSearchOperationException;
-import org.onap.aai.sparky.dal.rest.OperationResult;
-import org.onap.aai.sparky.dal.rest.RestClientBuilder;
-import org.onap.aai.sparky.dal.rest.RestfulDataAccessor;
 import org.onap.aai.sparky.logging.AaiUiMsgs;
-import org.onap.aai.sparky.security.SecurityContextFactory;
+import org.onap.aai.sparky.util.Encryptor;
 import org.onap.aai.sparky.util.NodeUtils;
-import org.onap.aai.cl.api.Logger;
-import org.onap.aai.cl.eelf.LoggerFactory;
+import org.onap.aai.sparky.viewandinspect.config.TierSupportUiConstants;
 
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.WebResource.Builder;
 
 
 /**
  * The Class ActiveInventoryAdapter.
  */
 
-/**
- * @author davea
- *
- */
-public class ActiveInventoryAdapter extends RestfulDataAccessor
-    implements ActiveInventoryDataProvider {
+public class ActiveInventoryAdapter {
 
   private static final Logger LOG =
       LoggerFactory.getInstance().getLogger(ActiveInventoryAdapter.class);
@@ -66,74 +65,153 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
   private static final String HEADER_FROM_APP_ID = "X-FromAppId";
   private static final String HEADER_AUTHORIZATION = "Authorization";
 
+  private static final String HTTP_SCHEME = "http";
+  private static final String HTTPS_SCHEME = "https";
+
   private static final String TRANSACTION_ID_PREFIX = "txnId-";
   private static final String UI_APP_NAME = "AAI-UI";
 
+  private OxmModelLoader oxmModelLoader;
+  private OxmEntityLookup oxmEntityLookup;
 
-  private ActiveInventoryConfig config;
+  private RestClient restClient;
+
+  private String activeInventoryIpAddress;
+  private String activeInventoryServerPort;
+  private int numRequestRetries;
+  private String basicAuthUserName;
+  private String basicAuthPassword;
+  private RestAuthenticationMode restAuthenticationMode;
+  private int connectTimeoutInMs;
+  private int readTimeoutInMs;
 
   /**
    * Instantiates a new active inventory adapter.
    *
-   * @param restClientBuilder the rest client builder
-   * @throws ElasticSearchOperationException the elastic search operation exception
-   * @throws IOException Signals that an I/O exception has occurred.
    */
-  public ActiveInventoryAdapter(RestClientBuilder restClientBuilder)
+
+  public ActiveInventoryAdapter(OxmModelLoader oxmModelLoader,
+      RestAuthenticationMode authenticationMode, boolean validateServerHostname,
+      boolean validateServerCertChain, String certFileName, String certPassword,
+      String truststoreFileName, int connectTimeoutInMs, int readTimeoutInMs)
       throws ElasticSearchOperationException, IOException {
-    super(restClientBuilder);
 
-    try {
-      this.config = ActiveInventoryConfig.getConfig();
-    } catch (Exception exc) {
-      throw new ElasticSearchOperationException("Error getting active inventory configuration",
-          exc);
-    }
+    this.oxmModelLoader = oxmModelLoader;
+    this.restAuthenticationMode = authenticationMode;
+    this.connectTimeoutInMs = connectTimeoutInMs;
+    this.readTimeoutInMs = readTimeoutInMs;
+
+
+    Encryptor enc = new Encryptor();
+    String certFileNameFullPath = TierSupportUiConstants.CONFIG_AUTH_LOCATION + certFileName;
+    String decryptedCertPassword = enc.decryptValue(certPassword);
+    String truststoreFileNameFullPath =
+        TierSupportUiConstants.CONFIG_AUTH_LOCATION + truststoreFileName;
 
-    clientBuilder.setUseHttps(true);
+    this.restClient = new RestClient().authenticationMode(authenticationMode)
+        .validateServerCertChain(validateServerCertChain)
+        .validateServerHostname(validateServerHostname).clientCertFile(certFileNameFullPath)
+        .clientCertPassword(decryptedCertPassword).trustStore(truststoreFileNameFullPath)
+        .connectTimeoutMs(connectTimeoutInMs).readTimeoutMs(readTimeoutInMs);
 
-    clientBuilder.setValidateServerHostname(config.getAaiSslConfig().isValidateServerHostName());
+  }
+
+  public ActiveInventoryAdapter(OxmModelLoader oxmModelLoader,
+      RestAuthenticationMode authenticationMode, boolean validateServerHostname,
+      boolean validateServerCertChain, String basicAuthUserName, String basicAuthPassword,
+      int connectTimeoutInMs, int readTimeoutInMs)
+      throws ElasticSearchOperationException, IOException {
+
+    this.oxmModelLoader = oxmModelLoader;
+    this.restAuthenticationMode = authenticationMode;
+
+    this.restClient = new RestClient().authenticationMode(authenticationMode)
+        .validateServerCertChain(validateServerCertChain)
+        .validateServerHostname(validateServerHostname).connectTimeoutMs(connectTimeoutInMs)
+        .readTimeoutMs(readTimeoutInMs);
+
+    this.basicAuthUserName = basicAuthUserName;
+    this.basicAuthPassword = basicAuthPassword;
+
+  }
 
-    SecurityContextFactory sslContextFactory = clientBuilder.getSslContextFactory();
 
-    sslContextFactory.setServerCertificationChainValidationEnabled(
-        config.getAaiSslConfig().isValidateServerCertificateChain());
+  protected Map<String, List<String>> getMessageHeaders() {
+
+    Map<String, List<String>> headers = new HashMap<String, List<String>>();
+
+    headers.putIfAbsent(HEADER_FROM_APP_ID, new ArrayList<String>());
+    headers.get(HEADER_FROM_APP_ID).add(UI_APP_NAME);
+
+    headers.putIfAbsent(HEADER_TRANS_ID, new ArrayList<String>());
+    headers.get(HEADER_TRANS_ID).add(TRANSACTION_ID_PREFIX + NodeUtils.getRandomTxnId());
+
+    if (restAuthenticationMode == RestAuthenticationMode.SSL_BASIC) {
+
+      headers.putIfAbsent(HEADER_AUTHORIZATION, new ArrayList<String>());
+      headers.get(HEADER_AUTHORIZATION).add(getBasicAuthenticationCredentials());
 
-    if (config.getAaiRestConfig().getAuthenticationMode() == RestAuthenticationMode.SSL_CERT) {
-      sslContextFactory.setClientCertFileName(config.getAaiSslConfig().getKeystoreFilename());
-      sslContextFactory.setClientCertPassword(config.getAaiSslConfig().getKeystorePassword());
-      sslContextFactory.setTrustStoreFileName(config.getAaiSslConfig().getTruststoreFilename());
     }
 
-    clientBuilder.setConnectTimeoutInMs(config.getAaiRestConfig().getConnectTimeoutInMs());
-    clientBuilder.setReadTimeoutInMs(config.getAaiRestConfig().getReadTimeoutInMs());
+    return headers;
+  }
 
+  protected String getBasicAuthenticationCredentials() {
+    String usernameAndPassword = String.join(":", basicAuthUserName, basicAuthPassword);
+    return "Basic " + java.util.Base64.getEncoder().encodeToString(usernameAndPassword.getBytes());
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * org.onap.aai.sparky.dal.rest.RestfulDataAccessor#setClientDefaults(com.sun.jersey.api.client.
-   * Client, java.lang.String, java.lang.String, java.lang.String)
-   */
-  @Override
-  protected Builder setClientDefaults(Client client, String url, String payloadContentType,
-      String acceptContentType) {
-    Builder builder = super.setClientDefaults(client, url, payloadContentType, acceptContentType);
-
-    builder = builder.header(HEADER_FROM_APP_ID, UI_APP_NAME);
-    byte bytes[] = new byte[6];
-    txnIdGenerator.nextBytes(bytes);
-    builder =
-        builder.header(HEADER_TRANS_ID, TRANSACTION_ID_PREFIX + ByteBuffer.wrap(bytes).getInt());
-
-    if (config.getAaiRestConfig().getAuthenticationMode() == RestAuthenticationMode.SSL_BASIC) {
-      builder = builder.header(HEADER_AUTHORIZATION,
-          config.getAaiSslConfig().getBasicAuthenticationCredentials());
+  public int getNumRequestRetries() {
+    return numRequestRetries;
+  }
+
+
+
+  public void setNumRequestRetries(int numRequestRetries) {
+    this.numRequestRetries = numRequestRetries;
+  }
+
+  public OxmEntityLookup getOxmEntityLookup() {
+    return oxmEntityLookup;
+  }
+
+  public void setOxmEntityLookup(OxmEntityLookup oxmEntityLookup) {
+    this.oxmEntityLookup = oxmEntityLookup;
+  }
+
+  public String getActiveInventoryIpAddress() {
+    return activeInventoryIpAddress;
+  }
+
+  public void setActiveInventoryIpAddress(String activeInventoryIpAddress) {
+    this.activeInventoryIpAddress = activeInventoryIpAddress;
+  }
+
+  public String getActiveInventoryServerPort() {
+    return activeInventoryServerPort;
+  }
+
+  public void setActiveInventoryServerPort(String activeInventoryServerPort) {
+    this.activeInventoryServerPort = activeInventoryServerPort;
+  }
+
+  protected String getResourceBasePath() {
+
+    String versionStr = null;
+    if (oxmModelLoader != null) {
+      versionStr = String.valueOf(oxmModelLoader.getLatestVersionNum());
     }
 
-    return builder;
+    return "/aai/v" + versionStr;
+
+  }
+
+  public int getConnectTimeoutInMs() {
+    return this.connectTimeoutInMs;
+  }
+
+  public int getReadTimeoutInMs() {
+    return this.readTimeoutInMs;
   }
 
   /**
@@ -144,11 +222,9 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
    * @throws Exception the exception
    */
   private String getFullUrl(String resourceUrl) throws Exception {
-    ActiveInventoryRestConfig aaiRestConfig = ActiveInventoryConfig.getConfig().getAaiRestConfig();
-    final String host = aaiRestConfig.getHost();
-    final String port = aaiRestConfig.getPort();
-    final String basePath = aaiRestConfig.getResourceBasePath();
-    return String.format("https://%s:%s%s%s", host, port, basePath, resourceUrl);
+    final String basePath = getResourceBasePath();
+    return String.format("https://%s:%s%s%s", activeInventoryIpAddress, activeInventoryServerPort,
+        basePath, resourceUrl);
   }
 
   public String getGenericQueryForSelfLink(String startNodeType, List<String> queryParams)
@@ -165,21 +241,11 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
 
     final String constructedLink = urlBuilder.toString();
 
-    // TODO: debug log for constructed link
-
     return constructedLink;
 
   }
 
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#getSelfLinksByEntityType(java.lang.
-   * String)
-   */
-  @Override
   public OperationResult getSelfLinksByEntityType(String entityType) throws Exception {
 
     /*
@@ -192,8 +258,7 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
           "Failed to getSelfLinksByEntityType() because entityType is null");
     }
 
-    OxmEntityDescriptor entityDescriptor =
-        OxmModelLoader.getInstance().getEntityDescriptor(entityType);
+    OxmEntityDescriptor entityDescriptor = oxmEntityLookup.getEntityDescriptors().get(entityType);
 
     if (entityDescriptor == null) {
       throw new NoSuchElementException("Failed to getSelfLinksByEntityType() because could"
@@ -202,25 +267,16 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
 
     String link = null;
     final String primaryKeyStr =
-        NodeUtils.concatArray(entityDescriptor.getPrimaryKeyAttributeName(), "/");
+        NodeUtils.concatArray(entityDescriptor.getPrimaryKeyAttributeNames(), "/");
 
     link = getFullUrl("/search/nodes-query?search-node-type=" + entityType + "&filter="
         + primaryKeyStr + ":EXISTS");
 
 
-
-    return doGet(link, "application/json");
+    return restClient.get(link, getMessageHeaders(), MediaType.APPLICATION_JSON_TYPE);
 
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#getSelfLinkForEntity(java.lang.String,
-   * java.lang.String, java.lang.String)
-   */
-  @Override
   public OperationResult getSelfLinkForEntity(String entityType, String primaryKeyName,
       String primaryKeyValue) throws Exception {
 
@@ -238,7 +294,6 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
           "Failed to getSelfLinkForEntity() because primaryKeyValue is null");
     }
 
-
     /*
      * Try to protect ourselves from illegal URI formatting exceptions caused by characters that
      * aren't natively supported in a URI, but can be escaped to make them legal.
@@ -264,8 +319,7 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
 
     }
 
-    return queryActiveInventoryWithRetries(link, "application/json",
-        this.config.getAaiRestConfig().getNumRequestRetries());
+    return queryActiveInventoryWithRetries(link, "application/json", numRequestRetries);
 
   }
 
@@ -305,25 +359,19 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
    */
   // package protected for test classes instead of private
   OperationResult queryActiveInventory(String url, String acceptContentType) {
-    return doGet(url, acceptContentType);
+
+    return restClient.get(url, getMessageHeaders(), MediaType.APPLICATION_JSON_TYPE);
+
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * org.onap.aai.sparky.dal.aai.ActiveInventoryDataProvider#queryActiveInventoryWithRetries(java.
-   * lang.String, java.lang.String, int)
-   */
-  @Override
   public OperationResult queryActiveInventoryWithRetries(String url, String responseType,
       int numRetries) {
 
     OperationResult result = null;
 
-    for (int x = 0; x < numRetries; x++) {
+    for (int retryCount = 0; retryCount < numRetries; retryCount++) {
 
-      LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_SEQ, url, String.valueOf(x + 1));
+      LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_SEQ, url, String.valueOf(retryCount + 1));
 
       result = queryActiveInventory(url, responseType);
 
@@ -337,33 +385,12 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
        * parallelized threads per task processor.
        */
 
-      result.setNumRequestRetries(x);
+      result.setNumRetries(retryCount);
 
       if (!shouldRetryRequest(result)) {
 
-        /*
-         * if (myConfig.getAaiRestConfig().isCacheEnabled()) {
-         * 
-         * CachedHttpRequest cachedRequest = new CachedHttpRequest();
-         * cachedRequest.setHttpRequestMethod("GET"); cachedRequest.setPayload("");
-         * cachedRequest.setPayloadMimeType(""); cachedRequest.setUrl(url);
-         * cachedRequest.setOperationType( TransactionStorageType.ACTIVE_INVENTORY_QUERY.getIndex()
-         * );
-         * 
-         * CachedHttpResponse cachedResponse = new CachedHttpResponse();
-         * cachedResponse.setPayload(result.getResult());
-         * cachedResponse.setPayloadMimeType("application/json");
-         * cachedResponse.setStatusCode(result.getResultCode());
-         * 
-         * CachedHttpTransaction txn = new CachedHttpTransaction(cachedRequest, cachedResponse);
-         * storageProvider.persistTransaction(txn);
-         * 
-         * }
-         */
-
-
-        result.setResolvedLinkFromServer(true);
-        LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_DONE_SEQ, url, String.valueOf(x + 1));
+        result.setFromCache(false);
+        LOG.debug(AaiUiMsgs.QUERY_AAI_RETRY_DONE_SEQ, url, String.valueOf(retryCount + 1));
 
         return result;
       }
@@ -377,31 +404,57 @@ public class ActiveInventoryAdapter extends RestfulDataAccessor
         LOG.error(AaiUiMsgs.QUERY_AAI_WAIT_INTERRUPTION, exc.getLocalizedMessage());
         break;
       }
-      LOG.error(AaiUiMsgs.QUERY_AAI_RETRY_FAILURE_WITH_SEQ, url, String.valueOf(x + 1));
-    }
+      LOG.error(AaiUiMsgs.QUERY_AAI_RETRY_FAILURE_WITH_SEQ, url, String.valueOf(retryCount + 1));
 
+    }
 
-    result.setResolvedLinkFailure(true);
     LOG.info(AaiUiMsgs.QUERY_AAI_RETRY_MAXED_OUT, url);
 
     return result;
 
   }
 
-  /*
-   * (non-Javadoc)
+  public String repairSelfLink(String selfLink) {
+    return repairSelfLink(selfLink, null);
+  }
+
+  /**
+   * This method adds a scheme, host and port (if missing) to the passed-in URI. If these parts of
+   * the URI are already present, they will not be duplicated.
    * 
-   * @see org.onap.aai.sparky.dal.rest.RestfulDataAccessor#shutdown()
+   * @param selflink The URI to repair
+   * @param queryParams The query parameters as a single string
+   * @return The corrected URI (i.e. includes a scheme/host/port)
    */
-  @Override
-  public void shutdown() {
-    // TODO Auto-generated method stub
+  public String repairSelfLink(String selflink, String queryParams) {
+    if (selflink == null) {
+      return selflink;
+    }
 
-    if (entityCache != null) {
-      entityCache.shutdown();
+    UriBuilder builder = UriBuilder.fromPath(selflink).host(activeInventoryIpAddress)
+        .port(Integer.parseInt(activeInventoryServerPort));
+
+    switch (restAuthenticationMode) {
+
+      case SSL_BASIC:
+      case SSL_CERT: {
+        builder.scheme(HTTPS_SCHEME);
+        break;
+      }
+
+      default: {
+        builder.scheme(HTTP_SCHEME);
+      }
     }
 
-  }
+    boolean includeQueryParams = ((null != queryParams) && (!"".equals(queryParams)));
 
+    /*
+     * builder.build().toString() will encode special characters to hexadecimal pairs prefixed with
+     * a '%' so we're adding the query parameters separately, in their UTF-8 representations, so
+     * that characters such as '?', '&', etc. remain intact as needed by the synchronizer
+     */
+    return (builder.build().toString() + (includeQueryParams ? queryParams : ""));
+  }
 
 }