Fix zip slip security flaw 01/97301/4
authorandre.schmid <andre.schmid@est.tech>
Fri, 27 Sep 2019 12:27:11 +0000 (13:27 +0100)
committerOfir Sonsino <ofir.sonsino@intl.att.com>
Wed, 30 Oct 2019 09:47:54 +0000 (09:47 +0000)
Apply zip slip checking in zip operations throughout the system.
Centralizes most of the zip logic in one class. Create tests to zip
functionalities and zip slip problem.

Change-Id: I721f3d44b34fe6d242c9537f5a515ce1bb534c9a
Issue-ID: SDC-1401
Signed-off-by: andre.schmid <andre.schmid@est.tech>
44 files changed:
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java
catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
catalog-be/src/test/java/org/openecomp/sdc/ZipUtil.java [deleted file]
catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java
common-app-api/pom.xml
common-app-api/src/main/java/org/openecomp/sdc/common/util/ZipUtil.java [deleted file]
common-app-api/src/main/java/org/openecomp/sdc/common/zip/ZipUtils.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipException.java [new file with mode: 0644]
common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipSlipException.java [new file with mode: 0644]
common-app-api/src/test/java/org/openecomp/sdc/common/util/ZipUtilTest.java [deleted file]
common-app-api/src/test/java/org/openecomp/sdc/common/zip/ZipUtilsTest.java [new file with mode: 0644]
common-app-api/src/test/resources/zip-slip/zip-slip-linux.zip [new file with mode: 0644]
common-app-api/src/test/resources/zip-slip/zip-slip-windows.zip [new file with mode: 0644]
common-app-api/src/test/resources/zip/extract-test.zip [new file with mode: 0644]
common-be/pom.xml
common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java
openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vendor-software-products-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/data/PackageArchive.java
openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java
openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java
openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java
openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml
openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java
openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java
openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java
openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java
openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java
openecomp-be/lib/openecomp-sdc-vendor-software-product-lib/openecomp-sdc-vendor-software-product-core/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/services/impl/filedatastructuremodule/CandidateServiceImpl.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java
openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java
openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java
openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/util/ZipUtils.java [deleted file]
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java
test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java
test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java
ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java

index e008896..514576f 100644 (file)
@@ -42,12 +42,12 @@ import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response;
 import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
 import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
-import org.openecomp.sdc.be.components.impl.GroupBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ImportUtils;
 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
@@ -75,7 +75,8 @@ import org.openecomp.sdc.common.datastructure.Wrapper;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.GeneralUtility;
 import org.openecomp.sdc.common.util.YamlToObjectConverter;
-import org.openecomp.sdc.common.util.ZipUtil;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.yaml.snakeyaml.Yaml;
 
@@ -168,37 +169,76 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet {
 
     }
 
-    protected void validateZip(Wrapper<Response> responseWrapper, File file, String payloadName) {
-        Map<String, byte[]> unzippedFolder = ZipUtil.readZip(file);
-        if (payloadName == null || payloadName.isEmpty() || !unzippedFolder.containsKey(payloadName)) {
-            log.info("Invalid json was received. payloadName should be yml file name");
-            Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
+    protected void validateZip(final Wrapper<Response> responseWrapper, final File zipFile, final String payloadName) {
+        if (StringUtils.isEmpty(payloadName)) {
+            log.info("Invalid JSON was received. Payload name is empty");
+            final Response errorResponse =
+                buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
             responseWrapper.setInnerElement(errorResponse);
+            return;
         }
+        final Map<String, byte[]> unzippedFolder;
+        try {
+            unzippedFolder = ZipUtils.readZip(zipFile, false);
+        } catch (final ZipException e) {
+            log.error("Could not read ZIP file '{}' for validation", zipFile.getName(), e);
+            final Response errorResponse =
+                buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
+            responseWrapper.setInnerElement(errorResponse);
+            return;
+        }
+        if (!unzippedFolder.containsKey(payloadName)) {
+            log.info("Could no find payload '{}' in ZIP file '{}'", payloadName, zipFile.getName());
+            final Response errorResponse =
+                buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
+            responseWrapper.setInnerElement(errorResponse);
+        }
+
 
     }
-    protected void validateCsar(Wrapper<Response> responseWrapper, File file, String payloadName) {
-        Map<String, byte[]> unzippedFolder = ZipUtil.readZip(file);
-        if (payloadName == null || payloadName.isEmpty() || unzippedFolder.isEmpty()) {
-            log.info("Invalid json was received. payloadName should be yml file name");
+
+    protected void validateCsar(final Wrapper<Response> responseWrapper, final File csarFile, final String payloadName) {
+        if (StringUtils.isEmpty(payloadName)) {
+            log.info("Invalid JSON was received. Payload name is empty");
+            Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
+            responseWrapper.setInnerElement(errorResponse);
+            return;
+        }
+        final Map<String, byte[]> unzippedFolder;
+        try {
+            unzippedFolder = ZipUtils.readZip(csarFile, false);
+        } catch (final ZipException e) {
+            log.error("Could not read CSAR file '{}' for validation", csarFile.getName(), e);
+            final Response errorResponse =
+                buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
+            responseWrapper.setInnerElement(errorResponse);
+            return;
+        }
+        if (unzippedFolder.isEmpty()) {
+            log.info("The CSAR file is empty");
             Response errorResponse = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
             responseWrapper.setInnerElement(errorResponse);
         }
 
     }
 
-    protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) {
+    protected void fillZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
         extractZipContents(yamlStringWrapper, file);
     }
 
-    public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) {
-        Map<String, byte[]> unzippedFolder = ZipUtil.readZip(file);
+    public static void extractZipContents(Wrapper<String> yamlStringWrapper, File file) throws ZipException {
+        final Map<String, byte[]> unzippedFolder = ZipUtils.readZip(file, false);
         String ymlName = unzippedFolder.keySet().iterator().next();
         fillToscaTemplateFromZip(yamlStringWrapper, ymlName, file);
     }
 
     private static void fillToscaTemplateFromZip(Wrapper<String> yamlStringWrapper, String payloadName, File file) {
-        Map<String, byte[]> unzippedFolder = ZipUtil.readZip(file);
+        Map<String, byte[]> unzippedFolder = null;
+        try {
+            unzippedFolder = ZipUtils.readZip(file, false);
+        } catch (final ZipException e) {
+            log.info("Failed to unzip file", e);
+        }
         byte[] yamlFileInBytes = unzippedFolder.get(payloadName);
         String yamlAsString = new String(yamlFileInBytes, StandardCharsets.UTF_8);
         log.debug("received yaml: {}", yamlAsString);
@@ -738,19 +778,23 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet {
         String csarUUID = innerElement.getPayloadName();
         String payloadData = innerElement.getPayloadData();
         if (payloadData == null) {
-            log.info("Failed to decode received csar", csarUUID);
+            log.info("Failed to decode received csar {}", csarUUID);
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID));
         }
 
         byte[] decodedPayload = Base64.decodeBase64(payloadData.getBytes(StandardCharsets.UTF_8));
         if (decodedPayload == null) {
-            log.info("Failed to decode received csar", csarUUID);
+            log.info("Failed to decode received csar {}", csarUUID);
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_NOT_FOUND, csarUUID));
         }
 
-        Map<String, byte[]> csar = ZipUtil.readZip(decodedPayload);
-        if (csar == null) {
-            log.info("Failed to unzip received csar", csarUUID);
+        Map<String, byte[]> csar = null;
+        try {
+            csar = ZipUtils.readZip(decodedPayload, false);
+        } catch (final ZipException e) {
+            log.info("Failed to unzip received csar {}", csarUUID, e);
+        }
+        if (MapUtils.isEmpty(csar)) {
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.CSAR_INVALID, csarUUID));
         }
         return Either.left(csar);
index 3d7471e..bfd7ce7 100644 (file)
-/*-\r
- * ============LICENSE_START=======================================================\r
- * SDC\r
- * ================================================================================\r
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.\r
- * ================================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ============LICENSE_END=========================================================\r
- */\r
-\r
-package org.openecomp.sdc.be.servlets;\r
-\r
-import java.io.File;\r
-import javax.inject.Inject;\r
-import javax.inject.Singleton;\r
-import javax.servlet.http.HttpServletRequest;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.DefaultValue;\r
-import javax.ws.rs.HeaderParam;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.PathParam;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.QueryParam;\r
-import javax.ws.rs.core.Context;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-import org.glassfish.jersey.media.multipart.FormDataContentDisposition;\r
-import org.glassfish.jersey.media.multipart.FormDataParam;\r
-import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;\r
-import org.openecomp.sdc.be.components.impl.ResourceImportManager;\r
-import org.openecomp.sdc.be.config.BeEcompErrorManager;\r
-import org.openecomp.sdc.be.dao.api.ActionStatus;\r
-import org.openecomp.sdc.be.impl.ComponentsUtils;\r
-import org.openecomp.sdc.be.impl.ServletUtils;\r
-import org.openecomp.sdc.be.model.UploadResourceInfo;\r
-import org.openecomp.sdc.be.model.User;\r
-import org.openecomp.sdc.be.user.UserBusinessLogic;\r
-import org.openecomp.sdc.common.api.Constants;\r
-import org.openecomp.sdc.common.datastructure.Wrapper;\r
-import org.openecomp.sdc.common.log.wrappers.Logger;\r
-import com.jcabi.aspects.Loggable;\r
-import io.swagger.v3.oas.annotations.OpenAPIDefinition;\r
-import io.swagger.v3.oas.annotations.Operation;\r
-import io.swagger.v3.oas.annotations.Parameter;\r
-import io.swagger.v3.oas.annotations.info.Info;\r
-import io.swagger.v3.oas.annotations.media.ArraySchema;\r
-import io.swagger.v3.oas.annotations.media.Content;\r
-import io.swagger.v3.oas.annotations.media.Schema;\r
-import io.swagger.v3.oas.annotations.responses.ApiResponse;\r
-import io.swagger.v3.oas.annotations.responses.ApiResponses;\r
-/**\r
- * Root resource (exposed at "/" path)\r
- */\r
-@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)\r
-@Path("/v1/catalog/upload")\r
-@OpenAPIDefinition(info = @Info(title = "Resources Catalog Upload", description = "Upload resource yaml"))\r
-@Singleton\r
-public class ResourceUploadServlet extends AbstractValidationsServlet {\r
-\r
-    private static final Logger log = Logger.getLogger(ResourceUploadServlet.class);\r
-    public static final String NORMATIVE_TYPE_RESOURCE = "multipart";\r
-    public static final String CSAR_TYPE_RESOURCE = "csar";\r
-    public static final String USER_TYPE_RESOURCE = "user-resource";\r
-    public static final String USER_TYPE_RESOURCE_UI_IMPORT = "user-resource-ui-import";\r
-\r
-    @Inject\r
-    public ResourceUploadServlet(UserBusinessLogic userBusinessLogic,\r
-        ComponentInstanceBusinessLogic componentInstanceBL,\r
-        ComponentsUtils componentsUtils, ServletUtils servletUtils,\r
-        ResourceImportManager resourceImportManager) {\r
-        super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);\r
-    }\r
-\r
-    public enum ResourceAuthorityTypeEnum {\r
-        NORMATIVE_TYPE_BE(NORMATIVE_TYPE_RESOURCE, true, false), USER_TYPE_BE(USER_TYPE_RESOURCE, true,\r
-                true), USER_TYPE_UI(USER_TYPE_RESOURCE_UI_IMPORT, false,\r
-                        true), CSAR_TYPE_BE(CSAR_TYPE_RESOURCE, true, true);\r
-\r
-        private String urlPath;\r
-        private boolean isBackEndImport, isUserTypeResource;\r
-\r
-        public static ResourceAuthorityTypeEnum findByUrlPath(String urlPath) {\r
-            ResourceAuthorityTypeEnum found = null;\r
-            for (ResourceAuthorityTypeEnum curr : ResourceAuthorityTypeEnum.values()) {\r
-                if (curr.getUrlPath().equals(urlPath)) {\r
-                    found = curr;\r
-                    break;\r
-                }\r
-            }\r
-            return found;\r
-        }\r
-\r
-        private ResourceAuthorityTypeEnum(String urlPath, boolean isBackEndImport, boolean isUserTypeResource) {\r
-            this.urlPath = urlPath;\r
-            this.isBackEndImport = isBackEndImport;\r
-            this.isUserTypeResource = isUserTypeResource;\r
-        }\r
-\r
-        public String getUrlPath() {\r
-            return urlPath;\r
-        }\r
-\r
-        public boolean isBackEndImport() {\r
-            return isBackEndImport;\r
-        }\r
-\r
-        public boolean isUserTypeResource() {\r
-            return isUserTypeResource;\r
-        }\r
-    }\r
-\r
-    @POST\r
-    @Path("/{resourceAuthority}")\r
-    @Consumes(MediaType.MULTIPART_FORM_DATA)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    @Operation(description = "Create Resource from yaml", method = "POST", summary = "Returns created resource",\r
-            responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource created"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation"),\r
-            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),\r
-            @ApiResponse(responseCode = "409", description = "Resource already exist")})\r
-    public Response uploadMultipart(\r
-            @Parameter(description = "validValues: normative-resource / user-resource",\r
-                    schema = @Schema(allowableValues = {NORMATIVE_TYPE_RESOURCE ,\r
-                            USER_TYPE_RESOURCE,USER_TYPE_RESOURCE_UI_IMPORT})) @PathParam(\r
-                                    value = "resourceAuthority") final String resourceAuthority,\r
-            @Parameter(description = "FileInputStream") @FormDataParam("resourceZip") File file,\r
-            @Parameter(description = "ContentDisposition") @FormDataParam("resourceZip") FormDataContentDisposition contentDispositionHeader,\r
-            @Parameter(description = "resourceMetadata") @FormDataParam("resourceMetadata") String resourceInfoJsonString,\r
-            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,\r
-            // updateResourse Query Parameter if false checks if already exist\r
-            @DefaultValue("true") @QueryParam("createNewVersion") boolean createNewVersion) {\r
-\r
-        try {\r
-\r
-            Wrapper<Response> responseWrapper = new Wrapper<>();\r
-            Wrapper<User> userWrapper = new Wrapper<>();\r
-            Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();\r
-            Wrapper<String> yamlStringWrapper = new Wrapper<>();\r
-\r
-            String url = request.getMethod() + " " + request.getRequestURI();\r
-            log.debug("Start handle request of {}", url);\r
-\r
-            // When we get an errorResponse it will be filled into the\r
-            // responseWrapper\r
-            validateAuthorityType(responseWrapper, resourceAuthority);\r
-\r
-            ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.findByUrlPath(resourceAuthority);\r
-\r
-            commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, resourceInfoJsonString);\r
-\r
-            fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), resourceInfoJsonString, resourceAuthorityEnum, file);\r
-\r
-            // PayLoad Validations\r
-            if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){\r
-                commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());\r
-\r
-                specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, resourceInfoJsonString, resourceAuthorityEnum);\r
-            }\r
-\r
-            if (responseWrapper.isEmpty()) {\r
-                handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, createNewVersion, null);\r
-            }\r
-\r
-            return responseWrapper.getInnerElement();\r
-\r
-        } catch (Exception e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Upload Resource");\r
-            log.debug("upload resource failed with exception", e);\r
-            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-        }\r
-    }\r
-\r
-    /********************************************************************************************************************/\r
-}\r
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.servlets;
+
+import java.io.File;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ResourceImportManager;
+import org.openecomp.sdc.be.config.BeEcompErrorManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.impl.ServletUtils;
+import org.openecomp.sdc.be.model.UploadResourceInfo;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.user.UserBusinessLogic;
+import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.common.datastructure.Wrapper;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import com.jcabi.aspects.Loggable;
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+/**
+ * Root resource (exposed at "/" path)
+ */
+@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
+@Path("/v1/catalog/upload")
+@OpenAPIDefinition(info = @Info(title = "Resources Catalog Upload", description = "Upload resource yaml"))
+@Singleton
+public class ResourceUploadServlet extends AbstractValidationsServlet {
+
+    private static final Logger log = Logger.getLogger(ResourceUploadServlet.class);
+    public static final String NORMATIVE_TYPE_RESOURCE = "multipart";
+    public static final String CSAR_TYPE_RESOURCE = "csar";
+    public static final String USER_TYPE_RESOURCE = "user-resource";
+    public static final String USER_TYPE_RESOURCE_UI_IMPORT = "user-resource-ui-import";
+
+    @Inject
+    public ResourceUploadServlet(UserBusinessLogic userBusinessLogic,
+        ComponentInstanceBusinessLogic componentInstanceBL,
+        ComponentsUtils componentsUtils, ServletUtils servletUtils,
+        ResourceImportManager resourceImportManager) {
+        super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
+    }
+
+    public enum ResourceAuthorityTypeEnum {
+        NORMATIVE_TYPE_BE(NORMATIVE_TYPE_RESOURCE, true, false), USER_TYPE_BE(USER_TYPE_RESOURCE, true,
+                true), USER_TYPE_UI(USER_TYPE_RESOURCE_UI_IMPORT, false,
+                        true), CSAR_TYPE_BE(CSAR_TYPE_RESOURCE, true, true);
+
+        private String urlPath;
+        private boolean isBackEndImport, isUserTypeResource;
+
+        public static ResourceAuthorityTypeEnum findByUrlPath(String urlPath) {
+            ResourceAuthorityTypeEnum found = null;
+            for (ResourceAuthorityTypeEnum curr : ResourceAuthorityTypeEnum.values()) {
+                if (curr.getUrlPath().equals(urlPath)) {
+                    found = curr;
+                    break;
+                }
+            }
+            return found;
+        }
+
+        private ResourceAuthorityTypeEnum(String urlPath, boolean isBackEndImport, boolean isUserTypeResource) {
+            this.urlPath = urlPath;
+            this.isBackEndImport = isBackEndImport;
+            this.isUserTypeResource = isUserTypeResource;
+        }
+
+        public String getUrlPath() {
+            return urlPath;
+        }
+
+        public boolean isBackEndImport() {
+            return isBackEndImport;
+        }
+
+        public boolean isUserTypeResource() {
+            return isUserTypeResource;
+        }
+    }
+
+    @POST
+    @Path("/{resourceAuthority}")
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(description = "Create Resource from yaml", method = "POST", summary = "Returns created resource",
+            responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource created"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+            @ApiResponse(responseCode = "409", description = "Resource already exist")})
+    public Response uploadMultipart(
+            @Parameter(description = "validValues: normative-resource / user-resource",
+                    schema = @Schema(allowableValues = {NORMATIVE_TYPE_RESOURCE ,
+                            USER_TYPE_RESOURCE,USER_TYPE_RESOURCE_UI_IMPORT})) @PathParam(
+                                    value = "resourceAuthority") final String resourceAuthority,
+            @Parameter(description = "FileInputStream") @FormDataParam("resourceZip") File file,
+            @Parameter(description = "ContentDisposition") @FormDataParam("resourceZip") FormDataContentDisposition contentDispositionHeader,
+            @Parameter(description = "resourceMetadata") @FormDataParam("resourceMetadata") String resourceInfoJsonString,
+            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
+            // updateResourse Query Parameter if false checks if already exist
+            @DefaultValue("true") @QueryParam("createNewVersion") boolean createNewVersion) {
+
+        try {
+
+            Wrapper<Response> responseWrapper = new Wrapper<>();
+            Wrapper<User> userWrapper = new Wrapper<>();
+            Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
+            Wrapper<String> yamlStringWrapper = new Wrapper<>();
+
+            String url = request.getMethod() + " " + request.getRequestURI();
+            log.debug("Start handle request of {}", url);
+
+            // When we get an errorResponse it will be filled into the
+            // responseWrapper
+            validateAuthorityType(responseWrapper, resourceAuthority);
+
+            ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.findByUrlPath(resourceAuthority);
+
+            commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, resourceInfoJsonString);
+
+            fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), resourceInfoJsonString, resourceAuthorityEnum, file);
+
+            // PayLoad Validations
+            if(!resourceAuthorityEnum.equals(ResourceAuthorityTypeEnum.CSAR_TYPE_BE)){
+                commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());
+
+                specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, resourceInfoJsonString, resourceAuthorityEnum);
+            }
+
+            if (responseWrapper.isEmpty()) {
+                handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, createNewVersion, null);
+            }
+
+            return responseWrapper.getInnerElement();
+
+        } catch (Exception e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Upload Resource");
+            log.debug("upload resource failed with exception", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
+}
index 415fdcf..03bed47 100644 (file)
-/*-\r
- * ============LICENSE_START=======================================================\r
- * SDC\r
- * ================================================================================\r
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.\r
- * ================================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ============LICENSE_END=========================================================\r
- */\r
-\r
-package org.openecomp.sdc.be.servlets;\r
-\r
-import com.jcabi.aspects.Loggable;\r
-import fj.data.Either;\r
-import javax.inject.Inject;\r
-import org.apache.http.HttpStatus;\r
-import org.json.JSONException;\r
-import org.json.JSONObject;\r
-import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;\r
-import org.openecomp.sdc.be.components.impl.CsarValidationUtils;\r
-import org.openecomp.sdc.be.components.impl.GroupBusinessLogic;\r
-import org.openecomp.sdc.be.components.impl.ImportUtils;\r
-import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;\r
-import org.openecomp.sdc.be.components.impl.ResourceImportManager;\r
-import org.openecomp.sdc.be.config.BeEcompErrorManager;\r
-import org.openecomp.sdc.be.dao.api.ActionStatus;\r
-import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;\r
-import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;\r
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;\r
-import org.openecomp.sdc.be.impl.ComponentsUtils;\r
-import org.openecomp.sdc.be.impl.ServletUtils;\r
-import org.openecomp.sdc.be.model.Product;\r
-import org.openecomp.sdc.be.model.Resource;\r
-import org.openecomp.sdc.be.model.UploadResourceInfo;\r
-import org.openecomp.sdc.be.model.User;\r
-import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;\r
-import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;\r
-import org.openecomp.sdc.be.user.UserBusinessLogic;\r
-import org.openecomp.sdc.common.api.Constants;\r
-import org.openecomp.sdc.common.datastructure.Wrapper;\r
-import org.openecomp.sdc.common.log.wrappers.Logger;\r
-import org.openecomp.sdc.exception.ResponseFormat;\r
-import io.swagger.v3.oas.annotations.OpenAPIDefinition;\r
-import io.swagger.v3.oas.annotations.Operation;\r
-import io.swagger.v3.oas.annotations.Parameter;\r
-import io.swagger.v3.oas.annotations.info.Info;\r
-import io.swagger.v3.oas.annotations.media.ArraySchema;\r
-import io.swagger.v3.oas.annotations.media.Content;\r
-import io.swagger.v3.oas.annotations.media.Schema;\r
-import io.swagger.v3.oas.annotations.responses.ApiResponse;\r
-import io.swagger.v3.oas.annotations.responses.ApiResponses;\r
-import javax.inject.Singleton;\r
-import javax.servlet.ServletContext;\r
-import javax.servlet.http.HttpServletRequest;\r
-import javax.ws.rs.*;\r
-import javax.ws.rs.core.Context;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-import java.io.FileNotFoundException;\r
-import java.io.IOException;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)\r
-@Path("/v1/catalog")\r
-@OpenAPIDefinition(info = @Info(title = "Resources Catalog", description = "Resources Servlet"))\r
-@Singleton\r
-public class ResourcesServlet extends AbstractValidationsServlet {\r
-\r
-    private static final Logger log = Logger.getLogger(ResourcesServlet.class);\r
-    private final ResourceBusinessLogic resourceBusinessLogic;\r
-\r
-    @Inject\r
-    public ResourcesServlet(UserBusinessLogic userBusinessLogic,\r
-        ComponentInstanceBusinessLogic componentInstanceBL,\r
-        ResourceBusinessLogic resourceBusinessLogic,\r
-        ComponentsUtils componentsUtils, ServletUtils servletUtils,\r
-        ResourceImportManager resourceImportManager) {\r
-        super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);\r
-        this.resourceBusinessLogic = resourceBusinessLogic;\r
-    }\r
-\r
-    @POST\r
-    @Path("/resources")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    @Operation(description = "Create Resource", method = "POST", summary = "Returns created resource",\r
-            responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource created"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation"),\r
-            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),\r
-            @ApiResponse(responseCode = "409", description = "Resource already exist")})\r
-    public Response createResource(@Parameter(description = "Resource object to be created", required = true) String data,\r
-            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {\r
-\r
-        userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);\r
-        init();\r
-\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("Start handle request of {}" , url);\r
-\r
-        // get modifier id\r
-        User modifier = new User();\r
-        modifier.setUserId(userId);\r
-        log.debug("modifier id is {}", userId);\r
-\r
-        Response response;\r
-        try {\r
-\r
-            Wrapper<Response> responseWrapper = new Wrapper<>();\r
-            // UI Import\r
-            if (isUIImport(data)) {\r
-                performUIImport(responseWrapper, data, request, userId, null);\r
-            }\r
-            // UI Create\r
-            else {\r
-\r
-                Either<Resource, ResponseFormat> convertResponse = parseToResource(data, modifier);\r
-                if (convertResponse.isRight()) {\r
-                    log.debug("failed to parse resource");\r
-                    response = buildErrorResponse(convertResponse.right().value());\r
-                    return response;\r
-                }\r
-\r
-                Resource resource = convertResponse.left().value();\r
-                Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);\r
-                Object representation = RepresentationUtils.toRepresentation(createdResource);\r
-                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);\r
-                responseWrapper.setInnerElement(response);\r
-            }\r
-            return responseWrapper.getInnerElement();\r
-        } catch (IOException e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Resource");\r
-            log.debug("create resource failed with exception", e);\r
-            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-            return response;\r
-        }\r
-    }\r
-\r
-    private boolean isUIImport(String data) {\r
-        boolean isUIImport;\r
-        try {\r
-            JSONObject json = new JSONObject(data);\r
-            String payloadName = json.getString(ImportUtils.Constants.UI_JSON_PAYLOAD_NAME);\r
-            isUIImport = payloadName != null && !payloadName.isEmpty();\r
-        } catch (JSONException e) {\r
-            log.debug("failed to parse json sent from client, json:{}", data, e);\r
-            isUIImport = false;\r
-        }\r
-        return isUIImport;\r
-    }\r
-\r
-    private void performUIImport(Wrapper<Response> responseWrapper, String data, final HttpServletRequest request, String userId, String resourceUniqueId) throws FileNotFoundException {\r
-\r
-        Wrapper<User> userWrapper = new Wrapper<>();\r
-        Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();\r
-        Wrapper<String> yamlStringWrapper = new Wrapper<>();\r
-\r
-        ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.USER_TYPE_UI;\r
-\r
-        commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, data);\r
-\r
-        if (!CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {\r
-            fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), data, resourceAuthorityEnum, null);\r
-\r
-            // PayLoad Validations\r
-            commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());\r
-        }\r
-        specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, data, resourceAuthorityEnum);\r
-\r
-        if (responseWrapper.isEmpty()) {\r
-            handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, true, resourceUniqueId);\r
-        }\r
-    }\r
-\r
-    private Either<Resource, ResponseFormat> parseToResource(String resourceJson, User user) {\r
-        return getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.RESOURCE);\r
-    }\r
-\r
-    private Either<Resource, ResponseFormat> parseToLightResource(String resourceJson, User user) {\r
-        Either<Resource, ResponseFormat> ret = getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);\r
-        if (ret.isLeft()) {// drop unwanted data (sent from UI in update flow)\r
-            ret.left().value().setRequirements(null);\r
-            ret.left().value().setCapabilities(null);\r
-        }\r
-        return ret;\r
-    }\r
-\r
-    @DELETE\r
-    @Path("/resources/{resourceId}")\r
-    public Response deleteResource(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request) {\r
-\r
-        ServletContext context = request.getSession().getServletContext();\r
-\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("Start handle request of {}" , url);\r
-\r
-        // get modifier id\r
-        String userId = request.getHeader(Constants.USER_ID_HEADER);\r
-        User modifier = new User();\r
-        modifier.setUserId(userId);\r
-        log.debug("modifier id is {}" , userId);\r
-\r
-        Response response;\r
-\r
-        try {\r
-            String resourceIdLower = resourceId.toLowerCase();\r
-            ResponseFormat actionResponse = resourceBusinessLogic.deleteResource(resourceIdLower, modifier);\r
-\r
-            if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {\r
-                log.debug("failed to delete resource");\r
-                response = buildErrorResponse(actionResponse);\r
-                return response;\r
-            }\r
-            response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);\r
-            return response;\r
-\r
-        } catch (JSONException e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource");\r
-            log.debug("delete resource failed with exception", e);\r
-            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-            return response;\r
-\r
-        }\r
-    }\r
-\r
-    @DELETE\r
-    @Path("/resources/{resourceName}/{version}")\r
-    public Response deleteResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("version") final String version, @Context final HttpServletRequest request) {\r
-\r
-        ServletContext context = request.getSession().getServletContext();\r
-\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("Start handle request of {}" , url);\r
-\r
-        // get modifier id\r
-        String userId = request.getHeader(Constants.USER_ID_HEADER);\r
-        User modifier = new User();\r
-        modifier.setUserId(userId);\r
-        log.debug("modifier id is {}" , userId);\r
-\r
-        Response response;\r
-        ResponseFormat actionResponse = resourceBusinessLogic.deleteResourceByNameAndVersion(resourceName, version, modifier);\r
-\r
-        if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {\r
-            log.debug("failed to delete resource");\r
-            response = buildErrorResponse(actionResponse);\r
-            return response;\r
-        }\r
-        response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);\r
-        return response;\r
-    }\r
-\r
-    @GET\r
-    @Path("/resources/{resourceId}")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    @Operation(description = "Retrieve Resource", method = "GET", summary = "Returns resource according to resourceId",\r
-            responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation"),\r
-            @ApiResponse(responseCode = "404", description = "Resource not found")})\r
-    public Response getResourceById(@PathParam("resourceId") final String resourceId,\r
-            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {\r
-\r
-        ServletContext context = request.getSession().getServletContext();\r
-\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("Start handle request of {}" , url);\r
-\r
-        // get modifier id\r
-        User modifier = new User();\r
-        modifier.setUserId(userId);\r
-        log.debug("modifier id is {}" , userId);\r
-\r
-        Response response;\r
-\r
-        try {\r
-            String resourceIdLower = resourceId.toLowerCase();\r
-            log.trace("get resource with id {}", resourceId);\r
-            Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResource(resourceIdLower, modifier);\r
-\r
-            if (actionResponse.isRight()) {\r
-                log.debug("failed to get resource");\r
-                response = buildErrorResponse(actionResponse.right().value());\r
-                return response;\r
-            }\r
-            Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());\r
-            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);\r
-\r
-        } catch (IOException e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource");\r
-            log.debug("get resource failed with exception", e);\r
-            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-\r
-        }\r
-    }\r
-\r
-    @GET\r
-    @Path("/resources/resourceName/{resourceName}/resourceVersion/{resourceVersion}")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    @Operation(description = "Retrieve Resource by name and version", method = "GET",\r
-            summary = "Returns resource according to resourceId", responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation"),\r
-            @ApiResponse(responseCode = "404", description = "Resource not found")})\r
-    public Response getResourceByNameAndVersion(@PathParam("resourceName") final String resourceName,\r
-            @PathParam("resourceVersion") final String resourceVersion, @Context final HttpServletRequest request,\r
-            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {\r
-\r
-        ServletContext context = request.getSession().getServletContext();\r
-        // get modifier id\r
-        User modifier = new User();\r
-        modifier.setUserId(userId);\r
-        log.debug("modifier id is {}" , userId);\r
-        Response response;\r
-        try {\r
-            Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResourceByNameAndVersion(resourceName, resourceVersion, userId);\r
-            if (actionResponse.isRight()) {\r
-                response = buildErrorResponse(actionResponse.right().value());\r
-                return response;\r
-            }\r
-            Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());\r
-            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);\r
-\r
-        } catch (IOException e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource by name and version");\r
-            log.debug("get resource failed with exception", e);\r
-            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-\r
-        }\r
-    }\r
-\r
-    @GET\r
-    @Path("/resources/validate-name/{resourceName}")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    @Operation(description = "validate resource name", method = "GET",\r
-            summary = "checks if the chosen resource name is available ", responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation")})\r
-    public Response validateResourceName(@PathParam("resourceName") final String resourceName,\r
-            @QueryParam("subtype") String resourceType, @Context final HttpServletRequest request,\r
-            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {\r
-        ServletContext context = request.getSession().getServletContext();\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("Start handle request of {}" , url);\r
-\r
-        // get modifier id\r
-        User modifier = new User();\r
-        modifier.setUserId(userId);\r
-        log.debug("modifier id is {}" , userId);\r
-        Response response;\r
-\r
-        if (resourceType != null && !ResourceTypeEnum.containsName(resourceType)) {\r
-            log.debug("invalid resource type received");\r
-            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));\r
-            return response;\r
-\r
-        }\r
-        ResourceTypeEnum typeEnum = null;\r
-        if (resourceType != null) {\r
-            typeEnum = ResourceTypeEnum.valueOf(resourceType);\r
-        }\r
-        Either<Map<String, Boolean>, ResponseFormat> actionResponse = resourceBusinessLogic.validateResourceNameExists(resourceName, typeEnum, userId);\r
-\r
-        if (actionResponse.isRight()) {\r
-            log.debug("failed to validate resource name");\r
-            response = buildErrorResponse(actionResponse.right().value());\r
-            return response;\r
-        }\r
-        return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());\r
-    }\r
-\r
-    @GET\r
-    @Path("/resources/certified/abstract")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    public Response getCertifiedAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("(get) Start handle request of {}" , url);\r
-        try {\r
-            List<Resource> resources = resourceBusinessLogic\r
-                    .getAllCertifiedResources(true, HighestFilterEnum.HIGHEST_ONLY, userId);\r
-            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resources));\r
-\r
-        } catch (IOException e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Abstract Resources");\r
-            log.debug("getCertifiedAbstractResources failed with exception", e);\r
-            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-        }\r
-    }\r
-\r
-    @GET\r
-    @Path("/resources/certified/notabstract")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    public Response getCertifiedNotAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("(get) Start handle request of {}" , url);\r
-        try {\r
-            List<Resource> resouces = resourceBusinessLogic.getAllCertifiedResources(false, HighestFilterEnum.ALL, userId);\r
-            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resouces));\r
-\r
-        } catch (IOException e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Non Abstract Resources");\r
-            log.debug("getCertifiedNotAbstractResources failed with exception", e);\r
-            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-        }\r
-\r
-    }\r
-\r
-    @PUT\r
-    @Path("/resources/{resourceId}/metadata")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    @Operation(description = "Update Resource Metadata", method = "PUT", summary = "Returns updated resource metadata",\r
-            responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource metadata updated"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation"),\r
-            @ApiResponse(responseCode = "400", description = "Invalid content")})\r
-    public Response updateResourceMetadata(@PathParam("resourceId") final String resourceId,\r
-            @Parameter(description = "Resource metadata to be updated", required = true) String data,\r
-            @Context final HttpServletRequest request,       @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {\r
-\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("Start handle request of {}" , url);\r
-\r
-        // get modifier id\r
-        User modifier = new User();\r
-        modifier.setUserId(userId);\r
-        log.debug("modifier id is {}", userId);\r
-        Response response;\r
-        try {\r
-            String resourceIdLower = resourceId.toLowerCase();\r
-            Either<Resource, ResponseFormat> updateInfoResource = getComponentsUtils().convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);\r
-            if (updateInfoResource.isRight()) {\r
-                log.debug("failed to parse resource metadata");\r
-                response = buildErrorResponse(updateInfoResource.right().value());\r
-                return response;\r
-            }\r
-            Resource updatedResource = resourceBusinessLogic.updateResourceMetadata(resourceIdLower, updateInfoResource.left().value(), null, modifier, false);\r
-            Object resource = RepresentationUtils.toRepresentation(updatedResource);\r
-            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);\r
-        } catch (IOException e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource Metadata");\r
-            log.debug("Update Resource Metadata failed with exception", e);\r
-            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-            return response;\r
-\r
-        }\r
-    }\r
-\r
-    @PUT\r
-    @Path("/resources/{resourceId}")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    @Operation(description = "Update Resource", method = "PUT", summary = "Returns updated resource",\r
-            responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource updated"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation"),\r
-            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),\r
-            @ApiResponse(responseCode = "409", description = "Resource already exist")})\r
-    public Response updateResource(\r
-            @Parameter(description = "Resource object to be updated", required = true) String data,\r
-            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,\r
-            @PathParam(value = "resourceId") String resourceId) {\r
-\r
-        userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);\r
-        init();\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("Start handle request of {}", url);\r
-        // get modifier id\r
-        User modifier = new User();\r
-        modifier.setUserId(userId);\r
-        log.debug("modifier id is {}", userId);\r
-        Response response;\r
-        try {\r
-            Wrapper<Response> responseWrapper = new Wrapper<>();\r
-            // UI Import\r
-            if (isUIImport(data)) {\r
-                performUIImport(responseWrapper, data, request, userId, resourceId);\r
-            } else {\r
-                Either<Resource, ResponseFormat> convertResponse = parseToLightResource(data, modifier);\r
-                if (convertResponse.isRight()) {\r
-                    log.debug("failed to parse resource");\r
-                    response = buildErrorResponse(convertResponse.right().value());\r
-                    return response;\r
-                }\r
-                Resource updatedResource = resourceBusinessLogic.validateAndUpdateResourceFromCsar(\r
-                        convertResponse.left().value(), modifier, null, null, resourceId);\r
-                Object representation = RepresentationUtils.toRepresentation(updatedResource);\r
-                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);\r
-                responseWrapper.setInnerElement(response);\r
-            }\r
-            return responseWrapper.getInnerElement();\r
-        } catch (IOException e) {\r
-            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource");\r
-            log.debug("update resource failed with exception", e);\r
-            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-            return response;\r
-\r
-        }\r
-    }\r
-\r
-    @GET\r
-    @Path("/resources/csar/{csaruuid}")\r
-    @Consumes(MediaType.APPLICATION_JSON)\r
-    @Produces(MediaType.APPLICATION_JSON)\r
-    @Operation(description = "Create Resource", method = "POST", summary = "Returns resource created from csar uuid",\r
-            responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource retrieced"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation"),\r
-            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})\r
-    public Response getResourceFromCsar(@Context final HttpServletRequest request,\r
-            @HeaderParam(value = Constants.USER_ID_HEADER) String userId,\r
-            @PathParam(value = "csaruuid") String csarUUID) {\r
-\r
-        init();\r
-\r
-        String url = request.getMethod() + " " + request.getRequestURI();\r
-        log.debug("Start handle request of {}", url);\r
-\r
-        // retrieve user details\r
-        userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);\r
-        User user = new User();\r
-        user.setUserId(userId);\r
-\r
-        log.debug("user id is {}", userId);\r
-\r
-        Response response;\r
-\r
-        try {\r
-\r
-            Either<Resource, ResponseFormat> eitherResource =\r
-                    resourceBusinessLogic.getLatestResourceFromCsarUuid(csarUUID, user);\r
-\r
-            // validate response\r
-            if (eitherResource.isRight()) {\r
-                log.debug("failed to get resource from csarUuid : {}", csarUUID);\r
-                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),\r
-                        eitherResource.right().value());\r
-            } else {\r
-                Object representation = RepresentationUtils.toRepresentation(eitherResource.left().value());\r
-                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);\r
-            }\r
-\r
-            return response;\r
-\r
-        } catch (IOException e) {\r
-            log.debug("get resource by csar failed with exception", e);\r
-            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));\r
-            return response;\r
-        }\r
-    }\r
-}\r
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.servlets;
+
+import com.jcabi.aspects.Loggable;
+import fj.data.Either;
+import javax.inject.Inject;
+import org.apache.http.HttpStatus;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
+import org.openecomp.sdc.be.components.impl.CsarValidationUtils;
+import org.openecomp.sdc.be.components.impl.ImportUtils;
+import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
+import org.openecomp.sdc.be.components.impl.ResourceImportManager;
+import org.openecomp.sdc.be.config.BeEcompErrorManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.datamodel.api.HighestFilterEnum;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.impl.ServletUtils;
+import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.UploadResourceInfo;
+import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
+import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum;
+import org.openecomp.sdc.be.user.UserBusinessLogic;
+import org.openecomp.sdc.common.api.Constants;
+import org.openecomp.sdc.common.datastructure.Wrapper;
+import org.openecomp.sdc.common.log.wrappers.Logger;
+import org.openecomp.sdc.exception.ResponseFormat;
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import javax.inject.Singleton;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
+@Path("/v1/catalog")
+@OpenAPIDefinition(info = @Info(title = "Resources Catalog", description = "Resources Servlet"))
+@Singleton
+public class ResourcesServlet extends AbstractValidationsServlet {
+
+    private static final Logger log = Logger.getLogger(ResourcesServlet.class);
+    private final ResourceBusinessLogic resourceBusinessLogic;
+
+    @Inject
+    public ResourcesServlet(UserBusinessLogic userBusinessLogic,
+        ComponentInstanceBusinessLogic componentInstanceBL,
+        ResourceBusinessLogic resourceBusinessLogic,
+        ComponentsUtils componentsUtils, ServletUtils servletUtils,
+        ResourceImportManager resourceImportManager) {
+        super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager);
+        this.resourceBusinessLogic = resourceBusinessLogic;
+    }
+
+    @POST
+    @Path("/resources")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(description = "Create Resource", method = "POST", summary = "Returns created resource",
+            responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource created"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+            @ApiResponse(responseCode = "409", description = "Resource already exist")})
+    public Response createResource(@Parameter(description = "Resource object to be created", required = true) String data,
+            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+        userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
+        init();
+
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("Start handle request of {}" , url);
+
+        // get modifier id
+        User modifier = new User();
+        modifier.setUserId(userId);
+        log.debug("modifier id is {}", userId);
+
+        Response response;
+        try {
+
+            Wrapper<Response> responseWrapper = new Wrapper<>();
+            // UI Import
+            if (isUIImport(data)) {
+                performUIImport(responseWrapper, data, request, userId, null);
+            }
+            // UI Create
+            else {
+
+                Either<Resource, ResponseFormat> convertResponse = parseToResource(data, modifier);
+                if (convertResponse.isRight()) {
+                    log.debug("failed to parse resource");
+                    response = buildErrorResponse(convertResponse.right().value());
+                    return response;
+                }
+
+                Resource resource = convertResponse.left().value();
+                Resource createdResource = resourceBusinessLogic.createResource(resource, AuditingActionEnum.CREATE_RESOURCE, modifier, null, null);
+                Object representation = RepresentationUtils.toRepresentation(createdResource);
+                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), representation);
+                responseWrapper.setInnerElement(response);
+            }
+            return responseWrapper.getInnerElement();
+        } catch (IOException e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Resource");
+            log.debug("create resource failed with exception", e);
+            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+        }
+    }
+
+    private boolean isUIImport(String data) {
+        boolean isUIImport;
+        try {
+            JSONObject json = new JSONObject(data);
+            String payloadName = json.getString(ImportUtils.Constants.UI_JSON_PAYLOAD_NAME);
+            isUIImport = payloadName != null && !payloadName.isEmpty();
+        } catch (JSONException e) {
+            log.debug("failed to parse json sent from client, json:{}", data, e);
+            isUIImport = false;
+        }
+        return isUIImport;
+    }
+
+    private void performUIImport(Wrapper<Response> responseWrapper, String data, final HttpServletRequest request, String userId, String resourceUniqueId) throws FileNotFoundException {
+
+        Wrapper<User> userWrapper = new Wrapper<>();
+        Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>();
+        Wrapper<String> yamlStringWrapper = new Wrapper<>();
+
+        ResourceAuthorityTypeEnum resourceAuthorityEnum = ResourceAuthorityTypeEnum.USER_TYPE_UI;
+
+        commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, resourceAuthorityEnum, userId, data);
+
+        if (!CsarValidationUtils.isCsarPayloadName(uploadResourceInfoWrapper.getInnerElement().getPayloadName())) {
+            fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), data, resourceAuthorityEnum, null);
+
+            // PayLoad Validations
+            commonPayloadValidations(responseWrapper, yamlStringWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement());
+        }
+        specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, data, resourceAuthorityEnum);
+
+        if (responseWrapper.isEmpty()) {
+            handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), resourceAuthorityEnum, true, resourceUniqueId);
+        }
+    }
+
+    private Either<Resource, ResponseFormat> parseToResource(String resourceJson, User user) {
+        return getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.RESOURCE);
+    }
+
+    private Either<Resource, ResponseFormat> parseToLightResource(String resourceJson, User user) {
+        Either<Resource, ResponseFormat> ret = getComponentsUtils().convertJsonToObjectUsingObjectMapper(resourceJson, user, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);
+        if (ret.isLeft()) {// drop unwanted data (sent from UI in update flow)
+            ret.left().value().setRequirements(null);
+            ret.left().value().setCapabilities(null);
+        }
+        return ret;
+    }
+
+    @DELETE
+    @Path("/resources/{resourceId}")
+    public Response deleteResource(@PathParam("resourceId") final String resourceId, @Context final HttpServletRequest request) {
+
+        ServletContext context = request.getSession().getServletContext();
+
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("Start handle request of {}" , url);
+
+        // get modifier id
+        String userId = request.getHeader(Constants.USER_ID_HEADER);
+        User modifier = new User();
+        modifier.setUserId(userId);
+        log.debug("modifier id is {}" , userId);
+
+        Response response;
+
+        try {
+            String resourceIdLower = resourceId.toLowerCase();
+            ResponseFormat actionResponse = resourceBusinessLogic.deleteResource(resourceIdLower, modifier);
+
+            if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
+                log.debug("failed to delete resource");
+                response = buildErrorResponse(actionResponse);
+                return response;
+            }
+            response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
+            return response;
+
+        } catch (JSONException e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Delete Resource");
+            log.debug("delete resource failed with exception", e);
+            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+
+        }
+    }
+
+    @DELETE
+    @Path("/resources/{resourceName}/{version}")
+    public Response deleteResourceByNameAndVersion(@PathParam("resourceName") final String resourceName, @PathParam("version") final String version, @Context final HttpServletRequest request) {
+
+        ServletContext context = request.getSession().getServletContext();
+
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("Start handle request of {}" , url);
+
+        // get modifier id
+        String userId = request.getHeader(Constants.USER_ID_HEADER);
+        User modifier = new User();
+        modifier.setUserId(userId);
+        log.debug("modifier id is {}" , userId);
+
+        Response response;
+        ResponseFormat actionResponse = resourceBusinessLogic.deleteResourceByNameAndVersion(resourceName, version, modifier);
+
+        if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
+            log.debug("failed to delete resource");
+            response = buildErrorResponse(actionResponse);
+            return response;
+        }
+        response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.NO_CONTENT), null);
+        return response;
+    }
+
+    @GET
+    @Path("/resources/{resourceId}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(description = "Retrieve Resource", method = "GET", summary = "Returns resource according to resourceId",
+            responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "404", description = "Resource not found")})
+    public Response getResourceById(@PathParam("resourceId") final String resourceId,
+            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+        ServletContext context = request.getSession().getServletContext();
+
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("Start handle request of {}" , url);
+
+        // get modifier id
+        User modifier = new User();
+        modifier.setUserId(userId);
+        log.debug("modifier id is {}" , userId);
+
+        Response response;
+
+        try {
+            String resourceIdLower = resourceId.toLowerCase();
+            log.trace("get resource with id {}", resourceId);
+            Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResource(resourceIdLower, modifier);
+
+            if (actionResponse.isRight()) {
+                log.debug("failed to get resource");
+                response = buildErrorResponse(actionResponse.right().value());
+                return response;
+            }
+            Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
+
+        } catch (IOException e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource");
+            log.debug("get resource failed with exception", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+
+        }
+    }
+
+    @GET
+    @Path("/resources/resourceName/{resourceName}/resourceVersion/{resourceVersion}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(description = "Retrieve Resource by name and version", method = "GET",
+            summary = "Returns resource according to resourceId", responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "404", description = "Resource not found")})
+    public Response getResourceByNameAndVersion(@PathParam("resourceName") final String resourceName,
+            @PathParam("resourceVersion") final String resourceVersion, @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+        ServletContext context = request.getSession().getServletContext();
+        // get modifier id
+        User modifier = new User();
+        modifier.setUserId(userId);
+        log.debug("modifier id is {}" , userId);
+        Response response;
+        try {
+            Either<Resource, ResponseFormat> actionResponse = resourceBusinessLogic.getResourceByNameAndVersion(resourceName, resourceVersion, userId);
+            if (actionResponse.isRight()) {
+                response = buildErrorResponse(actionResponse.right().value());
+                return response;
+            }
+            Object resource = RepresentationUtils.toRepresentation(actionResponse.left().value());
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
+
+        } catch (IOException e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Resource by name and version");
+            log.debug("get resource failed with exception", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+
+        }
+    }
+
+    @GET
+    @Path("/resources/validate-name/{resourceName}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(description = "validate resource name", method = "GET",
+            summary = "checks if the chosen resource name is available ", responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource found"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation")})
+    public Response validateResourceName(@PathParam("resourceName") final String resourceName,
+            @QueryParam("subtype") String resourceType, @Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        ServletContext context = request.getSession().getServletContext();
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("Start handle request of {}" , url);
+
+        // get modifier id
+        User modifier = new User();
+        modifier.setUserId(userId);
+        log.debug("modifier id is {}" , userId);
+        Response response;
+
+        if (resourceType != null && !ResourceTypeEnum.containsName(resourceType)) {
+            log.debug("invalid resource type received");
+            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT));
+            return response;
+
+        }
+        ResourceTypeEnum typeEnum = null;
+        if (resourceType != null) {
+            typeEnum = ResourceTypeEnum.valueOf(resourceType);
+        }
+        Either<Map<String, Boolean>, ResponseFormat> actionResponse = resourceBusinessLogic.validateResourceNameExists(resourceName, typeEnum, userId);
+
+        if (actionResponse.isRight()) {
+            log.debug("failed to validate resource name");
+            response = buildErrorResponse(actionResponse.right().value());
+            return response;
+        }
+        return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), actionResponse.left().value());
+    }
+
+    @GET
+    @Path("/resources/certified/abstract")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getCertifiedAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("(get) Start handle request of {}" , url);
+        try {
+            List<Resource> resources = resourceBusinessLogic
+                    .getAllCertifiedResources(true, HighestFilterEnum.HIGHEST_ONLY, userId);
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resources));
+
+        } catch (IOException e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Abstract Resources");
+            log.debug("getCertifiedAbstractResources failed with exception", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
+    @GET
+    @Path("/resources/certified/notabstract")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getCertifiedNotAbstractResources(@Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("(get) Start handle request of {}" , url);
+        try {
+            List<Resource> resouces = resourceBusinessLogic.getAllCertifiedResources(false, HighestFilterEnum.ALL, userId);
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), RepresentationUtils.toRepresentation(resouces));
+
+        } catch (IOException e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Get Certified Non Abstract Resources");
+            log.debug("getCertifiedNotAbstractResources failed with exception", e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+
+    }
+
+    @PUT
+    @Path("/resources/{resourceId}/metadata")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(description = "Update Resource Metadata", method = "PUT", summary = "Returns updated resource metadata",
+            responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource metadata updated"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "400", description = "Invalid content")})
+    public Response updateResourceMetadata(@PathParam("resourceId") final String resourceId,
+            @Parameter(description = "Resource metadata to be updated", required = true) String data,
+            @Context final HttpServletRequest request,       @HeaderParam(value = Constants.USER_ID_HEADER) String userId) {
+
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("Start handle request of {}" , url);
+
+        // get modifier id
+        User modifier = new User();
+        modifier.setUserId(userId);
+        log.debug("modifier id is {}", userId);
+        Response response;
+        try {
+            String resourceIdLower = resourceId.toLowerCase();
+            Either<Resource, ResponseFormat> updateInfoResource = getComponentsUtils().convertJsonToObjectUsingObjectMapper(data, modifier, Resource.class, AuditingActionEnum.UPDATE_RESOURCE_METADATA, ComponentTypeEnum.RESOURCE);
+            if (updateInfoResource.isRight()) {
+                log.debug("failed to parse resource metadata");
+                response = buildErrorResponse(updateInfoResource.right().value());
+                return response;
+            }
+            Resource updatedResource = resourceBusinessLogic.updateResourceMetadata(resourceIdLower, updateInfoResource.left().value(), null, modifier, false);
+            Object resource = RepresentationUtils.toRepresentation(updatedResource);
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), resource);
+        } catch (IOException e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource Metadata");
+            log.debug("Update Resource Metadata failed with exception", e);
+            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+
+        }
+    }
+
+    @PUT
+    @Path("/resources/{resourceId}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(description = "Update Resource", method = "PUT", summary = "Returns updated resource",
+            responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Resource updated"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+            @ApiResponse(responseCode = "409", description = "Resource already exist")})
+    public Response updateResource(
+            @Parameter(description = "Resource object to be updated", required = true) String data,
+            @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
+            @PathParam(value = "resourceId") String resourceId) {
+
+        userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
+        init();
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("Start handle request of {}", url);
+        // get modifier id
+        User modifier = new User();
+        modifier.setUserId(userId);
+        log.debug("modifier id is {}", userId);
+        Response response;
+        try {
+            Wrapper<Response> responseWrapper = new Wrapper<>();
+            // UI Import
+            if (isUIImport(data)) {
+                performUIImport(responseWrapper, data, request, userId, resourceId);
+            } else {
+                Either<Resource, ResponseFormat> convertResponse = parseToLightResource(data, modifier);
+                if (convertResponse.isRight()) {
+                    log.debug("failed to parse resource");
+                    response = buildErrorResponse(convertResponse.right().value());
+                    return response;
+                }
+                Resource updatedResource = resourceBusinessLogic.validateAndUpdateResourceFromCsar(
+                        convertResponse.left().value(), modifier, null, null, resourceId);
+                Object representation = RepresentationUtils.toRepresentation(updatedResource);
+                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
+                responseWrapper.setInnerElement(response);
+            }
+            return responseWrapper.getInnerElement();
+        } catch (IOException e) {
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Update Resource");
+            log.debug("update resource failed with exception", e);
+            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+
+        }
+    }
+
+    @GET
+    @Path("/resources/csar/{csaruuid}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    @Operation(description = "Create Resource", method = "POST", summary = "Returns resource created from csar uuid",
+            responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Resource.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Resource retrieced"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content")})
+    public Response getResourceFromCsar(@Context final HttpServletRequest request,
+            @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
+            @PathParam(value = "csaruuid") String csarUUID) {
+
+        init();
+
+        String url = request.getMethod() + " " + request.getRequestURI();
+        log.debug("Start handle request of {}", url);
+
+        // retrieve user details
+        userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER);
+        User user = new User();
+        user.setUserId(userId);
+
+        log.debug("user id is {}", userId);
+
+        Response response;
+
+        try {
+
+            Either<Resource, ResponseFormat> eitherResource =
+                    resourceBusinessLogic.getLatestResourceFromCsarUuid(csarUUID, user);
+
+            // validate response
+            if (eitherResource.isRight()) {
+                log.debug("failed to get resource from csarUuid : {}", csarUUID);
+                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK),
+                        eitherResource.right().value());
+            } else {
+                Object representation = RepresentationUtils.toRepresentation(eitherResource.left().value());
+                response = buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), representation);
+            }
+
+            return response;
+
+        } catch (IOException e) {
+            log.debug("get resource by csar failed with exception", e);
+            response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+            return response;
+        }
+    }
+}
index 5847a06..5a148ef 100644 (file)
-/*-\r
- * ============LICENSE_START=======================================================\r
- * SDC\r
- * ================================================================================\r
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
- * ================================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ============LICENSE_END=========================================================\r
- */\r
-\r
-package org.openecomp.sdc.be.servlets;\r
-\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.util.List;\r
-import java.util.Map;\r
-import javax.ws.rs.Consumes;\r
-import javax.ws.rs.HeaderParam;\r
-import javax.ws.rs.POST;\r
-import javax.ws.rs.Path;\r
-import javax.ws.rs.Produces;\r
-import javax.ws.rs.core.MediaType;\r
-import javax.ws.rs.core.Response;\r
-import org.apache.commons.lang3.tuple.ImmutablePair;\r
-import org.glassfish.jersey.media.multipart.FormDataParam;\r
-import org.openecomp.sdc.be.components.impl.CommonImportManager;\r
-import org.openecomp.sdc.be.components.validation.AccessValidations;\r
-import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;\r
-import org.openecomp.sdc.be.model.AnnotationTypeDefinition;\r
-import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations;\r
-import org.openecomp.sdc.be.utils.TypeUtils;\r
-import org.openecomp.sdc.common.datastructure.Wrapper;\r
-import org.springframework.http.HttpStatus;\r
-import org.springframework.stereotype.Controller;\r
-import com.google.common.annotations.VisibleForTesting;\r
-import com.jcabi.aspects.Loggable;\r
-import io.swagger.v3.oas.annotations.OpenAPIDefinition;\r
-import io.swagger.v3.oas.annotations.Operation;\r
-import io.swagger.v3.oas.annotations.Parameter;\r
-import io.swagger.v3.oas.annotations.info.Info;\r
-import io.swagger.v3.oas.annotations.media.ArraySchema;\r
-import io.swagger.v3.oas.annotations.media.Content;\r
-import io.swagger.v3.oas.annotations.media.Schema;\r
-import io.swagger.v3.oas.annotations.responses.ApiResponse;\r
-import io.swagger.v3.oas.annotations.responses.ApiResponses;\r
-/**\r
- * Here new APIs for types upload written in an attempt to gradually servlet responseCode\r
- */\r
-@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)\r
-@Path("/v1/catalog/uploadType")\r
-@Consumes(MediaType.MULTIPART_FORM_DATA)\r
-@Produces(MediaType.APPLICATION_JSON)\r
-@OpenAPIDefinition(info = @Info(title = "Catalog Types Upload"))\r
-@Controller\r
-public class TypesUploadEndpoint {\r
-\r
-    private final CommonImportManager commonImportManager;\r
-    private final AnnotationTypeOperations annotationTypeOperations;\r
-    private final AccessValidations accessValidations;\r
-\r
-    public TypesUploadEndpoint(CommonImportManager commonImportManager, AnnotationTypeOperations annotationTypeOperations, AccessValidations accessValidations) {\r
-        this.commonImportManager = commonImportManager;\r
-        this.annotationTypeOperations = annotationTypeOperations;\r
-        this.accessValidations = accessValidations;\r
-    }\r
-\r
-    @POST\r
-    @Path("/annotationtypes")\r
-    @Operation(description = "Create AnnotationTypes from yaml", method = "POST",\r
-            summary = "Returns created annotation types",responses = @ApiResponse(\r
-                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))\r
-    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "annotation types created"),\r
-            @ApiResponse(responseCode = "403", description = "Restricted operation"),\r
-            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),\r
-            @ApiResponse(responseCode = "409", description = "annotation types already exist")})\r
-    \r
-    public Response uploadAnnotationTypes(@Parameter(description = "FileInputStream") @FormDataParam("annotationTypesZip") File file,\r
-            @HeaderParam("USER_ID") String userId) throws IOException {\r
-        accessValidations.validateUserExists(userId, "Annotation Types Creation");\r
-        Wrapper<String> yamlStringWrapper = new Wrapper<>();\r
-        AbstractValidationsServlet.extractZipContents(yamlStringWrapper, file);\r
-        List<ImmutablePair<AnnotationTypeDefinition, Boolean>> typesResults =\r
-                commonImportManager.createElementTypes(yamlStringWrapper.getInnerElement(),\r
-                        TypesUploadEndpoint::buildAnnotationFromFieldMap, annotationTypeOperations);\r
-        HttpStatus status = getHttpStatus(typesResults);\r
-        return Response.status(status.value()).entity(typesResults).build();\r
-    }\r
-\r
-    @VisibleForTesting\r
-    static <T extends ToscaDataDefinition> HttpStatus getHttpStatus(List<ImmutablePair<T, Boolean>> typesResults) {\r
-        boolean typeActionFailed = false;\r
-        boolean typeExists = false;\r
-        boolean typeActionSucceeded = false;\r
-        for (ImmutablePair<T, Boolean> typeResult : typesResults) {\r
-            Boolean result = typeResult.getRight();\r
-            if (result==null) {\r
-                typeExists = true;\r
-            } else if (result) {\r
-                typeActionSucceeded = true;\r
-            } else {\r
-                typeActionFailed = true;\r
-            }\r
-        }\r
-        HttpStatus status = HttpStatus.OK;\r
-        if (typeActionFailed) {\r
-            status =  HttpStatus.BAD_REQUEST;\r
-        } else if (typeActionSucceeded) {\r
-            status = HttpStatus.CREATED;\r
-        } else if (typeExists) {\r
-            status = HttpStatus.CONFLICT;\r
-        }\r
-        return status;\r
-    }\r
-\r
-    private static <T extends ToscaDataDefinition> T buildAnnotationFromFieldMap(String typeName, Map<String, Object> toscaJson) {\r
-        AnnotationTypeDefinition annotationType = new AnnotationTypeDefinition();\r
-        annotationType.setVersion(TypeUtils.getFirstCertifiedVersionVersion());\r
-        annotationType.setHighestVersion(true);\r
-        annotationType.setType(typeName);\r
-        TypeUtils.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, annotationType::setDescription);\r
-        CommonImportManager.setProperties(toscaJson, annotationType::setProperties);\r
-        return (T) annotationType;\r
-    }\r
-\r
-\r
-}\r
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.servlets;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.openecomp.sdc.be.components.impl.CommonImportManager;
+import org.openecomp.sdc.be.components.validation.AccessValidations;
+import org.openecomp.sdc.be.datatypes.tosca.ToscaDataDefinition;
+import org.openecomp.sdc.be.model.AnnotationTypeDefinition;
+import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations;
+import org.openecomp.sdc.be.utils.TypeUtils;
+import org.openecomp.sdc.common.datastructure.Wrapper;
+import org.openecomp.sdc.common.zip.exception.ZipException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import com.google.common.annotations.VisibleForTesting;
+import com.jcabi.aspects.Loggable;
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+/**
+ * Here new APIs for types upload written in an attempt to gradually servlet responseCode
+ */
+@Loggable(prepend = true, value = Loggable.DEBUG, trim = false)
+@Path("/v1/catalog/uploadType")
+@Consumes(MediaType.MULTIPART_FORM_DATA)
+@Produces(MediaType.APPLICATION_JSON)
+@OpenAPIDefinition(info = @Info(title = "Catalog Types Upload"))
+@Controller
+public class TypesUploadEndpoint {
+    private static final Logger LOGGER = LoggerFactory.getLogger(TypesUploadEndpoint.class);
+
+    private final CommonImportManager commonImportManager;
+    private final AnnotationTypeOperations annotationTypeOperations;
+    private final AccessValidations accessValidations;
+
+    public TypesUploadEndpoint(CommonImportManager commonImportManager, AnnotationTypeOperations annotationTypeOperations, AccessValidations accessValidations) {
+        this.commonImportManager = commonImportManager;
+        this.annotationTypeOperations = annotationTypeOperations;
+        this.accessValidations = accessValidations;
+    }
+
+    @POST
+    @Path("/annotationtypes")
+    @Operation(description = "Create AnnotationTypes from yaml", method = "POST",
+            summary = "Returns created annotation types",responses = @ApiResponse(
+                    content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
+    @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "annotation types created"),
+            @ApiResponse(responseCode = "403", description = "Restricted operation"),
+            @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+            @ApiResponse(responseCode = "409", description = "annotation types already exist")})
+    
+    public Response uploadAnnotationTypes(@Parameter(description = "FileInputStream") @FormDataParam("annotationTypesZip") File file,
+            @HeaderParam("USER_ID") String userId) {
+        accessValidations.validateUserExists(userId, "Annotation Types Creation");
+        final Wrapper<String> yamlStringWrapper = new Wrapper<>();
+        try {
+            AbstractValidationsServlet.extractZipContents(yamlStringWrapper, file);
+        } catch (final ZipException e) {
+            LOGGER.error("Could not extract zip contents", e);
+        }
+        List<ImmutablePair<AnnotationTypeDefinition, Boolean>> typesResults =
+                commonImportManager.createElementTypes(yamlStringWrapper.getInnerElement(),
+                        TypesUploadEndpoint::buildAnnotationFromFieldMap, annotationTypeOperations);
+        HttpStatus status = getHttpStatus(typesResults);
+        return Response.status(status.value()).entity(typesResults).build();
+    }
+
+    @VisibleForTesting
+    static <T extends ToscaDataDefinition> HttpStatus getHttpStatus(List<ImmutablePair<T, Boolean>> typesResults) {
+        boolean typeActionFailed = false;
+        boolean typeExists = false;
+        boolean typeActionSucceeded = false;
+        for (ImmutablePair<T, Boolean> typeResult : typesResults) {
+            Boolean result = typeResult.getRight();
+            if (result==null) {
+                typeExists = true;
+            } else if (result) {
+                typeActionSucceeded = true;
+            } else {
+                typeActionFailed = true;
+            }
+        }
+        HttpStatus status = HttpStatus.OK;
+        if (typeActionFailed) {
+            status =  HttpStatus.BAD_REQUEST;
+        } else if (typeActionSucceeded) {
+            status = HttpStatus.CREATED;
+        } else if (typeExists) {
+            status = HttpStatus.CONFLICT;
+        }
+        return status;
+    }
+
+    private static <T extends ToscaDataDefinition> T buildAnnotationFromFieldMap(String typeName, Map<String, Object> toscaJson) {
+        AnnotationTypeDefinition annotationType = new AnnotationTypeDefinition();
+        annotationType.setVersion(TypeUtils.getFirstCertifiedVersionVersion());
+        annotationType.setHighestVersion(true);
+        annotationType.setType(typeName);
+        TypeUtils.setField(toscaJson, TypeUtils.ToscaTagNamesEnum.DESCRIPTION, annotationType::setDescription);
+        CommonImportManager.setProperties(toscaJson, annotationType::setProperties);
+        return (T) annotationType;
+    }
+
+
+}
index 2f1357e..836565c 100644 (file)
@@ -55,6 +55,7 @@ import org.openecomp.sdc.common.impl.ExternalConfiguration;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.GeneralUtility;
 import org.openecomp.sdc.common.util.ValidationUtils;
+import org.openecomp.sdc.common.zip.ZipUtils;
 import org.openecomp.sdc.exception.ResponseFormat;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -339,23 +340,20 @@ public class CsarUtils {
                                isInCertificationRequest);
        }
 
-       private Either<ZipOutputStream, ResponseFormat> addSchemaFilesFromCassandra(ZipOutputStream zip,
-                       byte[] schemaFileZip) {
-
+       private Either<ZipOutputStream, ResponseFormat> addSchemaFilesFromCassandra(final ZipOutputStream zip,
+                                                                                                                                                               final byte[] schemaFileZip) {
                final int initSize = 2048;
-
                log.debug("Starting copy from Schema file zip to CSAR zip");
-
-               try (ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(schemaFileZip));
-                               ByteArrayOutputStream out = new ByteArrayOutputStream();
-             BufferedOutputStream bos = new BufferedOutputStream(out, initSize)) {
+               try (final ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(schemaFileZip));
+                       final ByteArrayOutputStream out = new ByteArrayOutputStream();
+                       final BufferedOutputStream bos = new BufferedOutputStream(out, initSize)) {
 
             ZipEntry entry;
                        while ((entry = zipStream.getNextEntry()) != null) {
-
-                               String entryName = entry.getName();
+                               ZipUtils.checkForZipSlipInRead(entry);
+                               final String entryName = entry.getName();
                                int readSize = initSize;
-                               byte[] entryData = new byte[initSize];
+                               final byte[] entryData = new byte[initSize];
 
                                while ((readSize = zipStream.read(entryData, 0, readSize)) != -1) {
                                        bos.write(entryData, 0, readSize);
@@ -368,13 +366,12 @@ public class CsarUtils {
                                zip.flush();
                                out.reset();
                        }
-               } catch (IOException | NullPointerException e) {
-                       log.error("Error while writing the SDC schema file to the CSAR {}", e);
+               } catch (final Exception e) {
+                       log.error("Error while writing the SDC schema file to the CSAR", e);
                        return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
                }
 
                log.debug("Finished coppy from Schema file zip to CSAR zip");
-
                return Either.left(zip);
        }
 
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/ZipUtil.java b/catalog-be/src/test/java/org/openecomp/sdc/ZipUtil.java
deleted file mode 100644 (file)
index 87e351b..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Modifications Copyright (c) 2019 Samsung
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.io.output.ByteArrayOutputStream;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-public class ZipUtil {
-
-    public static void main(String[] args) {
-
-        String zipFileName = "/src/test/resources/config/config.zip";
-
-        zipFileName = "C:\\Git_work\\D2-SDnC\\catalog-be\\src\\test\\resources\\config\\config.zip";
-        zipFileName = "src/test/resources/config/config.zip";
-
-        Path path = Paths.get(zipFileName);
-
-        try {
-            byte[] zipAsBytes = Files.readAllBytes(path);
-            // encode to base
-
-            byte[] decodedMd5 = Base64.encodeBase64(zipAsBytes);
-            String decodedStr = new String(decodedMd5);
-
-            zipAsBytes = Base64.decodeBase64(decodedStr.getBytes());
-
-            // String str = new String(zipAsBytes);
-
-            // readZip(str.getBytes());
-            readZip(zipAsBytes);
-
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-
-    }
-
-    private static Map<String, byte[]> readZip(byte[] zipAsBytes) {
-
-        Map<String, byte[]> fileNameToByteArray = new HashMap<>();
-
-        byte[] buffer = new byte[1024];
-        ZipInputStream zis = null;
-        try {
-
-            zis = new ZipInputStream(new ByteArrayInputStream(zipAsBytes));
-            // get the zipped file list entry
-            ZipEntry ze = zis.getNextEntry();
-
-            while (ze != null) {
-
-                String fileName = ze.getName();
-
-                if (!ze.isDirectory()) {
-
-                    ByteArrayOutputStream os = new ByteArrayOutputStream();
-                    try {
-                        int len;
-                        while ((len = zis.read(buffer)) > 0) {
-                            os.write(buffer, 0, len);
-                        }
-
-                        // aClass.outputStreamMethod(os);
-                        String aString = new String(os.toByteArray(), "UTF-8");
-
-                        fileNameToByteArray.put(fileName, os.toByteArray());
-
-                    } finally {
-                        if (os != null) {
-                            os.close();
-                        }
-                    }
-                }
-                ze = zis.getNextEntry();
-
-            }
-
-            zis.closeEntry();
-            zis.close();
-
-        } catch (IOException ex) {
-            ex.printStackTrace();
-            return null;
-        } finally {
-            if (zis != null) {
-                try {
-                    zis.closeEntry();
-                    zis.close();
-                } catch (IOException e) {
-                    // TODO: add log
-                }
-
-            }
-        }
-
-        return fileNameToByteArray;
-
-    }
-
-    private static byte[] loadResource(String resourceDir) throws IOException, URISyntaxException {
-
-        Path path = Paths.get(ZipUtil.class.getResource(resourceDir).toURI());
-        return Files.readAllBytes(path);
-    }
-
-    public static Map<String, byte[]> readData(String resourceDir) throws IOException, URISyntaxException {
-
-        byte[] data = loadResource(resourceDir);
-        return readZip(data);
-    }
-}
index 2f7f5aa..9bad9f4 100644 (file)
@@ -50,11 +50,7 @@ import java.util.Map;
 
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
 import org.mockito.Mockito;
-import org.mockito.junit.MockitoJUnitRunner;
 
 import org.openecomp.sdc.be.components.impl.BaseBusinessLogicMock;
 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
@@ -66,7 +62,8 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.CsarOperation;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
-import org.openecomp.sdc.common.util.ZipUtil;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.exception.ResponseFormat;
 
 public class CsarBusinessLogicTest extends BaseBusinessLogicMock {
@@ -125,7 +122,7 @@ public class CsarBusinessLogicTest extends BaseBusinessLogicMock {
     }
 
     @Test()
-    public void testGetCsarInfoWithPayload() throws IOException, URISyntaxException {
+    public void testGetCsarInfoWithPayload() throws IOException, URISyntaxException, ZipException {
         // given
         Resource resource = new Resource();
         resource.setName(RESOURCE_NAME);
@@ -185,11 +182,11 @@ public class CsarBusinessLogicTest extends BaseBusinessLogicMock {
         test.validateCsarBeforeCreate(resource, AuditingActionEnum.ARTIFACT_DOWNLOAD, user, "csarUUID");
     }
 
-    public Map<String, byte[]> loadPayload(String payloadName) throws IOException, URISyntaxException {
+    public Map<String, byte[]> loadPayload(String payloadName) throws IOException, URISyntaxException, ZipException {
 
         Path path = Paths.get(getClass().getResource("/" + payloadName).toURI());
         byte[] data = Files.readAllBytes(path);
 
-        return ZipUtil.readZip(data);
+        return ZipUtils.readZip(data, false);
     }
 }
index 3ae65c8..69f9f57 100644 (file)
@@ -25,7 +25,7 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.IOException;
+import java.io.File;
 import java.net.URISyntaxException;
 import java.util.Arrays;
 import java.util.List;
@@ -41,7 +41,8 @@ import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentEx
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.model.NodeTypeInfo;
 import org.openecomp.sdc.be.model.User;
-import org.openecomp.sdc.ZipUtil;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 
 @RunWith(MockitoJUnitRunner.class)
 public class CsarInfoTest {
@@ -52,19 +53,18 @@ public class CsarInfoTest {
     private User user;
 
     private static final String CSAR_UUID = "csarUUID";
-    private static final String PAYLOAD_NAME = "/mock_service.csar";
+    private static final String PAYLOAD_NAME = "mock_service.csar";
     private static final String RESOURCE_NAME = "resourceName";
     private static final String MAIN_TEMPLATE_NAME = "Definitions/tosca_mock_vf.yaml";
-
     private static final String NEW_NODE_NAME = "new_db";
     private static final String NODE_TYPE = "tosca.nodes.Compute";
     private static final String DELIVER_FOR = "tosca.nodes.Root";
 
     @Before
-    public void setup() throws IOException, URISyntaxException {
-
+    public void setup() throws ZipException, URISyntaxException {
         // given
-        Map<String, byte[]> payload = ZipUtil.readData(PAYLOAD_NAME);
+        final File csarFile = new File(CsarInfoTest.class.getClassLoader().getResource(PAYLOAD_NAME).toURI());
+        final Map<String, byte[]> payload = ZipUtils.readZip(csarFile, false);
         String mainTemplateContent = new String(payload.get(MAIN_TEMPLATE_NAME));
 
         csarInfo = new CsarInfo(user, CSAR_UUID, payload, RESOURCE_NAME,
index 19d1a17..8ae02c4 100644 (file)
@@ -27,11 +27,14 @@ import static org.junit.Assert.assertNotNull;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
-import java.io.IOException;
+import java.io.File;
 import java.net.URISyntaxException;
-import java.util.*;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
-
 import org.assertj.core.util.Lists;
 import org.junit.Assert;
 import org.junit.Before;
@@ -41,8 +44,6 @@ import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
-
-import org.openecomp.sdc.ZipUtil;
 import org.openecomp.sdc.be.components.csar.CsarInfo;
 import org.openecomp.sdc.be.components.csar.YamlTemplateParsingHandler;
 import org.openecomp.sdc.be.components.impl.AnnotationBusinessLogic;
@@ -50,8 +51,15 @@ import org.openecomp.sdc.be.components.impl.GroupTypeBusinessLogic;
 import org.openecomp.sdc.be.components.validation.AnnotationValidator;
 import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
-import org.openecomp.sdc.be.model.*;
+import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.ComponentInstanceProperty;
+import org.openecomp.sdc.be.model.GroupProperty;
+import org.openecomp.sdc.be.model.GroupTypeDefinition;
+import org.openecomp.sdc.be.model.ParsedToscaYamlInfo;
+import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.operations.impl.AnnotationTypeOperations;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 
 import java.io.File;
 import java.io.IOException;
@@ -88,10 +96,8 @@ public class YamlTemplateParsingHandlerTest {
     private final static GroupTypeDefinition rootGroupType = buildRootGroupType();
     private final static String CAPABILITY_TYPE = "org.openecomp.capabilities.VLANAssignment";
     private final static String CAPABILITY_NAME = "vlan_assignment";
-    private static final String CSAR_FILE_PATH = "/csars/with_groups.csar";
-
+    private static final String CSAR_FILE_PATH = "csars/with_groups.csar";
     private static final String FILE_NAME = "MainServiceTemplate.yaml";
-
     private static final String CSAR_UUID = "csarUUID";
     private static final String RESOURCE_NAME = "resourceName";
     private static final String MAIN_TEMPLATE_NAME = "Definitions/MainServiceTemplate.yaml";
@@ -103,8 +109,10 @@ public class YamlTemplateParsingHandlerTest {
     YamlTemplateParsingHandler testSubject;
 
     @BeforeClass()
-    public static void prepareData() throws IOException, URISyntaxException {
-        csar = ZipUtil.readData(CSAR_FILE_PATH);
+    public static void prepareData() throws URISyntaxException, ZipException {
+        final File csarFile = new File(
+            YamlTemplateParsingHandlerTest.class.getClassLoader().getResource(CSAR_FILE_PATH).toURI());
+        csar = ZipUtils.readZip(csarFile, false);
 
         Optional<String> keyOp = csar.keySet().stream().filter(k -> k.endsWith(FILE_NAME)).findAny();
         byte[] mainTemplateService = keyOp.map(csar::get).orElse(null);
index 9ae2f25..af8a68f 100644 (file)
@@ -25,17 +25,11 @@ import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonParser;
 import fj.data.Either;
-import org.apache.commons.io.filefilter.WildcardFileFilter;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.common.log.wrappers.Logger;
-import org.openecomp.sdc.common.util.ZipUtil;
 
 import javax.annotation.PostConstruct;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-import java.nio.file.Files;
 import java.util.Map;
 
 @org.springframework.stereotype.Component("csar-operation")
@@ -62,29 +56,6 @@ public class CsarOperation {
 
     }
 
-    public Either<Map<String, byte[]>, StorageOperationStatus> getMockCsar(String csarUuid) {
-        File dir = new File("/var/tmp/mockCsar");
-        FileFilter fileFilter = new WildcardFileFilter("*.csar");
-        File[] files = dir.listFiles(fileFilter);
-        for (int i = 0; i < files.length; i++) {
-            File csar = files[i];
-            if (csar.getName().startsWith(csarUuid)) {
-                log.debug("Found CSAR file {} matching the passed csarUuid {}", csar.getAbsolutePath(), csarUuid);
-                byte[] data;
-                try {
-                    data = Files.readAllBytes(csar.toPath());
-                } catch (IOException e) {
-                    log.debug("Error reading mock file for CSAR, error: {}", e);
-                    return Either.right(StorageOperationStatus.NOT_FOUND);
-                }
-                Map<String, byte[]> readZip = ZipUtil.readZip(data);
-                return Either.left(readZip);
-            }
-        }
-        log.debug("Couldn't find mock file for CSAR starting with {}", csarUuid);
-        return Either.right(StorageOperationStatus.CSAR_NOT_FOUND);
-    }
-
     /**
      * get csar from remote repository
      *
index 8e1ee19..ed0b43e 100644 (file)
@@ -21,7 +21,8 @@
 package org.openecomp.sdc.be.model.operations.impl;
 
 import fj.data.Either;
-import org.apache.commons.io.filefilter.WildcardFileFilter;
+import java.util.Map;
+import java.util.Properties;
 import org.apache.http.HttpStatus;
 import org.openecomp.sdc.be.config.Configuration.OnboardingConfig;
 import org.openecomp.sdc.be.config.ConfigurationManager;
@@ -30,14 +31,7 @@ import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.http.client.api.HttpRequest;
 import org.openecomp.sdc.common.http.client.api.HttpResponse;
 import org.openecomp.sdc.common.log.wrappers.Logger;
-import org.openecomp.sdc.common.util.ZipUtil;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.Map;
-import java.util.Properties;
+import org.openecomp.sdc.common.zip.ZipUtils;
 
 @org.springframework.stereotype.Component("onboarding-client")
 public class OnboardingClient {
@@ -64,29 +58,6 @@ public class OnboardingClient {
 
     }
 
-    public Either<Map<String, byte[]>, StorageOperationStatus> getMockCsar(String csarUuid) {
-        File dir = new File("/var/tmp/mockCsar");
-        FileFilter fileFilter = new WildcardFileFilter("*.csar");
-        File[] files = dir.listFiles(fileFilter);
-        for (int i = 0; i < files.length; i++) {
-            File csar = files[i];
-            if (csar.getName().startsWith(csarUuid)) {
-                log.debug("Found CSAR file {} matching the passed csarUuid {}", csar.getAbsolutePath(), csarUuid);
-                byte[] data;
-                try {
-                    data = Files.readAllBytes(csar.toPath());
-                } catch (IOException e) {
-                    log.debug("Error reading mock file for CSAR, error: {}", e);
-                    return Either.right(StorageOperationStatus.NOT_FOUND);
-                }
-                Map<String, byte[]> readZip = ZipUtil.readZip(data);
-                return Either.left(readZip);
-            }
-        }
-        log.debug("Couldn't find mock file for CSAR starting with {}", csarUuid);
-        return Either.right(StorageOperationStatus.NOT_FOUND);
-    }
-
     public Either<Map<String, byte[]>, StorageOperationStatus> getCsar(String csarUuid, String userId) {
         String url = buildDownloadCsarUrl() + "/" + csarUuid;
 
@@ -109,7 +80,7 @@ public class OnboardingClient {
             case HttpStatus.SC_OK:
                 byte[] data = httpResponse.getResponse();
                 if (data != null && data.length > 0) {
-                    Map<String, byte[]> readZip = ZipUtil.readZip(data);
+                    Map<String, byte[]> readZip = ZipUtils.readZip(data, false);
                     return Either.left(readZip);
                 } else {
                     log.debug("Data received from rest is null or empty");
@@ -124,7 +95,7 @@ public class OnboardingClient {
             }
         }
         catch(Exception e) {
-            log.debug("Request failed with exception {}", e);
+            log.debug("Request failed with exception", e);
             return Either.right(StorageOperationStatus.GENERAL_ERROR);
         }
     }
@@ -158,7 +129,7 @@ public class OnboardingClient {
             }
         }
         catch(Exception e) {
-            log.debug("Request failed with exception {}", e);
+            log.debug("Request failed with exception", e);
             return Either.right(StorageOperationStatus.GENERAL_ERROR);
         }
     }
index 38d3bbe..62bfb24 100644 (file)
                        <scope>provided</scope>
                </dependency>
 
+               <dependency>
+                       <groupId>org.hamcrest</groupId>
+                       <artifactId>hamcrest</artifactId>
+                       <version>${hamcrest.version}</version>
+                       <scope>test</scope>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.hamcrest</groupId>
+                       <artifactId>hamcrest-library</artifactId>
+                       <version>${hamcrest.version}</version>
+                       <scope>test</scope>
+               </dependency>
+
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/util/ZipUtil.java b/common-app-api/src/main/java/org/openecomp/sdc/common/util/ZipUtil.java
deleted file mode 100644 (file)
index ec3c31c..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.common.util;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.openecomp.sdc.common.log.wrappers.Logger;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-public class ZipUtil {
-
-    private static final int KB = 1024;
-    private static Logger log = Logger.getLogger(ZipUtil.class.getName());
-
-    private ZipUtil() {
-    }
-
-    public static Map<String, byte[]> readZip(File file) {
-        try (InputStream fileInputStream = new FileInputStream(file)) {
-            return readZip(IOUtils.toByteArray(fileInputStream));
-        } catch (IOException e) {
-            log.info("close File stream failed - {}", e);
-            return null;
-        }
-    }
-
-    public static Map<String, byte[]> readZip(byte[] zipAsBytes) {
-        Map<String, byte[]> fileNameToByteArray = new HashMap<>();
-        byte[] buffer = new byte[KB];
-        try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(zipAsBytes);
-             ZipInputStream zis = new ZipInputStream(byteArrayInputStream)) {
-            // get the zipped file list entry
-            ZipEntry ze = zis.getNextEntry();
-
-            while (ze != null) {
-
-                String fileName = ze.getName();
-
-                if (!ze.isDirectory()) {
-
-                    try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
-                        int len;
-                        while ((len = zis.read(buffer)) > 0) {
-                            os.write(buffer, 0, len);
-                        }
-
-                        fileNameToByteArray.put(fileName, os.toByteArray());
-
-                    }
-                }
-                ze = zis.getNextEntry();
-            }
-        } catch (IOException ex) {
-            log.info("close Byte stream failed", ex);
-            return null;
-        }
-
-        return fileNameToByteArray;
-
-    }
-
-    public static void main(String[] args) {
-        String zipFileName = "/src/test/resources/config/config.zip";
-        zipFileName = "C:\\Git_work\\D2-SDnC\\catalog-be\\src\\test\\resources\\config\\config.zip";
-        Path path = Paths.get(zipFileName);
-
-        try {
-            byte[] zipAsBytes = Files.readAllBytes(path);
-            // encode to base
-
-            ZipUtil.readZip(zipAsBytes);
-
-        } catch (IOException e) {
-            log.info("close Byte stream failed", e);
-        }
-    }
-
-    public static byte[] zipBytes(byte[] input) throws IOException {
-        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
-             ZipOutputStream zos = new ZipOutputStream(baos)) {
-            ZipEntry entry = new ZipEntry("zip");
-            entry.setSize(input.length);
-            zos.putNextEntry(entry);
-            zos.write(input);
-            zos.closeEntry();
-            return baos.toByteArray();
-        }
-    }
-
-    public static byte[] unzip(byte[] zipped) {
-        try (ZipInputStream zipinputstream = new ZipInputStream(new ByteArrayInputStream(zipped));
-             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
-            byte[] buf = new byte[KB];
-            ZipEntry zipentry = zipinputstream.getNextEntry();
-            int n;
-            while ((n = zipinputstream.read(buf, 0, KB)) > -1) {
-                outputStream.write(buf, 0, n);
-            }
-            return outputStream.toByteArray();
-        } catch (Exception e) {
-            throw new IllegalStateException("Can't unzip input stream", e);
-        }
-    }
-}
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/zip/ZipUtils.java b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/ZipUtils.java
new file mode 100644 (file)
index 0000000..d90377f
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.zip;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+import org.apache.commons.io.IOUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
+import org.openecomp.sdc.common.zip.exception.ZipSlipException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Handles zip operations.
+ */
+public class ZipUtils {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ZipUtils.class);
+
+    private ZipUtils() {
+    }
+
+    /**
+     * Checks if the path is a zip slip attempt calling the {@link #checkForZipSlipInRead(Path)} method.
+     * @param zipEntry the zip entry
+     * @throws ZipSlipException when a zip slip attempt is detected
+     */
+    public static void checkForZipSlipInRead(final ZipEntry zipEntry) throws ZipSlipException {
+        final Path filePath = Paths.get(zipEntry.getName());
+        checkForZipSlipInRead(filePath);
+    }
+
+    /**
+     * Checks if the path is a zip slip attempt when you don't have a destination folder eg in memory reading or zip
+     * creation.
+     *
+     * @param filePath the file path
+     * @throws ZipSlipException when a zip slip attempt is detected
+     */
+    public static void checkForZipSlipInRead(final Path filePath) throws ZipSlipException {
+        final File file = filePath.toFile();
+        String canonicalPath = null;
+        try {
+            canonicalPath = file.getCanonicalPath();
+        } catch (final IOException ignored) {
+            //ignored
+        }
+        if (canonicalPath != null && !canonicalPath.equals(file.getAbsolutePath())) {
+            throw new ZipSlipException(filePath.toString());
+        }
+
+        if (filePath.toString().contains("../") || filePath.toString().contains("..\\")) {
+            throw new ZipSlipException(filePath.toString());
+        }
+    }
+
+    /**
+     * Checks if the zip entry is a zip slip attempt based on the destination directory.
+     *
+     * @param zipEntry the zip entry
+     * @param targetDirectoryPath the target extraction folder
+     * @throws ZipException when the zip slip was detected as a {@link ZipSlipException}. Also when there was a problem
+     * getting the canonical paths from the zip entry or target directory.
+     */
+    public static void checkForZipSlipInExtraction(final ZipEntry zipEntry,
+                                                   final Path targetDirectoryPath) throws ZipException {
+        final File targetDirectoryAsFile = targetDirectoryPath.toFile();
+        final File targetFile = new File(targetDirectoryAsFile, zipEntry.getName());
+        final String targetDirectoryCanonicalPath;
+        try {
+            targetDirectoryCanonicalPath = targetDirectoryAsFile.getCanonicalPath();
+        } catch (final IOException e) {
+            throw new ZipException(
+                String.format("Could not obtain canonical path of: '%s'", targetDirectoryAsFile.getAbsolutePath()), e);
+        }
+        final String targetFileCanonicalPath;
+        try {
+            targetFileCanonicalPath = targetFile.getCanonicalPath();
+        } catch (final IOException e) {
+            throw new ZipException(
+                String.format("Could not obtain canonical path of: '%s'", targetFile.getAbsolutePath()), e);
+        }
+
+        if (!targetFileCanonicalPath.startsWith(targetDirectoryCanonicalPath + File.separator)) {
+            throw new ZipSlipException(zipEntry.getName());
+        }
+    }
+
+    /**
+     * Creates a ZipInputStream from a byte array.
+     *
+     * @param zipFileBytes the zip byte array
+     * @return the created ZipInputStream.
+     */
+    private static ZipInputStream getInputStreamFromBytes(final byte[] zipFileBytes) {
+        return new ZipInputStream(new ByteArrayInputStream(zipFileBytes));
+    }
+
+    /**
+     * Reads a zip file into memory. Parses the zipFile in byte array and calls {@link #readZip(byte[], boolean)}.
+     *
+     * @param zipFile the zip file to read
+     * @param hasToIncludeDirectories includes or not the directories found during the zip reading
+     * @return a Map representing a pair of file path and file byte array
+     * @throws ZipException when there was a problem during the reading process
+     */
+    public static Map<String, byte[]> readZip(final File zipFile,
+                                              final boolean hasToIncludeDirectories) throws ZipException {
+        try {
+            return readZip(Files.readAllBytes(zipFile.toPath()), hasToIncludeDirectories);
+        } catch (final IOException e) {
+            throw new ZipException(String.format("Could not read the zip file '%s'", zipFile.getName()), e);
+        }
+    }
+
+    /**
+     * Reads a zip file to a in memory structure formed by the file path and its bytes. The structure can contains only
+     * files or files and directories. If configured to include directories, only empty directories and directories that
+     * contains files will be included. The full directory tree will not be generated, eg:
+     * <pre>
+     * \
+     * \..\Directory
+     * \..\..\ChildDirectory
+     * \..\..\..\aFile.txt
+     * \..\..\EmptyChildDirectory
+     * </pre>
+     * The return will include "Directory\ChildDirectory\aFile.txt" and "Directory\EmptyChildDirectory" but not
+     * "Directory" or the root.
+     *
+     * @param zipFileBytes the zip file byte array to read
+     * @param hasToIncludeDirectories includes or not the directories found during the zip reading.
+     * @return a Map representing a pair of file path and file byte array
+     * @throws ZipException when there was a problem during the reading process
+     */
+    public static Map<String, byte[]> readZip(final byte[] zipFileBytes,
+                                              final boolean hasToIncludeDirectories) throws ZipException {
+        final Map<String, byte[]> filePathAndByteMap = new HashMap<>();
+
+        try (final ZipInputStream inputZipStream = ZipUtils.getInputStreamFromBytes(zipFileBytes)) {
+            byte[] fileByteContent;
+            String currentEntryName;
+            ZipEntry zipEntry;
+            while ((zipEntry = inputZipStream.getNextEntry()) != null) {
+                checkForZipSlipInRead(zipEntry);
+                currentEntryName = zipEntry.getName();
+                fileByteContent = getBytes(inputZipStream);
+                if (zipEntry.isDirectory()) {
+                    if (hasToIncludeDirectories) {
+                        filePathAndByteMap.put(normalizeFolder(currentEntryName), null);
+                    }
+                } else {
+                    if (hasToIncludeDirectories) {
+                        final Path parentFolderPath = Paths.get(zipEntry.getName()).getParent();
+                        if (parentFolderPath != null) {
+                            filePathAndByteMap.putIfAbsent(normalizeFolder(parentFolderPath.toString()), null);
+                        }
+                    }
+                    filePathAndByteMap.put(currentEntryName, fileByteContent);
+                }
+            }
+        } catch (final IOException e) {
+            LOGGER.warn("Could not close the zip input stream", e);
+        }
+
+        return filePathAndByteMap;
+    }
+
+    /**
+     * Adds a {@link File#separator} at the end of the folder path if not present.
+     *
+     * @param folderPath the folder to normalize
+     * @return the normalized folder
+     */
+    private static String normalizeFolder(final String folderPath) {
+        final StringBuilder normalizedFolderBuilder = new StringBuilder(folderPath);
+        if(!folderPath.endsWith(File.separator)) {
+            normalizedFolderBuilder.append(File.separator);
+        }
+        return normalizedFolderBuilder.toString();
+    }
+
+    /**
+     * Converts a ZipInputStream in byte array.
+     *
+     * @param inputZipStream the zip input stream
+     * @return the byte array representing the input stream
+     * @throws ZipException when there was a problem parsing the input zip stream
+     */
+    private static byte[] getBytes(final ZipInputStream inputZipStream) throws ZipException {
+        final byte[] fileByteContent;
+        try {
+            fileByteContent = IOUtils.toByteArray(inputZipStream);
+        } catch (final IOException e) {
+            throw new ZipException("Could not read bytes from file", e);
+        }
+        return fileByteContent;
+    }
+
+    /**
+     * Unzips a zip file into an output folder.
+     *
+     * @param zipFilePath the zip file path
+     * @param outputFolder the output folder path
+     * @throws ZipException when there was a problem during the unzip process
+     */
+    public static void unzip(final Path zipFilePath, final Path outputFolder) throws ZipException {
+        if (zipFilePath == null || outputFolder == null) {
+            return;
+        }
+        createDirectoryIfNotExists(outputFolder);
+
+        final File zipFile = zipFilePath.toFile();
+        try (final FileInputStream fileInputStream = new FileInputStream(zipFile);
+            final ZipInputStream stream = new ZipInputStream(fileInputStream)) {
+
+            ZipEntry zipEntry;
+            while ((zipEntry = stream.getNextEntry()) != null) {
+                checkForZipSlipInExtraction(zipEntry, outputFolder);
+                final String fileName = zipEntry.getName();
+                final Path fileToWritePath = Paths.get(outputFolder.toString(), fileName);
+                if (zipEntry.isDirectory()) {
+                    createDirectoryIfNotExists(fileToWritePath);
+                } else {
+                    writeFile(stream, fileToWritePath);
+                }
+            }
+        } catch (final FileNotFoundException e) {
+            throw new ZipException(String.format("Could not find file: '%s'", zipFile.getAbsolutePath()), e);
+        } catch (final IOException e) {
+            throw new ZipException(
+                String.format("An unexpected error occurred trying to unzip '%s'", zipFile.getAbsolutePath()), e);
+        }
+    }
+
+    /**
+     * Writes a file from a zipInputStream to a path. Creates the file parent directories if they don't exist.
+     * @param zipInputStream the zip input stream
+     * @param fileToWritePath the file path to write
+     * @throws ZipException when there was a problem during the file creation
+     */
+    private static void writeFile(final ZipInputStream zipInputStream, final Path fileToWritePath) throws ZipException {
+        final Path parentFolderPath = fileToWritePath.getParent();
+        if (parentFolderPath != null) {
+            try {
+                Files.createDirectories(parentFolderPath);
+            } catch (final IOException e) {
+                throw new ZipException(
+                    String.format("Could not create parent directories of '%s'", fileToWritePath.toString()), e);
+            }
+        }
+        try (final FileOutputStream outputStream = new FileOutputStream(fileToWritePath.toFile())) {
+            IOUtils.copy(zipInputStream, outputStream);
+        } catch (final FileNotFoundException e) {
+            throw new ZipException(String.format("Could not find file '%s'", fileToWritePath.toString()), e);
+        } catch (final IOException e) {
+            throw new ZipException(
+                String.format("An unexpected error has occurred while writing file '%s'", fileToWritePath.toString())
+                , e);
+        }
+    }
+
+    /**
+     * Creates the path directories if the provided path does not exists.
+     *
+     * @param path the path to create directories
+     * @throws ZipException when there was a problem to create the directories
+     */
+    private static void createDirectoryIfNotExists(final Path path) throws ZipException {
+        if(path.toFile().exists()) {
+            return;
+        }
+        try {
+            Files.createDirectories(path);
+        } catch (final IOException e) {
+            throw new ZipException(String.format("Could not create directories for path '%s'", path.toString()), e);
+        }
+    }
+
+    /**
+     * Zips a directory and its children content.
+     *
+     * @param fromPath the directory path to zip
+     * @param toZipFilePath the path to the zip file that will be created
+     * @throws ZipException when there was a problem during the zip process
+     */
+    public static void createZipFromPath(final Path fromPath, final Path toZipFilePath) throws ZipException {
+        final Path createdZipFilePath;
+        try {
+            createdZipFilePath = Files.createFile(toZipFilePath);
+        } catch (final IOException e) {
+            throw new ZipException(String.format("Could not create file '%s'", toZipFilePath.toString()), e);
+        }
+
+        try(final FileOutputStream fileOutputStream = new FileOutputStream(createdZipFilePath.toFile());
+            final BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
+            final ZipOutputStream zipOut = new ZipOutputStream(bos);
+            final Stream<Path> walkStream = Files.walk(fromPath)) {
+            final Set<Path> allFilesSet = walkStream.collect(Collectors.toSet());
+            for (final Path path : allFilesSet) {
+                checkForZipSlipInRead(path);
+                if (path.equals(fromPath)) {
+                    continue;
+                }
+                final Path relativePath = fromPath.relativize(path);
+                final File file = path.toFile();
+                if (file.isDirectory()) {
+                    zipOut.putNextEntry(new ZipEntry(relativePath.toString() + File.separator));
+                } else {
+                    zipOut.putNextEntry(new ZipEntry(relativePath.toString()));
+                    zipOut.write(Files.readAllBytes(path));
+                }
+                zipOut.closeEntry();
+            }
+        } catch (final FileNotFoundException e) {
+            throw new ZipException(String.format("Could not create file '%s'", toZipFilePath.toString()), e);
+        } catch (final IOException e) {
+            throw new ZipException("An error has occurred while creating the zip package", e);
+        }
+    }
+
+}
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipException.java b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipException.java
new file mode 100644 (file)
index 0000000..414b482
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.zip.exception;
+
+public class ZipException extends Exception {
+
+    public ZipException(String s) {
+        super(s);
+    }
+
+    public ZipException(String s, Throwable throwable) {
+        super(s, throwable);
+    }
+}
diff --git a/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipSlipException.java b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipSlipException.java
new file mode 100644 (file)
index 0000000..203e357
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.zip.exception;
+
+public class ZipSlipException extends ZipException {
+
+    public ZipSlipException(final String filePath) {
+        super(String.format("Zip slip attempt detected in file: %s", filePath));
+    }
+}
diff --git a/common-app-api/src/test/java/org/openecomp/sdc/common/util/ZipUtilTest.java b/common-app-api/src/test/java/org/openecomp/sdc/common/util/ZipUtilTest.java
deleted file mode 100644 (file)
index 71e8d15..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.common.util;
-
-import org.junit.Test;
-
-import java.util.Map;
-
-public class ZipUtilTest {
-
-       // private ZipUtil createTestSubject() {
-       // return new ZipUtil();
-       // }
-
-       @Test
-       public void testReadZip() throws Exception {
-               byte[] zipAsBytes = new byte[] { ' ' };
-               Map<String, byte[]> result;
-
-               // default test
-               result = ZipUtil.readZip(zipAsBytes);
-       }
-
-       @Test
-       public void testMain() throws Exception {
-               String[] args = new String[] { "" };
-
-               // default test
-               ZipUtil.main(args);
-       }
-
-       @Test
-       public void testZipBytes() throws Exception {
-               byte[] input = new byte[] { ' ' };
-               byte[] result;
-
-               // default test
-               result = ZipUtil.zipBytes(input);
-       }
-
-       @Test
-       public void testUnzip() throws Exception {
-               byte[] zipped = new byte[] { ' ' };
-               byte[] result;
-
-               // default test
-               result = ZipUtil.unzip(zipped);
-       }
-}
diff --git a/common-app-api/src/test/java/org/openecomp/sdc/common/zip/ZipUtilsTest.java b/common-app-api/src/test/java/org/openecomp/sdc/common/zip/ZipUtilsTest.java
new file mode 100644 (file)
index 0000000..d5fb3dc
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.common.zip;
+
+import static org.hamcrest.Matchers.aMapWithSize;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isIn;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.openecomp.sdc.common.zip.exception.ZipException;
+import org.openecomp.sdc.common.zip.exception.ZipSlipException;
+
+public class ZipUtilsTest {
+
+    @Test
+    public void testZipSlipInRead() {
+        final byte[] windowsZipBytes;
+        final byte[] linuxZipBytes;
+        try {
+            final InputStream linuxZipAsStream = ZipUtilsTest.class.getClassLoader().getResourceAsStream("zip-slip/zip-slip-linux.zip");
+            final InputStream windowsZipAsStream = ZipUtilsTest.class.getClassLoader().getResourceAsStream("zip-slip/zip-slip-windows.zip");
+            if(linuxZipAsStream == null || windowsZipAsStream == null) {
+                fail("Could not load the zip slip files");
+            }
+            linuxZipBytes = IOUtils.toByteArray(linuxZipAsStream);
+            windowsZipBytes = IOUtils.toByteArray(windowsZipAsStream);
+        } catch (final IOException e) {
+            e.printStackTrace();
+            fail("Could not load the required zip slip files");
+            return;
+        }
+
+        try {
+            ZipUtils.readZip(linuxZipBytes, true);
+            fail("Zip slip should be detected");
+        } catch (final ZipException ex) {
+            assertThat("Expected ZipSlipException", ex, is(instanceOf(ZipSlipException.class)));
+        }
+
+        try {
+            ZipUtils.readZip(windowsZipBytes, true);
+            fail("Zip slip should be detected");
+        } catch (final ZipException ex) {
+            assertThat("Expected ZipSlipException", ex, is(instanceOf(ZipSlipException.class)));
+        }
+    }
+
+    @Test
+    public void testZipSlipInUnzip() throws IOException {
+        final Path tempDirectoryWindows = Files.createTempDirectory("zipSlipWindows" + System.currentTimeMillis());
+        final Path tempDirectoryLinux = Files.createTempDirectory("zipSlipLinux" + System.currentTimeMillis());
+        try {
+            final Path linuxZipPath;
+            final Path windowsZipPath;
+            try {
+                linuxZipPath = Paths
+                    .get(ZipUtilsTest.class.getClassLoader().getResource("zip-slip/zip-slip-linux.zip").toURI());
+                windowsZipPath = Paths
+                    .get(ZipUtilsTest.class.getClassLoader().getResource("zip-slip/zip-slip-windows.zip").toURI());
+            } catch (final URISyntaxException e) {
+                fail("Could not load the required zip slip files");
+                return;
+            }
+
+            try {
+                ZipUtils.unzip(windowsZipPath, tempDirectoryWindows);
+                ZipUtils.unzip(linuxZipPath, tempDirectoryLinux);
+                fail("Zip slip should be detected");
+            } catch (final ZipException ex) {
+                assertThat("At least one of the zip files should throw ZipSlipException",
+                    ex, is(instanceOf(ZipSlipException.class)));
+            }
+        } finally {
+            org.apache.commons.io.FileUtils.deleteDirectory(tempDirectoryLinux.toFile());
+            org.apache.commons.io.FileUtils.deleteDirectory(tempDirectoryWindows.toFile());
+        }
+    }
+
+    @Test
+    public void testUnzipAndZip() throws IOException, ZipException {
+        final Path unzipTempPath = Files.createTempDirectory("testUnzip");
+        final Path zipTempPath = Files.createTempDirectory("testZip");
+        final Path testZipPath;
+        try {
+            try {
+                testZipPath = Paths
+                    .get(ZipUtilsTest.class.getClassLoader().getResource("zip/extract-test.zip").toURI());
+                ZipUtils.unzip(testZipPath, unzipTempPath);
+            } catch (final URISyntaxException e) {
+                fail("Could not load the required zip file");
+                return;
+            }
+
+            final Set<Path> expectedPaths = new HashSet<>();
+            expectedPaths.add(Paths.get(unzipTempPath.toString(),"rootFile1.txt"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(),"rootFileNoExtension"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(),"EmptyFolder"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "SingleLvlFolder"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "SingleLvlFolder", "singleLvlFolderFile.txt"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "SingleLvlFolder", "singleLvlFolderFileNoExtension"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "twoLvlFolderFile.txt"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "twoLvlFolderFileNoExtension"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "SingleLvlFolder"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "SingleLvlFolder", "singleLvlFolderFile.txt"));
+            expectedPaths.add(Paths.get(unzipTempPath.toString(), "TwoLvlFolder", "SingleLvlFolder", "singleLvlFolderFileNoExtension"));
+
+            final AtomicLong actualPathCount = new AtomicLong(0);
+            try (Stream<Path> stream = Files.walk(unzipTempPath)) {
+                stream.filter(path -> !unzipTempPath.equals(path)).forEach(actualPath -> {
+                    actualPathCount.getAndIncrement();
+                    assertThat("Unzipped file should be in the expected list", actualPath, isIn(expectedPaths));
+                });
+            }
+            assertThat("The number of unzipped files should be as expected", actualPathCount.get(), is((long) expectedPaths.size()));
+            final Path zipFilePath = zipTempPath.resolve("testzip.zip");
+            ZipUtils.createZipFromPath(unzipTempPath, zipFilePath);
+            final Map<String, byte[]> fileMap = ZipUtils.readZip(zipFilePath.toFile(), true);
+            //matching the folder pattern of the readZip
+            final Set<String> expectedPathStringSet = expectedPaths.stream()
+                .map(path -> {
+                    final Path relativePath = unzipTempPath.relativize(path);
+                    return path.toFile().isDirectory() ? relativePath.toString() + File.separator : relativePath.toString();
+                }).collect(Collectors.toSet());
+            assertThat("The number of zipped files should be as expected", fileMap, aMapWithSize(expectedPathStringSet.size()));
+            fileMap.keySet().forEach(s -> {
+                assertThat("File in zip package should be in the expected list", s, isIn(expectedPathStringSet));
+            });
+        } finally {
+            FileUtils.deleteDirectory(unzipTempPath.toFile());
+            FileUtils.deleteDirectory(zipTempPath.toFile());
+        }
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/common-app-api/src/test/resources/zip-slip/zip-slip-linux.zip b/common-app-api/src/test/resources/zip-slip/zip-slip-linux.zip
new file mode 100644 (file)
index 0000000..38b3f49
Binary files /dev/null and b/common-app-api/src/test/resources/zip-slip/zip-slip-linux.zip differ
diff --git a/common-app-api/src/test/resources/zip-slip/zip-slip-windows.zip b/common-app-api/src/test/resources/zip-slip/zip-slip-windows.zip
new file mode 100644 (file)
index 0000000..3474c88
Binary files /dev/null and b/common-app-api/src/test/resources/zip-slip/zip-slip-windows.zip differ
diff --git a/common-app-api/src/test/resources/zip/extract-test.zip b/common-app-api/src/test/resources/zip/extract-test.zip
new file mode 100644 (file)
index 0000000..880452f
Binary files /dev/null and b/common-app-api/src/test/resources/zip/extract-test.zip differ
index f4b9ebf..025e3a9 100644 (file)
@@ -17,7 +17,7 @@
       <groupId>org.openecomp.sdc</groupId>
       <artifactId>common-app-api</artifactId>
       <version>${project.version}</version>
-      <scope>provided</scope>
+      <scope>compile</scope>
     </dependency>
 
     <dependency>
index bb26e6a..eb60d95 100644 (file)
@@ -34,8 +34,8 @@ import org.apache.commons.beanutils.BeanUtils;
 
 public class CommonUtil {
 
-    private static final String DEFAULT = "default";
-    private static final String UNDERSCORE_DEFAULT = "_default";
+    public static final String DEFAULT = "default";
+    public static final String UNDERSCORE_DEFAULT = "_default";
     private static ImmutableSet<Class<?>> complexClassType = ImmutableSet.of(Map.class, String.class, Integer.class, Float.class,
             Double.class, Set.class, Object.class, List.class);
 
index 97bc375..4f4258a 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.openecomp.sdcrests.vsp.rest.data;
 
-import java.io.IOException;
 import java.security.cert.CertificateException;
 import java.util.List;
 import java.util.Map;
@@ -29,6 +28,7 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.cxf.jaxrs.ext.multipart.Attachment;
 import org.openecomp.core.utilities.file.FileContentHandler;
 import org.openecomp.sdc.common.utils.CommonUtil;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
 import org.openecomp.sdc.vendorsoftwareproduct.security.SecurityManager;
@@ -61,7 +61,7 @@ public class PackageArchive {
         try {
             handlerPair = CommonUtil.getFileContentMapFromOrchestrationCandidateZip(
                 outerPackageFileBytes);
-        } catch (IOException exception) {
+        } catch (final ZipException exception) {
             LOG.error("Error reading files inside archive", exception);
         }
     }
index 42c77b9..90f8ad3 100644 (file)
 
 package org.openecomp.sdc.validation.impl;
 
-import org.apache.commons.collections4.CollectionUtils;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import org.apache.commons.collections4.MapUtils;
 import org.openecomp.core.utilities.file.FileContentHandler;
 import org.openecomp.core.utilities.file.FileUtils;
@@ -30,6 +34,8 @@ import org.openecomp.sdc.common.errors.ErrorCategory;
 import org.openecomp.sdc.common.errors.ErrorCode;
 import org.openecomp.sdc.common.errors.Messages;
 import org.openecomp.sdc.common.utils.SdcCommon;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.datatypes.error.ErrorMessage;
 import org.openecomp.sdc.heat.datatypes.structure.ValidationStructureList;
 import org.openecomp.sdc.heat.services.tree.HeatTreeManager;
@@ -38,79 +44,35 @@ import org.openecomp.sdc.validation.UploadValidationManager;
 import org.openecomp.sdc.validation.types.ValidationFileResponse;
 import org.openecomp.sdc.validation.util.ValidationManagerUtil;
 
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
 
 /**
  * Created by TALIO on 4/20/2016.
  */
 public class UploadValidationManagerImpl implements UploadValidationManager {
-  private static FileContentHandler getFileContentMapFromZip(byte[] uploadFileData)
-      throws IOException, CoreException {
-
-    ZipEntry zipEntry;
-    List<String> folderList = new ArrayList<>();
-    FileContentHandler mapFileContent = new FileContentHandler();
-    try (ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(uploadFileData))) {
-
-      byte[] fileByteContent;
-      String currentEntryName;
-
-      while ((zipEntry = inputZipStream.getNextEntry()) != null) {
-        currentEntryName = zipEntry.getName();
-        // else, get the file content (as byte array) and save it in a map.
-        fileByteContent = FileUtils.toByteArray(inputZipStream);
-
-        int index = lastIndexFileSeparatorIndex(currentEntryName);
-        String currSubstringWithoutSeparator =
-            currentEntryName.substring(index + 1, currentEntryName.length());
-        if (index != -1) {
-          if (currSubstringWithoutSeparator.length() > 0) {
-            mapFileContent.addFile(currentEntryName.substring(index + 1, currentEntryName.length()),
-                fileByteContent);
-          } else {
-            folderList.add(currentEntryName);
-          }
-        } else {
-          mapFileContent.addFile(currentEntryName, fileByteContent);
-        }
-      }
-    } catch (RuntimeException exception) {
-      throw new IOException(exception);
+
+  private static FileContentHandler getFileContentMapFromZip(byte[] uploadFileData) throws IOException {
+    final Map<String, byte[]> zipFileAndByteMap;
+    try {
+      zipFileAndByteMap = ZipUtils.readZip(uploadFileData, true);
+    } catch (final ZipException e) {
+      throw new IOException(e);
     }
 
-    if (CollectionUtils.isNotEmpty(folderList)) {
+    final boolean zipHasFolders = zipFileAndByteMap.values().stream().anyMatch(Objects::isNull);
+    if (zipHasFolders) {
       throw new CoreException((new ErrorCode.ErrorCodeBuilder())
           .withMessage(Messages.ZIP_SHOULD_NOT_CONTAIN_FOLDERS.getErrorMessage())
           .withId(Messages.ZIP_SHOULD_NOT_CONTAIN_FOLDERS.getErrorMessage())
           .withCategory(ErrorCategory.APPLICATION).build());
-
     }
+    final FileContentHandler mapFileContent = new FileContentHandler();
+    zipFileAndByteMap.entrySet().stream()
+        .filter(entry -> entry.getValue() != null)
+        .forEach(zipEntry -> mapFileContent.addFile(zipEntry.getKey(), zipEntry.getValue()));
 
     return mapFileContent;
   }
 
-  private static int lastIndexFileSeparatorIndex(String filePath) {
-    int length = filePath.length() - 1;
-
-    for (int i = length; i >= 0; i--) {
-      char currChar = filePath.charAt(i);
-      if (currChar == '/' || currChar == File.separatorChar || currChar == File.pathSeparatorChar) {
-        return i;
-      }
-    }
-    // if we've reached to the start of the string and didn't find file separator - return -1
-    return -1;
-  }
-
   @Override
   public ValidationFileResponse validateFile(String type, InputStream fileToValidate)
       throws IOException {
index 61d1799..8f0029a 100644 (file)
@@ -32,6 +32,7 @@ import org.openecomp.sdc.common.errors.CoreException;
 import org.openecomp.sdc.common.errors.Messages;
 import org.openecomp.sdc.common.utils.CommonUtil;
 import org.openecomp.sdc.common.utils.SdcCommon;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.datatypes.error.ErrorLevel;
 import org.openecomp.sdc.datatypes.error.ErrorMessage;
 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.OrchestrationTemplateCandidateData;
@@ -58,7 +59,7 @@ public class OrchestrationTemplateCSARHandler extends BaseOrchestrationTemplateH
       folderList = fileContentMapFromOrchestrationCandidateZip.getRight();
       Validator validator = ValidatorFactory.getValidator(contentMap);
       uploadFileResponse.addStructureErrors(validator.validateContent(contentMap, folderList));
-    } catch (IOException exception) {
+    } catch (final ZipException | IOException exception) {
       logger.error(exception.getMessage(), exception);
       uploadFileResponse.addStructureError(
           SdcCommon.UPLOAD_FILE,
index 1228098..7a183c0 100644 (file)
@@ -18,7 +18,9 @@ package org.openecomp.sdc.vendorsoftwareproduct.upload.csar;
 
 
 import static junit.framework.TestCase.assertTrue;
+import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 
@@ -161,7 +163,7 @@ public class UploadCSARFileTest {
       onboardPackageInfo = new OnboardPackageInfo(csarFileName, OnboardingTypesEnum.CSAR.toString(),
               convertFileInputStream(inputStream));
       uploadFileResponse = candidateManager.upload(vspDetails, onboardPackageInfo);
-      assertEquals(expectedErrorsNumber, uploadFileResponse.getErrors().size());
+      assertThat(String.format("Expecting %s error(s) in file '%s'", expectedErrorsNumber, csarFileName), uploadFileResponse.getErrors().size(), is(expectedErrorsNumber));
     }
     return uploadFileResponse;
   }
index ae7d44e..8610ecb 100644 (file)
 package org.openecomp.sdc.common.utils;
 
 import com.google.common.collect.Multimap;
-
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.openecomp.core.utilities.file.FileContentHandler;
-import org.openecomp.core.utilities.file.FileUtils;
 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
 import org.openecomp.sdc.common.errors.CoreException;
 import org.openecomp.sdc.common.errors.ErrorCategory;
 import org.openecomp.sdc.common.errors.ErrorCode;
 import org.openecomp.sdc.common.errors.Messages;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipInputStream;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 
 public class CommonUtil {
-  static final String DEFAULT = "default";
-  static final String _DEFAULT = "_default";
 
   private CommonUtil() {
     // prevent instantiation
   }
 
-  public static FileContentHandler validateAndUploadFileContent(OnboardingTypesEnum type,
-                                                                byte[] uploadedFileData)
-      throws IOException {
-    return getFileContentMapFromOrchestrationCandidateZipAndValidateNoFolders(type,
-        uploadedFileData);
-  }
-
   /**
-   * Gets files out of the zip AND validates zip is flat (no folders)
+   * Reads the files from the zip AND validates zip is flat (no folders).
    *
-   * @param uploadFileData zip file
+   * @param type the onboarding type
+   * @param uploadedFileData zip file bytes
    * @return FileContentHandler if input is valid and has no folders
+   * @throws IOException when the zip could not be read
    */
-  private static FileContentHandler getFileContentMapFromOrchestrationCandidateZipAndValidateNoFolders(
-      OnboardingTypesEnum type, byte[] uploadFileData)
-      throws IOException {
-    Pair<FileContentHandler, List<String>> pair =
-        getFileContentMapFromOrchestrationCandidateZip(uploadFileData);
-
+  public static FileContentHandler validateAndUploadFileContent(final OnboardingTypesEnum type,
+                                                                final byte[] uploadedFileData) throws IOException {
+    final Pair<FileContentHandler, List<String>> pair;
+    try {
+      pair = getFileContentMapFromOrchestrationCandidateZip(uploadedFileData);
+    } catch (final ZipException e) {
+      throw new IOException(e);
+    }
     if (isFileOriginFromZip(type.toString())) {
       validateNoFolders(pair.getRight());
     }
@@ -84,47 +72,22 @@ public class CommonUtil {
   }
 
   public static Pair<FileContentHandler, List<String>> getFileContentMapFromOrchestrationCandidateZip(
-      byte[] uploadFileData)
-      throws IOException {
-    ZipEntry zipEntry;
-    List<String> folderList = new ArrayList<>();
-    FileContentHandler mapFileContent = new FileContentHandler();
-    try (ByteArrayInputStream in = new ByteArrayInputStream(uploadFileData);
-         ZipInputStream inputZipStream = new ZipInputStream(in)) {
-      byte[] fileByteContent;
-      String currentEntryName;
-
-      while ((zipEntry = inputZipStream.getNextEntry()) != null) {
-        assertEntryNotVulnerable(zipEntry);
-        currentEntryName = zipEntry.getName();
-        fileByteContent = FileUtils.toByteArray(inputZipStream);
-
-        int index = lastIndexFileSeparatorIndex(currentEntryName);
-        if (index != -1) {
-          folderList.add(currentEntryName);
-        }
-        if (isFile(currentEntryName)) {
-          mapFileContent.addFile(currentEntryName, fileByteContent);
-        }
+      byte[] uploadFileData) throws ZipException {
+    final Map<String, byte[]> zipFileMap = ZipUtils.readZip(uploadFileData, true);
+    final List<String> folderList = new ArrayList<>();
+    final FileContentHandler mapFileContent = new FileContentHandler();
+
+    zipFileMap.forEach((key, value) -> {
+      if (value == null) {
+        folderList.add(key);
+      } else {
+        mapFileContent.addFile(key, value);
       }
-
-    } catch (RuntimeException exception) {
-      throw new IOException(exception);
-    }
+    });
 
     return new ImmutablePair<>(mapFileContent, folderList);
   }
 
-  private static void assertEntryNotVulnerable(ZipEntry entry) throws ZipException {
-    if (entry.getName().contains("../")) {
-      throw new ZipException("Path traversal attempt discovered.");
-    }
-  }
-
-  private static boolean isFile(String currentEntryName) {
-    return !(currentEntryName.endsWith("\\") || currentEntryName.endsWith("/"));
-  }
-
   private static void validateNoFolders(List<String> folderList) {
     if (CollectionUtils.isNotEmpty(folderList)) {
       throw new CoreException((new ErrorCode.ErrorCodeBuilder())
@@ -134,19 +97,6 @@ public class CommonUtil {
     }
   }
 
-  private static int lastIndexFileSeparatorIndex(String filePath) {
-    int length = filePath.length() - 1;
-
-    for (int i = length; i >= 0; i--) {
-      char currChar = filePath.charAt(i);
-      if (currChar == '/' || currChar == File.separatorChar || currChar == File.pathSeparatorChar) {
-        return i;
-      }
-    }
-    // if we've reached to the start of the string and didn't find file separator - return -1
-    return -1;
-  }
-
   private static boolean validateFilesExtensions(Set<String> allowedExtensions, FileContentHandler
       files) {
     for (String fileName : files.getFileList()) {
index bc0bd13..119616a 100644 (file)
 
 package org.openecomp.sdc.common.utils;
 
-import org.testng.annotations.Test;
+import static org.onap.sdc.tosca.services.CommonUtil.DEFAULT;
+import static org.onap.sdc.tosca.services.CommonUtil.UNDERSCORE_DEFAULT;
+import static org.testng.Assert.assertTrue;
 
 import java.util.HashMap;
 import java.util.Map;
-
-import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
 
 public class CommonUtilTest {
 
     @Test
     public void testGetObjectAsMap() {
-        Map<String, String> obj = new HashMap<>(1);
-        obj.put(CommonUtil.DEFAULT, "");
-        Map<String, Object> newMap = CommonUtil.getObjectAsMap(obj);
-
-        boolean exists = newMap.containsKey(CommonUtil._DEFAULT);
-
-        assertTrue(exists);
+        final Map<String, String> obj = new HashMap<>(1);
+        obj.put(DEFAULT, "");
+        assertTrue(CommonUtil.getObjectAsMap(obj).containsKey(UNDERSCORE_DEFAULT));
     }
+
 }
index ce88037..b86964f 100644 (file)
             <artifactId>commons-codec</artifactId>
             <version>${commons.codec.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest</artifactId>
+            <version>${hamcrest.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-library</artifactId>
+            <version>${hamcrest.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <artifactId>openecomp-sdc-logging-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.openecomp.sdc</groupId>
+            <artifactId>common-app-api</artifactId>
+            <version>${project.version}</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
 </project>
index c807d1b..31338dc 100644 (file)
 
 package org.openecomp.core.utilities.file;
 
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
-import org.onap.sdc.tosca.services.YamlUtil;
-import org.openecomp.core.utilities.json.JsonUtil;
-
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -28,11 +23,20 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.function.Function;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipInputStream;
-import java.util.*;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.onap.sdc.tosca.services.YamlUtil;
+import org.openecomp.core.utilities.json.JsonUtil;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 
 /**
  * The type File utils.
@@ -220,26 +224,14 @@ public class FileUtils {
    *
    * @param zipData the zip data
    * @return the file content map from zip
-   * @throws IOException the io exception
+   * @throws ZipException when an error occurs while extracting zip files
    */
-  public static FileContentHandler getFileContentMapFromZip(byte[] zipData) throws IOException {
-
-    try (ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(zipData))) {
-
-      FileContentHandler mapFileContent = new FileContentHandler();
-
-      ZipEntry zipEntry;
-
-      while ((zipEntry = inputZipStream.getNextEntry()) != null) {
-        assertEntryNotVulnerable(zipEntry);
-        mapFileContent.addFile(zipEntry.getName(), FileUtils.toByteArray(inputZipStream));
-      }
-
-      return mapFileContent;
-
-    } catch (RuntimeException exception) {
-      throw new IOException(exception);
-    }
+  public static FileContentHandler getFileContentMapFromZip(byte[] zipData)
+      throws ZipException {
+    final Map<String, byte[]> zipFileAndByteMap = ZipUtils.readZip(zipData, true);
+    final FileContentHandler mapFileContent = new FileContentHandler();
+    mapFileContent.setFiles(zipFileAndByteMap);
+    return mapFileContent;
   }
 
 
@@ -286,20 +278,28 @@ public class FileUtils {
    * @return a map containing file names and their absolute paths
    * @throws IOException the io exception
    */
-  public static Map<String, String> writeFilesFromFileContentHandler(FileContentHandler
-                                                                         fileContentHandler,
-                                                                     Path dir)
-      throws IOException {
-
+  public static Map<String, String> writeFilesFromFileContentHandler(final FileContentHandler fileContentHandler,
+                                                                     final Path dir) throws IOException {
     File file;
-    File dirFile = dir.toFile();
-    Map<String, String> filePaths = new HashMap<>();
-    for (Map.Entry<String, byte[]> fileEntry : fileContentHandler.getFiles().entrySet()) {
+    final File dirFile = dir.toFile();
+    final Map<String, String> filePaths = new HashMap<>();
+    for (final Map.Entry<String, byte[]> fileEntry : fileContentHandler.getFiles().entrySet()) {
       file = new File(dirFile, fileEntry.getKey());
-      file.getParentFile().mkdirs();
       filePaths.put(fileEntry.getKey(), file.getAbsolutePath());
-      try (FileOutputStream fop = new FileOutputStream(file.getAbsolutePath());) {
-        fop.write(fileEntry.getValue());
+      final byte[] fileBytes = fileEntry.getValue();
+      if (fileBytes == null) {
+        if (!file.exists() && !file.mkdirs()) {
+          throw new IOException("Could not create directory " + file.getAbsolutePath());
+        }
+        continue;
+      } else {
+        if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
+          throw new IOException("Could not create parent directory for " + file.getAbsolutePath());
+        }
+      }
+
+      try (final FileOutputStream fop = new FileOutputStream(file.getAbsolutePath());) {
+        fop.write(fileBytes);
         fop.flush();
       }
     }
@@ -318,10 +318,4 @@ public class FileUtils {
         fileExtension.equalsIgnoreCase(FileExtension.YAML.getDisplayName());
   }
 
-  private static void assertEntryNotVulnerable(ZipEntry entry) throws ZipException {
-    if (entry.getName().contains("../")) {
-      throw new ZipException("Path traversal attempt discovered.");
-    }
-  }
-
 }
index a4928ac..facfe57 100644 (file)
 package org.openecomp.core.utilities.file;
 
 import static junit.framework.TestCase.assertTrue;
-import static org.junit.Assert.assertEquals;
+import static org.hamcrest.Matchers.aMapWithSize;
+import static org.hamcrest.Matchers.anEmptyMap;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
 
 import java.io.File;
 import java.io.IOException;
@@ -34,6 +38,7 @@ import java.util.stream.Stream;
 import org.apache.commons.io.IOUtils;
 import org.junit.Assert;
 import org.junit.Test;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 
 /**
  * @author EVITALIY
@@ -74,25 +79,22 @@ public class FileUtilsTest {
     }
 
     @Test
-    public void testWriteFilesFromFileContentHandler() throws IOException {
-        Path dir = Files.createTempDirectory("CSAR_" + System.currentTimeMillis());
+    public void testWriteFilesFromFileContentHandler() throws IOException, ZipException {
+        final Path tempDirectory = Files.createTempDirectory("CSAR_" + System.currentTimeMillis());
         try {
-            byte[] uploadedFileData = IOUtils.toByteArray(
-                FileUtilsTest.class.getResource("resource-Spgw-csar-ZTE" +
-                    ".csar"));
-            FileContentHandler contentMap = FileUtils.getFileContentMapFromZip(uploadedFileData);
-            Map<String, String> filePaths = FileUtils.writeFilesFromFileContentHandler(contentMap,
-                dir);
-
-            assertFalse(filePaths.isEmpty());
-            assertEquals(filePaths.size(), 18);
-            for (Map.Entry<String, String> fileEntry : filePaths.entrySet()) {
-                File f = new File(fileEntry.getValue());
-                assertTrue(f.exists());
+            byte[] uploadedFileData =
+                IOUtils.toByteArray(FileUtilsTest.class.getResource("resource-Spgw-csar-ZTE.csar"));
+            final FileContentHandler contentMap = FileUtils.getFileContentMapFromZip(uploadedFileData);
+            final Map<String, String> filePaths = FileUtils.writeFilesFromFileContentHandler(contentMap, tempDirectory);
+
+            assertThat("The file map should not be empty", filePaths, is(not(anEmptyMap())));
+            assertThat("The file map should have size 20", filePaths, is(aMapWithSize(20)));
+            for (final Map.Entry<String, String> fileEntry : filePaths.entrySet()) {
+                final File f = new File(fileEntry.getValue());
+                assertThat(String.format("The file '%s' is expected to", f.getAbsolutePath()), f.exists(), is(true));
             }
-        }
-        finally {
-            org.apache.commons.io.FileUtils.deleteDirectory(dir.toFile());
+        } finally {
+            org.apache.commons.io.FileUtils.deleteDirectory(tempDirectory.toFile());
         }
     }
 
@@ -106,22 +108,22 @@ public class FileUtilsTest {
 
     @Test
     public void testGetFileWithoutExtention() {
-        Assert.assertEquals(FileUtils.getFileWithoutExtention("test.txt"), "test");
+        Assert.assertEquals("test", FileUtils.getFileWithoutExtention("test.txt"));
     }
 
     @Test
     public void testGetFileWithoutExtentionContainsNoExtension() {
-        Assert.assertEquals(FileUtils.getFileWithoutExtention("test"), "test");
+        Assert.assertEquals("test", FileUtils.getFileWithoutExtention("test"));
     }
 
     @Test
     public void testGetFileExtention() {
-        Assert.assertEquals(FileUtils.getFileExtension("test.txt"), "txt");
+        Assert.assertEquals("txt", FileUtils.getFileExtension("test.txt"));
     }
 
     @Test
     public void testGetNetworkPackageName() {
-        Assert.assertEquals(FileUtils.getNetworkPackageName("heat.zip"), "heat");
+        Assert.assertEquals("heat", FileUtils.getNetworkPackageName("heat.zip"));
     }
 
     @Test
@@ -191,6 +193,6 @@ public class FileUtilsTest {
         }
 
         Assert.assertNotNull(inputStream);
-        Assert.assertEquals(builder.toString(), "hello-test");
+        Assert.assertEquals("hello-test", builder.toString());
     }
 }
index dac9eae..ca1fbe1 100644 (file)
 
 package org.openecomp.sdc.enrichment.impl.external.artifact;
 
+import static org.openecomp.sdc.tosca.services.ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME;
+import static org.openecomp.sdc.tosca.services.ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
 import org.onap.sdc.tosca.datatypes.model.Directive;
 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
@@ -29,6 +42,7 @@ import org.openecomp.core.model.types.ServiceArtifact;
 import org.openecomp.core.utilities.file.FileContentHandler;
 import org.openecomp.core.utilities.file.FileUtils;
 import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.datatypes.error.ErrorLevel;
 import org.openecomp.sdc.datatypes.error.ErrorMessage;
 import org.openecomp.sdc.enrichment.EnrichmentInfo;
@@ -45,13 +59,6 @@ import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentMonitoringUploadEntity;
 import org.openecomp.sdc.versioning.dao.types.Version;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
-
-import static org.openecomp.sdc.tosca.services.ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME;
-import static org.openecomp.sdc.tosca.services.ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME;
-
 public class MonitoringMibEnricher implements ExternalArtifactEnricherInterface {
 
   private EnrichedServiceModelDao enrichedServiceModelDao;
@@ -265,8 +272,8 @@ public class MonitoringMibEnricher implements ExternalArtifactEnricherInterface
     try {
       mibs = FileUtils
           .getFileContentMapFromZip(FileUtils.toByteArray(monitoringArtifactInfo.getContent()));
-    } catch (IOException ioException) {
-      log.error("Failed to get file content map from zip ", ioException);
+    } catch (ZipException ex) {
+      log.error("Failed to get file content map from zip ", ex);
       ErrorMessage.ErrorMessageUtil
           .addMessage(mibServiceArtifact.getName() + "." + type.name(), errors)
           .add(new ErrorMessage(ErrorLevel.ERROR, Messages.INVALID_ZIP_FILE.getErrorMessage()));
index e112ef4..22ac1e8 100644 (file)
@@ -18,17 +18,21 @@ package org.openecomp.core.externaltesting.impl;
 
 import com.amdocs.zusammen.utils.fileutils.json.JsonUtil;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableSet;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParseException;
+import java.util.Map.Entry;
 import lombok.EqualsAndHashCode;
-import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.onap.sdc.tosca.services.YamlUtil;
 import org.openecomp.core.externaltesting.api.*;
 import org.openecomp.core.externaltesting.errors.ExternalTestingException;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
@@ -58,7 +62,6 @@ import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
 import java.util.zip.ZipOutputStream;
 
 public class ExternalTestingManagerImpl implements ExternalTestingManager {
@@ -97,6 +100,8 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager {
 
   private static final String SDC_CSAR = "sdc-csar";
   private static final String SDC_HEAT = "sdc-heat";
+  private final ImmutableSet<String> relevantArchiveFileExtensionSet =
+      ImmutableSet.of("yaml", "meta", "yml", "json", "env");
 
 
   private VersioningManager versioningManager;
@@ -721,10 +726,8 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager {
   private void processArchive(final VtpTestExecutionRequest test, final MultiValueMap<String, Object> body, final byte[] zip) {
 
     // We need to make one pass through the zip input stream.  Pull out files that match our expectations into a temporary
-    // map that we can process over.   These are not huge files so we shouldn't need to worry about memory.
-
-    List<String> extensions = Arrays.asList(".yaml", ".meta", ".yml", ".json", ".env");
-    final Map<String, byte[]> contentWeCareAbout = extractRelevantContent(zip, extensions);
+    // map that we can process over. These are not huge files so we shouldn't need to worry about memory.
+    final Map<String, byte[]> contentWeCareAbout = extractRelevantContent(zip);
 
     // VTP does not support concurrent executions of the same test with the same associated file name.
     // It writes files to /tmp and if we were to send two requests with the same file, the results are unpredictable.
@@ -891,34 +894,30 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager {
    * @param zip csar/heat zip to iterate over
    * @return relevant content from the archive file as a map.
    */
-  private Map<String, byte[]> extractRelevantContent(final byte[] zip, final List<String> extensions) {
-    final Map<String, byte[]> rv = new HashMap<>();  // FYI, rv = return value.
-    try (ByteArrayInputStream is = new ByteArrayInputStream(zip)) {
-      try (ZipInputStream zipStream = new ZipInputStream(is)) {
-        ZipEntry entry;
-        while ((entry = zipStream.getNextEntry()) != null) {
-          final String entryName = entry.getName();
-
-          // NOTE: leaving this debugging in for dublin...
-          logger.debug("archive contains entry {}", entryName);
-
-          extractIfMatching(extensions, rv, zipStream, entryName);
-        }
-      }
-    }
-    catch (IOException ex) {
-      logger.error("error encountered processing archive", ex);
-      throw new ExternalTestingException(SDC_RESOLVER_ERR, 500, ex.getMessage());
+  private Map<String, byte[]> extractRelevantContent(final byte[] zip) {
+    final Map<String, byte[]> zipFileAndByteMap;
+    try {
+      zipFileAndByteMap = ZipUtils.readZip(zip, false);
+    } catch (final ZipException ex) {
+      logger.error("An error occurred while processing archive", ex);
+      throw new ExternalTestingException(SDC_RESOLVER_ERR, 500, ex.getMessage(), ex);
     }
-    return rv;
+
+    return zipFileAndByteMap.entrySet().stream()
+        .filter(stringEntry -> hasRelevantExtension(stringEntry.getKey()))
+        .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
   }
 
-  private void extractIfMatching(List<String> extensions, Map<String, byte[]> rv, ZipInputStream zipStream, String entryName) throws IOException {
-    int idx = entryName.lastIndexOf('.');
-    if ((idx >= 0) && (extensions.contains(entryName.substring(idx)))) {
-      byte[] content = IOUtils.toByteArray(zipStream);
-      rv.put(entryName, content);
-    }
+  /**
+   * Checks if the file matches with a expected extension.
+   *
+   * @param filePath the file path
+   * @return {@code true} if the file extension matches with {@link #relevantArchiveFileExtensionSet}, {@code false}
+   * otherwise
+   */
+  private boolean hasRelevantExtension(final String filePath) {
+    final String entryExtension = FilenameUtils.getExtension(filePath);
+    return StringUtils.isNotEmpty(entryExtension) && (relevantArchiveFileExtensionSet.contains(entryExtension));
   }
 
   /**
index 04ddf6e..c429709 100644 (file)
@@ -18,6 +18,16 @@ package org.openecomp.core.externaltesting.impl;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.tuple.Pair;
@@ -25,28 +35,37 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.*;
+import org.mockito.ArgumentMatchers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 import org.mockito.junit.MockitoJUnitRunner;
-import org.openecomp.core.externaltesting.api.*;
+import org.openecomp.core.externaltesting.api.ClientConfiguration;
+import org.openecomp.core.externaltesting.api.ExternalTestingManager;
+import org.openecomp.core.externaltesting.api.RemoteTestingEndpointDefinition;
+import org.openecomp.core.externaltesting.api.TestTreeNode;
+import org.openecomp.core.externaltesting.api.VtpNameDescriptionPair;
+import org.openecomp.core.externaltesting.api.VtpTestCase;
+import org.openecomp.core.externaltesting.api.VtpTestExecutionRequest;
+import org.openecomp.core.externaltesting.api.VtpTestExecutionResponse;
 import org.openecomp.core.externaltesting.errors.ExternalTestingException;
 import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager;
 import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager;
 import org.openecomp.sdc.versioning.VersioningManager;
 import org.openecomp.sdc.versioning.dao.types.Version;
 import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.http.*;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.web.client.HttpServerErrorException;
 import org.springframework.web.client.HttpStatusCodeException;
 import org.springframework.web.client.ResourceAccessException;
 import org.springframework.web.client.RestTemplate;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.*;
-
 @RunWith(MockitoJUnitRunner.class)
 public class ExternalTestingManagerImplTest {
 
index 3255e18..07dc53d 100644 (file)
@@ -44,6 +44,8 @@ import org.openecomp.sdc.common.errors.ErrorCategory;
 import org.openecomp.sdc.common.errors.ErrorCode;
 import org.openecomp.sdc.common.errors.Messages;
 import org.openecomp.sdc.common.utils.SdcCommon;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipSlipException;
 import org.openecomp.sdc.datatypes.error.ErrorLevel;
 import org.openecomp.sdc.datatypes.error.ErrorMessage;
 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
@@ -426,6 +428,11 @@ public class CandidateServiceImpl implements CandidateService {
              new ByteArrayInputStream(contentData.array()))) {
       ZipEntry zipEntry;
       while ((zipEntry = zipStream.getNextEntry()) != null) {
+        try {
+          ZipUtils.checkForZipSlipInRead(zipEntry);
+        } catch (ZipSlipException e) {
+          throw new IOException(e);
+        }
         ZipEntry locZipEntry = new ZipEntry(zipEntry.getName());
         zos.putNextEntry(locZipEntry);
         byte[] buf = new byte[1024];
index 14cf90a..1bc547a 100644 (file)
@@ -58,6 +58,8 @@ import org.openecomp.core.utilities.file.FileContentHandler;
 import org.openecomp.core.utilities.file.FileUtils;
 import org.openecomp.sdc.common.errors.CoreException;
 import org.openecomp.sdc.common.errors.SdcRuntimeException;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipSlipException;
 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
 import org.openecomp.sdc.tosca.datatypes.ToscaFlatData;
 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
@@ -123,6 +125,7 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
         try (ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(toscaCsarPackage))) {
             ZipEntry zipEntry;
             while ((zipEntry = inputZipStream.getNextEntry()) != null) {
+                ZipUtils.checkForZipSlipInRead(zipEntry);
                 byte[] fileContent = FileUtils.toByteArray(inputZipStream);
                 String currentEntryName = zipEntry.getName();
                 if (!isFile(currentEntryName)) {
@@ -141,7 +144,7 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
                 handleToscaCsarWithoutToscaMetadata(toscaServiceModel);
             }
 
-        } catch (IOException exc) {
+        } catch (IOException | ZipSlipException exc) {
             throw new SdcRuntimeException(exc.getMessage(), exc);
         }
         return toscaServiceModel;
index 5060f4b..2907d1e 100644 (file)
@@ -28,7 +28,6 @@ import com.datastax.driver.core.Session;
 import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Path;
@@ -52,8 +51,9 @@ import org.openecomp.core.tools.commands.Command;
 import org.openecomp.core.tools.commands.CommandName;
 import org.openecomp.core.tools.importinfo.ImportProperties;
 import org.openecomp.core.tools.util.Utils;
-import org.openecomp.core.tools.util.ZipUtils;
 import org.openecomp.core.zusammen.impl.CassandraConnectionInitializer;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
 import org.yaml.snakeyaml.Yaml;
@@ -157,14 +157,14 @@ public final class ExportDataCommand extends Command {
         }, executor);
     }
 
-    private static void zipPath(Path rootDir) throws IOException {
-        LocalDateTime date = LocalDateTime.now();
-        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
-        String dateStr = date.format(formatter);
-        dateStr = dateStr.replaceAll(":", "_");
-        String zipFile = System.getProperty("user.home") + File.separatorChar + "onboarding_import" + dateStr + ".zip";
-        ZipUtils.createZip(zipFile, rootDir);
-        Utils.printMessage(LOGGER, "Exported file :" + zipFile);
+    private static void zipPath(final Path rootDir) throws ZipException {
+        final LocalDateTime date = LocalDateTime.now();
+        final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
+        final String dateStr = date.format(formatter).replace(":", "_");
+        final Path zipFile = Paths.get(System.getProperty("user.home"),String.format("onboarding_import%s.zip", dateStr));
+        ZipUtils.createZipFromPath(rootDir, zipFile);
+        Utils.printMessage(LOGGER, "Zip file was created " + zipFile.toString());
+        Utils.printMessage(LOGGER, "Exported file :" + zipFile.toString());
     }
 
 
index 1f5281a..cff8eb9 100644 (file)
@@ -35,8 +35,9 @@ import org.openecomp.core.tools.commands.Command;
 import org.openecomp.core.tools.commands.CommandName;
 import org.openecomp.core.tools.exportinfo.ExportDataCommand;
 import org.openecomp.core.tools.util.Utils;
-import org.openecomp.core.tools.util.ZipUtils;
 import org.openecomp.core.zusammen.impl.CassandraConnectionInitializer;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.openecomp.sdc.logging.api.Logger;
 import org.openecomp.sdc.logging.api.LoggerFactory;
 
@@ -66,7 +67,7 @@ public class ImportDataCommand extends Command {
                 files.forEach(new ImportSingleTable()::importFile);
             }
             FileUtils.forceDelete(outputFolder.toFile()); // leaves directory clean
-        } catch (IOException e) {
+        } catch (final IOException | ZipException e) {
             Utils.logError(LOGGER, e);
         }
         return true;
diff --git a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/util/ZipUtils.java b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/util/ZipUtils.java
deleted file mode 100644 (file)
index f58f18d..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.core.tools.util;
-
-import com.google.common.io.ByteStreams;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
-
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-public class ZipUtils {
-
-    private static final Logger logger = LoggerFactory.getLogger(ZipUtils.class);
-
-    private ZipUtils() {
-        // prevent instantiation
-    }
-
-    public static void createZip(String zipFileName, Path dir) throws IOException {
-        File dirObj = dir.toFile();
-        Path zippedFile = Files.createFile(Paths.get(zipFileName));
-        try (
-                FileOutputStream fileOutputStream = new FileOutputStream(File.separator + zippedFile.toFile());
-                BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
-                ZipOutputStream out = new ZipOutputStream(bos)) {
-            File[] files = dirObj.listFiles();
-            for (File file : files) {
-                out.putNextEntry(new ZipEntry(file.getName()));
-                Files.copy(Paths.get(file.getPath()), out);
-                out.closeEntry();
-            }
-            Utils.printMessage(logger, "Zip file was created " + zipFileName);
-        }
-    }
-
-    public static void unzip(Path zipFile, Path outputFolder) throws IOException {
-        if (zipFile == null || outputFolder == null) {
-            return;
-        }
-        createDirectoryIfNotExists(outputFolder);
-
-        try (FileInputStream fileInputStream = new FileInputStream(zipFile.toFile());
-             ZipInputStream stream = new ZipInputStream(fileInputStream)) {
-
-            ZipEntry entry;
-            while ((entry = stream.getNextEntry()) != null) {
-                assertEntryNotVulnerable(entry);
-                String fileName = entry.getName();
-                File newFile = new File(outputFolder.toString() + File.separator + fileName);
-                if (entry.isDirectory()) {
-                    createDirectoryIfNotExists(newFile.toPath());
-                } else {
-                    persistFile(stream, newFile);
-                }
-            }
-        }
-
-    }
-
-    private static void persistFile(ZipInputStream stream, File newFile) throws IOException {
-        new File(newFile.getParent()).mkdirs();
-        try (FileOutputStream outputStream = new FileOutputStream(newFile)) {
-            ByteStreams.copy(stream, outputStream);
-        }
-    }
-
-    private static void createDirectoryIfNotExists(Path path) throws IOException {
-        if (!path.toFile().exists()) {
-            Files.createDirectories(path);
-        }
-    }
-
-    private static void assertEntryNotVulnerable(ZipEntry entry) throws ZipException {
-        if (entry.getName().contains("../")) {
-            throw new ZipException("Path traversal attempt discovered.");
-        }
-    }
-}
-
index be235d0..b7eaf99 100644 (file)
 
 package org.openecomp.sdc.ci.tests.utils;
 
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertTrue;
+import static org.testng.AssertJUnit.fail;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import org.apache.commons.collections4.MapUtils;
 import org.openecomp.sdc.ci.tests.datatypes.enums.UserRoleEnum;
-import org.openecomp.sdc.ci.tests.tosca.datatypes.*;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaDefinition;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaGroupsTopologyTemplateDefinition;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaImportsDefinition;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaInputsTopologyTemplateDefinition;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaMetadataDefinition;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaNodeTemplatesTopologyTemplateDefinition;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaParameterConstants;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaSubstitutionMappingsDefinition;
+import org.openecomp.sdc.ci.tests.tosca.datatypes.ToscaTopologyTemplateDefinition;
 import org.openecomp.sdc.ci.tests.utils.general.ElementFactory;
 import org.openecomp.sdc.ci.tests.utils.rest.BaseRestUtils;
 import org.openecomp.sdc.ci.tests.utils.rest.ImportRestUtils;
 import org.openecomp.sdc.common.http.client.api.HttpResponse;
-import org.openecomp.sdc.common.util.ZipUtil;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.common.zip.exception.ZipException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.yaml.snakeyaml.Yaml;
 import org.yaml.snakeyaml.constructor.Constructor;
 import org.yaml.snakeyaml.introspector.PropertyUtils;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Map;
-
-import static org.testng.AssertJUnit.assertNotNull;
-import static org.testng.AssertJUnit.assertTrue;
-
 public class ToscaParserUtils {
 
        private static Logger log = LoggerFactory.getLogger(ToscaParserUtils.class.getName());
@@ -135,10 +146,8 @@ public class ToscaParserUtils {
         try {
                toscaDefinition = (ToscaDefinition) yaml.load(payload);
                } catch (Exception e) {
-                       log.debug("Failed to parse tosca yaml file");
-                       log.debug("Exception: " + e);
-                       System.out.println("Exception: " + e);
-                       assertTrue("Exception: " + e, false);
+                       log.debug("Failed to parse tosca yaml file", e);
+                       fail("Exception: " + e);
                }
         return toscaDefinition;
         
@@ -155,7 +164,6 @@ public class ToscaParserUtils {
        toscaStructure.addTypeDescription(ToscaImportsDefinition.getTypeDescription());
        toscaStructure.addTypeDescription(ToscaMetadataDefinition.getTypeDescription());
        toscaStructure.addTypeDescription(ToscaInputsTopologyTemplateDefinition.getTypeDescription());
-//     toscaStructure.addTypeDescription(ToscaInputsDefinition.getTypeDescription());
 //     Skip properties which are found in YAML, but not found in POJO
        PropertyUtils propertyUtils = new PropertyUtils();
        propertyUtils.setSkipMissingProperties(true);
@@ -193,12 +201,10 @@ public class ToscaParserUtils {
 
        }
 
-       public static String getYamlPayloadFromCsar(File csarName, String fileLocation) throws Exception {
-               
+       public static String getYamlPayloadFromCsar(File csarName, String fileLocation) throws IOException, ZipException {
                Path path = csarName.toPath();
                byte[] data = Files.readAllBytes(path);
                return getDataFromZipFileByBytes(fileLocation, data);
-               
        }
 
        /** method get file data from zip data by file location in the zip structure 
@@ -206,243 +212,16 @@ public class ToscaParserUtils {
         * @param data
         * @return
         */
-       public static String getDataFromZipFileByBytes(String fileLocation, byte[] data) {
-               Map<String, byte[]> readZip = null;
-               if (data != null && data.length > 0) {
-                       readZip = ZipUtil.readZip(data);
-
+       public static String getDataFromZipFileByBytes(String fileLocation, byte[] data) throws ZipException {
+               if (data == null || data.length == 0) {
+                       return null;
                }
-               byte[] artifactsBs = readZip.get(fileLocation);
-               String str = new String(artifactsBs, StandardCharsets.UTF_8);
-               return str;
-       }
-/*     public static Map<?, ?> getToscaYamlMap(String csarUUID, String fileLocation) throws Exception {
-               String csarPayload = CsarValidationUtils.getCsarPayload(csarUUID, fileLocation);
-               if (csarPayload != null) {
-                       Yaml yaml = new Yaml();
-                       Map<?, ?> map = (Map<?, ?>) yaml.load(csarPayload);
-                       return map;
+               final Map<String, byte[]> readZip = ZipUtils.readZip(data, false);
+               if (MapUtils.isEmpty(readZip)) {
+                       return null;
                }
-               return null;
+               byte[] artifactsBytes = readZip.get(fileLocation);
+               return new String(artifactsBytes, StandardCharsets.UTF_8);
        }
-
-       public static ToscaDefinition getToscaDefinitionObjectByCsarUuid(String csarUUID) throws Exception {
-
-               String TOSCAMetaLocation = "TOSCA-Metadata/TOSCA.meta";
-               Map<?, ?> map = getToscaYamlMap(csarUUID, TOSCAMetaLocation);
-               assertNotNull("Tosca Entry-Definitions is null", map);
-               if (map != null) {
-                       String definitionYamlLocation = (String) map.get("Entry-Definitions");
-                       Map<?, ?> toscaMap = getToscaYamlMap(csarUUID, definitionYamlLocation);
-                       assertNotNull("Tosca definition is null", toscaMap);
-                       if (toscaMap != null) {
-                               ToscaDefinition toscaDefinition = new ToscaDefinition();
-                               Set<?> keySet = toscaMap.keySet();
-                               for (Object key : keySet) {
-                                       ToscaKeysEnum toscaKey = ToscaKeysEnum.findToscaKey((String) key);
-                                       switch (toscaKey) {
-                                       case TOSCA_DEFINITION_VERSION:
-                                               getToscaDefinitionVersion(toscaMap, toscaDefinition);
-                                               break;
-                                       case NODE_TYPES:
-                                               getToscaNodeTypes(toscaMap, toscaDefinition);
-                                               break;
-                                       case TOPOLOGY_TEMPLATE:
-                                               getToscaTopologyTemplate(toscaMap, toscaDefinition);
-                                               break;
-                                       case IMPORTS:
-                                               // toscaMap.get("imports");
-                                               break;
-                                       default:
-                                               break;
-                                       }
-                               }
-                               return toscaDefinition;
-                       }
-               }
-               return null;
-
-       }
-
-       public static void getToscaDefinitionVersion(Map<?, ?> toscaMap, ToscaDefinition toscaDefinition) {
-               if (toscaMap.get("tosca_definitions_version") != null) {
-                       toscaDefinition.setTosca_definitions_version((String) toscaMap.get("tosca_definitions_version"));
-               }
-       }
-
-       // spec 90 page
-       public static void getToscaNodeTypes(Map<?, ?> toscaMap, ToscaDefinition toscaDefinition) {
-               @SuppressWarnings("unchecked")
-               Map<String, Map<String, String>> nodeTypes = (Map<String, Map<String, String>>) toscaMap.get("node_types");
-               Map<String, ToscaNodeTypesDefinition> listToscaNodeTypes = new HashMap<String, ToscaNodeTypesDefinition>();
-               if (nodeTypes != null) {
-                       for (Map.Entry<String, Map<String, String>> entry : nodeTypes.entrySet()) {
-                               ToscaNodeTypesDefinition toscaNodeTypes = new ToscaNodeTypesDefinition();
-                               String toscaNodeName = entry.getKey();
-                               toscaNodeTypes.setName(toscaNodeName);
-
-                               Map<String, String> toscaNodeType = entry.getValue();
-                               if (toscaNodeType != null) {
-                                       Set<Entry<String, String>> entrySet = toscaNodeType.entrySet();
-                                       if (entrySet != null) {
-                                               // boolean found = false;
-                                               for (Entry<String, String> toscaNodeTypeMap : entrySet) {
-                                                       String key = toscaNodeTypeMap.getKey();
-                                                       if (key.equals("derived_from")) {
-                                                               String derivedFrom = toscaNodeTypeMap.getValue();
-                                                               toscaNodeTypes.setDerived_from(derivedFrom);
-                                                               // found = true;
-                                                               break;
-                                                       } else {
-                                                               continue;
-                                                       }
-
-                                               }
-                                               // if (found == false) {
-                                               // System.out.println("Tosca file not valid,
-                                               // derived_from not found");
-                                               // }
-                                       }
-
-                               }
-//                             listToscaNodeTypes.add(toscaNodeTypes);
-                               listToscaNodeTypes.put(toscaNodeName, toscaNodeTypes);
-                       }
-                       toscaDefinition.setNode_types(listToscaNodeTypes);
-               }
-       }
-
-       public static void getToscaTopologyTemplate(Map<?, ?> toscaMap, ToscaDefinition toscaDefinition) {
-               ToscaTopologyTemplateDefinition toscaTopologyTemplate = new ToscaTopologyTemplateDefinition();
-               @SuppressWarnings("unchecked")
-               Map<String, Map<String, Object>> topologyTemplateMap = (Map<String, Map<String, Object>>) toscaMap.get("topology_template");
-//             List<ToscaNodeTemplatesTopologyTemplateDefinition> listToscaNodeTemplates = new ArrayList<>();
-               Map<String,ToscaNodeTemplatesTopologyTemplateDefinition> mapToscaNodeTemplates = new HashMap<String, ToscaNodeTemplatesTopologyTemplateDefinition>();
-
-               if (topologyTemplateMap != null) {
-                       getToscaNodeTemplates(topologyTemplateMap, mapToscaNodeTemplates);
-               }
-//             toscaTopologyTemplate.setToscaNodeTemplatesTopologyTemplateDefinition(listToscaNodeTemplates);
-               toscaTopologyTemplate.setNode_templates(mapToscaNodeTemplates);
-               toscaDefinition.setTopology_template(toscaTopologyTemplate);
-       }
-
-       public static void getToscaNodeTemplates(Map<String, Map<String, Object>> topologyTemplateMap, Map<String,ToscaNodeTemplatesTopologyTemplateDefinition> mapToscaNodeTemplates) {
-               Map<String, Object> nodeTemplatesMap = topologyTemplateMap.get("node_templates");
-               if (nodeTemplatesMap != null) {
-
-                       for (Entry<String, Object> nodeTemplates : nodeTemplatesMap.entrySet()) {
-                               ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates = new ToscaNodeTemplatesTopologyTemplateDefinition();
-                               getToscaNodeTemplatesName(nodeTemplates, toscaNodeTemplates);
-
-                               @SuppressWarnings("unchecked")
-                               Map<String, Object> node = (Map<String, Object>) nodeTemplates.getValue();
-                               getNodeTemplatesType(toscaNodeTemplates, node);
-                               getToscaNodeTemplateProperties(toscaNodeTemplates, node);
-                               getToscaNodeTemplateRequirements(toscaNodeTemplates, node);
-                               mapToscaNodeTemplates.putAll(mapToscaNodeTemplates);
-                       }
-               }
-       }
-
-       public static void getToscaNodeTemplateRequirements(ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates, Map<String, Object> node) {
-////           List<ToscaRequirementsNodeTemplatesDefinition> toscaRequirements = new ArrayList<>();
-//             List<Map<String, ToscaRequirementsNodeTemplatesDefinition>> toscaRequirements = new ArrayList<>();
-//             if (node.get("requirements") != null) {
-//                     @SuppressWarnings("unchecked")
-//                     List<Map<String, Object>> requirementList = (List<Map<String, Object>>) node.get("requirements");
-//                     for (int i = 0; i < requirementList.size(); i++) {
-//                             for (Map.Entry<String, Object> requirement : requirementList.get(i).entrySet()) {
-//                                     ToscaRequirementsNodeTemplatesDefinition toscaRequirement = new ToscaRequirementsNodeTemplatesDefinition();
-//                                     if (requirement.getKey() != null) {
-//                                             String requirementName = requirement.getKey();
-//                                             toscaRequirement.setName(requirementName);
-//                                     } else {
-//                                             log.debug("Tosca file not valid, requirements should contain name");
-//                                     }
-//
-//                                     @SuppressWarnings("unchecked")
-//                                     Map<String, String> requirementMap = (Map<String, String>) requirement.getValue();
-//                                     Set<Entry<String, String>> entrySet = requirementMap.entrySet();
-//                                     if (entrySet != null) {
-//                                             for (Entry<String, String> requirementField : entrySet) {
-//                                                     String key = requirementField.getKey();
-//                                                     switch (key) {
-//                                                     case "capability":
-//                                                             if (requirementMap.get(key) != null) {
-//                                                                     String capability = (String) requirementMap.get(key);
-//                                                                     toscaRequirement.setCapability(capability);
-//                                                                     break;
-//                                                             } else {
-//                                                                     continue;
-//                                                             }
-//                                                     case "node":
-//                                                             if (requirementMap.get(key) != null) {
-//                                                                     String requirementNode = (String) requirementMap.get(key);
-//                                                                     toscaRequirement.setNode(requirementNode);
-//                                                                     break;
-//                                                             } else {
-//                                                                     continue;
-//                                                             }
-//                                                     case "relationship":
-//                                                             if (requirementMap.get(key) != null) {
-//                                                                     String relationship = (String) requirementMap.get(key);
-//                                                                     toscaRequirement.setRelationship(relationship);
-//                                                                     break;
-//                                                             } else {
-//                                                                     continue;
-//                                                             }
-//                                                     default:
-//                                                             break;
-//                                                     }
-//                                             }
-//                                     }
-////                                   toscaRequirements.add(toscaRequirement);
-//                                     toscaRequirements.add(requirementMap);
-//                             }
-//                     }
-//             }
-////           toscaNodeTemplates.setRequirements(toscaRequirements);
-//             toscaNodeTemplates.setRequirements(requirements);
-               
-       }
-
-       public static void getToscaNodeTemplateProperties(ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates,
-                       Map<String, Object> node) {
-//             List<ToscaPropertiesNodeTemplatesDefinition> listToscaProperties = new ArrayList<>();
-               Map<String, Object> mapToscaProperties = new HashMap<>();
-               if (node.get("properties") != null) {
-                       @SuppressWarnings("unchecked")
-                       Map<String, Object> properties = (Map<String, Object>) node.get("properties");
-                       for (Map.Entry<String, Object> property : properties.entrySet()) {
-                               ToscaPropertiesNodeTemplatesDefinition toscaProperty = new ToscaPropertiesNodeTemplatesDefinition();
-                               String propertyName = property.getKey();
-                               Object propertyValue = property.getValue();
-                               toscaProperty.setName(propertyName);
-                               toscaProperty.setValue(propertyValue);
-//                             mapToscaProperties.add(toscaProperty);
-                               mapToscaProperties.put(propertyName, propertyValue);
-                       }
-               }
-               toscaNodeTemplates.setProperties(mapToscaProperties);
-       }
-
-       protected static void getNodeTemplatesType(ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates,
-                       Map<String, Object> node) {
-               if (node.get("type") != null) {
-                       String type = (String) node.get("type");
-                       toscaNodeTemplates.setType(type);
-               } else {
-                       log.debug("Tosca file not valid, nodeTemplate should contain type");
-               }
-       }
-
-       protected static void getToscaNodeTemplatesName(Entry<String, Object> nodeTemplates,
-                       ToscaNodeTemplatesTopologyTemplateDefinition toscaNodeTemplates) {
-               String name = nodeTemplates.getKey();
-               toscaNodeTemplates.setName(name);
-       }*/
-       
-       
        
 }
index 4dbc8b2..dae13a2 100644 (file)
 
 package org.openecomp.sdc.ci.tests.utils.general;
 
+import static org.testng.AssertJUnit.assertTrue;
+
 import com.aventstack.extentreports.Status;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
 import org.apache.commons.io.FileUtils;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.ci.tests.api.ComponentBaseTest;
-import org.openecomp.sdc.ci.tests.config.Config;
 import org.openecomp.sdc.ci.tests.datatypes.enums.XnfTypeEnum;
 import org.openecomp.sdc.common.util.GeneralUtility;
 import org.yaml.snakeyaml.Yaml;
 
-import java.io.*;
-import java.nio.file.Paths;
-import java.util.*;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipInputStream;
-
-import static org.testng.AssertJUnit.assertTrue;
-
 public class FileHandling {
 
 //     ------------------yaml parser methods----------------------------
@@ -264,10 +272,6 @@ public class FileHandling {
                return null;
        }
        
-//     public static Object[] getZipFileNamesFromFolder(String filepath) {
-//             return filterFileNamesFromFolder(filepath, ".zip");
-//     }
-       
        public static List<String> getZipFileNamesFromFolder(String filepath) {
                List<String> fileNamesListFromFolder = filterFileNamesListFromFolder(filepath, ".zip");
                fileNamesListFromFolder.addAll(filterFileNamesListFromFolder(filepath, ".csar"));
@@ -285,16 +289,6 @@ public class FileHandling {
                return fileCounter;
        }
        
-
-       /**
-        * @return last modified file name from default directory
-        * @throws Exception
-        */
-//     TODO add download directory capability
-//     public static synchronized File getLastModifiedFileNameFromDir() throws Exception{
-//             return getLastModifiedFileNameFromDir(ComponentBaseTest.getWindowTest().getDownloadDirectory());
-//     }
-       
        /**
         * @param dirPath
         * @return last modified file name from dirPath directory
@@ -369,52 +363,6 @@ public class FileHandling {
                        ComponentBaseTest.getExtendTest().log(Status.INFO, "Unable to write to flie " + pathToFile);
                }
        }
-       
-//     public static synchronized void writeToFile(File pathToFile, Map<String, Pair<String, Object>> dataMap, Integer leftSpaceCount) throws IOException{
-//
-//             BufferedWriter bw = null;
-//             FileWriter fw = null;
-//             try {
-//                     if(!pathToFile.exists()){
-//                             createEmptyFile(pathToFile);
-//                     }
-//                     fw = new FileWriter(pathToFile, true);
-//                     bw = new BufferedWriter(fw);
-//                     StringBuilder sb = new StringBuilder();
-//                     if(leftSpaceCount > 0 ){
-//                             for(int i = 0; i < leftSpaceCount; i++){
-//                                     sb.append(" ");
-//                             }
-//                     }
-//                     for(Map.Entry<String, Pair<String, Object>> entry : dataMap.entrySet()){
-//                             Object record = ArtifactUIUtils.getFormatedData(entry.getKey(), entry.getValue().right);
-//                             bw.write(sb.toString() + record);
-//                             bw.newLine();
-//                     }
-//                     bw.close();
-//                     fw.close();
-//             } catch (Exception e) {
-//                     ComponentBaseTest.getExtendTest().log(Status.INFO, "Unable to write to flie " + pathToFile);
-//             }
-//     }
-       
-       public static void deleteLastDowloadedFiles(List<File> files) throws IOException {
-               for (File file : files) {
-                       File fileToDelete =new File(Config.instance().getWindowsDownloadDirectory()+file.getName());
-                       fileToDelete.delete();
-               }
-       }
-// TODO add work with directory capaability
-//     public static void cleanCurrentDownloadDir() throws IOException {
-//             try{
-//                     ExtentTestActions.log(Status.INFO, "Cleaning directory " + ComponentBaseTest.getWindowTest().getDownloadDirectory());
-//                     System.gc();
-//                     FileUtils.cleanDirectory(new File(ComponentBaseTest.getWindowTest().getDownloadDirectory()));
-//             }
-//             catch(Exception e){
-//
-//             }
-//     }
 
        public static String getCreateDirByName(String dirName) {
                File dir = new File(dirName);
@@ -507,63 +455,7 @@ public class FileHandling {
                        }
                        return fileList;
        }
-       
-       private static final int BUFFER_SIZE = 4096;
-//    public static void unzip(String zipFilePath, String destDirectory) throws IOException {
-//        File destDir = new File(destDirectory);
-//        if (!destDir.exists()) {
-//            destDir.mkdir();
-//        }
-//        ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
-//        ZipEntry entry = zipIn.getNextEntry();
-////         iterates over entries in the zip file
-//        while (entry != null) {
-//             String entryName;
-//             if(System.getProperty("os.name").contains("Windows")){
-//                     entryName = entry.getName().replaceAll("/", "\\"+File.separator);
-//             }else{
-//                     entryName = entry.getName();
-//             }
-//            String filePath = destDirectory + entryName;
-//            String currPath = destDirectory;
-//            String[] dirs = entryName.split("\\"+File.separator);
-//            String currToken;
-//            for(int i = 0; i<dirs.length;++i){
-//             currToken = dirs[i];
-//             if(!entry.isDirectory() && i==dirs.length-1){
-//                      extractFile(zipIn, filePath);
-//             } else {
-//                     if(currPath.endsWith(File.separator)){
-//                             currPath = currPath + currToken;
-//                     }else{
-//                             currPath = currPath + File.separator + currToken;
-//                     }
-////                     if the entry is a directory, make the directory
-//                    File dir = new File(currPath);
-//                    dir.mkdir();
-//                }
-//            }
-//            zipIn.closeEntry();
-//            entry = zipIn.getNextEntry();
-//        }
-//        zipIn.close();
-//    }
-
-    private static void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
-        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
-        byte[] bytesIn = new byte[BUFFER_SIZE];
-        int read = 0;
-        while ((read = zipIn.read(bytesIn)) != -1) {
-            bos.write(bytesIn, 0, read);
-        }
-        bos.close();
-    }
-       
-//    public static int getFileCountFromDefaulDownloadDirectory(){
-//     return new File(ComponentBaseTest.getWindowTest().getDownloadDirectory()).listFiles().length;
-//    }
-    
-    
+
     public static String getKeyByValueFromPropertyFormatFile(String fullPath, String key) {
                Properties prop = new Properties();
                InputStream input = null;
index fb60f44..de2b408 100644 (file)
@@ -39,7 +39,6 @@ import org.openecomp.sdc.ci.tests.utils.general.ElementFactory;
 import org.openecomp.sdc.ci.tests.utils.rest.CatalogRestUtils;
 import org.openecomp.sdc.ci.tests.utils.rest.CategoryRestUtils;
 import org.openecomp.sdc.ci.tests.utils.rest.ResponseParser;
-import org.openecomp.sdc.common.util.ZipUtil;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 import org.yaml.snakeyaml.Yaml;
@@ -48,7 +47,6 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -177,34 +175,6 @@ public class DeploymentValiditaion extends ComponentBaseTest{
                return yamlList;
        }
 
-       @Test (enabled=false)
-       public void testYaml() throws IOException{
-
-               System.out.println("");
-
-               File file = new File("\\\\Comp-1\\FileIO\\Stop.txt");
-
-               Map<String, byte[]> readZip = null;
-               Path path = Paths.get("C:\\Users\\ys9693\\Documents\\csar\\attributesWithProporties\\attributesWithProporties.csar");
-               byte[] data = Files.readAllBytes(path);
-               if (data != null && data.length > 0) {
-                       readZip = ZipUtil.readZip(data);
-
-               }
-
-               byte[] artifactsBs = readZip.get("Definitions/VF_RI2_G6.yaml");
-               String str = new String(artifactsBs, StandardCharsets.UTF_8);
-
-               Yaml yaml = new Yaml();
-               Map<String, Object> load = (Map<String, Object>) yaml.load(str);
-               Map<String, Object> topology_template = (Map<String, Object>) load.get("topology_template");
-               Map<String, Object> node_templates = (Map<String, Object>) topology_template.get("node_templates");
-
-               Set<String> keySet = node_templates.keySet();
-       }
-
-
-
        @Test
        public void pasrseDataTypes() throws Exception{
 
index 1ac4a72..f8cc628 100644 (file)
@@ -501,7 +501,7 @@ public class FileHandling {
         while (entry != null) {
             String entryName;
             if (System.getProperty("os.name").contains("Windows")) {
-                entryName = entry.getName().replaceAll("/", "\\" + File.separator);
+                entryName = entry.getName().replace("/", "\\" + File.separator);
             } else {
                 entryName = entry.getName();
             }