Implement 'Update Service by importing Tosca Template'-story
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / servlets / AbstractValidationsServlet.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  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22 package org.openecomp.sdc.be.servlets;
23
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import com.google.gson.Gson;
26 import com.google.gson.JsonSyntaxException;
27 import fj.data.Either;
28 import java.io.File;
29 import java.io.FileInputStream;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.lang.reflect.Type;
33 import java.nio.charset.StandardCharsets;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Optional;
39 import java.util.function.Supplier;
40 import javax.servlet.ServletContext;
41 import javax.servlet.http.HttpServletRequest;
42 import javax.ws.rs.core.Response;
43 import org.apache.commons.codec.binary.Base64;
44 import org.apache.commons.io.IOUtils;
45 import org.apache.commons.lang3.StringUtils;
46 import org.apache.commons.lang3.tuple.ImmutablePair;
47 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
48 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
49 import org.openecomp.sdc.be.components.impl.ImportUtils;
50 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
51 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
52 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
53 import org.openecomp.sdc.be.components.impl.ServiceImportManager;
54 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
55 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
56 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
57 import org.openecomp.sdc.be.config.BeEcompErrorManager;
58 import org.openecomp.sdc.be.config.ConfigurationManager;
59 import org.openecomp.sdc.be.dao.api.ActionStatus;
60 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
61 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
62 import org.openecomp.sdc.be.impl.ComponentsUtils;
63 import org.openecomp.sdc.be.impl.ServletUtils;
64 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
65 import org.openecomp.sdc.be.model.ArtifactDefinition;
66 import org.openecomp.sdc.be.model.Component;
67 import org.openecomp.sdc.be.model.Resource;
68 import org.openecomp.sdc.be.model.Service;
69 import org.openecomp.sdc.be.model.UploadResourceInfo;
70 import org.openecomp.sdc.be.model.UploadServiceInfo;
71 import org.openecomp.sdc.be.model.User;
72 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
73 import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
74 import org.openecomp.sdc.be.servlets.ServiceUploadServlet.ServiceAuthorityTypeEnum;
75 import org.openecomp.sdc.be.user.Role;
76 import org.openecomp.sdc.be.user.UserBusinessLogic;
77 import org.openecomp.sdc.be.utils.TypeUtils;
78 import org.openecomp.sdc.common.api.Constants;
79 import org.openecomp.sdc.common.api.UploadArtifactInfo;
80 import org.openecomp.sdc.common.datastructure.Wrapper;
81 import org.openecomp.sdc.common.log.wrappers.Logger;
82 import org.openecomp.sdc.common.util.GeneralUtility;
83 import org.openecomp.sdc.common.util.YamlToObjectConverter;
84 import org.openecomp.sdc.common.zip.ZipUtils;
85 import org.openecomp.sdc.common.zip.exception.ZipException;
86 import org.openecomp.sdc.exception.ResponseFormat;
87 import org.springframework.web.context.WebApplicationContext;
88 import org.yaml.snakeyaml.Yaml;
89
90 public abstract class AbstractValidationsServlet extends BeGenericServlet {
91
92     private static final Logger log = Logger.getLogger(AbstractValidationsServlet.class);
93     private static final String TOSCA_SIMPLE_YAML_PREFIX = "tosca_simple_yaml_";
94     private static final List<String> TOSCA_DEFINITION_VERSIONS = Arrays
95         .asList(TOSCA_SIMPLE_YAML_PREFIX + "1_0_0", TOSCA_SIMPLE_YAML_PREFIX + "1_1_0", "tosca_simple_profile_for_nfv_1_0_0",
96             TOSCA_SIMPLE_YAML_PREFIX + "1_0", TOSCA_SIMPLE_YAML_PREFIX + "1_1", TOSCA_SIMPLE_YAML_PREFIX + "1_2", TOSCA_SIMPLE_YAML_PREFIX + "1_3");
97     private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar", ".meta");
98     private static final String INVALID_JSON_WAS_RECEIVED = "Invalid json was received.";
99     private static final String AUDIT_BEFORE_SENDING_RESPONSE = "audit before sending response";
100     private static final String VALIDATE_USER_ROLE = "validate user role";
101     private static final String USER_IS_NOT_IN_APPROPRIATE_ROLE_TO_PERFORM_ACTION = "user is not in appropriate role to perform action";
102     protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
103     protected ServletUtils servletUtils;
104     protected ResourceImportManager resourceImportManager;
105     protected ServiceImportManager serviceImportManager;
106
107     protected AbstractValidationsServlet(ComponentInstanceBusinessLogic componentInstanceBL,
108                                          ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager) {
109         super(componentsUtils);
110         this.servletUtils = servletUtils;
111         this.resourceImportManager = resourceImportManager;
112         this.componentInstanceBusinessLogic = componentInstanceBL;
113     }
114
115     public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
116         final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
117         String ymlName = unzippedFolder.keySet().iterator().next();
118         fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
119     }
120
121     private static void fillToscaTemplateFromZip(final Wrapper<String> yamlStringWrapper, final String payloadName, final File file)
122         throws ZipException {
123         final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
124         final byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
125         final String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
126         log.debug("received yaml: {}", yamlAsString);
127         yamlStringWrapper.setInnerElement(yamlAsString);
128     }
129
130     protected void init() {
131     }
132
133     protected synchronized void initSpringFromContext() {
134         if (serviceImportManager == null) {
135             ServletContext context = servletRequest.getSession().getServletContext();
136             WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context
137                 .getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR);
138             WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context);
139             serviceImportManager = webApplicationContext.getBean(ServiceImportManager.class);
140         }
141     }
142
143     protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) {
144         if (resourceImportManager.isResourceExist(resourceName)) {
145             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS);
146             Response errorResponse = buildErrorResponse(responseFormat);
147             getComponentsUtils().auditResource(responseFormat, user, resourceName, AuditingActionEnum.IMPORT_RESOURCE);
148             responseWrapper.setInnerElement(errorResponse);
149         }
150     }
151
152     protected void validateUserExist(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, String userUserId) {
153         log.debug("get user {} from DB", userUserId);
154         // get user details
155         if (userUserId == null) {
156             log.info("user userId is null");
157             Response response = returnMissingInformation(new User());
158             responseWrapper.setInnerElement(response);
159         } else {
160             UserBusinessLogic userAdmin = getServletUtils().getUserAdmin();
161             try {
162                 User user = userAdmin.getUser(userUserId);
163                 userWrapper.setInnerElement(user);
164             } catch (ComponentException ce) {
165                 log.info("user is not listed. userId={}", userUserId);
166                 User user = new User();
167                 user.setUserId(userUserId);
168                 Response response = returnMissingInformation(user);
169                 responseWrapper.setInnerElement(response);
170             }
171         }
172     }
173
174     protected Response returnMissingInformation(User user) {
175         ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_INFORMATION);
176         getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
177         return buildErrorResponse(responseFormat);
178     }
179
180     protected void validateDataNotNull(Wrapper<Response> responseWrapper, Object... dataParams) {
181         for (Object dataElement : dataParams) {
182             if (dataElement == null) {
183                 log.info("Invalid body was received.");
184                 Response response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
185                 responseWrapper.setInnerElement(response);
186                 break;
187             }
188         }
189     }
190
191     protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user) {
192         log.debug(VALIDATE_USER_ROLE);
193         if (!user.getRole().equals(Role.ADMIN.name()) && !user.getRole().equals(Role.DESIGNER.name())) {
194             log.info(USER_IS_NOT_IN_APPROPRIATE_ROLE_TO_PERFORM_ACTION);
195             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
196             log.debug(AUDIT_BEFORE_SENDING_RESPONSE);
197             getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
198             Response response = buildErrorResponse(responseFormat);
199             errorResponseWrapper.setInnerElement(response);
200         }
201     }
202
203     protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
204         if (StringUtils.isEmpty(payloadName)) {
205             log.info("Invalid JSON was received. Payload name is empty");
206             final Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
207             responseWrapper.setInnerElement(errorResponse);
208             return;
209         }
210         final Map<String, byte[]> unzippedFolder;
211         try {
212             unzippedFolder = ZipUtils.readZip(zipFile, false);
213         } catch (final ZipException e) {
214             log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
215             final Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
216             responseWrapper.setInnerElement(errorResponse);
217             return;
218         }
219         if (!unzippedFolder.containsKey(payloadName)) {
220             log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
221             final Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
222             responseWrapper.setInnerElement(errorResponse);
223         }
224     }
225
226     protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
227         if (StringUtils.isEmpty(payloadName)) {
228             log.info("Invalid JSON was received. Payload name is empty");
229             Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
230             responseWrapper.setInnerElement(errorResponse);
231             return;
232         }
233         final Map<String, byte[]> unzippedFolder;
234         try {
235             unzippedFolder = ZipUtils.readZip(csarFile, false);
236         } catch (final ZipException e) {
237             log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
238             final Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
239             responseWrapper.setInnerElement(errorResponse);
240             return;
241         }
242         if (unzippedFolder.isEmpty()) {
243             log.info("The CSAR file is empty");
244             Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
245             responseWrapper.setInnerElement(errorResponse);
246         }
247     }
248
249     protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
250         extractZipContents(yamlStringWrapper, file);
251     }
252
253     protected void fillPayloadDataFromFile(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfoWrapper, File file) {
254         try (InputStream fileInputStream = new FileInputStream(file)) {
255             byte[] data = new byte[(int) file.length()];
256             if (fileInputStream.read(data) == -1) {
257                 log.info(INVALID_JSON_WAS_RECEIVED);
258                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
259                 Response errorResp = buildErrorResponse(responseFormat);
260                 responseWrapper.setInnerElement(errorResp);
261             }
262             String payloadData = Base64.encodeBase64String(data);
263             uploadResourceInfoWrapper.setPayloadData(payloadData);
264         } catch (IOException e) {
265             log.info("Invalid json was received or Error while closing input Stream.");
266             log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
267             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
268             Response errorResp = buildErrorResponse(responseFormat);
269             responseWrapper.setInnerElement(errorResp);
270         }
271     }
272
273     protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ResourceAuthorityTypeEnum resourceAuthority) {
274         log.debug(VALIDATE_USER_ROLE);
275         if (resourceAuthority == ResourceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
276             if (!user.getRole().equals(Role.ADMIN.name())) {
277                 log.info(USER_IS_NOT_IN_APPROPRIATE_ROLE_TO_PERFORM_ACTION);
278                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
279                 log.debug(AUDIT_BEFORE_SENDING_RESPONSE);
280                 getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
281                 Response response = buildErrorResponse(responseFormat);
282                 errorResponseWrapper.setInnerElement(response);
283             }
284         } else {
285             validateUserRole(errorResponseWrapper, user);
286         }
287     }
288
289     protected void validateAndFillResourceJson(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, User user,
290                                                ResourceAuthorityTypeEnum resourceAuthorityEnum, String resourceInfo) {
291         boolean isValid;
292         try {
293             log.debug("The received json is {}", resourceInfo);
294             UploadResourceInfo resourceInfoObject = gson.fromJson(resourceInfo, UploadResourceInfo.class);
295             if (resourceInfoObject == null) {
296                 isValid = false;
297             } else {
298                 resourceInfoObject.setNormative(!resourceAuthorityEnum.isUserTypeResource());
299                 if (!resourceAuthorityEnum.isBackEndImport()) {
300                     isValid = resourceInfoObject.getPayloadName() != null && !resourceInfoObject.getPayloadName().isEmpty();
301                     //only resource name is checked
302                 } else {
303                     isValid = true;
304                 }
305                 uploadResourceInfoWrapper.setInnerElement(resourceInfoObject);
306             }
307         } catch (JsonSyntaxException e) {
308             log.debug("Invalid json was received. {}", e.getMessage(), e);
309             isValid = false;
310         }
311         if (!isValid) {
312             log.info(INVALID_JSON_WAS_RECEIVED);
313             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
314             getComponentsUtils().auditResource(responseFormat, user, "", AuditingActionEnum.IMPORT_RESOURCE);
315             Response errorResp = buildErrorResponse(responseFormat);
316             responseWrapper.setInnerElement(errorResp);
317         }
318     }
319
320     protected void validateAuthorityType(Wrapper<Response> responseWrapper, String authorityType) {
321         log.debug("The received authority type is {}", authorityType);
322         ResourceAuthorityTypeEnum authorityTypeEnum = ResourceAuthorityTypeEnum.findByUrlPath(authorityType);
323         if (authorityTypeEnum == null) {
324             log.info("Invalid authority type was received.");
325             Response errorResp = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
326             responseWrapper.setInnerElement(errorResp);
327         }
328     }
329
330     public ServletUtils getServletUtils() {
331         return servletUtils;
332     }
333
334     public Gson getGson() {
335         return getServletUtils().getGson();
336     }
337
338     @Override
339     public ComponentsUtils getComponentsUtils() {
340         return getServletUtils().getComponentsUtils();
341     }
342
343     protected void validatePayloadIsTosca(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user, String toscaPayload) {
344         log.debug("checking payload is valid tosca");
345         boolean isValid;
346         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
347         Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils
348             .findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
349         if (findFirstToscaStringElement.isRight()) {
350             isValid = false;
351         } else {
352             String defenitionVersionFound = findFirstToscaStringElement.left().value();
353             if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
354                 isValid = false;
355             } else {
356                 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
357             }
358         }
359         if (!isValid) {
360             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
361             Response errorResponse = buildErrorResponse(responseFormat);
362             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
363             responseWrapper.setInnerElement(errorResponse);
364         }
365     }
366
367     protected void validatePayloadIsYml(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo,
368                                         String toscaTamplatePayload) {
369         log.debug("checking tosca template is valid yml");
370         YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
371         boolean isYamlValid = yamlConvertor.isValidYaml(toscaTamplatePayload.getBytes());
372         if (!isYamlValid) {
373             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
374             Response errorResponse = buildErrorResponse(responseFormat);
375             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
376             responseWrapper.setInnerElement(errorResponse);
377         }
378     }
379
380     /**
381      * Gets the Resource type from the given node type name.
382      *
383      * @param nodeTypeFullName - Node type Name
384      * @return Resource Type name
385      */
386     private String getResourceType(final String nodeTypeFullName) {
387         final Optional<String> nodeTypeNamePrefix = getNodeTypeNamePrefix(nodeTypeFullName);
388         if (nodeTypeNamePrefix.isPresent()) {
389             final String nameWithouNamespacePrefix = nodeTypeFullName.substring(nodeTypeNamePrefix.get().length());
390             final String[] findTypes = nameWithouNamespacePrefix.split("\\.");
391             if (findTypes.length > 0) {
392                 final ResourceTypeEnum resourceType = ResourceTypeEnum.getType(findTypes[0].toUpperCase());
393                 if (resourceType != null) {
394                     return resourceType.name();
395                 }
396             }
397         }
398         return ResourceTypeEnum.VFC.name();
399     }
400
401     /**
402      * Extracts the Node Type Name prefix from the given Node Type Name.
403      *
404      * @param nodeName - Node Type Name
405      * @return Node Type Name prefix
406      */
407     private Optional<String> getNodeTypeNamePrefix(final String nodeName) {
408         final List<String> definedNodeTypeNamespaceList = ConfigurationManager.getConfigurationManager().getConfiguration()
409             .getDefinedResourceNamespace();
410         for (final String validNamespace : definedNodeTypeNamespaceList) {
411             if (nodeName.startsWith(validNamespace)) {
412                 return Optional.of(validNamespace);
413             }
414         }
415         return Optional.empty();
416     }
417
418     protected void validatePayloadNameSpace(final Wrapper<Response> responseWrapper, final UploadResourceInfo resourceInfo, final User user,
419                                             final String toscaPayload) {
420         boolean isValid;
421         String namespace = "";
422         final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
423         final Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils
424             .findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
425         if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
426             isValid = false;
427         } else {
428             namespace = toscaElement.left().value().keySet().iterator().next();
429             isValid = getNodeTypeNamePrefix(namespace).isPresent();
430         }
431         if (!isValid) {
432             final ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_NAMESPACE);
433             final Response errorResponse = buildErrorResponse(responseFormat);
434             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
435             responseWrapper.setInnerElement(errorResponse);
436         } else {
437             resourceInfo.setResourceType(getResourceType(namespace));
438         }
439     }
440
441     private void validatePayloadIsSingleResource(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user,
442                                                  String toscaPayload) {
443         log.debug("checking payload contains single resource");
444         boolean isValid;
445         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
446         Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils
447             .findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
448         if (toscaElement.isRight()) {
449             isValid = false;
450         } else {
451             isValid = toscaElement.left().value().size() == 1;
452         }
453         if (!isValid) {
454             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_SINGLE_RESOURCE);
455             Response errorResponse = buildErrorResponse(responseFormat);
456             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
457             responseWrapper.setInnerElement(errorResponse);
458         }
459     }
460
461     private void validatePayloadIsNotService(Wrapper<Response> responseWrapper, User user, UploadResourceInfo uploadResourceInfo,
462                                              String toscaPayload) {
463         log.debug("checking payload is not a tosca service");
464         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
465         Either<Object, ResultStatusEnum> toscaElement = ImportUtils
466             .findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL);
467         if (toscaElement.isLeft()) {
468             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.NOT_RESOURCE_TOSCA_TEMPLATE);
469             Response errorResponse = buildErrorResponse(responseFormat);
470             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
471             responseWrapper.setInnerElement(errorResponse);
472         }
473     }
474
475     private void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
476         String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName();
477         boolean isValidSuffix = isToscaTemplatePayloadNameValid(toscaTemplatePayloadName);
478         if (!isValidSuffix) {
479             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
480             Response errorResponse = buildErrorResponse(responseFormat);
481             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
482             responseWrapper.setInnerElement(errorResponse);
483         }
484     }
485
486     private boolean isToscaTemplatePayloadNameValid(String toscaTemplatePayloadName) {
487         boolean isValidSuffix = false;
488         if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) {
489             for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) {
490                 isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix);
491             }
492         }
493         return isValidSuffix;
494     }
495
496     private void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request,
497                              String resourceInfoJsonString) {
498         boolean isValid;
499         String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
500         if (recievedMD5 == null) {
501             isValid = false;
502         } else {
503             String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(resourceInfoJsonString);
504             isValid = calculateMD5.equals(recievedMD5);
505         }
506         if (!isValid) {
507             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_CHECKSUM);
508             Response errorResponse = buildErrorResponse(responseFormat);
509             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
510             responseWrapper.setInnerElement(errorResponse);
511         }
512     }
513
514     ComponentTypeEnum validateComponentType(String componentType) {
515         if (componentType == null) {
516             throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR);
517         }
518         if (ComponentTypeEnum.RESOURCE_PARAM_NAME.equalsIgnoreCase(componentType)) {
519             return ComponentTypeEnum.RESOURCE;
520         }
521         if (ComponentTypeEnum.SERVICE_PARAM_NAME.equalsIgnoreCase(componentType)) {
522             return ComponentTypeEnum.SERVICE;
523         }
524         log.debug("Invalid componentType:{}", componentType);
525         throw new ByActionStatusComponentException(ActionStatus.UNSUPPORTED_ERROR, componentType);
526     }
527
528     ComponentTypeEnum convertToComponentType(String componentType) {
529         return validateComponentType(componentType);
530     }
531
532     private void fillToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user,
533                                            UploadResourceInfo resourceInfo) {
534         if (resourceInfo.getPayloadData() == null || resourceInfo.getPayloadData().isEmpty()) {
535             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
536             Response errorResponse = buildErrorResponse(responseFormat);
537             getComponentsUtils().auditResource(responseFormat, user, resourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
538             responseWrapper.setInnerElement(errorResponse);
539         } else {
540             String toscaPayload = resourceInfo.getPayloadData();
541             String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
542             yamlStringWrapper.setInnerElement(decodedPayload);
543         }
544     }
545
546     void fillPayload(Wrapper<Response> responseWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper, Wrapper<String> yamlStringWrapper,
547                      User user, String resourceInfoJsonString, ResourceAuthorityTypeEnum resourceAuthorityEnum, File file) throws ZipException {
548         if (responseWrapper.isEmpty()) {
549             if (resourceAuthorityEnum.isBackEndImport()) {
550                 // PrePayload Validations
551                 if (responseWrapper.isEmpty()) {
552                     validateDataNotNull(responseWrapper, file, resourceInfoJsonString);
553                 }
554                 if (!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)) {
555                     if (responseWrapper.isEmpty()) {
556                         validateZip(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
557                     }
558                     // Fill PayLoad From File
559                     if (responseWrapper.isEmpty()) {
560                         fillToscaTemplateFromZip(yamlStringWrapper, uploadResourceInfoWrapper.getInnerElement().getPayloadName(), file);
561                     }
562                 } else {
563                     if (responseWrapper.isEmpty()) {
564                         validateCsar(responseWrapper, file, uploadResourceInfoWrapper.getInnerElement().getPayloadName());
565                     }
566                     // Fill PayLoad From File
567                     if (responseWrapper.isEmpty()) {
568                         fillPayloadDataFromFile(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), file);
569                     }
570                 }
571             } else {
572                 // Fill PayLoad From JSON
573                 if (responseWrapper.isEmpty()) {
574                     fillToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadResourceInfoWrapper.getInnerElement());
575                 }
576             }
577         }
578     }
579
580     protected void specificResourceAuthorityValidations(final Wrapper<Response> responseWrapper,
581                                                         final Wrapper<UploadResourceInfo> uploadResourceInfoWrapper,
582                                                         final Wrapper<String> yamlStringWrapper, final User user, final HttpServletRequest request,
583                                                         final String resourceInfoJsonString, final ResourceAuthorityTypeEnum resourceAuthorityEnum) {
584         if (responseWrapper.isEmpty()) {
585             // UI Only Validation
586             if (!resourceAuthorityEnum.isBackEndImport()) {
587                 importUIValidations(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, request, resourceInfoJsonString);
588             }
589             // User Defined Type Resources
590             if (resourceAuthorityEnum.isUserTypeResource() && !CsarValidationUtils
591                 .isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName()) && responseWrapper.isEmpty()) {
592                 validatePayloadNameSpace(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), user, yamlStringWrapper.getInnerElement());
593             }
594         }
595     }
596
597     void commonGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, Wrapper<UploadResourceInfo> uploadResourceInfoWrapper,
598                                   ResourceAuthorityTypeEnum resourceAuthorityEnum, String userId, String resourceInfoJsonString) {
599         if (responseWrapper.isEmpty()) {
600             validateUserExist(responseWrapper, userWrapper, userId);
601         }
602         if (responseWrapper.isEmpty()) {
603             validateUserRole(responseWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum);
604         }
605         if (responseWrapper.isEmpty()) {
606             validateAndFillResourceJson(responseWrapper, uploadResourceInfoWrapper, userWrapper.getInnerElement(), resourceAuthorityEnum,
607                 resourceInfoJsonString);
608         }
609         if (responseWrapper.isEmpty()) {
610             validateToscaTemplatePayloadName(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
611         }
612         if (responseWrapper.isEmpty()) {
613             validateResourceType(responseWrapper, uploadResourceInfoWrapper.getInnerElement(), userWrapper.getInnerElement());
614         }
615     }
616
617     private void validateResourceType(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) {
618         String resourceType = uploadResourceInfo.getResourceType();
619         if (resourceType == null || !ResourceTypeEnum.containsName(resourceType)) {
620             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
621             Response errorResponse = buildErrorResponse(responseFormat);
622             getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
623             responseWrapper.setInnerElement(errorResponse);
624         }
625     }
626
627     private void importUIValidations(Wrapper<Response> responseWrapper, UploadResourceInfo resourceInfo, User user, HttpServletRequest request,
628                                      String resourceInfoJsonString) {
629         if (responseWrapper.isEmpty()) {
630             validateMD5(responseWrapper, user, resourceInfo, request, resourceInfoJsonString);
631         }
632         if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
633             validateResourceDoesNotExist(responseWrapper, user, resourceInfo.getName());
634         }
635     }
636
637     void commonPayloadValidations(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user,
638                                   UploadResourceInfo uploadResourceInfo) {
639         if (responseWrapper.isEmpty()) {
640             validatePayloadIsYml(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
641         }
642         if (responseWrapper.isEmpty()) {
643             validatePayloadIsTosca(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
644         }
645         if (responseWrapper.isEmpty()) {
646             validatePayloadIsNotService(responseWrapper, user, uploadResourceInfo, yamlStringWrapper.getInnerElement());
647         }
648         if (responseWrapper.isEmpty()) {
649             validatePayloadIsSingleResource(responseWrapper, uploadResourceInfo, user, yamlStringWrapper.getInnerElement());
650         }
651     }
652
653     void handleImport(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfoObject, String yamlAsString,
654                       ResourceAuthorityTypeEnum authority, boolean createNewVersion, String resourceUniqueId) {
655         ImmutablePair<Resource, ActionStatus> createOrUpdateResponse = null;
656         Response response = null;
657         Object representation = null;
658         ImmutablePair<Resource, ActionStatus> importedResourceStatus = null;
659         if (CsarValidationUtils.isCsarPayloadName(resourceInfoObject.getPayloadName())) {
660             log.debug("import resource from csar");
661             importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
662         } else if (!authority.isUserTypeResource()) {
663             log.debug("import normative type resource");
664             createOrUpdateResponse =
665                 resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true, false);
666         } else {
667             log.debug("import user resource (not normative type)");
668             createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false);
669         }
670         if (createOrUpdateResponse != null) {
671             importedResourceStatus = createOrUpdateResponse;
672         }
673         if (importedResourceStatus != null) {
674             try {
675                 representation = RepresentationUtils.toRepresentation(importedResourceStatus.left);
676             } catch (IOException e) {
677                 log.debug("Error while building resource representation : {}", e.getMessage(), e);
678             }
679             response = buildOkResponse(getComponentsUtils().getResponseFormat(importedResourceStatus.right), representation);
680         }
681         responseWrapper.setInnerElement(response);
682     }
683
684     private ImmutablePair<Resource, ActionStatus> importResourceFromUICsar(UploadResourceInfo resourceInfoObject, User user,
685                                                                            String resourceUniqueId) {
686         Resource newResource;
687         ActionStatus actionStatus;
688         Resource resource = new Resource();
689         String payloadName = resourceInfoObject.getPayloadName();
690         fillResourceFromResourceInfoObject(resource, resourceInfoObject);
691         Map<String, byte[]> csarUIPayload = getCsarFromPayload(resourceInfoObject);
692         getAndValidateCsarYaml(csarUIPayload, resource, user, payloadName);
693         if (resourceUniqueId == null || resourceUniqueId.isEmpty()) {
694             newResource = resourceImportManager.getResourceBusinessLogic()
695                 .createResource(resource, AuditingActionEnum.CREATE_RESOURCE, user, csarUIPayload, payloadName);
696             actionStatus = ActionStatus.CREATED;
697         } else {
698             newResource = resourceImportManager.getResourceBusinessLogic()
699                 .validateAndUpdateResourceFromCsar(resource, user, csarUIPayload, payloadName, resourceUniqueId);
700             actionStatus = ActionStatus.OK;
701         }
702         return new ImmutablePair<>(newResource, actionStatus);
703     }
704
705     protected Resource throwComponentException(ResponseFormat responseFormat) {
706         throw new ByResponseFormatComponentException(responseFormat);
707     }
708
709     private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) {
710         getAndValidateComponentCsarYaml(csarUIPayload, resource, user, csarUUID);
711     }
712
713     private void getAndValidateComponentCsarYaml(Map<String, byte[]> csarUIPayload, Component component, User user, String csarUUID) {
714         Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils
715             .getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils(), null);
716         if (getToscaYamlRes.isRight()) {
717             ResponseFormat responseFormat = getToscaYamlRes.right().value();
718             log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat);
719             if (component instanceof Resource) {
720                 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed");
721                 getComponentsUtils().auditResource(responseFormat, user, (Resource) component, AuditingActionEnum.CREATE_RESOURCE);
722             } else {
723                 BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating service from CSAR: fetching CSAR with id " + csarUUID + " failed");
724             }
725             throwComponentException(responseFormat);
726         }
727         String toscaYaml = getToscaYamlRes.left().value().getValue();
728         log.debug("checking tosca template is valid yml");
729         YamlToObjectConverter yamlConvertor = new YamlToObjectConverter();
730         boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes());
731         if (!isValid) {
732             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE);
733             if (component instanceof Resource) {
734                 getComponentsUtils().auditResource(responseFormat, user, (Resource) component, AuditingActionEnum.IMPORT_RESOURCE);
735             }
736             throwComponentException(responseFormat);
737         }
738         log.debug("checking payload is valid tosca");
739         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaYaml);
740         Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils
741             .findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
742         if (findFirstToscaStringElement.isRight()) {
743             isValid = false;
744         } else {
745             String defenitionVersionFound = findFirstToscaStringElement.left().value();
746             if (defenitionVersionFound == null || defenitionVersionFound.isEmpty()) {
747                 isValid = false;
748             } else {
749                 isValid = TOSCA_DEFINITION_VERSIONS.contains(defenitionVersionFound);
750             }
751         }
752         if (!isValid) {
753             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE);
754             if (component instanceof Resource) {
755                 log.debug("enter getAndValidateComponentCsarYaml,component instanceof Resource");
756                 getComponentsUtils().auditResource(responseFormat, user, (Resource) component, AuditingActionEnum.IMPORT_RESOURCE);
757             }
758             throwComponentException(responseFormat);
759         }
760     }
761
762     private void fillResourceFromResourceInfoObject(Resource resource, UploadResourceInfo resourceInfoObject) {
763         resourceImportManager.populateResourceMetadata(resourceInfoObject, resource);
764         fillArtifacts(resource, resourceInfoObject);
765     }
766
767     private void fillArtifacts(Resource resource, UploadResourceInfo resourceInfoObject) {
768         if (resource != null && resourceInfoObject != null) {
769             List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList();
770             if (artifactList != null) {
771                 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
772                 buildArtifactsHM(artifactList, artifactsHM);
773                 resource.setArtifacts(artifactsHM);
774             }
775         }
776     }
777
778     private void buildArtifactsHM(List<UploadArtifactInfo> artifactList, Map<String, ArtifactDefinition> artifactsHM) {
779         for (UploadArtifactInfo artifact : artifactList) {
780             ArtifactDefinition artifactDef = new ArtifactDefinition();
781             artifactDef.setArtifactName(artifact.getArtifactName());
782             artifactDef.setArtifactType(artifact.getArtifactType().getType());
783             artifactDef.setDescription(artifact.getArtifactDescription());
784             artifactDef.setPayloadData(artifact.getArtifactData());
785             artifactDef.setArtifactRef(artifact.getArtifactPath());
786             artifactsHM.put(artifactDef.getArtifactName(), artifactDef);
787         }
788     }
789
790     private Map<String, byte[]> getCsarFromPayload(UploadResourceInfo innerElement) {
791         String csarUUID = innerElement.getPayloadName();
792         String payloadData = innerElement.getPayloadData();
793         return getComponentCsarFromPayload(csarUUID, payloadData);
794     }
795
796     private Map<String, byte[]> getComponentCsarFromPayload(String csarUUID, String payloadData) {
797         if (payloadData == null) {
798             log.info("Failed to decode received csar {}", csarUUID);
799             throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
800         }
801         byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
802         if (decodedPayload == null) {
803             log.info("Failed to decode received csar {}", csarUUID);
804             throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID);
805         }
806         Map<String, byte[]> csar = null;
807         try {
808             csar = ZipUtils.readZip(decodedPayload, false);
809         } catch (final ZipException e) {
810             log.info("Failed to unzip received csar {}", csarUUID, e);
811         }
812         return csar;
813     }
814
815     void validateInputStream(final HttpServletRequest request, Wrapper<String> dataWrapper, Wrapper<ResponseFormat> errorWrapper) throws IOException {
816         InputStream inputStream = request.getInputStream();
817         byte[] bytes = IOUtils.toByteArray(inputStream);
818         if (bytes == null || bytes.length == 0) {
819             log.info("Empty body was sent.");
820             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
821         } else {
822             dataWrapper.setInnerElement(new String(bytes, StandardCharsets.UTF_8));
823         }
824     }
825
826     <T> void validateClassParse(String data, Wrapper<T> parsedClassWrapper, Supplier<Class<T>> classGen, Wrapper<ResponseFormat> errorWrapper) {
827         try {
828             T parsedClass = gson.fromJson(data, classGen.get());
829             if (parsedClass == null) {
830                 errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
831             } else {
832                 parsedClassWrapper.setInnerElement(parsedClass);
833             }
834         } catch (JsonSyntaxException e) {
835             log.debug("Failed to decode received {} {} to object.", classGen.get().getName(), data, e);
836             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
837         }
838     }
839
840     void validateComponentInstanceBusinessLogic(HttpServletRequest request, String containerComponentType,
841                                                 Wrapper<ComponentInstanceBusinessLogic> blWrapper, Wrapper<ResponseFormat> errorWrapper) {
842         ServletContext context = request.getSession().getServletContext();
843         ComponentInstanceBusinessLogic componentInstanceLogic = getComponentInstanceBL(context);
844         if (componentInstanceLogic == null) {
845             log.debug("Unsupported component type {}", containerComponentType);
846             errorWrapper.setInnerElement(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
847         } else {
848             blWrapper.setInnerElement(componentInstanceLogic);
849         }
850     }
851
852     <T> Response buildResponseFromElement(Wrapper<ResponseFormat> errorWrapper, Wrapper<T> attributeWrapper) throws IOException {
853         Response response;
854         if (errorWrapper.isEmpty()) {
855             ObjectMapper mapper = new ObjectMapper();
856             String result = mapper.writeValueAsString(attributeWrapper.getInnerElement());
857             response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), result);
858         } else {
859             response = buildErrorResponse(errorWrapper.getInnerElement());
860         }
861         return response;
862     }
863
864     protected void validateXECOMPInstanceIDHeader(String instanceIdHeader, Wrapper<ResponseFormat> responseWrapper) {
865         ResponseFormat responseFormat;
866         if (StringUtils.isEmpty(instanceIdHeader)) {
867             log.debug("Missing X-ECOMP-InstanceID header");
868             responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID);
869             responseWrapper.setInnerElement(responseFormat);
870         }
871     }
872
873     protected void validateHttpCspUserIdHeader(String header, Wrapper<ResponseFormat> responseWrapper) {
874         ResponseFormat responseFormat;
875         if (StringUtils.isEmpty(header)) {
876             log.debug("MissingUSER_ID");
877             responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_USER_ID);
878             responseWrapper.setInnerElement(responseFormat);
879         }
880     }
881
882     <T> Either<T, ResponseFormat> parseToObject(String json, Supplier<Class<T>> classSupplier) {
883         try {
884             T object = RepresentationUtils.fromRepresentation(json, classSupplier.get());
885             return Either.left(object);
886         } catch (Exception e) {
887             log.debug("Failed to parse json to {} object", classSupplier.get().getName(), e);
888             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT);
889             return Either.right(responseFormat);
890         }
891     }
892
893     public <T> Either<List<T>, ResponseFormat> parseListOfObjects(String json, Type type) {
894         try {
895             List<T> listOfObjects = gson.fromJson(json, type);
896             return Either.left(listOfObjects);
897         } catch (Exception e) {
898             log.debug("Failed to parse json to {} object", type.getClass().getName(), e);
899             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
900             return Either.right(responseFormat);
901         }
902     }
903
904     protected void validateNotEmptyBody(String data) {
905         if (StringUtils.isEmpty(data)) {
906             throw new ByActionStatusComponentException(ActionStatus.MISSING_BODY);
907         }
908     }
909
910     protected void commonServiceGeneralValidations(Wrapper<Response> responseWrapper, Wrapper<User> userWrapper,
911                                                    Wrapper<UploadServiceInfo> uploadServiceInfoWrapper, ServiceAuthorityTypeEnum serviceAuthorityEnum,
912                                                    String userUserId, String serviceInfoJsonString) {
913         if (responseWrapper.isEmpty()) {
914             validateUserExist(responseWrapper, userWrapper, userUserId);
915         }
916         if (responseWrapper.isEmpty()) {
917             validateUserRole(responseWrapper, userWrapper.getInnerElement(), serviceAuthorityEnum);
918         }
919         if (responseWrapper.isEmpty()) {
920             validateAndFillServiceJson(responseWrapper, uploadServiceInfoWrapper, serviceAuthorityEnum,
921                 serviceInfoJsonString);
922         }
923         if (responseWrapper.isEmpty()) {
924             validateToscaTemplatePayloadName(responseWrapper, uploadServiceInfoWrapper.getInnerElement());
925         }
926     }
927
928     protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, ServiceAuthorityTypeEnum serviceAuthority) {
929         log.debug(VALIDATE_USER_ROLE);
930         if (serviceAuthority == ServiceAuthorityTypeEnum.NORMATIVE_TYPE_BE) {
931             if (!user.getRole().equals(Role.ADMIN.name())) {
932                 log.info(USER_IS_NOT_IN_APPROPRIATE_ROLE_TO_PERFORM_ACTION);
933                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION);
934                 log.debug(AUDIT_BEFORE_SENDING_RESPONSE);
935                 Response response = buildErrorResponse(responseFormat);
936                 errorResponseWrapper.setInnerElement(response);
937             }
938         } else {
939             validateUserRole(errorResponseWrapper, user);
940         }
941     }
942
943     protected void validateAndFillServiceJson(Wrapper<Response> responseWrapper, Wrapper<UploadServiceInfo> uploadServiceInfoWrapper,
944                                               ServiceAuthorityTypeEnum serviceAuthorityEnum, String serviceInfo) {
945         boolean isValid;
946         try {
947             log.debug("The received json is {}", serviceInfo);
948             UploadServiceInfo serviceInfoObject = gson.fromJson(serviceInfo, UploadServiceInfo.class);
949             if (serviceInfoObject == null) {
950                 isValid = false;
951             } else {
952                 if (!serviceAuthorityEnum.isBackEndImport()) {
953                     isValid = serviceInfoObject.getPayloadName() != null && !serviceInfoObject.getPayloadName().isEmpty();
954                     //only service name is checked
955                 } else {
956                     isValid = true;
957                 }
958                 uploadServiceInfoWrapper.setInnerElement(serviceInfoObject);
959                 log.debug("get isValid:{},serviceInfoObject get name:{},get tags:{},getContactId:{}," + " getPayloadName:{}", isValid,
960                     uploadServiceInfoWrapper.getInnerElement().getName(), uploadServiceInfoWrapper.getInnerElement().getTags(),
961                     uploadServiceInfoWrapper.getInnerElement().getContactId(), uploadServiceInfoWrapper.getInnerElement().getPayloadName());
962             }
963         } catch (JsonSyntaxException e) {
964             log.debug("enter validateAndFillServiceJson,Invalid json was received. {}", e.getMessage(), e);
965             isValid = false;
966         }
967         if (!isValid) {
968             log.info(INVALID_JSON_WAS_RECEIVED);
969             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
970             Response errorResp = buildErrorResponse(responseFormat);
971             responseWrapper.setInnerElement(errorResp);
972         }
973     }
974
975     protected void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadServiceInfo uploadServiceInfo) {
976         String toscaTemplatePayloadName = uploadServiceInfo.getPayloadName();
977         boolean isValidSuffix = isToscaTemplatePayloadNameValid(toscaTemplatePayloadName);
978         if (!isValidSuffix) {
979             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION);
980             Response errorResponse = buildErrorResponse(responseFormat);
981             responseWrapper.setInnerElement(errorResponse);
982         }
983     }
984
985     protected void specificServiceAuthorityValidations(Wrapper<Response> responseWrapper, Wrapper<UploadServiceInfo> uploadServiceInfoWrapper,
986                                                        Wrapper<String> yamlStringWrapper, HttpServletRequest request,
987                                                        String serviceInfoJsonString, ServiceAuthorityTypeEnum serviceAuthorityEnum) {
988         if (responseWrapper.isEmpty()) {
989             // UI Only Validation
990             if (!serviceAuthorityEnum.isBackEndImport()) {
991                 importUIValidations(responseWrapper, uploadServiceInfoWrapper.getInnerElement(), request, serviceInfoJsonString);
992             }
993             // User Defined Type Services
994             if (serviceAuthorityEnum.isUserTypeService()
995                 && !CsarValidationUtils.isCsarPayloadName(uploadServiceInfoWrapper.getInnerElement().getPayloadName())
996                 && responseWrapper.isEmpty()) {
997                 validatePayloadNameSpace(responseWrapper, uploadServiceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement());
998             }
999         }
1000     }
1001
1002     protected void importUIValidations(Wrapper<Response> responseWrapper, UploadServiceInfo serviceInfo, HttpServletRequest request,
1003                                        String serviceInfoJsonString) {
1004         if (responseWrapper.isEmpty()) {
1005             validateMD5(responseWrapper, request, serviceInfoJsonString);
1006         }
1007         if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod().equals("POST")) {
1008             validateServiceDoesNotExist(responseWrapper, serviceInfo.getName());
1009         }
1010     }
1011
1012     protected void validatePayloadNameSpace(Wrapper<Response> responseWrapper, UploadServiceInfo serviceInfo, String toscaPayload) {
1013         boolean isValid;
1014         String nameSpace = "";
1015         Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload);
1016         Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils
1017             .findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
1018         if (toscaElement.isRight() || toscaElement.left().value().size() != 1) {
1019             isValid = false;
1020         } else {
1021             nameSpace = toscaElement.left().value().keySet().iterator().next();
1022             isValid = nameSpace.startsWith(Constants.USER_DEFINED_SERVICE_NAMESPACE_PREFIX);
1023             log.debug("enter validatePayloadNameSpace,get nameSpace:{},get Valid is:{}", nameSpace, isValid);
1024         }
1025         if (!isValid) {
1026             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_SERVICE_NAMESPACE);
1027             Response errorResponse = buildErrorResponse(responseFormat);
1028             responseWrapper.setInnerElement(errorResponse);
1029         } else {
1030             String str1 = nameSpace.substring(Constants.USER_DEFINED_SERVICE_NAMESPACE_PREFIX.length());
1031             String[] findTypes = str1.split("\\.");
1032             if (ResourceTypeEnum.containsName(findTypes[0].toUpperCase())) {
1033                 String type = findTypes[0].toUpperCase();
1034                 serviceInfo.setServiceType(type);
1035             } else {
1036                 serviceInfo.setServiceType(ResourceTypeEnum.SERVICE.name());
1037             }
1038         }
1039     }
1040
1041     protected void validateMD5(Wrapper<Response> responseWrapper, HttpServletRequest request,
1042                                String serviceInfoJsonString) {
1043         boolean isValid;
1044         String recievedMD5 = request.getHeader(Constants.MD5_HEADER);
1045         if (recievedMD5 == null) {
1046             isValid = false;
1047         } else {
1048             String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(serviceInfoJsonString);
1049             isValid = calculateMD5.equals(recievedMD5);
1050         }
1051         if (!isValid) {
1052             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_SERVICE_CHECKSUM);
1053             Response errorResponse = buildErrorResponse(responseFormat);
1054             responseWrapper.setInnerElement(errorResponse);
1055         }
1056     }
1057
1058     protected void validateServiceDoesNotExist(Wrapper<Response> responseWrapper, String serviceName) {
1059         if (serviceImportManager.isServiceExist(serviceName)) {
1060             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.SERVICE_ALREADY_EXISTS);
1061             Response errorResponse = buildErrorResponse(responseFormat);
1062             responseWrapper.setInnerElement(errorResponse);
1063         }
1064     }
1065
1066     protected void handleImportService(Wrapper<Response> responseWrapper, User user, UploadServiceInfo serviceInfoObject) {
1067         Response response = null;
1068         ImmutablePair<Service, ActionStatus> importedServiceStatus = null;
1069         if (CsarValidationUtils.isCsarPayloadName(serviceInfoObject.getPayloadName())) {
1070             log.debug("import service from csar");
1071             importedServiceStatus = importServiceFromUICsar(serviceInfoObject, user);
1072         }
1073         if (importedServiceStatus != null) {
1074             Object representation = null;
1075             try {
1076                 representation = RepresentationUtils.toRepresentation(importedServiceStatus.left);
1077             } catch (IOException e) {
1078                 log.debug("Error while building service representation : {}", e.getMessage(), e);
1079             }
1080             response = buildOkResponse(getComponentsUtils().getResponseFormat(importedServiceStatus.right), representation);
1081         }
1082         responseWrapper.setInnerElement(response);
1083     }
1084
1085     private ImmutablePair<Service, ActionStatus> importServiceFromUICsar(UploadServiceInfo serviceInfoObject, User user) {
1086         Service service = new Service();
1087         String payloadName = serviceInfoObject.getPayloadName();
1088         fillServiceFromServiceInfoObject(service, serviceInfoObject);
1089         Map<String, byte[]> csarUIPayloadRes = getCsarFromPayload(serviceInfoObject);
1090         getAndValidateCsarYaml(csarUIPayloadRes, service, user, payloadName);
1091         final Service newService = serviceImportManager.getServiceImportBusinessLogic()
1092             .createService(service, AuditingActionEnum.CREATE_SERVICE, user, csarUIPayloadRes, payloadName);
1093         return new ImmutablePair<>(newService, ActionStatus.CREATED);
1094     }
1095
1096     private void fillServiceFromServiceInfoObject(Service service, UploadServiceInfo serviceInfoObject) {
1097         serviceImportManager.populateServiceMetadata(serviceInfoObject, service);
1098         fillArtifacts(service, serviceInfoObject);
1099     }
1100
1101     private Map<String, byte[]> getCsarFromPayload(UploadServiceInfo innerElement) {
1102         String csarUUID = innerElement.getPayloadName();
1103         String payloadData = innerElement.getPayloadData();
1104         return getComponentCsarFromPayload(csarUUID, payloadData);
1105     }
1106
1107     private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Service service, User user, String csarUUID) {
1108         getAndValidateComponentCsarYaml(csarUIPayload, service, user, csarUUID);
1109     }
1110
1111     private void fillArtifacts(Service service, UploadServiceInfo serviceInfoObject) {
1112         if (service != null && serviceInfoObject != null) {
1113             List<UploadArtifactInfo> artifactList = serviceInfoObject.getArtifactList();
1114             if (artifactList != null) {
1115                 Map<String, ArtifactDefinition> artifactsHM = new HashMap<>();
1116                 buildArtifactsHM(artifactList, artifactsHM);
1117                 service.setArtifacts(artifactsHM);
1118             }
1119         }
1120     }
1121
1122     /**
1123      * import service payload to postman
1124      *
1125      * @param responseWrapper
1126      * @param uploadServiceInfoWrapper
1127      * @param yamlStringWrapper
1128      * @param user
1129      * @param serviceInfoJsonString
1130      * @param serviceAuthorityEnum
1131      * @param file
1132      * @throws ZipException
1133      */
1134     protected void fillServicePayload(Wrapper<Response> responseWrapper, Wrapper<UploadServiceInfo> uploadServiceInfoWrapper,
1135                                       Wrapper<String> yamlStringWrapper, User user, String serviceInfoJsonString,
1136                                       ServiceAuthorityTypeEnum serviceAuthorityEnum, File file) throws ZipException {
1137         log.debug("enter fillServicePayload");
1138         if (responseWrapper.isEmpty()) {
1139             log.debug("enter fillServicePayload,get responseWrapper is empty");
1140             if (serviceAuthorityEnum.isBackEndImport()) {
1141                 // PrePayload Validations
1142                 if (responseWrapper.isEmpty()) {
1143                     validateDataNotNull(responseWrapper, file, serviceInfoJsonString);
1144                 }
1145                 if (responseWrapper.isEmpty()) {
1146                     log.debug("enter fillServicePayload,responseWrapper is empty");
1147                 }
1148                 if (!serviceAuthorityEnum.equals(ServiceAuthorityTypeEnum.CSAR_TYPE_BE)) {
1149                     if (responseWrapper.isEmpty()) {
1150                         validateZip(responseWrapper, file, uploadServiceInfoWrapper.getInnerElement().getPayloadName());
1151                     }
1152                     // Fill PayLoad From File
1153                     if (responseWrapper.isEmpty()) {
1154                         fillToscaTemplateFromZip(yamlStringWrapper, uploadServiceInfoWrapper.getInnerElement().getPayloadName(), file);
1155                     }
1156                 } else {
1157                     log.debug("enter fillServicePayload,ServiceAuthorityTypeEnum is CSAR_TYPE_BE");
1158                     if (responseWrapper.isEmpty()) {
1159                         validateCsar(responseWrapper, file, uploadServiceInfoWrapper.getInnerElement().getPayloadName());
1160                     }
1161                     if (!responseWrapper.isEmpty()) {
1162                         log.debug("enter fillServicePayload,get responseWrapper:{}", responseWrapper);
1163                     }
1164                     // Fill PayLoad From File
1165                     if (responseWrapper.isEmpty()) {
1166                         fillServicePayloadDataFromFile(responseWrapper, uploadServiceInfoWrapper.getInnerElement(), file);
1167                     }
1168                 }
1169             } else {
1170                 // Fill PayLoad From JSON
1171                 if (responseWrapper.isEmpty()) {
1172                     fillServiceToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadServiceInfoWrapper.getInnerElement());
1173                 }
1174             }
1175         }
1176     }
1177
1178     protected void fillServicePayloadDataFromFile(Wrapper<Response> responseWrapper, UploadServiceInfo uploadServiceInfoWrapper, File file) {
1179         try (InputStream fileInputStream = new FileInputStream(file)) {
1180             log.debug("enter fillServicePayloadDataFromFile");
1181             byte[] data = new byte[(int) file.length()];
1182             if (fileInputStream.read(data) == -1) {
1183                 log.info(INVALID_JSON_WAS_RECEIVED);
1184                 ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
1185                 Response errorResp = buildErrorResponse(responseFormat);
1186                 responseWrapper.setInnerElement(errorResp);
1187             }
1188             String payloadData = Base64.encodeBase64String(data);
1189             uploadServiceInfoWrapper.setPayloadData(payloadData);
1190             log.debug("enter fillServicePayloadDataFromFile,get payloadData:{}", uploadServiceInfoWrapper.getPayloadData());
1191             log.debug("enter fillServicePayloadDataFromFile,get uploadService:{}", uploadServiceInfoWrapper);
1192         } catch (IOException e) {
1193             log.info("Invalid json was received or Error while closing input Stream.");
1194             log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e);
1195             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT);
1196             Response errorResp = buildErrorResponse(responseFormat);
1197             responseWrapper.setInnerElement(errorResp);
1198         }
1199     }
1200
1201     private void fillServiceToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user,
1202                                                   UploadServiceInfo serviceInfo) {
1203         if (serviceInfo.getPayloadData() == null || serviceInfo.getPayloadData().isEmpty()) {
1204             ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD);
1205             Response errorResponse = buildErrorResponse(responseFormat);
1206             getComponentsUtils().auditResource(responseFormat, user, serviceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE);
1207             responseWrapper.setInnerElement(errorResponse);
1208         } else {
1209             String toscaPayload = serviceInfo.getPayloadData();
1210             String decodedPayload = new String(Base64.decodeBase64(toscaPayload));
1211             yamlStringWrapper.setInnerElement(decodedPayload);
1212         }
1213     }
1214 }