Add collaboration feature
[sdc.git] / openecomp-be / api / openecomp-sdc-rest-webapp / action-library-rest / action-library-rest-services / src / main / java / org / openecomp / sdcrests / action / rest / services / ActionsImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdcrests.action.rest.services;
22
23 import org.apache.commons.codec.digest.DigestUtils;
24 import org.apache.commons.lang3.StringUtils;
25 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
26 import org.openecomp.core.utilities.file.FileUtils;
27 import org.openecomp.core.utilities.json.JsonUtil;
28 import org.openecomp.sdc.action.ActionConstants;
29 import org.openecomp.sdc.action.ActionManager;
30 import org.openecomp.sdc.action.errors.ActionErrorConstants;
31 import org.openecomp.sdc.action.errors.ActionException;
32 import org.openecomp.sdc.action.logging.CategoryLogLevel;
33 import org.openecomp.sdc.action.logging.StatusCode;
34 import org.openecomp.sdc.action.types.Action;
35 import org.openecomp.sdc.action.types.ActionArtifact;
36 import org.openecomp.sdc.action.types.ActionArtifactProtection;
37 import org.openecomp.sdc.action.types.ActionRequest;
38 import org.openecomp.sdc.action.types.OpenEcompComponent;
39 import org.openecomp.sdc.logging.api.Logger;
40 import org.openecomp.sdc.logging.api.LoggerFactory;
41 import org.openecomp.sdcrests.action.rest.Actions;
42 import org.openecomp.sdcrests.action.rest.mapping.MapActionToActionResponseDto;
43 import org.openecomp.sdcrests.action.types.ActionResponseDto;
44 import org.openecomp.sdcrests.action.types.ActionVersionDto;
45 import org.openecomp.sdcrests.action.types.ListResponseWrapper;
46 import org.openecomp.sdcrests.wrappers.StringWrapperResponse;
47 import org.slf4j.MDC;
48 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.context.annotation.Scope;
50 import org.springframework.stereotype.Service;
51 import org.springframework.validation.annotation.Validated;
52
53 import javax.inject.Named;
54 import javax.servlet.http.HttpServletRequest;
55 import javax.ws.rs.core.Response;
56 import java.io.File;
57 import java.io.FileOutputStream;
58 import java.io.IOException;
59 import java.io.InputStream;
60 import java.util.ArrayList;
61 import java.util.HashMap;
62 import java.util.LinkedHashMap;
63 import java.util.List;
64 import java.util.Map;
65
66 import static org.openecomp.sdc.action.ActionConstants.ACTION_REQUEST_PARAM_NAME;
67 import static org.openecomp.sdc.action.ActionConstants.ACTION_REQUEST_PARAM_SUPPORTED_MODELS;
68 import static org.openecomp.sdc.action.ActionConstants.ARTIFACT_FILE;
69 import static org.openecomp.sdc.action.ActionConstants.ARTIFACT_NAME;
70 import static org.openecomp.sdc.action.ActionConstants.BE_FQDN;
71 import static org.openecomp.sdc.action.ActionConstants.CATEGORY_LOG_LEVEL;
72 import static org.openecomp.sdc.action.ActionConstants.CLIENT_IP;
73 import static org.openecomp.sdc.action.ActionConstants.ERROR_DESCRIPTION;
74 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_CATEGORY;
75 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_MODEL;
76 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_NAME;
77 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_NONE;
78 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_OPEN_ECOMP_COMPONENT;
79 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_VENDOR;
80 import static org.openecomp.sdc.action.ActionConstants.INSTANCE_UUID;
81 import static org.openecomp.sdc.action.ActionConstants.LOCAL_ADDR;
82 import static org.openecomp.sdc.action.ActionConstants.MAX_ACTION_ARTIFACT_SIZE;
83 import static org.openecomp.sdc.action.ActionConstants.MDC_ASDC_INSTANCE_UUID;
84 import static org.openecomp.sdc.action.ActionConstants.PARTNER_NAME;
85 import static org.openecomp.sdc.action.ActionConstants.REMOTE_HOST;
86 import static org.openecomp.sdc.action.ActionConstants.REQUEST_EMPTY_BODY;
87 import static org.openecomp.sdc.action.ActionConstants.REQUEST_ID;
88 import static org.openecomp.sdc.action.ActionConstants.REQUEST_TYPE_CREATE_ACTION;
89 import static org.openecomp.sdc.action.ActionConstants.REQUEST_TYPE_UPDATE_ACTION;
90 import static org.openecomp.sdc.action.ActionConstants.REQUEST_TYPE_VERSION_ACTION;
91 import static org.openecomp.sdc.action.ActionConstants.SERVICE_INSTANCE_ID;
92 import static org.openecomp.sdc.action.ActionConstants.SERVICE_METRIC_BEGIN_TIMESTAMP;
93 import static org.openecomp.sdc.action.ActionConstants.SERVICE_NAME;
94 import static org.openecomp.sdc.action.ActionConstants.STATUS;
95 import static org.openecomp.sdc.action.ActionConstants.STATUS_CODE;
96 import static org.openecomp.sdc.action.ActionConstants.SUPPORTED_COMPONENTS_ID;
97 import static org.openecomp.sdc.action.ActionConstants.SUPPORTED_MODELS_VERSION_ID;
98 import static org.openecomp.sdc.action.ActionConstants.TARGET_ENTITY;
99 import static org.openecomp.sdc.action.ActionConstants.TARGET_ENTITY_API;
100 import static org.openecomp.sdc.action.ActionConstants.TARGET_SERVICE_NAME;
101 import static org.openecomp.sdc.action.ActionConstants.TIMESTAMP;
102 import static org.openecomp.sdc.action.ActionConstants.UPDATED_BY;
103 import static org.openecomp.sdc.action.ActionConstants.X_OPEN_ECOMP_INSTANCE_ID_HEADER_PARAM;
104 import static org.openecomp.sdc.action.ActionConstants.X_OPEN_ECOMP_REQUEST_ID_HEADER_PARAM;
105 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_CHECKSUM_ERROR_CODE;
106 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_INVALID_NAME;
107 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_INVALID_NAME_CODE;
108 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_INVALID_PROTECTION_CODE;
109 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_READ_FILE_ERROR;
110 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_TOO_BIG_ERROR;
111 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_TOO_BIG_ERROR_CODE;
112 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG;
113 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_NOT_EXIST;
114 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_NOT_EXIST_CODE;
115 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_FILTER_MULTIPLE_QUERY_PARAM_NOT_SUPPORTED;
116 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INTERNAL_SERVER_ERR_CODE;
117 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INVALID_INSTANCE_ID_CODE;
118 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INVALID_PARAM_CODE;
119 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INVALID_REQUEST_BODY_CODE;
120 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INVALID_REQUEST_ID_CODE;
121 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INVALID_SEARCH_CRITERIA;
122 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_MULT_SEARCH_CRITERIA;
123 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_ARTIFACT_CHECKSUM_ERROR;
124 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_ARTIFACT_INVALID_PROTECTION_VALUE;
125 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_ARTIFACT_OPERATION_ALLOWED;
126 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_BODY_EMPTY;
127 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_CONTENT_TYPE_INVALID;
128 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_FILTER_PARAM_INVALID;
129 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_INVALID_GENERIC_CODE;
130 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_INVALID_NAME;
131 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_MISSING_MANDATORY_PARAM;
132 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_OPEN_ECOMP_INSTANCE_ID_INVALID;
133 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUEST_OPEN_ECOMP_REQUEST_ID_INVALID;
134 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UNSUPPORTED_OPERATION;
135 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_CODE;
136 import static org.openecomp.sdc.action.util.ActionUtil.actionErrorLogProcessor;
137 import static org.openecomp.sdc.action.util.ActionUtil.actionLogPostProcessor;
138 import static org.openecomp.sdc.action.util.ActionUtil.getUtcDateStringFromTimestamp;
139
140 /**
141  * Implements various CRUD API that can be performed on Action
142  */
143 @SuppressWarnings("ALL")
144 @Named
145 @Service("actions")
146 @Scope(value = "prototype")
147 @Validated
148 public class ActionsImpl implements Actions {
149
150   private static final Logger LOGGER = (Logger) LoggerFactory.getLogger(ActionsImpl.class);
151   @Autowired
152   private ActionManager actionManager;
153   private String whitespaceCharacters = "\\s"       /* dummy empty string for homogeneity */
154       + "\\u0009" // CHARACTER TABULATION
155       + "\\u000A" // LINE FEED (LF)
156       + "\\u000B" // LINE TABULATION
157       + "\\u000C" // FORM FEED (FF)
158       + "\\u000D" // CARRIAGE RETURN (CR)
159       + "\\u0020" // SPACE
160       + "\\u0085" // NEXT LINE (NEL)
161       + "\\u00A0" // NO-BREAK SPACE
162       + "\\u1680" // OGHAM SPACE MARK
163       + "\\u180E" // MONGOLIAN VOWEL SEPARATOR
164       + "\\u2000" // EN QUAD
165       + "\\u2001" // EM QUAD
166       + "\\u2002" // EN SPACE
167       + "\\u2003" // EM SPACE
168       + "\\u2004" // THREE-PER-EM SPACE
169       + "\\u2005" // FOUR-PER-EM SPACE
170       + "\\u2006" // SIX-PER-EM SPACE
171       + "\\u2007" // FIGURE SPACE
172       + "\\u2008" // PUNCTUATION SPACE
173       + "\\u2009" // THIN SPACE
174       + "\\u200A" // HAIR SPACE
175       + "\\u2028" // LINE SEPARATOR
176       + "\\u2029" // PARAGRAPH SEPARATOR
177       + "\\u202F" // NARROW NO-BREAK SPACE
178       + "\\u205F" // MEDIUM MATHEMATICAL SPACE
179       + "\\u3000" // IDEOGRAPHIC SPACE
180       ;
181   private String invalidFilenameChars = "#<>$+%!`&*'|{}?\"=/:@\\\\";
182   private String whitespaceRegex = ".*[" + whitespaceCharacters + "].*";
183   private String invalidFilenameRegex = ".*[" + whitespaceCharacters + invalidFilenameChars + "].*";
184
185   /**
186    * Calculate the checksum for a given input
187    *
188    * @param input Byte array for which the checksum has to be calculated
189    * @return Calculated checksum of the input byte array
190    */
191   private static String calculateCheckSum(byte[] input) {
192     String checksum = null;
193     if (input != null) {
194       checksum = DigestUtils.md5Hex(input);
195     }
196     return checksum;
197   }
198
199   @Override
200   public Response getActionsByActionInvariantUuId(String invariantID, String actionUUID,
201                                                   HttpServletRequest servletRequest) {
202     ListResponseWrapper responseList = new ListResponseWrapper();
203
204     try {
205       LOGGER.debug(" entering getActionsByActionInvariantUuId ");
206       initializeRequestMDC(servletRequest, invariantID, ActionRequest.GET_ACTIONS_INVARIANT_ID);
207       MDC.put(SERVICE_INSTANCE_ID, invariantID);
208
209       if (StringUtils.isEmpty(servletRequest.getQueryString())) {
210         responseList = getActionsByInvId(servletRequest, invariantID);
211       } else {
212         Response response = getActionByUUID(servletRequest, invariantID, actionUUID);
213         actionLogPostProcessor(StatusCode.COMPLETE, true);
214         return response;
215       }
216     } catch (ActionException exception) {
217       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
218       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
219       LOGGER.error("");
220       throw exception;
221     } catch (Exception exception) {
222       actionLogPostProcessor(StatusCode.ERROR, true);
223       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
224           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
225       LOGGER.error("");
226       throw exception;
227     } finally {
228       finalAuditMetricsLogProcessor(ActionRequest.GET_ACTIONS_INVARIANT_ID.name());
229     }
230
231     LOGGER.debug(" exit getActionsByActionInvariantUuId ");
232     actionLogPostProcessor(StatusCode.COMPLETE, true);
233     return Response.ok(responseList).build();
234   }
235
236   private ListResponseWrapper getActionsByInvId(HttpServletRequest servletRequest,
237                                                 String invariantID) {
238     LOGGER.debug(" entering getActionsByInvId with invariantID= " + invariantID);
239     ListResponseWrapper responseList = new ListResponseWrapper();
240     if (StringUtils.isEmpty(servletRequest.getQueryString())) {
241       Map<String, String> errorMap = validateRequestHeaders(servletRequest);
242       Map<String, String> queryParamErrors = validateQueryParam(invariantID);
243       errorMap.putAll(queryParamErrors);
244       if (errorMap.isEmpty()) {
245         List<Action> actions = actionManager.getActionsByActionInvariantUuId(invariantID);
246         List<ActionResponseDto> versionList = new ArrayList<>();
247         for (Action action : actions) {
248           ActionResponseDto responseDTO = createResponseDTO(action);
249           versionList.add(responseDTO);
250         }
251         responseList.setVersions(versionList);
252         responseList.setActionList(null);
253
254       } else {
255         checkAndThrowError(errorMap);
256       }
257     }
258     LOGGER.debug(" exit getActionsByInvId with invariantID= " + invariantID);
259     return responseList;
260   }
261
262   private Response getActionByUUID(HttpServletRequest servletRequest, String invariantID,
263                                    String actionUUID) throws ActionException {
264     int noOfFilterParams = 0;
265     Response response = null;
266     LOGGER.debug(" entering getActionByUUID with invariantID= " + invariantID + " and actionUUID= " +
267         actionUUID);
268     if (!StringUtils.isEmpty(actionUUID)) {
269       noOfFilterParams++;
270       response = getActionsByUniqueID(actionUUID, servletRequest, invariantID);
271     }
272     if (noOfFilterParams == 0) {
273       throw new ActionException(ACTION_INVALID_SEARCH_CRITERIA,
274           ACTION_REQUEST_FILTER_PARAM_INVALID);
275     }
276
277     LOGGER.debug(" exit getActionByUUID with invariantID= " + invariantID + " and actionUUID= " +
278         actionUUID);
279     return response;
280   }
281
282   @Override
283   public Response getOpenEcompComponents(HttpServletRequest servletRequest) {
284     try {
285       LOGGER.debug(" entering getEcompComponents ");
286       initializeRequestMDC(servletRequest, "", ActionRequest.GET_OPEN_ECOMP_COMPONENTS);
287       //Validate request syntax before passing to the manager
288       Map<String, String> errorMap = validateRequestHeaders(servletRequest);
289       checkAndThrowError(errorMap);
290       ListResponseWrapper response = new ListResponseWrapper();
291       List<OpenEcompComponent> openEcompComponents = actionManager.getOpenEcompComponents();
292       response.setActionList(null);
293       response.setComponentList(openEcompComponents);
294       LOGGER.debug(" exit getEcompComponents ");
295       actionLogPostProcessor(StatusCode.COMPLETE, true);
296       return Response.ok(response).build();
297     } catch (ActionException exception) {
298       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
299       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
300       LOGGER.error("");
301       throw exception;
302     } catch (Exception exception) {
303       actionLogPostProcessor(StatusCode.ERROR, true);
304       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
305           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
306       LOGGER.error("");
307       throw exception;
308     } finally {
309       finalAuditMetricsLogProcessor(ActionRequest.GET_OPEN_ECOMP_COMPONENTS.name());
310     }
311   }
312
313   @Override
314   public Response getFilteredActions(String vendor, String category, String name, String modelID,
315                                      String componentID, HttpServletRequest servletRequest) {
316     try {
317       LOGGER.debug(" entering getFilteredActions ");
318       Response response;
319       initializeRequestMDC(servletRequest, "", ActionRequest.GET_FILTERED_ACTIONS);
320       int noOfFilterParams = getNoOfFilterParams(vendor, category, name, modelID, componentID);
321       if (StringUtils.isEmpty(servletRequest.getQueryString())) {
322         response = getAllActions(servletRequest);
323         LOGGER.debug(" exit getFilteredActions ");
324         actionLogPostProcessor(StatusCode.COMPLETE, true);
325         return response;
326       }
327       validateNoOfFilterParamsExactly1(noOfFilterParams);
328       if (!StringUtils.isEmpty(vendor)) {
329         response = getActionsByVendor(vendor, servletRequest);
330       } else if (!StringUtils.isEmpty(category)) {
331         response = getActionsByCategory(category, servletRequest);
332       } else if (!StringUtils.isEmpty(name)) {
333         response = getActionsByName(name, servletRequest);
334       } else if (!StringUtils.isEmpty(modelID)) {
335         response = getActionsByModel(modelID, servletRequest);
336       } else if (!StringUtils.isEmpty(componentID)) {
337         response = getActionsByOpenEcompComponents(componentID, servletRequest);
338       } else {
339         throw new ActionException(ACTION_INVALID_PARAM_CODE, ACTION_REQUEST_FILTER_PARAM_INVALID);
340       }
341
342       LOGGER.debug(" exit getFilteredActions ");
343       actionLogPostProcessor(StatusCode.COMPLETE, true);
344       return response;
345     } catch (ActionException exception) {
346       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
347       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
348       LOGGER.error("");
349       throw exception;
350     } catch (Exception exception) {
351       actionLogPostProcessor(StatusCode.ERROR, true);
352       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
353           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
354       LOGGER.error("");
355       throw exception;
356     } finally {
357       finalAuditMetricsLogProcessor(ActionRequest.GET_FILTERED_ACTIONS.name());
358     }
359   }
360
361   private void validateNoOfFilterParamsExactly1(int noOfFilterParams) {
362     if (noOfFilterParams > 1) {
363       throw new ActionException(ACTION_MULT_SEARCH_CRITERIA,
364           ACTION_FILTER_MULTIPLE_QUERY_PARAM_NOT_SUPPORTED);
365     }
366     if (noOfFilterParams == 0) {
367       throw new ActionException(ACTION_INVALID_SEARCH_CRITERIA,
368           ACTION_REQUEST_FILTER_PARAM_INVALID);
369     }
370   }
371
372   private int getNoOfFilterParams(String vendor, String category, String name, String modelID, String componentID) {
373     int noOfFilterParams = 0;
374     if (!StringUtils.isEmpty(vendor)) {
375       noOfFilterParams++;
376     }
377     if (!StringUtils.isEmpty(category)) {
378       noOfFilterParams++;
379     }
380     if (!StringUtils.isEmpty(name)) {
381       noOfFilterParams++;
382     }
383     if (!StringUtils.isEmpty(modelID)) {
384       noOfFilterParams++;
385     }
386     if (!StringUtils.isEmpty(componentID)) {
387       noOfFilterParams++;
388     }
389     return noOfFilterParams;
390   }
391
392   @Override
393   public Response createAction(String requestJSON, HttpServletRequest servletRequest) {
394     try {
395       initializeRequestMDC(servletRequest, null, ActionRequest.CREATE_ACTION);
396       LOGGER.debug(" entering API createAction ");
397       Map<String, String> errorMap = validateRequestHeaders(servletRequest);
398       Map<String, String> requestBodyErrors =
399           validateRequestBody(REQUEST_TYPE_CREATE_ACTION, requestJSON);
400       errorMap.putAll(requestBodyErrors);
401       ActionResponseDto actionResponseDTO = new ActionResponseDto();
402       if (errorMap.isEmpty()) {
403         String user = servletRequest.getRemoteUser();
404         Action action = JsonUtil.json2Object(requestJSON, Action.class);
405         action.setData(requestJSON);
406         Action responseAction = actionManager.createAction(action, user);
407         MDC.put(SERVICE_INSTANCE_ID, responseAction.getActionInvariantUuId());
408         new MapActionToActionResponseDto().doMapping(responseAction, actionResponseDTO);
409       } else {
410         checkAndThrowError(errorMap);
411       }
412       actionLogPostProcessor(StatusCode.COMPLETE, true);
413       LOGGER.debug(" exit API createAction with ActionInvariantUUID= " + MDC.get(SERVICE_INSTANCE_ID));
414       return Response.ok(actionResponseDTO).build();
415     } catch (ActionException exception) {
416       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
417       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
418       LOGGER.error("");
419       throw exception;
420     } catch (Exception exception) {
421       actionLogPostProcessor(StatusCode.ERROR, true);
422       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
423           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
424       LOGGER.error(exception.getMessage());
425       throw exception;
426     } finally {
427       finalAuditMetricsLogProcessor(ActionRequest.CREATE_ACTION.name());
428     }
429
430   }
431
432   @Override
433   public Response updateAction(String invariantUUID, String requestJSON,
434                                HttpServletRequest servletRequest) {
435     ActionResponseDto actionResponseDTO = null;
436     try {
437       initializeRequestMDC(servletRequest, invariantUUID, ActionRequest.UPDATE_ACTION);
438       Map<String, String> errorMap = validateRequestHeaders(servletRequest);
439       Map<String, String> requestBodyErrors =
440           validateRequestBody(REQUEST_TYPE_UPDATE_ACTION, requestJSON);
441       errorMap.putAll(requestBodyErrors);
442       actionResponseDTO = new ActionResponseDto();
443       if (errorMap.isEmpty()) {
444         String user = servletRequest.getRemoteUser();
445         Action action = JsonUtil.json2Object(requestJSON, Action.class);
446         action.setActionInvariantUuId(invariantUUID);
447         action.setData(requestJSON);
448         Action updatedAction = actionManager.updateAction(action, user);
449         new MapActionToActionResponseDto().doMapping(updatedAction, actionResponseDTO);
450       } else {
451         checkAndThrowError(errorMap);
452       }
453       actionLogPostProcessor(StatusCode.COMPLETE, true);
454     } catch (ActionException exception) {
455       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
456       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
457       LOGGER.error("");
458       throw exception;
459     } catch (Exception exception) {
460       actionLogPostProcessor(StatusCode.ERROR, true);
461       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
462           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
463       LOGGER.error(exception.getMessage());
464       throw exception;
465     } finally {
466       finalAuditMetricsLogProcessor(ActionRequest.UPDATE_ACTION.name());
467     }
468
469     return Response.ok(actionResponseDTO).build();
470   }
471
472   @Override
473   public Response deleteAction(String actionInvariantUUID, HttpServletRequest servletRequest) {
474     try {
475       initializeRequestMDC(servletRequest, actionInvariantUUID, ActionRequest.DELETE_ACTION);
476       Map<String, String> errorMap = validateRequestHeaders(servletRequest);
477       if (errorMap.isEmpty()) {
478         String user = servletRequest.getRemoteUser();
479         actionManager.deleteAction(actionInvariantUUID, user);
480       } else {
481         checkAndThrowError(errorMap);
482       }
483
484       actionLogPostProcessor(StatusCode.COMPLETE, true);
485       return Response.ok(new ActionResponseDto()).build();
486     } catch (ActionException exception) {
487       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
488       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
489       LOGGER.error(MDC.get(ERROR_DESCRIPTION));
490       throw exception;
491     } catch (Exception exception) {
492       actionLogPostProcessor(StatusCode.ERROR, true);
493       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
494           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
495       LOGGER.error(exception.getMessage());
496       throw exception;
497     } finally {
498       finalAuditMetricsLogProcessor(ActionRequest.DELETE_ACTION.name());
499     }
500   }
501
502   @Override
503   public Response actOnAction(String invariantUUID, String requestJSON,
504                               HttpServletRequest servletRequest) {
505     Response response = null;
506     try {
507       initializeRequestMDC(servletRequest, invariantUUID, ActionRequest.ACTION_VERSIONING);
508       LOGGER.debug("entering actOnAction with invariantUUID= " + invariantUUID + " and requestJSON= " +
509           requestJSON);
510       Map<String, String> errorMap = validateRequestHeaders(servletRequest);
511       Map<String, String> requestBodyErrors =
512           validateRequestBody(REQUEST_TYPE_VERSION_ACTION, requestJSON);
513       errorMap.putAll(requestBodyErrors);
514
515       ActionVersionDto versionDTO = JsonUtil.json2Object(requestJSON, ActionVersionDto.class);
516       checkAndThrowError(errorMap);
517
518       String status = versionDTO.getStatus();
519       Action action = new Action();
520       String user = servletRequest.getRemoteUser();
521       switch (status) {
522         case "Checkout":
523           action = actionManager.checkout(invariantUUID, user);
524           break;
525         case "Undo_Checkout":
526           actionManager.undoCheckout(invariantUUID, user);
527           StringWrapperResponse responseText = new StringWrapperResponse();
528           responseText.setValue(ActionConstants.UNDO_CHECKOUT_RESPONSE_TEXT);
529           response = Response
530               .status(Response.Status.OK)
531               .entity(responseText)
532               .build();
533           return response;
534         case "Checkin":
535           action = actionManager.checkin(invariantUUID, user);
536           break;
537         case "Submit":
538           action = actionManager.submit(invariantUUID, user);
539           break;
540         default:
541           throw new ActionException(ACTION_INVALID_PARAM_CODE,
542               String.format(ACTION_UNSUPPORTED_OPERATION, status));
543       }
544
545       ActionResponseDto actionResponseDTO = new ActionResponseDto();
546       new MapActionToActionResponseDto().doMapping(action, actionResponseDTO);
547       response = Response.ok(actionResponseDTO).build();
548       actionLogPostProcessor(StatusCode.COMPLETE, true);
549     } catch (ActionException exception) {
550       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
551       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
552       LOGGER.error(MDC.get(ERROR_DESCRIPTION));
553       throw exception;
554     } catch (Exception exception) {
555       actionLogPostProcessor(StatusCode.ERROR, true);
556       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
557           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
558       LOGGER.error(exception.getMessage());
559       throw exception;
560     } finally {
561       finalAuditMetricsLogProcessor(ActionRequest.ACTION_VERSIONING.name());
562       LOGGER.debug("exit actOnAction with invariantUUID= " + invariantUUID + " and requestJSON= " +
563           requestJSON);
564     }
565     return response;
566   }
567
568   @Override
569   public Response uploadArtifact(String actionInvariantUUID,
570                                  String artifactName,
571                                  String artifactLabel,
572                                  String artifactCategory,
573                                  String artifactDescription,
574                                  String artifactProtection,
575                                  String checksum,
576                                  Attachment artifactToUpload,
577                                  HttpServletRequest servletRequest) {
578     Response response = null;
579     try {
580       initializeRequestMDC(servletRequest, actionInvariantUUID, ActionRequest.UPLOAD_ARTIFACT);
581       LOGGER.debug("entering uploadArtifact with actionInvariantUuId= " + actionInvariantUUID +
582           "artifactName= " + artifactName);
583       response =
584           uploadArtifactInternal(actionInvariantUUID, artifactName, artifactLabel, artifactCategory,
585               artifactDescription, artifactProtection, checksum, artifactToUpload, servletRequest);
586       actionLogPostProcessor(StatusCode.COMPLETE, true);
587       LOGGER.debug("exiting uploadArtifact with actionInvariantUuId= " + actionInvariantUUID +
588           "artifactName= " + artifactName);
589     } catch (ActionException exception) {
590       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
591       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
592       LOGGER.error(MDC.get(ERROR_DESCRIPTION));
593       throw exception;
594     } catch (Exception exception) {
595       actionLogPostProcessor(StatusCode.ERROR, true);
596       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
597           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
598       LOGGER.error(exception.getMessage());
599       throw exception;
600     } finally {
601       finalAuditMetricsLogProcessor(ActionRequest.UPLOAD_ARTIFACT.name());
602     }
603     LOGGER.debug("exiting uploadArtifact with actionInvariantUuId= " + actionInvariantUUID +
604         "artifactName= " + artifactName);
605     return response;
606   }
607
608   private Response uploadArtifactInternal(String actionInvariantUUID, String artifactName,
609                                           String artifactLabel, String artifactCategory,
610                                           String artifactDescription, String artifactProtection,
611                                           String checksum, Attachment artifactToUpload,
612                                           HttpServletRequest servletRequest) {
613     ListResponseWrapper responseList = null;
614     byte[] payload = null;
615     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
616     //Artifact name empty validation
617     if (StringUtils.isEmpty(artifactName)) {
618       errorMap.put(ACTION_REQUEST_INVALID_GENERIC_CODE,
619           ACTION_REQUEST_MISSING_MANDATORY_PARAM + ARTIFACT_NAME);
620     } else {
621       //Artifact name syntax check for whitespaces and invalid characters
622       if (artifactName.matches(invalidFilenameRegex)) {
623         errorMap.put(ACTION_ARTIFACT_INVALID_NAME_CODE, ACTION_ARTIFACT_INVALID_NAME);
624       }
625     }
626
627     //Content-Type Header Validation
628     String contentType = servletRequest.getContentType();
629     if (StringUtils.isEmpty(contentType)) {
630       errorMap.put(ACTION_REQUEST_INVALID_GENERIC_CODE, ACTION_REQUEST_CONTENT_TYPE_INVALID);
631     }
632
633     if (artifactToUpload == null) {
634       throw new ActionException(ACTION_REQUEST_INVALID_GENERIC_CODE,
635           ACTION_REQUEST_MISSING_MANDATORY_PARAM + ARTIFACT_FILE);
636     }
637
638     try (InputStream artifactInputStream = artifactToUpload.getDataHandler().getInputStream()) {
639       payload = FileUtils.toByteArray(artifactInputStream);
640     } catch (IOException exception) {
641       LOGGER.error(ACTION_ARTIFACT_READ_FILE_ERROR, exception);
642       throw new ActionException(ACTION_INTERNAL_SERVER_ERR_CODE, ACTION_ARTIFACT_READ_FILE_ERROR);
643     }
644
645     //Validate Artifact size
646     if (payload != null && payload.length > MAX_ACTION_ARTIFACT_SIZE) {
647       throw new ActionException(ACTION_ARTIFACT_TOO_BIG_ERROR_CODE, ACTION_ARTIFACT_TOO_BIG_ERROR);
648     }
649
650     //Validate Checksum
651     if (StringUtils.isEmpty(checksum) || !checksum.equalsIgnoreCase(calculateCheckSum(payload))) {
652       errorMap.put(ACTION_ARTIFACT_CHECKSUM_ERROR_CODE, ACTION_REQUEST_ARTIFACT_CHECKSUM_ERROR);
653     }
654
655     //Validate artifact protection values
656     if (StringUtils.isEmpty(artifactProtection)) {
657       artifactProtection = ActionArtifactProtection.readWrite.name();
658     }
659
660     if (!artifactProtection.equals(ActionArtifactProtection.readOnly.name()) &&
661         !artifactProtection.equals(ActionArtifactProtection.readWrite.name())) {
662       errorMap.put(ACTION_ARTIFACT_INVALID_PROTECTION_CODE,
663           ACTION_REQUEST_ARTIFACT_INVALID_PROTECTION_VALUE);
664     }
665
666     ActionArtifact uploadedArtifact = new ActionArtifact();
667     if (errorMap.isEmpty()) {
668       String user = servletRequest.getRemoteUser();
669       ActionArtifact upload = new ActionArtifact();
670       upload.setArtifactName(artifactName);
671       upload.setArtifactLabel(artifactLabel);
672       upload.setArtifactDescription(artifactDescription);
673       upload.setArtifact(payload);
674       upload.setArtifactCategory(artifactCategory);
675       upload.setArtifactProtection(artifactProtection);
676       uploadedArtifact = actionManager.uploadArtifact(upload, actionInvariantUUID, user);
677     } else {
678       checkAndThrowError(errorMap);
679     }
680     return Response.ok(uploadedArtifact).build();
681   }
682
683   @Override
684   public Response downloadArtifact(String actionUUID, String artifactUUID,
685                                    HttpServletRequest servletRequest) {
686     Response response = null;
687     try {
688       initializeRequestMDC(servletRequest, "", ActionRequest.DOWNLOAD_ARTIFACT);
689       LOGGER.debug(
690           " entering downloadArtifact with actionUUID= " + actionUUID + " and artifactUUID= " +
691               artifactUUID);
692       response = downloadArtifactInternal(actionUUID, artifactUUID, servletRequest);
693       actionLogPostProcessor(StatusCode.COMPLETE, true);
694     } catch (ActionException exception) {
695       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
696       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
697       LOGGER.error(MDC.get(ERROR_DESCRIPTION));
698       throw exception;
699     } catch (Exception exception) {
700       actionLogPostProcessor(StatusCode.ERROR, true);
701       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
702           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
703       LOGGER.error(exception.getMessage());
704       throw exception;
705     } finally {
706       finalAuditMetricsLogProcessor(ActionRequest.DOWNLOAD_ARTIFACT.name());
707     }
708     LOGGER.debug(" exit downloadArtifact with actionUUID= " + actionUUID + " and artifactUUID= " +
709         artifactUUID);
710     return response;
711   }
712
713   private Response downloadArtifactInternal(String actionUUID, String artifactUUID,
714                                             HttpServletRequest servletRequest) {
715     Response response;
716     ActionArtifact actionartifact = null;
717     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
718     Map<String, String> queryParamErrors = validateQueryParam(actionUUID);
719     errorMap.putAll(queryParamErrors);
720     queryParamErrors = validateQueryParam(artifactUUID);
721     errorMap.putAll(queryParamErrors);
722     if (errorMap.isEmpty()) {
723       actionartifact = actionManager.downloadArtifact(actionUUID, artifactUUID);
724     } else {
725       checkAndThrowError(errorMap);
726     }
727     response = createArtifactDownloadResponse(actionartifact);
728     return response;
729   }
730
731   @Override
732   public Response deleteArtifact(String actionInvariantUUID, String artifactUUID,
733                                  HttpServletRequest servletRequest) {
734     Response response = null;
735     try {
736       initializeRequestMDC(servletRequest, actionInvariantUUID, ActionRequest.DELETE_ARTIFACT);
737       LOGGER.debug(" entering deleteArtifact with actionInvariantUuId= " + actionInvariantUUID +
738           " and artifactUUID= " + artifactUUID);
739       response = deleteArtifactInternal(actionInvariantUUID, artifactUUID, servletRequest);
740       LOGGER.debug(" exit deleteArtifact with actionInvariantUuId= " + actionInvariantUUID +
741           " and artifactUUID= " + artifactUUID);
742       actionLogPostProcessor(StatusCode.COMPLETE, true);
743     } catch (ActionException exception) {
744       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
745       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
746       LOGGER.error(MDC.get(ERROR_DESCRIPTION));
747       throw exception;
748     } catch (Exception exception) {
749       actionLogPostProcessor(StatusCode.ERROR, true);
750       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
751           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
752       LOGGER.error(exception.getMessage());
753       throw exception;
754     } finally {
755       finalAuditMetricsLogProcessor(ActionRequest.DELETE_ARTIFACT.name());
756     }
757     return response;
758   }
759
760   private Response deleteArtifactInternal(String actionInvariantUUID, String artifactUUID,
761                                           HttpServletRequest servletRequest) {
762     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
763     Map<String, String> queryParamErrors = validateQueryParam(actionInvariantUUID);
764     errorMap.putAll(queryParamErrors);
765     queryParamErrors = validateQueryParam(artifactUUID);
766     errorMap.putAll(queryParamErrors);
767     if (errorMap.isEmpty()) {
768       actionManager
769           .deleteArtifact(actionInvariantUUID, artifactUUID, servletRequest.getRemoteUser());
770     } else {
771       checkAndThrowError(errorMap);
772     }
773     return Response.ok().build();
774   }
775
776   @Override
777   public Response updateArtifact(String actionInvariantUUID, String artifactUUID,
778                                  String artifactName, String artifactLabel, String artifactCategory,
779                                  String artifactDescription, String artifactProtection,
780                                  String checksum, Attachment artifactToUpdate,
781                                  HttpServletRequest servletRequest) {
782     Response response = null;
783     LOGGER.debug(" entering updateArtifact with actionInvariantUuId= " + actionInvariantUUID +
784         " and artifactUUID= " + artifactUUID + " and artifactName= " + artifactName +
785         " and artifactLabel= " + artifactLabel + " and artifactCategory= " + artifactCategory +
786         " and artifactDescription= " + artifactDescription + " and artifactProtection= " +
787         artifactProtection + " and checksum= " + checksum);
788     try {
789       initializeRequestMDC(servletRequest, actionInvariantUUID, ActionRequest.UPDATE_ARTIFACT);
790       response =
791           updateArtifactInternal(actionInvariantUUID, artifactUUID, artifactName, artifactLabel,
792               artifactCategory, artifactDescription, artifactProtection, checksum, artifactToUpdate,
793               servletRequest);
794       actionLogPostProcessor(StatusCode.COMPLETE, true);
795     } catch (ActionException exception) {
796       actionLogPostProcessor(StatusCode.ERROR, exception.getErrorCode(), exception.getDescription(), true);
797       actionErrorLogProcessor(CategoryLogLevel.ERROR, exception.getErrorCode(), exception.getDescription());
798       LOGGER.error(MDC.get(ERROR_DESCRIPTION));
799       throw exception;
800     } catch (Exception exception) {
801       actionLogPostProcessor(StatusCode.ERROR, true);
802       actionErrorLogProcessor(CategoryLogLevel.ERROR, ACTION_INTERNAL_SERVER_ERR_CODE,
803           ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
804       LOGGER.error(exception.getMessage());
805       throw exception;
806     } finally {
807       finalAuditMetricsLogProcessor(ActionRequest.UPDATE_ARTIFACT.name());
808     }
809     LOGGER.debug(" exit updateArtifact with actionInvariantUuId= " + actionInvariantUUID +
810         " and artifactUUID= " + artifactUUID + " and artifactName= " + artifactName +
811         " and artifactLabel= " + artifactLabel + " and artifactCategory= " + artifactCategory +
812         " and artifactDescription= " + artifactDescription + " and artifactProtection= " +
813         artifactProtection + " and checksum= " + checksum);
814     return response;
815   }
816
817   private void finalAuditMetricsLogProcessor(String targetServiceName) {
818     MDC.put(TARGET_SERVICE_NAME, targetServiceName);
819     MDC.put(TARGET_ENTITY, TARGET_ENTITY_API);
820     LOGGER.metrics("");
821     LOGGER.audit("");
822   }
823
824   private Response updateArtifactInternal(String actionInvariantUUID, String artifactUUID,
825                                           String artifactName, String artifactLabel,
826                                           String artifactCategory, String artifactDescription,
827                                           String artifactProtection, String checksum,
828                                           Attachment artifactToUpdate,
829                                           HttpServletRequest servletRequest) {
830     byte[] payload = null;
831     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
832
833     //Content-Type Header Validation
834     String contentType = servletRequest.getContentType();
835     if (StringUtils.isEmpty(contentType)) {
836       errorMap.put(ACTION_REQUEST_INVALID_GENERIC_CODE, ACTION_REQUEST_CONTENT_TYPE_INVALID);
837     }
838
839     if (artifactToUpdate != null) {
840
841       try (InputStream artifactInputStream = artifactToUpdate.getDataHandler().getInputStream()) {
842         payload = FileUtils.toByteArray(artifactInputStream);
843       } catch (IOException exception) {
844         LOGGER.error(ACTION_ARTIFACT_READ_FILE_ERROR, exception);
845         throw new ActionException(ACTION_INTERNAL_SERVER_ERR_CODE, ACTION_ARTIFACT_READ_FILE_ERROR);
846       }
847
848       //Validate Artifact size
849       if (payload != null && payload.length > MAX_ACTION_ARTIFACT_SIZE) {
850         throw new ActionException(ACTION_ARTIFACT_TOO_BIG_ERROR_CODE,
851             ACTION_ARTIFACT_TOO_BIG_ERROR);
852       }
853
854       //Validate Checksum
855       if (StringUtils.isEmpty(checksum) || !checksum.equalsIgnoreCase(calculateCheckSum(payload))) {
856         errorMap.put(ACTION_ARTIFACT_CHECKSUM_ERROR_CODE, ACTION_REQUEST_ARTIFACT_CHECKSUM_ERROR);
857       }
858     }
859
860     if (artifactProtection != null && (artifactProtection.isEmpty() ||
861         (!artifactProtection.equals(ActionArtifactProtection.readOnly.name()) &&
862             !artifactProtection.equals(ActionArtifactProtection.readWrite.name())))) {
863       errorMap.put(ACTION_ARTIFACT_INVALID_PROTECTION_CODE,
864           ACTION_REQUEST_ARTIFACT_INVALID_PROTECTION_VALUE);
865     }
866
867     ActionArtifact updateArtifact = new ActionArtifact();
868     if (errorMap.isEmpty()) {
869       String user = servletRequest.getRemoteUser();
870       ActionArtifact update = new ActionArtifact();
871       update.setArtifactUuId(artifactUUID);
872       update.setArtifactName(artifactName);
873       update.setArtifactLabel(artifactLabel);
874       update.setArtifactDescription(artifactDescription);
875       update.setArtifact(payload);
876       update.setArtifactCategory(artifactCategory);
877       update.setArtifactProtection(artifactProtection);
878       actionManager.updateArtifact(update, actionInvariantUUID, user);
879     } else {
880       checkAndThrowError(errorMap);
881     }
882     return Response.ok().build();
883   }
884
885   /**
886    * Get List of all actions
887    */
888   private Response getAllActions(HttpServletRequest servletRequest) {
889     ListResponseWrapper responseList = null;
890     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
891     if (errorMap.isEmpty()) {
892       List<Action> actions = actionManager.getFilteredActions(FILTER_TYPE_NONE, null);
893       responseList = createResponse(actions);
894     } else {
895       checkAndThrowError(errorMap);
896     }
897
898     return Response.ok(responseList).build();
899   }
900
901   /**
902    * Get Actions by OPENECOMP component ID
903    */
904   private Response getActionsByOpenEcompComponents(String componentID,
905                                                    HttpServletRequest servletRequest) {
906     ListResponseWrapper responseList = null;
907     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
908     Map<String, String> queryParamErrors = validateQueryParam(componentID);
909     errorMap.putAll(queryParamErrors);
910     if (errorMap.isEmpty()) {
911       List<Action> actions =
912           actionManager.getFilteredActions(FILTER_TYPE_OPEN_ECOMP_COMPONENT, componentID);
913       responseList = createResponse(actions);
914     } else {
915       checkAndThrowError(errorMap);
916     }
917     return Response.ok(responseList).build();
918   }
919
920   /**
921    * Get Actions by Model ID
922    */
923   private Response getActionsByModel(String modelId, HttpServletRequest servletRequest) {
924     ListResponseWrapper responseList = null;
925     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
926     Map<String, String> queryParamErrors = validateQueryParam(modelId);
927     errorMap.putAll(queryParamErrors);
928     if (errorMap.isEmpty()) {
929       List<Action> actions = actionManager.getFilteredActions(FILTER_TYPE_MODEL, modelId);
930       responseList = createResponse(actions);
931     } else {
932       checkAndThrowError(errorMap);
933     }
934     return Response.ok(responseList).build();
935   }
936
937   /**
938    * Get all actions with given action name
939    */
940   private Response getActionsByName(String name, HttpServletRequest servletRequest) {
941     ListResponseWrapper responseList = null;
942     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
943     Map<String, String> queryParamErrors = validateQueryParam(name);
944     errorMap.putAll(queryParamErrors);
945     if (errorMap.isEmpty()) {
946       List<Action> actions = actionManager.getFilteredActions(FILTER_TYPE_NAME, name);
947       responseList = createResponse(actions);
948     } else {
949       checkAndThrowError(errorMap);
950     }
951     return Response.ok(responseList).build();
952   }
953
954   /**
955    * Get an action with given ActionUUID
956    */
957   private Response getActionsByUniqueID(String actionUUID, HttpServletRequest servletRequest,
958                                         String actionInvariantUUID) {
959     LOGGER.debug(
960         " entering getActionByUUID with invariantID= " + actionInvariantUUID + " and actionUUID= " +
961             actionUUID);
962     Map<String, Object> responseDTO = new LinkedHashMap<>();
963     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
964     Map<String, String> queryParamErrors = validateQueryParam(actionUUID);
965     errorMap.putAll(queryParamErrors);
966     if (errorMap.isEmpty()) {
967       Action action = actionManager.getActionsByActionUuId(actionUUID);
968       if (action.getActionInvariantUuId() != null &&
969           action.getActionInvariantUuId().equalsIgnoreCase(actionInvariantUUID)) {
970         responseDTO = JsonUtil.json2Object(action.getData(), LinkedHashMap.class);
971         responseDTO.put(STATUS, action.getStatus().name());
972         responseDTO.put(TIMESTAMP, getUtcDateStringFromTimestamp(action.getTimestamp()));
973         responseDTO.put(UPDATED_BY, action.getUser());
974       } else {
975         throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
976       }
977     } else {
978       checkAndThrowError(errorMap);
979     }
980     LOGGER.debug(
981         " exit getActionByUUID with invariantID= " + actionInvariantUUID + " and actionUUID= " +
982             actionUUID);
983     return Response.ok(responseDTO).build();
984   }
985
986   /**
987    * Get all actions with given Vendor Name
988    */
989   private Response getActionsByVendor(String vendor, HttpServletRequest servletRequest) {
990     //Validate request syntax before passing to the manager
991     ListResponseWrapper responseList = null;
992     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
993     Map<String, String> queryParamErrors = validateQueryParam(vendor);
994     errorMap.putAll(queryParamErrors);
995     if (errorMap.isEmpty()) {
996       List<Action> actions = actionManager.getFilteredActions(FILTER_TYPE_VENDOR, vendor);
997       responseList = createResponse(actions);
998     } else {
999       checkAndThrowError(errorMap);
1000     }
1001     return Response.ok(responseList).build();
1002   }
1003
1004   /**
1005    * Get all actions with given Category Name
1006    */
1007   private Response getActionsByCategory(String category, HttpServletRequest servletRequest) {
1008     //Validate request syntax before passing to the manager
1009     ListResponseWrapper responseList = null;
1010     Map<String, String> errorMap = validateRequestHeaders(servletRequest);
1011     Map<String, String> queryParamErrors = validateQueryParam(category);
1012     errorMap.putAll(queryParamErrors);
1013     if (errorMap.isEmpty()) {
1014       List<Action> actions = actionManager.getFilteredActions(FILTER_TYPE_CATEGORY, category);
1015       responseList = createResponse(actions);
1016     } else {
1017       checkAndThrowError(errorMap);
1018     }
1019     return Response.ok(responseList).build();
1020   }
1021
1022   /**
1023    * Validates mandatory headers in the request
1024    *
1025    * @param servletRequest Servlet Request object
1026    * @return Map of error codes and description found in the request headers
1027    */
1028   private Map<String, String> validateRequestHeaders(HttpServletRequest servletRequest) {
1029     Map<String, String> errorMap = new LinkedHashMap<>();
1030     //Syntactic generic request parameter validations
1031     String openEcompRequestId = servletRequest.getHeader(X_OPEN_ECOMP_REQUEST_ID_HEADER_PARAM);
1032     if (StringUtils.isEmpty(openEcompRequestId)) {
1033       errorMap.put(ACTION_INVALID_REQUEST_ID_CODE, ACTION_REQUEST_OPEN_ECOMP_REQUEST_ID_INVALID);
1034     }
1035
1036     String opemnEcompInstanceId = servletRequest.getHeader(X_OPEN_ECOMP_INSTANCE_ID_HEADER_PARAM);
1037     if (StringUtils.isEmpty(opemnEcompInstanceId)) {
1038       errorMap.put(ACTION_INVALID_INSTANCE_ID_CODE, ACTION_REQUEST_OPEN_ECOMP_INSTANCE_ID_INVALID);
1039     }
1040     return errorMap;
1041   }
1042
1043   /**
1044    * Validates query parameter in the request
1045    *
1046    * @param queryParam Query Parameter to be validated
1047    * @return Map of error codes and description found in the query parameter
1048    */
1049   private Map<String, String> validateQueryParam(String queryParam) {
1050     Map<String, String> queryParamErrors = new LinkedHashMap<>();
1051     if (StringUtils.isEmpty(queryParam)) {
1052       queryParamErrors
1053           .put(ACTION_INVALID_PARAM_CODE, ACTION_REQUEST_MISSING_MANDATORY_PARAM + queryParam);
1054     }
1055     return queryParamErrors;
1056   }
1057
1058   /**
1059    * Validate request body based on request type
1060    *
1061    * @param requestJSON Raw request json body as string
1062    * @return Map of error codes and description found in the request body
1063    */
1064   private Map<String, String> validateRequestBody(String requestType, String requestJSON) {
1065     Map<String, String> requestBodyErrorMap = new LinkedHashMap<>();
1066     if (StringUtils.isEmpty(requestJSON) || requestJSON.equals(REQUEST_EMPTY_BODY)) {
1067       requestBodyErrorMap.put(ACTION_INVALID_REQUEST_BODY_CODE, ACTION_REQUEST_BODY_EMPTY);
1068     } else {
1069       if(requestType == ActionConstants.REQUEST_TYPE_CREATE_ACTION){
1070         //placeholder for future implementation
1071       }
1072       if(requestType == ActionConstants.REQUEST_TYPE_UPDATE_ACTION){
1073         //Semantic request specific validations
1074         Action action = JsonUtil.json2Object(requestJSON, Action.class);
1075         if(StringUtils.isEmpty(action.getName())){
1076           setErrorValue(ACTION_REQUEST_INVALID_GENERIC_CODE, ACTION_REQUEST_PARAM_NAME,
1077               requestBodyErrorMap);
1078         } else {
1079           //Added check for action names not allowing whitespaces
1080           if (action.getName().matches(whitespaceRegex)){
1081             requestBodyErrorMap.put(ACTION_ARTIFACT_INVALID_NAME_CODE, ACTION_REQUEST_INVALID_NAME);
1082           }
1083         }
1084
1085         if(action.getSupportedModels() != null && !isIDPresentInMap(action.getSupportedModels(),
1086             SUPPORTED_MODELS_VERSION_ID)){
1087           setErrorValue(ACTION_REQUEST_INVALID_GENERIC_CODE,
1088               ACTION_REQUEST_PARAM_SUPPORTED_MODELS, requestBodyErrorMap);
1089         }
1090         if(action.getSupportedComponents() != null && !isIDPresentInMap(action
1091             .getSupportedComponents(), SUPPORTED_COMPONENTS_ID)){
1092           setErrorValue(ACTION_REQUEST_INVALID_GENERIC_CODE,
1093               ACTION_REQUEST_PARAM_SUPPORTED_MODELS, requestBodyErrorMap);
1094         }
1095         if(action.getArtifacts() != null){
1096           setErrorValue(ACTION_UPDATE_NOT_ALLOWED_CODE,
1097               ACTION_REQUEST_ARTIFACT_OPERATION_ALLOWED, requestBodyErrorMap);
1098         }
1099       }
1100
1101     }
1102     return requestBodyErrorMap;
1103   }
1104
1105   /**
1106    * Populates Given Error Map with Given Error Code and Error MEssage
1107    */
1108   private void setErrorValue(String key, String message, Map<String, String> errorMap) {
1109     String errorMessage = errorMap.get(key);
1110     if (errorMessage != null) {
1111       message = errorMessage + ", " + message;
1112     } else {
1113       if(key == ACTION_REQUEST_INVALID_GENERIC_CODE)
1114         message = ACTION_REQUEST_MISSING_MANDATORY_PARAM + message;
1115     }
1116     errorMap.put(key, message);
1117   }
1118
1119   /**
1120    * Returns true if given key exists in List of HashMap
1121    */
1122   private boolean isIDPresentInMap(List<HashMap<String, String>> map, String idName) {
1123     if (map != null && !map.isEmpty()) {
1124       for (HashMap<String, String> entry : map) {
1125         if (StringUtils.isEmpty(entry.get(idName))) {
1126           return false;
1127         }
1128       }
1129     }
1130     return true;
1131   }
1132
1133   /**
1134    * @throws ActionException if given ErrorMap is not empty. All error messages at given time are
1135    *                         thrown in one single exception
1136    */
1137   private void checkAndThrowError(Map<String, String> errorMap) {
1138     if (errorMap.size() > 1) {
1139       //Multiple errors detected .. Send the response with a common error code for multiple errors
1140       throw new ActionException(ACTION_REQUEST_INVALID_GENERIC_CODE,
1141           StringUtils.join(errorMap.values(), ", "));
1142     } else if (errorMap.size() == 1) {
1143       String svcPolicyExceptionCode = errorMap.entrySet().iterator().next().getKey();
1144       throw new ActionException(svcPolicyExceptionCode,
1145           errorMap.get(svcPolicyExceptionCode));
1146     }
1147   }
1148
1149   /**
1150    * Populates ActionResponseDto based on given Action
1151    */
1152   private ActionResponseDto createResponseDTO(Action action) {
1153     String data = action.getData();
1154     ActionResponseDto responseDTO = JsonUtil.json2Object(data, ActionResponseDto.class);
1155     responseDTO.setStatus(action.getStatus().name());
1156     responseDTO.setTimestamp(getUtcDateStringFromTimestamp(action.getTimestamp()));
1157     //if(!action.getUser().equals(DELETE_ACTION_USER))
1158     responseDTO.setUpdatedBy(action.getUser());
1159     return responseDTO;
1160   }
1161
1162   /**
1163    * Creates response based on given list of actions
1164    */
1165   private ListResponseWrapper createResponse(List<Action> actions) {
1166     ListResponseWrapper responseList = new ListResponseWrapper();
1167     for (Action action : actions) {
1168       ActionResponseDto responseDTO = createResponseDTO(action);
1169       responseList.add(responseDTO);
1170     }
1171     return responseList;
1172   }
1173
1174
1175   private Response createArtifactDownloadResponse(ActionArtifact actionartifact) {
1176     if (actionartifact != null && actionartifact.getArtifact() != null) {
1177       byte[] artifactsBytes = actionartifact.getArtifact();
1178       File artifactFile = new File(actionartifact.getArtifactName());
1179       try (FileOutputStream fos = new FileOutputStream(artifactFile)) {
1180         fos.write(artifactsBytes);
1181         fos.close();
1182       } catch (IOException exception) {
1183         LOGGER.error(ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG, exception);
1184         throw new ActionException(ActionErrorConstants.ACTION_INTERNAL_SERVER_ERR_CODE,
1185             ActionErrorConstants.ACTION_ENTITY_INTERNAL_SERVER_ERROR_MSG);
1186       }
1187       Response.ResponseBuilder responseBuilder = Response.ok(artifactFile);
1188       responseBuilder.header("Content-Disposition",
1189           "attachment; filename=" + actionartifact.getArtifactName());
1190       responseBuilder.header("Content-MD5", CalcMD5CheckSum(artifactsBytes));
1191       responseBuilder.header("Content-Length", artifactFile.length());
1192       return responseBuilder.build();
1193     } else {
1194       throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
1195           ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
1196     }
1197   }
1198
1199   /**
1200    * Initialize MDC for logging the current request
1201    *
1202    * @param actionInvariantId Action Invariant Id if available (null otherwise)
1203    * @param servletRequest    Request Contecxt object
1204    * @param requestType       Current action request (CRUD of Action, Artifact, Version operations)
1205    */
1206   private void initializeRequestMDC(HttpServletRequest servletRequest, String actionInvariantId,
1207                                     ActionRequest requestType) {
1208     MDC.put(REQUEST_ID, servletRequest.getHeader(X_OPEN_ECOMP_REQUEST_ID_HEADER_PARAM));
1209     MDC.put(PARTNER_NAME, servletRequest.getRemoteUser());
1210     MDC.put(INSTANCE_UUID, MDC_ASDC_INSTANCE_UUID);
1211     MDC.put(SERVICE_METRIC_BEGIN_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
1212     MDC.put(STATUS_CODE, StatusCode.COMPLETE.name());
1213     MDC.put(SERVICE_NAME, requestType.name());
1214     MDC.put(CLIENT_IP, MDC.get(REMOTE_HOST));
1215     MDC.put(SERVICE_INSTANCE_ID, actionInvariantId);
1216     MDC.put(LOCAL_ADDR, MDC.get("ServerIPAddress"));
1217     MDC.put(BE_FQDN, MDC.get("ServerFQDN"));
1218
1219     if (LOGGER.isDebugEnabled()) {
1220       MDC.put(CATEGORY_LOG_LEVEL, CategoryLogLevel.DEBUG.name());
1221     } else if (LOGGER.isInfoEnabled()) {
1222       MDC.put(CATEGORY_LOG_LEVEL, CategoryLogLevel.INFO.name());
1223     } else if (LOGGER.isWarnEnabled()) {
1224       MDC.put(CATEGORY_LOG_LEVEL, CategoryLogLevel.WARN.name());
1225     } else if (LOGGER.isErrorEnabled()) {
1226       MDC.put(CATEGORY_LOG_LEVEL, CategoryLogLevel.ERROR.name());
1227     }
1228   }
1229
1230   private String CalcMD5CheckSum(byte[] input) {
1231     String checksum = null;
1232     if (input != null) {
1233       checksum = DigestUtils.md5Hex(input).toUpperCase();
1234       System.out.println("checksum : " + checksum);
1235     }
1236     return checksum;
1237   }
1238 }