2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright (C) 2020 Nokia. All rights reserved.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.dcae.restapi;
24 import com.att.nsa.clock.SaClock;
25 import com.att.nsa.logging.LoggingContext;
26 import com.att.nsa.logging.log4j.EcompFields;
27 import org.json.JSONObject;
28 import org.onap.dcae.ApplicationSettings;
29 import org.onap.dcae.common.EventSender;
30 import org.onap.dcae.common.EventUpdater;
31 import org.onap.dcae.common.HeaderUtils;
32 import org.onap.dcae.common.validator.GeneralEventValidator;
33 import org.onap.dcae.common.validator.StndDefinedDataValidator;
34 import org.onap.dcae.common.VESLogger;
35 import org.onap.dcae.common.model.StndDefinedNamespaceParameterHasEmptyValueException;
36 import org.onap.dcae.common.model.StndDefinedNamespaceParameterNotDefinedException;
37 import org.onap.dcae.common.model.VesEvent;
38 import org.onap.dcaegen2.services.sdk.standardization.header.CustomHeaderUtils;
39 import org.slf4j.Logger;
40 import org.springframework.beans.factory.annotation.Autowired;
41 import org.springframework.beans.factory.annotation.Qualifier;
42 import org.springframework.http.MediaType;
43 import org.springframework.http.ResponseEntity;
44 import org.springframework.web.bind.annotation.PathVariable;
45 import org.springframework.web.bind.annotation.PostMapping;
46 import org.springframework.web.bind.annotation.RequestBody;
47 import org.springframework.web.bind.annotation.RestController;
49 import javax.servlet.http.HttpServletRequest;
50 import java.util.List;
51 import java.util.UUID;
53 import static org.springframework.http.ResponseEntity.accepted;
54 import static org.springframework.http.ResponseEntity.badRequest;
57 public class VesRestController {
59 private static final String VES_EVENT_MESSAGE = "Received a VESEvent '%s', marked with unique identifier '%s', on api version '%s', from host: '%s'";
60 private static final String EVENT_LIST = "eventList";
61 private static final String EVENT = "event";
62 private final ApplicationSettings settings;
63 private final Logger requestLogger;
64 private final Logger logger;
65 private EventSender eventSender;
66 private final HeaderUtils headerUtils;
67 private final GeneralEventValidator generalEventValidator;
68 private final EventUpdater eventUpdater;
69 private final StndDefinedDataValidator stndDefinedValidator;
72 VesRestController(ApplicationSettings settings, @Qualifier("incomingRequestsLogger") Logger incomingRequestsLogger,
73 @Qualifier("errorLog") Logger logger, @Qualifier("eventSender") EventSender eventSender, HeaderUtils headerUtils,
74 StndDefinedDataValidator stndDefinedDataValidator) {
75 this.settings = settings;
76 this.requestLogger = incomingRequestsLogger;
78 this.eventSender = eventSender;
79 this.headerUtils = headerUtils;
80 this.stndDefinedValidator = stndDefinedDataValidator;
81 this.generalEventValidator = new GeneralEventValidator(settings);
82 this.eventUpdater = new EventUpdater(settings);
85 @PostMapping(value = {"/eventListener/{version}"}, consumes = "application/json")
86 ResponseEntity<String> event(@RequestBody String event, @PathVariable String version, HttpServletRequest request) {
87 if (settings.isVersionSupported(version)) {
88 return process(event, version, request, EVENT);
90 return badRequest().contentType(MediaType.APPLICATION_JSON).body(String.format("API version %s is not supported", version));
93 @PostMapping(value = {"/eventListener/{version}/eventBatch"}, consumes = "application/json")
94 ResponseEntity<String> events(@RequestBody String events, @PathVariable String version, HttpServletRequest request) {
95 if (settings.isVersionSupported(version)) {
96 return process(events, version, request, EVENT_LIST);
98 return badRequest().contentType(MediaType.APPLICATION_JSON).body(String.format("API version %s is not supported", version));
101 private ResponseEntity<String> process(String payload, String version, HttpServletRequest request, String type) {
102 CustomHeaderUtils headerUtils = createHeaderUtils(version, request);
103 if (headerUtils.isOkCustomHeaders()) {
104 final VesEvent vesEvent = new VesEvent(new JSONObject(payload));
105 final String requestURI = request.getRequestURI();
106 return handleEvent(vesEvent, version, type, headerUtils, requestURI);
108 return badRequest().body(ApiException.INVALID_CUSTOM_HEADER.toString());
111 private ResponseEntity<String> handleEvent(VesEvent vesEvent, String version, String type, CustomHeaderUtils headerUtils, String requestURI) {
113 generalEventValidator.validate(vesEvent, type, version);
114 List<VesEvent> vesEvents = transformEvent(vesEvent, type, version, requestURI);
115 executeStndDefinedValidation(vesEvents);
116 eventSender.send(vesEvents);
117 } catch (EventValidatorException e) {
118 logger.error(e.getMessage());
119 return ResponseEntity.status(e.getApiException().httpStatusCode)
120 .body(e.getApiException().toJSON().toString());
121 } catch (StndDefinedNamespaceParameterNotDefinedException e) {
122 return ResponseEntity.status(ApiException.MISSING_NAMESPACE_PARAMETER.httpStatusCode)
123 .body(ApiException.MISSING_NAMESPACE_PARAMETER.toJSON().toString());
124 } catch (StndDefinedNamespaceParameterHasEmptyValueException e) {
125 return ResponseEntity.status(ApiException.MISSING_NAMESPACE_PARAMETER.httpStatusCode)
126 .body(ApiException.EMPTY_NAMESPACE_PARAMETER.toJSON().toString());
129 // TODO call service and return status, replace CambriaClient, split event to single object and list of them
130 return accepted().headers(this.headerUtils.fillHeaders(headerUtils.getRspCustomHeader()))
131 .contentType(MediaType.APPLICATION_JSON).body("Accepted");
134 private void executeStndDefinedValidation(List<VesEvent> vesEvents) {
135 if (settings.getExternalSchemaValidationCheckflag()) {
136 vesEvents.forEach(stndDefinedValidator::validate);
140 private CustomHeaderUtils createHeaderUtils(String version, HttpServletRequest request) {
141 return new CustomHeaderUtils(version.toLowerCase().replace("v", ""),
142 headerUtils.extractHeaders(request),
143 settings.getApiVersionDescriptionFilepath(),
144 headerUtils.getRestApiIdentify(request.getRequestURI()));
148 private List<VesEvent> transformEvent(VesEvent vesEvent, String type, String version, String requestURI) {
149 return this.eventUpdater.convert(vesEvent, version, generateUUID(vesEvent, version, requestURI), type);
152 private UUID generateUUID(VesEvent vesEvent, String version, String uri) {
153 UUID uuid = UUID.randomUUID();
154 setUpECOMPLoggingForRequest(uuid);
155 requestLogger.info(String.format(VES_EVENT_MESSAGE, vesEvent.asJsonObject(), uuid, version, uri));
159 private static void setUpECOMPLoggingForRequest(UUID uuid) {
160 LoggingContext localLC = VESLogger.getLoggingContextForThread(uuid);
161 localLC.put(EcompFields.kBeginTimestampMs, SaClock.now());