X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Faai%2Fdatarouter%2Futil%2FSearchServiceAgent.java;fp=src%2Fmain%2Fjava%2Forg%2Fonap%2Faai%2Fdatarouter%2Futil%2FSearchServiceAgent.java;h=20d0981205bd90bb509d45d5c74e014b7bb398c2;hb=2a5ff133471c5a69b0dfd760d2743f48112da9a0;hp=0000000000000000000000000000000000000000;hpb=e6be129e4865104321cdd6313f9729c4e7b07d22;p=aai%2Fdata-router.git diff --git a/src/main/java/org/onap/aai/datarouter/util/SearchServiceAgent.java b/src/main/java/org/onap/aai/datarouter/util/SearchServiceAgent.java new file mode 100644 index 0000000..20d0981 --- /dev/null +++ b/src/main/java/org/onap/aai/datarouter/util/SearchServiceAgent.java @@ -0,0 +1,366 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 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========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.datarouter.util; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.jetty.util.security.Password; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.datarouter.logging.DataRouterMsgs; +import org.onap.aai.datarouter.policy.EntityEventPolicy; +import org.onap.aai.restclient.client.Headers; +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.HttpUtil; +import org.slf4j.MDC; + +import com.sun.jersey.core.util.MultivaluedMapImpl; + +public class SearchServiceAgent { + + private Logger logger; + + private RestClient searchClient = null; + private Map indexSchemaMapping = new HashMap<>(); + + private String searchUrl = null; + private String documentEndpoint = null; + + + /** + * Creates a new instance of the search service agent. + * + * @param certName - Certificate to use for talking to the Search Service. + * @param keystore - Keystore to use for talking to the Search Service. + * @param keystorePwd - Keystore password for talking to the Search Service. + * @param searchUrl - URL at which the Search Service can be reached. + * @param documentEndpoint - Endpoint for accessing document resources on the Search Service. + * @param logger - Logger to use for system logs. + */ + public SearchServiceAgent(String certName, + String keystore, + String keystorePwd, + String searchUrl, + String documentEndpoint, + Logger logger) { + + initialize(certName, keystore, keystorePwd, searchUrl, documentEndpoint, logger); + } + + + /** + * Performs all one-time initialization required for the search agent. + * + * @param certName - Certificate to use for talking to the Search Service. + * @param keystore - Keystore to use for talking to the Search Service. + * @param keystorePwd - Keystore password for talking to the Search Service. + * @param searchUrl - URL at which the Search Service can be reached. + * @param documentEndpoint - Endpoint for accessing document resources on the Search Service. + * @param logger - Logger to use for system logs. + */ + private void initialize(String certName, + String keystore, + String keystorePwd, + String searchUrl, + String documentEndpoint, + Logger logger) { + + // Create REST client for search service + searchClient = new RestClient() + .authenticationMode(RestAuthenticationMode.SSL_CERT) + .validateServerHostname(false) + .validateServerCertChain(true) + .clientCertFile(DataRouterConstants.DR_HOME_AUTH + certName) + .clientCertPassword(Password.deobfuscate(keystorePwd)) + .trustStore(DataRouterConstants.DR_HOME_AUTH + keystore); + + this.searchUrl = searchUrl; + this.documentEndpoint = documentEndpoint; + + this.logger = logger; + } + + + /** + * Creates an index through the search db abstraction + * + * @param index - The name of the index to be created. + * @param schemaLocation - The name of the schema file for the index. + */ + public void createSearchIndex(String index, String schemaLocation) { + + // Create a mapping of the index name to schema location + indexSchemaMapping.put(index, schemaLocation); + + // Now, create the index. + createIndex(index, schemaLocation); + } + + + /** + * This method performs the actual work of creating a search index. + * + * @param index - The name of the index to be created. + * @param schemaLocation - The name of the schema file for the index. + */ + private void createIndex(String index, String schemaLocation) { + + logger.debug("Creating search index, index name: = " + index + ", schemaLocation = " + schemaLocation); + + MultivaluedMap headers = new MultivaluedMapImpl(); + headers.put("Accept", Arrays.asList("application/json")); + headers.put(Headers.FROM_APP_ID, Arrays.asList("DL")); + headers.put(Headers.TRANSACTION_ID, Arrays.asList(UUID.randomUUID().toString())); + + String url = concatSubUri(searchUrl, index); + try { + + OperationResult result = searchClient.put(url, loadFileData(schemaLocation), headers, + MediaType.APPLICATION_JSON_TYPE, null); + + if (!HttpUtil.isHttpResponseClassSuccess(result.getResultCode())) { + logger.error(DataRouterMsgs.FAIL_TO_CREATE_SEARCH_INDEX, index, result.getFailureCause()); + } else { + logger.info(DataRouterMsgs.SEARCH_INDEX_CREATE_SUCCESS, index); + } + + } catch (Exception e) { + logger.error(DataRouterMsgs.FAIL_TO_CREATE_SEARCH_INDEX, index, e.getLocalizedMessage()); + } + } + + + /** + * Retrieves a document from the search service. + * + * @param index - The index to retrieve the document from. + * @param id - The unique identifier for the document. + * + * @return - The REST response returned from the Search Service. + */ + public OperationResult getDocument(String index, String id) { + + Map> headers = new HashMap<>(); + headers.put(Headers.FROM_APP_ID, Arrays.asList("Data Router")); + headers.put(Headers.TRANSACTION_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID))); + + String url = concatSubUri(searchUrl, index, documentEndpoint, id); + return searchClient.get(url, headers, MediaType.APPLICATION_JSON_TYPE); + } + + + /** + * Creates or updates a document in the Search Service. + * + * @param index - The index to create or update the document in. + * @param id - The identifier for the document. + * @param payload - The document contents. + * @param headers - HTTP headers. + */ + public void putDocument(String index, String id, String payload, Map> headers) { + + // Try to post the document to the search service. + OperationResult result = doDocumentPut(index, id, payload, headers); + + // A 404 response from the Search Service may indicate that the index we are writing + // to does not actually exist. We will try creating it now. + if(result.getResultCode() == Status.NOT_FOUND.getStatusCode()) { + + // Lookup the location of the schema that we want to create. + String indexSchemaLocation = indexSchemaMapping.get(index); + if(indexSchemaLocation != null) { + + // Try creating the index now... + logger.info(DataRouterMsgs.CREATE_MISSING_INDEX, index); + createIndex(index, indexSchemaLocation); + + // ...and retry the document post. + result = doDocumentPut(index, id, payload, headers); + } + } + + if(!resultSuccessful(result)) { + logger.error(DataRouterMsgs.FAIL_TO_CREATE_UPDATE_DOC, index, result.getFailureCause()); + } + } + + + /** + * This method does the actual work of submitting a document PUT request to the Search Service. + * + * @param index - The index to create or update the document in. + * @param id - The identifier for the document. + * @param payload - The document contents. + * @param headers - HTTP headers. + * + * @return - The HTTP response returned by the Search Service. + */ + private OperationResult doDocumentPut(String index, String id, String payload, Map> headers) { + + String url = concatSubUri(searchUrl, index, documentEndpoint, id); + return searchClient.put(url, payload, headers, MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE); + } + + + /** + * Creates a document in the Search Service. + * + * @param index - The index to create the document in. + * @param payload - The document contents. + * @param headers - HTTP headers. + */ + public void postDocument(String index, String payload, Map> headers) { + + // Try to post the document to the search service. + OperationResult result = doDocumentPost(index, payload, headers); + + // A 404 response from the Search Service may indicate that the index we are writing + // to does not actually exist. We will try creating it now. + if(result.getResultCode() == Status.NOT_FOUND.getStatusCode()) { + + // Lookup the location of the schema that we want to create. + String indexSchemaLocation = indexSchemaMapping.get(index); + if(indexSchemaLocation != null) { + + // Try creating the index now... + logger.info(DataRouterMsgs.CREATE_MISSING_INDEX, index); + createIndex(index, indexSchemaLocation); + + // ...and retry the document post. + result = doDocumentPost(index, payload, headers); + } + } + + if(!resultSuccessful(result)) { + logger.error(DataRouterMsgs.FAIL_TO_CREATE_UPDATE_DOC, index, result.getFailureCause()); + } + } + + + /** + * This method does the actual work of submitting a document PUT request to the Search Service. + * + * @param index - The index to create or update the document in. + * @param payload - The document contents. + * @param headers - HTTP headers. + * + * @return - The HTTP response returned by the Search Service. + */ + private OperationResult doDocumentPost(String index, String payload, Map> headers) { + + String url = concatSubUri(searchUrl, index, documentEndpoint); + return searchClient.post(url, payload, headers, MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE); + } + + + /** + * Removes a document from the Search Service. + * + * @param index - The index to create the document in. + * @param id - The identifier for the document. + * @param payload - The document contents. + * @param headers - HTTP headers. + */ + public void deleteDocument(String index, String documentId, Map> headers) { + + String url = concatSubUri(searchUrl, index, documentEndpoint, documentId); + searchClient.delete(url, headers, null); + } + + + /** + * Convenience method to load up all the data from a file into a string + * + * @param filename the filename to read from disk + * @return the data contained within the file + * @throws Exception + */ + protected String loadFileData(String filename) throws Exception { + StringBuilder data = new StringBuilder(); + try { + BufferedReader in = new BufferedReader(new InputStreamReader( + EntityEventPolicy.class.getClassLoader().getResourceAsStream("/" + filename), + StandardCharsets.UTF_8)); + String line; + + while ((line = in.readLine()) != null) { + data.append(line); + } + } catch (Exception e) { + throw new Exception("Failed to read from file = " + filename + ".", e); + } + + return data.toString(); + } + + + /** + * Helper utility to concatenate substrings of a URI together to form a proper URI. + * + * @param suburis the list of substrings to concatenate together + * @return the concatenated list of substrings + */ + public static String concatSubUri(String... suburis) { + String finalUri = ""; + + for (String suburi : suburis) { + + if (suburi != null) { + // Remove any leading / since we only want to append / + suburi = suburi.replaceFirst("^/*", ""); + + // Add a trailing / if one isn't already there + finalUri += suburi.endsWith("/") ? suburi : suburi + "/"; + } + } + + return finalUri; + } + + + /** + * Helper utility to check the response code of an HTTP response. + * + * @param aResult - The response that we want to check. + * + * @return - true if the response contains a success code, + * false otherwise. + */ + private boolean resultSuccessful(OperationResult aResult) { + + return (aResult.getResultCode() >= 200) && (aResult.getResultCode() < 300); + } +}