diff options
20 files changed, 430 insertions, 488 deletions
diff --git a/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java b/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java index b64cb74..199b5ec 100644 --- a/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java +++ b/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuth.java @@ -25,29 +25,18 @@ import org.springframework.http.HttpHeaders; public class SearchDbServiceAuth { - public SearchDbServiceAuth() {} + public SearchDbServiceAuth() { // Do not instantiate + } public boolean authBasic(String username, String authFunction) { return SearchDbServiceAuthCore.authorize(username, authFunction); } public String authUser(HttpHeaders headers, String authUser, String authFunction) { - - - SearchDbServiceAuth aaiAuth = new SearchDbServiceAuth(); - - StringBuilder username = new StringBuilder(); - - username.append(authUser); - if (aaiAuth.authBasic(username.toString(), authFunction) == false) { - return "AAI_9101"; - - } - return "OK"; + return new SearchDbServiceAuth().authBasic(authUser, authFunction) ? "OK" : "AAI_9101"; } public boolean authCookie(Cookie cookie, String authFunction, StringBuilder username) { - if (cookie == null) { return false; } diff --git a/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java b/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java index 95c48c3..369caa1 100644 --- a/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java +++ b/src/main/java/org/onap/aai/sa/auth/SearchDbServiceAuthCore.java @@ -51,13 +51,13 @@ public class SearchDbServiceAuthCore { DELETE } - // Don't instantiate - private SearchDbServiceAuthCore() {} - private static boolean usersInitialized = false; private static HashMap<String, SearchDbAuthUser> users; private static Timer timer = null; + // Don't instantiate + private SearchDbServiceAuthCore() {} + public static synchronized void init() { if (SearchDbServiceAuthCore.authFileName == null) { SearchDbServiceAuthCore.authFileName = "/home/aaiadmin/etc/aaipolicy.json"; @@ -133,7 +133,6 @@ public class SearchDbServiceAuthCore { } usersInitialized = true; - } public static class SearchDbAuthUser { @@ -160,18 +159,15 @@ public class SearchDbServiceAuthCore { for (Map.Entry<String, TabularAuthRole> roleEntry : this.roles.entrySet()) { TabularAuthRole role = roleEntry.getValue(); if (role.hasAllowedFunction(checkFunc)) { - // break out as soon as we find it return true; } } - // we would have got positive confirmation had it been there return false; } public void setUser(String myuser) { this.username = myuser; } - } public static class TabularAuthRole { diff --git a/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java b/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java index 664124d..bf6f17c 100644 --- a/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java +++ b/src/main/java/org/onap/aai/sa/rest/AnalyzerApi.java @@ -46,113 +46,116 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/services/search-data-service/v1/analyzers/search") public class AnalyzerApi { - private SearchServiceApi searchService = null; + private SearchServiceApi searchService = null; - // Set up the loggers. - private static Logger logger = LoggerFactory.getInstance().getLogger(IndexApi.class.getName()); + // 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 AnalyzerApi( @Qualifier("searchServiceApi") SearchServiceApi searchService) { - this.searchService = searchService; - } + private static final String MSG_AUTHENTICATION_FAILURE = "Authentication failure."; + + public AnalyzerApi(@Qualifier("searchServiceApi") SearchServiceApi searchService) { + this.searchService = searchService; + } @RequestMapping(method = RequestMethod.GET, consumes = {"application/json"}, produces = {"application/json"}) public ResponseEntity<String> processGet(HttpServletRequest request, @RequestHeader HttpHeaders headers, - ApiUtils apiUtils) { + ApiUtils apiUtils) { - HttpStatus responseCode = HttpStatus.INTERNAL_SERVER_ERROR; + HttpStatus responseCode = HttpStatus.INTERNAL_SERVER_ERROR; String responseString; - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); + // Initialize the MDC Context for logging purposes. + ApiUtils.initMdcContext(request, headers); - // Validate that the request is correctly authenticated before going - // any further. - try { + // Validate that the request is correctly authenticated before going + // any further. + try { if (!searchService.validateRequest(headers, request, ApiUtils.Action.GET, ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, "Authentication failure."); + logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, MSG_AUTHENTICATION_FAILURE); return ResponseEntity.status(HttpStatus.FORBIDDEN).contentType(MediaType.APPLICATION_JSON) - .body("Authentication failure."); - } + .body(MSG_AUTHENTICATION_FAILURE); + } - } catch (Exception e) { + } catch (Exception e) { - logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, - "Unexpected authentication failure - cause: " + e.getMessage()); + logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, + "Unexpected authentication failure - cause: " + e.getMessage()); return ResponseEntity.status(HttpStatus.FORBIDDEN).contentType(MediaType.APPLICATION_JSON) - .body("Authentication failure."); - } + .body(MSG_AUTHENTICATION_FAILURE); + } - // Now, build the list of analyzers. - try { + // Now, build the list of analyzers. + try { responseString = buildAnalyzerList(ElasticSearchHttpController.getInstance().getAnalysisConfig()); - responseCode = HttpStatus.OK; - } catch (Exception e) { - logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, - "Unexpected failure retrieving analysis configuration - cause: " + e.getMessage()); - responseString = "Failed to retrieve analysis configuration. Cause: " + e.getMessage(); - } + responseCode = HttpStatus.OK; + } catch (Exception e) { + logger.warn(SearchDbMsgs.GET_ANALYZERS_FAILURE, + "Unexpected failure retrieving analysis configuration - cause: " + e.getMessage()); + responseString = "Failed to retrieve analysis configuration. Cause: " + e.getMessage(); + } - // Build the HTTP response. + // Build the HTTP response. ResponseEntity<String> response = ResponseEntity.status(responseCode).contentType(MediaType.APPLICATION_JSON).body(responseString); - // Generate our audit log. - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + // Generate our audit log. + String unknownLogField = "Unknown"; + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, responseCode.value()) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, responseCode.value()), - (request != null) ? request.getMethod() : "Unknown", - (request != null) ? request.getRequestURL ().toString () : "Unknown", - (request != null) ? request.getRemoteHost () : "Unknown", - Integer.toString(response.getStatusCodeValue ())); + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, responseCode.value()), + (request != null) ? request.getMethod() : unknownLogField, + (request != null) ? request.getRequestURL().toString() : unknownLogField, + (request != null) ? request.getRemoteHost() : unknownLogField, + 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 list of analyzer objects and generates a simple json structure to enumerate them. - * + * * <p> * Note, this includes only the aspects of the analyzer object that we want to make public to an external client. - * + * * @param analysisConfig - The analysis configuration object to extract the analyzers from. - * @return - A json string enumerating the defined analyzers. - */ - private String buildAnalyzerList(AnalysisConfiguration analysisConfig) { - - StringBuilder sb = new StringBuilder(); - - sb.append("{"); - AtomicBoolean firstAnalyzer = new AtomicBoolean(true); - for (AnalyzerSchema analyzer : analysisConfig.getAnalyzers()) { - - if (!firstAnalyzer.compareAndSet(true, false)) { - sb.append(", "); - } - - sb.append("{"); - sb.append("\"name\": \"").append(analyzer.getName()).append("\", "); - sb.append("\"description\": \"").append(analyzer.getDescription()).append("\", "); - sb.append("\"behaviours\": ["); - AtomicBoolean firstBehaviour = new AtomicBoolean(true); - for (String behaviour : analyzer.getBehaviours()) { - if (!firstBehaviour.compareAndSet(true, false)) { - sb.append(", "); + * @return - A json string enumerating the defined analyzers. + */ + private String buildAnalyzerList(AnalysisConfiguration analysisConfig) { + + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + AtomicBoolean firstAnalyzer = new AtomicBoolean(true); + for (AnalyzerSchema analyzer : analysisConfig.getAnalyzers()) { + + if (!firstAnalyzer.compareAndSet(true, false)) { + sb.append(", "); + } + + sb.append("{"); + sb.append("\"name\": \"").append(analyzer.getName()).append("\", "); + sb.append("\"description\": \"").append(analyzer.getDescription()).append("\", "); + sb.append("\"behaviours\": ["); + AtomicBoolean firstBehaviour = new AtomicBoolean(true); + for (String behaviour : analyzer.getBehaviours()) { + if (!firstBehaviour.compareAndSet(true, false)) { + sb.append(", "); + } + sb.append("\"").append(behaviour).append("\""); + } + sb.append("]"); + sb.append("}"); } - sb.append("\"").append(behaviour).append("\""); - } - sb.append("]"); - sb.append("}"); - } - sb.append("}"); + sb.append("}"); - return sb.toString(); - } + return sb.toString(); + } } diff --git a/src/main/java/org/onap/aai/sa/rest/ApiUtils.java b/src/main/java/org/onap/aai/sa/rest/ApiUtils.java index fee8621..f240561 100644 --- a/src/main/java/org/onap/aai/sa/rest/ApiUtils.java +++ b/src/main/java/org/onap/aai/sa/rest/ApiUtils.java @@ -20,8 +20,10 @@ */ package org.onap.aai.sa.rest; +import com.google.common.base.Strings; import java.util.UUID; import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.Response.Status.Family; import org.onap.aai.cl.mdc.MdcContext; import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; import org.slf4j.MDC; @@ -34,8 +36,11 @@ import org.springframework.http.HttpStatus; */ public class ApiUtils { - public static final String SEARCH_AUTH_POLICY_NAME = "search"; public static final String URL_PREFIX = "services/search-data-service/v1/search"; + public static final String SEARCH_AUTH_POLICY_NAME = "search"; + + private static final String URI_SEGMENT_INDEXES = "indexes"; + private static final String URI_SEGMENT_DOCUMENTS = "documents"; public enum Action { POST, @@ -56,8 +61,7 @@ public class ApiUtils { String transId = null; if (headers != null) { transId = headers.getFirst("X-TransactionId"); - - if ((transId == null) || (transId.equals(""))) { + if (Strings.isNullOrEmpty(transId)) { transId = UUID.randomUUID().toString(); } } @@ -73,38 +77,29 @@ public class ApiUtils { } public static String buildIndexUri(String index) { - return (URL_PREFIX + "/indexes/") + index; } public static String buildDocumentUri(String index, String documentId) { - return buildIndexUri(index) + "/documents/" + documentId; } public static boolean validateIndexUri(String uri) { - - // If the URI starts with a leading '/' character, remove it. uri = uri.startsWith("/") ? uri.substring(1) : uri; - - // Now, tokenize the URI string. String[] tokens = uri.split("/"); - - return (tokens.length == 6) && (tokens[4].equals("indexes")); - + return (tokens.length == 6) && (tokens[4].equals(URI_SEGMENT_INDEXES)); } public static boolean validateDocumentUri(String uri, boolean requireId) { uri = uri.startsWith("/") ? uri.substring(1) : uri; - - // Now, tokenize the URI string. String[] tokens = uri.split("/"); if (requireId) { - return (tokens.length == 8) && (tokens[4].equals("indexes") && (tokens[6].equals("documents"))); + return (tokens.length == 8) + && (tokens[4].equals(URI_SEGMENT_INDEXES) && (tokens[6].equals(URI_SEGMENT_DOCUMENTS))); } else { return ((tokens.length == 8) || (tokens.length == 7)) - && (tokens[4].equals("indexes") && (tokens[6].equals("documents"))); + && (tokens[4].equals(URI_SEGMENT_INDEXES) && (tokens[6].equals(URI_SEGMENT_DOCUMENTS))); } } @@ -115,7 +110,7 @@ public class ApiUtils { int i = 0; for (String token : tokens) { - if (token.equals("indexes") && i + 1 < tokens.length) { + if (token.equals(URI_SEGMENT_INDEXES) && i + 1 < tokens.length) { return tokens[i + 1]; } i++; @@ -131,7 +126,7 @@ public class ApiUtils { int i = 0; for (String token : tokens) { - if (token.equals("documents") && i + 1 < tokens.length) { + if (token.equals(URI_SEGMENT_DOCUMENTS) && i + 1 < tokens.length) { return tokens[i + 1]; } i++; @@ -144,11 +139,15 @@ public class ApiUtils { try { return HttpStatus.valueOf(httpStatusCode).getReasonPhrase(); } catch (IllegalArgumentException e) { - if (httpStatusCode == 207) { + if (207 == httpStatusCode) { return "Multi-Status"; } else { return "Unknown"; } } } + + public static boolean isSuccessStatusCode(int statusCode) { + return Family.familyOf(statusCode).equals(Family.SUCCESSFUL); + } } diff --git a/src/main/java/org/onap/aai/sa/rest/BulkApi.java b/src/main/java/org/onap/aai/sa/rest/BulkApi.java index 84f4953..3a7b797 100644 --- a/src/main/java/org/onap/aai/sa/rest/BulkApi.java +++ b/src/main/java/org/onap/aai/sa/rest/BulkApi.java @@ -67,6 +67,7 @@ public class BulkApi { private static Logger logger = LoggerFactory.getInstance().getLogger(BulkApi.class.getName()); private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(BulkApi.class.getName()); + private static final String MSG_STACK_TRACE = "Stack Trace:\n"; /** * Create a new instance of the BulkApi end point. @@ -89,20 +90,20 @@ public class BulkApi { */ public ResponseEntity<String> processPost(String operations, HttpServletRequest request, HttpHeaders headers, DocumentStoreInterface documentStore) { - // Initialize the MDC Context for logging purposes. ApiUtils.initMdcContext(request, headers); - // Set a default result code and entity string for the request. - int resultCode = 500; - String resultString; - if (logger.isDebugEnabled()) { logger.debug("SEARCH: Process Bulk Request - operations = [" + operations.replaceAll("\n", "") + " ]"); } + // We expect a payload containing a JSON structure enumerating the operations to be performed. + if (operations == null) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Missing operations list payload"); + return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Missing payload", request); + } + try { - // Validate that the request is correctly authenticated before going - // any further. + // Validate that the request is correctly authenticated before going any further. if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, ApiUtils.SEARCH_AUTH_POLICY_NAME)) { logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Authentication failure."); @@ -110,25 +111,17 @@ public class BulkApi { return buildResponse(HttpStatus.FORBIDDEN.value(), "Authentication failure.", request); } } catch (Exception e) { - // This is a catch all for any unexpected failure trying to perform - // the authentication. + // This is a catch all for any unexpected failure trying to perform the authentication. logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Unexpected authentication failure - cause: " + e.getMessage()); if (logger.isDebugEnabled()) { - logger.debug("Stack Trace:\n" + e.getStackTrace()); + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); } return buildResponse(HttpStatus.FORBIDDEN.value(), "Authentication failure - cause " + e.getMessage(), request); } - // We expect a payload containing a JSON structure enumerating the - // operations to be performed. - if (operations == null) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Missing operations list payload"); - return buildResponse(resultCode, "Missing payload", request); - } - // Marshal the supplied json string into a Java object. ObjectMapper mapper = new ObjectMapper(); BulkRequest[] requests = null; @@ -137,7 +130,7 @@ public class BulkApi { } catch (IOException e) { logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Failed to marshal operations list: " + e.getMessage()); if (logger.isDebugEnabled()) { - logger.debug("Stack Trace:\n" + e.getStackTrace()); + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); } // Populate the result code and entity string for our HTTP response // and return the response to the client.. @@ -145,54 +138,47 @@ public class BulkApi { request); } - // Verify that our parsed operations list actually contains some valid - // operations. + // Verify that our parsed operations list actually contains some valid operations. if (requests.length == 0) { logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Empty operations list in bulk request"); - // Populate the result code and entity string for our HTTP response // and return the response to the client.. return buildResponse(HttpStatus.BAD_REQUEST.value(), "Empty operations list in bulk request", request); } - try { + int resultCode; + String resultString; + + try { // Now, forward the set of bulk operations to the DAO for processing. OperationResult result = documentStore.performBulkOperations(requests); - // Populate the result code and entity string for our HTTP response. resultCode = result.getResultCode(); resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); - } catch (DocumentStoreOperationException e) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Unexpected failure communicating with document store: " + e.getMessage()); if (logger.isDebugEnabled()) { - logger.debug("Stack Trace:\n" + e.getStackTrace()); + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); } - // Populate the result code and entity string for our HTTP response. resultCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); resultString = "Unexpected failure processing bulk operations: " + e.getMessage(); } - // Build our HTTP response. ResponseEntity<String> response = ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); - // Log the result. if ((response.getStatusCodeValue() >= 200) && (response.getStatusCodeValue() < 300)) { logger.info(SearchDbMsgs.PROCESSED_BULK_OPERATIONS); } else { logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, response.getBody()); } - // Finally, return the HTTP response to the client. return buildResponse(resultCode, resultString, request); } - /** * This method generates an audit log and returns an HTTP response object. * @@ -206,12 +192,13 @@ public class BulkApi { ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); // Generate our audit log. + String unknownLogField = "Unknown"; auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, resultCode) .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, ApiUtils.getHttpStatusString(resultCode)), - (request != null) ? request.getMethod() : "Unknown", - (request != null) ? request.getRequestURL().toString() : "Unknown", - (request != null) ? request.getRemoteHost() : "Unknown", + (request != null) ? request.getMethod() : unknownLogField, + (request != null) ? request.getRequestURL().toString() : unknownLogField, + (request != null) ? request.getRemoteHost() : unknownLogField, Integer.toString(response.getStatusCodeValue())); // Clear the MDC context so that no other transaction inadvertently diff --git a/src/main/java/org/onap/aai/sa/rest/Document.java b/src/main/java/org/onap/aai/sa/rest/Document.java index 89ac2e1..e9bcaf4 100644 --- a/src/main/java/org/onap/aai/sa/rest/Document.java +++ b/src/main/java/org/onap/aai/sa/rest/Document.java @@ -26,9 +26,10 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; public class Document { - private Map<String, Object> fields = new HashMap<String, Object>(); + private Map<String, Object> fields = new HashMap<>(); @JsonAnyGetter public Map<String, Object> getFields() { @@ -41,20 +42,16 @@ public class Document { } public String toJson() throws JsonProcessingException { - - ObjectMapper mapper = new ObjectMapper(); - return mapper.writeValueAsString(this); + return new ObjectMapper().writeValueAsString(this); } - @Override public String toString() { - String str = "Document: ["; - for (String key : fields.keySet()) { - str += key + ": " + fields.get(key); + StringBuilder sb = new StringBuilder("Document: ["); + for (Entry<String, Object> entry : fields.entrySet()) { + sb.append(entry.getKey()).append(": ").append(entry.getValue()); } - str += "]"; - - return str; + sb.append("]"); + return sb.toString(); } } diff --git a/src/main/java/org/onap/aai/sa/rest/DocumentApi.java b/src/main/java/org/onap/aai/sa/rest/DocumentApi.java index af650a7..14d430e 100644 --- a/src/main/java/org/onap/aai/sa/rest/DocumentApi.java +++ b/src/main/java/org/onap/aai/sa/rest/DocumentApi.java @@ -43,6 +43,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; public class DocumentApi { + private static final String MSG_REQUEST_BODY = "Request Body: "; private static final String REQUEST_HEADER_RESOURCE_VERSION = "If-Match"; private static final String RESPONSE_HEADER_RESOURCE_VERSION = "ETag"; private static final String REQUEST_HEADER_ALLOW_IMPLICIT_INDEX_CREATION = "X-CreateIndex"; @@ -88,7 +89,7 @@ public class DocumentApi { DocumentOperationResult result = documentStore.createDocument(index, document, implicitlyCreateIndex(headers)); String output = null; - if (result.getResultCode() >= 200 && result.getResultCode() <= 299) { + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); } else { output = result.getError() != null @@ -155,7 +156,7 @@ public class DocumentApi { } String output = null; - if (result.getResultCode() >= 200 && result.getResultCode() <= 299) { + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); } else { output = result.getError() != null @@ -212,7 +213,7 @@ public class DocumentApi { DocumentOperationResult result = documentStore.deleteDocument(index, document); String output = null; - if (!(result.getResultCode() >= 200 && result.getResultCode() <= 299)) { // + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { output = result.getError() != null ? mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getError()) : result.getFailureCause(); @@ -271,7 +272,7 @@ public class DocumentApi { DocumentOperationResult result = documentStore.getDocument(index, document); String output = null; - if (result.getResultCode() >= 200 && result.getResultCode() <= 299) { + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getDocument()); } else { output = result.getError() != null @@ -320,7 +321,7 @@ public class DocumentApi { SearchOperationResult result = documentStore.search(index, queryText); String output = null; - if (result.getResultCode() >= 200 && result.getResultCode() <= 299) { + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result.getSearchResult()); } else { output = result.getError() != null @@ -349,7 +350,7 @@ public class DocumentApi { logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "GET", (request != null) ? request.getRequestURL().toString() : ""); if (logger.isDebugEnabled()) { - logger.debug("Request Body: " + content); + logger.debug(MSG_REQUEST_BODY + content); } return processQuery(index, content, request, headers, documentStore); } @@ -363,7 +364,7 @@ public class DocumentApi { logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "POST", (request != null) ? request.getRequestURL().toString() : ""); if (logger.isDebugEnabled()) { - logger.debug("Request Body: " + content); + logger.debug(MSG_REQUEST_BODY + content); } return processQuery(index, content, request, headers, documentStore); @@ -379,7 +380,7 @@ public class DocumentApi { logger.info(SearchDbMsgs.PROCESS_PAYLOAD_QUERY, "POST", (request != null) ? request.getRequestURL().toString() : ""); if (logger.isDebugEnabled()) { - logger.debug("Request Body: " + content); + logger.debug(MSG_REQUEST_BODY + content); } return processSuggestQuery(index, content, request, headers, documentStore); @@ -437,7 +438,7 @@ public class DocumentApi { // ElasticSearch syntax, to the document store DAO. SearchOperationResult result = documentStore.searchWithPayload(index, searchStatement.toElasticSearch()); String output = null; - if (result.getResultCode() >= 200 && result.getResultCode() <= 299) { + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { output = prepareOutput(mapper, result); } else { output = result.getError() != null @@ -512,7 +513,7 @@ public class DocumentApi { SearchOperationResult result = documentStore.suggestionQueryWithPayload(index, suggestionStatement.toElasticSearch()); String output = null; - if (result.getResultCode() >= 200 && result.getResultCode() <= 299) { + if (ApiUtils.isSuccessStatusCode(result.getResultCode())) { output = prepareSuggestOutput(mapper, result); } else { output = result.getError() != null @@ -541,15 +542,8 @@ public class DocumentApi { * @return - true if the headers indicate that missing indices should be implicitly created, false otherwise. */ private boolean implicitlyCreateIndex(HttpHeaders headers) { - - boolean createIndexIfNotPresent = false; String implicitIndexCreationHeader = headers.getFirst(REQUEST_HEADER_ALLOW_IMPLICIT_INDEX_CREATION); - - if ((implicitIndexCreationHeader != null) && (implicitIndexCreationHeader.equals("true"))) { - createIndexIfNotPresent = true; - } - - return createIndexIfNotPresent; + return implicitIndexCreationHeader != null && "true".equals(implicitIndexCreationHeader); } private String prepareOutput(ObjectMapper mapper, SearchOperationResult result) throws JsonProcessingException { 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<String> 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<String> 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<String> 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<String> processCreateDynamicIndex(String dynamicSchema, HttpServletRequest request, + HttpHeaders headers, String index, DocumentStoreInterface documentStore) { - ResponseEntity<String> response = null; + ResponseEntity<String> response = null; ResponseEntity<String> 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<String> 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<String> 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<String> responseFromOperationResult(OperationResult result) { + * + * @param result - The {@link OperationResult} to be converted. + * @return - The equivalent {@link ResponseEntity} object. + */ + public ResponseEntity<String> 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<String> errorResponse(HttpStatus status, String msg, HttpServletRequest request) { + public ResponseEntity<String> 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<String> 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); - } } diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java index afb1da3..1880168 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchError.java @@ -31,8 +31,7 @@ public class ElasticSearchError { private String reason; private ElasticSearchCause causedBy; - private Map<String, Object> additionalProperties = new HashMap<String, Object>(); - + private Map<String, Object> additionalProperties = new HashMap<>(); public String getType() { return type; diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java index a0b72f7..6d08c1d 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java @@ -54,7 +54,6 @@ import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.Response.Status.Family; import javax.ws.rs.core.UriBuilder; import org.eclipse.jetty.http.HttpStatus; import org.json.simple.JSONArray; @@ -641,11 +640,8 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { MdcOverride override = getStartTime(new MdcOverride()); HttpURLConnection conn = createConnection(url, HttpMethod.PUT); - - attachDocument(conn, document); - opResult = getOperationResult(conn); buildDocumentResult(opResult, indexName); @@ -759,7 +755,7 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { InputStream inputStream = null; - if (!isSuccessCode(resultCode)) { + if (!ApiUtils.isSuccessStatusCode(resultCode)) { inputStream = conn.getErrorStream(); } else { try { @@ -842,11 +838,7 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { } private boolean isSuccess(OperationResult result) { - return isSuccessCode(result.getResultCode()); - } - - private boolean isSuccessCode(int statusCode) { - return Family.familyOf(statusCode).equals(Family.SUCCESSFUL); + return ApiUtils.isSuccessStatusCode(result.getResultCode()); } private UriBuilder createUriBuilder(String path, String... paths) { @@ -1216,7 +1208,7 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { // Increment the operation counts. totalOps++; - if (isSuccessCode(item.operationStatus().getStatus())) { + if (ApiUtils.isSuccessStatusCode(item.operationStatus().getStatus())) { totalSuccess++; } else { totalFails++; diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java index a0941e7..6374716 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchOperationStatus.java @@ -35,8 +35,7 @@ public class ElasticSearchOperationStatus { private Integer status; private ElasticSearchError error; - private Map<String, Object> additionalProperties = new HashMap<String, Object>(); - + private Map<String, Object> additionalProperties = new HashMap<>(); public ElasticSearchError getError() { return error; @@ -110,5 +109,4 @@ public class ElasticSearchOperationStatus { + ", shards=" + shards + ", status=" + status + "]"; } - } diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java index 529900d..151e02b 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchResultItem.java @@ -112,7 +112,7 @@ public class ElasticSearchResultItem { sb.append("\"status-message\": \""); - if ((operationStatus().getStatus() >= 200) && (operationStatus().getStatus() < 300)) { + if (ApiUtils.isSuccessStatusCode(operationStatus().getStatus())) { sb.append("OK"); } else { // Sometimes the error object doesn't get populated, so check diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java index e1994fe..84f0e9e 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Aggregation.java @@ -45,13 +45,11 @@ public class Aggregation { } public String toElasticSearch() { - StringBuffer sb = new StringBuffer(); - + StringBuilder sb = new StringBuilder(); sb.append("\""); sb.append(name); sb.append("\": "); sb.append(aggregation.toElasticSearch()); - return sb.toString(); } diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java index 4b446fd..94a091d 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/AggregationStatement.java @@ -81,7 +81,7 @@ public class AggregationStatement { } public String toElasticSearch() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("{"); @@ -127,7 +127,7 @@ public class AggregationStatement { @Override public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); if (nested != null) { sb.append("{nested: "); diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java index 5851f9a..a4e0cc2 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/DateRangeAggregation.java @@ -26,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; * An example of a date_range aggregation: * * <p> - * + * * <pre> * { * "aggs": { @@ -48,7 +48,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; */ public class DateRangeAggregation extends AbstractAggregation { - private String format; @JsonProperty("ranges") @@ -114,7 +113,7 @@ public class DateRangeAggregation extends AbstractAggregation { @Override public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("date-range: {field: " + field + ", format: " + format + ", size: " + size + ", minThreshold: " + minThreshold + "ranges: ["); for (int i = 0; i < dateRanges.length; i++) { diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java index 4e8bdd0..134c660 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/Filter.java @@ -28,7 +28,7 @@ import java.util.List; * * <p> * The expected JSON structure for a filter stanza is as follows: - * + * * <pre> * { * "filter": { @@ -77,7 +77,7 @@ public class Filter { StringBuilder sb = new StringBuilder(); - List<QueryStatement> notMatchQueries = new ArrayList<QueryStatement>(); + List<QueryStatement> notMatchQueries = new ArrayList<>(); sb.append("{"); sb.append("\"bool\": {"); @@ -123,7 +123,6 @@ public class Filter { matchQueriesCount = 0; for (QueryStatement query : any) { - // if(!firstQuery.compareAndSet(true, false)) { if (matchQueriesCount > 0) { sb.append(", "); } @@ -137,11 +136,9 @@ public class Filter { } sb.append("],"); - // firstQuery.set(true); notMatchQueriesCount = 0; sb.append("\"must_not\": ["); for (QueryStatement query : notMatchQueries) { - // if(!firstQuery.compareAndSet(true, false)) { if (notMatchQueriesCount > 0) { sb.append(", "); } diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java index 9f37856..d14f8df 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/searchapi/SearchStatement.java @@ -33,7 +33,7 @@ import org.radeox.util.logging.Logger; * The expected JSON structure to represent a search statement is as follows: * * <p> - * + * * <pre> * { * "results-start": int, - Optional: index of starting point in result set. @@ -152,11 +152,10 @@ public class SearchStatement { * @return - ElasticSearch syntax string. */ public String toElasticSearch() { - StringBuilder sb = new StringBuilder(); - List<QueryStatement> notMatchQueries = new ArrayList<QueryStatement>(); - List<QueryStatement> mustQueries = new ArrayList<QueryStatement>(); - List<QueryStatement> shouldQueries = new ArrayList<QueryStatement>(); + List<QueryStatement> notMatchQueries = new ArrayList<>(); + List<QueryStatement> mustQueries = new ArrayList<>(); + List<QueryStatement> shouldQueries = new ArrayList<>(); createQueryLists(queries, mustQueries, shouldQueries, notMatchQueries); diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java index 46536ab..a35062b 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/service/SearchService.java @@ -21,6 +21,7 @@ package org.onap.aai.sa.searchdbabstraction.service; import java.io.FileInputStream; +import java.io.IOException; import java.util.Properties; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; @@ -31,23 +32,23 @@ import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; import org.springframework.beans.factory.annotation.Autowired; public class SearchService { - static Logger logger = LoggerFactory.getInstance().getLogger(SearchService.class.getName()); + static Logger logger = LoggerFactory.getInstance().getLogger(SearchService.class.getName()); - @Autowired - private ElasticSearchConfig esConfig; + @Autowired + private ElasticSearchConfig esConfig; - public SearchService() { - try { - start(); - } catch (Exception e) { - logger.error(SearchDbMsgs.STARTUP_EXCEPTION, e.getLocalizedMessage()); + public SearchService() { + try { + start(); + } catch (Exception e) { + logger.error(SearchDbMsgs.STARTUP_EXCEPTION, e.getLocalizedMessage()); + } } - } - protected void start() throws Exception { - Properties configProperties = new Properties(); - configProperties.load(new FileInputStream(SearchDbConstants.ES_CONFIG_FILE)); + protected void start() throws IOException { + Properties configProperties = new Properties(); + configProperties.load(new FileInputStream(SearchDbConstants.ES_CONFIG_FILE)); new ElasticSearchHttpController(esConfig); - logger.info(SearchDbMsgs.SERVICE_STARTED); - } + logger.info(SearchDbMsgs.SERVICE_STARTED); + } } diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java index df91cca..1627ae2 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/util/DocumentSchemaUtil.java @@ -32,24 +32,21 @@ import org.onap.aai.sa.rest.DocumentSchema; public class DocumentSchemaUtil { - private DocumentSchemaUtil() { // Do not instantiate - } - private static String dynamicCustomMapping = null; private static final String DYNAMIC_CUSTOM_TEMPALTE_FILE = System.getProperty("CONFIG_HOME") + File.separator + "dynamic-custom-template.json"; - public static String generateDocumentMappings(String documentSchema) throws IOException { + private DocumentSchemaUtil() { // Do not instantiate + } + public static 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); - return generateDocumentMappings(schema); } public static String generateDocumentMappings(DocumentSchema schema) throws IOException { - // Adding dynamic template to add fielddata=true to dynamic fields of type "string" // in order to avoid aggregation queries breaking in ESv6.1.2 if (dynamicCustomMapping == null) { diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java index 0819d38..561f604 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/util/SearchDbConstants.java @@ -22,9 +22,6 @@ package org.onap.aai.sa.searchdbabstraction.util; public class SearchDbConstants { - private SearchDbConstants() { // Do not instantiate - } - public static final String SDB_FILESEP = (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); public static final String SDB_BUNDLECONFIG_NAME = @@ -48,4 +45,8 @@ public class SearchDbConstants { // Logging related public static final String SDB_SERVICE_NAME = "SearchDataService"; + + private SearchDbConstants() { // Do not instantiate + } + } |