X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Faai%2Fsa%2Frest%2FIndexApi.java;h=7d58fb3bc9a20bb3cc8fa1f9fd6f106e9e3e828e;hb=ecd35f117eb0118f9cbd96fe132a1c359214bfc7;hp=4add62c4816fe8a218034c68067176897f75aa82;hpb=f637a36c9df966c341727910e30241b63cc49c06;p=aai%2Fsearch-data-service.git diff --git a/src/main/java/org/onap/aai/sa/rest/IndexApi.java b/src/main/java/org/onap/aai/sa/rest/IndexApi.java index 4add62c..7d58fb3 100644 --- a/src/main/java/org/onap/aai/sa/rest/IndexApi.java +++ b/src/main/java/org/onap/aai/sa/rest/IndexApi.java @@ -43,365 +43,361 @@ import org.springframework.http.ResponseEntity; public class IndexApi { - private static final String HEADER_VALIDATION_SUCCESS = "SUCCESS"; - protected SearchServiceApi searchService = null; - - /** - * Configuration for the custom analyzers that will be used for indexing. - */ - protected AnalysisConfiguration analysisConfig; - - // Set up the loggers. + private static final String UNKNOWN_LOG_FIELD_STR = "Unknown"; + private static final String MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE = + "Unexpected authentication failure - cause: "; + private static final String MSG_AUTHENTICATION_FAILURE = "Authentication failure."; + private static final String HEADER_VALIDATION_SUCCESS = "SUCCESS"; + protected SearchServiceApi searchService = null; + + /** + * Configuration for the custom analyzers that will be used for indexing. + */ + protected AnalysisConfiguration analysisConfig; + + // Set up the loggers. private static Logger logger = LoggerFactory.getInstance().getLogger(IndexApi.class.getName()); private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(IndexApi.class.getName()); - public IndexApi(SearchServiceApi searchService) { - this.searchService = searchService; - init(); - } + public IndexApi(SearchServiceApi searchService) { + this.searchService = searchService; + init(); + } - /** - * Initializes the end point. - * - * @throws FileNotFoundException - * @throws IOException - * @throws DocumentStoreOperationException - */ - public void init() { + /** + * Initializes the end point. + * + * @throws FileNotFoundException + * @throws IOException + * @throws DocumentStoreOperationException + */ + public void init() { - // Instantiate our analysis configuration object. - analysisConfig = new AnalysisConfiguration(); - } + // Instantiate our analysis configuration object. + analysisConfig = new AnalysisConfiguration(); + } - /** + /** * Processes client requests to create a new index and document type in the document store. - * + * * @param documentSchema - The contents of the request body which is expected to be a JSON structure which * corresponds to the schema defined in document.schema.json - * @param index - The name of the index to create. - * @return - A Standard REST response - */ + * @param index - The name of the index to create. + * @return - A Standard REST response + */ public ResponseEntity processCreateIndex(String documentSchema, HttpServletRequest request, HttpHeaders headers, String index, DocumentStoreInterface documentStore) { - int resultCode = 500; - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); + int resultCode = 500; - // Validate that the request is correctly authenticated before going - // any further. - try { + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); + // Validate that the request is correctly authenticated before going any further. + try { if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, "Authentication failure."); - return errorResponse(HttpStatus.FORBIDDEN, "Authentication failure.", request); - } + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, MSG_AUTHENTICATION_FAILURE); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } - } catch (Exception e) { - - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, - "Unexpected authentication failure - cause: " + e.getMessage()); - return errorResponse(HttpStatus.FORBIDDEN, "Authentication failure.", request); - } + } catch (Exception e) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, + MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } - // We expect a payload containing the document schema. Make sure - // it is present. - if (documentSchema == null) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, "Missing document schema payload"); - return errorResponse(HttpStatus.valueOf(resultCode), "Missing payload", request); - } + // We expect a payload containing the document schema. Make sure + // it is present. + if (documentSchema == null) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, "Missing document schema payload"); + return errorResponse(HttpStatus.valueOf(resultCode), "Missing payload", request); + } String resultString; - try { - // Marshal the supplied json string into a document schema object. - ObjectMapper mapper = new ObjectMapper(); - DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); - - // Now, ask the DAO to create the index. - OperationResult result = documentStore.createIndex(index, schema); - - // Extract the result code and string from the OperationResult - // object so that we can use them to generate a standard REST - // response. - // Note that we want to return a 201 result code on a successful - // create, so if we get back a 200 from the document store, - // translate that int a 201. - resultCode = (result.getResultCode() == 200) ? 201 : result.getResultCode(); + try { + // Marshal the supplied json string into a document schema object. + ObjectMapper mapper = new ObjectMapper(); + DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); + + // Now, ask the DAO to create the index. + OperationResult result = documentStore.createIndex(index, schema); + + // Extract the result code and string from the OperationResult + // object so that we can use them to generate a standard REST + // response. + // Note that we want to return a 201 result code on a successful + // create, so if we get back a 200 from the document store, + // translate that int a 201. + resultCode = (result.getResultCode() == 200) ? 201 : result.getResultCode(); resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); - } catch (com.fasterxml.jackson.core.JsonParseException - | com.fasterxml.jackson.databind.JsonMappingException e) { + } catch (com.fasterxml.jackson.core.JsonParseException + | com.fasterxml.jackson.databind.JsonMappingException e) { - // We were unable to marshal the supplied json string into a valid - // document schema, so return an appropriate error response. - resultCode = HttpStatus.BAD_REQUEST.value(); - resultString = "Malformed schema: " + e.getMessage(); + // We were unable to marshal the supplied json string into a valid + // document schema, so return an appropriate error response. + resultCode = HttpStatus.BAD_REQUEST.value(); + resultString = "Malformed schema: " + e.getMessage(); - } catch (IOException e) { + } catch (IOException e) { - // We'll treat this is a general internal error. - resultCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); - resultString = "IO Failure: " + e.getMessage(); - } + // We'll treat this is a general internal error. + resultCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); + resultString = "IO Failure: " + e.getMessage(); + } ResponseEntity response = ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); + if (ApiUtils.isSuccessStatusCode(response.getStatusCodeValue())) { + logger.info(SearchDbMsgs.CREATED_INDEX, index); + } else { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, resultString); + } - // Log the result. - if ((response.getStatusCodeValue() >= 200) && (response.getStatusCodeValue() < 300)) { - logger.info(SearchDbMsgs.CREATED_INDEX, index); - } else { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, resultString); - } - - // Generate our audit log. - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + // Generate our audit log. + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, resultCode).setField( LogLine.DefinedFields.RESPONSE_DESCRIPTION, HttpStatus.valueOf(resultCode).toString()), - (request != null) ? request.getMethod() : "Unknown", - (request != null) ? request.getRequestURL ().toString () : "Unknown", - (request != null) ? request.getRemoteHost () : "Unknown", - Integer.toString(response.getStatusCodeValue ())); + (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, + Integer.toString(response.getStatusCodeValue())); - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); - // Finally, return the response. - return response; - } + // Finally, return the response. + return response; + } - /** + /** * This function accepts any JSON and will "blindly" write it to the document store. - * + * * Note, eventually this "dynamic" flow should follow the same JSON-Schema validation procedure as the normal create * index flow. - * - * @param dynamicSchema - The JSON string that will be sent to the document store. - * @param index - The name of the index to be created. - * @param documentStore - The document store specific interface. - * @return The result of the document store interface's operation. - */ - public ResponseEntity processCreateDynamicIndex(String dynamicSchema, HttpServletRequest request, - HttpHeaders headers, String index, DocumentStoreInterface documentStore) { + * + * @param dynamicSchema - The JSON string that will be sent to the document store. + * @param index - The name of the index to be created. + * @param documentStore - The document store specific interface. + * @return The result of the document store interface's operation. + */ + public ResponseEntity processCreateDynamicIndex(String dynamicSchema, HttpServletRequest request, + HttpHeaders headers, String index, DocumentStoreInterface documentStore) { - ResponseEntity response = null; + ResponseEntity response = null; ResponseEntity validationResponse = validateRequest(request, headers, index, SearchDbMsgs.INDEX_CREATE_FAILURE); - if (validationResponse.getStatusCodeValue () != HttpStatus.OK.value ()) { - response = validationResponse; - } else { - OperationResult result = documentStore.createDynamicIndex(index, dynamicSchema); + if (validationResponse.getStatusCodeValue() != HttpStatus.OK.value()) { + response = validationResponse; + } else { + OperationResult result = documentStore.createDynamicIndex(index, dynamicSchema); - int resultCode = (result.getResultCode() == 200) ? 201 : result.getResultCode(); - String resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); + int resultCode = (result.getResultCode() == 200) ? 201 : result.getResultCode(); + String resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); - response = ResponseEntity.status(resultCode).body(resultString); - } + response = ResponseEntity.status(resultCode).body(resultString); + } - return response; - } + return response; + } - /** + /** * Processes a client request to remove an index from the document store. Note that this implicitly deletes all * documents contained within that index. - * - * @param index - The index to be deleted. - * @return - A standard REST response. - */ + * + * @param index - The index to be deleted. + * @return - A standard REST response. + */ public ResponseEntity processDelete(String index, HttpServletRequest request, HttpHeaders headers, - DocumentStoreInterface documentStore) { + DocumentStoreInterface documentStore) { - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); ResponseEntity response; - // Validate that the request is correctly authenticated before going - // any further. - try { - if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, - ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, "Authentication failure."); - return errorResponse(HttpStatus.FORBIDDEN, "Authentication failure.", request); - } - - } catch (Exception e) { - logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, - "Unexpected authentication failure - cause: " + e.getMessage()); - return errorResponse(HttpStatus.FORBIDDEN, "Authentication failure.", request); - } - - try { - // Send the request to the document store. - response = responseFromOperationResult(documentStore.deleteIndex(index)); - } catch (DocumentStoreOperationException e) { + // Validate that the request is correctly authenticated before going + // any further. + try { + if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME)) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, MSG_AUTHENTICATION_FAILURE); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + + } catch (Exception e) { + logger.warn(SearchDbMsgs.INDEX_CREATE_FAILURE, index, + MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + + try { + // Send the request to the document store. + response = responseFromOperationResult(documentStore.deleteIndex(index)); + } catch (DocumentStoreOperationException e) { response = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON) .body(e.getMessage()); - } + } - // Log the result. - if ((response.getStatusCodeValue() >= 200) && (response.getStatusCodeValue() < 300)) { - logger.info(SearchDbMsgs.DELETED_INDEX, index); - } else { + if (ApiUtils.isSuccessStatusCode(response.getStatusCodeValue())) { + logger.info(SearchDbMsgs.DELETED_INDEX, index); + } else { logger.warn(SearchDbMsgs.INDEX_DELETE_FAILURE, index, response.getBody()); - } + } - // Generate our audit log. - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatusCodeValue()).setField( LogLine.DefinedFields.RESPONSE_DESCRIPTION, response.getStatusCode().getReasonPhrase()), - (request != null) ? request.getMethod() : "Unknown", - (request != null) ? request.getRequestURL ().toString () : "Unknown", - (request != null) ? request.getRemoteHost () : "Unknown", - Integer.toString(response.getStatusCodeValue())); + (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, + Integer.toString(response.getStatusCodeValue())); - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); + // Clear the MDC context so that no other transaction inadvertently uses our transaction id. + ApiUtils.clearMdcContext(); - return response; - } + return response; + } - /** + /** * This method takes a JSON format document schema and produces a set of field mappings in the form that Elastic * Search expects. - * - * @param documentSchema - A document schema expressed as a JSON string. - * @return - A JSON string expressing an Elastic Search mapping configuration. - * @throws com.fasterxml.jackson.core.JsonParseException - * @throws com.fasterxml.jackson.databind.JsonMappingException - * @throws IOException - */ + * + * @param documentSchema - A document schema expressed as a JSON string. + * @return - A JSON string expressing an Elastic Search mapping configuration. + * @throws com.fasterxml.jackson.core.JsonParseException + * @throws com.fasterxml.jackson.databind.JsonMappingException + * @throws IOException + */ public String generateDocumentMappings(String documentSchema) throws IOException { - // Unmarshal the json content into a document schema object. - ObjectMapper mapper = new ObjectMapper(); - DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); + // Unmarshal the json content into a document schema object. + ObjectMapper mapper = new ObjectMapper(); + DocumentSchema schema = mapper.readValue(documentSchema, DocumentSchema.class); - // Now, generate the Elastic Search mapping json and return it. - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append("\"properties\": {"); + // Now, generate the Elastic Search mapping json and return it. + StringBuilder sb = new StringBuilder(); + sb.append("{"); + sb.append("\"properties\": {"); - boolean first = true; - for (DocumentFieldSchema field : schema.getFields()) { + boolean first = true; + for (DocumentFieldSchema field : schema.getFields()) { - if (!first) { - sb.append(","); - } else { - first = false; - } + if (!first) { + sb.append(","); + } else { + first = false; + } - sb.append("\"").append(field.getName()).append("\": {"); + sb.append("\"").append(field.getName()).append("\": {"); - // The field type is mandatory. - sb.append("\"type\": \"").append(field.getDataType()).append("\""); + // The field type is mandatory. + sb.append("\"type\": \"").append(field.getDataType()).append("\""); - // If the index field was specified, then append it. - if (field.getSearchable() != null) { + // If the index field was specified, then append it. + if (field.getSearchable() != null) { sb.append(", \"index\": \"").append(field.getSearchable() ? "analyzed" : "not_analyzed").append("\""); - } + } - // If a search analyzer was specified, then append it. - if (field.getSearchAnalyzer() != null) { - sb.append(", \"search_analyzer\": \"").append(field.getSearchAnalyzer()).append("\""); - } + // If a search analyzer was specified, then append it. + if (field.getSearchAnalyzer() != null) { + sb.append(", \"search_analyzer\": \"").append(field.getSearchAnalyzer()).append("\""); + } - // If an indexing analyzer was specified, then append it. - if (field.getIndexAnalyzer() != null) { - sb.append(", \"analyzer\": \"").append(field.getIndexAnalyzer()).append("\""); - } else { - sb.append(", \"analyzer\": \"").append("whitespace").append("\""); - } + // If an indexing analyzer was specified, then append it. + if (field.getIndexAnalyzer() != null) { + sb.append(", \"analyzer\": \"").append(field.getIndexAnalyzer()).append("\""); + } else { + sb.append(", \"analyzer\": \"").append("whitespace").append("\""); + } - sb.append("}"); - } + sb.append("}"); + } - sb.append("}"); - sb.append("}"); + sb.append("}"); + sb.append("}"); - logger.debug("Generated document mappings: " + sb.toString()); + logger.debug("Generated document mappings: " + sb.toString()); - return sb.toString(); - } + return sb.toString(); + } - /** + /** * Converts an {@link OperationResult} to a standard REST {@link ResponseEntity} object. - * - * @param result - The {@link OperationResult} to be converted. - * @return - The equivalent {@link ResponseEntity} object. - */ - public ResponseEntity responseFromOperationResult(OperationResult result) { + * + * @param result - The {@link OperationResult} to be converted. + * @return - The equivalent {@link ResponseEntity} object. + */ + public ResponseEntity responseFromOperationResult(OperationResult result) { - if ((result.getResultCode() >= 200) && (result.getResultCode() < 300)) { + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) .body(result.getResult()); - } else { - if (result.getFailureCause() != null) { + } else { + if (result.getFailureCause() != null) { return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) .body(result.getFailureCause()); - } else { + } else { return ResponseEntity.status(result.getResultCode()).contentType(MediaType.APPLICATION_JSON) .body(result.getResult()); - } + } + } } - } - public ResponseEntity errorResponse(HttpStatus status, String msg, HttpServletRequest request) { + public ResponseEntity errorResponse(HttpStatus status, String msg, HttpServletRequest request) { - // Generate our audit log. - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + // Generate our audit log. + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, status.value()) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, status.getReasonPhrase()), - (request != null) ? request.getMethod() : "Unknown", - (request != null) ? request.getRequestURL ().toString () : "Unknown", - (request != null) ? request.getRemoteHost() : "Unknown", Integer.toString(status.value())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return ResponseEntity.status(status).contentType ( MediaType.APPLICATION_JSON ).body(msg); - } - - - /** - * A helper method used for validating/authenticating an incoming request. - * - * @param request - The http request that will be validated. - * @param headers - The http headers that will be validated. - * @param index - The name of the index that the document store request is being made against. - * @param failureMsgEnum - The logging message to be used upon validation failure. - * @return A success or failure response - */ + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, status.getReasonPhrase()), + (request != null) ? request.getMethod() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRequestURL().toString() : UNKNOWN_LOG_FIELD_STR, + (request != null) ? request.getRemoteHost() : UNKNOWN_LOG_FIELD_STR, Integer.toString(status.value())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON).body(msg); + } + + + /** + * A helper method used for validating/authenticating an incoming request. + * + * @param request - The http request that will be validated. + * @param headers - The http headers that will be validated. + * @param index - The name of the index that the document store request is being made against. + * @param failureMsgEnum - The logging message to be used upon validation failure. + * @return A success or failure response + */ private ResponseEntity validateRequest(HttpServletRequest request, HttpHeaders headers, String index, SearchDbMsgs failureMsgEnum) { - try { + try { if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(failureMsgEnum, index, "Authentication failure."); - return errorResponse(HttpStatus.FORBIDDEN, "Authentication failure.", request); - } - } catch (Exception e) { - logger.warn(failureMsgEnum, index, "Unexpected authentication failure - cause: " + e.getMessage()); - return errorResponse(HttpStatus.FORBIDDEN, "Authentication failure.", request); + logger.warn(failureMsgEnum, index, MSG_AUTHENTICATION_FAILURE); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + } catch (Exception e) { + logger.warn(failureMsgEnum, index, MSG_UNEXPECTED_AUTHENTICATION_FAILURE_CAUSE + e.getMessage()); + return errorResponse(HttpStatus.FORBIDDEN, MSG_AUTHENTICATION_FAILURE, request); + } + return ResponseEntity.status(HttpStatus.OK).body(HEADER_VALIDATION_SUCCESS); } - return ResponseEntity.status(HttpStatus.OK).body(HEADER_VALIDATION_SUCCESS); - } }